Created
September 17, 2018 00:14
-
-
Save mr-nfamous/b780873067992b6aba39714e0df633b1 to your computer and use it in GitHub Desktop.
Python __build_class__
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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