Commit 0698cfe5 authored by Arnaud Fontaine's avatar Arnaud Fontaine

linecache: Display source code of TALES Expressions and add support for ipdb.

Signed-off-by: Julien Muchembled's avatarJulien Muchembled <jm@nexedi.com>
parent 6f92189a
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
# #
############################################################################## ##############################################################################
import os, sys import os, re, sys
if sys.version_info < (2, 7): if sys.version_info < (2, 7):
...@@ -100,29 +100,51 @@ if 1: ...@@ -100,29 +100,51 @@ if 1:
from docutils import utils from docutils import utils
utils.relative_path = lambda source, target: os.path.abspath(target) utils.relative_path = lambda source, target: os.path.abspath(target)
import linecache def patch_linecache():
import linecache
from os.path import basename
linecache_getlines = linecache.getlines expr_search = re.compile('^Python expression "(.+)"$').search
def getlines(filename, module_globals=None):
def get_globals(frame):
"""
ipdb does not pass module_globals to getlines()...
"""
m = frame.f_globals['__name__']
if m == 'linecache':
frame = frame.f_back
m = frame.f_globals['__name__']
if m == 'IPython.core.debugger':
co_name = frame.f_code.co_name
if co_name == 'format_stack_entry':
return frame.f_locals['frame'].f_globals
elif co_name == 'print_list_lines':
return frame.f_locals['self'].curframe.f_globals
linecache_getlines = linecache.getlines
def getlines(filename, module_globals=None):
""" """
Patch of linecache module (used in traceback and pdb module) to display ZODB Patch of linecache module (used in traceback, ipdb, and pdb modules) to
Components and Python Script source code properly without requiring to display ZODB Components, Python Script source code and TALES Expressions
create a temporary file on the filesystem properly without requiring to create a temporary file on the filesystem
The filename is always '<string>' for any code executed by exec() (ZODB The filename is is always '<string>' for any code executed by exec() (ZODB
Components) and '(FILENAME)?Script \(Python\)' for Zope Python Scripts. Components), '(FILENAME)?Script \(Python\)' for Zope Python Scripts and
'Python Expression "CODE"' for TALES expressions.
linecache.cache filled by linecache.updatecache() called by the original linecache.cache filled by linecache.updatecache() called by the original
linecache.getlines() is bypassed for ZODB Components and Python Script to linecache.getlines() is bypassed for Python Script to avoid getting
avoid getting inconsistent source code. Having no cache could be an issue if inconsistent source code. Having no cache could be an issue if performances
performances would be required here but as linecache module is only called would be required here but as linecache module is only called by traceback
by traceback and pdb modules not used often, this should not be an issue. and pdb modules not used often, this should not be an issue.
""" """
if filename and module_globals: if filename:
data = None if module_globals is None:
module_globals = get_globals(sys._getframe(1))
# Get source code of ZODB Components (following PEP 302) # Get source code of ZODB Components (following PEP 302)
if filename == '<string>' and '__loader__' in module_globals: if filename == '<string>' and '__loader__' in module_globals:
data = None
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)
...@@ -132,14 +154,21 @@ def getlines(filename, module_globals=None): ...@@ -132,14 +154,21 @@ def getlines(filename, module_globals=None):
except (ImportError, AttributeError): except (ImportError, AttributeError):
pass pass
# Get source code of Zope Python Script return data.splitlines(True) if data is not None else ()
elif 'Script (Python)' in filename and 'script' in module_globals:
data = module_globals['script'].body()
if data is not None:
data = [line + '\n' for line in data.splitlines()]
return data
if basename(filename) == 'Script (Python)':
try:
script = module_globals['script']
if script._p_jar.opened:
return script.body().splitlines(True)
except Exception:
pass
return ()
x = expr_search(filename)
if x:
return x.groups()
return linecache_getlines(filename, module_globals) return linecache_getlines(filename, module_globals)
linecache.getlines = getlines linecache.getlines = getlines
patch_linecache()
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