Close #19030: improvements to inspect and Enum.

inspect.getmembers and inspect.classify_class_attrs now search the metaclass
mro for types.DynamicClassAttributes (what use to be called
enum._RouteClassAttributeToGetattr); in part this means that these two
functions no longer rely solely on dir().

Besides now returning more accurate information, these improvements also
allow a more helpful help() on Enum classes.
This commit is contained in:
Ethan Furman 2013-09-25 07:14:41 -07:00
parent 7cba5fd267
commit e03ea37a7b
4 changed files with 155 additions and 60 deletions

View file

@ -1,36 +1,10 @@
import sys
from collections import OrderedDict
from types import MappingProxyType
from types import MappingProxyType, DynamicClassAttribute
__all__ = ['Enum', 'IntEnum', 'unique']
class _RouteClassAttributeToGetattr:
"""Route attribute access on a class to __getattr__.
This is a descriptor, used to define attributes that act differently when
accessed through an instance and through a class. Instance access remains
normal, but access to an attribute through a class will be routed to the
class's __getattr__ method; this is done by raising AttributeError.
"""
def __init__(self, fget=None):
self.fget = fget
if fget.__doc__ is not None:
self.__doc__ = fget.__doc__
def __get__(self, instance, ownerclass=None):
if instance is None:
raise AttributeError()
return self.fget(instance)
def __set__(self, instance, value):
raise AttributeError("can't set attribute")
def __delete__(self, instance):
raise AttributeError("can't delete attribute")
def _is_descriptor(obj):
"""Returns True if obj is a descriptor, False otherwise."""
return (
@ -504,12 +478,12 @@ class Enum(metaclass=EnumMeta):
# members are not set directly on the enum class -- __getattr__ is
# used to look them up.
@_RouteClassAttributeToGetattr
@DynamicClassAttribute
def name(self):
"""The name of the Enum member."""
return self._name_
@_RouteClassAttributeToGetattr
@DynamicClassAttribute
def value(self):
"""The value of the Enum member."""
return self._value_