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