Skip to content

Instantly share code, notes, and snippets.

@mr-nfamous
Created September 17, 2018 00:14
Show Gist options
  • Save mr-nfamous/b780873067992b6aba39714e0df633b1 to your computer and use it in GitHub Desktop.
Save mr-nfamous/b780873067992b6aba39714e0df633b1 to your computer and use it in GitHub Desktop.
Python __build_class__
import dis
from sys import _getframe as GF
def vprint(f, *args, **kws):
kws = ', '.join(f'{k}={v!r}' for k,v in kws.items())
args= ', '.join(a for b in (map(repr, args), (kws,)) for a in b if a)
print(f'{f}({args})')
class BuildClass:
import builtins as __module
__builder = __module.__build_class__
def __init__(self, verbose=False, nested=False):
self.verbose = verbose
if not nested:
self.finished = 0
self.nested = nested
def __enter__(self, m=__module, f=__builder):
m.__build_class__ = self
self.call = f
return self
def __call__(self, func, name, *bases, **kws):
if not self.nested and self.finished:
raise TypeError(""
"tried to build nested class but nesting was "
"prohibited")
if self.verbose:
print('__build_class__ "function" argument:')
dis.show_code(func)
print('-'*80)
print('__build_class__ "function" disassembled bytecode:\n')
dis.dis(func)
kws['verbose'] = True
metaclass = kws.pop('metaclass', type)
namespace = metaclass.__prepare__(name, bases, **kws)
classcell = eval(func.__code__, GF(1).f_globals, namespace)
new_class = type.__call__(metaclass, name, bases, namespace, **kws)
self.finished = True
return new_class
def __exit__(self, a,b,c,m=__module, f=__builder):
m.__build_class__ = f
if __name__ == '__main__':
class Dict(dict):
def __init__(self, verbose=False):
self.verbose = verbose
def __setitem__(self, k, v):
if self.verbose:
vprint('namespace.__setitem__', k, v)
dict.__setitem__(self,k,v)
class Type(type):
@classmethod
def __prepare__(cls, name, bases, **kws):
if kws.get('verbose'):
vprint('type.__prepare__', name, bases, **kws)
return Dict(kws.get('verbose', False))
@staticmethod # explicit
def __new__(cls, name, bases, ns, **kws):
if kws.pop('verbose', 0):
vprint('type.__new__', name, bases, ns, **kws)
return type.__new__(cls, name, bases, ns)
with BuildClass(1,0) as c:
class List(list, metaclass=Type):
def append(self,x):
super().append(x)
#class x: pass
from builtins import __build_class__ as q
assert q is c
self = List()
self.append(9)
print(self)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment