diff --git a/CHANGES.rst b/CHANGES.rst index a57b4340e5..5afe97abcb 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -15,6 +15,9 @@ https://github.com/zopefoundation/Zope/blob/4.x/CHANGES.rst For details, see `#1136 `_. +- Restore filename on code objects of objects returned from + ``App.Extensions.getObject()``. This got lost in 4.0a6. + - Update to newest compatible versions of dependencies. diff --git a/src/App/Extensions.py b/src/App/Extensions.py index a13c9d5c0f..dce6b121d6 100644 --- a/src/App/Extensions.py +++ b/src/App/Extensions.py @@ -180,8 +180,9 @@ def getObject(module, name, reload=0): except Exception: raise NotFound("The specified module, '%s', " "couldn't be opened." % module) + execcode = compile(execsrc, path, 'exec') module_dict = {} - exec(execsrc, module_dict) + exec(execcode, module_dict) if old is not None: # XXX Accretive?? diff --git a/src/App/tests/fixtures/error.py b/src/App/tests/fixtures/error.py new file mode 100644 index 0000000000..81fa728910 --- /dev/null +++ b/src/App/tests/fixtures/error.py @@ -0,0 +1,2 @@ +# This file intentionally contains a SyntaxError +a = # noqa diff --git a/src/App/tests/fixtures/getObject.py b/src/App/tests/fixtures/getObject.py new file mode 100644 index 0000000000..2ee5467cd2 --- /dev/null +++ b/src/App/tests/fixtures/getObject.py @@ -0,0 +1,5 @@ +import sys + + +def f1(): + return sys._getframe(0).f_code.co_filename diff --git a/src/App/tests/test_Extensions.py b/src/App/tests/test_Extensions.py new file mode 100644 index 0000000000..30d6271027 --- /dev/null +++ b/src/App/tests/test_Extensions.py @@ -0,0 +1,38 @@ +import types +import unittest +from pathlib import Path + +import App.config +from App.Extensions import getObject + + +class GetObjectTests(unittest.TestCase): + """Testing ..Extensions.getObject().""" + + def setUp(self): + cfg = App.config.getConfiguration() + assert not hasattr(cfg, 'extensions') + cfg.extensions = Path(__file__).parent / 'fixtures' + + def tearDown(self): + cfg = App.config.getConfiguration() + del cfg.extensions + + def test_Extensions__getObject__1(self): + """Check that "getObject" returns the requested function and ... + + that its code object has the path set. + """ + obj = getObject('getObject', 'f1') + self.assertIsInstance(obj, types.FunctionType) + self.assertEqual(obj.__name__, 'f1') + path = obj() + self.assertTrue( + path.endswith(str(Path('App/tests/fixtures/getObject.py')))) + + def test_Extensions__getObject__2(self): + """It raises a SyntaxError if necessary.""" + try: + getObject('error', 'f1') + except SyntaxError as e: + self.assertEqual(str(e), 'invalid syntax (error.py, line 2)')