/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
|