[ python-Bugs-864944 ] doctest chokes on recursive members

SourceForge.net noreply at sourceforge.net
Sun Aug 8 05:25:16 CEST 2004


Bugs item #864944, was opened at 2003-12-23 06:51
Message generated for change (Comment added) made by tim_one
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=864944&group_id=5470

Category: Python Library
Group: Python 2.3
>Status: Closed
>Resolution: Fixed
Priority: 5
Submitted By: Gintautas Miliauskas (gintautasm)
>Assigned to: Tim Peters (tim_one)
Summary: doctest chokes on recursive members

Initial Comment:
doctests recurse infinitely when they find a recursive
member in a class. A simple example:

--b0rk.py--
class Crash:
    pass

Crash.c = Crash
-----

--test.py--
import doctest
import b0rk

doctest.testmod(b0rk)
-----

--output of test.py--
Traceback (most recent call last):
  File "test.py", line 5, in ?
    doctest.testmod(b0rk)
  File "/usr/lib/python2.3/doctest.py", line 1148, in
testmod
    f, t = tester.rundict(m.__dict__, name, m)
  File "/usr/lib/python2.3/doctest.py", line 908, in
rundict
    f2, t2 = self.__runone(value, name + "." + thisname)
  File "/usr/lib/python2.3/doctest.py", line 1069, in
__runone
    return self.rundoc(target, name)
  File "/usr/lib/python2.3/doctest.py", line 828, in rundoc
    f2, t2 = self.run__test__(d, name)
<.............................>
  File "/usr/lib/python2.3/doctest.py", line 935, in
run__test__
    f, t = self.rundoc(v, thisname)
  File "/usr/lib/python2.3/doctest.py", line 790, in rundoc
    for tag, kind, homecls, value in
_classify_class_attrs(object):
  File "/usr/lib/python2.3/inspect.py", line 201, in
classify_class_attrs
    mro = getmro(cls)
RuntimeError: maximum recursion depth exceeded
-----

----------------------------------------------------------------------

>Comment By: Tim Peters (tim_one)
Date: 2004-08-07 23:25

Message:
Logged In: YES 
user_id=31435

This is fixed in Python 2.4's doctest.py, which does keep a 
set of already-seen objects.  But, since this was done as 
part of a massive refactoring of doctest.py, I have no plan to 
backport any part of it to the 2.3 line.

----------------------------------------------------------------------

Comment By: Marius Gedminas (mgedmin)
Date: 2003-12-29 05:52

Message:
Logged In: YES 
user_id=44660

The fact that the traceback ends in getmro is just an accident.
There is an infinite recursion between run__test__ and rundoc
when a class attribute references the class itself.

The problem was originally noticed by playing with Zope 3.
Apparently Zope 3 interfaces add a class attribute that
references the class itself (perhaps indirectly) and causes this
problem to appear whenever a class declares that it implements
some interface, e.g.

  from zope.interface import implements

  class SomeClass(object):
      """docstring

      >>> x = SomeClass()
      ...
      """

      implements(ISomeInterface)

Since Zope 3 component architecture requires that virtually
all classes declare what interfaces they implement, it makes
class doctests unusable with Zope 3.

A possible solution is to keep a set of "seen" objects and check
near the beginning of Tester.rundoc whether an object was
already processed.


----------------------------------------------------------------------

Comment By: Gintautas Miliauskas (gintautasm)
Date: 2003-12-29 05:46

Message:
Logged In: YES 
user_id=936754

I guess I snipped a little too much traceback...

Here is a part of traceback (reproduced with python 2.2.)
that illustrates the idea:

<...>
  File "/usr/lib/python2.2/doctest.py", line 905, in run__test__
    f, t = self.rundoc(v, thisname)
  File "/usr/lib/python2.2/doctest.py", line 798, in rundoc
    f2, t2 = self.run__test__(d, name)
  File "/usr/lib/python2.2/doctest.py", line 905, in run__test__
    f, t = self.rundoc(v, thisname)
  File "/usr/lib/python2.2/doctest.py", line 798, in rundoc
    f2, t2 = self.run__test__(d, name)
  File "/usr/lib/python2.2/doctest.py", line 905, in run__test__
    f, t = self.rundoc(v, thisname)
  File "/usr/lib/python2.2/doctest.py", line 798, in rundoc
    f2, t2 = self.run__test__(d, name)
<...>

It's definitely not a fault of getmro(). Besides, I've
tested and the crash occurs on Python 2.1, 2.2 and 2.3.

----------------------------------------------------------------------

Comment By: Terry J. Reedy (tjreedy)
Date: 2003-12-28 17:05

Message:
Logged In: YES 
user_id=593130

Traceback says crash happens in inspect.getmro and not in 
doctest itself.  In 2.2.1, I get

>>> class C: pass
...
>>> C.c=C
>>> import inspect as i
>>> i.getmro(C)
(<class __main__.C at 0x00867510>,)

However, mro resolution was changed for 2.3.  See if above 
changes in 2.3.  Or if calling on class inside imported module 
makes a difference.


----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=864944&group_id=5470


More information about the Python-bugs-list mailing list