This file is indexed.

/usr/lib/python3/dist-packages/optlang/container.py is in python3-optlang 1.3.0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# Copyright 2013 Novo Nordisk Foundation Center for Biosustainability,
# Technical University of Denmark.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from itertools import islice

from optlang.exceptions import ContainerAlreadyContains


class Container(object):
    '''
    A container for objects that have a name attribute.
    Items in the Container can be accessed by index like a list or by key (the name attribute of the item).
    For convenience, an item can also be accessed as an attribute with the same name as the name attribute of the item.

    Items can be added to the Container using the list-like methods 'append' and 'extend' or by
    dict-like assignment.

    Examples
    --------
    >>> container = Container()
    >>> var1 = Variable("coffee", lb=-10, ub=10)

    The variable can be added in either of the following ways:
    >>> container.append(var1)
    >>> container.extend([var1])
    >>> container["coffee"] = var1 # Note the key must match the name attribute of the item

    The added item can be accessed in either of the following ways:
    >>> container[0]
    >>> container["coffee"]
    >>> container.coffee
    '-10 <= coffee <= 10'
    '''

    def __init__(self, iterable=()):
        self._dict = {}
        self._object_list = []
        self._indices = {}
        for item in iterable:
            try:
                item.name
            except AttributeError:
                raise AttributeError("Item " + item.__repr__() + " does not have a 'name' attribute")
            self.append(item)

    @staticmethod
    def _check_for_name_attribute(value):
        if not hasattr(value, 'name'):
            raise AttributeError('Object %s does not have a "name" attribute and cannot not be stored.' % value)

    def __len__(self):
        return len(self._dict)

    def __contains__(self, item):
        if item in self._dict:
            return True
        elif hasattr(item, "name") and item.name in self._dict:
            return item is self._dict[item.name]
        return False

    def __iter__(self):
        original_length = len(self._object_list)
        for item in self._object_list.__iter__():
            if original_length != len(self._object_list):
                raise RuntimeError("container changed size during iteration")
            yield item

    def __getitem__(self, item):
        try:
            return self._object_list[item]  # Try treating item as int or slice
        except TypeError:  # Not int or slice
            return self._dict[item]  # Treat item as key (name)

    def __setitem__(self, key, value):
        self._check_for_name_attribute(value)

        if isinstance(key, int):
            old_value = self._object_list[key]
            if old_value.name == value.name:
                self._object_list[key] = value
                self._dict[value.name] = value
            else:
                if value.name in self:
                    raise ValueError("The container already contains an object with the name " + repr(value.name))
                else:
                    self._object_list[key] = value
                    del self._dict[old_value.name]
                    self._dict[value.name] = value
        else:
            if value.name != key:
                raise ValueError("Name of item does not match key")
            try:
                old_value = self._dict[key]
            except KeyError:
                self.append(value)
            else:
                self._dict[old_value.name] = value
                self._object_list[self._indices[old_value.name]] = value

    def __delitem__(self, key):
        name = self[key].name
        index = self._indices[name]
        del self._dict[name]
        del self._object_list[index]
        del self._indices[name]
        self._reindex(index)

    def _reindex(self, start=0):
        for i, item in enumerate(islice(self._object_list, start, len(self))):
            self._indices[item.name] = start + i

    def update_key(self, key):
        item = self._dict[key]
        name = item.name
        if key != name:
            self._dict[name] = item
            del self._dict[key]
            self._indices[name] = self._indices[key]
            del self._indices[key]

    def keys(self):
        return list(item.name for item in self._object_list)

    def iterkeys(self):
        return (item.name for item in self._object_list)

    def values(self):
        return list(iter(self._object_list))

    def itervalues(self):
        return iter(self._object_list)

    def items(self):
        return ((item.name, item) for item in self._object_list)

    def iteritems(self):
        return self.items()

    def fromkeys(self, keys):
        return self.__class__((self[key] for key in keys))

    def get(self, key, default=None):
        try:
            return self[key]
        except (KeyError, IndexError):
            return default

    def clear(self):
        self._dict = {}
        self._indices = {}
        self._object_list = []

    def has_key(self, key):
        return key in self._dict

    def append(self, value):
        self._check_for_name_attribute(value)
        name = value.name
        if name in self._dict:
            raise ContainerAlreadyContains("Container '%s' already contains an object with name '%s'." % (self, value.name))
        self._indices[name] = len(self)
        self._object_list.append(value)
        self._dict[name] = value

    def extend(self, values):
        for value in values:
            self._check_for_name_attribute(value)
            if value.name in self._dict:
                raise ContainerAlreadyContains("Container '%s' already contains an object with name '%s'." % (self, value.name))
        length = len(self)
        self._object_list.extend(values)
        self._dict.update({value.name: value for value in values})
        self._indices.update({value.name: length + i for i, value in enumerate(values)})

    def __getattr__(self, name):
        try:
            return self[name]
        except KeyError:
            raise AttributeError("'%s' object has no attribute %s" % (self, name))

    def __getstate__(self):
        return self._object_list

    def __setstate__(self, obj_list):
        self.__init__(obj_list)

    def __dir__(self):
        attributes = list(self.__class__.__dict__.keys())
        attributes.extend(item.name for item in self._object_list)
        return attributes