[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