@@ -151,8 +151,12 @@ class SignatureError(Exception):
151151class SignatureMembers (Mapping ):
152152 def __init__ (self , members = ()):
153153 self ._dict = dict ()
154- self ._frozen = False
155- self += members
154+ for name , member in dict (members ).items ():
155+ self ._check_name (name )
156+ if type (member ) is not Member :
157+ raise TypeError (f"Value { member !r} must be a member; "
158+ f"did you mean In({ member !r} ) or Out({ member !r} )?" )
159+ self ._dict [name ] = member
156160
157161 def flip (self ):
158162 return FlippedSignatureMembers (self )
@@ -179,16 +183,7 @@ def __getitem__(self, name):
179183 return self ._dict [name ]
180184
181185 def __setitem__ (self , name , member ):
182- self ._check_name (name )
183- if name in self ._dict :
184- raise SignatureError (f"Member '{ name } ' already exists in the signature and cannot "
185- f"be replaced" )
186- if type (member ) is not Member :
187- raise TypeError (f"Assigned value { member !r} must be a member; "
188- f"did you mean In({ member !r} ) or Out({ member !r} )?" )
189- if self ._frozen :
190- raise SignatureError ("Cannot add members to a frozen signature" )
191- self ._dict [name ] = member
186+ raise SignatureError ("Members cannot be added to a signature once constructed" )
192187
193188 def __delitem__ (self , name ):
194189 raise SignatureError ("Members cannot be removed from a signature" )
@@ -199,21 +194,6 @@ def __iter__(self):
199194 def __len__ (self ):
200195 return len (self ._dict )
201196
202- def __iadd__ (self , members ):
203- for name , member in dict (members ).items ():
204- self [name ] = member
205- return self
206-
207- @property
208- def frozen (self ):
209- return self ._frozen
210-
211- def freeze (self ):
212- self ._frozen = True
213- for member in self .values ():
214- if member .is_signature :
215- member .signature .freeze ()
216-
217197 def flatten (self , * , path = ()):
218198 for name , member in self .items ():
219199 yield ((* path , name ), member )
@@ -244,8 +224,7 @@ def create_dimensions(dimensions, *, path, src_loc_at):
244224 return attrs
245225
246226 def __repr__ (self ):
247- frozen_repr = ".freeze()" if self ._frozen else ""
248- return f"SignatureMembers({ self ._dict } ){ frozen_repr } "
227+ return f"SignatureMembers({ self ._dict } )"
249228
250229
251230@final
@@ -277,17 +256,6 @@ def __iter__(self):
277256 def __len__ (self ):
278257 return self .__unflipped .__len__ ()
279258
280- def __iadd__ (self , members ):
281- self .__unflipped .__iadd__ ({name : member .flip () for name , member in members .items ()})
282- return self
283-
284- @property
285- def frozen (self ):
286- return self .__unflipped .frozen
287-
288- def freeze (self ):
289- self .__unflipped .freeze ()
290-
291259 # These methods do not access instance variables and so their implementation can be shared
292260 # between the normal and the flipped member collections.
293261 flatten = SignatureMembers .flatten
@@ -358,12 +326,6 @@ def flip(self):
358326 def members (self ):
359327 return self .__members
360328
361- @members .setter
362- def members (self , new_members ):
363- # The setter is called when `sig.members += ...` is used.
364- if new_members is not self .__members :
365- raise AttributeError ("property 'members' of 'Signature' object cannot be set" )
366-
367329 def __eq__ (self , other ):
368330 other_unflipped = other .flip () if type (other ) is FlippedSignature else other
369331 if type (self ) is type (other_unflipped ) is Signature :
@@ -374,14 +336,6 @@ def __eq__(self, other):
374336 # usually be overridden in a derived class.
375337 return self is other
376338
377- @property
378- def frozen (self ):
379- return self .members .frozen
380-
381- def freeze (self ):
382- self .members .freeze ()
383- return self
384-
385339 def flatten (self , obj ):
386340 for name , member in self .members .items ():
387341 path = (name ,)
@@ -544,11 +498,6 @@ def flip(self):
544498 def members (self ):
545499 return FlippedSignatureMembers (self .__unflipped .members )
546500
547- @members .setter
548- def members (self , new_members ):
549- if new_members .flip () is not self .__unflipped .members :
550- raise AttributeError ("property 'members' of 'FlippedSignature' object cannot be set" )
551-
552501 def __eq__ (self , other ):
553502 if type (other ) is FlippedSignature :
554503 # Trivial case.
@@ -561,10 +510,8 @@ def __eq__(self, other):
561510 # in infinite recursion.
562511 return NotImplemented
563512
564- # These methods do not access instance variables and so their implementation can be shared
513+ # This method does not access instance variables and so its implementation can be shared
565514 # between the normal and the flipped member collections.
566- frozen = Signature .frozen
567- freeze = Signature .freeze
568515 is_compliant = Signature .is_compliant
569516
570517 # FIXME: document this logic
@@ -581,16 +528,10 @@ def __getattr__(self, name):
581528 return getattr (self .__unflipped , name )
582529
583530 def __setattr__ (self , name , value ):
584- if name == "members" :
585- # Although `sig.flip().members` does not call `__getattr__` but directly invokes
586- # the descriptor of the `FlippedSignature.members` property, `sig.flip().members +=`
587- # does call `__setattr__`, and this must be special-cased for the setter to work.
588- FlippedSignature .members .__set__ (self , value )
589- else :
590- try : # descriptor first
591- _gettypeattr (self .__unflipped , name ).__set__ (self , value )
592- except AttributeError :
593- setattr (self .__unflipped , name , value )
531+ try : # descriptor first
532+ _gettypeattr (self .__unflipped , name ).__set__ (self , value )
533+ except AttributeError :
534+ setattr (self .__unflipped , name , value )
594535
595536 def __delattr__ (self , name ):
596537 try : # descriptor first
@@ -703,7 +644,7 @@ def connect(m, *args, **kwargs):
703644 reasons_as_string = "" .join ("\n - " + reason for reason in reasons )
704645 raise ConnectionError (f"Argument { handle !r} does not match its signature:" +
705646 reasons_as_string )
706- signatures [handle ] = obj .signature . freeze ()
647+ signatures [handle ] = obj .signature
707648
708649 # Collate signatures and build connections.
709650 flattens = {handle : signature .members .flatten ()
@@ -875,8 +816,8 @@ def __init__(self):
875816 @property
876817 def signature (self ):
877818 cls = type (self )
878- signature = Signature ({})
879- for base in cls .mro ()[:cls .mro ().index (Component )]:
819+ members = {}
820+ for base in reversed ( cls .mro ()[:cls .mro ().index (Component )]) :
880821 for name , annot in base .__dict__ .get ("__annotations__" , {}).items ():
881822 if name .startswith ("_" ):
882823 continue
@@ -897,9 +838,11 @@ def signature(self):
897838 category = SyntaxWarning ,
898839 stacklevel = 2 )
899840 elif type (annot ) is Member :
900- signature .members [name ] = annot
901- if not signature .members :
841+ if name in members :
842+ raise SignatureError (f"Member '{ name } ' is redefined in { base .__module__ } .{ base .__qualname__ } " )
843+ members [name ] = annot
844+ if not members :
902845 raise NotImplementedError (
903846 f"Component '{ cls .__module__ } .{ cls .__qualname__ } ' does not have signature member "
904847 f"annotations" )
905- return signature
848+ return Signature ( members )
0 commit comments