@@ -816,20 +816,78 @@ def wrapper(f):
816816 wraps = functools .wraps
817817
818818
819+ class _WithMetaclass (type ):
820+ """
821+ Metaclasses to be used in six.with_metaclass: instances of
822+ _WithMetaclass are metaclasses, so this is a metametaclass.
823+ """
824+ @classmethod
825+ def get (cls , meta , bases ):
826+ """
827+ Return a metaclass (an instance of _WithMetaclass) which, if an
828+ instance of it is used as base class, will create a class with
829+ metaclass "meta" and bases "bases".
830+ """
831+ # We use "meta" as base class instead of "type" to support the
832+ # following wrong usage:
833+ #
834+ # class X(six.with_metaclass(M)):
835+ # __metaclass__ = M
836+ #
837+ return cls ("metaclass" , (meta ,), dict (meta = meta , bases = bases ))
838+
839+ def instance (self ):
840+ """
841+ Return an instance of the metaclass "self".
842+ """
843+ return self .__new__ (self , "temporary_class" , (object ,), {})
844+
845+ @property
846+ def __prepare__ (self ):
847+ # We forward __prepare__ to __prepare which is the actual
848+ # implementation.
849+ #
850+ # This is needed because an ordinary __prepare__ method on the
851+ # metametaclass would not be called, since it is overridden by
852+ # type.__prepare__ (as an application of the general principle
853+ # that instance attributes override type attributes). A property
854+ # works because it bypasses attribute lookup on the instance.
855+ return self .__prepare
856+
857+ def __prepare (self , name , __bases , ** kwargs ):
858+ """
859+ Ensure that metaclass.__prepare__ is called with the correct
860+ arguments.
861+ """
862+ return self .meta .__prepare__ (name , self .bases , ** kwargs )
863+
864+ def __call__ (self , name , __bases , d ):
865+ """
866+ Create the eventual class with metaclass "self.meta" and bases
867+ "self.bases".
868+ """
869+ return self .meta (name , self .bases , d )
870+
871+
819872def with_metaclass (meta , * bases ):
820873 """Create a base class with a metaclass."""
821- # This requires a bit of explanation: the basic idea is to make a dummy
822- # metaclass for one level of class instantiation that replaces itself with
823- # the actual metaclass.
824- class metaclass (type ):
825-
826- def __new__ (cls , name , this_bases , d ):
827- return meta (name , bases , d )
828-
829- @classmethod
830- def __prepare__ (cls , name , this_bases ):
831- return meta .__prepare__ (name , bases )
832- return type .__new__ (metaclass , 'temporary_class' , (), {})
874+ # This requires a bit of explanation: with_metaclass() returns
875+ # a temporary class which will setup the correct metaclass when
876+ # this temporary class is used as base class.
877+ #
878+ # In detail: let T = with_metaclass(meta, *bases). When the user
879+ # does "class X(with_metaclass(meta, *bases))", Python will first
880+ # determine the metaclass of X from its bases. In our case, there is
881+ # a single base class T. Therefore, the metaclass will be type(T).
882+ #
883+ # Next, Python will call type(T)("X", (T,), methods) and it is this
884+ # call that we want to override. So we need to define a __call__
885+ # method in the metaclass of type(T), which needs a metametaclass,
886+ # called "_WithMetaclass".
887+ # The metaclass type(T) is returned by _WithMetaclass.get(...) and
888+ # the instance() method creates an instance of this metaclass, which
889+ # is a regular class.
890+ return _WithMetaclass .get (meta , bases ).instance ()
833891
834892
835893def add_metaclass (metaclass ):
0 commit comments