[Python-bugs-list] [ python-Bugs-576990 ] inheriting from property and docstrings

noreply@sourceforge.net noreply@sourceforge.net
Tue, 09 Jul 2002 04:52:36 -0700


Bugs item #576990, was opened at 2002-07-03 14:42
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=576990&group_id=5470

Category: Python Interpreter Core
Group: Python 2.2.1
Status: Open
Resolution: None
Priority: 5
Submitted By: Roeland Rengelink (rengelink)
Assigned to: Nobody/Anonymous (nobody)
Summary: inheriting from property and docstrings

Initial Comment:
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   
   
   

----------------------------------------------------------------------

>Comment By: Roeland Rengelink (rengelink)
Date: 2002-07-09 11:52

Message:
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. 

----------------------------------------------------------------------

Comment By: Roeland Rengelink (rengelink)
Date: 2002-07-08 12:23

Message:
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

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=576990&group_id=5470