@@ -53,6 +53,9 @@ class Tolerance(Data):
5353 This value is called the "true value".
5454 By convention, the second value is considered the "true value" by the comparison functions of this class.
5555
56+ The :class:`compas.tolerance.Tolerance` class is implemented using a "singleton" pattern and can therefore have only 1 (one) instance per context.
57+ Usage of :attr:`compas.tolerance.TOL` outside of :mod:`compas` internals is therefore deprecated.
58+
5659 Examples
5760 --------
5861 >>> tol = Tolerance()
@@ -67,6 +70,9 @@ class Tolerance(Data):
6770
6871 """
6972
73+ _instance = None
74+ _is_inited = False
75+
7076 ABSOLUTE = 1e-9
7177 """float: Determines when a number is small enough to be considered zero.
7278 """
@@ -108,8 +114,9 @@ class Tolerance(Data):
108114 """
109115
110116 def __new__ (cls , * args , ** kwargs ):
111- if not hasattr (cls , "_instance" ):
112- cls ._instance = super (Tolerance , cls ).__new__ (cls )
117+ if not isinstance (cls ._instance , cls ):
118+ cls ._instance = object .__new__ (cls , * args , ** kwargs )
119+ cls ._inited = False
113120 return cls ._instance
114121
115122 @property
@@ -151,22 +158,34 @@ def __init__(
151158 name = None ,
152159 ):
153160 super (Tolerance , self ).__init__ (name = name )
154- self ._unit = None
155- self ._absolute = None
156- self ._relative = None
157- self ._angular = None
158- self ._approximation = None
159- self ._precision = None
160- self ._lineardeflection = None
161- self ._angulardeflection = None
162- self .unit = unit
163- self .absolute = absolute
164- self .relative = relative
165- self .angular = angular
166- self .approximation = approximation
167- self .precision = precision
168- self .lineardeflection = lineardflection
169- self .angulardeflection = angulardflection
161+ if not self ._is_inited :
162+ self ._unit = None
163+ self ._absolute = None
164+ self ._relative = None
165+ self ._angular = None
166+ self ._approximation = None
167+ self ._precision = None
168+ self ._lineardeflection = None
169+ self ._angulardeflection = None
170+
171+ self ._is_inited = True
172+
173+ if unit is not None :
174+ self .unit = unit
175+ if absolute is not None :
176+ self .absolute = absolute
177+ if relative is not None :
178+ self .relative = relative
179+ if angular is not None :
180+ self .angular = angular
181+ if approximation is not None :
182+ self .approximation = approximation
183+ if precision is not None :
184+ self .precision = precision
185+ if lineardflection is not None :
186+ self .lineardeflection = lineardflection
187+ if angulardflection is not None :
188+ self .angulardeflection = angulardflection
170189
171190 # this can be autogenerated if we use slots
172191 # __repr__: return f"{__class__.__name__}({', '.join(f'{k}={v!r}' for k, v in self.__dict__.items())})}"
@@ -193,6 +212,23 @@ def reset(self):
193212 self ._lineardeflection = None
194213 self ._angulardeflection = None
195214
215+ def update_from_dict (self , tolerance ):
216+ """Update the tolerance singleton from the key-value pairs found in a dict.
217+
218+ Parameters
219+ ----------
220+ tolerance : dict
221+ A dictionary containing named tolerance values.
222+
223+ Returns
224+ -------
225+ None
226+
227+ """
228+ for name in tolerance :
229+ if hasattr (self , name ):
230+ setattr (self , name , tolerance [name ])
231+
196232 @property
197233 def units (self ):
198234 return self ._unit
0 commit comments