mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 03:44:55 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			178 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			178 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""Enumeration metaclass."""
 | 
						|
 | 
						|
class EnumMetaclass(type):
 | 
						|
    """Metaclass for enumeration.
 | 
						|
 | 
						|
    To define your own enumeration, do something like
 | 
						|
 | 
						|
    class Color(Enum):
 | 
						|
        red = 1
 | 
						|
        green = 2
 | 
						|
        blue = 3
 | 
						|
 | 
						|
    Now, Color.red, Color.green and Color.blue behave totally
 | 
						|
    different: they are enumerated values, not integers.
 | 
						|
 | 
						|
    Enumerations cannot be instantiated; however they can be
 | 
						|
    subclassed.
 | 
						|
    """
 | 
						|
 | 
						|
    def __init__(cls, name, bases, dict):
 | 
						|
        super(EnumMetaclass, cls).__init__(name, bases, dict)
 | 
						|
        cls._members = []
 | 
						|
        for attr in dict.keys():
 | 
						|
            if not (attr.startswith('__') and attr.endswith('__')):
 | 
						|
                enumval = EnumInstance(name, attr, dict[attr])
 | 
						|
                setattr(cls, attr, enumval)
 | 
						|
                cls._members.append(attr)
 | 
						|
 | 
						|
    def __getattr__(cls, name):
 | 
						|
        if name == "__members__":
 | 
						|
            return cls._members
 | 
						|
        raise AttributeError, name
 | 
						|
 | 
						|
    def __repr__(cls):
 | 
						|
        s1 = s2 = ""
 | 
						|
        enumbases = [base.__name__ for base in cls.__bases__
 | 
						|
                     if isinstance(base, EnumMetaclass) and not base is Enum]
 | 
						|
        if enumbases:
 | 
						|
            s1 = "(%s)" % ", ".join(enumbases)
 | 
						|
        enumvalues = ["%s: %d" % (val, getattr(cls, val))
 | 
						|
                      for val in cls._members]
 | 
						|
        if enumvalues:
 | 
						|
            s2 = ": {%s}" % ", ".join(enumvalues)
 | 
						|
        return "%s%s%s" % (cls.__name__, s1, s2)
 | 
						|
 | 
						|
class FullEnumMetaclass(EnumMetaclass):
 | 
						|
    """Metaclass for full enumerations.
 | 
						|
 | 
						|
    A full enumeration displays all the values defined in base classes.
 | 
						|
    """
 | 
						|
 | 
						|
    def __init__(cls, name, bases, dict):
 | 
						|
        super(FullEnumMetaclass, cls).__init__(name, bases, dict)
 | 
						|
        for obj in cls.__mro__:
 | 
						|
            if isinstance(obj, EnumMetaclass):
 | 
						|
                for attr in obj._members:
 | 
						|
                    # XXX inefficient
 | 
						|
                    if not attr in cls._members:
 | 
						|
                        cls._members.append(attr)
 | 
						|
 | 
						|
class EnumInstance(int):
 | 
						|
    """Class to represent an enumeration value.
 | 
						|
 | 
						|
    EnumInstance('Color', 'red', 12) prints as 'Color.red' and behaves
 | 
						|
    like the integer 12 when compared, but doesn't support arithmetic.
 | 
						|
 | 
						|
    XXX Should it record the actual enumeration rather than just its
 | 
						|
    name?
 | 
						|
    """
 | 
						|
 | 
						|
    def __new__(cls, classname, enumname, value):
 | 
						|
        return int.__new__(cls, value)
 | 
						|
 | 
						|
    def __init__(self, classname, enumname, value):
 | 
						|
        self.__classname = classname
 | 
						|
        self.__enumname = enumname
 | 
						|
 | 
						|
    def __repr__(self):
 | 
						|
        return "EnumInstance(%s, %s, %d)" % (self.__classname, self.__enumname,
 | 
						|
                                             self)
 | 
						|
 | 
						|
    def __str__(self):
 | 
						|
        return "%s.%s" % (self.__classname, self.__enumname)
 | 
						|
 | 
						|
class Enum:
 | 
						|
    __metaclass__ = EnumMetaclass
 | 
						|
 | 
						|
class FullEnum:
 | 
						|
    __metaclass__ = FullEnumMetaclass
 | 
						|
 | 
						|
def _test():
 | 
						|
 | 
						|
    class Color(Enum):
 | 
						|
        red = 1
 | 
						|
        green = 2
 | 
						|
        blue = 3
 | 
						|
 | 
						|
    print Color.red
 | 
						|
 | 
						|
    print repr(Color.red)
 | 
						|
    print Color.red == Color.red
 | 
						|
    print Color.red == Color.blue
 | 
						|
    print Color.red == 1
 | 
						|
    print Color.red == 2
 | 
						|
 | 
						|
    class ExtendedColor(Color):
 | 
						|
        white = 0
 | 
						|
        orange = 4
 | 
						|
        yellow = 5
 | 
						|
        purple = 6
 | 
						|
        black = 7
 | 
						|
 | 
						|
    print ExtendedColor.orange
 | 
						|
    print ExtendedColor.red
 | 
						|
 | 
						|
    print Color.red == ExtendedColor.red
 | 
						|
 | 
						|
    class OtherColor(Enum):
 | 
						|
        white = 4
 | 
						|
        blue = 5
 | 
						|
 | 
						|
    class MergedColor(Color, OtherColor):
 | 
						|
        pass
 | 
						|
 | 
						|
    print MergedColor.red
 | 
						|
    print MergedColor.white
 | 
						|
 | 
						|
    print Color
 | 
						|
    print ExtendedColor
 | 
						|
    print OtherColor
 | 
						|
    print MergedColor
 | 
						|
 | 
						|
def _test2():
 | 
						|
 | 
						|
    class Color(FullEnum):
 | 
						|
        red = 1
 | 
						|
        green = 2
 | 
						|
        blue = 3
 | 
						|
 | 
						|
    print Color.red
 | 
						|
 | 
						|
    print repr(Color.red)
 | 
						|
    print Color.red == Color.red
 | 
						|
    print Color.red == Color.blue
 | 
						|
    print Color.red == 1
 | 
						|
    print Color.red == 2
 | 
						|
 | 
						|
    class ExtendedColor(Color):
 | 
						|
        white = 0
 | 
						|
        orange = 4
 | 
						|
        yellow = 5
 | 
						|
        purple = 6
 | 
						|
        black = 7
 | 
						|
 | 
						|
    print ExtendedColor.orange
 | 
						|
    print ExtendedColor.red
 | 
						|
 | 
						|
    print Color.red == ExtendedColor.red
 | 
						|
 | 
						|
    class OtherColor(FullEnum):
 | 
						|
        white = 4
 | 
						|
        blue = 5
 | 
						|
 | 
						|
    class MergedColor(Color, OtherColor):
 | 
						|
        pass
 | 
						|
 | 
						|
    print MergedColor.red
 | 
						|
    print MergedColor.white
 | 
						|
 | 
						|
    print Color
 | 
						|
    print ExtendedColor
 | 
						|
    print OtherColor
 | 
						|
    print MergedColor
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    _test()
 | 
						|
    _test2()
 | 
						|
 |