Wow - this ended up being more difficult that I'd anticipated. Ensuring that decorators work in Michael Foord-inspired enums, etc mandated a fairly big redesign. As it was you couldn't do something like:

class A():
    a = 1

class B(Enum):
    B = A.a

because when the name 'A' was resolved in the definition of class B, it was returning an int (the next enum value).

The end result may well still have some holes, but it's looking pretty good to me.

Enums are constructed like:

class Color(Enum):
    RED, GREEN, BLUE
    CYAN = 10
    MAGENTA
    YELLOW
    BLACK

where the assigned enum starts a new count i.e. the above is 0, 1, 2, 10, 11, 12, 13. Arbitrary attributes may be assigned and not contribute to the enumeration so long as the object being assigned does not implement __index__ (if it does, it creates a discontiguous enumeration).

#!/usr/bin/env python3

import builtins
import collections
import operator

class EnumValue(int):
    def __new__(cls, key, value):
        e = super().__new__(cls, value)
        super().__setattr__(e, 'key', key)
        super().__setattr__(e, 'owner', None)
        return e

    def __setattr__(self, key, value):
        raise TypeError("Cannot set attribute of type %r" % (type(self),))

    def __str__(self):
        return "%s.%s" % (self.owner.__name__, self.key)

    def __repr__(self):
        if self.owner is not None:
            return "<%s '%s.%s': %d>" % (self.__qualname__, self.owner.__qualname__, self.key, int(self))

        return "<%s '%s': %d>" % (self.__qualname__, self.key, int(self))

class EnumProxy(object):
    def __init__(self, key, value=None):
        self.key = key
        self.values = [value]
        self.used = False

    def __repr__(self):
        return "<%s '%s': %s>" % (self.__qualname__, self.key, self.values)

    def _get(self, used=None):
        if used:
            self.used = True

        try:
            return locals()[self.key]
        except KeyError:
            try:
                return globals()[self.key]
            except KeyError:
                try:
                    return getattr(builtins, self.key)
                except KeyError:
                    raise NameError(self.key, self.values)

    def __call__(self, *p, **kw):
        return self._get(True)(*p, **kw)

    def __getattr__(self, name):
        return getattr(self._get(True), name)

class EnumValues(collections.OrderedDict):
    def __init__(self):
        super().__init__()
        self.sealed = False

    def __getitem__(self, key):
        try:
            obj = super().__getitem__(key)

            if not self.sealed and isinstance(obj, EnumProxy):
                obj.values.append(None)

            return obj

        except KeyError:
            # Don't do anything with __dunder__ attributes
            if key[:2] == '__' and key[-2:] == '__':
                raise

            proxy = EnumProxy(key, None)
            super().__setitem__(key, proxy)
            return proxy

    def __setitem__(self, key, value):
        if key[:2] == '__' and key[-2:] == '__':
            return super().__setitem__(key, value)

        try:
            if isinstance(value, EnumProxy):
                value = value._get(True)

            elif not isinstance(value, EnumValue):
                value = operator.index(value)

        except TypeError:
            return super().__setitem__(key, value)

        try:
            o = super().__getitem__(key)

            if isinstance(o, EnumProxy):
                o.values.append(value)

        except KeyError:
            if isinstance(value, EnumProxy):
                int.__setattr__(value, 'key', key)
            else:
                value = EnumProxy(key, value)

            super().__setitem__(value.key, value)

class EnumMeta(type):

    @classmethod
    def __prepare__(metacls, name, bases):
        return EnumValues()

    def __new__(cls, name, bases, classdict):
        classdict.sealed = True

        del_list = []

        for v in classdict.values():
            if isinstance(v, EnumProxy) and v.used:
                del_list.append(v)

        for v in del_list:
            del classdict[v.key]

        result = type.__new__(cls, name, bases, dict(classdict))
        value = 0
        keys = {}
        values = {}

        for v in classdict.values():
            if isinstance(v, EnumProxy) and not v.used:
                if len(v.values) > 1:
                    raise AttributeError("Duplicate enum key '%s.%s'" % (result.__qualname__, v.key,))

                if v.values[0] is not None:
                    value = v.values[0]

                if isinstance(value, EnumValue):

                    if (value.key is not None) and (value.key != v.key):
                        raise AttributeError("Assigned enum value to non-matching key '%s': %r" % (v.key, value))

                    if value.owner is not None:
                        raise AttributeError("Assigned owned enum value to key '%s': %r" % (v.key, value))

                    int.__setattr__(value, 'key', v.key)
                    v = value

                else:
                    v = EnumValue(v.key, value)

                setattr(result, v.key, v)
                value += 1

            if isinstance(v, EnumValue):
                int.__setattr__(v, 'owner', result)

                if v in values:
                    raise AttributeError("Duplicate enum value %d for keys: '%s' and '%s'" % (int(v), values[v].key, v.key))

                keys[v.key] = v
                values[v] = v

        enum = sorted(values)

        result._key_to_enum = collections.OrderedDict()
        result._value_to_enum = values

        for e in enum:
            result._key_to_enum[e.key] = e

        return result

    def __getitem__(self, key):
        try:
            key = operator.index(key)
        except TypeError:
            return self._key_to_enum[key]
        else:
            return self._value_to_enum[key]

    def _items(self):
        return self._key_to_enum.items()

    def _keys(self):
        return self._key_to_enum.keys()

    def _values(self):
        return self._key_to_enum.values()

    def items(self):
        return self._items()

    def keys(self):
        return self._keys()

    def values(self):
        return self._values()

    def __iter__(self):
        return iter(self.values())

    def __repr__(self):
        r = super().__repr__()
        r = ['<enum', r[6:-1], ' ']
        r.append(str(self))
        r.append('>')
        return ''.join(r)

    def __str__(self):
        s = ['{']

        for k, v in self.items():
            if s[-1][-1:] != '{':
                s.append(', ')

            s.extend([k, ':', str(int(v))])

        s.append('}')
        return ''.join(s)

class Enum(metaclass=EnumMeta):
    def __getitem__(self, key):
        cls = type(self)
        return type(cls).__getitem__(cls, key)

    @classmethod
    def items(cls):
        return cls._items()

    @classmethod
    def keys(cls):
        return cls._keys()

    @classmethod
    def values(cls):
        return cls._values()

    def __iter__(self):
        return iter(self.values())

    def __repr__(self):
        r = super().__repr__()
        r = r.replace('object at 0x', 'enum at 0x')
        r = [r[:-1], ' ']
        r.append(str(self))
        r.append('>')
        return ''.join(r)

    def __str__(self):
        return str(type(self))

if __name__ == '__main__':

    class Color(Enum):
        RED, GREEN, BLUE
        ORANGE = "orange"
        CYAN = 10
        MAGENTA
        YELLOW
        BLACK

    import unittest

    class TestEnum(unittest.TestCase):

        EXPECTED_KEY_ORDER = ('RED', 'GREEN', 'BLUE', 'CYAN', 'MAGENTA', 'YELLOW', 'BLACK')
        EXPECTED_INT_VALUE_ORDER = (0, 1, 2, 10, 11, 12, 13)
        EXPECTED_ENUM_VALUE_ORDER = (Color.RED, Color.GREEN, Color.BLUE, Color.CYAN, Color.MAGENTA, Color.YELLOW, Color.BLACK)
        EXPECTED_ITEMS_ORDER = tuple(zip(EXPECTED_KEY_ORDER, EXPECTED_ENUM_VALUE_ORDER))

        def test_type(self):
            self.assertIsInstance(Color.RED, int)

        def test_class_enum_values(self):
            self.assertEqual(0, Color.RED)
            self.assertEqual(1, Color.GREEN)
            self.assertEqual(2, Color.BLUE)
            self.assertEqual(10, Color.CYAN)
            self.assertEqual(11, Color.MAGENTA)
            self.assertEqual(12, Color.YELLOW)
            self.assertEqual(13, Color.BLACK)
            self.assertEqual("orange", Color.ORANGE)

        def test_instance_enum_values(self):
            e = Color()
            self.assertIs(Color.RED, e.RED)
            self.assertIs(Color.GREEN, e.GREEN)
            self.assertIs(Color.BLUE, e.BLUE)
            self.assertIs(Color.CYAN, e.CYAN)
            self.assertIs(Color.MAGENTA, e.MAGENTA)
            self.assertIs(Color.YELLOW, e.YELLOW)
            self.assertIs(Color.BLACK, e.BLACK)
            self.assertIs(Color.ORANGE, e.ORANGE)

        def test_class_indexing(self):
            self.assertIs(Color.CYAN, Color['CYAN'])
            self.assertIs(Color.CYAN, Color[10])

        def test_instance_indexing(self):
            e = Color()
            self.assertIs(Color.CYAN, e['CYAN'])
            self.assertIs(Color.CYAN, e[10])

        def test_class_keys(self):
            self.assertEqual(self.EXPECTED_KEY_ORDER, tuple(Color.keys()))

        def test_instance_keys(self):
            self.assertEqual(tuple(Color.keys()), tuple(Color().keys()))

        def test_class_values(self):
            self.assertEqual(self.EXPECTED_INT_VALUE_ORDER, tuple(Color.values()))
            self.assertEqual(self.EXPECTED_ENUM_VALUE_ORDER, tuple(Color.values()))

        def test_instance_values(self):
            self.assertEqual(tuple(Color.values()), tuple(Color().values()))

        def test_class_items(self):
            self.assertEqual(self.EXPECTED_ITEMS_ORDER, tuple(Color.items()))

        def test_instance_items(self):
            self.assertEqual(tuple(Color.items()), tuple(Color().items()))

        def test_owner(self):
            for e in Color:
                self.assertIs(e.owner, Color)

        def test_class_str(self):
            s = str(Color)

            for e in Color:
                self.assertIn('%s:%d' % (e.key, int(e)), s)

        def test_instance_str(self):
            self.assertEqual(str(Color), str(Color()))

        def test_class_repr(self):
            r = repr(Color)
            self.assertIn(Color.__qualname__, r)
            self.assertIn(str(Color), r)

        def test_instance_repr(self):
            e = Color()
            r = repr(e)
            self.assertIn(Color.__qualname__, r)
            self.assertIn('at 0x', r)
            self.assertIn(str(Color()), r)

        def _create_duplicate_key(self):
            class DuplicateKey(Enum):
                KEY,
                KEY

        def test_duplicate_key(self):
            self.assertRaises(AttributeError, self._create_duplicate_key)

        def _create_duplicate_value(self):
            class DuplicateValue(Enum):
                KEY1,
                KEY2 = 0

        def test_duplicate_value(self):
            self.assertRaises(AttributeError, self._create_duplicate_value)

        def _assign_wrong_key(self):
            class WrongKey(Enum):
                KEY1 = EnumValue('KEY2', 0)

        def test_wrong_key(self):
            self.assertRaises(AttributeError, self._assign_wrong_key)

        def test_unnamed_key1(self):
            class UnnamedKey(Enum):
                KEY1 = EnumValue(None, 5)

            self.assertEqual(UnnamedKey.KEY1, 5)
            self.assertIs(UnnamedKey, UnnamedKey.KEY1.owner)

        def test_unnamed_key1(self):
            unnamed = EnumValue(None, 5)

            class UnnamedKey(Enum):
                KEY1 = unnamed

            self.assertEqual(UnnamedKey.KEY1, 5)
            self.assertIs(UnnamedKey.KEY1, unnamed)
            self.assertIs(UnnamedKey, UnnamedKey.KEY1.owner)

        def _assign_wrong_owner(self):
            class WrongOwner(Enum):
                KEY1 = Color.RED

        def test_wrong_owner(self):
            self.assertRaises(AttributeError, self._assign_wrong_owner)

    unittest.main()

Tim Delaney