##// END OF EJS Templates
Allow passing a custom CachingCompiler to the interactive shell...
martinRenou -
Show More
@@ -99,7 +99,7 b' class CachingCompiler(codeop.Compile):'
99 99 Arguments are exactly the same as ast.parse (in the standard library),
100 100 and are passed to the built-in compile function."""
101 101 return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1)
102
102
103 103 def reset_compiler_flags(self):
104 104 """Reset compiler flags to default state."""
105 105 # This value is copied from codeop.Compile.__init__, so if that ever
@@ -112,25 +112,53 b' class CachingCompiler(codeop.Compile):'
112 112 """
113 113 return self.flags
114 114
115 def cache(self, code, number=0):
115 def get_code_name(self, raw_code, transformed_code, number):
116 """Compute filename given the code, and the cell number.
117
118 Parameters
119 ----------
120 raw_code : str
121 The raw cell code.
122 transformed_code : str
123 The executable Python source code to cache and compile.
124 number : int
125 A number which forms part of the code's name. Used for the execution
126 counter.
127
128 Returns
129 -------
130 The computed filename.
131 """
132 return code_name(transformed_code, number)
133
134 def cache(self, transformed_code, number=0, raw_code=None):
116 135 """Make a name for a block of code, and cache the code.
117 136
118 137 Parameters
119 138 ----------
120 code : str
121 The Python source code to cache.
139 transformed_code : str
140 The executable Python source code to cache and compile.
122 141 number : int
123 142 A number which forms part of the code's name. Used for the execution
124 143 counter.
144 raw_code : str
145 The raw code before transformation, if None, set to `transformed_code`.
125 146
126 147 Returns
127 148 -------
128 149 The name of the cached code (as a string). Pass this as the filename
129 150 argument to compilation, so that tracebacks are correctly hooked up.
130 151 """
131 name = code_name(code, number)
132 entry = (len(code), time.time(),
133 [line+'\n' for line in code.splitlines()], name)
152 if raw_code is None:
153 raw_code = transformed_code
154
155 name = self.get_code_name(raw_code, transformed_code, number)
156 entry = (
157 len(transformed_code),
158 time.time(),
159 [line + "\n" for line in transformed_code.splitlines()],
160 name,
161 )
134 162 linecache.cache[name] = entry
135 163 linecache._ipython_cache[name] = entry
136 164 return name
@@ -146,7 +174,7 b' class CachingCompiler(codeop.Compile):'
146 174 yield
147 175 finally:
148 176 # turn off only the bits we turned on so that something like
149 # __future__ that set flags stays.
177 # __future__ that set flags stays.
150 178 self.flags &= ~turn_on_bits
151 179
152 180
@@ -340,7 +340,7 b' class InteractiveShell(SingletonConfigurable):'
340 340 """An enhanced, interactive shell for Python."""
341 341
342 342 _instance = None
343
343
344 344 ast_transformers = List([], help=
345 345 """
346 346 A list of ast.NodeTransformer subclass instances, which will be applied
@@ -407,7 +407,7 b' class InteractiveShell(SingletonConfigurable):'
407 407 Enable magic commands to be called without the leading %.
408 408 """
409 409 ).tag(config=True)
410
410
411 411 banner1 = Unicode(default_banner,
412 412 help="""The part of the banner to be printed before the profile"""
413 413 ).tag(config=True)
@@ -443,7 +443,8 b' class InteractiveShell(SingletonConfigurable):'
443 443 display_formatter = Instance(DisplayFormatter, allow_none=True)
444 444 displayhook_class = Type(DisplayHook)
445 445 display_pub_class = Type(DisplayPublisher)
446
446 compiler_class = Type(CachingCompiler)
447
447 448 sphinxify_docstring = Bool(False, help=
448 449 """
449 450 Enables rich html representation of docstrings. (This requires the
@@ -534,7 +535,7 b' class InteractiveShell(SingletonConfigurable):'
534 535 ).tag(config=True)
535 536
536 537 # deprecated prompt traits:
537
538
538 539 prompt_in1 = Unicode('In [\\#]: ',
539 540 help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
540 541 ).tag(config=True)
@@ -547,14 +548,14 b' class InteractiveShell(SingletonConfigurable):'
547 548 prompts_pad_left = Bool(True,
548 549 help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
549 550 ).tag(config=True)
550
551
551 552 @observe('prompt_in1', 'prompt_in2', 'prompt_out', 'prompt_pad_left')
552 553 def _prompt_trait_changed(self, change):
553 554 name = change['name']
554 555 warn("InteractiveShell.{name} is deprecated since IPython 4.0"
555 556 " and ignored since 5.0, set TerminalInteractiveShell.prompts"
556 557 " object directly.".format(name=name))
557
558
558 559 # protect against weird cases where self.config may not exist:
559 560
560 561 show_rewritten_input = Bool(True,
@@ -638,7 +639,7 b' class InteractiveShell(SingletonConfigurable):'
638 639 self.init_profile_dir(profile_dir)
639 640 self.init_instance_attrs()
640 641 self.init_environment()
641
642
642 643 # Check if we're in a virtualenv, and set up sys.path.
643 644 self.init_virtualenv()
644 645
@@ -748,7 +749,7 b' class InteractiveShell(SingletonConfigurable):'
748 749 self.more = False
749 750
750 751 # command compiler
751 self.compile = CachingCompiler()
752 self.compile = self.compiler_class()
752 753
753 754 # Make an empty namespace, which extension writers can rely on both
754 755 # existing and NEVER being used by ipython itself. This gives them a
@@ -986,7 +987,7 b' class InteractiveShell(SingletonConfigurable):'
986 987 #-------------------------------------------------------------------------
987 988 # Things related to the banner
988 989 #-------------------------------------------------------------------------
989
990
990 991 @property
991 992 def banner(self):
992 993 banner = self.banner1
@@ -1000,7 +1001,7 b' class InteractiveShell(SingletonConfigurable):'
1000 1001 if banner is None:
1001 1002 banner = self.banner
1002 1003 sys.stdout.write(banner)
1003
1004
1004 1005 #-------------------------------------------------------------------------
1005 1006 # Things related to hooks
1006 1007 #-------------------------------------------------------------------------
@@ -1017,10 +1018,10 b' class InteractiveShell(SingletonConfigurable):'
1017 1018 # default hooks have priority 100, i.e. low; user hooks should have
1018 1019 # 0-100 priority
1019 1020 self.set_hook(hook_name,getattr(hooks,hook_name), 100, _warn_deprecated=False)
1020
1021
1021 1022 if self.display_page:
1022 1023 self.set_hook('show_in_pager', page.as_hook(page.display_page), 90)
1023
1024
1024 1025 def set_hook(self,name,hook, priority=50, str_key=None, re_key=None,
1025 1026 _warn_deprecated=True):
1026 1027 """set_hook(name,hook) -> sets an internal IPython hook.
@@ -1084,7 +1085,7 b' class InteractiveShell(SingletonConfigurable):'
1084 1085 warn("ip.register_post_execute is deprecated, use "
1085 1086 "ip.events.register('post_run_cell', func) instead.", stacklevel=2)
1086 1087 self.events.register('post_run_cell', func)
1087
1088
1088 1089 def _clear_warning_registry(self):
1089 1090 # clear the warning registry, so that different code blocks with
1090 1091 # overlapping line number ranges don't cause spurious suppression of
@@ -1126,12 +1127,12 b' class InteractiveShell(SingletonConfigurable):'
1126 1127 else:
1127 1128 main_mod.__dict__.clear()
1128 1129 main_mod.__name__ = modname
1129
1130
1130 1131 main_mod.__file__ = filename
1131 1132 # It seems pydoc (and perhaps others) needs any module instance to
1132 1133 # implement a __nonzero__ method
1133 1134 main_mod.__nonzero__ = lambda : True
1134
1135
1135 1136 return main_mod
1136 1137
1137 1138 def clear_main_mod_cache(self):
@@ -1283,7 +1284,7 b' class InteractiveShell(SingletonConfigurable):'
1283 1284 'user_local':self.user_ns,
1284 1285 'builtin':builtin_mod.__dict__
1285 1286 }
1286
1287
1287 1288 @property
1288 1289 def user_global_ns(self):
1289 1290 return self.user_module.__dict__
@@ -1316,17 +1317,17 b' class InteractiveShell(SingletonConfigurable):'
1316 1317 user_ns.setdefault("__name__", "__main__")
1317 1318 user_module = DummyMod()
1318 1319 user_module.__dict__ = user_ns
1319
1320
1320 1321 if user_module is None:
1321 1322 user_module = types.ModuleType("__main__",
1322 1323 doc="Automatically created module for IPython interactive environment")
1323
1324
1324 1325 # We must ensure that __builtin__ (without the final 's') is always
1325 1326 # available and pointing to the __builtin__ *module*. For more details:
1326 1327 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1327 1328 user_module.__dict__.setdefault('__builtin__', builtin_mod)
1328 1329 user_module.__dict__.setdefault('__builtins__', builtin_mod)
1329
1330
1330 1331 if user_ns is None:
1331 1332 user_ns = user_module.__dict__
1332 1333
@@ -1382,7 +1383,7 b' class InteractiveShell(SingletonConfigurable):'
1382 1383 # For more details:
1383 1384 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1384 1385 ns = {}
1385
1386
1386 1387 # make global variables for user access to the histories
1387 1388 ns['_ih'] = self.history_manager.input_hist_parsed
1388 1389 ns['_oh'] = self.history_manager.output_hist
@@ -1395,7 +1396,7 b' class InteractiveShell(SingletonConfigurable):'
1395 1396
1396 1397 # Store myself as the public api!!!
1397 1398 ns['get_ipython'] = self.get_ipython
1398
1399
1399 1400 ns['exit'] = self.exiter
1400 1401 ns['quit'] = self.exiter
1401 1402
@@ -1409,7 +1410,7 b' class InteractiveShell(SingletonConfigurable):'
1409 1410
1410 1411 # Finally, update the real user's namespace
1411 1412 self.user_ns.update(ns)
1412
1413
1413 1414 @property
1414 1415 def all_ns_refs(self):
1415 1416 """Get a list of references to all the namespace dictionaries in which
@@ -1435,7 +1436,7 b' class InteractiveShell(SingletonConfigurable):'
1435 1436 # Reset last execution result
1436 1437 self.last_execution_succeeded = True
1437 1438 self.last_execution_result = None
1438
1439
1439 1440 # Flush cached output items
1440 1441 if self.displayhook.do_full_cache:
1441 1442 self.displayhook.flush()
@@ -1500,7 +1501,7 b' class InteractiveShell(SingletonConfigurable):'
1500 1501 raise ValueError("Refusing to delete %s" % varname)
1501 1502
1502 1503 ns_refs = self.all_ns_refs
1503
1504
1504 1505 if by_name: # Delete by name
1505 1506 for ns in ns_refs:
1506 1507 try:
@@ -1775,8 +1776,14 b' class InteractiveShell(SingletonConfigurable):'
1775 1776 if meth == 'pdoc':
1776 1777 pmethod(info.obj, oname, formatter)
1777 1778 elif meth == 'pinfo':
1778 pmethod(info.obj, oname, formatter, info,
1779 enable_html_pager=self.enable_html_pager, **kw)
1779 pmethod(
1780 info.obj,
1781 oname,
1782 formatter,
1783 info,
1784 enable_html_pager=self.enable_html_pager,
1785 **kw
1786 )
1780 1787 else:
1781 1788 pmethod(info.obj, oname)
1782 1789 else:
@@ -1900,7 +1907,7 b' class InteractiveShell(SingletonConfigurable):'
1900 1907 print('Exception type :', etype)
1901 1908 print('Exception value:', value)
1902 1909 print('Traceback :', tb)
1903
1910
1904 1911 def validate_stb(stb):
1905 1912 """validate structured traceback return type
1906 1913
@@ -1929,7 +1936,7 b' class InteractiveShell(SingletonConfigurable):'
1929 1936 else:
1930 1937 def wrapped(self,etype,value,tb,tb_offset=None):
1931 1938 """wrap CustomTB handler, to protect IPython from user code
1932
1939
1933 1940 This makes it harder (but not impossible) for custom exception
1934 1941 handlers to crash IPython.
1935 1942 """
@@ -1978,10 +1985,10 b' class InteractiveShell(SingletonConfigurable):'
1978 1985
1979 1986 def _get_exc_info(self, exc_tuple=None):
1980 1987 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
1981
1988
1982 1989 Ensures sys.last_type,value,traceback hold the exc_info we found,
1983 1990 from whichever source.
1984
1991
1985 1992 raises ValueError if none of these contain any information
1986 1993 """
1987 1994 if exc_tuple is None:
@@ -1993,10 +2000,10 b' class InteractiveShell(SingletonConfigurable):'
1993 2000 if hasattr(sys, 'last_type'):
1994 2001 etype, value, tb = sys.last_type, sys.last_value, \
1995 2002 sys.last_traceback
1996
2003
1997 2004 if etype is None:
1998 2005 raise ValueError("No exception to find")
1999
2006
2000 2007 # Now store the exception info in sys.last_type etc.
2001 2008 # WARNING: these variables are somewhat deprecated and not
2002 2009 # necessarily safe to use in a threaded environment, but tools
@@ -2005,16 +2012,16 b' class InteractiveShell(SingletonConfigurable):'
2005 2012 sys.last_type = etype
2006 2013 sys.last_value = value
2007 2014 sys.last_traceback = tb
2008
2015
2009 2016 return etype, value, tb
2010
2017
2011 2018 def show_usage_error(self, exc):
2012 2019 """Show a short message for UsageErrors
2013
2020
2014 2021 These are special exceptions that shouldn't show a traceback.
2015 2022 """
2016 2023 print("UsageError: %s" % exc, file=sys.stderr)
2017
2024
2018 2025 def get_exception_only(self, exc_tuple=None):
2019 2026 """
2020 2027 Return as a string (ending with a newline) the exception that
@@ -2128,7 +2135,7 b' class InteractiveShell(SingletonConfigurable):'
2128 2135
2129 2136 def init_readline(self):
2130 2137 """DEPRECATED
2131
2138
2132 2139 Moved to terminal subclass, here only to simplify the init logic."""
2133 2140 # Set a number of methods that depend on readline to be no-op
2134 2141 warnings.warn('`init_readline` is no-op since IPython 5.0 and is Deprecated',
@@ -2295,12 +2302,13 b' class InteractiveShell(SingletonConfigurable):'
2295 2302 # should be split into a prompt manager and displayhook. We probably
2296 2303 # even need a centralize colors management object.
2297 2304 self.run_line_magic('colors', self.colors)
2298
2305
2299 2306 # Defined here so that it's included in the documentation
2300 2307 @functools.wraps(magic.MagicsManager.register_function)
2301 2308 def register_magic_function(self, func, magic_kind='line', magic_name=None):
2302 self.magics_manager.register_function(func,
2303 magic_kind=magic_kind, magic_name=magic_name)
2309 self.magics_manager.register_function(
2310 func, magic_kind=magic_kind, magic_name=magic_name
2311 )
2304 2312
2305 2313 def run_line_magic(self, magic_name, line, _stack_depth=1):
2306 2314 """Execute the given line magic.
@@ -2531,7 +2539,7 b' class InteractiveShell(SingletonConfigurable):'
2531 2539 ec = 130
2532 2540 if ec > 128:
2533 2541 ec = -(ec - 128)
2534
2542
2535 2543 # We explicitly do NOT return the subprocess status code, because
2536 2544 # a non-None value would trigger :func:`sys.displayhook` calls.
2537 2545 # Instead, we store the exit_code in user_ns. Note the semantics
@@ -2594,7 +2602,7 b' class InteractiveShell(SingletonConfigurable):'
2594 2602 def init_payload(self):
2595 2603 self.payload_manager = PayloadManager(parent=self)
2596 2604 self.configurables.append(self.payload_manager)
2597
2605
2598 2606 #-------------------------------------------------------------------------
2599 2607 # Things related to the prefilter
2600 2608 #-------------------------------------------------------------------------
@@ -2634,13 +2642,13 b' class InteractiveShell(SingletonConfigurable):'
2634 2642
2635 2643 def _user_obj_error(self):
2636 2644 """return simple exception dict
2637
2645
2638 2646 for use in user_expressions
2639 2647 """
2640
2648
2641 2649 etype, evalue, tb = self._get_exc_info()
2642 2650 stb = self.InteractiveTB.get_exception_only(etype, evalue)
2643
2651
2644 2652 exc_info = {
2645 2653 "status": "error",
2646 2654 "traceback": stb,
@@ -2649,13 +2657,13 b' class InteractiveShell(SingletonConfigurable):'
2649 2657 }
2650 2658
2651 2659 return exc_info
2652
2660
2653 2661 def _format_user_obj(self, obj):
2654 2662 """format a user object to display dict
2655
2663
2656 2664 for use in user_expressions
2657 2665 """
2658
2666
2659 2667 data, md = self.display_formatter.format(obj)
2660 2668 value = {
2661 2669 'status' : 'ok',
@@ -2663,7 +2671,7 b' class InteractiveShell(SingletonConfigurable):'
2663 2671 'metadata' : md,
2664 2672 }
2665 2673 return value
2666
2674
2667 2675 def user_expressions(self, expressions):
2668 2676 """Evaluate a dict of expressions in the user's namespace.
2669 2677
@@ -2682,7 +2690,7 b' class InteractiveShell(SingletonConfigurable):'
2682 2690 out = {}
2683 2691 user_ns = self.user_ns
2684 2692 global_ns = self.user_global_ns
2685
2693
2686 2694 for key, expr in expressions.items():
2687 2695 try:
2688 2696 value = self._format_user_obj(eval(expr, global_ns, user_ns))
@@ -3096,12 +3104,14 b' class InteractiveShell(SingletonConfigurable):'
3096 3104 # Our own compiler remembers the __future__ environment. If we want to
3097 3105 # run code with a separate __future__ environment, use the default
3098 3106 # compiler
3099 compiler = self.compile if shell_futures else CachingCompiler()
3107 compiler = self.compile if shell_futures else self.compiler_class()
3100 3108
3101 3109 _run_async = False
3102 3110
3103 3111 with self.builtin_trap:
3104 cell_name = self.compile.cache(cell, self.execution_count)
3112 cell_name = self.compile.cache(
3113 cell, self.execution_count, raw_code=raw_cell
3114 )
3105 3115
3106 3116 with self.display_trap:
3107 3117 # Compile to bytecode
@@ -3207,13 +3217,13 b' class InteractiveShell(SingletonConfigurable):'
3207 3217
3208 3218 def transform_ast(self, node):
3209 3219 """Apply the AST transformations from self.ast_transformers
3210
3220
3211 3221 Parameters
3212 3222 ----------
3213 3223 node : ast.Node
3214 3224 The root node to be transformed. Typically called with the ast.Module
3215 3225 produced by parsing user input.
3216
3226
3217 3227 Returns
3218 3228 -------
3219 3229 An ast.Node corresponding to the node it was called with. Note that it
@@ -3260,7 +3270,7 b' class InteractiveShell(SingletonConfigurable):'
3260 3270 Experimental value: 'async' Will try to run top level interactive
3261 3271 async/await code in default runner, this will not respect the
3262 3272 interactivity setting and will only run the last node if it is an
3263 expression.
3273 expression.
3264 3274
3265 3275 compiler : callable
3266 3276 A function with the same interface as the built-in compile(), to turn
@@ -3481,17 +3491,17 b' class InteractiveShell(SingletonConfigurable):'
3481 3491
3482 3492 def enable_gui(self, gui=None):
3483 3493 raise NotImplementedError('Implement enable_gui in a subclass')
3484
3494
3485 3495 def enable_matplotlib(self, gui=None):
3486 3496 """Enable interactive matplotlib and inline figure support.
3487
3497
3488 3498 This takes the following steps:
3489
3499
3490 3500 1. select the appropriate eventloop and matplotlib backend
3491 3501 2. set up matplotlib for interactive use with that backend
3492 3502 3. configure formatters for inline figure display
3493 3503 4. enable the selected gui eventloop
3494
3504
3495 3505 Parameters
3496 3506 ----------
3497 3507 gui : optional, string
@@ -3505,7 +3515,7 b' class InteractiveShell(SingletonConfigurable):'
3505 3515 """
3506 3516 from IPython.core import pylabtools as pt
3507 3517 gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select)
3508
3518
3509 3519 if gui != 'inline':
3510 3520 # If we have our first gui selection, store it
3511 3521 if self.pylab_gui_select is None:
@@ -3515,16 +3525,16 b' class InteractiveShell(SingletonConfigurable):'
3515 3525 print('Warning: Cannot change to a different GUI toolkit: %s.'
3516 3526 ' Using %s instead.' % (gui, self.pylab_gui_select))
3517 3527 gui, backend = pt.find_gui_and_backend(self.pylab_gui_select)
3518
3528
3519 3529 pt.activate_matplotlib(backend)
3520 3530 pt.configure_inline_support(self, backend)
3521
3531
3522 3532 # Now we must activate the gui pylab wants to use, and fix %run to take
3523 3533 # plot updates into account
3524 3534 self.enable_gui(gui)
3525 3535 self.magics_manager.registry['ExecutionMagics'].default_runner = \
3526 3536 pt.mpl_runner(self.safe_execfile)
3527
3537
3528 3538 return gui, backend
3529 3539
3530 3540 def enable_pylab(self, gui=None, import_all=True, welcome_message=False):
@@ -3534,7 +3544,7 b' class InteractiveShell(SingletonConfigurable):'
3534 3544 namespace all of numpy and pylab, and configures IPython to correctly
3535 3545 interact with the GUI event loop. The GUI backend to be used can be
3536 3546 optionally selected with the optional ``gui`` argument.
3537
3547
3538 3548 This method only adds preloading the namespace to InteractiveShell.enable_matplotlib.
3539 3549
3540 3550 Parameters
@@ -3554,9 +3564,9 b' class InteractiveShell(SingletonConfigurable):'
3554 3564 This argument is ignored, no welcome message will be displayed.
3555 3565 """
3556 3566 from IPython.core.pylabtools import import_pylab
3557
3567
3558 3568 gui, backend = self.enable_matplotlib(gui)
3559
3569
3560 3570 # We want to prevent the loading of pylab to pollute the user's
3561 3571 # namespace as shown by the %who* magics, so we execute the activation
3562 3572 # code in an empty namespace, and we update *both* user_ns and
General Comments 0
You need to be logged in to leave comments. Login now