Commit 2a7ab878 authored by Arnaud Fontaine's avatar Arnaud Fontaine

Display source code of Zope Python Scripts for any module using linecache (pdb and traceback).

parent 4406c9b3
...@@ -14,6 +14,21 @@ from Products.PythonScripts.PythonScript import PythonScript ...@@ -14,6 +14,21 @@ from Products.PythonScripts.PythonScript import PythonScript
from OFS.misc_ import p_ from OFS.misc_ import p_
from App.ImageFile import ImageFile from App.ImageFile import ImageFile
PythonScript_write = PythonScript.write
def write(self, text):
"""
Change the Python Script and purge linecache cache entry (meaningful for any
module relying on linecache, such as traceback and pdb)
"""
PythonScript_write(self, text)
import linecache
try:
del linecache.cache[self.get_filepath()]
except KeyError:
pass
PythonScript.write = write
def haveProxyRole(self): def haveProxyRole(self):
"""if a script has proxy role, return True""" """if a script has proxy role, return True"""
......
...@@ -109,12 +109,14 @@ linecache_getlines = linecache.getlines ...@@ -109,12 +109,14 @@ linecache_getlines = linecache.getlines
def getlines(filename, module_globals=None): def getlines(filename, module_globals=None):
""" """
The filename is always '<string>' for any code executed by exec(). ZODB The filename is always '<string>' for any code executed by exec(). ZODB
Component modules always set __file__ attribute to <erp5.component...>. Component modules always set __file__ attribute to <erp5.component...> and
'Script (Python)' for Zope Python Scripts.
The original getlines() will be called which look into the cache and if not The original getlines() will be called which look into the cache and if not
available, call updatecache. available, call updatecache.
""" """
if filename == '<string>' and module_globals and '__file__' in module_globals: if ((filename == '<string>' or filename == 'Script (Python)')
and module_globals and '__file__' in module_globals):
filename = module_globals['__file__'] filename = module_globals['__file__']
return linecache_getlines(filename, module_globals) return linecache_getlines(filename, module_globals)
...@@ -129,9 +131,17 @@ def updatecache(filename, module_globals=None): ...@@ -129,9 +131,17 @@ def updatecache(filename, module_globals=None):
through PEP 302 Loader, but it is perhaps to be more generic. Anyhow, <> is through PEP 302 Loader, but it is perhaps to be more generic. Anyhow, <> is
really needed to differenciate files on the filesystem to the ones only in really needed to differenciate files on the filesystem to the ones only in
memory... memory...
Also, get source code of Zope Python Script and store it in the linecache
cache as well (using __file__ module attribute equals to: 'Script
(Python):ABSOLUTE_URL'). See PythonScript.py patch as well to remove cache
entry when a PythonScript is modified.
""" """
if (filename[0] == '<' and filename[-1] == '>' and module_globals and if filename and module_globals:
'__loader__' in module_globals): data = None
# Get source code of ZODB Components (following PEP 302)
if filename[0] == '<' and filename[-1] == '>' and '__loader__' in module_globals:
name = module_globals.get('__name__') name = module_globals.get('__name__')
loader = module_globals['__loader__'] loader = module_globals['__loader__']
get_source = getattr(loader, 'get_source', None) get_source = getattr(loader, 'get_source', None)
...@@ -144,6 +154,11 @@ def updatecache(filename, module_globals=None): ...@@ -144,6 +154,11 @@ def updatecache(filename, module_globals=None):
if data is None: if data is None:
return [] return []
# Get source code of Zope Python Script
elif filename.startswith('Script (Python)') and 'script' in module_globals:
data = module_globals['script'].body()
if data is not None:
data_len = len(data) data_len = len(data)
data = [line + '\n' for line in data.splitlines()] data = [line + '\n' for line in data.splitlines()]
linecache.cache[filename] = (data_len, None, data, filename) linecache.cache[filename] = (data_len, None, data, filename)
......
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