diff --git a/pykat/commands.py b/pykat/commands.py index 83aa6f0b81f34048369908cc73d4868234f633f9..c05a48c7e668f9408014283e0a2b9bb205f1a9e8 100644 --- a/pykat/commands.py +++ b/pykat/commands.py @@ -34,8 +34,23 @@ class Command(object): self.tag = None self.__removed = False self.__name = name.strip("*") - self._putters_to_register = [] + self._putters = [] + + def __deepcopy__(self, memo): + """ + When deep copying a kat object we need to take into account + the instance specific properties. + """ + + cls = self.__class__ + result = cls.__new__(cls) + result.__dict__ = copy.deepcopy(self.__dict__, memo) + + for _ in result._putters: + _._updateOwner(result) + return result + def getFinesseText(self): """ Base class for individual finesse optical components """ raise NotImplementedError("This function is not implemented") @@ -50,21 +65,21 @@ class Command(object): """ self._kat = kat - for _ in self._putters_to_register: + for _ in self._putters: kat.registerVariable(_.name, _) def _on_kat_remove(self): self.__removed = True - for i in range(len(self._putters_to_register)): - _ = self._putters_to_register[i] + for i in range(len(self._putters)): + _ = self._putters[i] self._kat.unregisterVariable(_.name) _.clearPuts() - del self._putters_to_register[i] + del self._putters[i] - del self._putters_to_register[:] + del self._putters[:] def remove(self): @@ -118,7 +133,7 @@ class func(Command): self.enabled = True self.output = putter(name, self) - self._putters_to_register.append(self.output) + self._putters.append(self.output) def getFinesseText(self): rtn = [] @@ -157,7 +172,7 @@ class lock(Command): self.output = putter(name, self) - self._putters_to_register.append(self.output) + self._putters.append(self.output) @staticmethod @@ -383,8 +398,8 @@ class xaxis(Command): self.x = putter("x1", self) self.mx = putter("mx1", self) - self._putters_to_register.append(self.x) - self._putters_to_register.append(self.mx) + self._putters.append(self.x) + self._putters.append(self.mx) if scale == "lin": scale = Scale.linear @@ -465,8 +480,8 @@ class x2axis(xaxis): self.x = putter("x2", self) self.mx = putter("mx2", self) - self._putters_to_register.append(self.x) - self._putters_to_register.append(self.mx) + self._putters.append(self.x) + self._putters.append(self.mx) @staticmethod def parseFinesseText(text): diff --git a/pykat/components.py b/pykat/components.py index 345e60c45aafbdd56a444e26b098780773e1d1bc..7c5a6920553638384eb44a89362ff627f5844a1f 100644 --- a/pykat/components.py +++ b/pykat/components.py @@ -84,7 +84,7 @@ class NodeGaussSetter(object): def qy(self, value): self.__node().setGauss(self.__comp(), self.qx, complex(value)) -id___ = 0 +id_____pykat_class = 0 class Component(object): __metaclass__ = abc.ABCMeta @@ -93,9 +93,9 @@ class Component(object): # This creates an instance specific class for the component # this enables us to add properties to instances rather than # all classes - global id___ - id___ += 1 - cnew_name = str("%s.%s_%i" % (cls.__module__, cls.__name__, id___)) + global id_____pykat_class + id_____pykat_class += 1 + cnew_name = str("%s.%s_%i" % (cls.__module__, cls.__name__, id_____pykat_class)) cnew = type(cnew_name, (cls,), {}) @@ -130,6 +130,9 @@ class Component(object): result = self.__class__.__new__(self.__class__.__base__) result.__dict__ = copy.deepcopy(self.__dict__, memo) + for _ in result._params: + _._updateOwner(result) + return result def _register_param(self, param): diff --git a/pykat/detectors.py b/pykat/detectors.py index 757494aa8df653068d1456a9415c6b350d732329..e652372326ff8e4cf885f5fcd9e365330de935f0 100644 --- a/pykat/detectors.py +++ b/pykat/detectors.py @@ -31,7 +31,7 @@ if USE_GUI: import pykat.gui.resources from pykat.gui.graphics import * -id___ = 0 +id_____pykat_class = 0 class BaseDetector(object) : """ @@ -45,9 +45,9 @@ class BaseDetector(object) : # This creates an instance specific class for the component # this enables us to add properties to instances rather than # all classes - global id___ - id___ += 1 - cnew_name = str("%s.%s_%i" % (cls.__module__, cls.__name__, id___)) + global id_____pykat_class + id_____pykat_class += 1 + cnew_name = str("%s.%s_%i" % (cls.__module__, cls.__name__, id_____pykat_class)) cnew = type(cnew_name, (cls,), {}) diff --git a/pykat/param.py b/pykat/param.py index 440473c5a0ccf6ccd1c6cd4973a210280bac5b3f..72e9561d01888b157512d1c0f6851172aff8a03d 100644 --- a/pykat/param.py +++ b/pykat/param.py @@ -28,29 +28,31 @@ class putable(object): def isPutable(self): return self._isPutable def put(self, var, alt=False): + if not self._isPutable: + raise pkex.BasePyKatException("Can't put to this object") + if var is not None and not isinstance(var, putter): raise pkex.BasePyKatException("`%s` was not something that can be `put` to a parameter" % str(var)) # Remove existing puts - if self._putter is not None: self._putter().unregister(self) + if self._putter is not None: + self._putter.unregister(self) - if var is not None: - self._putter = weakref.ref(var) - else: - self._putter = None + self._putter = var self._alt = alt - if var is not None: self._putter().register(self) + if var is not None: + self._putter.register(self) def _getPutFinesseText(self): rtn = [] - - if self._putter is not None and self._putter() is not None: + + if self._isPutable and self._putter is not None: putter_enabled = True - - if hasattr(self._putter().owner, 'enabled'): - putter_enabled = self._putter().owner.enabled + + if hasattr(self._putter.owner, 'enabled'): + putter_enabled = self._putter.owner.enabled if putter_enabled: if self._alt: @@ -59,10 +61,11 @@ class putable(object): alt = '' # if something is being put to this - rtn.append("put{alt} {comp} {param} ${value}".format(alt=alt, comp=self._component_name, param=self._parameter_name, value=self._putter().put_name())) + rtn.append("put{alt} {comp} {param} ${value}".format(alt=alt, comp=self._component_name, param=self._parameter_name, value=self._putter.put_name())) return rtn - + + class putter(object): """ If an object can be put to something that is putable it should inherit this @@ -74,18 +77,29 @@ class putter(object): self.put_count = 0 self._isPutter = isPutter self.putees = [] # list of params that this puts to - self.__owner = weakref.ref(owner) + assert(owner is not None) + self.__owner = weakref.ref(owner) + def _updateOwner(self, newOwner): + del self.__owner + self.__owner = weakref.ref(newOwner) + def clearPuts(self): for _ in self.putees: _.put(None) def register(self, toput): + if not self._isPutter: + raise pkex.BasePyKatException("This object can't put") + self.put_count += 1 self.putees.append(toput) def unregister(self, item): + if not self._isPutter: + raise pkex.BasePyKatException("This object can't put") + self.put_count -= 1 self.putees.remove(item) @@ -106,21 +120,24 @@ class putter(object): class Param(putable, putter): - def __init__(self, name, owner, value, canFsig=False, fsig_name=None, isPutable=True, isPutter=True, isTunable=True, var_name=None): + def __init__(self, name, owner, value, canFsig=False, fsig_name=None, isPutable=True, isPutter=True, isTunable=True, var_name=None, register=True): self._name = name + self._registered = register self._owner = weakref.ref(owner) self._value = value self._isPutter = isPutter self._isTunable = isTunable - self._owner()._register_param(self) self._canFsig = False + if self._registered: + self._owner()._register_param(self) + if canFsig: self._canFsig = True - + if fsig_name is None: raise pkex.BasePyKatException("If parameter is a possible fsig target the fsig_name argument must be set") - + self.__fsig_name = fsig_name if isPutter: @@ -130,15 +147,6 @@ class Param(putable, putter): putter.__init__(self, var_name, owner, isPutter) putable.__init__(self, owner.name, name, isPutable) - - def _updateOwner(self, newOwner): - """ - This updates the internal weak reference to link a parameter to who owns it. - Should only be called by the __deepcopy__ component method to ensure things - are kept up to date. - """ - del self._owner - self._owner = weakref.ref(newOwner) @property def canFsig(self): return self._canFsig @@ -200,7 +208,16 @@ class Param(putable, putter): rtn.append("set {put_name} {comp} {param}".format(put_name=self.put_name(), comp=self._owner().name, param=self.name)) return rtn - + + def _updateOwner(self, newOwner): + """ + This updates the internal weak reference to link a parameter to who owns it. + Should only be called by the __deepcopy__ component method to ensure things + are kept up to date. + """ + del self._owner + self._owner = weakref.ref(newOwner) + def _onOwnerRemoved(self): #if this param can be put somewhere we need to check if it is if self.isPutable: