mirror of
https://github.com/micropython/micropython.git
synced 2025-09-06 01:40:34 +02:00
Including the stochastic tests needed to guarantee sensitivity to the potential iterate-while-modifying hazard a naive implementation might have. Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
183 lines
3.0 KiB
Python
183 lines
3.0 KiB
Python
# Test that __set_name__ can access and mutate its owner argument.
|
|
|
|
|
|
def skip_if_no_descriptors():
|
|
class Descriptor:
|
|
def __get__(self, obj, cls):
|
|
return
|
|
|
|
class TestClass:
|
|
Forward = Descriptor()
|
|
|
|
a = TestClass()
|
|
try:
|
|
a.__class__
|
|
except AttributeError:
|
|
# Target doesn't support __class__.
|
|
print("SKIP")
|
|
raise SystemExit
|
|
|
|
b = a.Forward
|
|
if "Descriptor" in repr(b.__class__):
|
|
# Target doesn't support descriptors.
|
|
print("SKIP")
|
|
raise SystemExit
|
|
|
|
|
|
skip_if_no_descriptors()
|
|
|
|
|
|
# Test basic accesses and mutations.
|
|
|
|
|
|
class GetSibling:
|
|
def __set_name__(self, owner, name):
|
|
print(getattr(owner, name + "_sib"))
|
|
|
|
|
|
class GetSiblingTest:
|
|
desc = GetSibling()
|
|
desc_sib = 111
|
|
|
|
|
|
t110 = GetSiblingTest()
|
|
|
|
|
|
class SetSibling:
|
|
def __set_name__(self, owner, name):
|
|
setattr(owner, name + "_sib", 121)
|
|
|
|
|
|
class SetSiblingTest:
|
|
desc = SetSibling()
|
|
|
|
|
|
t120 = SetSiblingTest()
|
|
|
|
print(t120.desc_sib)
|
|
|
|
|
|
class DelSibling:
|
|
def __set_name__(self, owner, name):
|
|
delattr(owner, name + "_sib")
|
|
|
|
|
|
class DelSiblingTest:
|
|
desc = DelSibling()
|
|
desc_sib = 131
|
|
|
|
|
|
t130 = DelSiblingTest()
|
|
|
|
try:
|
|
print(t130.desc_sib)
|
|
except AttributeError:
|
|
print("AttributeError")
|
|
|
|
|
|
class GetSelf:
|
|
x = 211
|
|
|
|
def __set_name__(self, owner, name):
|
|
print(getattr(owner, name).x)
|
|
|
|
|
|
class GetSelfTest:
|
|
desc = GetSelf()
|
|
|
|
|
|
t210 = GetSelfTest()
|
|
|
|
|
|
class SetSelf:
|
|
def __set_name__(self, owner, name):
|
|
setattr(owner, name, 221)
|
|
|
|
|
|
class SetSelfTest:
|
|
desc = SetSelf()
|
|
|
|
|
|
t220 = SetSelfTest()
|
|
|
|
print(t220.desc)
|
|
|
|
|
|
class DelSelf:
|
|
def __set_name__(self, owner, name):
|
|
delattr(owner, name)
|
|
|
|
|
|
class DelSelfTest:
|
|
desc = DelSelf()
|
|
|
|
|
|
t230 = DelSelfTest()
|
|
|
|
try:
|
|
print(t230.desc)
|
|
except AttributeError:
|
|
print("AttributeError")
|
|
|
|
|
|
# Test exception behavior.
|
|
|
|
|
|
class Raise:
|
|
def __set_name__(self, owner, name):
|
|
raise Exception()
|
|
|
|
|
|
try:
|
|
|
|
class RaiseTest:
|
|
desc = Raise()
|
|
except Exception as e: # CPython raises RuntimeError, MicroPython propagates the original exception
|
|
print("Exception")
|
|
|
|
|
|
# Ensure removed/overwritten class members still get __set_name__ called.
|
|
|
|
|
|
class SetSpecific:
|
|
def __init__(self, sib_name, sib_replace):
|
|
self.sib_name = sib_name
|
|
self.sib_replace = sib_replace
|
|
|
|
def __set_name__(self, owner, name):
|
|
setattr(owner, self.sib_name, self.sib_replace)
|
|
|
|
|
|
class SetReplaceTest:
|
|
a = SetSpecific("b", 312) # one of these is changed first
|
|
b = SetSpecific("a", 311)
|
|
|
|
|
|
t310 = SetReplaceTest()
|
|
print(t310.a)
|
|
print(t310.b)
|
|
|
|
|
|
class DelSpecific:
|
|
def __init__(self, sib_name):
|
|
self.sib_name = sib_name
|
|
|
|
def __set_name__(self, owner, name):
|
|
delattr(owner, self.sib_name)
|
|
|
|
|
|
class DelReplaceTest:
|
|
a = DelSpecific("b") # one of these is removed first
|
|
b = DelSpecific("a")
|
|
|
|
|
|
t320 = DelReplaceTest()
|
|
try:
|
|
print(t320.a)
|
|
except AttributeError:
|
|
print("AttributeError")
|
|
try:
|
|
print(t320.b)
|
|
except AttributeError:
|
|
print("AttributeError")
|