[docs] Code, test, and doc review for PEP-0435 Enum (issue 17947)

mm at ensoft.co.uk mm at ensoft.co.uk
Tue May 14 20:12:45 CEST 2013


http://bugs.python.org/review/17947/diff/8131/Lib/enum.py
File Lib/enum.py (right):

http://bugs.python.org/review/17947/diff/8131/Lib/enum.py#newcode103
Lib/enum.py:103: enum_class = type.__new__(metacls, cls, bases,
classdict)
On 2013/05/14 01:41:45, stoneleaf wrote:
> On 2013/05/14 01:29:56, isoschiz wrote:
> > On 2013/05/14 00:09:15, stoneleaf wrote:
> > > On 2013/05/14 00:01:06, isoschiz wrote:
> > > > On 2013/05/13 20:32:37, stoneleaf wrote:
> > > > > On 2013/05/13 19:25:49, isoschiz wrote:
> > > > > > Shouldn't this technically be a use of super()? Not that I
guess
> complex
> > > > type
> > > > > > hierarchies of Metaclasses are common.
> > > > > 
> > > > > __new__ is one of the few things (the only thing?) that cannot
be shared
> > --
> > > > you
> > > > > can only create an object once.
> > > > 
> > > > And yet in this instance you are deferring to your superclass'
__new__. If
> > > > someone mixes in an extension type with a custom __new__ as well
as Enum,
> > then
> > > > this will break. Using super() will make that possible.
> > > 
> > > I don't understand.  Can you provide an example?
> > 
> > It requires writing an extension type (i.e. a type defined in C in
an
> extension
> > module), which will have its own __new__ - let's call this type
ext.Parent
> > 
> > class MyEnumMeta(Enum, ext.Parent): pass
> > 
> > will now not do what is expected. Even though in the mro ext.Parent
comes
> before
> > type, the __new__ in Enum delegates directly to type, bypassing
ext.Parent.
> > Using super() here produces the desired behaviour.
> > 
> > In either case, your statement about __new__ only being able to be
called once
> > is true. The question though is which __new__ actually gets to do
the work. We
> > shouldn't presuppose that type.__new__ is what the user needs.
> > 
> > (I must confess I've not tried this with "type", but it definitely
fails when
> > deferring to "object.__new__" instead of the extension class'
__new__)
> 
> I think you are confusing the metaclass __new__ with the class
__new__.  There
> is already support to find (right above this code, actually) the
correct __new__
> to use to create the class instances (aka members):  first it looks in
the Enum
> hierarchy for a custom __new__, then it looks in the mixed-in type
(ext.Parent
> in your case) for a __new__ to use.  If there is no custom __new__ and
no other
> type was mixed in, object.__new__ gets used.
> 
> Or maybe you made a typo, and meant `class MyEnumMeta(EnumMeta,
ext.Parent)`; I
> have no experience with extension classes so I'm not sure what happens
metaclass
> wise when one is mixed with a native python type.
> 
> Decimal now has a C version, doesn't it?  I'll a test with that and
see what
> happens.

Sorry - I did typo: I meant MyEnumMeta, as you indicated.

The Decimal implementation may indeed exhibit the problem. However, I
think it can easily be solved by just replacing type with super() in
that line. It will work identically in all of the simple cases, but
should also work should anyone want to do anything "weird".

Also note that this can also apply if the __new__ methods are doing some
extra work (either before or after the actual allocation), exactly like
this function. So even if ext.Parent wasn't an extension class, it might
want it's __new__ called so it could, say, add a new property into the
classdict or similar.

http://bugs.python.org/review/17947/


More information about the docs mailing list