Update mustclose and test_mustclose for Python 3 (this was hard!)

This commit is contained in:
Jim Paris 2019-07-25 15:48:15 -04:00
parent 55119a3e07
commit 5db034432c
2 changed files with 18 additions and 10 deletions

View File

@ -12,12 +12,17 @@ def must_close(errorfile = sys.stderr, wrap_verify = False):
already been called.""" already been called."""
def class_decorator(cls): def class_decorator(cls):
def is_method_or_function(x):
return inspect.ismethod(x) or inspect.isfunction(x)
def wrap_class_method(wrapper): def wrap_class_method(wrapper):
try: try:
orig = getattr(cls, wrapper.__name__).__func__ orig = getattr(cls, wrapper.__name__)
except Exception: except AttributeError:
orig = lambda x: None orig = lambda x: None
setattr(cls, wrapper.__name__, decorator.decorator(wrapper, orig)) if is_method_or_function(orig):
setattr(cls, wrapper.__name__,
decorator.decorator(wrapper, orig))
@wrap_class_method @wrap_class_method
def __init__(orig, self, *args, **kwargs): def __init__(orig, self, *args, **kwargs):
@ -49,16 +54,16 @@ def must_close(errorfile = sys.stderr, wrap_verify = False):
raise AssertionError("called " + str(orig) + " after close") raise AssertionError("called " + str(orig) + " after close")
return orig(self, *args, **kwargs) return orig(self, *args, **kwargs)
if wrap_verify: if wrap_verify:
for (name, method) in inspect.getmembers(cls, inspect.ismethod): for (name, method) in inspect.getmembers(cls, is_method_or_function):
# Skip class methods
if method.__self__ is not None:
continue
# Skip some methods # Skip some methods
if name in [ "__del__", "__init__" ]: if name in [ "__del__", "__init__" ]:
continue continue
# Set up wrapper # Set up wrapper
setattr(cls, name, decorator.decorator(verifier, if inspect.ismethod(method):
method.__func__)) func = method.__func__
else:
func = method
setattr(cls, name, decorator.decorator(verifier, func))
return cls return cls
return class_decorator return class_decorator

View File

@ -71,6 +71,7 @@ class TestMustClose(object):
# No error # No error
err.truncate(0) err.truncate(0)
err.seek(0)
y = Foo("bye") y = Foo("bye")
y.close() y.close()
del y del y
@ -82,6 +83,7 @@ class TestMustClose(object):
# Verify function calls when wrap_verify is True # Verify function calls when wrap_verify is True
err.truncate(0) err.truncate(0)
err.seek(0)
z = Bar() z = Bar()
eq_(inspect.getargspec(z.blah), eq_(inspect.getargspec(z.blah),
inspect.ArgSpec(args = ['self', 'arg'], inspect.ArgSpec(args = ['self', 'arg'],
@ -90,7 +92,7 @@ class TestMustClose(object):
z.close() z.close()
with assert_raises(AssertionError) as e: with assert_raises(AssertionError) as e:
z.blah("hello") z.blah("hello")
in_("called <function blah at 0x", str(e.exception)) in_("called <function Bar.blah at 0x", str(e.exception))
in_("> after close", str(e.exception)) in_("> after close", str(e.exception))
# Since the most recent assertion references 'z', # Since the most recent assertion references 'z',
# we need to raise another assertion here so that # we need to raise another assertion here so that
@ -107,6 +109,7 @@ class TestMustClose(object):
# Class with missing methods # Class with missing methods
err.truncate(0) err.truncate(0)
err.seek(0)
w = Baz() w = Baz()
w.close() w.close()
del w del w