[Python-Dev] A baffler in test_repr
Tim Peters
tim.one@home.com
Sun, 23 Sep 2001 04:52:21 -0400
[Tim, reports test_repr failure due to repr(a_static_method), but only
when the whole test suite is run, not in isolation]
+ The same thing happens with classmethod (repr is normally
<classmethod object at 0xnnnnnnnn>
but magically turns into
<classmethod instance at 0xnnnnnnnn>
"sometimes").
+ The gross cause is that tp_repr is normally NULL in the classmethod
and staticmethod types, and PyObject_Repr then prints "object at".
But by the time test_repr starts running (but not in isolation),
their tp_repr slots point to object_repr (which prints "instance at").
The tp_str and tp_hash slots have also changed.
+ To provoke a failure via regrtest, it's necessary and sufficient to
run test_inspect before test_repr, in the same run:
C:\Code\python\PCbuild>python ../lib/test/regrtest.py test_repr # ok
test_repr
1 test OK.
C:\Code\python\PCbuild>python ../lib/test/regrtest.py test_inspect
test_repr # fails
test_inspect
test_repr
test test_repr failed -- Traceback (most recent call last):
File "../lib/test\test_repr.py", line 156, in test_descriptors
self.failUnless(repr(x).startswith('<staticmethod object at 0x'))
File "C:\CODE\PYTHON\lib\unittest.py", line 256, in failUnless
if not expr: raise self.failureException, msg
AssertionError
1 test OK.
1 test failed:
test_repr
C:\Code\python\PCbuild>
+ Turns out I provoked this by adding classify_class_attrs() to
inspect.py, and then foolishly added a test for it <wink>. The
symptom can be provoked by one judiciously chosen line:
C:\Code\python\PCbuild>python
Python 2.2a3+ (#23, Sep 20 2001, 19:43:51) [MSC 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> staticmethod(42) # "object at" output
<staticmethod object at 0x00788710>
>>> len(staticmethod.__dict__) # and you think this is harmless <wink>
10
>>> staticmethod(42) # whoa! now it's "instance at" output
<staticmethod instance at 0x00788710>
>>>
That is, just asking for a type's __dict__ can change the values in the type
slots. This doesn't seem right -- or does it?
gunshyly y'rs - tim