doctest + shelve question

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Sat Mar 7 09:26:38 EST 2009


En Fri, 06 Mar 2009 19:56:07 -0200, Sebastian Bartos  
<seth.kriticos at googlemail.com> escribió:

> I have a question. I'm writing a simple object serialization module
> using shelve to write arbitrary objects to a file (M.py). Now I have the
> problem, that if I create a simple object in the doctest documentation
> file M.txt like this:
>
>     >>> class tdata(object):
>     ...     def __init__(self, name):
>     ...         self.name = name
>     >>> tinst = tdata(u'foo')
>
> and then run it with my module M:
>
>     >>> import M
>     >>> foo = M.serialize('/tmp/foo', tinst.name, tinst)
>
> then I get the following problem:
>
> Failed example:
>     foo = M.serialize('/tmp/foo', tinst)
> Exception raised:
>     Traceback (most recent call last):
>       File "/usr/lib/python2.5/doctest.py", line 1228, in __run
>         compileflags, 1) in test.globs
> ...
>       File "/usr/lib/python2.5/shelve.py", line 123, in __setitem__
>         p.dump(value)
>     PicklingError: Can't pickle <class 'tdata'>: attribute lookup
> __builtin__.tdata failed
>
>
> If I do the same in the interactive interpreter, then it works fine.
>
> Now, as I want to test an arbitrary data class, the doctest file is the
> place to put the simple tdata class, but as far as I traced the problem,
> it uses it's own namespace or something, and so does not work.

The environment in which doctests run isn't a module, and pickle requires  
that the class definition be a top level object in a module. So your class  
should reside in a true Python module.

In your case, if the intent was to show that any class may be serialized  
using your library, I think you could use *any* existing class in any  
other module - there is no need to create a special one.

This is a (very ugly!) workaround:

     >>> def _register_as_true_class_in_its_module(class_):
     ...   import sys
     ...   m = sys.modules[class_.__module__]
     ...   setattr(m, class_.__name__, class_)
     ...
     >>> class tdata(object):
     ...     def __init__(self, name):
     ...         self.name = name
     >>> _register_as_true_class_in_its_module(tdata)
     >>> tinst = tdata(u'foo')

See http://bugs.python.org/issue5021 for a (somewhat) related issue.

-- 
Gabriel Genellina




More information about the Python-list mailing list