def test_empty(self): """Test the trivial case - combining zero context managers.""" with multi_manager()() as result: self.assertEqual(result, ()) with multi_manager()('foo', 'bar') as result: self.assertEqual(result, ())
def before_after(self, what): """ Return a pair of functions to execute before and after the event. """ before_hooks = self.hook_list(what, "before") around_hooks = self.hook_list(what, "around") after_hooks = self.hook_list(what, "after") multi_hook = multi_manager(*around_hooks) # Save in a closure for both functions around_hook = [None] def before_func(*args, **kwargs): """All hooks to be called before the event.""" for before_hook in before_hooks: before_hook(*args, **kwargs) around_hook[0] = multi_hook(*args, **kwargs) around_hook[0].__enter__() def after_func(*args, **kwargs): """All hooks to be called after the event.""" around_hook[0].__exit__(None, None, None) around_hook[0] = None for after_hook in after_hooks: after_hook(*args, **kwargs) return before_func, after_func
def wrap(self, what, function, *hook_args, **hook_kwargs): """ Return a function that executes all the callbacks in proper relations to the given test part. """ before_hooks = self.hook_list(what, "before") around_hooks = self.hook_list(what, "around") after_hooks = self.hook_list(what, "after") multi_hook = multi_manager(*around_hooks) @wraps(function) def wrapped(*args, **kwargs): """Run all the hooks in proper relations to the event.""" for before_hook in before_hooks: before_hook(*hook_args, **hook_kwargs) try: with multi_hook(*hook_args, **hook_kwargs): return function(*args, **kwargs) finally: # 'after' hooks still run after an exception for after_hook in reversed(after_hooks): after_hook(*hook_args, **hook_kwargs) return wrapped
def before_after(self, what): """ Return a pair of functions to execute before and after the event. """ before_hooks = self.hook_list(what, 'before') around_hooks = self.hook_list(what, 'around') after_hooks = self.hook_list(what, 'after') multi_hook = multi_manager(*around_hooks) # Save in a closure for both functions around_hook = [None] def before_func(*args, **kwargs): """All hooks to be called before the event.""" for before_hook in before_hooks: before_hook(*args, **kwargs) around_hook[0] = multi_hook(*args, **kwargs) around_hook[0].__enter__() def after_func(*args, **kwargs): """All hooks to be called after the event.""" around_hook[0].__exit__(None, None, None) around_hook[0] = None for after_hook in after_hooks: after_hook(*args, **kwargs) return before_func, after_func
def wrap(self, what, function, *hook_args, **hook_kwargs): """ Return a function that executes all the callbacks in proper relations to the given test part. """ before_hooks = self.hook_list(what, 'before') around_hooks = self.hook_list(what, 'around') after_hooks = self.hook_list(what, 'after') multi_hook = multi_manager(*around_hooks) @wraps(function) def wrapped(*args, **kwargs): """Run all the hooks in proper relations to the event.""" for before_hook in before_hooks: before_hook(*hook_args, **hook_kwargs) try: with multi_hook(*hook_args, **hook_kwargs): return function(*args, **kwargs) finally: # 'after' hooks still run after an exception for after_hook in reversed(after_hooks): after_hook(*hook_args, **hook_kwargs) return wrapped
def test_args(self): """ Test passing arguments to the invoked managers. """ @contextmanager def yield_args(*args): """A context manager passing its arguments to the context.""" yield args with multi_manager(yield_args, yield_args)('foo', 'bar') \ as (args1, args2): self.assertEqual(args1, ('foo', 'bar')) self.assertEqual(args2, ('foo', 'bar'))
def test_exceptions(self): """Test exception propagation.""" order = [] multi_cm = multi_manager(self.good_cm(order, 1), self.bad_cm, self.good_cm(order, 3)) with self.assertRaises(Exception): with multi_cm() as (_, _): raise AssertionError("Should not succeed") self.assertEqual(order, [ 'before cm 1', 'after cm 1', ])
def test_multi_manager(self): """Test combining context managers.""" order = [] multi_cm = multi_manager(self.good_cm(order, 1), self.good_cm(order, 2)) with multi_cm() as (ctx1, ctx2): self.assertEqual(ctx1, 'from cm 1') self.assertEqual(ctx2, 'from cm 2') self.assertEqual(order, [ 'before cm 1', 'before cm 2', 'after cm 2', 'after cm 1', ])