Commit afd3eab3 authored by Niklas Stefan Nolte's avatar Niklas Stefan Nolte 🔥 Committed by Rosen Matev
Browse files

Make algorithm/tool immutable after instantiation

parent 45b7b9b7
......@@ -263,6 +263,8 @@ class Algorithm(object):
"""
_algorithm_store = dict()
_readonly = False
def __new__(cls,
alg_type,
name=None,
......@@ -434,6 +436,7 @@ class Algorithm(object):
for key, src in instance._outputs.items():
setattr(instance, key, src)
instance._readonly = True
cls._algorithm_store[identity] = instance
#return the cached or new instance
return instance
......@@ -632,6 +635,30 @@ class Algorithm(object):
pass
return top
def __setitem__(self, k, v):
if self._readonly:
raise ConfigurationError(
'cannot change member after initialization')
return object.__setitem__(self, k, v)
def __setattr__(self, k, v):
if self._readonly:
raise ConfigurationError(
'cannot change member after initialization')
return object.__setattr__(self, k, v)
def __delitem__(self, i):
if self._readonly:
raise ConfigurationError(
'cannot change member after initialization')
return object.__delitem__(self, i)
def __delattr__(self, a):
if self._readonly:
raise ConfigurationError(
'cannot change member after initialization')
return object.__delattr__(self, a)
# TODO(AP): maybe wrap_algorithm is better
def make_algorithm(alg_type,
......@@ -683,6 +710,8 @@ class Tool(object):
_tool_store = dict()
_readonly = False
def __new__(cls, tool_type, name=None, **kwargs):
"""
Args:
......@@ -734,6 +763,7 @@ class Tool(object):
instance._tools = _tools
for tool in instance._tools.values():
tool.set_parent(instance)
instance._readonly = True
cls._tool_store[identity] = instance
return instance
......@@ -793,14 +823,20 @@ class Tool(object):
return self.type.getType()
def set_parent(self, parent):
if self.parent:
raise ConfigurationError(
"This Tool already has a parent. Please instantiate a new one")
if not is_algorithm(parent) and not is_tool(parent):
raise TypeError("{} not of type Algorithm or Tool".format(parent))
object.__setattr__(self, "_readonly",
False) # this is the only allowed modification
self._parent = parent
self._private = True
del self._tool_store[self._id]
self._id = self._calc_id(self._tooltype, self._properties,
self._inputs, self._tools, parent)
self._tool_store[self._id] = self
object.__setattr__(self, "_readonly", True) # make immutable again
def __repr__(self):
return 'Tool({})'.format(self.name)
......@@ -833,6 +869,30 @@ class Tool(object):
return config
def __setitem__(self, k, v):
if self._readonly:
raise ConfigurationError(
'cannot change member after initialization')
return object.__setitem__(self, k, v)
def __setattr__(self, k, v):
if self._readonly:
raise ConfigurationError(
'cannot change member after initialization')
return object.__setattr__(self, k, v)
def __delitem__(self, i):
if self._readonly:
raise ConfigurationError(
'cannot change member after initialization')
return object.__delitem__(self, i)
def __delattr__(self, a):
if self._readonly:
raise ConfigurationError(
'cannot change member after initialization')
return object.__delattr__(self, a)
# TODO(AP): maybe wrap_tool is better
def make_tool(tool_type, defaults=None):
......
......@@ -66,6 +66,10 @@ def test_init():
consumer = Algorithm(IntDataConsumer, InputLocation=producer)
assert consumer.inputs['InputLocation'] == data
with pytest.raises(ConfigurationError):
# cannot change property after instantiation
consumer.OutputLevel = 2
def test_init_input_location_list():
"""Properties that are lists of DataHandle objects should be supported."""
......
......@@ -33,3 +33,7 @@ def test_init():
# initializing an algorithm twice should give the same instance
t2 = Tool(FloatTool, Input=Algorithm(Producer))
assert t is t2, "tool instantiation doesn't seem to be cached correctly"
with pytest.raises(ConfigurationError):
# immutable after instantiation
t.OutputLevel = 2
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment