From e44095689a27490ed9a1714deba037d35754b0dc Mon Sep 17 00:00:00 2001
From: Daniel Brown <ddb@star.sr.bham.ac.uk>
Date: Mon, 9 Jan 2017 22:09:22 +0000
Subject: [PATCH] further work for freezing components

---
 pykat/commands.py   | 18 ++++++------------
 pykat/components.py | 21 ++++++++-------------
 pykat/detectors.py  | 20 ++++++++------------
 3 files changed, 22 insertions(+), 37 deletions(-)

diff --git a/pykat/commands.py b/pykat/commands.py
index 772c003..e065c57 100644
--- a/pykat/commands.py
+++ b/pykat/commands.py
@@ -43,31 +43,25 @@ class Command(object):
         When deep copying a kat object we need to take into account
         the instance specific properties.
         """
-
         cls = self.__class__
         result = cls.__new__(cls)
+        result._unfreeze()
         result.__dict__ = copy.deepcopy(self.__dict__, memo)
         
         for _ in result._putters:
             _._updateOwner(result)
-        
+
+        result._freeze()
         return result
     
     def _freeze(self): self.__dict__["____FROZEN____"] = True
     def _unfreeze(self): self.__dict__["____FROZEN____"] = False
         
     def __setattr__(self, name, value):
-        if self.__dict__["____FROZEN____"] and not hasattr(self, name):
+        if "____FROZEN____" in self.__dict__ and self.__dict__["____FROZEN____"] and not hasattr(self, name):
             warnings.warn("'%s' does not have attribute called '%s'" % (self.__name, name), stacklevel=2)
-            
-        if hasattr(self, name) and hasattr(self.__class__, name):
-            prop = getattr(self.__class__, name)
-            
-            if isinstance(prop, property):
-                prop.fset(self, value)
-                return
-                
-        self.__dict__[name] = value
+
+        super(Command, self).__setattr__(name, value)
                        
     def getFinesseText(self):
         """ Base class for individual finesse optical components """
diff --git a/pykat/components.py b/pykat/components.py
index 4c0f953..9d014d3 100644
--- a/pykat/components.py
+++ b/pykat/components.py
@@ -100,7 +100,8 @@ class Component(object):
         
         cnew = type(cnew_name, (cls,), {})
         
-        return object.__new__(cnew)
+        o = object.__new__(cnew)
+        return o
         
     def __init__(self, name=None):
         self._unfreeze()
@@ -125,32 +126,26 @@ class Component(object):
     def _unfreeze(self): self.__dict__["____FROZEN____"] = False
         
     def __setattr__(self, name, value):
-        if self.__dict__["____FROZEN____"] and not hasattr(self, name):
+        if "____FROZEN____" in self.__dict__ and self.__dict__["____FROZEN____"] and not hasattr(self, name):
             warnings.warn("'%s' does not have attribute called '%s'" % (self.__name, name), stacklevel=2)
-            
-        if hasattr(self, name) and hasattr(self.__class__, name):
-            prop = getattr(self.__class__, name)
-            
-            if isinstance(prop, property):
-                prop.fset(self, value)
-                return
-                
-        self.__dict__[name] = value
+
+        super(Component, self).__setattr__(name, value)
          
     def __deepcopy__(self, memo):
         """
         When deep copying a kat object we need to take into account
         the instance specific properties.
         """
-        
         # Here we create a copy of this object based of the base class
         # of this one, otherwise we're making a copy of a copy of a copy...
         result = self.__class__.__new__(self.__class__.__base__)
+        result._unfreeze()
         result.__dict__ = copy.deepcopy(self.__dict__, memo)
         
         for _ in result._params:
             _._updateOwner(result)
-        
+    
+        result._freeze()
         return result
         
     def _register_param(self, param):
diff --git a/pykat/detectors.py b/pykat/detectors.py
index a957cd6..0258000 100644
--- a/pykat/detectors.py
+++ b/pykat/detectors.py
@@ -51,11 +51,12 @@ class BaseDetector(object) :
         
         cnew = type(cnew_name, (cls,), {})
         
-        return object.__new__(cnew)
+        o = object.__new__(cnew)
+        return o
         
     def __init__(self, name, nodes=None, max_nodes=1):
 
-        self.__dict__["____FROZEN____"] = False
+        self._unfreeze()
         
         self.__name = name
         self._svgItem = None
@@ -103,17 +104,10 @@ class BaseDetector(object) :
     def _unfreeze(self): self.__dict__["____FROZEN____"] = False
         
     def __setattr__(self, name, value):
-        if self.__dict__["____FROZEN____"] and not hasattr(self, name):
+        if "____FROZEN____" in self.__dict__ and self.__dict__["____FROZEN____"] and not hasattr(self, name):
             warnings.warn("'%s' does not have attribute called '%s'" % (self.__name, name), stacklevel=2)
-            
-        if hasattr(self, name) and hasattr(self.__class__, name):
-            prop = getattr(self.__class__, name)
-            
-            if isinstance(prop, property):
-                prop.fset(self, value)
-                return
-                
-        self.__dict__[name] = value
+
+        super(BaseDetector, self).__setattr__(name, value)
     
     def __deepcopy__(self, memo):
         """
@@ -124,8 +118,10 @@ class BaseDetector(object) :
         # Here we create a copy of this object based of the base class
         # of this one, otherwise we're making a copy of a copy of a copy...
         result = self.__class__.__new__(self.__class__.__base__)
+        result._unfreeze()
         result.__dict__ = copy.deepcopy(self.__dict__, memo)
         
+        result._freeze()
         return result
                 
     def _register_param(self, param):
-- 
GitLab