msg11453 - (view) |
Author: Roeland Rengelink (rengelink) |
Date: 2002-07-03 14:42 |
If I inherit from property, and try to initialize a derived property object, the doc string doesn't get set. This bug was introduced in 2.2.1, and is present in 2.3a0: Compare: Python 2.2 (#1, Mar 26 2002, 15:46:04) [GCC 2.95.3 20010315 (SuSE)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> class myprop(property):pass ... >>> a = myprop(None, None, None, 'hi') >>> print a.__doc__ hi and, Python 2.2.1 (#1, Jun 16 2002, 16:19:48) [GCC 2.95.3 20010315 (SuSE)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> class myprop(property):pass ... >>> a = myprop(None, None, None, 'hi') >>> print a.__doc__ None There is no problem with the getter/setter functions passed to the constructor. i.e.: myprop(f,g,h,None) works identical in 2.2 and 2.2.1 Good luck, Roeland Rengelink |
|
|
msg11454 - (view) |
Author: Roeland Rengelink (rengelink) |
Date: 2002-07-08 12:23 |
Logged In: YES user_id=302601 Some more details: In fact 2.2.1 is consistently wrong, whereas 2.2 is inconsistently right ;), compare: Python 2.2.1 (#20, Jul 8 2002, 13:25:14) [GCC 3.1] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> class myprop(property):pass ... >>> class yourprop(property): ... "A doc string" ... >>> print myprop(None, None, None, 'Hi there').__doc__ None >>> print yourprop(None, None, None, 'Hi there').__doc__ A doc string and Python 2.2 (#4, Jan 7 2002, 11:59:25) [GCC 2.95.2 19991024 (release)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> class myprop(property):pass ... >>> class yourprop(property): ... "A doc string" ... >>> print myprop(None, None, None, 'Hi there').__doc__ Hi there >>> print yourprop(None, None, None, 'Hi there').__doc__ A doc string So, in 2.2.1 myprop(...).__doc__ will allways return myprop.__doc__. In 2.2 myprop.__doc__ will return the instance's __doc__, iff myprop.__doc__ is None. For the record: I was expecting 'Hi there' (i.e. obj->prop_doc), as in: >>> property(None, None, None, 'Hi there').__doc__ 'Hi there' Hope this helps, Roeland |
|
|
msg11455 - (view) |
Author: Roeland Rengelink (rengelink) |
Date: 2002-07-09 11:52 |
Logged In: YES user_id=302601 I think I found the problem, Compare: >>> property.__doc__ 'property(fget=None,.... # the doc string and >>> property.__dict__['__doc__'] <member '__doc__' of 'property' objects> Note that property.__doc__ and property.__dict__['__doc__'] are not the same. Python will go out of its way to prevent this weird situation in user derived classes., 1. type_new(name, bases, attrs) will copy attrs to new_tp.tp_dict, and will also copy attrs['__doc__'] to tp.tp_doc 2. PyType_Ready(tp) will copy tp.tp_doc to tp.tp_dict['__doc__'] if tp.tp_dict['__doc__'] is undefined This guarantees that tp.tp_dict['__doc__'] will exist, usually copying tp.tp_doc, and shadowing property.tp_dict['__doc__'] if tp is derived from property The solution seems to be: 1. In type_new(): if possible copy attr['__doc__'] to tp.tp_doc, and delete __doc__ from attr (to prevent ending up in tp_dict) 2. in PyType_Ready(): don't copy tp.tp_doc to tp_dict['__doc__'] These two steps make sure that, tp_dict['__doc__'] no longer shadows properties.tp_dict['__doc__']. Unfortunately, this means that tp.__doc__ doesn't generally return the docstrings for user-defined types. Therefore: 3. in type_get_doc(): return tp.tp_doc also for heap types. The result of this will be: 1. properties will be subclassable again. (good) 2. __doc__ string become read-only attributes (bad??) 3. test cases in test_descr that assume that instance.__dict__['__doc__'] exists, will fail 4. a weird test_failure in test_module.py Patches for this modification are attached, except for (test_module.py), which I don't understand. |
|
|
msg11456 - (view) |
Author: Raymond Hettinger (rhettinger) *  |
Date: 2002-09-08 21:55 |
Logged In: YES user_id=80475 I think this is based on a misunderstanding of how to use property. Instead of inheriting from it, you use it as a function call in a new-style class (derived from object): This works fine in versions from 2.2 upto 2.3a: >>> class Myprop(object): a = property(None,None,None,'a sample docstring') >>> Myprop.a.__doc__ 'a sample docstring' Marking as invalid and closing. |
|
|
msg11457 - (view) |
Author: Raymond Hettinger (rhettinger) *  |
Date: 2002-09-08 22:11 |
Logged In: YES user_id=80475 Okay, now I see what you're trying to do. Still, it the strangest use of property that I've seen to-date. Re-opening the bug report. |
|
|
msg11458 - (view) |
Author: Roeland Rengelink (rengelink) |
Date: 2002-09-09 10:49 |
Logged In: YES user_id=302601 To give a usage example: (because rhettinger thought this was a very strange use of properties, and, for all I know, he may be right) >>> class typed_property(property): ... def __init__(self, tp, doc): ... def getter(inst): ... return inst.__dict__[self] ... def setter(inst, val): ... if not isinstance(val, tp): ... raise TypeError ... inst.__dict__[self] = val ... property.__init__(self, getter, setter, ... None, doc) ... >>> class A(object): ... a = typed_property(int, 'a prop') ... >>> inst = A() >>> inst.a = 1 >>> print inst.a 1 >>> inst.a = 'a' Traceback (most recent call last): File "", line 1, in ? File "", line 7, in setter TypeError >>> A.a.__doc__ 'a prop' The last only works in 2.2, and then only if typed_property itself has no doc string |
|
|
msg11459 - (view) |
Author: Guido van Rossum (gvanrossum) *  |
Date: 2002-09-24 12:43 |
Logged In: YES user_id=6380 OK, I'll have a look. We've have numerous hacks upon hacks to get __doc__ to behave right. I don't know if it is within my powers to fix this without breaking other things. But if it is, I'll try to fix it in 2.2.1 as well as 2.3. |
|
|
msg11460 - (view) |
Author: Thomas Heller (theller) *  |
Date: 2002-09-24 13:06 |
Logged In: YES user_id=11105 The attached simple fix (descrobj.diff) fixes the problem for me. |
|
|
msg11461 - (view) |
Author: Thomas Heller (theller) *  |
Date: 2002-09-24 13:12 |
Logged In: YES user_id=11105 Ups, forget my patch. Nothing works, sorry. |
|
|
msg11462 - (view) |
Author: Guido van Rossum (gvanrossum) *  |
Date: 2002-09-24 17:01 |
Logged In: YES user_id=6380 The problem is that class myprop has a __doc__ in its class __dict__ that is the docstring for myprop, or None if that class has no docstring. The march through the MRO looking for an instance attribute descriptor finds this before it would ever get to the property class, so effectively a __doc__ property is not inherited. The simplest workaround I found is this: class myprop(property): __doc__ = property.__dict__['__doc__'] (__doc__ = property.__doc__ does not do the right thing, it gets the property class's docstring rather than the descriptor.) This is a mess. I'll have to think about whether it's possible at all to fix it without breaking something else. I'll also have to think about whether it's worth it. |
|
|
msg11463 - (view) |
Author: Brett Cannon (brett.cannon) *  |
Date: 2003-05-17 02:39 |
Logged In: YES user_id=357491 I vaguely remember this coming on up on python-dev and it being said that this would not get fixed. Am I remembering correctly? |
|
|
msg11464 - (view) |
Author: Guido van Rossum (gvanrossum) *  |
Date: 2003-05-18 21:05 |
Logged In: YES user_id=6380 Yes, you remember correctly. |
|
|
msg11465 - (view) |
Author: Brett Cannon (brett.cannon) *  |
Date: 2003-05-18 22:21 |
Logged In: YES user_id=357491 Since Guido said I remembered correctly I am closing this as "won't fix". |
|
|