.gitignore (original) (raw)

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

[ Show hidden characters]({{ revealButtonHref }})

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 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

[ Show hidden characters]({{ revealButtonHref }})

#!/usr/bin/env python3
import foo
assert not hasattr(foo, 'frob')
assert foo.Foo(1, 2).frob() == 3

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

[ Show hidden characters]({{ revealButtonHref }})

#!/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 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

[ Show hidden characters]({{ revealButtonHref }})

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]