From 2837c1dc27dac958ffa37d82bc34a56b8860fbc9 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 25 Sep 2013 16:52:05 +0200 Subject: [PATCH] [ADD] composition function utility bzr revid: xmo@openerp.com-20130925145205-vumu9cgr5kob0900 --- openerp/tests/__init__.py | 2 ++ openerp/tests/test_func.py | 22 ++++++++++++++++++++++ openerp/tools/func.py | 15 +++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 openerp/tests/test_func.py diff --git a/openerp/tests/__init__.py b/openerp/tests/__init__.py index 0e86effe8f0..aa38f7831e9 100644 --- a/openerp/tests/__init__.py +++ b/openerp/tests/__init__.py @@ -22,6 +22,7 @@ import test_translate import test_uninstall import test_view_validation import test_qweb +import test_func # This need a change in `oe run-tests` to only run fast_suite + checks by default. # import test_xmlrpc @@ -43,6 +44,7 @@ checks = [ test_osv, test_translate, test_qweb, + test_func, ] # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/tests/test_func.py b/openerp/tests/test_func.py new file mode 100644 index 00000000000..7bb2e8fdf07 --- /dev/null +++ b/openerp/tests/test_func.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +import functools +import unittest2 + +from ..tools.func import compose + +class TestCompose(unittest2.TestCase): + def test_basic(self): + str_add = compose(str, lambda a, b: a + b) + self.assertEqual( + str_add(1, 2), + "3") + + def test_decorator(self): + """ ensure compose() can be partially applied as a decorator + """ + @functools.partial(compose, unicode) + def mul(a, b): + return a * b + + self.assertEqual(mul(5, 42), u"210") + diff --git a/openerp/tools/func.py b/openerp/tools/func.py index 4728d971c69..ca8bba6bd49 100644 --- a/openerp/tools/func.py +++ b/openerp/tools/func.py @@ -57,4 +57,19 @@ def frame_codeinfo(fframe, back=0): except Exception: return "", '' +def compose(a, b): + """ Composes the callables ``a`` and ``b``. ``compose(a, b)(*args)`` is + equivalent to ``a(b(*args))``. + + Can be used as a decorator by partially applying ``a``:: + + @partial(compose, a) + def b(): + ... + """ + @wraps(b) + def wrapper(*args, **kwargs): + return a(b(*args, **kwargs)) + return wrapper + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: