Skip to content

Commit e1fa6e0

Browse files
matthiasdienerinducer
authored andcommitted
PythonFunctionGenerator: add decorator support
1 parent 227c62c commit e1fa6e0

2 files changed

Lines changed: 42 additions & 1 deletion

File tree

pytools/py_codegen.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,14 @@ def get_picklable_module(self, name=None):
5252

5353

5454
class PythonFunctionGenerator(PythonCodeGenerator):
55-
def __init__(self, name, args):
55+
def __init__(self, name, args, decorators=None):
5656
PythonCodeGenerator.__init__(self)
5757
self.name = name
5858

59+
if decorators:
60+
for decorator in decorators:
61+
self(decorator)
62+
5963
self("def {}({}):".format(name, ", ".join(args)))
6064
self.indent()
6165

pytools/test/test_py_codegen.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import sys
44

5+
import pytest
6+
57
import pytools
68
import pytools.py_codegen as codegen
79

@@ -30,6 +32,41 @@ def test_picklable_function():
3032
assert f() == 1
3133

3234

35+
def test_function_decorators(capfd):
36+
cg = codegen.PythonFunctionGenerator("f", args=(), decorators=["@staticmethod"])
37+
cg("return 42")
38+
39+
assert cg.get_function()() == 42
40+
41+
cg = codegen.PythonFunctionGenerator("f", args=(), decorators=["@classmethod"])
42+
cg("return 42")
43+
44+
with pytest.raises(TypeError):
45+
cg.get_function()()
46+
47+
cg = codegen.PythonFunctionGenerator("f", args=(),
48+
decorators=["@staticmethod", "@classmethod"])
49+
cg("return 42")
50+
51+
with pytest.raises(TypeError):
52+
cg.get_function()()
53+
54+
cg = codegen.PythonFunctionGenerator("f", args=("x"),
55+
decorators=["from functools import lru_cache", "@lru_cache"])
56+
cg("print('Hello World!')")
57+
cg("return 42")
58+
59+
f = cg.get_function()
60+
61+
assert f(0) == 42
62+
out, _err = capfd.readouterr()
63+
assert out == "Hello World!\n"
64+
65+
assert f(0) == 42
66+
out, _err = capfd.readouterr()
67+
assert out == "" # second print is not executed due to lru_cache
68+
69+
3370
if __name__ == "__main__":
3471
if len(sys.argv) > 1:
3572
exec(sys.argv[1])

0 commit comments

Comments
 (0)