@@ -77,6 +77,12 @@ def test(fun, name):
7777 traceback.print_exc()
7878 else:
7979 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}")
8086
8187 def test_dunder(obj, fun_name, *args):
8288 # avoid going through tp_getattr/o, which may be overridden to something funky
@@ -93,8 +99,8 @@ def write_attr(obj, attr, value):
9399 obj = Klass()
94100 test(lambda: bool(obj), "bool(obj)")
95101 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__' )
98104 test(lambda: obj.foo, "obj.foo")
99105 test(lambda: obj.bar, "obj.bar")
100106
@@ -107,25 +113,26 @@ def write_attr(obj, attr, value):
107113 test(lambda: obj.foo, "obj.foo")
108114 test(lambda: obj.bar, "obj.bar")
109115
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")
118125
119126 class Dummy1:
120127 pass
121128
122129 obj = Klass()
123130 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)
129136
130137 class WithDescr:
131138 descr = Klass()
@@ -215,7 +222,7 @@ def tp_decl(self, name_prefix):
215222 Slot ('tp_as_number' , 'nb_bool' , 'int $name$(PyObject* self)' , ['1' , '0' , None ]),
216223 Slot ('tp_as_sequence' , 'sq_length' , 'Py_ssize_t $name$(PyObject* self)' , ['0' , '1' , '42' , None ]),
217224 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 ,
219226 '''
220227 if (global_stash1 == NULL) Py_RETURN_NONE;
221228 Py_IncRef(global_stash1);
@@ -227,7 +234,14 @@ def tp_decl(self, name_prefix):
227234 Py_IncRef(global_stash1);
228235 return global_stash1;
229236 ''' ]),
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 ,
231245 '''
232246 Py_IncRef(value);
233247 Py_XDECREF(global_stash1);
@@ -253,10 +267,24 @@ def tp_decl(self, name_prefix):
253267MAGIC = {
254268 '__bool__(self)' : ['True' , 'False' , None ],
255269 '__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 ],
258272 '__get__(self,obj,objtype=None)' : ['obj' , 'True' , 'self.descr_value' , None ],
259273 '__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+ ''' ],
260288}
261289
262290
0 commit comments