diff -r 61ca4732399b Lib/inspect.py --- a/Lib/inspect.py Wed Sep 04 14:30:16 2013 +0300 +++ b/Lib/inspect.py Sun Sep 08 21:55:51 2013 -0700 @@ -301,34 +301,39 @@ def classify_class_attrs(cls): 'method' any other flavor of method 'data' not a method 2. The class which defined this attribute (a class). 3. The object as obtained directly from the defining class's __dict__, not via getattr. This is especially important for data attributes: C.data is just a data object, but C.__dict__['data'] may be a data descriptor with additional info, like a __doc__ string. + + If one of the items in dir(cls) is stored in the metaclass it will now + be discovered and not have None be listed as the class in which it was + defined. """ mro = getmro(cls) + metamro = getmro(type(cls)) # for attributes stored in the metaclass names = dir(cls) result = [] for name in names: # Get the object associated with the name, and where it was defined. # Getting an obj from the __dict__ sometimes reveals more than # using getattr. Static and class methods are dramatic examples. # Furthermore, some objects may raise an Exception when fetched with # getattr(). This is the case with some descriptors (bug #1785). # Thus, we only use getattr() as a last resort. homecls = None - for base in (cls,) + mro: + for base in (cls,) + mro + metamro: if name in base.__dict__: obj = base.__dict__[name] homecls = base break else: obj = getattr(cls, name) homecls = getattr(obj, "__objclass__", homecls) # Classify the object. if isinstance(obj, staticmethod):