Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow passing a custom CachingCompiler to the interactive shell #12809

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 34 additions & 6 deletions IPython/core/compilerop.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -112,25 +112,53 @@ def compiler_flags(self):
""" """
return self.flags return self.flags


def cache(self, code, number=0): def get_code_name(self, raw_code, transformed_code, number):
"""Compute filename given the code, and the cell number.

Parameters
----------
raw_code : str
The raw cell code.
transformed_code : str
The executable Python source code to cache and compile.
number : int
A number which forms part of the code's name. Used for the execution
counter.

Returns
-------
The computed filename.
"""
return code_name(transformed_code, number)

def cache(self, transformed_code, number=0, raw_code=None):
"""Make a name for a block of code, and cache the code. """Make a name for a block of code, and cache the code.


Parameters Parameters
---------- ----------
code : str transformed_code : str
The Python source code to cache. The executable Python source code to cache and compile.
number : int number : int
A number which forms part of the code's name. Used for the execution A number which forms part of the code's name. Used for the execution
counter. counter.
raw_code : str
The raw code before transformation, if None, set to `transformed_code`.


Returns Returns
------- -------
The name of the cached code (as a string). Pass this as the filename The name of the cached code (as a string). Pass this as the filename
argument to compilation, so that tracebacks are correctly hooked up. argument to compilation, so that tracebacks are correctly hooked up.
""" """
name = code_name(code, number) if raw_code is None:
entry = (len(code), time.time(), raw_code = transformed_code
[line+'\n' for line in code.splitlines()], name)
name = self.get_code_name(raw_code, transformed_code, number)
entry = (
len(transformed_code),
time.time(),
[line + "\n" for line in transformed_code.splitlines()],
name,
)
linecache.cache[name] = entry linecache.cache[name] = entry
linecache._ipython_cache[name] = entry linecache._ipython_cache[name] = entry
return name return name
Expand Down
24 changes: 17 additions & 7 deletions IPython/core/interactiveshell.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -443,6 +443,7 @@ def _import_runner(self, proposal):
display_formatter = Instance(DisplayFormatter, allow_none=True) display_formatter = Instance(DisplayFormatter, allow_none=True)
displayhook_class = Type(DisplayHook) displayhook_class = Type(DisplayHook)
display_pub_class = Type(DisplayPublisher) display_pub_class = Type(DisplayPublisher)
compiler_class = Type(CachingCompiler)


sphinxify_docstring = Bool(False, help= sphinxify_docstring = Bool(False, help=
""" """
Expand Down Expand Up @@ -748,7 +749,7 @@ def init_instance_attrs(self):
self.more = False self.more = False


# command compiler # command compiler
self.compile = CachingCompiler() self.compile = self.compiler_class()


# Make an empty namespace, which extension writers can rely on both # Make an empty namespace, which extension writers can rely on both
# existing and NEVER being used by ipython itself. This gives them a # existing and NEVER being used by ipython itself. This gives them a
Expand Down Expand Up @@ -1775,8 +1776,14 @@ def _inspect(self, meth, oname, namespaces=None, **kw):
if meth == 'pdoc': if meth == 'pdoc':
pmethod(info.obj, oname, formatter) pmethod(info.obj, oname, formatter)
elif meth == 'pinfo': elif meth == 'pinfo':
pmethod(info.obj, oname, formatter, info, pmethod(
enable_html_pager=self.enable_html_pager, **kw) info.obj,
oname,
formatter,
info,
enable_html_pager=self.enable_html_pager,
**kw
)
else: else:
pmethod(info.obj, oname) pmethod(info.obj, oname)
else: else:
Expand Down Expand Up @@ -2299,8 +2306,9 @@ def init_magics(self):
# Defined here so that it's included in the documentation # Defined here so that it's included in the documentation
@functools.wraps(magic.MagicsManager.register_function) @functools.wraps(magic.MagicsManager.register_function)
def register_magic_function(self, func, magic_kind='line', magic_name=None): def register_magic_function(self, func, magic_kind='line', magic_name=None):
self.magics_manager.register_function(func, self.magics_manager.register_function(
magic_kind=magic_kind, magic_name=magic_name) func, magic_kind=magic_kind, magic_name=magic_name
)


def run_line_magic(self, magic_name, line, _stack_depth=1): def run_line_magic(self, magic_name, line, _stack_depth=1):
"""Execute the given line magic. """Execute the given line magic.
Expand Down Expand Up @@ -3096,12 +3104,14 @@ def error_before_exec(value):
# Our own compiler remembers the __future__ environment. If we want to # Our own compiler remembers the __future__ environment. If we want to
# run code with a separate __future__ environment, use the default # run code with a separate __future__ environment, use the default
# compiler # compiler
compiler = self.compile if shell_futures else CachingCompiler() compiler = self.compile if shell_futures else self.compiler_class()


_run_async = False _run_async = False


with self.builtin_trap: with self.builtin_trap:
cell_name = self.compile.cache(cell, self.execution_count) cell_name = self.compile.cache(
cell, self.execution_count, raw_code=raw_cell
)


with self.display_trap: with self.display_trap:
# Compile to bytecode # Compile to bytecode
Expand Down