Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python-2.7: doctests ignored in setter method of a class

Why does the following example fail to run its doctest in the setter method?

class Foo:
    a = None

    @property
    def a(self):
        pass

    @a.setter
    def a(self, v):
        '''
        >>> 1 == 1
        False
        '''
        pass

if __name__ == "__main__":
    import doctest
    doctest.testmod()

The debugger confirms that no test is run (example above written to dtest.py):

>>> import dtest, doctest
>>> doctest.testmod(dtest)
TestResults(failed=0, attempted=0)

The same test in the getter method is correctly executed, reporting failure of course...

like image 775
sphakka Avatar asked Apr 28 '14 12:04

sphakka


1 Answers

The @a.setter decorator ignores the docstring and it is not copied to the resulting property object; set the docstring on the getter instead.

See the property documentation:

If given, doc will be the docstring of the property attribute. Otherwise, the property will copy fget‘s docstring (if it exists).

Emphasis mine.

Your code results in:

>>> class Foo:
...     a = None
...     @property
...     def a(self):
...         pass
...     @a.setter
...     def a(self, v):
...         '''
...         >>> 1 == 1
...         False
...         '''
...         pass
...
>>> Foo.a
<property object at 0x101a21050>
>>> Foo.a.__doc__ is None
True

Set the docstring on the getter however and you get:

>>> class Foo:
...     a = None
...     @property
...     def a(self):
...         '''
...         >>> 1 == 1
...         False
...         '''
...         pass
...     @a.setter
...     def a(self, v):
...         pass
... 
>>> Foo.a
<property object at 0x101a210a8>
>>> Foo.a.__doc__
'\n        >>> 1 == 1\n        False\n        '

Another, ugly workaround would be to recreate the property with the docstring being copied from the setter, explicitly:

class Foo:
    a = None

    @property
    def a(self):
        pass

    @a.setter
    def a(self, v):
        '''
        >>> 1 == 1
        False
        '''
        pass

    a = property(a.fget, a.fset, doc=a.fset.__doc__)
like image 136
Martijn Pieters Avatar answered Sep 28 '22 06:09

Martijn Pieters