Skip to content

Instantly share code, notes, and snippets.

@dustinvtran
Last active December 27, 2017 10:24
Show Gist options
  • Save dustinvtran/e46f35842ba59d868a8985a0134d04cd to your computer and use it in GitHub Desktop.
Save dustinvtran/e46f35842ba59d868a8985a0134d04cd to your computer and use it in GitHub Desktop.
Context managers as namespaces. From "Don't Do This" by Richard Jones (https://www.youtube.com/watch?v=H2yfXnUb1S4)
import inspect
class LocalsCapture(object):
def __enter__(self):
caller_frame = inspect.currentframe().f_back
self.local_names = set(caller_frame.f_locals)
return self
def __exit__(self, exc_type, exc_val, exc_tb):
caller_frame = inspect.currentframe().f_back
for name in caller_frame.f_locals:
if name not in self.local_names:
self.capture(name, caller_frame.f_locals[name])
class capture_in(LocalsCapture):
def __init__(self, namespace):
self.namespace = namespace
def capture(self, name, value):
self.namespace[name] = value
class capture_on(LocalsCapture):
def __init__(self, object):
self.object = object
def capture(self, name, value):
self.object.__dict__[name] = value
class capture_globals(capture_in):
def __init__(self):
caller_frame = inspect.currentframe().f_back
super(capture_globals, self).__init__(caller_frame.f_globals)
d = {}
with capture_in(d):
spam = 'ham'
print(d)
# {'spam': 'ham'}
class T(object):
def __init__(self):
with capture_on(self):
spam = 'spam'
ham = 'ham'
t = T()
print(t.spam)
# 'spam'
def foo():
with capture_globals():
spam = 'ham'
print(spam)
foo()
# 'ham'
print(spam)
# 'ham'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment