from types import ClassType, FunctionType |
from types import FunctionType |
import sys, os |
import sys, os |
__all__ = [ |
__all__ = [ |
'decorate_class', 'metaclass_is_decorator', 'metaclass_for_bases', |
'decorate_class', 'metaclass_is_decorator', 'metaclass_for_bases', |
tracers_for = lambda f: [f.f_trace] |
tracers_for = lambda f: [f.f_trace] |
|
|
|
|
|
def with_metaclass(meta, *bases): |
|
"""Python 2/3-compatible metaclass spelling; internal use only""" |
|
class tmp(type): |
|
def __new__(cls, name, _bases, cdict): |
|
return meta(name, bases, cdict) |
|
return type.__new__(tmp, 'tmp', (), {}) |
|
|
|
|
|
|
|
|
|
|
|
try: |
|
old_build_class = __build_class__ |
|
except NameError: |
|
# Python 2 |
|
from types import ClassType |
|
NEXT, GLOBALS, DEFAULTS = 'next', 'func_globals', 'func_defaults' |
|
else: |
|
# Python 3 |
|
ClassType = type |
|
NEXT, GLOBALS, DEFAULTS = '__next__', '__globals__', '__defaults__' |
|
|
|
def apply_decorators(cls, advice): |
|
if metaclass_is_decorator(advice): |
|
cls = advice.callback( |
|
apply_decorators(cls, advice.previousMetaclass) |
|
) |
|
return cls |
|
|
|
def py3_build_class(func, name, *bases, **kw): |
|
cls = old_build_class(func, name, *bases, **kw) |
|
advice = cls.__dict__.get('__metaclass__', None) |
|
decorated = apply_decorators(cls, advice) |
|
if '__metaclass__' in cls.__dict__: |
|
try: |
|
del cls.__metaclass__ |
|
except TypeError: |
|
pass |
|
return decorated |
|
|
|
getattr(__builtins__,'__dict__',__builtins__)[ |
|
'__build_class__' |
|
] = py3_build_class |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
filename = "<%s wrapping %s at 0x%08X>" % (qname(wrapper), qname(func), id(func)) |
filename = "<%s wrapping %s at 0x%08X>" % (qname(wrapper), qname(func), id(func)) |
d ={} |
d ={} |
exec compile(body, filename, "exec") in func.func_globals, d |
exec(compile(body, filename, "exec"), getattr(func, GLOBALS), d) |
|
|
f = d[wrapname](func, *args, **kw) |
f = d[wrapname](func, *args, **kw) |
cache_source(filename, body, f) |
cache_source(filename, body, f) |
|
|
f.func_defaults = func.func_defaults |
setattr(f, DEFAULTS, getattr(func, DEFAULTS)) |
f.__doc__ = func.__doc__ |
f.__doc__ = func.__doc__ |
f.__dict__ = func.__dict__ |
f.__dict__ = func.__dict__ |
return f |
return f |
defaultMetaclass = caller_globals.get('__metaclass__', ClassType) |
defaultMetaclass = caller_globals.get('__metaclass__', ClassType) |
|
|
|
|
def advise(name,bases,cdict): |
def advise(name,bases,cdict,**kw): |
|
|
if '__metaclass__' in cdict: |
if '__metaclass__' in cdict: |
del cdict['__metaclass__'] |
del cdict['__metaclass__'] |
else: |
else: |
meta = metaclass_for_bases(bases, previousMetaclass) |
meta = metaclass_for_bases(bases, previousMetaclass) |
|
|
newClass = meta(name,bases,cdict) |
newClass = meta(name,bases,cdict,**kw) |
|
|
# this lets the decorator replace the class completely, if it wants to |
# this lets the decorator replace the class completely, if it wants to |
return decorator(newClass) |
return decorator(newClass) |
def super_next(cls, attr): |
def super_next(cls, attr): |
for c in cls.__mro__: |
for c in cls.__mro__: |
if attr in c.__dict__: |
if attr in c.__dict__: |
yield getattr(c, attr).im_func |
meth = getattr(c, attr) |
|
yield getattr(meth, 'im_func', meth) |
|
|
# Python 2.6 and above mix ABCMeta into various random places :-( |
# Python 2.6 and above mix ABCMeta into various random places :-( |
try: |
try: |
|
|
def __new__(meta, name, bases, cdict): |
def __new__(meta, name, bases, cdict): |
cls = super(classy_class, meta).__new__(meta, name, bases, cdict) |
cls = super(classy_class, meta).__new__(meta, name, bases, cdict) |
supr = super_next(cls, '__class_new__').next |
supr = getattr(super_next(cls, '__class_new__'), NEXT) |
return supr()(meta, name, bases, cdict, supr) |
return supr()(meta, name, bases, cdict, supr) |
|
|
def __init__(cls, name, bases, cdict): |
def __init__(cls, name, bases, cdict): |
supr = super_next(cls, '__class_init__').next |
supr = getattr(super_next(cls, '__class_init__'), NEXT) |
return supr()(cls, name, bases, cdict, supr) |
return supr()(cls, name, bases, cdict, supr) |
|
|
def __call__(cls, *args, **kw): |
def __call__(cls, *args, **kw): |
return cls.__class_call__.im_func(cls, *args, **kw) |
return cls.__class_call__(*args, **kw) |
|
|
if base is not type: |
if base is not type: |
# Our instances do not support ABC-ness |
# Our instances do not support ABC-ness |
|
|
|
|
|
|
|
class classy(with_metaclass(classy_class)): |
class classy(object): |
|
"""Base class for classes that want to be their own metaclass""" |
"""Base class for classes that want to be their own metaclass""" |
__metaclass__ = classy_class |
|
__slots__ = () |
__slots__ = () |
|
|
def __class_new__(meta, name, bases, cdict, supr): |
def __class_new__(meta, name, bases, cdict, supr): |
|
|
def __class_call__(cls, *args, **kw): |
def __class_call__(cls, *args, **kw): |
return type.__call__(cls, *args, **kw) |
return type.__call__(cls, *args, **kw) |
__class_call__ = classmethod(__class_call__) |
|
|
|
|
__class_call__ = classmethod(__class_call__) |
|
|
|
|
|
|