On 5/6/2013 6:26 PM, Ethan Furman wrote:
On 05/05/2013 01:01 AM, Glenn Linderman wrote:

The bigger problem is that the arithmetic on enumeration items, which seems like it should be inherited from NamedInt (and seems to be, because the third value from each print is a NamedInt), doesn't pick up "x" or "y", nor does it pick up "the-x" or "the-y", but rather, it somehow picks up the str of the value.

Indeed, the bigger problem is that we ended up have an (NamedInt, Enum) wrapping a NamedInt, so we had both NEI.x._intname /and/ NEI.x.value._intname, and it was just one big mess.

But I think it is solved. Try the new code. Here's what your example should look like:

OK. I notice you changed some super()s to specific int calls; I think I understand why, having recently reread about the specific problem that super() solves regarding diamond inheritance, and with that understanding, it is clear that super() is not always the right thing to use, particularly when unrelated classes may still have particular methods with name clashes (dunder methods would commonly have the same names in unrelated classes). So my use of super likely contributed to the multiple wrappings that you allude to above, although I haven't (yet) tried to figure out the exact details of how that happened.


    class NamedInt( int ):
        def __new__( cls, *args, **kwds ):
            _args = args
            name, *args = args
            if len( args ) == 0:
                raise TypeError("name and value must be specified")
            self = int.__new__( cls, *args, **kwds )
            self._intname = name
            return self
        @property
        def __name__( self ):
            return self._intname
        def __repr__( self ):
            # repr() is updated to include the name and type info
            return "{}({!r}, {})".format(type(self).__name__,
                                         self.__name__,
                                         int.__repr__(self))
        def __str__( self ):
# str() is unchanged, even if it relies on the repr() fallback
            base = int
            base_str = base.__str__
            if base_str.__objclass__ is object:
                return base.__repr__(self)
            return base_str(self)
# for testing, we only define one operator that propagates expressions
        def __add__(self, other):
            temp = int( self ) + int( other )
if isinstance( self, NamedInt ) and isinstance( other, NamedInt ):
                return NamedInt(
                    '({0} + {1})'.format(self.__name__, other.__name__),
                    temp )
            else:
                return temp

    class NEI( NamedInt, Enum ):
        x = ('the-x', 1 )
        y = ('the-y', 2 )

I had tried this sort of constructor, thinking it should work, but couldn't tell that it helped or hindered, but it probably took eliminating the super() problem earlier, and likely your preservation of __new__ in your ref435 changes, to enable this syntax to do what I expected it might. This certainly does allow the name definitions to be better grouped, even though still somewhat redundant.

It may take a subclass of the enum_type, as Nick was suggesting, to make the NamedInt and the enumeration member actually share a single name... but this (after fleshing out NamedInt with more operators) would be a functional method of producing enumerations for the various flag parameters in the Python API (that are mostly inherited from wrapped C APIs, I suppose... at least, I haven't found a need or benefit of creating flag parameters in new Python APIs that I have created).

NEI.x + NEI.y

And this works as expected, now. Can't say I still fully understand the changes, but the test case works, and the constructors for the NamedInt inside the NEI class works, so this is pretty much what I was hoping to be able when I started down this path... but since it found some issues that you were able to fix in ref435, I guess I wasn't totally wasting your time presenting the issue. Thanks for investigating, and fixing, rather than blowing it off, even given my amateurish presentation.

And I should have called this NIE, not NEI, because it was intended to stand for NamedIntEnum... but it is just a name, so doesn't affect the functionality.


N.B. In your latest ref435.py code, line 105, should be "An Enum class _is_ final..." rather than "in".
_______________________________________________
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