Commit 2f76b1f2 authored by Daniel Brown's avatar Daniel Brown
Browse files

More deepcopying fixes for weakrefs in putters and params

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