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):
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):
......
......@@ -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):
......
......@@ -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,), {})
......
......@@ -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:
......
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