Andy Maier added the comment:

Using Ethan's sample code (Thanks!!), I was pointed in the right direction and 
was able to produce a simple piece of code that reproduces the behavior without 
depending on enum34, as well as a proposal for a fix in pydoc.py.

The problem can be reproduced with a class that specifies a metaclass that has 
class attributes and includes these class attributes in its __dir__() result, 
which causes them to "propagate" as class attributes to the class using that 
metaclass, at least for the purposes of pydoc.

In the course of the processing within pydoc.py, the tuple returned by 
inspect.classify_class_attrs() for such class attributes then has None for its 
class item, which triggers the issue I originally reported (pydoc traps and 
produces just a dummy help description).

In my original problem with the enum34 module, the same thing happens, just 
here the "propagated" class attributes include the __members__ list, which is 
defined as a property. So I do believe that my simple code represents the same 
error situation as the original enum34 issue.

Because pydoc.py already has its own classify_class_attrs() function that 
wrappers inspect.classify_class_attrs() for the purpose of treating data 
descriptors correctly, I think it would be acceptable to continue down the path 
of fixing it up, just this case for class attributes propagated by the 
metaclass. That's what my proposed fix does.

Unfortunately, it seems one can attach only one file, so I paste the 
reproduction code in here, and attach the fixed pydoc.py.

Here is the code that reproduces the issue:
---------------- bug2.py
# Boolean test switches that control whether a class variable of the metaclass
# is added to the dir() result.
# If the fix is not present, then enabling each one triggers the error
# behavior; If none of them is enabled, the error behavior is not triggered.
with_food = True      # Add the 'normal' class attribute 'food'
with_drink = True     # Add the property-based class attribute 'drink'

class FoodMeta(type):
    """Metaclass that adds its class attributes to dir() of classes using it."""

    food = 'ham'      # 'normal' class attribute
    
    @property
    def drink(cls):   # property-based class attribute
        return 'beer'

    def __dir__(cls):
        ret = [name for name in cls.__dict__] # the normal list
        if with_food:
            ret += ['food']
        if with_drink:
            ret += ['drink']
        print "bug2.FoodMeta.__dir__(): return=%s" % (repr(ret),)
        return ret

class Food(object):
    """docstring for Food class"""
    __metaclass__ = FoodMeta

    def diet(self):
        return "no!"

if __name__ == '__main__':
    print "bug2: Calling help(Food):"
    help(Food)

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

-> Please review the reproduction code and the fix and let me know how to 
proceed.

Andy

----------
Added file: http://bugs.python.org/file35501/pydoc_fix2.py

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue21561>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to