Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

#170 weird warning with property()

devel (cvs)
closed-fixed
Edward Loper
5
2007-09-23
2007-02-12
Cat slave
No

Seems that epydoc gets confused somehow when using property() with comments on the referenced methods. Maybe it's not important, I am just pointing out that I get warnings and don't know if I did something wrong.

I updated to trunk version r1465, but keep getting this warning:

+---------------------------------------------------------------------------------------------------------------------------------------
| File /whatever/file.py, in file.A.x
| Warning: Invalid context for u'return'
| Warning: Invalid context for u'rtype'

When i have something like this (javadoc type):

-----8<-----CUT-----8<-----
Class A:

def _get_x(self):
u"""\ bla bla.

@return my X.
@rtype int
"""
return self._x

def _set_x(self, x):
u"""\ bla bla.

@param x Desired X.
@type x int
"""
self._x = x

x = property(_get_x, _set_x)
-----8<-----CUT-----8<-----

Discussion

  • Edward Loper
    Edward Loper
    2007-02-13

    • assigned_to: nobody --> edloper
     
  • Edward Loper
    Edward Loper
    2007-02-13

    Logged In: YES
    user_id=195958
    Originator: NO

    This is caused by a change from Python 2.4 -> 2.5. Apparently, in 2.5, when you don't specify an explicit doc for a property, it will copy it from fget.__doc__. And so the property ends up with the fget function's docstring. That docstring contains fields that make sense in the context of a function (eg @return) but not for a property. I.e., the following code:

    . class A:
    . def f(): "f's docstring"
    . g = property(f)
    . print "A.g's docstring is %s" % A.g.__doc__

    returns different values under Python 2.4 and Python 2.5 (docstring is None for 2.4, docstring is "f's docstring" for 2.5).

    I'm not really sure what the best fix for this is. We could test if prop.__doc__ is prop.fget.__doc__, but that could give false positives, esp if people are explicitly trying to copy the fget's doc to the property with something like:

    x = property(_get_x, _set_x, doc=_get_x.__doc__)

    Another alternative would be to make the property docstring accept return fields.. But it's not immediately clear what it would do with them. And we would also need to consider @param fields, which seem even more odd to include in the property's __doc__..

    In the meantime, a simple fix for your own code would be to explicitly define property x's doc. I.e., do one of:

    x = property(_get_x, _set_x, doc=None)

    or:

    x = property(_get_x, _set_x, doc="description of x")

     
  • Cat slave
    Cat slave
    2007-02-13

    Logged In: YES
    user_id=363555
    Originator: YES

    Thanks for the precise answer.

    Now, if I adopt the property(fget, fset, doc=u"""....""") format, what should I put in doc to let the API know what property type it is? Like I would do with a @type or @rtype in normal methods.

     
  • Edward Loper
    Edward Loper
    2007-02-13

    Logged In: YES
    user_id=195958
    Originator: NO

    Epydoc understands the '@type' field in the property docstring [1]. I usually end up formatting it something like:

    | x = property(x_fget, x_fset, doc=
    | """The x position of the frooble.
    | @type: C{int}
    | @see: L{y}, which gives the y position.""")

    Because that way it looks like other docstrings.

    [1] http://epydoc.sourceforge.net/fields.html

     
  • Cat slave
    Cat slave
    2007-02-13

    Logged In: YES
    user_id=363555
    Originator: YES

    sorry, i did not specify on my reply, but in the original post, i am using javadoc docstring.

    | Warning: u'type' did not expect an argument

    so i get the above warning when i have:

    member = property(fget, gset, doc=u"""\ bla bla bla

    @type unicode
    """)

    Also have tried @rtype in case. I have also tried: "@type: C{unicode}", and it gives no warnings, but nothing is added on the left column in the API.

    Thanks.

     
  • Edward Loper
    Edward Loper
    2007-02-14

    Logged In: YES
    user_id=195958
    Originator: NO

    Ah, ok. I see the problem then. In javadoc, you can't tell from just the markup whether a filed takes an arg or not; so the javadoc processer just has a list of fields that do and don't take args. It has "type" listed in the does-takea-an-arg list, which is incompatible with how it's used in properties. c.f with epytext, where the difference between "@type x: foo" and "@type: x foo" is easy to parse.

    So.. The easiest solution would be to just define a new field name that's used in javadoc markup for variables and properties to define their types. The new field would be declared as not-taking-an-argument, but would otherwise be identical to the 'type' field. Not sure what a good name for this new field would be. @mytype perhaps? Or @selftype or @vartype?

    A somewhat harder option would be to refactor epydoc's code a little, so that the docstring markup knows what type of object the docstring it's processing belongs to; and the javadoc markup code could then use that to make 'type' behave differently depending on whether it's a var/property docstring (where @type takes no arg) or a function/class/module docstring (where @type takes an arg).

     
  • Cat slave
    Cat slave
    2007-02-14

    Logged In: YES
    user_id=363555
    Originator: YES

    If you choose the new field way, maybe it could be named @propertytype.

    or maybe I should put laziness apart and learn epytext syntax, which seem to be more easy to document class and module variables.

    Thanks for prompt and efficient support.

     
  • Logged In: YES
    user_id=1053920
    Originator: NO

    Probably the 2.5 added the "get doc from fget" feature because people has started writing read only properties with the idiom:

    @property
    def foo(self):
    """Magic number."""
    return 42

    Wouldn't be easier to add rtype in the tags recognized by the property? It doesn't take arguments and is consistent between the function and the property.

    The patch is here below. If Ed doesn't dislike it i'll commit it.

    --- src/epydoc/docstringparser.py (revision 1564)
    +++ src/epydoc/docstringparser.py (working copy)
    @@ -759,11 +759,19 @@
    api_doc.return_descr = descr

    def process_rtype_field(api_doc, docindex, tag, arg, descr):
    - _check(api_doc, tag, arg, context=RoutineDoc, expect_arg=False)
    - if api_doc.return_type is not None:
    - raise ValueError(REDEFINED % 'return value type')
    - api_doc.return_type = descr
    + _check(api_doc, tag, arg,
    + context=(RoutineDoc, PropertyDoc), expect_arg=False)
    + if isinstance(api_doc, RoutineDoc):
    + if api_doc.return_type is not None:
    + raise ValueError(REDEFINED % 'return value type')
    + api_doc.return_type = descr

    + elif isinstance(api_doc, PropertyDoc):
    + _check(api_doc, tag, arg, expect_arg=False)
    + if api_doc.type_descr is not None:
    + raise ValueError(REDEFINED % tag)
    + api_doc.type_descr = descr
    +
    def process_arg_field(api_doc, docindex, tag, arg, descr):
    _check(api_doc, tag, arg, context=RoutineDoc, expect_arg=True)
    idents = re.split('[:;, ] *', arg)

     
  • Edward Loper
    Edward Loper
    2007-09-23

    Logged In: YES
    user_id=195958
    Originator: NO

    Looks good, Daniele. I applied your patch in svn 1623 -- so now @rtype can be used with properties.

    It might be a good idea to add a FAQ entry about the behavior in py2.5 of copying the property's __doc__ from the fget method.

     
  • Edward Loper
    Edward Loper
    2007-09-23

    • status: open --> closed-fixed