Commit 58ab3a19 authored by Jérome Perrin's avatar Jérome Perrin

py3: review linecache patches

 - Products.PythonScripts now has a __loader__
 - do not use < > as filename for component on py3, this makes linecache
 work out of the box. On py2 I think it was causing errors trying to
 actually open the file, but this does not seem needed on py3 and
 simplifies everything
parent 90ef8add
Pipeline #34948 failed with stage
in 0 seconds
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
# #
############################################################################## ##############################################################################
import six
import sys import sys
import traceback import traceback
...@@ -84,6 +85,11 @@ class TestERP5PythonScript(ERP5TypeTestCase): ...@@ -84,6 +85,11 @@ class TestERP5PythonScript(ERP5TypeTestCase):
self.script.setBody('return "Hello " + who') self.script.setBody('return "Hello " + who')
self.assertEqual(self.script("world"), "Hello world") self.assertEqual(self.script("world"), "Hello world")
if six.PY2:
filename = 'ERP5 Python Script'
else:
filename = 'ERP5 Python Script:%s' % self.script.getPath()
try: try:
self.script(123) self.script(123)
except TypeError: except TypeError:
...@@ -91,8 +97,8 @@ class TestERP5PythonScript(ERP5TypeTestCase): ...@@ -91,8 +97,8 @@ class TestERP5PythonScript(ERP5TypeTestCase):
# python script code is visible in traceback # python script code is visible in traceback
self.assertEqual( self.assertEqual(
traceback.format_tb(tb)[-1], traceback.format_tb(tb)[-1],
' File "ERP5 Python Script", line 1, in %s\n' ' File "%s", line 1, in %s\n'
' return "Hello " + who\n' % self.id() ' return "Hello " + who\n' % (filename, self.id())
) )
else: else:
self.fail('Exception not raised') self.fail('Exception not raised')
...@@ -126,6 +132,11 @@ class TestERP5WorkflowScript(ERP5TypeTestCase): ...@@ -126,6 +132,11 @@ class TestERP5WorkflowScript(ERP5TypeTestCase):
self.script.setBody('return "Hello " + state_change') self.script.setBody('return "Hello " + state_change')
self.assertEqual(self.script("world"), "Hello world") self.assertEqual(self.script("world"), "Hello world")
if six.PY2:
filename = 'ERP5 Workflow Script'
else:
filename = 'ERP5 Workflow Script:%s' % self.script.getPath()
try: try:
self.script(123) self.script(123)
except TypeError: except TypeError:
...@@ -133,8 +144,8 @@ class TestERP5WorkflowScript(ERP5TypeTestCase): ...@@ -133,8 +144,8 @@ class TestERP5WorkflowScript(ERP5TypeTestCase):
# python script code is visible in traceback # python script code is visible in traceback
self.assertEqual( self.assertEqual(
traceback.format_tb(tb)[-1], traceback.format_tb(tb)[-1],
' File "ERP5 Workflow Script", line 1, in script_test_script\n' (' File "%s", line 1, in script_test_script\n'
' return "Hello " + state_change\n' ' return "Hello " + state_change\n') % filename
) )
else: else:
self.fail('Exception not raised') self.fail('Exception not raised')
...@@ -332,7 +332,10 @@ class ComponentDynamicPackage(ModuleType): ...@@ -332,7 +332,10 @@ class ComponentDynamicPackage(ModuleType):
component = getattr(site.portal_components, component_id) component = getattr(site.portal_components, component_id)
relative_url = component.getRelativeUrl() relative_url = component.getRelativeUrl()
if six.PY2:
module_file = '<' + relative_url + '>' module_file = '<' + relative_url + '>'
else:
module_file = 'erp5://' + relative_url
module_fullname = '%s.%s_version.%s' % (self._namespace, version, name) module_fullname = '%s.%s_version.%s' % (self._namespace, version, name)
module = ModuleType(module_fullname, component.getDescription()) module = ModuleType(module_fullname, component.getDescription())
......
...@@ -173,50 +173,13 @@ def patch_linecache(): ...@@ -173,50 +173,13 @@ def patch_linecache():
if x: if x:
return x.groups() return x.groups()
if filename.startswith('<portal_components/'):
# use our special key for lazycache
filename = 'erp5-linecache://' + filename
return linecache_getlines(filename, module_globals) return linecache_getlines(filename, module_globals)
linecache.getlines = getlines linecache.getlines = getlines
if sys.version_info[:3] >= (3, ):
linecache_lazycache = linecache.lazycache
def lazycache(filename, module_globals):
if filename:
# XXX linecache ignores files named like <this>, but this is
# what we used for portal_components filename (and it's not so
# good because it's not easy to copy paste, so we might want to
# reconsider), for now, we add an arbitrary prefix for cache.
if (filename.startswith('<') and filename.endswith('>')):
filename = 'erp5-linecache://' + filename
# For python scripts, insert a fake PEP302 loader so that
# linecache can find the source code
if basename(filename) in (
'Script (Python)',
'ERP5 Python Script',
'ERP5 Workflow Script',
) and module_globals is not None:
script = module_globals['script']
body = ''
if script._p_jar is None or script._p_jar.opened:
body = script.body()
class PythonScriptLoader:
def __init__(self, filename, body):
self.filename = filename
self.body = body
def get_source(self, name, *args, **kw):
return self.body
assert '__loader___' not in module_globals
module_globals['__loader__'] = PythonScriptLoader(filename, body)
return linecache_lazycache(filename, module_globals)
linecache.lazycache = lazycache
patch_linecache() if sys.version_info[:3] < (3, ):
patch_linecache()
import decimal as _decimal import decimal as _decimal
......
...@@ -3426,9 +3426,9 @@ ImportError: No module named non.existing.module ...@@ -3426,9 +3426,9 @@ ImportError: No module named non.existing.module
''' '''
else: else:
expected_output = ''' expected_output = '''
File "<portal_components/test.erp5.testRunLiveTestImportError>", line 4, in <module> File "erp5://portal_components/test.erp5.testRunLiveTestImportError", line 4, in <module>
break_at_import() break_at_import()
File "<portal_components/test.erp5.testRunLiveTestImportError>", line 3, in break_at_import File "erp5://portal_components/test.erp5.testRunLiveTestImportError", line 3, in break_at_import
import non.existing.module # pylint:disable=import-error import non.existing.module # pylint:disable=import-error
ModuleNotFoundError: No module named 'non' ModuleNotFoundError: No module named 'non'
''' '''
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment