Created
June 15, 2016 10:07
-
-
Save kezabelle/d24d529a6f47eb515201bfa84ee6550e to your computer and use it in GitHub Desktop.
Peeking into a class' API usage by smashing over __getattribute__
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
from collections import namedtuple, defaultdict | |
from operator import itemgetter | |
ClassUsage = namedtuple('ClassUsage', 'cls attrs') | |
AttributeUsage = namedtuple('AttributeUsage', 'name count') | |
attrname = itemgetter(0) | |
attrcount = itemgetter(1) | |
def print_handler(data): | |
print(data) | |
def peek(handler=None): | |
if handler is None: | |
handler = print_handler | |
def class_decorator(cls): | |
def printer(self, item): | |
if not item.startswith('_'): | |
if not hasattr(cls, "_attributes_used"): | |
cls._attributes_used = defaultdict(int) | |
cls._attributes_used[item] += 1 | |
out = tuple( | |
AttributeUsage(name=attrname(x), count=attrcount(x)) | |
for x in sorted(cls._attributes_used.items(), key=attrname) | |
) | |
usage = ClassUsage(cls=cls, attrs=out) | |
handler(usage) | |
return super(cls, self).__getattribute__(item) | |
setattr(cls, '__getattribute__', printer) | |
return cls | |
return class_decorator | |
@peek() # I can't figure out how to get rid of the parens :( | |
class Lol(...): | |
pass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In an ideal world, one could do:
and it'd Just Work, defaulting to the print handler.
In reality, without the parens,
handler
isLol
, notNone
so one has to provide()
to ensure immediate evaluation