summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichele Simionato <michele.simionato@gmail.com>2015-09-25 04:25:43 +0200
committerMichele Simionato <michele.simionato@gmail.com>2015-09-25 04:25:43 +0200
commitf6f1f69f576e438b3aad336d3faa20d1012b3aeb (patch)
tree2e28bbf524e97a01caf2a9eb0c36c5daa3d37f47
parent705cfa854bfa3bc44494d1d985cff1d01e270ae9 (diff)
parentcf1a9ac320717f5db042130eb995e42f1e3d3a6c (diff)
downloadpython-decorator-git-f6f1f69f576e438b3aad336d3faa20d1012b3aeb.tar.gz
Merge pull request #15 from zbenjamin/master
Ensure each generated function has a unique filename
-rw-r--r--src/decorator.py11
-rw-r--r--src/tests/test.py29
2 files changed, 38 insertions, 2 deletions
diff --git a/src/decorator.py b/src/decorator.py
index b9d3732..760193b 100644
--- a/src/decorator.py
+++ b/src/decorator.py
@@ -87,6 +87,10 @@ class FunctionMaker(object):
It has attributes name, doc, module, signature, defaults, dict and
methods update and make.
"""
+
+ # Atomic get-and-increment provided by the GIL
+ _compile_count = itertools.count()
+
def __init__(self, func=None, name=None, signature=None,
defaults=None, doc=None, module=None, funcdict=None):
self.shortsignature = signature
@@ -176,8 +180,13 @@ class FunctionMaker(object):
raise NameError('%s is overridden in\n%s' % (n, src))
if not src.endswith('\n'): # add a newline just for safety
src += '\n' # this is needed in old versions of Python
+
+ # Ensure each generated function has a unique filename for profilers
+ # (such as cProfile) that depend on the tuple of (<filename>,
+ # <definition line>, <function name>) being unique.
+ filename = '<decorator-gen-%d>' % (next(self._compile_count),)
try:
- code = compile(src, '<string>', 'single')
+ code = compile(src, filename, 'single')
exec(code, evaldict)
except:
print('Error in generated code:', file=sys.stderr)
diff --git a/src/tests/test.py b/src/tests/test.py
index 45a9b9b..ab65dfa 100644
--- a/src/tests/test.py
+++ b/src/tests/test.py
@@ -6,7 +6,7 @@ import decimal
import inspect
import functools
import collections
-from decorator import dispatch_on, contextmanager
+from decorator import dispatch_on, contextmanager, decorator
try:
from . import documentation as doc
except (SystemError, ValueError):
@@ -52,6 +52,33 @@ class ExtraTestCase(unittest.TestCase):
sig = inspect.signature(doc.f1)
self.assertEqual(str(sig), '(x)')
+ def test_unique_filenames(self):
+ @decorator
+ def d1(f, *args, **kwargs):
+ return f(*args, **kwargs)
+
+ @decorator
+ def d2(f, *args, **kwargs):
+ return f(*args, **kwargs)
+
+ @d1
+ def f1(x, y, z):
+ pass
+
+ @d2
+ def f2(x, y, z):
+ pass
+
+ f1_orig = f1
+
+ @d1
+ def f1(x, y, z):
+ pass
+
+ self.assertNotEqual(d1.__code__.co_filename, d2.__code__.co_filename)
+ self.assertNotEqual(f1.__code__.co_filename, f2.__code__.co_filename)
+ self.assertNotEqual(f1_orig.__code__.co_filename, f1.__code__.co_filename)
+
# ################### test dispatch_on ############################# #
# adapted from test_functools in Python 3.5
singledispatch = dispatch_on('obj')