Last active
August 26, 2015 03:59
-
-
Save o11c/ce0c2ff74b87ea71ad46 to your computer and use it in GitHub Desktop.
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
*.pyc |
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
import util | |
from collections import namedtuple | |
Foo = namedtuple('Foo', 'x y') | |
@util.member(Foo) | |
def frob(self): | |
return self.x + self.y | |
util.cleanup() |
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 python3 | |
import foo | |
assert not hasattr(foo, 'frob') | |
assert foo.Foo(1, 2).frob() == 3 |
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 python3 | |
import traceback | |
import util | |
class Foo: | |
def oops(self): | |
raise ValueError | |
class Bar: | |
pass | |
@util.member(Bar) | |
def oops(self): | |
raise ValueError | |
util.cleanup() | |
def tb_has_qualname(cls): | |
try: | |
cls().oops() | |
except ValueError as e: | |
fun_name = traceback.extract_tb(e.__traceback__)[-1][2] | |
unqual = fun_name == 'oops' | |
assert unqual or fun_name.endswith('.oops') | |
return not unqual | |
assert False, 'unreachable' | |
def test(): | |
foo_q = tb_has_qualname(Foo) | |
print('Foo qualname?', foo_q) | |
bar_q = tb_has_qualname(Bar) | |
print('Bar qualname?', bar_q) | |
assert foo_q == bar_q | |
if __name__ == '__main__': | |
test() |
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
import sys | |
# It is not possible to delete something from the calling globals before | |
# it exists. Remember, the decorator (necessarily) operates on the | |
# function *before* its own result is assigned to the namespace. | |
DELETEME = object() | |
def member(cls): | |
def decorator(fun): | |
name = fun.__name__ | |
fun.__qualname__ = '%s.%s' % (cls.__qualname__, name) | |
setattr(cls, name, fun) | |
return DELETEME | |
return decorator | |
def filtered_dir(obj): | |
return [x for x in dir(obj) if x != '__%s__' % x.strip('_')] | |
def print_info(name, obj): | |
print('%s: ' % name, obj) | |
print('type(%s): ' % name, type(obj)) | |
print('filtered_dir(%s):' % name, filtered_dir(obj)) | |
if hasattr(obj, '__dict__'): | |
print('vars(%s): ' % name, vars(obj)) | |
print() | |
def cleanup(exclude={'DELETEME'}): | |
# Basically the same logic as collections.namedtuple uses | |
# to set the returned class's __module__ | |
try: | |
mod_globals = sys._getframe(1).f_globals | |
except (AttributeError, ValueError): | |
print('Unable to get caller\'s globals for cleanup') | |
return | |
keys_to_delete = {k for k, v in mod_globals.items() if v is DELETEME} | |
for k in keys_to_delete - exclude: | |
del mod_globals[k] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment