mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 19:34:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			169 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""Enumeration metaclass.
 | 
						|
 | 
						|
XXX This is very much a work in progress.
 | 
						|
 | 
						|
"""
 | 
						|
 | 
						|
import string
 | 
						|
 | 
						|
class EnumMetaClass:
 | 
						|
    """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__(self, name, bases, dict):
 | 
						|
        """Constructor -- create an enumeration.
 | 
						|
 | 
						|
        Called at the end of the class statement.  The arguments are
 | 
						|
        the name of the new class, a tuple containing the base
 | 
						|
        classes, and a dictionary containing everything that was
 | 
						|
        entered in the class' namespace during execution of the class
 | 
						|
        statement.  In the above example, it would be {'red': 1,
 | 
						|
        'green': 2, 'blue': 3}.
 | 
						|
 | 
						|
        """
 | 
						|
        for base in bases:
 | 
						|
            if base.__class__ is not EnumMetaClass:
 | 
						|
                raise TypeError, "Enumeration base class must be enumeration"
 | 
						|
        bases = filter(lambda x: x is not Enum, bases)
 | 
						|
        self.__name__ = name
 | 
						|
        self.__bases__ = bases
 | 
						|
        self.__dict = {}
 | 
						|
        for key, value in dict.items():
 | 
						|
            self.__dict[key] = EnumInstance(name, key, value)
 | 
						|
 | 
						|
    def __getattr__(self, name):
 | 
						|
        """Return an enumeration value.
 | 
						|
 | 
						|
        For example, Color.red returns the value corresponding to red.
 | 
						|
 | 
						|
        XXX Perhaps the values should be created in the constructor?
 | 
						|
 | 
						|
        This looks in the class dictionary and if it is not found
 | 
						|
        there asks the base classes.
 | 
						|
 | 
						|
        The special attribute __members__ returns the list of names
 | 
						|
        defined in this class (it does not merge in the names defined
 | 
						|
        in base classes).
 | 
						|
 | 
						|
        """
 | 
						|
        if name == '__members__':
 | 
						|
            return self.__dict.keys()
 | 
						|
 | 
						|
        try:
 | 
						|
            return self.__dict[name]
 | 
						|
        except KeyError:
 | 
						|
            for base in self.__bases__:
 | 
						|
                try:
 | 
						|
                    return getattr(base, name)
 | 
						|
                except AttributeError:
 | 
						|
                    continue
 | 
						|
 | 
						|
        raise AttributeError, name
 | 
						|
 | 
						|
    def __repr__(self):
 | 
						|
        s = self.__name__
 | 
						|
        if self.__bases__:
 | 
						|
            s = s + '(' + string.join(map(lambda x: x.__name__,
 | 
						|
                                          self.__bases__), ", ") + ')'
 | 
						|
        if self.__dict:
 | 
						|
            list = []
 | 
						|
            for key, value in self.__dict.items():
 | 
						|
                list.append("%s: %s" % (key, int(value)))
 | 
						|
            s = "%s: {%s}" % (s, string.join(list, ", "))
 | 
						|
        return s
 | 
						|
 | 
						|
 | 
						|
class EnumInstance:
 | 
						|
    """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 __init__(self, classname, enumname, value):
 | 
						|
        self.__classname = classname
 | 
						|
        self.__enumname = enumname
 | 
						|
        self.__value = value
 | 
						|
 | 
						|
    def __int__(self):
 | 
						|
        return self.__value
 | 
						|
 | 
						|
    def __repr__(self):
 | 
						|
        return "EnumInstance(%s, %s, %s)" % (`self.__classname`,
 | 
						|
                                             `self.__enumname`,
 | 
						|
                                             `self.__value`)
 | 
						|
 | 
						|
    def __str__(self):
 | 
						|
        return "%s.%s" % (self.__classname, self.__enumname)
 | 
						|
 | 
						|
    def __cmp__(self, other):
 | 
						|
        return cmp(self.__value, int(other))
 | 
						|
 | 
						|
 | 
						|
# Create the base class for enumerations.
 | 
						|
# It is an empty enumeration.
 | 
						|
Enum = EnumMetaClass("Enum", (), {})
 | 
						|
 | 
						|
 | 
						|
def _test():
 | 
						|
 | 
						|
    class Color(Enum):
 | 
						|
        red = 1
 | 
						|
        green = 2
 | 
						|
        blue = 3
 | 
						|
 | 
						|
    print Color.red
 | 
						|
    print dir(Color)
 | 
						|
 | 
						|
    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
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    _test()
 |