diff options
| author | Michele Simionato <michele.simionato@gmail.com> | 2018-11-04 06:17:59 +0100 |
|---|---|---|
| committer | Michele Simionato <michele.simionato@gmail.com> | 2018-11-04 06:17:59 +0100 |
| commit | 2d1e9ba1072951a2c0eb8d280520fbc40b571652 (patch) | |
| tree | fcc399018805062631bc32a528d4a6ab515b8421 | |
| parent | ae956276697a4d89a3e0db3623feb0b1f7eaf53c (diff) | |
| download | python-decorator-git-2d1e9ba1072951a2c0eb8d280520fbc40b571652.tar.gz | |
Added a test for decorating generators
| -rw-r--r-- | CHANGES.md | 6 | ||||
| -rw-r--r-- | src/decorator.py | 30 | ||||
| -rw-r--r-- | src/tests/test.py | 17 |
3 files changed, 36 insertions, 17 deletions
@@ -1,6 +1,12 @@ HISTORY -------- +## unreleased + +Accepted a patch from Sylvain Marie (https://github.com/smarie): now the +decorator module can decorate generator functions by preserving their +being generator functions. + ## 4.3.1 (2018-08-04) Added a section "For the impatient" to the README, addressing an issue diff --git a/src/decorator.py b/src/decorator.py index 4433abf..80507ed 100644 --- a/src/decorator.py +++ b/src/decorator.py @@ -65,6 +65,12 @@ except AttributeError: # let's assume there are no coroutine functions in old Python def iscoroutinefunction(f): return False +try: + from inspect import isgeneratorfunction +except ImportError: + # assume no generator function in old Python versions + def isgeneratorfunction(): + return False DEF = re.compile(r'\s*def\s*([_\w][_\w\d]*)\s*\(') @@ -216,14 +222,6 @@ class FunctionMaker(object): return self.make(body, evaldict, addsource, **attrs) -try: - from inspect import isgeneratorfunction -except ImportError: - # assume no generator function in very old python versions - def isgeneratorfunction(): - return False - - def decorate(func, caller, extras=()): """ decorate(func, caller) decorates a function using a caller. @@ -237,17 +235,15 @@ def decorate(func, caller, extras=()): evaldict[ex] = extra es += ex + ', ' - if not ('3.5' <= sys.version < '3.6'): - create_generator = isgeneratorfunction(caller) - else: - # With Python 3.5: apparently isgeneratorfunction returns - # True for all coroutines - + if sys.version_info[2:] == (3, 5): + # With Python 3.5 isgeneratorfunction returns True for all coroutines # However we know that it is NOT possible to have a generator # coroutine in python 3.5: PEP525 was not there yet. - create_generator = isgeneratorfunction(caller) and not iscoroutinefunction(caller) - - if create_generator: + generatorcaller = isgeneratorfunction( + caller) and not iscoroutinefunction(caller) + else: + generatorcaller = isgeneratorfunction(caller) + if generatorcaller: fun = FunctionMaker.create( func, "for res in _call_(_func_, %s%%(shortsignature)s):\n" " yield res" % es, evaldict, __wrapped__=func) diff --git a/src/tests/test.py b/src/tests/test.py index 3c4dcd1..9068b11 100644 --- a/src/tests/test.py +++ b/src/tests/test.py @@ -58,6 +58,23 @@ class CoroutineTestCase(unittest.TestCase): ''') +def gen123(): + yield 1 + yield 2 + yield 3 + + +class GeneratorCallerTestCase(unittest.TestCase): + def test_gen123(self): + @decorator + def square(func, *args, **kw): + for x in gen123(): + yield x * x + new = square(gen123) + self.assertTrue(inspect.isgeneratorfunction(new)) + self.assertEqual(list(new()), [1, 4, 9]) + + class DocumentationTestCase(unittest.TestCase): def test(self): err = doctest.testmod(doc)[0] |
