[Python-Dev] test_doctest failing, but perhaps by accident

Tim Peters tim.one@home.com
Wed, 21 Mar 2001 17:30:52 -0500


[Michael Hudson]
> Oooh, look at this:
>
> $ ../../python
> Python 2.1b2 (#3, Mar 21 2001, 21:29:14)
> [GCC 2.95.1 19990816/Linux (release)] on linux2
> Type "copyright", "credits" or "license" for more information.
> >>> import doctest
> >>> doctest.Tester.__dict__.keys()
> ['__init__', '__doc__', 'run__test__', '_Tester__record_outcome',
> 'runstring', 'summarize', '_Tester__runone', 'rundict', 'merge',
> 'rundoc', '__module__']
> >>> doctest.testmod(doctest)
> (0, 53)
> >>> doctest.Tester.__dict__.keys()
> ['__init__', '__doc__', 'run__test__', 'summarize',
> '_Tester__runone', 'rundict', 'merge', 'runstring', 'rundoc',
> '_Tester__record_outcome', '__module__']

Cute!  Hard to explain, unless someone is using PyDict_Next on this dict:
since the dict has 11 items, it's exactly at the boundary where PyDict_Next
will now resize it.

> Indeed:
>
> $ ../../python
> Python 2.1b2 (#3, Mar 21 2001, 21:29:14)
> [GCC 2.95.1 19990816/Linux (release)] on linux2
> Type "copyright", "credits" or "license" for more information.
> >>> import doctest
> >>> doctest.Tester.__dict__.keys()
> ['__init__', '__doc__', 'run__test__', '_Tester__record_outcome',
> 'runstring', 'summarize', '_Tester__runone', 'rundict', 'merge',
> 'rundoc', '__module__']
> >>> doctest.Tester.__dict__['__doc__'] = doctest.Tester.__dict__['__doc__']
> >>> doctest.Tester.__dict__.keys()
> ['__init__', '__doc__', 'run__test__', 'summarize',
> '_Tester__runone', 'rundict', 'merge', 'runstring', 'rundoc',
> '_Tester__record_outcome', '__module__']
>
> BUT, and this is where I give up:
>
>     This has always happened!  It even happens with Python 1.5.2!

Yes, but in this case you did an explicit setitem, and PyDict_SetItem *will*
resize it (because it started with 11 entries:  11*3 >= 16*2, but 10*3 <
16*2).  Nothing has changed there in many years.

> it just makes a difference now.  So maybe it's something else entirely.

Well, nobody should rely on the order of dict.items().  Curiously, doctest
actually doesn't, but the order of its verbose-mode *output* blocks changes,
and it's the regrtest.py framework that cares about that.

I'm calling this one a bug in doctest.py, and will fix it there.  Ugly:
since we can longer rely on list.sort() not raising exceptions, it won't be
enough to replace the existing

    for k, v in dict.items():

with

    items = dict.items()
    items.sort()
    for k, v in items:

I guess

    keys = dict.keys()
    keys.sort()
    for k in keys:
        v = dict[k]

is the easiest safe alternative (these are namespace dicts, btw, so it's
certain the keys are all strings).

thanks-for-the-help!-ly y'rs  - tim