Created
December 17, 2014 07:18
-
-
Save mihneasim/0b62c91ee2ca13e2b464 to your computer and use it in GitHub Desktop.
Call before and call after - Python decorators
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
from functools import wraps | |
def call_before(before_func, *args, **kwargs): | |
def call_before_decorator(func): | |
@wraps(func) | |
def wrapping(*args2, **kwargs2): | |
before_func(*args, **kwargs) | |
return func(*args2, **kwargs2) | |
return wrapping | |
return call_before_decorator | |
def call_after(after_func, *args, **kwargs): | |
def call_after_decorator(func): | |
@wraps(func) | |
def wrapping(*args2, **kwargs2): | |
try: | |
result = func(*args2, **kwargs2) | |
finally: | |
after_func(*args, **kwargs) | |
return result | |
return wrapping | |
return call_after_decorator | |
# And use them chained: | |
def log_enter_exit(logger, message=""): | |
def enter_exit_decorator(func): | |
@wraps(func) | |
@call_before(logger.debug, "Calling %s - %s", func.__name__, message) | |
@call_after(logger.debug, "Called %s - %s", func.__name__, message) | |
def wrapping(*args, **kwargs): | |
return func(*args, **kwargs) | |
return wrapping | |
return enter_exit_decorator | |
# Tests, because tests: | |
import mock | |
import unittest | |
from commons.decorators import * | |
class DecoratorsTestCase(unittest.TestCase): | |
def test_callbefore(self): | |
a = [] | |
def append(where, what): | |
where.append(what) | |
@call_before(append, a, 3) | |
def extend(where, what): | |
where.extend(what) | |
return where | |
self.assertEqual(extend(a, [4, 5]), [3, 4, 5]) | |
self.assertEqual(extend(a, [6]), [3, 4, 5, 3, 6]) | |
self.assertEqual(extend([], [1, 2]), [1, 2]) | |
self.assertEqual(a, [3, 4, 5, 3, 6, 3]) | |
def test_callafter(self): | |
a = [] | |
def append(where, what): | |
where.append(what) | |
@call_after(append, a, 6) | |
def extend(where, what): | |
where.extend(what) | |
return list(where) | |
self.assertEqual(extend(a, [4, 5]), [4, 5]) | |
self.assertEqual(a, [4, 5, 6]) | |
self.assertEqual(extend(a, [7]), [4, 5, 6, 7]) | |
self.assertEqual(a, [4, 5, 6, 7, 6]) | |
self.assertEqual(extend([], [1, 2]), [1, 2]) | |
self.assertEqual(a, [4, 5, 6, 7, 6, 6]) | |
def test_log_enter_exit(self): | |
logger = mock.Mock() | |
messages = [] | |
def debug(pattern, *args, **kwargs): | |
messages.append(pattern % args) | |
logger.debug.side_effect = debug | |
logger.debug("Testing my %s", "mock") | |
self.assertEqual(messages[0], "Testing my mock") | |
@log_enter_exit(logger, "Whoaa") | |
def append(arg): | |
messages.append(arg) | |
return 3 | |
self.assertEqual(append(666), 3) | |
self.assertEqual(messages[-3], "Calling append - Whoaa") | |
self.assertEqual(messages[-2], 666) | |
self.assertEqual(messages[-1], "Called append - Whoaa") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment