lib.wiring: make sig.members += actually work.

This commit is contained in:
Catherine 2023-11-27 14:01:36 +00:00
parent 02756f6ec7
commit 8b48af6de8
2 changed files with 45 additions and 4 deletions

View file

@ -353,6 +353,12 @@ class Signature(metaclass=SignatureMeta):
def members(self):
return self.__members
@members.setter
def members(self, new_members):
# The setter is called when `sig.members += ...` is used.
if new_members is not self.__members:
raise AttributeError("property 'members' of 'Signature' object cannot be set")
def __eq__(self, other):
other_unflipped = other.flip() if type(other) is FlippedSignature else other
if type(self) is type(other_unflipped) is Signature:
@ -518,6 +524,11 @@ class FlippedSignature:
def members(self):
return FlippedSignatureMembers(self.__unflipped.members)
@members.setter
def members(self, new_members):
if new_members.flip() is not self.__unflipped.members:
raise AttributeError("property 'members' of 'FlippedSignature' object cannot be set")
def __eq__(self, other):
if type(other) is FlippedSignature:
# Trivial case.
@ -550,10 +561,16 @@ class FlippedSignature:
return getattr(self.__unflipped, name)
def __setattr__(self, name, value):
try: # descriptor first
_gettypeattr(self.__unflipped, name).__set__(self, value)
except AttributeError:
setattr(self.__unflipped, name, value)
if name == "members":
# Although `sig.flip().members` does not call `__getattr__` but directly invokes
# the descriptor of the `FlippedSignature.members` property, `sig.flip().members +=`
# does call `__setattr__`, and this must be special-cased for the setter to work.
FlippedSignature.members.__set__(self, value)
else:
try: # descriptor first
_gettypeattr(self.__unflipped, name).__set__(self, value)
except AttributeError:
setattr(self.__unflipped, name, value)
def __delattr__(self, name):
try: # descriptor first

View file

@ -374,6 +374,18 @@ class SignatureTestCase(unittest.TestCase):
r"^Cannot add members to a frozen signature$"):
sig.members += {"b": Out(1)}
def test_members_plus_equal(self):
sig = Signature({})
# This invokes the setter of Signature.members.
sig.members += {"a": In(1)}
self.assertIn("a", sig.members)
def test_members_equal_wrong(self):
sig = Signature({})
with self.assertRaisesRegex(AttributeError,
r"property 'members' of 'Signature' object cannot be set"):
sig.members = SignatureMembers({})
def assertFlattenedSignature(self, actual, expected):
for (a_path, a_member, a_value), (b_path, b_member, b_value) in zip(actual, expected):
self.assertEqual(a_path, b_path)
@ -595,6 +607,18 @@ class FlippedSignatureTestCase(unittest.TestCase):
fsig.x()
self.assertEqual(x_type, S)
def test_members_plus_equal(self):
sig = Signature({})
# This invokes the setter of FlippedSignature.members.
sig.flip().members += {"a": In(1)}
self.assertIn("a", sig.members)
def test_members_equal_wrong(self):
sig = Signature({})
with self.assertRaisesRegex(AttributeError,
r"property 'members' of 'FlippedSignature' object cannot be set"):
sig.flip().members = SignatureMembers({})
class InterfaceTestCase(unittest.TestCase):
pass