On 04/25/2013 07:13 PM, Nick Coghlan wrote:
On Fri, Apr 26, 2013 at 8:29 AM, Barry Warsaw <ba...@python.org> wrote:
On Apr 25, 2013, at 03:19 PM, Guido van Rossum wrote:

Clearly this is a trick question. :-)

A bit, yes. :)

I was told when this was brought up previously (a week ago?) that it
would be simple to make it truly the same class.

It didn't sound simple to me, but I haven't seen any actual code yet.

I'm the one who said I didn't see any obvious barriers to the merger,
but I've realised there is one, and it's similar to one namedtuple
struggles with: how to handle method definitions.

[snip]

With a merged design, it becomes *really* hard to give the instances
custom behaviour, because the metaclass will somehow have to
differentiate between namespace entries that are intended to be
callables, and those which are intended to be instances of the enum.
This is not an easy problem to solve.

I'm probably going to regret asking this, but what's difficult with the 
following?

8<-----------------------------------------------------------------------------------------
class EnumDict(dict):
    """
    automatically assigns the next _int for an enum
    """

    def __init__(yo):
        super().__init__()
        yo._allow_duplicates = False
        yo._value = 1
        yo._base = 1
        yo._enums = []
        yo._type = None # object means enum, anything else means all must be of 
that type

    def __setitem__(yo, key, new_value):
        """
        main purpose is to support auto-numbering of members
        """
        existing = yo.get(key)
        if type(existing) is attrs:  # attrs is a helper class
            raise TypeError('Attempted to reuse key: %s' % key)
        if not key[:2] == key[-2:] == '__':
            old_value = None
            if isinstance(new_value, attrs):
                old_value = new_value
                if new_value.integer is None:
                    new_value = yo._value
                else:
                    new_value = new_value.integer
                    if not isinstance(new_value, int):
                        raise TypeError(
                            "an enum integer must be an instance of type <int>, not 
%s"
                            % type(new_value)
                            )
            if not callable(new_value):  # this if-else is probably not final
                if (isinstance(new_value, int) and old_value is not None
                or yo._type in (object, )):
                    yo._check_duplicate_integer(new_value, key)
                    yo._value = new_value
                    yo._inc_integer()
                    yo._enums.append(key)
                    new_value = attrs(integer=new_value)
                elif yo._type is None: # random bunch of named constants
                    yo._check_duplicate_integer(new_value, key)
                    value = yo._value
                    yo._inc_integer()
                    yo._enums.append(key)
                    new_value = attrs(value=new_value, integer=value)
                elif isinstance(new_value, yo._type): # single type of named 
constants
                    if isinstance(yo._type, int):
                        value = new_value
                    else:
                        value = yo._value
                    yo._check_duplicate_integer(value, key)
                    yo._inc_integer()
                    yo._enums.append(key)
                    new_value = attrs(value=new_value, integer=value)


            if old_value is not None:
                new_value, old_value.integer = old_value, new_value.integer
        dict.__setitem__(yo, key, new_value)

    def _inc_integer(yo):
        if yo._base == 1:
            yo._value += 1
        else:
            if yo._value == 0:
                value = 1
            else:
                value = floor(log(yo._value, 2))
                value = 2 ** value
                value <<= 1
            yo._value = value

    def _check_duplicate_integer(yo, new_value, key):
        for name, value in yo.items():
            if not isinstance(value, attrs):
                continue
            if value.integer == new_value and name != key and not 
yo._allow_duplicates:
                raise TypeError('duplicate value for %s: %d' % (key, value))

8<-------------------------------------------------------------------------------------------

Basically, if the assigned value is not `attrs` or a literal of the same type 
as the enum, the metaclass ignores it.

--
~Ethan~
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to