Skip to content

Commit 3b3da41

Browse files
committed
add unittest for adding and removing attribute in class instance prior to deepcopy
1 parent d009a6c commit 3b3da41

File tree

1 file changed

+85
-59
lines changed

1 file changed

+85
-59
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_class-set-attrib.py

Lines changed: 85 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -39,87 +39,113 @@
3939

4040
counter = 0
4141

42+
4243
class Foo:
43-
def __setattr__(self, key, value):
44-
global counter
45-
counter = counter + 1
46-
object.__setattr__(self, key, value)
47-
def __delattr__(self, key):
48-
global counter
49-
counter = counter + 10
50-
object.__delattr__(self, key)
44+
def __setattr__(self, key, value):
45+
global counter
46+
counter = counter + 1
47+
object.__setattr__(self, key, value)
48+
49+
def __delattr__(self, key):
50+
global counter
51+
counter = counter + 10
52+
object.__delattr__(self, key)
53+
5154

5255
def test_call():
53-
global counter
54-
counter = 0
55-
f = Foo()
56-
f.a = 1
57-
Foo.b = 123
58-
assert counter == 1, "setting attrib on class should not call its own __setattr__"
59-
del f.a
60-
del Foo.b
61-
assert counter == 11, "deleting attrib on class should not call its own __delattr__"
56+
global counter
57+
counter = 0
58+
f = Foo()
59+
f.a = 1
60+
Foo.b = 123
61+
assert counter == 1, "setting attrib on class should not call its own __setattr__"
62+
del f.a
63+
del Foo.b
64+
assert counter == 11, "deleting attrib on class should not call its own __delattr__"
65+
6266

6367
class AClass:
64-
pass
68+
pass
69+
6570

6671
class BClass(AClass):
67-
pass
72+
pass
73+
6874

6975
class CClass(BClass):
70-
pass
76+
pass
77+
7178

7279
class DClass(BClass):
73-
pass
80+
pass
81+
7482

7583
def custom_set(self, key, value):
76-
object.__setattr__(self, key, value + 10 if isinstance(value, int) else value)
84+
object.__setattr__(self, key, value + 10 if isinstance(value, int) else value)
85+
7786

7887
def custom_get(self, key):
79-
value = object.__getattribute__(self, key)
80-
return value + 100 if isinstance(value, int) else value
88+
value = object.__getattribute__(self, key)
89+
return value + 100 if isinstance(value, int) else value
90+
8191

8292
def test_assignments():
83-
object = CClass()
84-
# writing to BClass changes the result, writing to DClass doesn't
85-
targets = (AClass, BClass, DClass, CClass, object)
86-
results = (0, 1, 1, 3, 4)
87-
for i in range(0, len(targets)):
88-
targets[i].foo = i
89-
assert object.foo == results[i], "normal %d" %i
90-
# make sure that a custom __getattribute__ is used
91-
BClass.__getattribute__ = custom_get
92-
for i in range(0, len(targets)):
93-
targets[i].bar = i
94-
assert object.bar == results[i] + 100, "custom get %d" % i
95-
# check correct lookups when deleting attributes
96-
for i in reversed(range(0, len(targets))):
97-
assert object.bar == results[i] + 100, "delete %d" % i
98-
del targets[i].bar
99-
# make sure a custom __setattr__ is used
100-
BClass.__setattr__ = custom_set
101-
object.baz = 9
102-
assert object.baz == 119, "custom set"
93+
object = CClass()
94+
# writing to BClass changes the result, writing to DClass doesn't
95+
targets = (AClass, BClass, DClass, CClass, object)
96+
results = (0, 1, 1, 3, 4)
97+
for i in range(0, len(targets)):
98+
targets[i].foo = i
99+
assert object.foo == results[i], "normal %d" % i
100+
# make sure that a custom __getattribute__ is used
101+
BClass.__getattribute__ = custom_get
102+
for i in range(0, len(targets)):
103+
targets[i].bar = i
104+
assert object.bar == results[i] + 100, "custom get %d" % i
105+
# check correct lookups when deleting attributes
106+
for i in reversed(range(0, len(targets))):
107+
assert object.bar == results[i] + 100, "delete %d" % i
108+
del targets[i].bar
109+
# make sure a custom __setattr__ is used
110+
BClass.__setattr__ = custom_set
111+
object.baz = 9
112+
assert object.baz == 119, "custom set"
103113

104114

105115
def test_setattr_via_decorator():
106-
def setdec(func):
107-
setattr(func, 'SPECIAL_ATTR', {'a': 1, 'b': 2})
108-
return func
116+
def setdec(func):
117+
setattr(func, 'SPECIAL_ATTR', {'a': 1, 'b': 2})
118+
return func
109119

110-
@setdec
111-
def f():
112-
return 1
120+
@setdec
121+
def f():
122+
return 1
113123

114-
assert hasattr(f, 'SPECIAL_ATTR')
115-
assert getattr(f, 'SPECIAL_ATTR') == {'a': 1, 'b': 2}
124+
assert hasattr(f, 'SPECIAL_ATTR')
125+
assert getattr(f, 'SPECIAL_ATTR') == {'a': 1, 'b': 2}
116126

127+
class MyClass(object):
128+
@setdec
129+
def f(self):
130+
return 1
117131

118-
class MyClass(object):
119-
@setdec
120-
def f(self):
121-
return 1
132+
m = MyClass()
133+
assert hasattr(m.f, 'SPECIAL_ATTR')
134+
assert getattr(m.f, 'SPECIAL_ATTR') == {'a': 1, 'b': 2}
135+
136+
137+
def test_deepcopy_attribute_removal():
138+
from copy import deepcopy
139+
140+
class A:
141+
a = "a"
142+
143+
def add_rem_attr(self):
144+
self.b = "b"
145+
del self.b
146+
147+
i1 = A()
148+
assert i1.__dict__ == deepcopy(i1).__dict__
122149

123-
m = MyClass()
124-
assert hasattr(m.f, 'SPECIAL_ATTR')
125-
assert getattr(m.f, 'SPECIAL_ATTR') == {'a': 1, 'b': 2}
150+
i1.add_rem_attr()
151+
assert i1.__dict__ == deepcopy(i1).__dict__

0 commit comments

Comments
 (0)