@@ -77,6 +77,12 @@ def test(fun, name):
77
77
traceback.print_exc()
78
78
else:
79
79
print(type(e))
80
+
81
+ def test_dunder(obj, fun_name, *args):
82
+ # avoid going through tp_getattr/o, which may be overridden to something funky
83
+ args_str = ','.join([repr(x) for x in args])
84
+ test(lambda: Klass.__dict__[fun_name](obj, *args), f"{fun_name} via class dict")
85
+ test(lambda: getattr(obj, fun_name)(*args), f"{fun_name}")
80
86
81
87
def test_dunder(obj, fun_name, *args):
82
88
# avoid going through tp_getattr/o, which may be overridden to something funky
@@ -93,8 +99,8 @@ def write_attr(obj, attr, value):
93
99
obj = Klass()
94
100
test(lambda: bool(obj), "bool(obj)")
95
101
test(lambda: len(obj), "len(obj)")
96
- test(lambda: obj.__bool__(), "obj. __bool__()" )
97
- test(lambda: obj.__len__(), "obj. __len__()" )
102
+ test_dunder( obj, ' __bool__' )
103
+ test_dunder( obj, ' __len__' )
98
104
test(lambda: obj.foo, "obj.foo")
99
105
test(lambda: obj.bar, "obj.bar")
100
106
@@ -107,25 +113,26 @@ def write_attr(obj, attr, value):
107
113
test(lambda: obj.foo, "obj.foo")
108
114
test(lambda: obj.bar, "obj.bar")
109
115
110
- test(lambda: obj.__bool__(), "obj.__bool__()")
111
- test(lambda: obj.__len__(), "obj.__len__()")
112
- test(lambda: obj.__getattr__('bar'), "obj.__getattr__('bar')")
113
- test(lambda: obj.__getattribute__('bar'), "obj.__getattribute__('bar')")
114
- test(lambda: obj.__setattr__('foo', 11), "obj.__setattr__('foo', 11)")
115
- test(lambda: obj.__getattr__('foo'), "obj.__getattr__('foo')")
116
- test(lambda: obj.__delattr__('foo'), "obj.__delattr__('foo')")
117
- test(lambda: obj.__getattr__('foo'), "obj.__getattr__('foo')")
116
+ test_dunder(obj, '__bool__')
117
+ test_dunder(obj, '__len__')
118
+ test_dunder(obj, '__getattr__', 'bar')
119
+ test_dunder(obj, '__getattribute__', 'bar')
120
+ test_dunder(obj, '__setattr__', 'foo', 11)
121
+ test_dunder(obj, '__getattr__', 'foo')
122
+ test_dunder(obj, '__delattr__', 'foo')
123
+ test_dunder(obj, '__getattr__', 'foo')
124
+ test(lambda: obj.foo, "obj.foo")
118
125
119
126
class Dummy1:
120
127
pass
121
128
122
129
obj = Klass()
123
130
owner = Dummy1()
124
- test(lambda: obj.__get__(owner), "obj. __get__( owner)" )
125
- test(lambda: obj.__set__(owner, 42), "obj.__set__( owner, 42)" )
126
- test(lambda: obj.__get__(owner), "obj. __get__( owner)" )
127
- test(lambda: obj.__delete__(owner), "obj. __delete__( owner)" )
128
- test(lambda: obj.__get__(owner), "obj. __get__( owner)" )
131
+ test_dunder( obj, ' __get__', owner)
132
+ test_dunder( obj, '__set__', owner, 42)
133
+ test_dunder( obj, ' __get__', owner)
134
+ test_dunder( obj, ' __delete__', owner)
135
+ test_dunder( obj, ' __get__', owner)
129
136
130
137
class WithDescr:
131
138
descr = Klass()
@@ -215,7 +222,7 @@ def tp_decl(self, name_prefix):
215
222
Slot ('tp_as_number' , 'nb_bool' , 'int $name$(PyObject* self)' , ['1' , '0' , None ]),
216
223
Slot ('tp_as_sequence' , 'sq_length' , 'Py_ssize_t $name$(PyObject* self)' , ['0' , '1' , '42' , None ]),
217
224
Slot ('tp_as_mapping' , 'mp_length' , 'Py_ssize_t $name$(PyObject* self)' , ['0' , '1' , '42' , None ]),
218
- Slot (NO_GROUP , 'tp_getattr' , 'PyObject* $name$(PyObject* self, char *name)' , ['Py_RETURN_NONE' , 'Py_RETURN_TRUE ' , 'Py_NewRef(self)' , None ,
225
+ Slot (NO_GROUP , 'tp_getattr' , 'PyObject* $name$(PyObject* self, char *name)' , ['Py_RETURN_NONE' , 'Py_RETURN_FALSE ' , 'Py_NewRef(self)' , None ,
219
226
'''
220
227
if (global_stash1 == NULL) Py_RETURN_NONE;
221
228
Py_IncRef(global_stash1);
@@ -227,7 +234,14 @@ def tp_decl(self, name_prefix):
227
234
Py_IncRef(global_stash1);
228
235
return global_stash1;
229
236
''' ]),
230
- Slot (NO_GROUP , 'tp_setattro' , 'PyObject* $name$(PyObject* self, PyObject *name, PyObject *value)' , ['0' , None ,
237
+ Slot (NO_GROUP , 'tp_setattro' , 'int $name$(PyObject* self, PyObject *name, PyObject *value)' , ['0' , None ,
238
+ '''
239
+ Py_IncRef(value);
240
+ Py_XDECREF(global_stash1);
241
+ global_stash1 = value;
242
+ return 0;
243
+ ''' ]),
244
+ Slot (NO_GROUP , 'tp_setattr' , 'int $name$(PyObject* self, char *name, PyObject *value)' , ['0' , None ,
231
245
'''
232
246
Py_IncRef(value);
233
247
Py_XDECREF(global_stash1);
@@ -253,10 +267,24 @@ def tp_decl(self, name_prefix):
253
267
MAGIC = {
254
268
'__bool__(self)' : ['True' , 'False' , None ],
255
269
'__len__(self)' : ['0' , '1' , '42' , None ],
256
- '__getattribute__(self,name)' : ['name' , '42' , None ],
257
- '__getattr__(self,name)' : ['name+"abc"' , 'False' , None ],
270
+ '__getattribute__(self,name)' : ['name' , '42' , 'self._dict[name]' , None ],
271
+ '__getattr__(self,name)' : ['name+"abc"' , 'False' , 'self._dict[name]' , None ],
258
272
'__get__(self,obj,objtype=None)' : ['obj' , 'True' , 'self.descr_value' , None ],
259
273
'__set__(self,obj,value)' : ['self.descr_value = value\n return None' , None ],
274
+ '__setattr__(self,name,value)' : [None ,
275
+ '''
276
+ if not self._dict:
277
+ self._dict = dict()
278
+ self._dict[name] = value
279
+ return None
280
+ ''' ],
281
+ '__delattr__(self,name,value)' : [None ,
282
+ '''
283
+ if not self._dict:
284
+ self._dict = dict()
285
+ del self._dict[name]
286
+ return None
287
+ ''' ],
260
288
}
261
289
262
290
0 commit comments