Created
August 11, 2020 15:57
-
-
Save dsc/047e8eef80fe29ee9126b76ec8cbfa2b to your computer and use it in GitHub Desktop.
A debugging tool for the lazy: pay a ridiculous performance penalty so you don't have to actually have to pay attention to what's calling what.
This file contains 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
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
""" A debugging tool for the lazy: pay a ridiculous performance penalty so | |
you don't have to actually have to pay attention to what's calling what. | |
""" | |
# import logging | |
# log = logging.getLogger('lessly') | |
import inspect, weakref | |
from contextlib import contextmanager | |
from proxy import AttributeProxy | |
class StackFrame(AttributeProxy): | |
""" Context manager for a frame on the stack. Provides convenience for | |
chaining frames and prevents leaks due to reference cycles. | |
""" | |
weakframe = None | |
frame = None | |
def __init__(self, frame=None): | |
super(StackFrame, self).__init__('frame') | |
self.weakframe = weakref.ref(frame or inspect.currentframe().f_back) | |
def cleanup(self, *args, **kw): | |
try: | |
del self.frame | |
finally: | |
self.frame = None | |
def previous(self): | |
"Moves up to the previous frame in the stack." | |
if self.frame: | |
f_back = StackFrame(self.frame.f_back) | |
if f_back: | |
try: | |
self.cleanup() | |
self.frame = f_back | |
return self | |
finally: | |
del f_back | |
else: | |
return None | |
else: | |
raise ReferenceError("Can only traverse the stack in a context block!") | |
def locals(self): | |
return self.frame.f_locals | |
def globals(self): | |
return self.frame.f_globals | |
def code(self): | |
return self.frame.f_code | |
### Context Manager Protocol ### | |
def __enter__(self): | |
self.frame = self.weakframe() | |
return self | |
__exit__ = cleanup | |
__del__ = cleanup | |
# from lessly.meta.managed import InnerClass | |
def find_calling_instance(Type): | |
frame = inspect.currentframe().f_back | |
try: | |
while frame: | |
for v in frame.f_locals.values(): | |
if isinstance(v, Type): | |
return v | |
# elif issubclass(type(v), InnerClass): | |
# log.debug('InnerClass detected while looking for %s: <%s at 0x%x>...' % (Type, type(v).__name__, id(v))) | |
# for attr in dir(v): | |
# inner = getattr(v, attr, None) | |
# if isinstance(inner, Type): | |
# log.debug('--> success! %s' % inner) | |
# return inner | |
frame = frame.f_back | |
finally: | |
del frame | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment