Bug 1172800 - Avoid using inspect.getsourcelines() and inspect.getfile(). r=gps

inspect.getsourcelines() and inspect.getfile() involve I/O out of our control.
Our use of those functions, however, doesn't require all their smarts. In fact,
we only use them on function objects, for which we can just do the work
ourselves without involving inspect functions that trigger I/O.
This commit is contained in:
Mike Hommey 2015-06-09 15:18:39 +09:00
parent d86ab35b59
commit ad313aeb3b
2 changed files with 12 additions and 4 deletions

View File

@ -324,7 +324,7 @@ class MozbuildSandbox(Sandbox):
if name.islower() or name.isupper() or name[0].islower():
raise NameError('Template function names must be CamelCase.')
self.templates[name] = TemplateFunction(func)
self.templates[name] = TemplateFunction(func, self)
@memoize
def _create_subcontext(self, cls):
@ -408,11 +408,13 @@ class MozbuildSandbox(Sandbox):
class TemplateFunction(object):
def __init__(self, func):
self.path = inspect.getfile(func)
def __init__(self, func, sandbox):
self.path = func.func_code.co_filename
self.name = func.func_name
lines, firstlineno = inspect.getsourcelines(func)
firstlineno = func.func_code.co_firstlineno
lines = sandbox._current_source.splitlines(True)
lines = inspect.getblock(lines[firstlineno - 1:])
first_op = None
generator = tokenize.generate_tokens(iter(lines).next)
# Find the first indent token in the source of this template function,

View File

@ -129,6 +129,9 @@ class Sandbox(dict):
# evaluation.
self._last_name_error = None
# Current literal source being executed.
self._current_source = None
@property
def _context(self):
return self._active_contexts[-1]
@ -171,6 +174,8 @@ class Sandbox(dict):
# too low-level for that. However, we could add bytecode generation via
# the marshall module if parsing performance were ever an issue.
old_source = self._current_source
self._current_source = source
try:
# compile() inherits the __future__ from the module by default. We
# do want Unicode literals.
@ -212,6 +217,7 @@ class Sandbox(dict):
source_stack.append(path)
raise SandboxExecutionError(source_stack, exc[0], exc[1], exc[2])
finally:
self._current_source = old_source
self._context._sandbox = old_sandbox
if path and becomes_current_path:
self._context.pop_source()