##// END OF EJS Templates
Merge pull request #13520 from Carreau/main-tempfile-import...
Matthias Bussonnier -
r27548:6d40fd89 merge
parent child Browse files
Show More
@@ -1,3722 +1,3737 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Main IPython class."""
2 """Main IPython class."""
3
3
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13
13
14 import abc
14 import abc
15 import ast
15 import ast
16 import atexit
16 import atexit
17 import builtins as builtin_mod
17 import builtins as builtin_mod
18 import dis
18 import dis
19 import functools
19 import functools
20 import inspect
20 import inspect
21 import os
21 import os
22 import re
22 import re
23 import runpy
23 import runpy
24 import subprocess
24 import sys
25 import sys
25 import tempfile
26 import tempfile
26 import traceback
27 import traceback
27 import types
28 import types
28 import subprocess
29 import warnings
29 import warnings
30 from ast import stmt
30 from io import open as io_open
31 from io import open as io_open
31
32 from logging import error
32 from pathlib import Path
33 from pathlib import Path
33 from pickleshare import PickleShareDB
34 from typing import Callable
35 from typing import List as ListType
36 from typing import Optional, Tuple
37 from warnings import warn
34
38
39 from pickleshare import PickleShareDB
40 from tempfile import TemporaryDirectory
41 from traitlets import (
42 Any,
43 Bool,
44 CaselessStrEnum,
45 Dict,
46 Enum,
47 Instance,
48 Integer,
49 List,
50 Type,
51 Unicode,
52 default,
53 observe,
54 validate,
55 )
35 from traitlets.config.configurable import SingletonConfigurable
56 from traitlets.config.configurable import SingletonConfigurable
36 from traitlets.utils.importstring import import_item
57 from traitlets.utils.importstring import import_item
37 from IPython.core import oinspect
58
38 from IPython.core import magic
59 import IPython.core.hooks
39 from IPython.core import page
60 from IPython.core import magic, oinspect, page, prefilter, ultratb
40 from IPython.core import prefilter
41 from IPython.core import ultratb
42 from IPython.core.alias import Alias, AliasManager
61 from IPython.core.alias import Alias, AliasManager
43 from IPython.core.autocall import ExitAutocall
62 from IPython.core.autocall import ExitAutocall
44 from IPython.core.builtin_trap import BuiltinTrap
63 from IPython.core.builtin_trap import BuiltinTrap
45 from IPython.core.events import EventManager, available_events
46 from IPython.core.compilerop import CachingCompiler, check_linecache_ipython
64 from IPython.core.compilerop import CachingCompiler, check_linecache_ipython
47 from IPython.core.debugger import InterruptiblePdb
65 from IPython.core.debugger import InterruptiblePdb
48 from IPython.core.display_trap import DisplayTrap
66 from IPython.core.display_trap import DisplayTrap
49 from IPython.core.displayhook import DisplayHook
67 from IPython.core.displayhook import DisplayHook
50 from IPython.core.displaypub import DisplayPublisher
68 from IPython.core.displaypub import DisplayPublisher
51 from IPython.core.error import InputRejected, UsageError
69 from IPython.core.error import InputRejected, UsageError
70 from IPython.core.events import EventManager, available_events
52 from IPython.core.extensions import ExtensionManager
71 from IPython.core.extensions import ExtensionManager
53 from IPython.core.formatters import DisplayFormatter
72 from IPython.core.formatters import DisplayFormatter
54 from IPython.core.history import HistoryManager
73 from IPython.core.history import HistoryManager
55 from IPython.core.inputtransformer2 import ESC_MAGIC, ESC_MAGIC2
74 from IPython.core.inputtransformer2 import ESC_MAGIC, ESC_MAGIC2
56 from IPython.core.logger import Logger
75 from IPython.core.logger import Logger
57 from IPython.core.macro import Macro
76 from IPython.core.macro import Macro
58 from IPython.core.payload import PayloadManager
77 from IPython.core.payload import PayloadManager
59 from IPython.core.prefilter import PrefilterManager
78 from IPython.core.prefilter import PrefilterManager
60 from IPython.core.profiledir import ProfileDir
79 from IPython.core.profiledir import ProfileDir
61 from IPython.core.usage import default_banner
80 from IPython.core.usage import default_banner
62 from IPython.display import display
81 from IPython.display import display
82 from IPython.paths import get_ipython_dir
63 from IPython.testing.skipdoctest import skip_doctest
83 from IPython.testing.skipdoctest import skip_doctest
64 from IPython.utils import PyColorize
84 from IPython.utils import PyColorize, io, openpy, py3compat
65 from IPython.utils import io
66 from IPython.utils import py3compat
67 from IPython.utils import openpy
68 from IPython.utils.decorators import undoc
85 from IPython.utils.decorators import undoc
69 from IPython.utils.io import ask_yes_no
86 from IPython.utils.io import ask_yes_no
70 from IPython.utils.ipstruct import Struct
87 from IPython.utils.ipstruct import Struct
71 from IPython.paths import get_ipython_dir
88 from IPython.utils.path import ensure_dir_exists, get_home_dir, get_py_filename
72 from IPython.utils.path import get_home_dir, get_py_filename, ensure_dir_exists
89 from IPython.utils.process import getoutput, system
73 from IPython.utils.process import system, getoutput
74 from IPython.utils.strdispatch import StrDispatch
90 from IPython.utils.strdispatch import StrDispatch
75 from IPython.utils.syspathcontext import prepended_to_syspath
91 from IPython.utils.syspathcontext import prepended_to_syspath
76 from IPython.utils.text import format_screen, LSString, SList, DollarFormatter
92 from IPython.utils.text import DollarFormatter, LSString, SList, format_screen
77 from IPython.utils.tempdir import TemporaryDirectory
78 from traitlets import (
79 Integer, Bool, CaselessStrEnum, Enum, List, Dict, Unicode, Instance, Type,
80 observe, default, validate, Any
81 )
82 from warnings import warn
83 from logging import error
84 import IPython.core.hooks
85
86 from typing import List as ListType, Tuple, Optional, Callable
87 from ast import stmt
88
93
89 sphinxify: Optional[Callable]
94 sphinxify: Optional[Callable]
90
95
91 try:
96 try:
92 import docrepr.sphinxify as sphx
97 import docrepr.sphinxify as sphx
93
98
94 def sphinxify(oinfo):
99 def sphinxify(oinfo):
95 wrapped_docstring = sphx.wrap_main_docstring(oinfo)
100 wrapped_docstring = sphx.wrap_main_docstring(oinfo)
96
101
97 def sphinxify_docstring(docstring):
102 def sphinxify_docstring(docstring):
98 with TemporaryDirectory() as dirname:
103 with TemporaryDirectory() as dirname:
99 return {
104 return {
100 "text/html": sphx.sphinxify(wrapped_docstring, dirname),
105 "text/html": sphx.sphinxify(wrapped_docstring, dirname),
101 "text/plain": docstring,
106 "text/plain": docstring,
102 }
107 }
103
108
104 return sphinxify_docstring
109 return sphinxify_docstring
105 except ImportError:
110 except ImportError:
106 sphinxify = None
111 sphinxify = None
107
112
108
113
109 class ProvisionalWarning(DeprecationWarning):
114 class ProvisionalWarning(DeprecationWarning):
110 """
115 """
111 Warning class for unstable features
116 Warning class for unstable features
112 """
117 """
113 pass
118 pass
114
119
115 from ast import Module
120 from ast import Module
116
121
117 _assign_nodes = (ast.AugAssign, ast.AnnAssign, ast.Assign)
122 _assign_nodes = (ast.AugAssign, ast.AnnAssign, ast.Assign)
118 _single_targets_nodes = (ast.AugAssign, ast.AnnAssign)
123 _single_targets_nodes = (ast.AugAssign, ast.AnnAssign)
119
124
120 #-----------------------------------------------------------------------------
125 #-----------------------------------------------------------------------------
121 # Await Helpers
126 # Await Helpers
122 #-----------------------------------------------------------------------------
127 #-----------------------------------------------------------------------------
123
128
124 # we still need to run things using the asyncio eventloop, but there is no
129 # we still need to run things using the asyncio eventloop, but there is no
125 # async integration
130 # async integration
126 from .async_helpers import _asyncio_runner, _pseudo_sync_runner
131 from .async_helpers import (
127 from .async_helpers import _curio_runner, _trio_runner, _should_be_async
132 _asyncio_runner,
133 _curio_runner,
134 _pseudo_sync_runner,
135 _should_be_async,
136 _trio_runner,
137 )
128
138
129 #-----------------------------------------------------------------------------
139 #-----------------------------------------------------------------------------
130 # Globals
140 # Globals
131 #-----------------------------------------------------------------------------
141 #-----------------------------------------------------------------------------
132
142
133 # compiled regexps for autoindent management
143 # compiled regexps for autoindent management
134 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
144 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
135
145
136 #-----------------------------------------------------------------------------
146 #-----------------------------------------------------------------------------
137 # Utilities
147 # Utilities
138 #-----------------------------------------------------------------------------
148 #-----------------------------------------------------------------------------
139
149
140 @undoc
150 @undoc
141 def softspace(file, newvalue):
151 def softspace(file, newvalue):
142 """Copied from code.py, to remove the dependency"""
152 """Copied from code.py, to remove the dependency"""
143
153
144 oldvalue = 0
154 oldvalue = 0
145 try:
155 try:
146 oldvalue = file.softspace
156 oldvalue = file.softspace
147 except AttributeError:
157 except AttributeError:
148 pass
158 pass
149 try:
159 try:
150 file.softspace = newvalue
160 file.softspace = newvalue
151 except (AttributeError, TypeError):
161 except (AttributeError, TypeError):
152 # "attribute-less object" or "read-only attributes"
162 # "attribute-less object" or "read-only attributes"
153 pass
163 pass
154 return oldvalue
164 return oldvalue
155
165
156 @undoc
166 @undoc
157 def no_op(*a, **kw):
167 def no_op(*a, **kw):
158 pass
168 pass
159
169
160
170
161 class SpaceInInput(Exception): pass
171 class SpaceInInput(Exception): pass
162
172
163
173
164 class SeparateUnicode(Unicode):
174 class SeparateUnicode(Unicode):
165 r"""A Unicode subclass to validate separate_in, separate_out, etc.
175 r"""A Unicode subclass to validate separate_in, separate_out, etc.
166
176
167 This is a Unicode based trait that converts '0'->'' and ``'\\n'->'\n'``.
177 This is a Unicode based trait that converts '0'->'' and ``'\\n'->'\n'``.
168 """
178 """
169
179
170 def validate(self, obj, value):
180 def validate(self, obj, value):
171 if value == '0': value = ''
181 if value == '0': value = ''
172 value = value.replace('\\n','\n')
182 value = value.replace('\\n','\n')
173 return super(SeparateUnicode, self).validate(obj, value)
183 return super(SeparateUnicode, self).validate(obj, value)
174
184
175
185
176 @undoc
186 @undoc
177 class DummyMod(object):
187 class DummyMod(object):
178 """A dummy module used for IPython's interactive module when
188 """A dummy module used for IPython's interactive module when
179 a namespace must be assigned to the module's __dict__."""
189 a namespace must be assigned to the module's __dict__."""
180 __spec__ = None
190 __spec__ = None
181
191
182
192
183 class ExecutionInfo(object):
193 class ExecutionInfo(object):
184 """The arguments used for a call to :meth:`InteractiveShell.run_cell`
194 """The arguments used for a call to :meth:`InteractiveShell.run_cell`
185
195
186 Stores information about what is going to happen.
196 Stores information about what is going to happen.
187 """
197 """
188 raw_cell = None
198 raw_cell = None
189 store_history = False
199 store_history = False
190 silent = False
200 silent = False
191 shell_futures = True
201 shell_futures = True
192
202
193 def __init__(self, raw_cell, store_history, silent, shell_futures):
203 def __init__(self, raw_cell, store_history, silent, shell_futures):
194 self.raw_cell = raw_cell
204 self.raw_cell = raw_cell
195 self.store_history = store_history
205 self.store_history = store_history
196 self.silent = silent
206 self.silent = silent
197 self.shell_futures = shell_futures
207 self.shell_futures = shell_futures
198
208
199 def __repr__(self):
209 def __repr__(self):
200 name = self.__class__.__qualname__
210 name = self.__class__.__qualname__
201 raw_cell = ((self.raw_cell[:50] + '..')
211 raw_cell = ((self.raw_cell[:50] + '..')
202 if len(self.raw_cell) > 50 else self.raw_cell)
212 if len(self.raw_cell) > 50 else self.raw_cell)
203 return '<%s object at %x, raw_cell="%s" store_history=%s silent=%s shell_futures=%s>' %\
213 return '<%s object at %x, raw_cell="%s" store_history=%s silent=%s shell_futures=%s>' %\
204 (name, id(self), raw_cell, self.store_history, self.silent, self.shell_futures)
214 (name, id(self), raw_cell, self.store_history, self.silent, self.shell_futures)
205
215
206
216
207 class ExecutionResult(object):
217 class ExecutionResult(object):
208 """The result of a call to :meth:`InteractiveShell.run_cell`
218 """The result of a call to :meth:`InteractiveShell.run_cell`
209
219
210 Stores information about what took place.
220 Stores information about what took place.
211 """
221 """
212 execution_count = None
222 execution_count = None
213 error_before_exec = None
223 error_before_exec = None
214 error_in_exec: Optional[BaseException] = None
224 error_in_exec: Optional[BaseException] = None
215 info = None
225 info = None
216 result = None
226 result = None
217
227
218 def __init__(self, info):
228 def __init__(self, info):
219 self.info = info
229 self.info = info
220
230
221 @property
231 @property
222 def success(self):
232 def success(self):
223 return (self.error_before_exec is None) and (self.error_in_exec is None)
233 return (self.error_before_exec is None) and (self.error_in_exec is None)
224
234
225 def raise_error(self):
235 def raise_error(self):
226 """Reraises error if `success` is `False`, otherwise does nothing"""
236 """Reraises error if `success` is `False`, otherwise does nothing"""
227 if self.error_before_exec is not None:
237 if self.error_before_exec is not None:
228 raise self.error_before_exec
238 raise self.error_before_exec
229 if self.error_in_exec is not None:
239 if self.error_in_exec is not None:
230 raise self.error_in_exec
240 raise self.error_in_exec
231
241
232 def __repr__(self):
242 def __repr__(self):
233 name = self.__class__.__qualname__
243 name = self.__class__.__qualname__
234 return '<%s object at %x, execution_count=%s error_before_exec=%s error_in_exec=%s info=%s result=%s>' %\
244 return '<%s object at %x, execution_count=%s error_before_exec=%s error_in_exec=%s info=%s result=%s>' %\
235 (name, id(self), self.execution_count, self.error_before_exec, self.error_in_exec, repr(self.info), repr(self.result))
245 (name, id(self), self.execution_count, self.error_before_exec, self.error_in_exec, repr(self.info), repr(self.result))
236
246
237
247
238 class InteractiveShell(SingletonConfigurable):
248 class InteractiveShell(SingletonConfigurable):
239 """An enhanced, interactive shell for Python."""
249 """An enhanced, interactive shell for Python."""
240
250
241 _instance = None
251 _instance = None
242
252
243 ast_transformers = List([], help=
253 ast_transformers = List([], help=
244 """
254 """
245 A list of ast.NodeTransformer subclass instances, which will be applied
255 A list of ast.NodeTransformer subclass instances, which will be applied
246 to user input before code is run.
256 to user input before code is run.
247 """
257 """
248 ).tag(config=True)
258 ).tag(config=True)
249
259
250 autocall = Enum((0,1,2), default_value=0, help=
260 autocall = Enum((0,1,2), default_value=0, help=
251 """
261 """
252 Make IPython automatically call any callable object even if you didn't
262 Make IPython automatically call any callable object even if you didn't
253 type explicit parentheses. For example, 'str 43' becomes 'str(43)'
263 type explicit parentheses. For example, 'str 43' becomes 'str(43)'
254 automatically. The value can be '0' to disable the feature, '1' for
264 automatically. The value can be '0' to disable the feature, '1' for
255 'smart' autocall, where it is not applied if there are no more
265 'smart' autocall, where it is not applied if there are no more
256 arguments on the line, and '2' for 'full' autocall, where all callable
266 arguments on the line, and '2' for 'full' autocall, where all callable
257 objects are automatically called (even if no arguments are present).
267 objects are automatically called (even if no arguments are present).
258 """
268 """
259 ).tag(config=True)
269 ).tag(config=True)
260
270
261 autoindent = Bool(True, help=
271 autoindent = Bool(True, help=
262 """
272 """
263 Autoindent IPython code entered interactively.
273 Autoindent IPython code entered interactively.
264 """
274 """
265 ).tag(config=True)
275 ).tag(config=True)
266
276
267 autoawait = Bool(True, help=
277 autoawait = Bool(True, help=
268 """
278 """
269 Automatically run await statement in the top level repl.
279 Automatically run await statement in the top level repl.
270 """
280 """
271 ).tag(config=True)
281 ).tag(config=True)
272
282
273 loop_runner_map ={
283 loop_runner_map ={
274 'asyncio':(_asyncio_runner, True),
284 'asyncio':(_asyncio_runner, True),
275 'curio':(_curio_runner, True),
285 'curio':(_curio_runner, True),
276 'trio':(_trio_runner, True),
286 'trio':(_trio_runner, True),
277 'sync': (_pseudo_sync_runner, False)
287 'sync': (_pseudo_sync_runner, False)
278 }
288 }
279
289
280 loop_runner = Any(default_value="IPython.core.interactiveshell._asyncio_runner",
290 loop_runner = Any(default_value="IPython.core.interactiveshell._asyncio_runner",
281 allow_none=True,
291 allow_none=True,
282 help="""Select the loop runner that will be used to execute top-level asynchronous code"""
292 help="""Select the loop runner that will be used to execute top-level asynchronous code"""
283 ).tag(config=True)
293 ).tag(config=True)
284
294
285 @default('loop_runner')
295 @default('loop_runner')
286 def _default_loop_runner(self):
296 def _default_loop_runner(self):
287 return import_item("IPython.core.interactiveshell._asyncio_runner")
297 return import_item("IPython.core.interactiveshell._asyncio_runner")
288
298
289 @validate('loop_runner')
299 @validate('loop_runner')
290 def _import_runner(self, proposal):
300 def _import_runner(self, proposal):
291 if isinstance(proposal.value, str):
301 if isinstance(proposal.value, str):
292 if proposal.value in self.loop_runner_map:
302 if proposal.value in self.loop_runner_map:
293 runner, autoawait = self.loop_runner_map[proposal.value]
303 runner, autoawait = self.loop_runner_map[proposal.value]
294 self.autoawait = autoawait
304 self.autoawait = autoawait
295 return runner
305 return runner
296 runner = import_item(proposal.value)
306 runner = import_item(proposal.value)
297 if not callable(runner):
307 if not callable(runner):
298 raise ValueError('loop_runner must be callable')
308 raise ValueError('loop_runner must be callable')
299 return runner
309 return runner
300 if not callable(proposal.value):
310 if not callable(proposal.value):
301 raise ValueError('loop_runner must be callable')
311 raise ValueError('loop_runner must be callable')
302 return proposal.value
312 return proposal.value
303
313
304 automagic = Bool(True, help=
314 automagic = Bool(True, help=
305 """
315 """
306 Enable magic commands to be called without the leading %.
316 Enable magic commands to be called without the leading %.
307 """
317 """
308 ).tag(config=True)
318 ).tag(config=True)
309
319
310 banner1 = Unicode(default_banner,
320 banner1 = Unicode(default_banner,
311 help="""The part of the banner to be printed before the profile"""
321 help="""The part of the banner to be printed before the profile"""
312 ).tag(config=True)
322 ).tag(config=True)
313 banner2 = Unicode('',
323 banner2 = Unicode('',
314 help="""The part of the banner to be printed after the profile"""
324 help="""The part of the banner to be printed after the profile"""
315 ).tag(config=True)
325 ).tag(config=True)
316
326
317 cache_size = Integer(1000, help=
327 cache_size = Integer(1000, help=
318 """
328 """
319 Set the size of the output cache. The default is 1000, you can
329 Set the size of the output cache. The default is 1000, you can
320 change it permanently in your config file. Setting it to 0 completely
330 change it permanently in your config file. Setting it to 0 completely
321 disables the caching system, and the minimum value accepted is 3 (if
331 disables the caching system, and the minimum value accepted is 3 (if
322 you provide a value less than 3, it is reset to 0 and a warning is
332 you provide a value less than 3, it is reset to 0 and a warning is
323 issued). This limit is defined because otherwise you'll spend more
333 issued). This limit is defined because otherwise you'll spend more
324 time re-flushing a too small cache than working
334 time re-flushing a too small cache than working
325 """
335 """
326 ).tag(config=True)
336 ).tag(config=True)
327 color_info = Bool(True, help=
337 color_info = Bool(True, help=
328 """
338 """
329 Use colors for displaying information about objects. Because this
339 Use colors for displaying information about objects. Because this
330 information is passed through a pager (like 'less'), and some pagers
340 information is passed through a pager (like 'less'), and some pagers
331 get confused with color codes, this capability can be turned off.
341 get confused with color codes, this capability can be turned off.
332 """
342 """
333 ).tag(config=True)
343 ).tag(config=True)
334 colors = CaselessStrEnum(('Neutral', 'NoColor','LightBG','Linux'),
344 colors = CaselessStrEnum(('Neutral', 'NoColor','LightBG','Linux'),
335 default_value='Neutral',
345 default_value='Neutral',
336 help="Set the color scheme (NoColor, Neutral, Linux, or LightBG)."
346 help="Set the color scheme (NoColor, Neutral, Linux, or LightBG)."
337 ).tag(config=True)
347 ).tag(config=True)
338 debug = Bool(False).tag(config=True)
348 debug = Bool(False).tag(config=True)
339 disable_failing_post_execute = Bool(False,
349 disable_failing_post_execute = Bool(False,
340 help="Don't call post-execute functions that have failed in the past."
350 help="Don't call post-execute functions that have failed in the past."
341 ).tag(config=True)
351 ).tag(config=True)
342 display_formatter = Instance(DisplayFormatter, allow_none=True)
352 display_formatter = Instance(DisplayFormatter, allow_none=True)
343 displayhook_class = Type(DisplayHook)
353 displayhook_class = Type(DisplayHook)
344 display_pub_class = Type(DisplayPublisher)
354 display_pub_class = Type(DisplayPublisher)
345 compiler_class = Type(CachingCompiler)
355 compiler_class = Type(CachingCompiler)
346
356
347 sphinxify_docstring = Bool(False, help=
357 sphinxify_docstring = Bool(False, help=
348 """
358 """
349 Enables rich html representation of docstrings. (This requires the
359 Enables rich html representation of docstrings. (This requires the
350 docrepr module).
360 docrepr module).
351 """).tag(config=True)
361 """).tag(config=True)
352
362
353 @observe("sphinxify_docstring")
363 @observe("sphinxify_docstring")
354 def _sphinxify_docstring_changed(self, change):
364 def _sphinxify_docstring_changed(self, change):
355 if change['new']:
365 if change['new']:
356 warn("`sphinxify_docstring` is provisional since IPython 5.0 and might change in future versions." , ProvisionalWarning)
366 warn("`sphinxify_docstring` is provisional since IPython 5.0 and might change in future versions." , ProvisionalWarning)
357
367
358 enable_html_pager = Bool(False, help=
368 enable_html_pager = Bool(False, help=
359 """
369 """
360 (Provisional API) enables html representation in mime bundles sent
370 (Provisional API) enables html representation in mime bundles sent
361 to pagers.
371 to pagers.
362 """).tag(config=True)
372 """).tag(config=True)
363
373
364 @observe("enable_html_pager")
374 @observe("enable_html_pager")
365 def _enable_html_pager_changed(self, change):
375 def _enable_html_pager_changed(self, change):
366 if change['new']:
376 if change['new']:
367 warn("`enable_html_pager` is provisional since IPython 5.0 and might change in future versions.", ProvisionalWarning)
377 warn("`enable_html_pager` is provisional since IPython 5.0 and might change in future versions.", ProvisionalWarning)
368
378
369 data_pub_class = None
379 data_pub_class = None
370
380
371 exit_now = Bool(False)
381 exit_now = Bool(False)
372 exiter = Instance(ExitAutocall)
382 exiter = Instance(ExitAutocall)
373 @default('exiter')
383 @default('exiter')
374 def _exiter_default(self):
384 def _exiter_default(self):
375 return ExitAutocall(self)
385 return ExitAutocall(self)
376 # Monotonically increasing execution counter
386 # Monotonically increasing execution counter
377 execution_count = Integer(1)
387 execution_count = Integer(1)
378 filename = Unicode("<ipython console>")
388 filename = Unicode("<ipython console>")
379 ipython_dir= Unicode('').tag(config=True) # Set to get_ipython_dir() in __init__
389 ipython_dir= Unicode('').tag(config=True) # Set to get_ipython_dir() in __init__
380
390
381 # Used to transform cells before running them, and check whether code is complete
391 # Used to transform cells before running them, and check whether code is complete
382 input_transformer_manager = Instance('IPython.core.inputtransformer2.TransformerManager',
392 input_transformer_manager = Instance('IPython.core.inputtransformer2.TransformerManager',
383 ())
393 ())
384
394
385 @property
395 @property
386 def input_transformers_cleanup(self):
396 def input_transformers_cleanup(self):
387 return self.input_transformer_manager.cleanup_transforms
397 return self.input_transformer_manager.cleanup_transforms
388
398
389 input_transformers_post = List([],
399 input_transformers_post = List([],
390 help="A list of string input transformers, to be applied after IPython's "
400 help="A list of string input transformers, to be applied after IPython's "
391 "own input transformations."
401 "own input transformations."
392 )
402 )
393
403
394 @property
404 @property
395 def input_splitter(self):
405 def input_splitter(self):
396 """Make this available for backward compatibility (pre-7.0 release) with existing code.
406 """Make this available for backward compatibility (pre-7.0 release) with existing code.
397
407
398 For example, ipykernel ipykernel currently uses
408 For example, ipykernel ipykernel currently uses
399 `shell.input_splitter.check_complete`
409 `shell.input_splitter.check_complete`
400 """
410 """
401 from warnings import warn
411 from warnings import warn
402 warn("`input_splitter` is deprecated since IPython 7.0, prefer `input_transformer_manager`.",
412 warn("`input_splitter` is deprecated since IPython 7.0, prefer `input_transformer_manager`.",
403 DeprecationWarning, stacklevel=2
413 DeprecationWarning, stacklevel=2
404 )
414 )
405 return self.input_transformer_manager
415 return self.input_transformer_manager
406
416
407 logstart = Bool(False, help=
417 logstart = Bool(False, help=
408 """
418 """
409 Start logging to the default log file in overwrite mode.
419 Start logging to the default log file in overwrite mode.
410 Use `logappend` to specify a log file to **append** logs to.
420 Use `logappend` to specify a log file to **append** logs to.
411 """
421 """
412 ).tag(config=True)
422 ).tag(config=True)
413 logfile = Unicode('', help=
423 logfile = Unicode('', help=
414 """
424 """
415 The name of the logfile to use.
425 The name of the logfile to use.
416 """
426 """
417 ).tag(config=True)
427 ).tag(config=True)
418 logappend = Unicode('', help=
428 logappend = Unicode('', help=
419 """
429 """
420 Start logging to the given file in append mode.
430 Start logging to the given file in append mode.
421 Use `logfile` to specify a log file to **overwrite** logs to.
431 Use `logfile` to specify a log file to **overwrite** logs to.
422 """
432 """
423 ).tag(config=True)
433 ).tag(config=True)
424 object_info_string_level = Enum((0,1,2), default_value=0,
434 object_info_string_level = Enum((0,1,2), default_value=0,
425 ).tag(config=True)
435 ).tag(config=True)
426 pdb = Bool(False, help=
436 pdb = Bool(False, help=
427 """
437 """
428 Automatically call the pdb debugger after every exception.
438 Automatically call the pdb debugger after every exception.
429 """
439 """
430 ).tag(config=True)
440 ).tag(config=True)
431 display_page = Bool(False,
441 display_page = Bool(False,
432 help="""If True, anything that would be passed to the pager
442 help="""If True, anything that would be passed to the pager
433 will be displayed as regular output instead."""
443 will be displayed as regular output instead."""
434 ).tag(config=True)
444 ).tag(config=True)
435
445
436
446
437 show_rewritten_input = Bool(True,
447 show_rewritten_input = Bool(True,
438 help="Show rewritten input, e.g. for autocall."
448 help="Show rewritten input, e.g. for autocall."
439 ).tag(config=True)
449 ).tag(config=True)
440
450
441 quiet = Bool(False).tag(config=True)
451 quiet = Bool(False).tag(config=True)
442
452
443 history_length = Integer(10000,
453 history_length = Integer(10000,
444 help='Total length of command history'
454 help='Total length of command history'
445 ).tag(config=True)
455 ).tag(config=True)
446
456
447 history_load_length = Integer(1000, help=
457 history_load_length = Integer(1000, help=
448 """
458 """
449 The number of saved history entries to be loaded
459 The number of saved history entries to be loaded
450 into the history buffer at startup.
460 into the history buffer at startup.
451 """
461 """
452 ).tag(config=True)
462 ).tag(config=True)
453
463
454 ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none', 'last_expr_or_assign'],
464 ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none', 'last_expr_or_assign'],
455 default_value='last_expr',
465 default_value='last_expr',
456 help="""
466 help="""
457 'all', 'last', 'last_expr' or 'none', 'last_expr_or_assign' specifying
467 'all', 'last', 'last_expr' or 'none', 'last_expr_or_assign' specifying
458 which nodes should be run interactively (displaying output from expressions).
468 which nodes should be run interactively (displaying output from expressions).
459 """
469 """
460 ).tag(config=True)
470 ).tag(config=True)
461
471
462 # TODO: this part of prompt management should be moved to the frontends.
472 # TODO: this part of prompt management should be moved to the frontends.
463 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
473 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
464 separate_in = SeparateUnicode('\n').tag(config=True)
474 separate_in = SeparateUnicode('\n').tag(config=True)
465 separate_out = SeparateUnicode('').tag(config=True)
475 separate_out = SeparateUnicode('').tag(config=True)
466 separate_out2 = SeparateUnicode('').tag(config=True)
476 separate_out2 = SeparateUnicode('').tag(config=True)
467 wildcards_case_sensitive = Bool(True).tag(config=True)
477 wildcards_case_sensitive = Bool(True).tag(config=True)
468 xmode = CaselessStrEnum(('Context', 'Plain', 'Verbose', 'Minimal'),
478 xmode = CaselessStrEnum(('Context', 'Plain', 'Verbose', 'Minimal'),
469 default_value='Context',
479 default_value='Context',
470 help="Switch modes for the IPython exception handlers."
480 help="Switch modes for the IPython exception handlers."
471 ).tag(config=True)
481 ).tag(config=True)
472
482
473 # Subcomponents of InteractiveShell
483 # Subcomponents of InteractiveShell
474 alias_manager = Instance('IPython.core.alias.AliasManager', allow_none=True)
484 alias_manager = Instance('IPython.core.alias.AliasManager', allow_none=True)
475 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
485 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
476 builtin_trap = Instance('IPython.core.builtin_trap.BuiltinTrap', allow_none=True)
486 builtin_trap = Instance('IPython.core.builtin_trap.BuiltinTrap', allow_none=True)
477 display_trap = Instance('IPython.core.display_trap.DisplayTrap', allow_none=True)
487 display_trap = Instance('IPython.core.display_trap.DisplayTrap', allow_none=True)
478 extension_manager = Instance('IPython.core.extensions.ExtensionManager', allow_none=True)
488 extension_manager = Instance('IPython.core.extensions.ExtensionManager', allow_none=True)
479 payload_manager = Instance('IPython.core.payload.PayloadManager', allow_none=True)
489 payload_manager = Instance('IPython.core.payload.PayloadManager', allow_none=True)
480 history_manager = Instance('IPython.core.history.HistoryAccessorBase', allow_none=True)
490 history_manager = Instance('IPython.core.history.HistoryAccessorBase', allow_none=True)
481 magics_manager = Instance('IPython.core.magic.MagicsManager', allow_none=True)
491 magics_manager = Instance('IPython.core.magic.MagicsManager', allow_none=True)
482
492
483 profile_dir = Instance('IPython.core.application.ProfileDir', allow_none=True)
493 profile_dir = Instance('IPython.core.application.ProfileDir', allow_none=True)
484 @property
494 @property
485 def profile(self):
495 def profile(self):
486 if self.profile_dir is not None:
496 if self.profile_dir is not None:
487 name = os.path.basename(self.profile_dir.location)
497 name = os.path.basename(self.profile_dir.location)
488 return name.replace('profile_','')
498 return name.replace('profile_','')
489
499
490
500
491 # Private interface
501 # Private interface
492 _post_execute = Dict()
502 _post_execute = Dict()
493
503
494 # Tracks any GUI loop loaded for pylab
504 # Tracks any GUI loop loaded for pylab
495 pylab_gui_select = None
505 pylab_gui_select = None
496
506
497 last_execution_succeeded = Bool(True, help='Did last executed command succeeded')
507 last_execution_succeeded = Bool(True, help='Did last executed command succeeded')
498
508
499 last_execution_result = Instance('IPython.core.interactiveshell.ExecutionResult', help='Result of executing the last command', allow_none=True)
509 last_execution_result = Instance('IPython.core.interactiveshell.ExecutionResult', help='Result of executing the last command', allow_none=True)
500
510
501 def __init__(self, ipython_dir=None, profile_dir=None,
511 def __init__(self, ipython_dir=None, profile_dir=None,
502 user_module=None, user_ns=None,
512 user_module=None, user_ns=None,
503 custom_exceptions=((), None), **kwargs):
513 custom_exceptions=((), None), **kwargs):
504 # This is where traits with a config_key argument are updated
514 # This is where traits with a config_key argument are updated
505 # from the values on config.
515 # from the values on config.
506 super(InteractiveShell, self).__init__(**kwargs)
516 super(InteractiveShell, self).__init__(**kwargs)
507 if 'PromptManager' in self.config:
517 if 'PromptManager' in self.config:
508 warn('As of IPython 5.0 `PromptManager` config will have no effect'
518 warn('As of IPython 5.0 `PromptManager` config will have no effect'
509 ' and has been replaced by TerminalInteractiveShell.prompts_class')
519 ' and has been replaced by TerminalInteractiveShell.prompts_class')
510 self.configurables = [self]
520 self.configurables = [self]
511
521
512 # These are relatively independent and stateless
522 # These are relatively independent and stateless
513 self.init_ipython_dir(ipython_dir)
523 self.init_ipython_dir(ipython_dir)
514 self.init_profile_dir(profile_dir)
524 self.init_profile_dir(profile_dir)
515 self.init_instance_attrs()
525 self.init_instance_attrs()
516 self.init_environment()
526 self.init_environment()
517
527
518 # Check if we're in a virtualenv, and set up sys.path.
528 # Check if we're in a virtualenv, and set up sys.path.
519 self.init_virtualenv()
529 self.init_virtualenv()
520
530
521 # Create namespaces (user_ns, user_global_ns, etc.)
531 # Create namespaces (user_ns, user_global_ns, etc.)
522 self.init_create_namespaces(user_module, user_ns)
532 self.init_create_namespaces(user_module, user_ns)
523 # This has to be done after init_create_namespaces because it uses
533 # This has to be done after init_create_namespaces because it uses
524 # something in self.user_ns, but before init_sys_modules, which
534 # something in self.user_ns, but before init_sys_modules, which
525 # is the first thing to modify sys.
535 # is the first thing to modify sys.
526 # TODO: When we override sys.stdout and sys.stderr before this class
536 # TODO: When we override sys.stdout and sys.stderr before this class
527 # is created, we are saving the overridden ones here. Not sure if this
537 # is created, we are saving the overridden ones here. Not sure if this
528 # is what we want to do.
538 # is what we want to do.
529 self.save_sys_module_state()
539 self.save_sys_module_state()
530 self.init_sys_modules()
540 self.init_sys_modules()
531
541
532 # While we're trying to have each part of the code directly access what
542 # While we're trying to have each part of the code directly access what
533 # it needs without keeping redundant references to objects, we have too
543 # it needs without keeping redundant references to objects, we have too
534 # much legacy code that expects ip.db to exist.
544 # much legacy code that expects ip.db to exist.
535 self.db = PickleShareDB(os.path.join(self.profile_dir.location, 'db'))
545 self.db = PickleShareDB(os.path.join(self.profile_dir.location, 'db'))
536
546
537 self.init_history()
547 self.init_history()
538 self.init_encoding()
548 self.init_encoding()
539 self.init_prefilter()
549 self.init_prefilter()
540
550
541 self.init_syntax_highlighting()
551 self.init_syntax_highlighting()
542 self.init_hooks()
552 self.init_hooks()
543 self.init_events()
553 self.init_events()
544 self.init_pushd_popd_magic()
554 self.init_pushd_popd_magic()
545 self.init_user_ns()
555 self.init_user_ns()
546 self.init_logger()
556 self.init_logger()
547 self.init_builtins()
557 self.init_builtins()
548
558
549 # The following was in post_config_initialization
559 # The following was in post_config_initialization
550 self.init_inspector()
560 self.init_inspector()
551 self.raw_input_original = input
561 self.raw_input_original = input
552 self.init_completer()
562 self.init_completer()
553 # TODO: init_io() needs to happen before init_traceback handlers
563 # TODO: init_io() needs to happen before init_traceback handlers
554 # because the traceback handlers hardcode the stdout/stderr streams.
564 # because the traceback handlers hardcode the stdout/stderr streams.
555 # This logic in in debugger.Pdb and should eventually be changed.
565 # This logic in in debugger.Pdb and should eventually be changed.
556 self.init_io()
566 self.init_io()
557 self.init_traceback_handlers(custom_exceptions)
567 self.init_traceback_handlers(custom_exceptions)
558 self.init_prompts()
568 self.init_prompts()
559 self.init_display_formatter()
569 self.init_display_formatter()
560 self.init_display_pub()
570 self.init_display_pub()
561 self.init_data_pub()
571 self.init_data_pub()
562 self.init_displayhook()
572 self.init_displayhook()
563 self.init_magics()
573 self.init_magics()
564 self.init_alias()
574 self.init_alias()
565 self.init_logstart()
575 self.init_logstart()
566 self.init_pdb()
576 self.init_pdb()
567 self.init_extension_manager()
577 self.init_extension_manager()
568 self.init_payload()
578 self.init_payload()
569 self.events.trigger('shell_initialized', self)
579 self.events.trigger('shell_initialized', self)
570 atexit.register(self.atexit_operations)
580 atexit.register(self.atexit_operations)
571
581
572 # The trio runner is used for running Trio in the foreground thread. It
582 # The trio runner is used for running Trio in the foreground thread. It
573 # is different from `_trio_runner(async_fn)` in `async_helpers.py`
583 # is different from `_trio_runner(async_fn)` in `async_helpers.py`
574 # which calls `trio.run()` for every cell. This runner runs all cells
584 # which calls `trio.run()` for every cell. This runner runs all cells
575 # inside a single Trio event loop. If used, it is set from
585 # inside a single Trio event loop. If used, it is set from
576 # `ipykernel.kernelapp`.
586 # `ipykernel.kernelapp`.
577 self.trio_runner = None
587 self.trio_runner = None
578
588
579 def get_ipython(self):
589 def get_ipython(self):
580 """Return the currently running IPython instance."""
590 """Return the currently running IPython instance."""
581 return self
591 return self
582
592
583 #-------------------------------------------------------------------------
593 #-------------------------------------------------------------------------
584 # Trait changed handlers
594 # Trait changed handlers
585 #-------------------------------------------------------------------------
595 #-------------------------------------------------------------------------
586 @observe('ipython_dir')
596 @observe('ipython_dir')
587 def _ipython_dir_changed(self, change):
597 def _ipython_dir_changed(self, change):
588 ensure_dir_exists(change['new'])
598 ensure_dir_exists(change['new'])
589
599
590 def set_autoindent(self,value=None):
600 def set_autoindent(self,value=None):
591 """Set the autoindent flag.
601 """Set the autoindent flag.
592
602
593 If called with no arguments, it acts as a toggle."""
603 If called with no arguments, it acts as a toggle."""
594 if value is None:
604 if value is None:
595 self.autoindent = not self.autoindent
605 self.autoindent = not self.autoindent
596 else:
606 else:
597 self.autoindent = value
607 self.autoindent = value
598
608
599 def set_trio_runner(self, tr):
609 def set_trio_runner(self, tr):
600 self.trio_runner = tr
610 self.trio_runner = tr
601
611
602 #-------------------------------------------------------------------------
612 #-------------------------------------------------------------------------
603 # init_* methods called by __init__
613 # init_* methods called by __init__
604 #-------------------------------------------------------------------------
614 #-------------------------------------------------------------------------
605
615
606 def init_ipython_dir(self, ipython_dir):
616 def init_ipython_dir(self, ipython_dir):
607 if ipython_dir is not None:
617 if ipython_dir is not None:
608 self.ipython_dir = ipython_dir
618 self.ipython_dir = ipython_dir
609 return
619 return
610
620
611 self.ipython_dir = get_ipython_dir()
621 self.ipython_dir = get_ipython_dir()
612
622
613 def init_profile_dir(self, profile_dir):
623 def init_profile_dir(self, profile_dir):
614 if profile_dir is not None:
624 if profile_dir is not None:
615 self.profile_dir = profile_dir
625 self.profile_dir = profile_dir
616 return
626 return
617 self.profile_dir = ProfileDir.create_profile_dir_by_name(
627 self.profile_dir = ProfileDir.create_profile_dir_by_name(
618 self.ipython_dir, "default"
628 self.ipython_dir, "default"
619 )
629 )
620
630
621 def init_instance_attrs(self):
631 def init_instance_attrs(self):
622 self.more = False
632 self.more = False
623
633
624 # command compiler
634 # command compiler
625 self.compile = self.compiler_class()
635 self.compile = self.compiler_class()
626
636
627 # Make an empty namespace, which extension writers can rely on both
637 # Make an empty namespace, which extension writers can rely on both
628 # existing and NEVER being used by ipython itself. This gives them a
638 # existing and NEVER being used by ipython itself. This gives them a
629 # convenient location for storing additional information and state
639 # convenient location for storing additional information and state
630 # their extensions may require, without fear of collisions with other
640 # their extensions may require, without fear of collisions with other
631 # ipython names that may develop later.
641 # ipython names that may develop later.
632 self.meta = Struct()
642 self.meta = Struct()
633
643
634 # Temporary files used for various purposes. Deleted at exit.
644 # Temporary files used for various purposes. Deleted at exit.
635 # The files here are stored with Path from Pathlib
645 # The files here are stored with Path from Pathlib
636 self.tempfiles = []
646 self.tempfiles = []
637 self.tempdirs = []
647 self.tempdirs = []
638
648
639 # keep track of where we started running (mainly for crash post-mortem)
649 # keep track of where we started running (mainly for crash post-mortem)
640 # This is not being used anywhere currently.
650 # This is not being used anywhere currently.
641 self.starting_dir = os.getcwd()
651 self.starting_dir = os.getcwd()
642
652
643 # Indentation management
653 # Indentation management
644 self.indent_current_nsp = 0
654 self.indent_current_nsp = 0
645
655
646 # Dict to track post-execution functions that have been registered
656 # Dict to track post-execution functions that have been registered
647 self._post_execute = {}
657 self._post_execute = {}
648
658
649 def init_environment(self):
659 def init_environment(self):
650 """Any changes we need to make to the user's environment."""
660 """Any changes we need to make to the user's environment."""
651 pass
661 pass
652
662
653 def init_encoding(self):
663 def init_encoding(self):
654 # Get system encoding at startup time. Certain terminals (like Emacs
664 # Get system encoding at startup time. Certain terminals (like Emacs
655 # under Win32 have it set to None, and we need to have a known valid
665 # under Win32 have it set to None, and we need to have a known valid
656 # encoding to use in the raw_input() method
666 # encoding to use in the raw_input() method
657 try:
667 try:
658 self.stdin_encoding = sys.stdin.encoding or 'ascii'
668 self.stdin_encoding = sys.stdin.encoding or 'ascii'
659 except AttributeError:
669 except AttributeError:
660 self.stdin_encoding = 'ascii'
670 self.stdin_encoding = 'ascii'
661
671
662
672
663 @observe('colors')
673 @observe('colors')
664 def init_syntax_highlighting(self, changes=None):
674 def init_syntax_highlighting(self, changes=None):
665 # Python source parser/formatter for syntax highlighting
675 # Python source parser/formatter for syntax highlighting
666 pyformat = PyColorize.Parser(style=self.colors, parent=self).format
676 pyformat = PyColorize.Parser(style=self.colors, parent=self).format
667 self.pycolorize = lambda src: pyformat(src,'str')
677 self.pycolorize = lambda src: pyformat(src,'str')
668
678
669 def refresh_style(self):
679 def refresh_style(self):
670 # No-op here, used in subclass
680 # No-op here, used in subclass
671 pass
681 pass
672
682
673 def init_pushd_popd_magic(self):
683 def init_pushd_popd_magic(self):
674 # for pushd/popd management
684 # for pushd/popd management
675 self.home_dir = get_home_dir()
685 self.home_dir = get_home_dir()
676
686
677 self.dir_stack = []
687 self.dir_stack = []
678
688
679 def init_logger(self):
689 def init_logger(self):
680 self.logger = Logger(self.home_dir, logfname='ipython_log.py',
690 self.logger = Logger(self.home_dir, logfname='ipython_log.py',
681 logmode='rotate')
691 logmode='rotate')
682
692
683 def init_logstart(self):
693 def init_logstart(self):
684 """Initialize logging in case it was requested at the command line.
694 """Initialize logging in case it was requested at the command line.
685 """
695 """
686 if self.logappend:
696 if self.logappend:
687 self.magic('logstart %s append' % self.logappend)
697 self.magic('logstart %s append' % self.logappend)
688 elif self.logfile:
698 elif self.logfile:
689 self.magic('logstart %s' % self.logfile)
699 self.magic('logstart %s' % self.logfile)
690 elif self.logstart:
700 elif self.logstart:
691 self.magic('logstart')
701 self.magic('logstart')
692
702
693
703
694 def init_builtins(self):
704 def init_builtins(self):
695 # A single, static flag that we set to True. Its presence indicates
705 # A single, static flag that we set to True. Its presence indicates
696 # that an IPython shell has been created, and we make no attempts at
706 # that an IPython shell has been created, and we make no attempts at
697 # removing on exit or representing the existence of more than one
707 # removing on exit or representing the existence of more than one
698 # IPython at a time.
708 # IPython at a time.
699 builtin_mod.__dict__['__IPYTHON__'] = True
709 builtin_mod.__dict__['__IPYTHON__'] = True
700 builtin_mod.__dict__['display'] = display
710 builtin_mod.__dict__['display'] = display
701
711
702 self.builtin_trap = BuiltinTrap(shell=self)
712 self.builtin_trap = BuiltinTrap(shell=self)
703
713
704 @observe('colors')
714 @observe('colors')
705 def init_inspector(self, changes=None):
715 def init_inspector(self, changes=None):
706 # Object inspector
716 # Object inspector
707 self.inspector = oinspect.Inspector(oinspect.InspectColors,
717 self.inspector = oinspect.Inspector(oinspect.InspectColors,
708 PyColorize.ANSICodeColors,
718 PyColorize.ANSICodeColors,
709 self.colors,
719 self.colors,
710 self.object_info_string_level)
720 self.object_info_string_level)
711
721
712 def init_io(self):
722 def init_io(self):
713 # implemented in subclasses, TerminalInteractiveShell does call
723 # implemented in subclasses, TerminalInteractiveShell does call
714 # colorama.init().
724 # colorama.init().
715 pass
725 pass
716
726
717 def init_prompts(self):
727 def init_prompts(self):
718 # Set system prompts, so that scripts can decide if they are running
728 # Set system prompts, so that scripts can decide if they are running
719 # interactively.
729 # interactively.
720 sys.ps1 = 'In : '
730 sys.ps1 = 'In : '
721 sys.ps2 = '...: '
731 sys.ps2 = '...: '
722 sys.ps3 = 'Out: '
732 sys.ps3 = 'Out: '
723
733
724 def init_display_formatter(self):
734 def init_display_formatter(self):
725 self.display_formatter = DisplayFormatter(parent=self)
735 self.display_formatter = DisplayFormatter(parent=self)
726 self.configurables.append(self.display_formatter)
736 self.configurables.append(self.display_formatter)
727
737
728 def init_display_pub(self):
738 def init_display_pub(self):
729 self.display_pub = self.display_pub_class(parent=self, shell=self)
739 self.display_pub = self.display_pub_class(parent=self, shell=self)
730 self.configurables.append(self.display_pub)
740 self.configurables.append(self.display_pub)
731
741
732 def init_data_pub(self):
742 def init_data_pub(self):
733 if not self.data_pub_class:
743 if not self.data_pub_class:
734 self.data_pub = None
744 self.data_pub = None
735 return
745 return
736 self.data_pub = self.data_pub_class(parent=self)
746 self.data_pub = self.data_pub_class(parent=self)
737 self.configurables.append(self.data_pub)
747 self.configurables.append(self.data_pub)
738
748
739 def init_displayhook(self):
749 def init_displayhook(self):
740 # Initialize displayhook, set in/out prompts and printing system
750 # Initialize displayhook, set in/out prompts and printing system
741 self.displayhook = self.displayhook_class(
751 self.displayhook = self.displayhook_class(
742 parent=self,
752 parent=self,
743 shell=self,
753 shell=self,
744 cache_size=self.cache_size,
754 cache_size=self.cache_size,
745 )
755 )
746 self.configurables.append(self.displayhook)
756 self.configurables.append(self.displayhook)
747 # This is a context manager that installs/revmoes the displayhook at
757 # This is a context manager that installs/revmoes the displayhook at
748 # the appropriate time.
758 # the appropriate time.
749 self.display_trap = DisplayTrap(hook=self.displayhook)
759 self.display_trap = DisplayTrap(hook=self.displayhook)
750
760
751 def init_virtualenv(self):
761 def init_virtualenv(self):
752 """Add the current virtualenv to sys.path so the user can import modules from it.
762 """Add the current virtualenv to sys.path so the user can import modules from it.
753 This isn't perfect: it doesn't use the Python interpreter with which the
763 This isn't perfect: it doesn't use the Python interpreter with which the
754 virtualenv was built, and it ignores the --no-site-packages option. A
764 virtualenv was built, and it ignores the --no-site-packages option. A
755 warning will appear suggesting the user installs IPython in the
765 warning will appear suggesting the user installs IPython in the
756 virtualenv, but for many cases, it probably works well enough.
766 virtualenv, but for many cases, it probably works well enough.
757
767
758 Adapted from code snippets online.
768 Adapted from code snippets online.
759
769
760 http://blog.ufsoft.org/2009/1/29/ipython-and-virtualenv
770 http://blog.ufsoft.org/2009/1/29/ipython-and-virtualenv
761 """
771 """
762 if 'VIRTUAL_ENV' not in os.environ:
772 if 'VIRTUAL_ENV' not in os.environ:
763 # Not in a virtualenv
773 # Not in a virtualenv
764 return
774 return
765 elif os.environ["VIRTUAL_ENV"] == "":
775 elif os.environ["VIRTUAL_ENV"] == "":
766 warn("Virtual env path set to '', please check if this is intended.")
776 warn("Virtual env path set to '', please check if this is intended.")
767 return
777 return
768
778
769 p = Path(sys.executable)
779 p = Path(sys.executable)
770 p_venv = Path(os.environ["VIRTUAL_ENV"])
780 p_venv = Path(os.environ["VIRTUAL_ENV"])
771
781
772 # fallback venv detection:
782 # fallback venv detection:
773 # stdlib venv may symlink sys.executable, so we can't use realpath.
783 # stdlib venv may symlink sys.executable, so we can't use realpath.
774 # but others can symlink *to* the venv Python, so we can't just use sys.executable.
784 # but others can symlink *to* the venv Python, so we can't just use sys.executable.
775 # So we just check every item in the symlink tree (generally <= 3)
785 # So we just check every item in the symlink tree (generally <= 3)
776 paths = [p]
786 paths = [p]
777 while p.is_symlink():
787 while p.is_symlink():
778 new_path = p.readlink()
788 new_path = p.readlink()
779 if not new_path.is_absolute():
789 if not new_path.is_absolute():
780 new_path = p.parent / new_path
790 new_path = p.parent / new_path
781 p = new_path
791 p = new_path
782 paths.append(p)
792 paths.append(p)
783
793
784 # In Cygwin paths like "c:\..." and '\cygdrive\c\...' are possible
794 # In Cygwin paths like "c:\..." and '\cygdrive\c\...' are possible
785 if p_venv.parts[1] == "cygdrive":
795 if p_venv.parts[1] == "cygdrive":
786 drive_name = p_venv.parts[2]
796 drive_name = p_venv.parts[2]
787 p_venv = (drive_name + ":/") / Path(*p_venv.parts[3:])
797 p_venv = (drive_name + ":/") / Path(*p_venv.parts[3:])
788
798
789 if any(p_venv == p.parents[1] for p in paths):
799 if any(p_venv == p.parents[1] for p in paths):
790 # Our exe is inside or has access to the virtualenv, don't need to do anything.
800 # Our exe is inside or has access to the virtualenv, don't need to do anything.
791 return
801 return
792
802
793 if sys.platform == "win32":
803 if sys.platform == "win32":
794 virtual_env = str(Path(os.environ["VIRTUAL_ENV"], "Lib", "site-packages"))
804 virtual_env = str(Path(os.environ["VIRTUAL_ENV"], "Lib", "site-packages"))
795 else:
805 else:
796 virtual_env_path = Path(
806 virtual_env_path = Path(
797 os.environ["VIRTUAL_ENV"], "lib", "python{}.{}", "site-packages"
807 os.environ["VIRTUAL_ENV"], "lib", "python{}.{}", "site-packages"
798 )
808 )
799 p_ver = sys.version_info[:2]
809 p_ver = sys.version_info[:2]
800
810
801 # Predict version from py[thon]-x.x in the $VIRTUAL_ENV
811 # Predict version from py[thon]-x.x in the $VIRTUAL_ENV
802 re_m = re.search(r"\bpy(?:thon)?([23])\.(\d+)\b", os.environ["VIRTUAL_ENV"])
812 re_m = re.search(r"\bpy(?:thon)?([23])\.(\d+)\b", os.environ["VIRTUAL_ENV"])
803 if re_m:
813 if re_m:
804 predicted_path = Path(str(virtual_env_path).format(*re_m.groups()))
814 predicted_path = Path(str(virtual_env_path).format(*re_m.groups()))
805 if predicted_path.exists():
815 if predicted_path.exists():
806 p_ver = re_m.groups()
816 p_ver = re_m.groups()
807
817
808 virtual_env = str(virtual_env_path).format(*p_ver)
818 virtual_env = str(virtual_env_path).format(*p_ver)
809
819
810 warn(
820 warn(
811 "Attempting to work in a virtualenv. If you encounter problems, "
821 "Attempting to work in a virtualenv. If you encounter problems, "
812 "please install IPython inside the virtualenv."
822 "please install IPython inside the virtualenv."
813 )
823 )
814 import site
824 import site
815 sys.path.insert(0, virtual_env)
825 sys.path.insert(0, virtual_env)
816 site.addsitedir(virtual_env)
826 site.addsitedir(virtual_env)
817
827
818 #-------------------------------------------------------------------------
828 #-------------------------------------------------------------------------
819 # Things related to injections into the sys module
829 # Things related to injections into the sys module
820 #-------------------------------------------------------------------------
830 #-------------------------------------------------------------------------
821
831
822 def save_sys_module_state(self):
832 def save_sys_module_state(self):
823 """Save the state of hooks in the sys module.
833 """Save the state of hooks in the sys module.
824
834
825 This has to be called after self.user_module is created.
835 This has to be called after self.user_module is created.
826 """
836 """
827 self._orig_sys_module_state = {'stdin': sys.stdin,
837 self._orig_sys_module_state = {'stdin': sys.stdin,
828 'stdout': sys.stdout,
838 'stdout': sys.stdout,
829 'stderr': sys.stderr,
839 'stderr': sys.stderr,
830 'excepthook': sys.excepthook}
840 'excepthook': sys.excepthook}
831 self._orig_sys_modules_main_name = self.user_module.__name__
841 self._orig_sys_modules_main_name = self.user_module.__name__
832 self._orig_sys_modules_main_mod = sys.modules.get(self.user_module.__name__)
842 self._orig_sys_modules_main_mod = sys.modules.get(self.user_module.__name__)
833
843
834 def restore_sys_module_state(self):
844 def restore_sys_module_state(self):
835 """Restore the state of the sys module."""
845 """Restore the state of the sys module."""
836 try:
846 try:
837 for k, v in self._orig_sys_module_state.items():
847 for k, v in self._orig_sys_module_state.items():
838 setattr(sys, k, v)
848 setattr(sys, k, v)
839 except AttributeError:
849 except AttributeError:
840 pass
850 pass
841 # Reset what what done in self.init_sys_modules
851 # Reset what what done in self.init_sys_modules
842 if self._orig_sys_modules_main_mod is not None:
852 if self._orig_sys_modules_main_mod is not None:
843 sys.modules[self._orig_sys_modules_main_name] = self._orig_sys_modules_main_mod
853 sys.modules[self._orig_sys_modules_main_name] = self._orig_sys_modules_main_mod
844
854
845 #-------------------------------------------------------------------------
855 #-------------------------------------------------------------------------
846 # Things related to the banner
856 # Things related to the banner
847 #-------------------------------------------------------------------------
857 #-------------------------------------------------------------------------
848
858
849 @property
859 @property
850 def banner(self):
860 def banner(self):
851 banner = self.banner1
861 banner = self.banner1
852 if self.profile and self.profile != 'default':
862 if self.profile and self.profile != 'default':
853 banner += '\nIPython profile: %s\n' % self.profile
863 banner += '\nIPython profile: %s\n' % self.profile
854 if self.banner2:
864 if self.banner2:
855 banner += '\n' + self.banner2
865 banner += '\n' + self.banner2
856 return banner
866 return banner
857
867
858 def show_banner(self, banner=None):
868 def show_banner(self, banner=None):
859 if banner is None:
869 if banner is None:
860 banner = self.banner
870 banner = self.banner
861 sys.stdout.write(banner)
871 sys.stdout.write(banner)
862
872
863 #-------------------------------------------------------------------------
873 #-------------------------------------------------------------------------
864 # Things related to hooks
874 # Things related to hooks
865 #-------------------------------------------------------------------------
875 #-------------------------------------------------------------------------
866
876
867 def init_hooks(self):
877 def init_hooks(self):
868 # hooks holds pointers used for user-side customizations
878 # hooks holds pointers used for user-side customizations
869 self.hooks = Struct()
879 self.hooks = Struct()
870
880
871 self.strdispatchers = {}
881 self.strdispatchers = {}
872
882
873 # Set all default hooks, defined in the IPython.hooks module.
883 # Set all default hooks, defined in the IPython.hooks module.
874 hooks = IPython.core.hooks
884 hooks = IPython.core.hooks
875 for hook_name in hooks.__all__:
885 for hook_name in hooks.__all__:
876 # default hooks have priority 100, i.e. low; user hooks should have
886 # default hooks have priority 100, i.e. low; user hooks should have
877 # 0-100 priority
887 # 0-100 priority
878 self.set_hook(hook_name, getattr(hooks, hook_name), 100)
888 self.set_hook(hook_name, getattr(hooks, hook_name), 100)
879
889
880 if self.display_page:
890 if self.display_page:
881 self.set_hook('show_in_pager', page.as_hook(page.display_page), 90)
891 self.set_hook('show_in_pager', page.as_hook(page.display_page), 90)
882
892
883 def set_hook(self, name, hook, priority=50, str_key=None, re_key=None):
893 def set_hook(self, name, hook, priority=50, str_key=None, re_key=None):
884 """set_hook(name,hook) -> sets an internal IPython hook.
894 """set_hook(name,hook) -> sets an internal IPython hook.
885
895
886 IPython exposes some of its internal API as user-modifiable hooks. By
896 IPython exposes some of its internal API as user-modifiable hooks. By
887 adding your function to one of these hooks, you can modify IPython's
897 adding your function to one of these hooks, you can modify IPython's
888 behavior to call at runtime your own routines."""
898 behavior to call at runtime your own routines."""
889
899
890 # At some point in the future, this should validate the hook before it
900 # At some point in the future, this should validate the hook before it
891 # accepts it. Probably at least check that the hook takes the number
901 # accepts it. Probably at least check that the hook takes the number
892 # of args it's supposed to.
902 # of args it's supposed to.
893
903
894 f = types.MethodType(hook,self)
904 f = types.MethodType(hook,self)
895
905
896 # check if the hook is for strdispatcher first
906 # check if the hook is for strdispatcher first
897 if str_key is not None:
907 if str_key is not None:
898 sdp = self.strdispatchers.get(name, StrDispatch())
908 sdp = self.strdispatchers.get(name, StrDispatch())
899 sdp.add_s(str_key, f, priority )
909 sdp.add_s(str_key, f, priority )
900 self.strdispatchers[name] = sdp
910 self.strdispatchers[name] = sdp
901 return
911 return
902 if re_key is not None:
912 if re_key is not None:
903 sdp = self.strdispatchers.get(name, StrDispatch())
913 sdp = self.strdispatchers.get(name, StrDispatch())
904 sdp.add_re(re.compile(re_key), f, priority )
914 sdp.add_re(re.compile(re_key), f, priority )
905 self.strdispatchers[name] = sdp
915 self.strdispatchers[name] = sdp
906 return
916 return
907
917
908 dp = getattr(self.hooks, name, None)
918 dp = getattr(self.hooks, name, None)
909 if name not in IPython.core.hooks.__all__:
919 if name not in IPython.core.hooks.__all__:
910 print("Warning! Hook '%s' is not one of %s" % \
920 print("Warning! Hook '%s' is not one of %s" % \
911 (name, IPython.core.hooks.__all__ ))
921 (name, IPython.core.hooks.__all__ ))
912
922
913 if name in IPython.core.hooks.deprecated:
923 if name in IPython.core.hooks.deprecated:
914 alternative = IPython.core.hooks.deprecated[name]
924 alternative = IPython.core.hooks.deprecated[name]
915 raise ValueError(
925 raise ValueError(
916 "Hook {} has been deprecated since IPython 5.0. Use {} instead.".format(
926 "Hook {} has been deprecated since IPython 5.0. Use {} instead.".format(
917 name, alternative
927 name, alternative
918 )
928 )
919 )
929 )
920
930
921 if not dp:
931 if not dp:
922 dp = IPython.core.hooks.CommandChainDispatcher()
932 dp = IPython.core.hooks.CommandChainDispatcher()
923
933
924 try:
934 try:
925 dp.add(f,priority)
935 dp.add(f,priority)
926 except AttributeError:
936 except AttributeError:
927 # it was not commandchain, plain old func - replace
937 # it was not commandchain, plain old func - replace
928 dp = f
938 dp = f
929
939
930 setattr(self.hooks,name, dp)
940 setattr(self.hooks,name, dp)
931
941
932 #-------------------------------------------------------------------------
942 #-------------------------------------------------------------------------
933 # Things related to events
943 # Things related to events
934 #-------------------------------------------------------------------------
944 #-------------------------------------------------------------------------
935
945
936 def init_events(self):
946 def init_events(self):
937 self.events = EventManager(self, available_events)
947 self.events = EventManager(self, available_events)
938
948
939 self.events.register("pre_execute", self._clear_warning_registry)
949 self.events.register("pre_execute", self._clear_warning_registry)
940
950
941 def register_post_execute(self, func):
951 def register_post_execute(self, func):
942 """DEPRECATED: Use ip.events.register('post_run_cell', func)
952 """DEPRECATED: Use ip.events.register('post_run_cell', func)
943
953
944 Register a function for calling after code execution.
954 Register a function for calling after code execution.
945 """
955 """
946 raise ValueError(
956 raise ValueError(
947 "ip.register_post_execute is deprecated since IPython 1.0, use "
957 "ip.register_post_execute is deprecated since IPython 1.0, use "
948 "ip.events.register('post_run_cell', func) instead."
958 "ip.events.register('post_run_cell', func) instead."
949 )
959 )
950
960
951 def _clear_warning_registry(self):
961 def _clear_warning_registry(self):
952 # clear the warning registry, so that different code blocks with
962 # clear the warning registry, so that different code blocks with
953 # overlapping line number ranges don't cause spurious suppression of
963 # overlapping line number ranges don't cause spurious suppression of
954 # warnings (see gh-6611 for details)
964 # warnings (see gh-6611 for details)
955 if "__warningregistry__" in self.user_global_ns:
965 if "__warningregistry__" in self.user_global_ns:
956 del self.user_global_ns["__warningregistry__"]
966 del self.user_global_ns["__warningregistry__"]
957
967
958 #-------------------------------------------------------------------------
968 #-------------------------------------------------------------------------
959 # Things related to the "main" module
969 # Things related to the "main" module
960 #-------------------------------------------------------------------------
970 #-------------------------------------------------------------------------
961
971
962 def new_main_mod(self, filename, modname):
972 def new_main_mod(self, filename, modname):
963 """Return a new 'main' module object for user code execution.
973 """Return a new 'main' module object for user code execution.
964
974
965 ``filename`` should be the path of the script which will be run in the
975 ``filename`` should be the path of the script which will be run in the
966 module. Requests with the same filename will get the same module, with
976 module. Requests with the same filename will get the same module, with
967 its namespace cleared.
977 its namespace cleared.
968
978
969 ``modname`` should be the module name - normally either '__main__' or
979 ``modname`` should be the module name - normally either '__main__' or
970 the basename of the file without the extension.
980 the basename of the file without the extension.
971
981
972 When scripts are executed via %run, we must keep a reference to their
982 When scripts are executed via %run, we must keep a reference to their
973 __main__ module around so that Python doesn't
983 __main__ module around so that Python doesn't
974 clear it, rendering references to module globals useless.
984 clear it, rendering references to module globals useless.
975
985
976 This method keeps said reference in a private dict, keyed by the
986 This method keeps said reference in a private dict, keyed by the
977 absolute path of the script. This way, for multiple executions of the
987 absolute path of the script. This way, for multiple executions of the
978 same script we only keep one copy of the namespace (the last one),
988 same script we only keep one copy of the namespace (the last one),
979 thus preventing memory leaks from old references while allowing the
989 thus preventing memory leaks from old references while allowing the
980 objects from the last execution to be accessible.
990 objects from the last execution to be accessible.
981 """
991 """
982 filename = os.path.abspath(filename)
992 filename = os.path.abspath(filename)
983 try:
993 try:
984 main_mod = self._main_mod_cache[filename]
994 main_mod = self._main_mod_cache[filename]
985 except KeyError:
995 except KeyError:
986 main_mod = self._main_mod_cache[filename] = types.ModuleType(
996 main_mod = self._main_mod_cache[filename] = types.ModuleType(
987 modname,
997 modname,
988 doc="Module created for script run in IPython")
998 doc="Module created for script run in IPython")
989 else:
999 else:
990 main_mod.__dict__.clear()
1000 main_mod.__dict__.clear()
991 main_mod.__name__ = modname
1001 main_mod.__name__ = modname
992
1002
993 main_mod.__file__ = filename
1003 main_mod.__file__ = filename
994 # It seems pydoc (and perhaps others) needs any module instance to
1004 # It seems pydoc (and perhaps others) needs any module instance to
995 # implement a __nonzero__ method
1005 # implement a __nonzero__ method
996 main_mod.__nonzero__ = lambda : True
1006 main_mod.__nonzero__ = lambda : True
997
1007
998 return main_mod
1008 return main_mod
999
1009
1000 def clear_main_mod_cache(self):
1010 def clear_main_mod_cache(self):
1001 """Clear the cache of main modules.
1011 """Clear the cache of main modules.
1002
1012
1003 Mainly for use by utilities like %reset.
1013 Mainly for use by utilities like %reset.
1004
1014
1005 Examples
1015 Examples
1006 --------
1016 --------
1007 In [15]: import IPython
1017 In [15]: import IPython
1008
1018
1009 In [16]: m = _ip.new_main_mod(IPython.__file__, 'IPython')
1019 In [16]: m = _ip.new_main_mod(IPython.__file__, 'IPython')
1010
1020
1011 In [17]: len(_ip._main_mod_cache) > 0
1021 In [17]: len(_ip._main_mod_cache) > 0
1012 Out[17]: True
1022 Out[17]: True
1013
1023
1014 In [18]: _ip.clear_main_mod_cache()
1024 In [18]: _ip.clear_main_mod_cache()
1015
1025
1016 In [19]: len(_ip._main_mod_cache) == 0
1026 In [19]: len(_ip._main_mod_cache) == 0
1017 Out[19]: True
1027 Out[19]: True
1018 """
1028 """
1019 self._main_mod_cache.clear()
1029 self._main_mod_cache.clear()
1020
1030
1021 #-------------------------------------------------------------------------
1031 #-------------------------------------------------------------------------
1022 # Things related to debugging
1032 # Things related to debugging
1023 #-------------------------------------------------------------------------
1033 #-------------------------------------------------------------------------
1024
1034
1025 def init_pdb(self):
1035 def init_pdb(self):
1026 # Set calling of pdb on exceptions
1036 # Set calling of pdb on exceptions
1027 # self.call_pdb is a property
1037 # self.call_pdb is a property
1028 self.call_pdb = self.pdb
1038 self.call_pdb = self.pdb
1029
1039
1030 def _get_call_pdb(self):
1040 def _get_call_pdb(self):
1031 return self._call_pdb
1041 return self._call_pdb
1032
1042
1033 def _set_call_pdb(self,val):
1043 def _set_call_pdb(self,val):
1034
1044
1035 if val not in (0,1,False,True):
1045 if val not in (0,1,False,True):
1036 raise ValueError('new call_pdb value must be boolean')
1046 raise ValueError('new call_pdb value must be boolean')
1037
1047
1038 # store value in instance
1048 # store value in instance
1039 self._call_pdb = val
1049 self._call_pdb = val
1040
1050
1041 # notify the actual exception handlers
1051 # notify the actual exception handlers
1042 self.InteractiveTB.call_pdb = val
1052 self.InteractiveTB.call_pdb = val
1043
1053
1044 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
1054 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
1045 'Control auto-activation of pdb at exceptions')
1055 'Control auto-activation of pdb at exceptions')
1046
1056
1047 def debugger(self,force=False):
1057 def debugger(self,force=False):
1048 """Call the pdb debugger.
1058 """Call the pdb debugger.
1049
1059
1050 Keywords:
1060 Keywords:
1051
1061
1052 - force(False): by default, this routine checks the instance call_pdb
1062 - force(False): by default, this routine checks the instance call_pdb
1053 flag and does not actually invoke the debugger if the flag is false.
1063 flag and does not actually invoke the debugger if the flag is false.
1054 The 'force' option forces the debugger to activate even if the flag
1064 The 'force' option forces the debugger to activate even if the flag
1055 is false.
1065 is false.
1056 """
1066 """
1057
1067
1058 if not (force or self.call_pdb):
1068 if not (force or self.call_pdb):
1059 return
1069 return
1060
1070
1061 if not hasattr(sys,'last_traceback'):
1071 if not hasattr(sys,'last_traceback'):
1062 error('No traceback has been produced, nothing to debug.')
1072 error('No traceback has been produced, nothing to debug.')
1063 return
1073 return
1064
1074
1065 self.InteractiveTB.debugger(force=True)
1075 self.InteractiveTB.debugger(force=True)
1066
1076
1067 #-------------------------------------------------------------------------
1077 #-------------------------------------------------------------------------
1068 # Things related to IPython's various namespaces
1078 # Things related to IPython's various namespaces
1069 #-------------------------------------------------------------------------
1079 #-------------------------------------------------------------------------
1070 default_user_namespaces = True
1080 default_user_namespaces = True
1071
1081
1072 def init_create_namespaces(self, user_module=None, user_ns=None):
1082 def init_create_namespaces(self, user_module=None, user_ns=None):
1073 # Create the namespace where the user will operate. user_ns is
1083 # Create the namespace where the user will operate. user_ns is
1074 # normally the only one used, and it is passed to the exec calls as
1084 # normally the only one used, and it is passed to the exec calls as
1075 # the locals argument. But we do carry a user_global_ns namespace
1085 # the locals argument. But we do carry a user_global_ns namespace
1076 # given as the exec 'globals' argument, This is useful in embedding
1086 # given as the exec 'globals' argument, This is useful in embedding
1077 # situations where the ipython shell opens in a context where the
1087 # situations where the ipython shell opens in a context where the
1078 # distinction between locals and globals is meaningful. For
1088 # distinction between locals and globals is meaningful. For
1079 # non-embedded contexts, it is just the same object as the user_ns dict.
1089 # non-embedded contexts, it is just the same object as the user_ns dict.
1080
1090
1081 # FIXME. For some strange reason, __builtins__ is showing up at user
1091 # FIXME. For some strange reason, __builtins__ is showing up at user
1082 # level as a dict instead of a module. This is a manual fix, but I
1092 # level as a dict instead of a module. This is a manual fix, but I
1083 # should really track down where the problem is coming from. Alex
1093 # should really track down where the problem is coming from. Alex
1084 # Schmolck reported this problem first.
1094 # Schmolck reported this problem first.
1085
1095
1086 # A useful post by Alex Martelli on this topic:
1096 # A useful post by Alex Martelli on this topic:
1087 # Re: inconsistent value from __builtins__
1097 # Re: inconsistent value from __builtins__
1088 # Von: Alex Martelli <aleaxit@yahoo.com>
1098 # Von: Alex Martelli <aleaxit@yahoo.com>
1089 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
1099 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
1090 # Gruppen: comp.lang.python
1100 # Gruppen: comp.lang.python
1091
1101
1092 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
1102 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
1093 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
1103 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
1094 # > <type 'dict'>
1104 # > <type 'dict'>
1095 # > >>> print type(__builtins__)
1105 # > >>> print type(__builtins__)
1096 # > <type 'module'>
1106 # > <type 'module'>
1097 # > Is this difference in return value intentional?
1107 # > Is this difference in return value intentional?
1098
1108
1099 # Well, it's documented that '__builtins__' can be either a dictionary
1109 # Well, it's documented that '__builtins__' can be either a dictionary
1100 # or a module, and it's been that way for a long time. Whether it's
1110 # or a module, and it's been that way for a long time. Whether it's
1101 # intentional (or sensible), I don't know. In any case, the idea is
1111 # intentional (or sensible), I don't know. In any case, the idea is
1102 # that if you need to access the built-in namespace directly, you
1112 # that if you need to access the built-in namespace directly, you
1103 # should start with "import __builtin__" (note, no 's') which will
1113 # should start with "import __builtin__" (note, no 's') which will
1104 # definitely give you a module. Yeah, it's somewhat confusing:-(.
1114 # definitely give you a module. Yeah, it's somewhat confusing:-(.
1105
1115
1106 # These routines return a properly built module and dict as needed by
1116 # These routines return a properly built module and dict as needed by
1107 # the rest of the code, and can also be used by extension writers to
1117 # the rest of the code, and can also be used by extension writers to
1108 # generate properly initialized namespaces.
1118 # generate properly initialized namespaces.
1109 if (user_ns is not None) or (user_module is not None):
1119 if (user_ns is not None) or (user_module is not None):
1110 self.default_user_namespaces = False
1120 self.default_user_namespaces = False
1111 self.user_module, self.user_ns = self.prepare_user_module(user_module, user_ns)
1121 self.user_module, self.user_ns = self.prepare_user_module(user_module, user_ns)
1112
1122
1113 # A record of hidden variables we have added to the user namespace, so
1123 # A record of hidden variables we have added to the user namespace, so
1114 # we can list later only variables defined in actual interactive use.
1124 # we can list later only variables defined in actual interactive use.
1115 self.user_ns_hidden = {}
1125 self.user_ns_hidden = {}
1116
1126
1117 # Now that FakeModule produces a real module, we've run into a nasty
1127 # Now that FakeModule produces a real module, we've run into a nasty
1118 # problem: after script execution (via %run), the module where the user
1128 # problem: after script execution (via %run), the module where the user
1119 # code ran is deleted. Now that this object is a true module (needed
1129 # code ran is deleted. Now that this object is a true module (needed
1120 # so doctest and other tools work correctly), the Python module
1130 # so doctest and other tools work correctly), the Python module
1121 # teardown mechanism runs over it, and sets to None every variable
1131 # teardown mechanism runs over it, and sets to None every variable
1122 # present in that module. Top-level references to objects from the
1132 # present in that module. Top-level references to objects from the
1123 # script survive, because the user_ns is updated with them. However,
1133 # script survive, because the user_ns is updated with them. However,
1124 # calling functions defined in the script that use other things from
1134 # calling functions defined in the script that use other things from
1125 # the script will fail, because the function's closure had references
1135 # the script will fail, because the function's closure had references
1126 # to the original objects, which are now all None. So we must protect
1136 # to the original objects, which are now all None. So we must protect
1127 # these modules from deletion by keeping a cache.
1137 # these modules from deletion by keeping a cache.
1128 #
1138 #
1129 # To avoid keeping stale modules around (we only need the one from the
1139 # To avoid keeping stale modules around (we only need the one from the
1130 # last run), we use a dict keyed with the full path to the script, so
1140 # last run), we use a dict keyed with the full path to the script, so
1131 # only the last version of the module is held in the cache. Note,
1141 # only the last version of the module is held in the cache. Note,
1132 # however, that we must cache the module *namespace contents* (their
1142 # however, that we must cache the module *namespace contents* (their
1133 # __dict__). Because if we try to cache the actual modules, old ones
1143 # __dict__). Because if we try to cache the actual modules, old ones
1134 # (uncached) could be destroyed while still holding references (such as
1144 # (uncached) could be destroyed while still holding references (such as
1135 # those held by GUI objects that tend to be long-lived)>
1145 # those held by GUI objects that tend to be long-lived)>
1136 #
1146 #
1137 # The %reset command will flush this cache. See the cache_main_mod()
1147 # The %reset command will flush this cache. See the cache_main_mod()
1138 # and clear_main_mod_cache() methods for details on use.
1148 # and clear_main_mod_cache() methods for details on use.
1139
1149
1140 # This is the cache used for 'main' namespaces
1150 # This is the cache used for 'main' namespaces
1141 self._main_mod_cache = {}
1151 self._main_mod_cache = {}
1142
1152
1143 # A table holding all the namespaces IPython deals with, so that
1153 # A table holding all the namespaces IPython deals with, so that
1144 # introspection facilities can search easily.
1154 # introspection facilities can search easily.
1145 self.ns_table = {'user_global':self.user_module.__dict__,
1155 self.ns_table = {'user_global':self.user_module.__dict__,
1146 'user_local':self.user_ns,
1156 'user_local':self.user_ns,
1147 'builtin':builtin_mod.__dict__
1157 'builtin':builtin_mod.__dict__
1148 }
1158 }
1149
1159
1150 @property
1160 @property
1151 def user_global_ns(self):
1161 def user_global_ns(self):
1152 return self.user_module.__dict__
1162 return self.user_module.__dict__
1153
1163
1154 def prepare_user_module(self, user_module=None, user_ns=None):
1164 def prepare_user_module(self, user_module=None, user_ns=None):
1155 """Prepare the module and namespace in which user code will be run.
1165 """Prepare the module and namespace in which user code will be run.
1156
1166
1157 When IPython is started normally, both parameters are None: a new module
1167 When IPython is started normally, both parameters are None: a new module
1158 is created automatically, and its __dict__ used as the namespace.
1168 is created automatically, and its __dict__ used as the namespace.
1159
1169
1160 If only user_module is provided, its __dict__ is used as the namespace.
1170 If only user_module is provided, its __dict__ is used as the namespace.
1161 If only user_ns is provided, a dummy module is created, and user_ns
1171 If only user_ns is provided, a dummy module is created, and user_ns
1162 becomes the global namespace. If both are provided (as they may be
1172 becomes the global namespace. If both are provided (as they may be
1163 when embedding), user_ns is the local namespace, and user_module
1173 when embedding), user_ns is the local namespace, and user_module
1164 provides the global namespace.
1174 provides the global namespace.
1165
1175
1166 Parameters
1176 Parameters
1167 ----------
1177 ----------
1168 user_module : module, optional
1178 user_module : module, optional
1169 The current user module in which IPython is being run. If None,
1179 The current user module in which IPython is being run. If None,
1170 a clean module will be created.
1180 a clean module will be created.
1171 user_ns : dict, optional
1181 user_ns : dict, optional
1172 A namespace in which to run interactive commands.
1182 A namespace in which to run interactive commands.
1173
1183
1174 Returns
1184 Returns
1175 -------
1185 -------
1176 A tuple of user_module and user_ns, each properly initialised.
1186 A tuple of user_module and user_ns, each properly initialised.
1177 """
1187 """
1178 if user_module is None and user_ns is not None:
1188 if user_module is None and user_ns is not None:
1179 user_ns.setdefault("__name__", "__main__")
1189 user_ns.setdefault("__name__", "__main__")
1180 user_module = DummyMod()
1190 user_module = DummyMod()
1181 user_module.__dict__ = user_ns
1191 user_module.__dict__ = user_ns
1182
1192
1183 if user_module is None:
1193 if user_module is None:
1184 user_module = types.ModuleType("__main__",
1194 user_module = types.ModuleType("__main__",
1185 doc="Automatically created module for IPython interactive environment")
1195 doc="Automatically created module for IPython interactive environment")
1186
1196
1187 # We must ensure that __builtin__ (without the final 's') is always
1197 # We must ensure that __builtin__ (without the final 's') is always
1188 # available and pointing to the __builtin__ *module*. For more details:
1198 # available and pointing to the __builtin__ *module*. For more details:
1189 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1199 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1190 user_module.__dict__.setdefault('__builtin__', builtin_mod)
1200 user_module.__dict__.setdefault('__builtin__', builtin_mod)
1191 user_module.__dict__.setdefault('__builtins__', builtin_mod)
1201 user_module.__dict__.setdefault('__builtins__', builtin_mod)
1192
1202
1193 if user_ns is None:
1203 if user_ns is None:
1194 user_ns = user_module.__dict__
1204 user_ns = user_module.__dict__
1195
1205
1196 return user_module, user_ns
1206 return user_module, user_ns
1197
1207
1198 def init_sys_modules(self):
1208 def init_sys_modules(self):
1199 # We need to insert into sys.modules something that looks like a
1209 # We need to insert into sys.modules something that looks like a
1200 # module but which accesses the IPython namespace, for shelve and
1210 # module but which accesses the IPython namespace, for shelve and
1201 # pickle to work interactively. Normally they rely on getting
1211 # pickle to work interactively. Normally they rely on getting
1202 # everything out of __main__, but for embedding purposes each IPython
1212 # everything out of __main__, but for embedding purposes each IPython
1203 # instance has its own private namespace, so we can't go shoving
1213 # instance has its own private namespace, so we can't go shoving
1204 # everything into __main__.
1214 # everything into __main__.
1205
1215
1206 # note, however, that we should only do this for non-embedded
1216 # note, however, that we should only do this for non-embedded
1207 # ipythons, which really mimic the __main__.__dict__ with their own
1217 # ipythons, which really mimic the __main__.__dict__ with their own
1208 # namespace. Embedded instances, on the other hand, should not do
1218 # namespace. Embedded instances, on the other hand, should not do
1209 # this because they need to manage the user local/global namespaces
1219 # this because they need to manage the user local/global namespaces
1210 # only, but they live within a 'normal' __main__ (meaning, they
1220 # only, but they live within a 'normal' __main__ (meaning, they
1211 # shouldn't overtake the execution environment of the script they're
1221 # shouldn't overtake the execution environment of the script they're
1212 # embedded in).
1222 # embedded in).
1213
1223
1214 # This is overridden in the InteractiveShellEmbed subclass to a no-op.
1224 # This is overridden in the InteractiveShellEmbed subclass to a no-op.
1215 main_name = self.user_module.__name__
1225 main_name = self.user_module.__name__
1216 sys.modules[main_name] = self.user_module
1226 sys.modules[main_name] = self.user_module
1217
1227
1218 def init_user_ns(self):
1228 def init_user_ns(self):
1219 """Initialize all user-visible namespaces to their minimum defaults.
1229 """Initialize all user-visible namespaces to their minimum defaults.
1220
1230
1221 Certain history lists are also initialized here, as they effectively
1231 Certain history lists are also initialized here, as they effectively
1222 act as user namespaces.
1232 act as user namespaces.
1223
1233
1224 Notes
1234 Notes
1225 -----
1235 -----
1226 All data structures here are only filled in, they are NOT reset by this
1236 All data structures here are only filled in, they are NOT reset by this
1227 method. If they were not empty before, data will simply be added to
1237 method. If they were not empty before, data will simply be added to
1228 them.
1238 them.
1229 """
1239 """
1230 # This function works in two parts: first we put a few things in
1240 # This function works in two parts: first we put a few things in
1231 # user_ns, and we sync that contents into user_ns_hidden so that these
1241 # user_ns, and we sync that contents into user_ns_hidden so that these
1232 # initial variables aren't shown by %who. After the sync, we add the
1242 # initial variables aren't shown by %who. After the sync, we add the
1233 # rest of what we *do* want the user to see with %who even on a new
1243 # rest of what we *do* want the user to see with %who even on a new
1234 # session (probably nothing, so they really only see their own stuff)
1244 # session (probably nothing, so they really only see their own stuff)
1235
1245
1236 # The user dict must *always* have a __builtin__ reference to the
1246 # The user dict must *always* have a __builtin__ reference to the
1237 # Python standard __builtin__ namespace, which must be imported.
1247 # Python standard __builtin__ namespace, which must be imported.
1238 # This is so that certain operations in prompt evaluation can be
1248 # This is so that certain operations in prompt evaluation can be
1239 # reliably executed with builtins. Note that we can NOT use
1249 # reliably executed with builtins. Note that we can NOT use
1240 # __builtins__ (note the 's'), because that can either be a dict or a
1250 # __builtins__ (note the 's'), because that can either be a dict or a
1241 # module, and can even mutate at runtime, depending on the context
1251 # module, and can even mutate at runtime, depending on the context
1242 # (Python makes no guarantees on it). In contrast, __builtin__ is
1252 # (Python makes no guarantees on it). In contrast, __builtin__ is
1243 # always a module object, though it must be explicitly imported.
1253 # always a module object, though it must be explicitly imported.
1244
1254
1245 # For more details:
1255 # For more details:
1246 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1256 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1247 ns = {}
1257 ns = {}
1248
1258
1249 # make global variables for user access to the histories
1259 # make global variables for user access to the histories
1250 ns['_ih'] = self.history_manager.input_hist_parsed
1260 ns['_ih'] = self.history_manager.input_hist_parsed
1251 ns['_oh'] = self.history_manager.output_hist
1261 ns['_oh'] = self.history_manager.output_hist
1252 ns['_dh'] = self.history_manager.dir_hist
1262 ns['_dh'] = self.history_manager.dir_hist
1253
1263
1254 # user aliases to input and output histories. These shouldn't show up
1264 # user aliases to input and output histories. These shouldn't show up
1255 # in %who, as they can have very large reprs.
1265 # in %who, as they can have very large reprs.
1256 ns['In'] = self.history_manager.input_hist_parsed
1266 ns['In'] = self.history_manager.input_hist_parsed
1257 ns['Out'] = self.history_manager.output_hist
1267 ns['Out'] = self.history_manager.output_hist
1258
1268
1259 # Store myself as the public api!!!
1269 # Store myself as the public api!!!
1260 ns['get_ipython'] = self.get_ipython
1270 ns['get_ipython'] = self.get_ipython
1261
1271
1262 ns['exit'] = self.exiter
1272 ns['exit'] = self.exiter
1263 ns['quit'] = self.exiter
1273 ns['quit'] = self.exiter
1264
1274
1265 # Sync what we've added so far to user_ns_hidden so these aren't seen
1275 # Sync what we've added so far to user_ns_hidden so these aren't seen
1266 # by %who
1276 # by %who
1267 self.user_ns_hidden.update(ns)
1277 self.user_ns_hidden.update(ns)
1268
1278
1269 # Anything put into ns now would show up in %who. Think twice before
1279 # Anything put into ns now would show up in %who. Think twice before
1270 # putting anything here, as we really want %who to show the user their
1280 # putting anything here, as we really want %who to show the user their
1271 # stuff, not our variables.
1281 # stuff, not our variables.
1272
1282
1273 # Finally, update the real user's namespace
1283 # Finally, update the real user's namespace
1274 self.user_ns.update(ns)
1284 self.user_ns.update(ns)
1275
1285
1276 @property
1286 @property
1277 def all_ns_refs(self):
1287 def all_ns_refs(self):
1278 """Get a list of references to all the namespace dictionaries in which
1288 """Get a list of references to all the namespace dictionaries in which
1279 IPython might store a user-created object.
1289 IPython might store a user-created object.
1280
1290
1281 Note that this does not include the displayhook, which also caches
1291 Note that this does not include the displayhook, which also caches
1282 objects from the output."""
1292 objects from the output."""
1283 return [self.user_ns, self.user_global_ns, self.user_ns_hidden] + \
1293 return [self.user_ns, self.user_global_ns, self.user_ns_hidden] + \
1284 [m.__dict__ for m in self._main_mod_cache.values()]
1294 [m.__dict__ for m in self._main_mod_cache.values()]
1285
1295
1286 def reset(self, new_session=True, aggressive=False):
1296 def reset(self, new_session=True, aggressive=False):
1287 """Clear all internal namespaces, and attempt to release references to
1297 """Clear all internal namespaces, and attempt to release references to
1288 user objects.
1298 user objects.
1289
1299
1290 If new_session is True, a new history session will be opened.
1300 If new_session is True, a new history session will be opened.
1291 """
1301 """
1292 # Clear histories
1302 # Clear histories
1293 self.history_manager.reset(new_session)
1303 self.history_manager.reset(new_session)
1294 # Reset counter used to index all histories
1304 # Reset counter used to index all histories
1295 if new_session:
1305 if new_session:
1296 self.execution_count = 1
1306 self.execution_count = 1
1297
1307
1298 # Reset last execution result
1308 # Reset last execution result
1299 self.last_execution_succeeded = True
1309 self.last_execution_succeeded = True
1300 self.last_execution_result = None
1310 self.last_execution_result = None
1301
1311
1302 # Flush cached output items
1312 # Flush cached output items
1303 if self.displayhook.do_full_cache:
1313 if self.displayhook.do_full_cache:
1304 self.displayhook.flush()
1314 self.displayhook.flush()
1305
1315
1306 # The main execution namespaces must be cleared very carefully,
1316 # The main execution namespaces must be cleared very carefully,
1307 # skipping the deletion of the builtin-related keys, because doing so
1317 # skipping the deletion of the builtin-related keys, because doing so
1308 # would cause errors in many object's __del__ methods.
1318 # would cause errors in many object's __del__ methods.
1309 if self.user_ns is not self.user_global_ns:
1319 if self.user_ns is not self.user_global_ns:
1310 self.user_ns.clear()
1320 self.user_ns.clear()
1311 ns = self.user_global_ns
1321 ns = self.user_global_ns
1312 drop_keys = set(ns.keys())
1322 drop_keys = set(ns.keys())
1313 drop_keys.discard('__builtin__')
1323 drop_keys.discard('__builtin__')
1314 drop_keys.discard('__builtins__')
1324 drop_keys.discard('__builtins__')
1315 drop_keys.discard('__name__')
1325 drop_keys.discard('__name__')
1316 for k in drop_keys:
1326 for k in drop_keys:
1317 del ns[k]
1327 del ns[k]
1318
1328
1319 self.user_ns_hidden.clear()
1329 self.user_ns_hidden.clear()
1320
1330
1321 # Restore the user namespaces to minimal usability
1331 # Restore the user namespaces to minimal usability
1322 self.init_user_ns()
1332 self.init_user_ns()
1323 if aggressive and not hasattr(self, "_sys_modules_keys"):
1333 if aggressive and not hasattr(self, "_sys_modules_keys"):
1324 print("Cannot restore sys.module, no snapshot")
1334 print("Cannot restore sys.module, no snapshot")
1325 elif aggressive:
1335 elif aggressive:
1326 print("culling sys module...")
1336 print("culling sys module...")
1327 current_keys = set(sys.modules.keys())
1337 current_keys = set(sys.modules.keys())
1328 for k in current_keys - self._sys_modules_keys:
1338 for k in current_keys - self._sys_modules_keys:
1329 if k.startswith("multiprocessing"):
1339 if k.startswith("multiprocessing"):
1330 continue
1340 continue
1331 del sys.modules[k]
1341 del sys.modules[k]
1332
1342
1333 # Restore the default and user aliases
1343 # Restore the default and user aliases
1334 self.alias_manager.clear_aliases()
1344 self.alias_manager.clear_aliases()
1335 self.alias_manager.init_aliases()
1345 self.alias_manager.init_aliases()
1336
1346
1337 # Now define aliases that only make sense on the terminal, because they
1347 # Now define aliases that only make sense on the terminal, because they
1338 # need direct access to the console in a way that we can't emulate in
1348 # need direct access to the console in a way that we can't emulate in
1339 # GUI or web frontend
1349 # GUI or web frontend
1340 if os.name == 'posix':
1350 if os.name == 'posix':
1341 for cmd in ('clear', 'more', 'less', 'man'):
1351 for cmd in ('clear', 'more', 'less', 'man'):
1342 if cmd not in self.magics_manager.magics['line']:
1352 if cmd not in self.magics_manager.magics['line']:
1343 self.alias_manager.soft_define_alias(cmd, cmd)
1353 self.alias_manager.soft_define_alias(cmd, cmd)
1344
1354
1345 # Flush the private list of module references kept for script
1355 # Flush the private list of module references kept for script
1346 # execution protection
1356 # execution protection
1347 self.clear_main_mod_cache()
1357 self.clear_main_mod_cache()
1348
1358
1349 def del_var(self, varname, by_name=False):
1359 def del_var(self, varname, by_name=False):
1350 """Delete a variable from the various namespaces, so that, as
1360 """Delete a variable from the various namespaces, so that, as
1351 far as possible, we're not keeping any hidden references to it.
1361 far as possible, we're not keeping any hidden references to it.
1352
1362
1353 Parameters
1363 Parameters
1354 ----------
1364 ----------
1355 varname : str
1365 varname : str
1356 The name of the variable to delete.
1366 The name of the variable to delete.
1357 by_name : bool
1367 by_name : bool
1358 If True, delete variables with the given name in each
1368 If True, delete variables with the given name in each
1359 namespace. If False (default), find the variable in the user
1369 namespace. If False (default), find the variable in the user
1360 namespace, and delete references to it.
1370 namespace, and delete references to it.
1361 """
1371 """
1362 if varname in ('__builtin__', '__builtins__'):
1372 if varname in ('__builtin__', '__builtins__'):
1363 raise ValueError("Refusing to delete %s" % varname)
1373 raise ValueError("Refusing to delete %s" % varname)
1364
1374
1365 ns_refs = self.all_ns_refs
1375 ns_refs = self.all_ns_refs
1366
1376
1367 if by_name: # Delete by name
1377 if by_name: # Delete by name
1368 for ns in ns_refs:
1378 for ns in ns_refs:
1369 try:
1379 try:
1370 del ns[varname]
1380 del ns[varname]
1371 except KeyError:
1381 except KeyError:
1372 pass
1382 pass
1373 else: # Delete by object
1383 else: # Delete by object
1374 try:
1384 try:
1375 obj = self.user_ns[varname]
1385 obj = self.user_ns[varname]
1376 except KeyError as e:
1386 except KeyError as e:
1377 raise NameError("name '%s' is not defined" % varname) from e
1387 raise NameError("name '%s' is not defined" % varname) from e
1378 # Also check in output history
1388 # Also check in output history
1379 ns_refs.append(self.history_manager.output_hist)
1389 ns_refs.append(self.history_manager.output_hist)
1380 for ns in ns_refs:
1390 for ns in ns_refs:
1381 to_delete = [n for n, o in ns.items() if o is obj]
1391 to_delete = [n for n, o in ns.items() if o is obj]
1382 for name in to_delete:
1392 for name in to_delete:
1383 del ns[name]
1393 del ns[name]
1384
1394
1385 # Ensure it is removed from the last execution result
1395 # Ensure it is removed from the last execution result
1386 if self.last_execution_result.result is obj:
1396 if self.last_execution_result.result is obj:
1387 self.last_execution_result = None
1397 self.last_execution_result = None
1388
1398
1389 # displayhook keeps extra references, but not in a dictionary
1399 # displayhook keeps extra references, but not in a dictionary
1390 for name in ('_', '__', '___'):
1400 for name in ('_', '__', '___'):
1391 if getattr(self.displayhook, name) is obj:
1401 if getattr(self.displayhook, name) is obj:
1392 setattr(self.displayhook, name, None)
1402 setattr(self.displayhook, name, None)
1393
1403
1394 def reset_selective(self, regex=None):
1404 def reset_selective(self, regex=None):
1395 """Clear selective variables from internal namespaces based on a
1405 """Clear selective variables from internal namespaces based on a
1396 specified regular expression.
1406 specified regular expression.
1397
1407
1398 Parameters
1408 Parameters
1399 ----------
1409 ----------
1400 regex : string or compiled pattern, optional
1410 regex : string or compiled pattern, optional
1401 A regular expression pattern that will be used in searching
1411 A regular expression pattern that will be used in searching
1402 variable names in the users namespaces.
1412 variable names in the users namespaces.
1403 """
1413 """
1404 if regex is not None:
1414 if regex is not None:
1405 try:
1415 try:
1406 m = re.compile(regex)
1416 m = re.compile(regex)
1407 except TypeError as e:
1417 except TypeError as e:
1408 raise TypeError('regex must be a string or compiled pattern') from e
1418 raise TypeError('regex must be a string or compiled pattern') from e
1409 # Search for keys in each namespace that match the given regex
1419 # Search for keys in each namespace that match the given regex
1410 # If a match is found, delete the key/value pair.
1420 # If a match is found, delete the key/value pair.
1411 for ns in self.all_ns_refs:
1421 for ns in self.all_ns_refs:
1412 for var in ns:
1422 for var in ns:
1413 if m.search(var):
1423 if m.search(var):
1414 del ns[var]
1424 del ns[var]
1415
1425
1416 def push(self, variables, interactive=True):
1426 def push(self, variables, interactive=True):
1417 """Inject a group of variables into the IPython user namespace.
1427 """Inject a group of variables into the IPython user namespace.
1418
1428
1419 Parameters
1429 Parameters
1420 ----------
1430 ----------
1421 variables : dict, str or list/tuple of str
1431 variables : dict, str or list/tuple of str
1422 The variables to inject into the user's namespace. If a dict, a
1432 The variables to inject into the user's namespace. If a dict, a
1423 simple update is done. If a str, the string is assumed to have
1433 simple update is done. If a str, the string is assumed to have
1424 variable names separated by spaces. A list/tuple of str can also
1434 variable names separated by spaces. A list/tuple of str can also
1425 be used to give the variable names. If just the variable names are
1435 be used to give the variable names. If just the variable names are
1426 give (list/tuple/str) then the variable values looked up in the
1436 give (list/tuple/str) then the variable values looked up in the
1427 callers frame.
1437 callers frame.
1428 interactive : bool
1438 interactive : bool
1429 If True (default), the variables will be listed with the ``who``
1439 If True (default), the variables will be listed with the ``who``
1430 magic.
1440 magic.
1431 """
1441 """
1432 vdict = None
1442 vdict = None
1433
1443
1434 # We need a dict of name/value pairs to do namespace updates.
1444 # We need a dict of name/value pairs to do namespace updates.
1435 if isinstance(variables, dict):
1445 if isinstance(variables, dict):
1436 vdict = variables
1446 vdict = variables
1437 elif isinstance(variables, (str, list, tuple)):
1447 elif isinstance(variables, (str, list, tuple)):
1438 if isinstance(variables, str):
1448 if isinstance(variables, str):
1439 vlist = variables.split()
1449 vlist = variables.split()
1440 else:
1450 else:
1441 vlist = variables
1451 vlist = variables
1442 vdict = {}
1452 vdict = {}
1443 cf = sys._getframe(1)
1453 cf = sys._getframe(1)
1444 for name in vlist:
1454 for name in vlist:
1445 try:
1455 try:
1446 vdict[name] = eval(name, cf.f_globals, cf.f_locals)
1456 vdict[name] = eval(name, cf.f_globals, cf.f_locals)
1447 except:
1457 except:
1448 print('Could not get variable %s from %s' %
1458 print('Could not get variable %s from %s' %
1449 (name,cf.f_code.co_name))
1459 (name,cf.f_code.co_name))
1450 else:
1460 else:
1451 raise ValueError('variables must be a dict/str/list/tuple')
1461 raise ValueError('variables must be a dict/str/list/tuple')
1452
1462
1453 # Propagate variables to user namespace
1463 # Propagate variables to user namespace
1454 self.user_ns.update(vdict)
1464 self.user_ns.update(vdict)
1455
1465
1456 # And configure interactive visibility
1466 # And configure interactive visibility
1457 user_ns_hidden = self.user_ns_hidden
1467 user_ns_hidden = self.user_ns_hidden
1458 if interactive:
1468 if interactive:
1459 for name in vdict:
1469 for name in vdict:
1460 user_ns_hidden.pop(name, None)
1470 user_ns_hidden.pop(name, None)
1461 else:
1471 else:
1462 user_ns_hidden.update(vdict)
1472 user_ns_hidden.update(vdict)
1463
1473
1464 def drop_by_id(self, variables):
1474 def drop_by_id(self, variables):
1465 """Remove a dict of variables from the user namespace, if they are the
1475 """Remove a dict of variables from the user namespace, if they are the
1466 same as the values in the dictionary.
1476 same as the values in the dictionary.
1467
1477
1468 This is intended for use by extensions: variables that they've added can
1478 This is intended for use by extensions: variables that they've added can
1469 be taken back out if they are unloaded, without removing any that the
1479 be taken back out if they are unloaded, without removing any that the
1470 user has overwritten.
1480 user has overwritten.
1471
1481
1472 Parameters
1482 Parameters
1473 ----------
1483 ----------
1474 variables : dict
1484 variables : dict
1475 A dictionary mapping object names (as strings) to the objects.
1485 A dictionary mapping object names (as strings) to the objects.
1476 """
1486 """
1477 for name, obj in variables.items():
1487 for name, obj in variables.items():
1478 if name in self.user_ns and self.user_ns[name] is obj:
1488 if name in self.user_ns and self.user_ns[name] is obj:
1479 del self.user_ns[name]
1489 del self.user_ns[name]
1480 self.user_ns_hidden.pop(name, None)
1490 self.user_ns_hidden.pop(name, None)
1481
1491
1482 #-------------------------------------------------------------------------
1492 #-------------------------------------------------------------------------
1483 # Things related to object introspection
1493 # Things related to object introspection
1484 #-------------------------------------------------------------------------
1494 #-------------------------------------------------------------------------
1485
1495
1486 def _ofind(self, oname, namespaces=None):
1496 def _ofind(self, oname, namespaces=None):
1487 """Find an object in the available namespaces.
1497 """Find an object in the available namespaces.
1488
1498
1489 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
1499 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
1490
1500
1491 Has special code to detect magic functions.
1501 Has special code to detect magic functions.
1492 """
1502 """
1493 oname = oname.strip()
1503 oname = oname.strip()
1494 if not oname.startswith(ESC_MAGIC) and \
1504 if not oname.startswith(ESC_MAGIC) and \
1495 not oname.startswith(ESC_MAGIC2) and \
1505 not oname.startswith(ESC_MAGIC2) and \
1496 not all(a.isidentifier() for a in oname.split(".")):
1506 not all(a.isidentifier() for a in oname.split(".")):
1497 return {'found': False}
1507 return {'found': False}
1498
1508
1499 if namespaces is None:
1509 if namespaces is None:
1500 # Namespaces to search in:
1510 # Namespaces to search in:
1501 # Put them in a list. The order is important so that we
1511 # Put them in a list. The order is important so that we
1502 # find things in the same order that Python finds them.
1512 # find things in the same order that Python finds them.
1503 namespaces = [ ('Interactive', self.user_ns),
1513 namespaces = [ ('Interactive', self.user_ns),
1504 ('Interactive (global)', self.user_global_ns),
1514 ('Interactive (global)', self.user_global_ns),
1505 ('Python builtin', builtin_mod.__dict__),
1515 ('Python builtin', builtin_mod.__dict__),
1506 ]
1516 ]
1507
1517
1508 ismagic = False
1518 ismagic = False
1509 isalias = False
1519 isalias = False
1510 found = False
1520 found = False
1511 ospace = None
1521 ospace = None
1512 parent = None
1522 parent = None
1513 obj = None
1523 obj = None
1514
1524
1515
1525
1516 # Look for the given name by splitting it in parts. If the head is
1526 # Look for the given name by splitting it in parts. If the head is
1517 # found, then we look for all the remaining parts as members, and only
1527 # found, then we look for all the remaining parts as members, and only
1518 # declare success if we can find them all.
1528 # declare success if we can find them all.
1519 oname_parts = oname.split('.')
1529 oname_parts = oname.split('.')
1520 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
1530 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
1521 for nsname,ns in namespaces:
1531 for nsname,ns in namespaces:
1522 try:
1532 try:
1523 obj = ns[oname_head]
1533 obj = ns[oname_head]
1524 except KeyError:
1534 except KeyError:
1525 continue
1535 continue
1526 else:
1536 else:
1527 for idx, part in enumerate(oname_rest):
1537 for idx, part in enumerate(oname_rest):
1528 try:
1538 try:
1529 parent = obj
1539 parent = obj
1530 # The last part is looked up in a special way to avoid
1540 # The last part is looked up in a special way to avoid
1531 # descriptor invocation as it may raise or have side
1541 # descriptor invocation as it may raise or have side
1532 # effects.
1542 # effects.
1533 if idx == len(oname_rest) - 1:
1543 if idx == len(oname_rest) - 1:
1534 obj = self._getattr_property(obj, part)
1544 obj = self._getattr_property(obj, part)
1535 else:
1545 else:
1536 obj = getattr(obj, part)
1546 obj = getattr(obj, part)
1537 except:
1547 except:
1538 # Blanket except b/c some badly implemented objects
1548 # Blanket except b/c some badly implemented objects
1539 # allow __getattr__ to raise exceptions other than
1549 # allow __getattr__ to raise exceptions other than
1540 # AttributeError, which then crashes IPython.
1550 # AttributeError, which then crashes IPython.
1541 break
1551 break
1542 else:
1552 else:
1543 # If we finish the for loop (no break), we got all members
1553 # If we finish the for loop (no break), we got all members
1544 found = True
1554 found = True
1545 ospace = nsname
1555 ospace = nsname
1546 break # namespace loop
1556 break # namespace loop
1547
1557
1548 # Try to see if it's magic
1558 # Try to see if it's magic
1549 if not found:
1559 if not found:
1550 obj = None
1560 obj = None
1551 if oname.startswith(ESC_MAGIC2):
1561 if oname.startswith(ESC_MAGIC2):
1552 oname = oname.lstrip(ESC_MAGIC2)
1562 oname = oname.lstrip(ESC_MAGIC2)
1553 obj = self.find_cell_magic(oname)
1563 obj = self.find_cell_magic(oname)
1554 elif oname.startswith(ESC_MAGIC):
1564 elif oname.startswith(ESC_MAGIC):
1555 oname = oname.lstrip(ESC_MAGIC)
1565 oname = oname.lstrip(ESC_MAGIC)
1556 obj = self.find_line_magic(oname)
1566 obj = self.find_line_magic(oname)
1557 else:
1567 else:
1558 # search without prefix, so run? will find %run?
1568 # search without prefix, so run? will find %run?
1559 obj = self.find_line_magic(oname)
1569 obj = self.find_line_magic(oname)
1560 if obj is None:
1570 if obj is None:
1561 obj = self.find_cell_magic(oname)
1571 obj = self.find_cell_magic(oname)
1562 if obj is not None:
1572 if obj is not None:
1563 found = True
1573 found = True
1564 ospace = 'IPython internal'
1574 ospace = 'IPython internal'
1565 ismagic = True
1575 ismagic = True
1566 isalias = isinstance(obj, Alias)
1576 isalias = isinstance(obj, Alias)
1567
1577
1568 # Last try: special-case some literals like '', [], {}, etc:
1578 # Last try: special-case some literals like '', [], {}, etc:
1569 if not found and oname_head in ["''",'""','[]','{}','()']:
1579 if not found and oname_head in ["''",'""','[]','{}','()']:
1570 obj = eval(oname_head)
1580 obj = eval(oname_head)
1571 found = True
1581 found = True
1572 ospace = 'Interactive'
1582 ospace = 'Interactive'
1573
1583
1574 return {
1584 return {
1575 'obj':obj,
1585 'obj':obj,
1576 'found':found,
1586 'found':found,
1577 'parent':parent,
1587 'parent':parent,
1578 'ismagic':ismagic,
1588 'ismagic':ismagic,
1579 'isalias':isalias,
1589 'isalias':isalias,
1580 'namespace':ospace
1590 'namespace':ospace
1581 }
1591 }
1582
1592
1583 @staticmethod
1593 @staticmethod
1584 def _getattr_property(obj, attrname):
1594 def _getattr_property(obj, attrname):
1585 """Property-aware getattr to use in object finding.
1595 """Property-aware getattr to use in object finding.
1586
1596
1587 If attrname represents a property, return it unevaluated (in case it has
1597 If attrname represents a property, return it unevaluated (in case it has
1588 side effects or raises an error.
1598 side effects or raises an error.
1589
1599
1590 """
1600 """
1591 if not isinstance(obj, type):
1601 if not isinstance(obj, type):
1592 try:
1602 try:
1593 # `getattr(type(obj), attrname)` is not guaranteed to return
1603 # `getattr(type(obj), attrname)` is not guaranteed to return
1594 # `obj`, but does so for property:
1604 # `obj`, but does so for property:
1595 #
1605 #
1596 # property.__get__(self, None, cls) -> self
1606 # property.__get__(self, None, cls) -> self
1597 #
1607 #
1598 # The universal alternative is to traverse the mro manually
1608 # The universal alternative is to traverse the mro manually
1599 # searching for attrname in class dicts.
1609 # searching for attrname in class dicts.
1600 attr = getattr(type(obj), attrname)
1610 attr = getattr(type(obj), attrname)
1601 except AttributeError:
1611 except AttributeError:
1602 pass
1612 pass
1603 else:
1613 else:
1604 # This relies on the fact that data descriptors (with both
1614 # This relies on the fact that data descriptors (with both
1605 # __get__ & __set__ magic methods) take precedence over
1615 # __get__ & __set__ magic methods) take precedence over
1606 # instance-level attributes:
1616 # instance-level attributes:
1607 #
1617 #
1608 # class A(object):
1618 # class A(object):
1609 # @property
1619 # @property
1610 # def foobar(self): return 123
1620 # def foobar(self): return 123
1611 # a = A()
1621 # a = A()
1612 # a.__dict__['foobar'] = 345
1622 # a.__dict__['foobar'] = 345
1613 # a.foobar # == 123
1623 # a.foobar # == 123
1614 #
1624 #
1615 # So, a property may be returned right away.
1625 # So, a property may be returned right away.
1616 if isinstance(attr, property):
1626 if isinstance(attr, property):
1617 return attr
1627 return attr
1618
1628
1619 # Nothing helped, fall back.
1629 # Nothing helped, fall back.
1620 return getattr(obj, attrname)
1630 return getattr(obj, attrname)
1621
1631
1622 def _object_find(self, oname, namespaces=None):
1632 def _object_find(self, oname, namespaces=None):
1623 """Find an object and return a struct with info about it."""
1633 """Find an object and return a struct with info about it."""
1624 return Struct(self._ofind(oname, namespaces))
1634 return Struct(self._ofind(oname, namespaces))
1625
1635
1626 def _inspect(self, meth, oname, namespaces=None, **kw):
1636 def _inspect(self, meth, oname, namespaces=None, **kw):
1627 """Generic interface to the inspector system.
1637 """Generic interface to the inspector system.
1628
1638
1629 This function is meant to be called by pdef, pdoc & friends.
1639 This function is meant to be called by pdef, pdoc & friends.
1630 """
1640 """
1631 info = self._object_find(oname, namespaces)
1641 info = self._object_find(oname, namespaces)
1632 docformat = (
1642 docformat = (
1633 sphinxify(self.object_inspect(oname)) if self.sphinxify_docstring else None
1643 sphinxify(self.object_inspect(oname)) if self.sphinxify_docstring else None
1634 )
1644 )
1635 if info.found:
1645 if info.found:
1636 pmethod = getattr(self.inspector, meth)
1646 pmethod = getattr(self.inspector, meth)
1637 # TODO: only apply format_screen to the plain/text repr of the mime
1647 # TODO: only apply format_screen to the plain/text repr of the mime
1638 # bundle.
1648 # bundle.
1639 formatter = format_screen if info.ismagic else docformat
1649 formatter = format_screen if info.ismagic else docformat
1640 if meth == 'pdoc':
1650 if meth == 'pdoc':
1641 pmethod(info.obj, oname, formatter)
1651 pmethod(info.obj, oname, formatter)
1642 elif meth == 'pinfo':
1652 elif meth == 'pinfo':
1643 pmethod(
1653 pmethod(
1644 info.obj,
1654 info.obj,
1645 oname,
1655 oname,
1646 formatter,
1656 formatter,
1647 info,
1657 info,
1648 enable_html_pager=self.enable_html_pager,
1658 enable_html_pager=self.enable_html_pager,
1649 **kw,
1659 **kw,
1650 )
1660 )
1651 else:
1661 else:
1652 pmethod(info.obj, oname)
1662 pmethod(info.obj, oname)
1653 else:
1663 else:
1654 print('Object `%s` not found.' % oname)
1664 print('Object `%s` not found.' % oname)
1655 return 'not found' # so callers can take other action
1665 return 'not found' # so callers can take other action
1656
1666
1657 def object_inspect(self, oname, detail_level=0):
1667 def object_inspect(self, oname, detail_level=0):
1658 """Get object info about oname"""
1668 """Get object info about oname"""
1659 with self.builtin_trap:
1669 with self.builtin_trap:
1660 info = self._object_find(oname)
1670 info = self._object_find(oname)
1661 if info.found:
1671 if info.found:
1662 return self.inspector.info(info.obj, oname, info=info,
1672 return self.inspector.info(info.obj, oname, info=info,
1663 detail_level=detail_level
1673 detail_level=detail_level
1664 )
1674 )
1665 else:
1675 else:
1666 return oinspect.object_info(name=oname, found=False)
1676 return oinspect.object_info(name=oname, found=False)
1667
1677
1668 def object_inspect_text(self, oname, detail_level=0):
1678 def object_inspect_text(self, oname, detail_level=0):
1669 """Get object info as formatted text"""
1679 """Get object info as formatted text"""
1670 return self.object_inspect_mime(oname, detail_level)['text/plain']
1680 return self.object_inspect_mime(oname, detail_level)['text/plain']
1671
1681
1672 def object_inspect_mime(self, oname, detail_level=0, omit_sections=()):
1682 def object_inspect_mime(self, oname, detail_level=0, omit_sections=()):
1673 """Get object info as a mimebundle of formatted representations.
1683 """Get object info as a mimebundle of formatted representations.
1674
1684
1675 A mimebundle is a dictionary, keyed by mime-type.
1685 A mimebundle is a dictionary, keyed by mime-type.
1676 It must always have the key `'text/plain'`.
1686 It must always have the key `'text/plain'`.
1677 """
1687 """
1678 with self.builtin_trap:
1688 with self.builtin_trap:
1679 info = self._object_find(oname)
1689 info = self._object_find(oname)
1680 if info.found:
1690 if info.found:
1681 docformat = (
1691 docformat = (
1682 sphinxify(self.object_inspect(oname))
1692 sphinxify(self.object_inspect(oname))
1683 if self.sphinxify_docstring
1693 if self.sphinxify_docstring
1684 else None
1694 else None
1685 )
1695 )
1686 return self.inspector._get_info(
1696 return self.inspector._get_info(
1687 info.obj,
1697 info.obj,
1688 oname,
1698 oname,
1689 info=info,
1699 info=info,
1690 detail_level=detail_level,
1700 detail_level=detail_level,
1691 formatter=docformat,
1701 formatter=docformat,
1692 omit_sections=omit_sections,
1702 omit_sections=omit_sections,
1693 )
1703 )
1694 else:
1704 else:
1695 raise KeyError(oname)
1705 raise KeyError(oname)
1696
1706
1697 #-------------------------------------------------------------------------
1707 #-------------------------------------------------------------------------
1698 # Things related to history management
1708 # Things related to history management
1699 #-------------------------------------------------------------------------
1709 #-------------------------------------------------------------------------
1700
1710
1701 def init_history(self):
1711 def init_history(self):
1702 """Sets up the command history, and starts regular autosaves."""
1712 """Sets up the command history, and starts regular autosaves."""
1703 self.history_manager = HistoryManager(shell=self, parent=self)
1713 self.history_manager = HistoryManager(shell=self, parent=self)
1704 self.configurables.append(self.history_manager)
1714 self.configurables.append(self.history_manager)
1705
1715
1706 #-------------------------------------------------------------------------
1716 #-------------------------------------------------------------------------
1707 # Things related to exception handling and tracebacks (not debugging)
1717 # Things related to exception handling and tracebacks (not debugging)
1708 #-------------------------------------------------------------------------
1718 #-------------------------------------------------------------------------
1709
1719
1710 debugger_cls = InterruptiblePdb
1720 debugger_cls = InterruptiblePdb
1711
1721
1712 def init_traceback_handlers(self, custom_exceptions):
1722 def init_traceback_handlers(self, custom_exceptions):
1713 # Syntax error handler.
1723 # Syntax error handler.
1714 self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor', parent=self)
1724 self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor', parent=self)
1715
1725
1716 # The interactive one is initialized with an offset, meaning we always
1726 # The interactive one is initialized with an offset, meaning we always
1717 # want to remove the topmost item in the traceback, which is our own
1727 # want to remove the topmost item in the traceback, which is our own
1718 # internal code. Valid modes: ['Plain','Context','Verbose','Minimal']
1728 # internal code. Valid modes: ['Plain','Context','Verbose','Minimal']
1719 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1729 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1720 color_scheme='NoColor',
1730 color_scheme='NoColor',
1721 tb_offset = 1,
1731 tb_offset = 1,
1722 check_cache=check_linecache_ipython,
1732 check_cache=check_linecache_ipython,
1723 debugger_cls=self.debugger_cls, parent=self)
1733 debugger_cls=self.debugger_cls, parent=self)
1724
1734
1725 # The instance will store a pointer to the system-wide exception hook,
1735 # The instance will store a pointer to the system-wide exception hook,
1726 # so that runtime code (such as magics) can access it. This is because
1736 # so that runtime code (such as magics) can access it. This is because
1727 # during the read-eval loop, it may get temporarily overwritten.
1737 # during the read-eval loop, it may get temporarily overwritten.
1728 self.sys_excepthook = sys.excepthook
1738 self.sys_excepthook = sys.excepthook
1729
1739
1730 # and add any custom exception handlers the user may have specified
1740 # and add any custom exception handlers the user may have specified
1731 self.set_custom_exc(*custom_exceptions)
1741 self.set_custom_exc(*custom_exceptions)
1732
1742
1733 # Set the exception mode
1743 # Set the exception mode
1734 self.InteractiveTB.set_mode(mode=self.xmode)
1744 self.InteractiveTB.set_mode(mode=self.xmode)
1735
1745
1736 def set_custom_exc(self, exc_tuple, handler):
1746 def set_custom_exc(self, exc_tuple, handler):
1737 """set_custom_exc(exc_tuple, handler)
1747 """set_custom_exc(exc_tuple, handler)
1738
1748
1739 Set a custom exception handler, which will be called if any of the
1749 Set a custom exception handler, which will be called if any of the
1740 exceptions in exc_tuple occur in the mainloop (specifically, in the
1750 exceptions in exc_tuple occur in the mainloop (specifically, in the
1741 run_code() method).
1751 run_code() method).
1742
1752
1743 Parameters
1753 Parameters
1744 ----------
1754 ----------
1745 exc_tuple : tuple of exception classes
1755 exc_tuple : tuple of exception classes
1746 A *tuple* of exception classes, for which to call the defined
1756 A *tuple* of exception classes, for which to call the defined
1747 handler. It is very important that you use a tuple, and NOT A
1757 handler. It is very important that you use a tuple, and NOT A
1748 LIST here, because of the way Python's except statement works. If
1758 LIST here, because of the way Python's except statement works. If
1749 you only want to trap a single exception, use a singleton tuple::
1759 you only want to trap a single exception, use a singleton tuple::
1750
1760
1751 exc_tuple == (MyCustomException,)
1761 exc_tuple == (MyCustomException,)
1752
1762
1753 handler : callable
1763 handler : callable
1754 handler must have the following signature::
1764 handler must have the following signature::
1755
1765
1756 def my_handler(self, etype, value, tb, tb_offset=None):
1766 def my_handler(self, etype, value, tb, tb_offset=None):
1757 ...
1767 ...
1758 return structured_traceback
1768 return structured_traceback
1759
1769
1760 Your handler must return a structured traceback (a list of strings),
1770 Your handler must return a structured traceback (a list of strings),
1761 or None.
1771 or None.
1762
1772
1763 This will be made into an instance method (via types.MethodType)
1773 This will be made into an instance method (via types.MethodType)
1764 of IPython itself, and it will be called if any of the exceptions
1774 of IPython itself, and it will be called if any of the exceptions
1765 listed in the exc_tuple are caught. If the handler is None, an
1775 listed in the exc_tuple are caught. If the handler is None, an
1766 internal basic one is used, which just prints basic info.
1776 internal basic one is used, which just prints basic info.
1767
1777
1768 To protect IPython from crashes, if your handler ever raises an
1778 To protect IPython from crashes, if your handler ever raises an
1769 exception or returns an invalid result, it will be immediately
1779 exception or returns an invalid result, it will be immediately
1770 disabled.
1780 disabled.
1771
1781
1772 Notes
1782 Notes
1773 -----
1783 -----
1774 WARNING: by putting in your own exception handler into IPython's main
1784 WARNING: by putting in your own exception handler into IPython's main
1775 execution loop, you run a very good chance of nasty crashes. This
1785 execution loop, you run a very good chance of nasty crashes. This
1776 facility should only be used if you really know what you are doing.
1786 facility should only be used if you really know what you are doing.
1777 """
1787 """
1778
1788
1779 if not isinstance(exc_tuple, tuple):
1789 if not isinstance(exc_tuple, tuple):
1780 raise TypeError("The custom exceptions must be given as a tuple.")
1790 raise TypeError("The custom exceptions must be given as a tuple.")
1781
1791
1782 def dummy_handler(self, etype, value, tb, tb_offset=None):
1792 def dummy_handler(self, etype, value, tb, tb_offset=None):
1783 print('*** Simple custom exception handler ***')
1793 print('*** Simple custom exception handler ***')
1784 print('Exception type :', etype)
1794 print('Exception type :', etype)
1785 print('Exception value:', value)
1795 print('Exception value:', value)
1786 print('Traceback :', tb)
1796 print('Traceback :', tb)
1787
1797
1788 def validate_stb(stb):
1798 def validate_stb(stb):
1789 """validate structured traceback return type
1799 """validate structured traceback return type
1790
1800
1791 return type of CustomTB *should* be a list of strings, but allow
1801 return type of CustomTB *should* be a list of strings, but allow
1792 single strings or None, which are harmless.
1802 single strings or None, which are harmless.
1793
1803
1794 This function will *always* return a list of strings,
1804 This function will *always* return a list of strings,
1795 and will raise a TypeError if stb is inappropriate.
1805 and will raise a TypeError if stb is inappropriate.
1796 """
1806 """
1797 msg = "CustomTB must return list of strings, not %r" % stb
1807 msg = "CustomTB must return list of strings, not %r" % stb
1798 if stb is None:
1808 if stb is None:
1799 return []
1809 return []
1800 elif isinstance(stb, str):
1810 elif isinstance(stb, str):
1801 return [stb]
1811 return [stb]
1802 elif not isinstance(stb, list):
1812 elif not isinstance(stb, list):
1803 raise TypeError(msg)
1813 raise TypeError(msg)
1804 # it's a list
1814 # it's a list
1805 for line in stb:
1815 for line in stb:
1806 # check every element
1816 # check every element
1807 if not isinstance(line, str):
1817 if not isinstance(line, str):
1808 raise TypeError(msg)
1818 raise TypeError(msg)
1809 return stb
1819 return stb
1810
1820
1811 if handler is None:
1821 if handler is None:
1812 wrapped = dummy_handler
1822 wrapped = dummy_handler
1813 else:
1823 else:
1814 def wrapped(self,etype,value,tb,tb_offset=None):
1824 def wrapped(self,etype,value,tb,tb_offset=None):
1815 """wrap CustomTB handler, to protect IPython from user code
1825 """wrap CustomTB handler, to protect IPython from user code
1816
1826
1817 This makes it harder (but not impossible) for custom exception
1827 This makes it harder (but not impossible) for custom exception
1818 handlers to crash IPython.
1828 handlers to crash IPython.
1819 """
1829 """
1820 try:
1830 try:
1821 stb = handler(self,etype,value,tb,tb_offset=tb_offset)
1831 stb = handler(self,etype,value,tb,tb_offset=tb_offset)
1822 return validate_stb(stb)
1832 return validate_stb(stb)
1823 except:
1833 except:
1824 # clear custom handler immediately
1834 # clear custom handler immediately
1825 self.set_custom_exc((), None)
1835 self.set_custom_exc((), None)
1826 print("Custom TB Handler failed, unregistering", file=sys.stderr)
1836 print("Custom TB Handler failed, unregistering", file=sys.stderr)
1827 # show the exception in handler first
1837 # show the exception in handler first
1828 stb = self.InteractiveTB.structured_traceback(*sys.exc_info())
1838 stb = self.InteractiveTB.structured_traceback(*sys.exc_info())
1829 print(self.InteractiveTB.stb2text(stb))
1839 print(self.InteractiveTB.stb2text(stb))
1830 print("The original exception:")
1840 print("The original exception:")
1831 stb = self.InteractiveTB.structured_traceback(
1841 stb = self.InteractiveTB.structured_traceback(
1832 (etype,value,tb), tb_offset=tb_offset
1842 (etype,value,tb), tb_offset=tb_offset
1833 )
1843 )
1834 return stb
1844 return stb
1835
1845
1836 self.CustomTB = types.MethodType(wrapped,self)
1846 self.CustomTB = types.MethodType(wrapped,self)
1837 self.custom_exceptions = exc_tuple
1847 self.custom_exceptions = exc_tuple
1838
1848
1839 def excepthook(self, etype, value, tb):
1849 def excepthook(self, etype, value, tb):
1840 """One more defense for GUI apps that call sys.excepthook.
1850 """One more defense for GUI apps that call sys.excepthook.
1841
1851
1842 GUI frameworks like wxPython trap exceptions and call
1852 GUI frameworks like wxPython trap exceptions and call
1843 sys.excepthook themselves. I guess this is a feature that
1853 sys.excepthook themselves. I guess this is a feature that
1844 enables them to keep running after exceptions that would
1854 enables them to keep running after exceptions that would
1845 otherwise kill their mainloop. This is a bother for IPython
1855 otherwise kill their mainloop. This is a bother for IPython
1846 which expects to catch all of the program exceptions with a try:
1856 which expects to catch all of the program exceptions with a try:
1847 except: statement.
1857 except: statement.
1848
1858
1849 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
1859 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
1850 any app directly invokes sys.excepthook, it will look to the user like
1860 any app directly invokes sys.excepthook, it will look to the user like
1851 IPython crashed. In order to work around this, we can disable the
1861 IPython crashed. In order to work around this, we can disable the
1852 CrashHandler and replace it with this excepthook instead, which prints a
1862 CrashHandler and replace it with this excepthook instead, which prints a
1853 regular traceback using our InteractiveTB. In this fashion, apps which
1863 regular traceback using our InteractiveTB. In this fashion, apps which
1854 call sys.excepthook will generate a regular-looking exception from
1864 call sys.excepthook will generate a regular-looking exception from
1855 IPython, and the CrashHandler will only be triggered by real IPython
1865 IPython, and the CrashHandler will only be triggered by real IPython
1856 crashes.
1866 crashes.
1857
1867
1858 This hook should be used sparingly, only in places which are not likely
1868 This hook should be used sparingly, only in places which are not likely
1859 to be true IPython errors.
1869 to be true IPython errors.
1860 """
1870 """
1861 self.showtraceback((etype, value, tb), tb_offset=0)
1871 self.showtraceback((etype, value, tb), tb_offset=0)
1862
1872
1863 def _get_exc_info(self, exc_tuple=None):
1873 def _get_exc_info(self, exc_tuple=None):
1864 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
1874 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
1865
1875
1866 Ensures sys.last_type,value,traceback hold the exc_info we found,
1876 Ensures sys.last_type,value,traceback hold the exc_info we found,
1867 from whichever source.
1877 from whichever source.
1868
1878
1869 raises ValueError if none of these contain any information
1879 raises ValueError if none of these contain any information
1870 """
1880 """
1871 if exc_tuple is None:
1881 if exc_tuple is None:
1872 etype, value, tb = sys.exc_info()
1882 etype, value, tb = sys.exc_info()
1873 else:
1883 else:
1874 etype, value, tb = exc_tuple
1884 etype, value, tb = exc_tuple
1875
1885
1876 if etype is None:
1886 if etype is None:
1877 if hasattr(sys, 'last_type'):
1887 if hasattr(sys, 'last_type'):
1878 etype, value, tb = sys.last_type, sys.last_value, \
1888 etype, value, tb = sys.last_type, sys.last_value, \
1879 sys.last_traceback
1889 sys.last_traceback
1880
1890
1881 if etype is None:
1891 if etype is None:
1882 raise ValueError("No exception to find")
1892 raise ValueError("No exception to find")
1883
1893
1884 # Now store the exception info in sys.last_type etc.
1894 # Now store the exception info in sys.last_type etc.
1885 # WARNING: these variables are somewhat deprecated and not
1895 # WARNING: these variables are somewhat deprecated and not
1886 # necessarily safe to use in a threaded environment, but tools
1896 # necessarily safe to use in a threaded environment, but tools
1887 # like pdb depend on their existence, so let's set them. If we
1897 # like pdb depend on their existence, so let's set them. If we
1888 # find problems in the field, we'll need to revisit their use.
1898 # find problems in the field, we'll need to revisit their use.
1889 sys.last_type = etype
1899 sys.last_type = etype
1890 sys.last_value = value
1900 sys.last_value = value
1891 sys.last_traceback = tb
1901 sys.last_traceback = tb
1892
1902
1893 return etype, value, tb
1903 return etype, value, tb
1894
1904
1895 def show_usage_error(self, exc):
1905 def show_usage_error(self, exc):
1896 """Show a short message for UsageErrors
1906 """Show a short message for UsageErrors
1897
1907
1898 These are special exceptions that shouldn't show a traceback.
1908 These are special exceptions that shouldn't show a traceback.
1899 """
1909 """
1900 print("UsageError: %s" % exc, file=sys.stderr)
1910 print("UsageError: %s" % exc, file=sys.stderr)
1901
1911
1902 def get_exception_only(self, exc_tuple=None):
1912 def get_exception_only(self, exc_tuple=None):
1903 """
1913 """
1904 Return as a string (ending with a newline) the exception that
1914 Return as a string (ending with a newline) the exception that
1905 just occurred, without any traceback.
1915 just occurred, without any traceback.
1906 """
1916 """
1907 etype, value, tb = self._get_exc_info(exc_tuple)
1917 etype, value, tb = self._get_exc_info(exc_tuple)
1908 msg = traceback.format_exception_only(etype, value)
1918 msg = traceback.format_exception_only(etype, value)
1909 return ''.join(msg)
1919 return ''.join(msg)
1910
1920
1911 def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None,
1921 def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None,
1912 exception_only=False, running_compiled_code=False):
1922 exception_only=False, running_compiled_code=False):
1913 """Display the exception that just occurred.
1923 """Display the exception that just occurred.
1914
1924
1915 If nothing is known about the exception, this is the method which
1925 If nothing is known about the exception, this is the method which
1916 should be used throughout the code for presenting user tracebacks,
1926 should be used throughout the code for presenting user tracebacks,
1917 rather than directly invoking the InteractiveTB object.
1927 rather than directly invoking the InteractiveTB object.
1918
1928
1919 A specific showsyntaxerror() also exists, but this method can take
1929 A specific showsyntaxerror() also exists, but this method can take
1920 care of calling it if needed, so unless you are explicitly catching a
1930 care of calling it if needed, so unless you are explicitly catching a
1921 SyntaxError exception, don't try to analyze the stack manually and
1931 SyntaxError exception, don't try to analyze the stack manually and
1922 simply call this method."""
1932 simply call this method."""
1923
1933
1924 try:
1934 try:
1925 try:
1935 try:
1926 etype, value, tb = self._get_exc_info(exc_tuple)
1936 etype, value, tb = self._get_exc_info(exc_tuple)
1927 except ValueError:
1937 except ValueError:
1928 print('No traceback available to show.', file=sys.stderr)
1938 print('No traceback available to show.', file=sys.stderr)
1929 return
1939 return
1930
1940
1931 if issubclass(etype, SyntaxError):
1941 if issubclass(etype, SyntaxError):
1932 # Though this won't be called by syntax errors in the input
1942 # Though this won't be called by syntax errors in the input
1933 # line, there may be SyntaxError cases with imported code.
1943 # line, there may be SyntaxError cases with imported code.
1934 self.showsyntaxerror(filename, running_compiled_code)
1944 self.showsyntaxerror(filename, running_compiled_code)
1935 elif etype is UsageError:
1945 elif etype is UsageError:
1936 self.show_usage_error(value)
1946 self.show_usage_error(value)
1937 else:
1947 else:
1938 if exception_only:
1948 if exception_only:
1939 stb = ['An exception has occurred, use %tb to see '
1949 stb = ['An exception has occurred, use %tb to see '
1940 'the full traceback.\n']
1950 'the full traceback.\n']
1941 stb.extend(self.InteractiveTB.get_exception_only(etype,
1951 stb.extend(self.InteractiveTB.get_exception_only(etype,
1942 value))
1952 value))
1943 else:
1953 else:
1944 try:
1954 try:
1945 # Exception classes can customise their traceback - we
1955 # Exception classes can customise their traceback - we
1946 # use this in IPython.parallel for exceptions occurring
1956 # use this in IPython.parallel for exceptions occurring
1947 # in the engines. This should return a list of strings.
1957 # in the engines. This should return a list of strings.
1948 stb = value._render_traceback_()
1958 stb = value._render_traceback_()
1949 except Exception:
1959 except Exception:
1950 stb = self.InteractiveTB.structured_traceback(etype,
1960 stb = self.InteractiveTB.structured_traceback(etype,
1951 value, tb, tb_offset=tb_offset)
1961 value, tb, tb_offset=tb_offset)
1952
1962
1953 self._showtraceback(etype, value, stb)
1963 self._showtraceback(etype, value, stb)
1954 if self.call_pdb:
1964 if self.call_pdb:
1955 # drop into debugger
1965 # drop into debugger
1956 self.debugger(force=True)
1966 self.debugger(force=True)
1957 return
1967 return
1958
1968
1959 # Actually show the traceback
1969 # Actually show the traceback
1960 self._showtraceback(etype, value, stb)
1970 self._showtraceback(etype, value, stb)
1961
1971
1962 except KeyboardInterrupt:
1972 except KeyboardInterrupt:
1963 print('\n' + self.get_exception_only(), file=sys.stderr)
1973 print('\n' + self.get_exception_only(), file=sys.stderr)
1964
1974
1965 def _showtraceback(self, etype, evalue, stb: str):
1975 def _showtraceback(self, etype, evalue, stb: str):
1966 """Actually show a traceback.
1976 """Actually show a traceback.
1967
1977
1968 Subclasses may override this method to put the traceback on a different
1978 Subclasses may override this method to put the traceback on a different
1969 place, like a side channel.
1979 place, like a side channel.
1970 """
1980 """
1971 val = self.InteractiveTB.stb2text(stb)
1981 val = self.InteractiveTB.stb2text(stb)
1972 try:
1982 try:
1973 print(val)
1983 print(val)
1974 except UnicodeEncodeError:
1984 except UnicodeEncodeError:
1975 print(val.encode("utf-8", "backslashreplace").decode())
1985 print(val.encode("utf-8", "backslashreplace").decode())
1976
1986
1977 def showsyntaxerror(self, filename=None, running_compiled_code=False):
1987 def showsyntaxerror(self, filename=None, running_compiled_code=False):
1978 """Display the syntax error that just occurred.
1988 """Display the syntax error that just occurred.
1979
1989
1980 This doesn't display a stack trace because there isn't one.
1990 This doesn't display a stack trace because there isn't one.
1981
1991
1982 If a filename is given, it is stuffed in the exception instead
1992 If a filename is given, it is stuffed in the exception instead
1983 of what was there before (because Python's parser always uses
1993 of what was there before (because Python's parser always uses
1984 "<string>" when reading from a string).
1994 "<string>" when reading from a string).
1985
1995
1986 If the syntax error occurred when running a compiled code (i.e. running_compile_code=True),
1996 If the syntax error occurred when running a compiled code (i.e. running_compile_code=True),
1987 longer stack trace will be displayed.
1997 longer stack trace will be displayed.
1988 """
1998 """
1989 etype, value, last_traceback = self._get_exc_info()
1999 etype, value, last_traceback = self._get_exc_info()
1990
2000
1991 if filename and issubclass(etype, SyntaxError):
2001 if filename and issubclass(etype, SyntaxError):
1992 try:
2002 try:
1993 value.filename = filename
2003 value.filename = filename
1994 except:
2004 except:
1995 # Not the format we expect; leave it alone
2005 # Not the format we expect; leave it alone
1996 pass
2006 pass
1997
2007
1998 # If the error occurred when executing compiled code, we should provide full stacktrace.
2008 # If the error occurred when executing compiled code, we should provide full stacktrace.
1999 elist = traceback.extract_tb(last_traceback) if running_compiled_code else []
2009 elist = traceback.extract_tb(last_traceback) if running_compiled_code else []
2000 stb = self.SyntaxTB.structured_traceback(etype, value, elist)
2010 stb = self.SyntaxTB.structured_traceback(etype, value, elist)
2001 self._showtraceback(etype, value, stb)
2011 self._showtraceback(etype, value, stb)
2002
2012
2003 # This is overridden in TerminalInteractiveShell to show a message about
2013 # This is overridden in TerminalInteractiveShell to show a message about
2004 # the %paste magic.
2014 # the %paste magic.
2005 def showindentationerror(self):
2015 def showindentationerror(self):
2006 """Called by _run_cell when there's an IndentationError in code entered
2016 """Called by _run_cell when there's an IndentationError in code entered
2007 at the prompt.
2017 at the prompt.
2008
2018
2009 This is overridden in TerminalInteractiveShell to show a message about
2019 This is overridden in TerminalInteractiveShell to show a message about
2010 the %paste magic."""
2020 the %paste magic."""
2011 self.showsyntaxerror()
2021 self.showsyntaxerror()
2012
2022
2013 @skip_doctest
2023 @skip_doctest
2014 def set_next_input(self, s, replace=False):
2024 def set_next_input(self, s, replace=False):
2015 """ Sets the 'default' input string for the next command line.
2025 """ Sets the 'default' input string for the next command line.
2016
2026
2017 Example::
2027 Example::
2018
2028
2019 In [1]: _ip.set_next_input("Hello Word")
2029 In [1]: _ip.set_next_input("Hello Word")
2020 In [2]: Hello Word_ # cursor is here
2030 In [2]: Hello Word_ # cursor is here
2021 """
2031 """
2022 self.rl_next_input = s
2032 self.rl_next_input = s
2023
2033
2024 def _indent_current_str(self):
2034 def _indent_current_str(self):
2025 """return the current level of indentation as a string"""
2035 """return the current level of indentation as a string"""
2026 return self.input_splitter.get_indent_spaces() * ' '
2036 return self.input_splitter.get_indent_spaces() * ' '
2027
2037
2028 #-------------------------------------------------------------------------
2038 #-------------------------------------------------------------------------
2029 # Things related to text completion
2039 # Things related to text completion
2030 #-------------------------------------------------------------------------
2040 #-------------------------------------------------------------------------
2031
2041
2032 def init_completer(self):
2042 def init_completer(self):
2033 """Initialize the completion machinery.
2043 """Initialize the completion machinery.
2034
2044
2035 This creates completion machinery that can be used by client code,
2045 This creates completion machinery that can be used by client code,
2036 either interactively in-process (typically triggered by the readline
2046 either interactively in-process (typically triggered by the readline
2037 library), programmatically (such as in test suites) or out-of-process
2047 library), programmatically (such as in test suites) or out-of-process
2038 (typically over the network by remote frontends).
2048 (typically over the network by remote frontends).
2039 """
2049 """
2040 from IPython.core.completer import IPCompleter
2050 from IPython.core.completer import IPCompleter
2041 from IPython.core.completerlib import (module_completer,
2051 from IPython.core.completerlib import (
2042 magic_run_completer, cd_completer, reset_completer)
2052 cd_completer,
2053 magic_run_completer,
2054 module_completer,
2055 reset_completer,
2056 )
2043
2057
2044 self.Completer = IPCompleter(shell=self,
2058 self.Completer = IPCompleter(shell=self,
2045 namespace=self.user_ns,
2059 namespace=self.user_ns,
2046 global_namespace=self.user_global_ns,
2060 global_namespace=self.user_global_ns,
2047 parent=self,
2061 parent=self,
2048 )
2062 )
2049 self.configurables.append(self.Completer)
2063 self.configurables.append(self.Completer)
2050
2064
2051 # Add custom completers to the basic ones built into IPCompleter
2065 # Add custom completers to the basic ones built into IPCompleter
2052 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
2066 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
2053 self.strdispatchers['complete_command'] = sdisp
2067 self.strdispatchers['complete_command'] = sdisp
2054 self.Completer.custom_completers = sdisp
2068 self.Completer.custom_completers = sdisp
2055
2069
2056 self.set_hook('complete_command', module_completer, str_key = 'import')
2070 self.set_hook('complete_command', module_completer, str_key = 'import')
2057 self.set_hook('complete_command', module_completer, str_key = 'from')
2071 self.set_hook('complete_command', module_completer, str_key = 'from')
2058 self.set_hook('complete_command', module_completer, str_key = '%aimport')
2072 self.set_hook('complete_command', module_completer, str_key = '%aimport')
2059 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
2073 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
2060 self.set_hook('complete_command', cd_completer, str_key = '%cd')
2074 self.set_hook('complete_command', cd_completer, str_key = '%cd')
2061 self.set_hook('complete_command', reset_completer, str_key = '%reset')
2075 self.set_hook('complete_command', reset_completer, str_key = '%reset')
2062
2076
2063 @skip_doctest
2077 @skip_doctest
2064 def complete(self, text, line=None, cursor_pos=None):
2078 def complete(self, text, line=None, cursor_pos=None):
2065 """Return the completed text and a list of completions.
2079 """Return the completed text and a list of completions.
2066
2080
2067 Parameters
2081 Parameters
2068 ----------
2082 ----------
2069 text : string
2083 text : string
2070 A string of text to be completed on. It can be given as empty and
2084 A string of text to be completed on. It can be given as empty and
2071 instead a line/position pair are given. In this case, the
2085 instead a line/position pair are given. In this case, the
2072 completer itself will split the line like readline does.
2086 completer itself will split the line like readline does.
2073 line : string, optional
2087 line : string, optional
2074 The complete line that text is part of.
2088 The complete line that text is part of.
2075 cursor_pos : int, optional
2089 cursor_pos : int, optional
2076 The position of the cursor on the input line.
2090 The position of the cursor on the input line.
2077
2091
2078 Returns
2092 Returns
2079 -------
2093 -------
2080 text : string
2094 text : string
2081 The actual text that was completed.
2095 The actual text that was completed.
2082 matches : list
2096 matches : list
2083 A sorted list with all possible completions.
2097 A sorted list with all possible completions.
2084
2098
2085 Notes
2099 Notes
2086 -----
2100 -----
2087 The optional arguments allow the completion to take more context into
2101 The optional arguments allow the completion to take more context into
2088 account, and are part of the low-level completion API.
2102 account, and are part of the low-level completion API.
2089
2103
2090 This is a wrapper around the completion mechanism, similar to what
2104 This is a wrapper around the completion mechanism, similar to what
2091 readline does at the command line when the TAB key is hit. By
2105 readline does at the command line when the TAB key is hit. By
2092 exposing it as a method, it can be used by other non-readline
2106 exposing it as a method, it can be used by other non-readline
2093 environments (such as GUIs) for text completion.
2107 environments (such as GUIs) for text completion.
2094
2108
2095 Examples
2109 Examples
2096 --------
2110 --------
2097 In [1]: x = 'hello'
2111 In [1]: x = 'hello'
2098
2112
2099 In [2]: _ip.complete('x.l')
2113 In [2]: _ip.complete('x.l')
2100 Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
2114 Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
2101 """
2115 """
2102
2116
2103 # Inject names into __builtin__ so we can complete on the added names.
2117 # Inject names into __builtin__ so we can complete on the added names.
2104 with self.builtin_trap:
2118 with self.builtin_trap:
2105 return self.Completer.complete(text, line, cursor_pos)
2119 return self.Completer.complete(text, line, cursor_pos)
2106
2120
2107 def set_custom_completer(self, completer, pos=0) -> None:
2121 def set_custom_completer(self, completer, pos=0) -> None:
2108 """Adds a new custom completer function.
2122 """Adds a new custom completer function.
2109
2123
2110 The position argument (defaults to 0) is the index in the completers
2124 The position argument (defaults to 0) is the index in the completers
2111 list where you want the completer to be inserted.
2125 list where you want the completer to be inserted.
2112
2126
2113 `completer` should have the following signature::
2127 `completer` should have the following signature::
2114
2128
2115 def completion(self: Completer, text: string) -> List[str]:
2129 def completion(self: Completer, text: string) -> List[str]:
2116 raise NotImplementedError
2130 raise NotImplementedError
2117
2131
2118 It will be bound to the current Completer instance and pass some text
2132 It will be bound to the current Completer instance and pass some text
2119 and return a list with current completions to suggest to the user.
2133 and return a list with current completions to suggest to the user.
2120 """
2134 """
2121
2135
2122 newcomp = types.MethodType(completer, self.Completer)
2136 newcomp = types.MethodType(completer, self.Completer)
2123 self.Completer.custom_matchers.insert(pos,newcomp)
2137 self.Completer.custom_matchers.insert(pos,newcomp)
2124
2138
2125 def set_completer_frame(self, frame=None):
2139 def set_completer_frame(self, frame=None):
2126 """Set the frame of the completer."""
2140 """Set the frame of the completer."""
2127 if frame:
2141 if frame:
2128 self.Completer.namespace = frame.f_locals
2142 self.Completer.namespace = frame.f_locals
2129 self.Completer.global_namespace = frame.f_globals
2143 self.Completer.global_namespace = frame.f_globals
2130 else:
2144 else:
2131 self.Completer.namespace = self.user_ns
2145 self.Completer.namespace = self.user_ns
2132 self.Completer.global_namespace = self.user_global_ns
2146 self.Completer.global_namespace = self.user_global_ns
2133
2147
2134 #-------------------------------------------------------------------------
2148 #-------------------------------------------------------------------------
2135 # Things related to magics
2149 # Things related to magics
2136 #-------------------------------------------------------------------------
2150 #-------------------------------------------------------------------------
2137
2151
2138 def init_magics(self):
2152 def init_magics(self):
2139 from IPython.core import magics as m
2153 from IPython.core import magics as m
2140 self.magics_manager = magic.MagicsManager(shell=self,
2154 self.magics_manager = magic.MagicsManager(shell=self,
2141 parent=self,
2155 parent=self,
2142 user_magics=m.UserMagics(self))
2156 user_magics=m.UserMagics(self))
2143 self.configurables.append(self.magics_manager)
2157 self.configurables.append(self.magics_manager)
2144
2158
2145 # Expose as public API from the magics manager
2159 # Expose as public API from the magics manager
2146 self.register_magics = self.magics_manager.register
2160 self.register_magics = self.magics_manager.register
2147
2161
2148 self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics,
2162 self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics,
2149 m.ConfigMagics, m.DisplayMagics, m.ExecutionMagics,
2163 m.ConfigMagics, m.DisplayMagics, m.ExecutionMagics,
2150 m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics,
2164 m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics,
2151 m.NamespaceMagics, m.OSMagics, m.PackagingMagics,
2165 m.NamespaceMagics, m.OSMagics, m.PackagingMagics,
2152 m.PylabMagics, m.ScriptMagics,
2166 m.PylabMagics, m.ScriptMagics,
2153 )
2167 )
2154 self.register_magics(m.AsyncMagics)
2168 self.register_magics(m.AsyncMagics)
2155
2169
2156 # Register Magic Aliases
2170 # Register Magic Aliases
2157 mman = self.magics_manager
2171 mman = self.magics_manager
2158 # FIXME: magic aliases should be defined by the Magics classes
2172 # FIXME: magic aliases should be defined by the Magics classes
2159 # or in MagicsManager, not here
2173 # or in MagicsManager, not here
2160 mman.register_alias('ed', 'edit')
2174 mman.register_alias('ed', 'edit')
2161 mman.register_alias('hist', 'history')
2175 mman.register_alias('hist', 'history')
2162 mman.register_alias('rep', 'recall')
2176 mman.register_alias('rep', 'recall')
2163 mman.register_alias('SVG', 'svg', 'cell')
2177 mman.register_alias('SVG', 'svg', 'cell')
2164 mman.register_alias('HTML', 'html', 'cell')
2178 mman.register_alias('HTML', 'html', 'cell')
2165 mman.register_alias('file', 'writefile', 'cell')
2179 mman.register_alias('file', 'writefile', 'cell')
2166
2180
2167 # FIXME: Move the color initialization to the DisplayHook, which
2181 # FIXME: Move the color initialization to the DisplayHook, which
2168 # should be split into a prompt manager and displayhook. We probably
2182 # should be split into a prompt manager and displayhook. We probably
2169 # even need a centralize colors management object.
2183 # even need a centralize colors management object.
2170 self.run_line_magic('colors', self.colors)
2184 self.run_line_magic('colors', self.colors)
2171
2185
2172 # Defined here so that it's included in the documentation
2186 # Defined here so that it's included in the documentation
2173 @functools.wraps(magic.MagicsManager.register_function)
2187 @functools.wraps(magic.MagicsManager.register_function)
2174 def register_magic_function(self, func, magic_kind='line', magic_name=None):
2188 def register_magic_function(self, func, magic_kind='line', magic_name=None):
2175 self.magics_manager.register_function(
2189 self.magics_manager.register_function(
2176 func, magic_kind=magic_kind, magic_name=magic_name
2190 func, magic_kind=magic_kind, magic_name=magic_name
2177 )
2191 )
2178
2192
2179 def _find_with_lazy_load(self, /, type_, magic_name: str):
2193 def _find_with_lazy_load(self, /, type_, magic_name: str):
2180 """
2194 """
2181 Try to find a magic potentially lazy-loading it.
2195 Try to find a magic potentially lazy-loading it.
2182
2196
2183 Parameters
2197 Parameters
2184 ----------
2198 ----------
2185
2199
2186 type_: "line"|"cell"
2200 type_: "line"|"cell"
2187 the type of magics we are trying to find/lazy load.
2201 the type of magics we are trying to find/lazy load.
2188 magic_name: str
2202 magic_name: str
2189 The name of the magic we are trying to find/lazy load
2203 The name of the magic we are trying to find/lazy load
2190
2204
2191
2205
2192 Note that this may have any side effects
2206 Note that this may have any side effects
2193 """
2207 """
2194 finder = {"line": self.find_line_magic, "cell": self.find_cell_magic}[type_]
2208 finder = {"line": self.find_line_magic, "cell": self.find_cell_magic}[type_]
2195 fn = finder(magic_name)
2209 fn = finder(magic_name)
2196 if fn is not None:
2210 if fn is not None:
2197 return fn
2211 return fn
2198 lazy = self.magics_manager.lazy_magics.get(magic_name)
2212 lazy = self.magics_manager.lazy_magics.get(magic_name)
2199 if lazy is None:
2213 if lazy is None:
2200 return None
2214 return None
2201
2215
2202 self.run_line_magic("load_ext", lazy)
2216 self.run_line_magic("load_ext", lazy)
2203 res = finder(magic_name)
2217 res = finder(magic_name)
2204 return res
2218 return res
2205
2219
2206 def run_line_magic(self, magic_name: str, line, _stack_depth=1):
2220 def run_line_magic(self, magic_name: str, line, _stack_depth=1):
2207 """Execute the given line magic.
2221 """Execute the given line magic.
2208
2222
2209 Parameters
2223 Parameters
2210 ----------
2224 ----------
2211 magic_name : str
2225 magic_name : str
2212 Name of the desired magic function, without '%' prefix.
2226 Name of the desired magic function, without '%' prefix.
2213 line : str
2227 line : str
2214 The rest of the input line as a single string.
2228 The rest of the input line as a single string.
2215 _stack_depth : int
2229 _stack_depth : int
2216 If run_line_magic() is called from magic() then _stack_depth=2.
2230 If run_line_magic() is called from magic() then _stack_depth=2.
2217 This is added to ensure backward compatibility for use of 'get_ipython().magic()'
2231 This is added to ensure backward compatibility for use of 'get_ipython().magic()'
2218 """
2232 """
2219 fn = self._find_with_lazy_load("line", magic_name)
2233 fn = self._find_with_lazy_load("line", magic_name)
2220 if fn is None:
2234 if fn is None:
2221 lazy = self.magics_manager.lazy_magics.get(magic_name)
2235 lazy = self.magics_manager.lazy_magics.get(magic_name)
2222 if lazy:
2236 if lazy:
2223 self.run_line_magic("load_ext", lazy)
2237 self.run_line_magic("load_ext", lazy)
2224 fn = self.find_line_magic(magic_name)
2238 fn = self.find_line_magic(magic_name)
2225 if fn is None:
2239 if fn is None:
2226 cm = self.find_cell_magic(magic_name)
2240 cm = self.find_cell_magic(magic_name)
2227 etpl = "Line magic function `%%%s` not found%s."
2241 etpl = "Line magic function `%%%s` not found%s."
2228 extra = '' if cm is None else (' (But cell magic `%%%%%s` exists, '
2242 extra = '' if cm is None else (' (But cell magic `%%%%%s` exists, '
2229 'did you mean that instead?)' % magic_name )
2243 'did you mean that instead?)' % magic_name )
2230 raise UsageError(etpl % (magic_name, extra))
2244 raise UsageError(etpl % (magic_name, extra))
2231 else:
2245 else:
2232 # Note: this is the distance in the stack to the user's frame.
2246 # Note: this is the distance in the stack to the user's frame.
2233 # This will need to be updated if the internal calling logic gets
2247 # This will need to be updated if the internal calling logic gets
2234 # refactored, or else we'll be expanding the wrong variables.
2248 # refactored, or else we'll be expanding the wrong variables.
2235
2249
2236 # Determine stack_depth depending on where run_line_magic() has been called
2250 # Determine stack_depth depending on where run_line_magic() has been called
2237 stack_depth = _stack_depth
2251 stack_depth = _stack_depth
2238 if getattr(fn, magic.MAGIC_NO_VAR_EXPAND_ATTR, False):
2252 if getattr(fn, magic.MAGIC_NO_VAR_EXPAND_ATTR, False):
2239 # magic has opted out of var_expand
2253 # magic has opted out of var_expand
2240 magic_arg_s = line
2254 magic_arg_s = line
2241 else:
2255 else:
2242 magic_arg_s = self.var_expand(line, stack_depth)
2256 magic_arg_s = self.var_expand(line, stack_depth)
2243 # Put magic args in a list so we can call with f(*a) syntax
2257 # Put magic args in a list so we can call with f(*a) syntax
2244 args = [magic_arg_s]
2258 args = [magic_arg_s]
2245 kwargs = {}
2259 kwargs = {}
2246 # Grab local namespace if we need it:
2260 # Grab local namespace if we need it:
2247 if getattr(fn, "needs_local_scope", False):
2261 if getattr(fn, "needs_local_scope", False):
2248 kwargs['local_ns'] = self.get_local_scope(stack_depth)
2262 kwargs['local_ns'] = self.get_local_scope(stack_depth)
2249 with self.builtin_trap:
2263 with self.builtin_trap:
2250 result = fn(*args, **kwargs)
2264 result = fn(*args, **kwargs)
2251 return result
2265 return result
2252
2266
2253 def get_local_scope(self, stack_depth):
2267 def get_local_scope(self, stack_depth):
2254 """Get local scope at given stack depth.
2268 """Get local scope at given stack depth.
2255
2269
2256 Parameters
2270 Parameters
2257 ----------
2271 ----------
2258 stack_depth : int
2272 stack_depth : int
2259 Depth relative to calling frame
2273 Depth relative to calling frame
2260 """
2274 """
2261 return sys._getframe(stack_depth + 1).f_locals
2275 return sys._getframe(stack_depth + 1).f_locals
2262
2276
2263 def run_cell_magic(self, magic_name, line, cell):
2277 def run_cell_magic(self, magic_name, line, cell):
2264 """Execute the given cell magic.
2278 """Execute the given cell magic.
2265
2279
2266 Parameters
2280 Parameters
2267 ----------
2281 ----------
2268 magic_name : str
2282 magic_name : str
2269 Name of the desired magic function, without '%' prefix.
2283 Name of the desired magic function, without '%' prefix.
2270 line : str
2284 line : str
2271 The rest of the first input line as a single string.
2285 The rest of the first input line as a single string.
2272 cell : str
2286 cell : str
2273 The body of the cell as a (possibly multiline) string.
2287 The body of the cell as a (possibly multiline) string.
2274 """
2288 """
2275 fn = self._find_with_lazy_load("cell", magic_name)
2289 fn = self._find_with_lazy_load("cell", magic_name)
2276 if fn is None:
2290 if fn is None:
2277 lm = self.find_line_magic(magic_name)
2291 lm = self.find_line_magic(magic_name)
2278 etpl = "Cell magic `%%{0}` not found{1}."
2292 etpl = "Cell magic `%%{0}` not found{1}."
2279 extra = '' if lm is None else (' (But line magic `%{0}` exists, '
2293 extra = '' if lm is None else (' (But line magic `%{0}` exists, '
2280 'did you mean that instead?)'.format(magic_name))
2294 'did you mean that instead?)'.format(magic_name))
2281 raise UsageError(etpl.format(magic_name, extra))
2295 raise UsageError(etpl.format(magic_name, extra))
2282 elif cell == '':
2296 elif cell == '':
2283 message = '%%{0} is a cell magic, but the cell body is empty.'.format(magic_name)
2297 message = '%%{0} is a cell magic, but the cell body is empty.'.format(magic_name)
2284 if self.find_line_magic(magic_name) is not None:
2298 if self.find_line_magic(magic_name) is not None:
2285 message += ' Did you mean the line magic %{0} (single %)?'.format(magic_name)
2299 message += ' Did you mean the line magic %{0} (single %)?'.format(magic_name)
2286 raise UsageError(message)
2300 raise UsageError(message)
2287 else:
2301 else:
2288 # Note: this is the distance in the stack to the user's frame.
2302 # Note: this is the distance in the stack to the user's frame.
2289 # This will need to be updated if the internal calling logic gets
2303 # This will need to be updated if the internal calling logic gets
2290 # refactored, or else we'll be expanding the wrong variables.
2304 # refactored, or else we'll be expanding the wrong variables.
2291 stack_depth = 2
2305 stack_depth = 2
2292 if getattr(fn, magic.MAGIC_NO_VAR_EXPAND_ATTR, False):
2306 if getattr(fn, magic.MAGIC_NO_VAR_EXPAND_ATTR, False):
2293 # magic has opted out of var_expand
2307 # magic has opted out of var_expand
2294 magic_arg_s = line
2308 magic_arg_s = line
2295 else:
2309 else:
2296 magic_arg_s = self.var_expand(line, stack_depth)
2310 magic_arg_s = self.var_expand(line, stack_depth)
2297 kwargs = {}
2311 kwargs = {}
2298 if getattr(fn, "needs_local_scope", False):
2312 if getattr(fn, "needs_local_scope", False):
2299 kwargs['local_ns'] = self.user_ns
2313 kwargs['local_ns'] = self.user_ns
2300
2314
2301 with self.builtin_trap:
2315 with self.builtin_trap:
2302 args = (magic_arg_s, cell)
2316 args = (magic_arg_s, cell)
2303 result = fn(*args, **kwargs)
2317 result = fn(*args, **kwargs)
2304 return result
2318 return result
2305
2319
2306 def find_line_magic(self, magic_name):
2320 def find_line_magic(self, magic_name):
2307 """Find and return a line magic by name.
2321 """Find and return a line magic by name.
2308
2322
2309 Returns None if the magic isn't found."""
2323 Returns None if the magic isn't found."""
2310 return self.magics_manager.magics['line'].get(magic_name)
2324 return self.magics_manager.magics['line'].get(magic_name)
2311
2325
2312 def find_cell_magic(self, magic_name):
2326 def find_cell_magic(self, magic_name):
2313 """Find and return a cell magic by name.
2327 """Find and return a cell magic by name.
2314
2328
2315 Returns None if the magic isn't found."""
2329 Returns None if the magic isn't found."""
2316 return self.magics_manager.magics['cell'].get(magic_name)
2330 return self.magics_manager.magics['cell'].get(magic_name)
2317
2331
2318 def find_magic(self, magic_name, magic_kind='line'):
2332 def find_magic(self, magic_name, magic_kind='line'):
2319 """Find and return a magic of the given type by name.
2333 """Find and return a magic of the given type by name.
2320
2334
2321 Returns None if the magic isn't found."""
2335 Returns None if the magic isn't found."""
2322 return self.magics_manager.magics[magic_kind].get(magic_name)
2336 return self.magics_manager.magics[magic_kind].get(magic_name)
2323
2337
2324 def magic(self, arg_s):
2338 def magic(self, arg_s):
2325 """
2339 """
2326 DEPRECATED
2340 DEPRECATED
2327
2341
2328 Deprecated since IPython 0.13 (warning added in
2342 Deprecated since IPython 0.13 (warning added in
2329 8.1), use run_line_magic(magic_name, parameter_s).
2343 8.1), use run_line_magic(magic_name, parameter_s).
2330
2344
2331 Call a magic function by name.
2345 Call a magic function by name.
2332
2346
2333 Input: a string containing the name of the magic function to call and
2347 Input: a string containing the name of the magic function to call and
2334 any additional arguments to be passed to the magic.
2348 any additional arguments to be passed to the magic.
2335
2349
2336 magic('name -opt foo bar') is equivalent to typing at the ipython
2350 magic('name -opt foo bar') is equivalent to typing at the ipython
2337 prompt:
2351 prompt:
2338
2352
2339 In[1]: %name -opt foo bar
2353 In[1]: %name -opt foo bar
2340
2354
2341 To call a magic without arguments, simply use magic('name').
2355 To call a magic without arguments, simply use magic('name').
2342
2356
2343 This provides a proper Python function to call IPython's magics in any
2357 This provides a proper Python function to call IPython's magics in any
2344 valid Python code you can type at the interpreter, including loops and
2358 valid Python code you can type at the interpreter, including loops and
2345 compound statements.
2359 compound statements.
2346 """
2360 """
2347 warnings.warn(
2361 warnings.warn(
2348 "`magic(...)` is deprecated since IPython 0.13 (warning added in "
2362 "`magic(...)` is deprecated since IPython 0.13 (warning added in "
2349 "8.1), use run_line_magic(magic_name, parameter_s).",
2363 "8.1), use run_line_magic(magic_name, parameter_s).",
2350 DeprecationWarning,
2364 DeprecationWarning,
2351 stacklevel=2,
2365 stacklevel=2,
2352 )
2366 )
2353 # TODO: should we issue a loud deprecation warning here?
2367 # TODO: should we issue a loud deprecation warning here?
2354 magic_name, _, magic_arg_s = arg_s.partition(' ')
2368 magic_name, _, magic_arg_s = arg_s.partition(' ')
2355 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
2369 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
2356 return self.run_line_magic(magic_name, magic_arg_s, _stack_depth=2)
2370 return self.run_line_magic(magic_name, magic_arg_s, _stack_depth=2)
2357
2371
2358 #-------------------------------------------------------------------------
2372 #-------------------------------------------------------------------------
2359 # Things related to macros
2373 # Things related to macros
2360 #-------------------------------------------------------------------------
2374 #-------------------------------------------------------------------------
2361
2375
2362 def define_macro(self, name, themacro):
2376 def define_macro(self, name, themacro):
2363 """Define a new macro
2377 """Define a new macro
2364
2378
2365 Parameters
2379 Parameters
2366 ----------
2380 ----------
2367 name : str
2381 name : str
2368 The name of the macro.
2382 The name of the macro.
2369 themacro : str or Macro
2383 themacro : str or Macro
2370 The action to do upon invoking the macro. If a string, a new
2384 The action to do upon invoking the macro. If a string, a new
2371 Macro object is created by passing the string to it.
2385 Macro object is created by passing the string to it.
2372 """
2386 """
2373
2387
2374 from IPython.core import macro
2388 from IPython.core import macro
2375
2389
2376 if isinstance(themacro, str):
2390 if isinstance(themacro, str):
2377 themacro = macro.Macro(themacro)
2391 themacro = macro.Macro(themacro)
2378 if not isinstance(themacro, macro.Macro):
2392 if not isinstance(themacro, macro.Macro):
2379 raise ValueError('A macro must be a string or a Macro instance.')
2393 raise ValueError('A macro must be a string or a Macro instance.')
2380 self.user_ns[name] = themacro
2394 self.user_ns[name] = themacro
2381
2395
2382 #-------------------------------------------------------------------------
2396 #-------------------------------------------------------------------------
2383 # Things related to the running of system commands
2397 # Things related to the running of system commands
2384 #-------------------------------------------------------------------------
2398 #-------------------------------------------------------------------------
2385
2399
2386 def system_piped(self, cmd):
2400 def system_piped(self, cmd):
2387 """Call the given cmd in a subprocess, piping stdout/err
2401 """Call the given cmd in a subprocess, piping stdout/err
2388
2402
2389 Parameters
2403 Parameters
2390 ----------
2404 ----------
2391 cmd : str
2405 cmd : str
2392 Command to execute (can not end in '&', as background processes are
2406 Command to execute (can not end in '&', as background processes are
2393 not supported. Should not be a command that expects input
2407 not supported. Should not be a command that expects input
2394 other than simple text.
2408 other than simple text.
2395 """
2409 """
2396 if cmd.rstrip().endswith('&'):
2410 if cmd.rstrip().endswith('&'):
2397 # this is *far* from a rigorous test
2411 # this is *far* from a rigorous test
2398 # We do not support backgrounding processes because we either use
2412 # We do not support backgrounding processes because we either use
2399 # pexpect or pipes to read from. Users can always just call
2413 # pexpect or pipes to read from. Users can always just call
2400 # os.system() or use ip.system=ip.system_raw
2414 # os.system() or use ip.system=ip.system_raw
2401 # if they really want a background process.
2415 # if they really want a background process.
2402 raise OSError("Background processes not supported.")
2416 raise OSError("Background processes not supported.")
2403
2417
2404 # we explicitly do NOT return the subprocess status code, because
2418 # we explicitly do NOT return the subprocess status code, because
2405 # a non-None value would trigger :func:`sys.displayhook` calls.
2419 # a non-None value would trigger :func:`sys.displayhook` calls.
2406 # Instead, we store the exit_code in user_ns.
2420 # Instead, we store the exit_code in user_ns.
2407 self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1))
2421 self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1))
2408
2422
2409 def system_raw(self, cmd):
2423 def system_raw(self, cmd):
2410 """Call the given cmd in a subprocess using os.system on Windows or
2424 """Call the given cmd in a subprocess using os.system on Windows or
2411 subprocess.call using the system shell on other platforms.
2425 subprocess.call using the system shell on other platforms.
2412
2426
2413 Parameters
2427 Parameters
2414 ----------
2428 ----------
2415 cmd : str
2429 cmd : str
2416 Command to execute.
2430 Command to execute.
2417 """
2431 """
2418 cmd = self.var_expand(cmd, depth=1)
2432 cmd = self.var_expand(cmd, depth=1)
2419 # warn if there is an IPython magic alternative.
2433 # warn if there is an IPython magic alternative.
2420 main_cmd = cmd.split()[0]
2434 main_cmd = cmd.split()[0]
2421 has_magic_alternatives = ("pip", "conda", "cd")
2435 has_magic_alternatives = ("pip", "conda", "cd")
2422
2436
2423 if main_cmd in has_magic_alternatives:
2437 if main_cmd in has_magic_alternatives:
2424 warnings.warn(
2438 warnings.warn(
2425 (
2439 (
2426 "You executed the system command !{0} which may not work "
2440 "You executed the system command !{0} which may not work "
2427 "as expected. Try the IPython magic %{0} instead."
2441 "as expected. Try the IPython magic %{0} instead."
2428 ).format(main_cmd)
2442 ).format(main_cmd)
2429 )
2443 )
2430
2444
2431 # protect os.system from UNC paths on Windows, which it can't handle:
2445 # protect os.system from UNC paths on Windows, which it can't handle:
2432 if sys.platform == 'win32':
2446 if sys.platform == 'win32':
2433 from IPython.utils._process_win32 import AvoidUNCPath
2447 from IPython.utils._process_win32 import AvoidUNCPath
2434 with AvoidUNCPath() as path:
2448 with AvoidUNCPath() as path:
2435 if path is not None:
2449 if path is not None:
2436 cmd = '"pushd %s &&"%s' % (path, cmd)
2450 cmd = '"pushd %s &&"%s' % (path, cmd)
2437 try:
2451 try:
2438 ec = os.system(cmd)
2452 ec = os.system(cmd)
2439 except KeyboardInterrupt:
2453 except KeyboardInterrupt:
2440 print('\n' + self.get_exception_only(), file=sys.stderr)
2454 print('\n' + self.get_exception_only(), file=sys.stderr)
2441 ec = -2
2455 ec = -2
2442 else:
2456 else:
2443 # For posix the result of the subprocess.call() below is an exit
2457 # For posix the result of the subprocess.call() below is an exit
2444 # code, which by convention is zero for success, positive for
2458 # code, which by convention is zero for success, positive for
2445 # program failure. Exit codes above 128 are reserved for signals,
2459 # program failure. Exit codes above 128 are reserved for signals,
2446 # and the formula for converting a signal to an exit code is usually
2460 # and the formula for converting a signal to an exit code is usually
2447 # signal_number+128. To more easily differentiate between exit
2461 # signal_number+128. To more easily differentiate between exit
2448 # codes and signals, ipython uses negative numbers. For instance
2462 # codes and signals, ipython uses negative numbers. For instance
2449 # since control-c is signal 2 but exit code 130, ipython's
2463 # since control-c is signal 2 but exit code 130, ipython's
2450 # _exit_code variable will read -2. Note that some shells like
2464 # _exit_code variable will read -2. Note that some shells like
2451 # csh and fish don't follow sh/bash conventions for exit codes.
2465 # csh and fish don't follow sh/bash conventions for exit codes.
2452 executable = os.environ.get('SHELL', None)
2466 executable = os.environ.get('SHELL', None)
2453 try:
2467 try:
2454 # Use env shell instead of default /bin/sh
2468 # Use env shell instead of default /bin/sh
2455 ec = subprocess.call(cmd, shell=True, executable=executable)
2469 ec = subprocess.call(cmd, shell=True, executable=executable)
2456 except KeyboardInterrupt:
2470 except KeyboardInterrupt:
2457 # intercept control-C; a long traceback is not useful here
2471 # intercept control-C; a long traceback is not useful here
2458 print('\n' + self.get_exception_only(), file=sys.stderr)
2472 print('\n' + self.get_exception_only(), file=sys.stderr)
2459 ec = 130
2473 ec = 130
2460 if ec > 128:
2474 if ec > 128:
2461 ec = -(ec - 128)
2475 ec = -(ec - 128)
2462
2476
2463 # We explicitly do NOT return the subprocess status code, because
2477 # We explicitly do NOT return the subprocess status code, because
2464 # a non-None value would trigger :func:`sys.displayhook` calls.
2478 # a non-None value would trigger :func:`sys.displayhook` calls.
2465 # Instead, we store the exit_code in user_ns. Note the semantics
2479 # Instead, we store the exit_code in user_ns. Note the semantics
2466 # of _exit_code: for control-c, _exit_code == -signal.SIGNIT,
2480 # of _exit_code: for control-c, _exit_code == -signal.SIGNIT,
2467 # but raising SystemExit(_exit_code) will give status 254!
2481 # but raising SystemExit(_exit_code) will give status 254!
2468 self.user_ns['_exit_code'] = ec
2482 self.user_ns['_exit_code'] = ec
2469
2483
2470 # use piped system by default, because it is better behaved
2484 # use piped system by default, because it is better behaved
2471 system = system_piped
2485 system = system_piped
2472
2486
2473 def getoutput(self, cmd, split=True, depth=0):
2487 def getoutput(self, cmd, split=True, depth=0):
2474 """Get output (possibly including stderr) from a subprocess.
2488 """Get output (possibly including stderr) from a subprocess.
2475
2489
2476 Parameters
2490 Parameters
2477 ----------
2491 ----------
2478 cmd : str
2492 cmd : str
2479 Command to execute (can not end in '&', as background processes are
2493 Command to execute (can not end in '&', as background processes are
2480 not supported.
2494 not supported.
2481 split : bool, optional
2495 split : bool, optional
2482 If True, split the output into an IPython SList. Otherwise, an
2496 If True, split the output into an IPython SList. Otherwise, an
2483 IPython LSString is returned. These are objects similar to normal
2497 IPython LSString is returned. These are objects similar to normal
2484 lists and strings, with a few convenience attributes for easier
2498 lists and strings, with a few convenience attributes for easier
2485 manipulation of line-based output. You can use '?' on them for
2499 manipulation of line-based output. You can use '?' on them for
2486 details.
2500 details.
2487 depth : int, optional
2501 depth : int, optional
2488 How many frames above the caller are the local variables which should
2502 How many frames above the caller are the local variables which should
2489 be expanded in the command string? The default (0) assumes that the
2503 be expanded in the command string? The default (0) assumes that the
2490 expansion variables are in the stack frame calling this function.
2504 expansion variables are in the stack frame calling this function.
2491 """
2505 """
2492 if cmd.rstrip().endswith('&'):
2506 if cmd.rstrip().endswith('&'):
2493 # this is *far* from a rigorous test
2507 # this is *far* from a rigorous test
2494 raise OSError("Background processes not supported.")
2508 raise OSError("Background processes not supported.")
2495 out = getoutput(self.var_expand(cmd, depth=depth+1))
2509 out = getoutput(self.var_expand(cmd, depth=depth+1))
2496 if split:
2510 if split:
2497 out = SList(out.splitlines())
2511 out = SList(out.splitlines())
2498 else:
2512 else:
2499 out = LSString(out)
2513 out = LSString(out)
2500 return out
2514 return out
2501
2515
2502 #-------------------------------------------------------------------------
2516 #-------------------------------------------------------------------------
2503 # Things related to aliases
2517 # Things related to aliases
2504 #-------------------------------------------------------------------------
2518 #-------------------------------------------------------------------------
2505
2519
2506 def init_alias(self):
2520 def init_alias(self):
2507 self.alias_manager = AliasManager(shell=self, parent=self)
2521 self.alias_manager = AliasManager(shell=self, parent=self)
2508 self.configurables.append(self.alias_manager)
2522 self.configurables.append(self.alias_manager)
2509
2523
2510 #-------------------------------------------------------------------------
2524 #-------------------------------------------------------------------------
2511 # Things related to extensions
2525 # Things related to extensions
2512 #-------------------------------------------------------------------------
2526 #-------------------------------------------------------------------------
2513
2527
2514 def init_extension_manager(self):
2528 def init_extension_manager(self):
2515 self.extension_manager = ExtensionManager(shell=self, parent=self)
2529 self.extension_manager = ExtensionManager(shell=self, parent=self)
2516 self.configurables.append(self.extension_manager)
2530 self.configurables.append(self.extension_manager)
2517
2531
2518 #-------------------------------------------------------------------------
2532 #-------------------------------------------------------------------------
2519 # Things related to payloads
2533 # Things related to payloads
2520 #-------------------------------------------------------------------------
2534 #-------------------------------------------------------------------------
2521
2535
2522 def init_payload(self):
2536 def init_payload(self):
2523 self.payload_manager = PayloadManager(parent=self)
2537 self.payload_manager = PayloadManager(parent=self)
2524 self.configurables.append(self.payload_manager)
2538 self.configurables.append(self.payload_manager)
2525
2539
2526 #-------------------------------------------------------------------------
2540 #-------------------------------------------------------------------------
2527 # Things related to the prefilter
2541 # Things related to the prefilter
2528 #-------------------------------------------------------------------------
2542 #-------------------------------------------------------------------------
2529
2543
2530 def init_prefilter(self):
2544 def init_prefilter(self):
2531 self.prefilter_manager = PrefilterManager(shell=self, parent=self)
2545 self.prefilter_manager = PrefilterManager(shell=self, parent=self)
2532 self.configurables.append(self.prefilter_manager)
2546 self.configurables.append(self.prefilter_manager)
2533 # Ultimately this will be refactored in the new interpreter code, but
2547 # Ultimately this will be refactored in the new interpreter code, but
2534 # for now, we should expose the main prefilter method (there's legacy
2548 # for now, we should expose the main prefilter method (there's legacy
2535 # code out there that may rely on this).
2549 # code out there that may rely on this).
2536 self.prefilter = self.prefilter_manager.prefilter_lines
2550 self.prefilter = self.prefilter_manager.prefilter_lines
2537
2551
2538 def auto_rewrite_input(self, cmd):
2552 def auto_rewrite_input(self, cmd):
2539 """Print to the screen the rewritten form of the user's command.
2553 """Print to the screen the rewritten form of the user's command.
2540
2554
2541 This shows visual feedback by rewriting input lines that cause
2555 This shows visual feedback by rewriting input lines that cause
2542 automatic calling to kick in, like::
2556 automatic calling to kick in, like::
2543
2557
2544 /f x
2558 /f x
2545
2559
2546 into::
2560 into::
2547
2561
2548 ------> f(x)
2562 ------> f(x)
2549
2563
2550 after the user's input prompt. This helps the user understand that the
2564 after the user's input prompt. This helps the user understand that the
2551 input line was transformed automatically by IPython.
2565 input line was transformed automatically by IPython.
2552 """
2566 """
2553 if not self.show_rewritten_input:
2567 if not self.show_rewritten_input:
2554 return
2568 return
2555
2569
2556 # This is overridden in TerminalInteractiveShell to use fancy prompts
2570 # This is overridden in TerminalInteractiveShell to use fancy prompts
2557 print("------> " + cmd)
2571 print("------> " + cmd)
2558
2572
2559 #-------------------------------------------------------------------------
2573 #-------------------------------------------------------------------------
2560 # Things related to extracting values/expressions from kernel and user_ns
2574 # Things related to extracting values/expressions from kernel and user_ns
2561 #-------------------------------------------------------------------------
2575 #-------------------------------------------------------------------------
2562
2576
2563 def _user_obj_error(self):
2577 def _user_obj_error(self):
2564 """return simple exception dict
2578 """return simple exception dict
2565
2579
2566 for use in user_expressions
2580 for use in user_expressions
2567 """
2581 """
2568
2582
2569 etype, evalue, tb = self._get_exc_info()
2583 etype, evalue, tb = self._get_exc_info()
2570 stb = self.InteractiveTB.get_exception_only(etype, evalue)
2584 stb = self.InteractiveTB.get_exception_only(etype, evalue)
2571
2585
2572 exc_info = {
2586 exc_info = {
2573 "status": "error",
2587 "status": "error",
2574 "traceback": stb,
2588 "traceback": stb,
2575 "ename": etype.__name__,
2589 "ename": etype.__name__,
2576 "evalue": py3compat.safe_unicode(evalue),
2590 "evalue": py3compat.safe_unicode(evalue),
2577 }
2591 }
2578
2592
2579 return exc_info
2593 return exc_info
2580
2594
2581 def _format_user_obj(self, obj):
2595 def _format_user_obj(self, obj):
2582 """format a user object to display dict
2596 """format a user object to display dict
2583
2597
2584 for use in user_expressions
2598 for use in user_expressions
2585 """
2599 """
2586
2600
2587 data, md = self.display_formatter.format(obj)
2601 data, md = self.display_formatter.format(obj)
2588 value = {
2602 value = {
2589 'status' : 'ok',
2603 'status' : 'ok',
2590 'data' : data,
2604 'data' : data,
2591 'metadata' : md,
2605 'metadata' : md,
2592 }
2606 }
2593 return value
2607 return value
2594
2608
2595 def user_expressions(self, expressions):
2609 def user_expressions(self, expressions):
2596 """Evaluate a dict of expressions in the user's namespace.
2610 """Evaluate a dict of expressions in the user's namespace.
2597
2611
2598 Parameters
2612 Parameters
2599 ----------
2613 ----------
2600 expressions : dict
2614 expressions : dict
2601 A dict with string keys and string values. The expression values
2615 A dict with string keys and string values. The expression values
2602 should be valid Python expressions, each of which will be evaluated
2616 should be valid Python expressions, each of which will be evaluated
2603 in the user namespace.
2617 in the user namespace.
2604
2618
2605 Returns
2619 Returns
2606 -------
2620 -------
2607 A dict, keyed like the input expressions dict, with the rich mime-typed
2621 A dict, keyed like the input expressions dict, with the rich mime-typed
2608 display_data of each value.
2622 display_data of each value.
2609 """
2623 """
2610 out = {}
2624 out = {}
2611 user_ns = self.user_ns
2625 user_ns = self.user_ns
2612 global_ns = self.user_global_ns
2626 global_ns = self.user_global_ns
2613
2627
2614 for key, expr in expressions.items():
2628 for key, expr in expressions.items():
2615 try:
2629 try:
2616 value = self._format_user_obj(eval(expr, global_ns, user_ns))
2630 value = self._format_user_obj(eval(expr, global_ns, user_ns))
2617 except:
2631 except:
2618 value = self._user_obj_error()
2632 value = self._user_obj_error()
2619 out[key] = value
2633 out[key] = value
2620 return out
2634 return out
2621
2635
2622 #-------------------------------------------------------------------------
2636 #-------------------------------------------------------------------------
2623 # Things related to the running of code
2637 # Things related to the running of code
2624 #-------------------------------------------------------------------------
2638 #-------------------------------------------------------------------------
2625
2639
2626 def ex(self, cmd):
2640 def ex(self, cmd):
2627 """Execute a normal python statement in user namespace."""
2641 """Execute a normal python statement in user namespace."""
2628 with self.builtin_trap:
2642 with self.builtin_trap:
2629 exec(cmd, self.user_global_ns, self.user_ns)
2643 exec(cmd, self.user_global_ns, self.user_ns)
2630
2644
2631 def ev(self, expr):
2645 def ev(self, expr):
2632 """Evaluate python expression expr in user namespace.
2646 """Evaluate python expression expr in user namespace.
2633
2647
2634 Returns the result of evaluation
2648 Returns the result of evaluation
2635 """
2649 """
2636 with self.builtin_trap:
2650 with self.builtin_trap:
2637 return eval(expr, self.user_global_ns, self.user_ns)
2651 return eval(expr, self.user_global_ns, self.user_ns)
2638
2652
2639 def safe_execfile(self, fname, *where, exit_ignore=False, raise_exceptions=False, shell_futures=False):
2653 def safe_execfile(self, fname, *where, exit_ignore=False, raise_exceptions=False, shell_futures=False):
2640 """A safe version of the builtin execfile().
2654 """A safe version of the builtin execfile().
2641
2655
2642 This version will never throw an exception, but instead print
2656 This version will never throw an exception, but instead print
2643 helpful error messages to the screen. This only works on pure
2657 helpful error messages to the screen. This only works on pure
2644 Python files with the .py extension.
2658 Python files with the .py extension.
2645
2659
2646 Parameters
2660 Parameters
2647 ----------
2661 ----------
2648 fname : string
2662 fname : string
2649 The name of the file to be executed.
2663 The name of the file to be executed.
2650 *where : tuple
2664 *where : tuple
2651 One or two namespaces, passed to execfile() as (globals,locals).
2665 One or two namespaces, passed to execfile() as (globals,locals).
2652 If only one is given, it is passed as both.
2666 If only one is given, it is passed as both.
2653 exit_ignore : bool (False)
2667 exit_ignore : bool (False)
2654 If True, then silence SystemExit for non-zero status (it is always
2668 If True, then silence SystemExit for non-zero status (it is always
2655 silenced for zero status, as it is so common).
2669 silenced for zero status, as it is so common).
2656 raise_exceptions : bool (False)
2670 raise_exceptions : bool (False)
2657 If True raise exceptions everywhere. Meant for testing.
2671 If True raise exceptions everywhere. Meant for testing.
2658 shell_futures : bool (False)
2672 shell_futures : bool (False)
2659 If True, the code will share future statements with the interactive
2673 If True, the code will share future statements with the interactive
2660 shell. It will both be affected by previous __future__ imports, and
2674 shell. It will both be affected by previous __future__ imports, and
2661 any __future__ imports in the code will affect the shell. If False,
2675 any __future__ imports in the code will affect the shell. If False,
2662 __future__ imports are not shared in either direction.
2676 __future__ imports are not shared in either direction.
2663
2677
2664 """
2678 """
2665 fname = Path(fname).expanduser().resolve()
2679 fname = Path(fname).expanduser().resolve()
2666
2680
2667 # Make sure we can open the file
2681 # Make sure we can open the file
2668 try:
2682 try:
2669 with fname.open("rb"):
2683 with fname.open("rb"):
2670 pass
2684 pass
2671 except:
2685 except:
2672 warn('Could not open file <%s> for safe execution.' % fname)
2686 warn('Could not open file <%s> for safe execution.' % fname)
2673 return
2687 return
2674
2688
2675 # Find things also in current directory. This is needed to mimic the
2689 # Find things also in current directory. This is needed to mimic the
2676 # behavior of running a script from the system command line, where
2690 # behavior of running a script from the system command line, where
2677 # Python inserts the script's directory into sys.path
2691 # Python inserts the script's directory into sys.path
2678 dname = str(fname.parent)
2692 dname = str(fname.parent)
2679
2693
2680 with prepended_to_syspath(dname), self.builtin_trap:
2694 with prepended_to_syspath(dname), self.builtin_trap:
2681 try:
2695 try:
2682 glob, loc = (where + (None, ))[:2]
2696 glob, loc = (where + (None, ))[:2]
2683 py3compat.execfile(
2697 py3compat.execfile(
2684 fname, glob, loc,
2698 fname, glob, loc,
2685 self.compile if shell_futures else None)
2699 self.compile if shell_futures else None)
2686 except SystemExit as status:
2700 except SystemExit as status:
2687 # If the call was made with 0 or None exit status (sys.exit(0)
2701 # If the call was made with 0 or None exit status (sys.exit(0)
2688 # or sys.exit() ), don't bother showing a traceback, as both of
2702 # or sys.exit() ), don't bother showing a traceback, as both of
2689 # these are considered normal by the OS:
2703 # these are considered normal by the OS:
2690 # > python -c'import sys;sys.exit(0)'; echo $?
2704 # > python -c'import sys;sys.exit(0)'; echo $?
2691 # 0
2705 # 0
2692 # > python -c'import sys;sys.exit()'; echo $?
2706 # > python -c'import sys;sys.exit()'; echo $?
2693 # 0
2707 # 0
2694 # For other exit status, we show the exception unless
2708 # For other exit status, we show the exception unless
2695 # explicitly silenced, but only in short form.
2709 # explicitly silenced, but only in short form.
2696 if status.code:
2710 if status.code:
2697 if raise_exceptions:
2711 if raise_exceptions:
2698 raise
2712 raise
2699 if not exit_ignore:
2713 if not exit_ignore:
2700 self.showtraceback(exception_only=True)
2714 self.showtraceback(exception_only=True)
2701 except:
2715 except:
2702 if raise_exceptions:
2716 if raise_exceptions:
2703 raise
2717 raise
2704 # tb offset is 2 because we wrap execfile
2718 # tb offset is 2 because we wrap execfile
2705 self.showtraceback(tb_offset=2)
2719 self.showtraceback(tb_offset=2)
2706
2720
2707 def safe_execfile_ipy(self, fname, shell_futures=False, raise_exceptions=False):
2721 def safe_execfile_ipy(self, fname, shell_futures=False, raise_exceptions=False):
2708 """Like safe_execfile, but for .ipy or .ipynb files with IPython syntax.
2722 """Like safe_execfile, but for .ipy or .ipynb files with IPython syntax.
2709
2723
2710 Parameters
2724 Parameters
2711 ----------
2725 ----------
2712 fname : str
2726 fname : str
2713 The name of the file to execute. The filename must have a
2727 The name of the file to execute. The filename must have a
2714 .ipy or .ipynb extension.
2728 .ipy or .ipynb extension.
2715 shell_futures : bool (False)
2729 shell_futures : bool (False)
2716 If True, the code will share future statements with the interactive
2730 If True, the code will share future statements with the interactive
2717 shell. It will both be affected by previous __future__ imports, and
2731 shell. It will both be affected by previous __future__ imports, and
2718 any __future__ imports in the code will affect the shell. If False,
2732 any __future__ imports in the code will affect the shell. If False,
2719 __future__ imports are not shared in either direction.
2733 __future__ imports are not shared in either direction.
2720 raise_exceptions : bool (False)
2734 raise_exceptions : bool (False)
2721 If True raise exceptions everywhere. Meant for testing.
2735 If True raise exceptions everywhere. Meant for testing.
2722 """
2736 """
2723 fname = Path(fname).expanduser().resolve()
2737 fname = Path(fname).expanduser().resolve()
2724
2738
2725 # Make sure we can open the file
2739 # Make sure we can open the file
2726 try:
2740 try:
2727 with fname.open("rb"):
2741 with fname.open("rb"):
2728 pass
2742 pass
2729 except:
2743 except:
2730 warn('Could not open file <%s> for safe execution.' % fname)
2744 warn('Could not open file <%s> for safe execution.' % fname)
2731 return
2745 return
2732
2746
2733 # Find things also in current directory. This is needed to mimic the
2747 # Find things also in current directory. This is needed to mimic the
2734 # behavior of running a script from the system command line, where
2748 # behavior of running a script from the system command line, where
2735 # Python inserts the script's directory into sys.path
2749 # Python inserts the script's directory into sys.path
2736 dname = str(fname.parent)
2750 dname = str(fname.parent)
2737
2751
2738 def get_cells():
2752 def get_cells():
2739 """generator for sequence of code blocks to run"""
2753 """generator for sequence of code blocks to run"""
2740 if fname.suffix == ".ipynb":
2754 if fname.suffix == ".ipynb":
2741 from nbformat import read
2755 from nbformat import read
2742 nb = read(fname, as_version=4)
2756 nb = read(fname, as_version=4)
2743 if not nb.cells:
2757 if not nb.cells:
2744 return
2758 return
2745 for cell in nb.cells:
2759 for cell in nb.cells:
2746 if cell.cell_type == 'code':
2760 if cell.cell_type == 'code':
2747 yield cell.source
2761 yield cell.source
2748 else:
2762 else:
2749 yield fname.read_text(encoding="utf-8")
2763 yield fname.read_text(encoding="utf-8")
2750
2764
2751 with prepended_to_syspath(dname):
2765 with prepended_to_syspath(dname):
2752 try:
2766 try:
2753 for cell in get_cells():
2767 for cell in get_cells():
2754 result = self.run_cell(cell, silent=True, shell_futures=shell_futures)
2768 result = self.run_cell(cell, silent=True, shell_futures=shell_futures)
2755 if raise_exceptions:
2769 if raise_exceptions:
2756 result.raise_error()
2770 result.raise_error()
2757 elif not result.success:
2771 elif not result.success:
2758 break
2772 break
2759 except:
2773 except:
2760 if raise_exceptions:
2774 if raise_exceptions:
2761 raise
2775 raise
2762 self.showtraceback()
2776 self.showtraceback()
2763 warn('Unknown failure executing file: <%s>' % fname)
2777 warn('Unknown failure executing file: <%s>' % fname)
2764
2778
2765 def safe_run_module(self, mod_name, where):
2779 def safe_run_module(self, mod_name, where):
2766 """A safe version of runpy.run_module().
2780 """A safe version of runpy.run_module().
2767
2781
2768 This version will never throw an exception, but instead print
2782 This version will never throw an exception, but instead print
2769 helpful error messages to the screen.
2783 helpful error messages to the screen.
2770
2784
2771 `SystemExit` exceptions with status code 0 or None are ignored.
2785 `SystemExit` exceptions with status code 0 or None are ignored.
2772
2786
2773 Parameters
2787 Parameters
2774 ----------
2788 ----------
2775 mod_name : string
2789 mod_name : string
2776 The name of the module to be executed.
2790 The name of the module to be executed.
2777 where : dict
2791 where : dict
2778 The globals namespace.
2792 The globals namespace.
2779 """
2793 """
2780 try:
2794 try:
2781 try:
2795 try:
2782 where.update(
2796 where.update(
2783 runpy.run_module(str(mod_name), run_name="__main__",
2797 runpy.run_module(str(mod_name), run_name="__main__",
2784 alter_sys=True)
2798 alter_sys=True)
2785 )
2799 )
2786 except SystemExit as status:
2800 except SystemExit as status:
2787 if status.code:
2801 if status.code:
2788 raise
2802 raise
2789 except:
2803 except:
2790 self.showtraceback()
2804 self.showtraceback()
2791 warn('Unknown failure executing module: <%s>' % mod_name)
2805 warn('Unknown failure executing module: <%s>' % mod_name)
2792
2806
2793 def run_cell(self, raw_cell, store_history=False, silent=False, shell_futures=True):
2807 def run_cell(self, raw_cell, store_history=False, silent=False, shell_futures=True):
2794 """Run a complete IPython cell.
2808 """Run a complete IPython cell.
2795
2809
2796 Parameters
2810 Parameters
2797 ----------
2811 ----------
2798 raw_cell : str
2812 raw_cell : str
2799 The code (including IPython code such as %magic functions) to run.
2813 The code (including IPython code such as %magic functions) to run.
2800 store_history : bool
2814 store_history : bool
2801 If True, the raw and translated cell will be stored in IPython's
2815 If True, the raw and translated cell will be stored in IPython's
2802 history. For user code calling back into IPython's machinery, this
2816 history. For user code calling back into IPython's machinery, this
2803 should be set to False.
2817 should be set to False.
2804 silent : bool
2818 silent : bool
2805 If True, avoid side-effects, such as implicit displayhooks and
2819 If True, avoid side-effects, such as implicit displayhooks and
2806 and logging. silent=True forces store_history=False.
2820 and logging. silent=True forces store_history=False.
2807 shell_futures : bool
2821 shell_futures : bool
2808 If True, the code will share future statements with the interactive
2822 If True, the code will share future statements with the interactive
2809 shell. It will both be affected by previous __future__ imports, and
2823 shell. It will both be affected by previous __future__ imports, and
2810 any __future__ imports in the code will affect the shell. If False,
2824 any __future__ imports in the code will affect the shell. If False,
2811 __future__ imports are not shared in either direction.
2825 __future__ imports are not shared in either direction.
2812
2826
2813 Returns
2827 Returns
2814 -------
2828 -------
2815 result : :class:`ExecutionResult`
2829 result : :class:`ExecutionResult`
2816 """
2830 """
2817 result = None
2831 result = None
2818 try:
2832 try:
2819 result = self._run_cell(
2833 result = self._run_cell(
2820 raw_cell, store_history, silent, shell_futures)
2834 raw_cell, store_history, silent, shell_futures)
2821 finally:
2835 finally:
2822 self.events.trigger('post_execute')
2836 self.events.trigger('post_execute')
2823 if not silent:
2837 if not silent:
2824 self.events.trigger('post_run_cell', result)
2838 self.events.trigger('post_run_cell', result)
2825 return result
2839 return result
2826
2840
2827 def _run_cell(self, raw_cell:str, store_history:bool, silent:bool, shell_futures:bool) -> ExecutionResult:
2841 def _run_cell(self, raw_cell:str, store_history:bool, silent:bool, shell_futures:bool) -> ExecutionResult:
2828 """Internal method to run a complete IPython cell."""
2842 """Internal method to run a complete IPython cell."""
2829
2843
2830 # we need to avoid calling self.transform_cell multiple time on the same thing
2844 # we need to avoid calling self.transform_cell multiple time on the same thing
2831 # so we need to store some results:
2845 # so we need to store some results:
2832 preprocessing_exc_tuple = None
2846 preprocessing_exc_tuple = None
2833 try:
2847 try:
2834 transformed_cell = self.transform_cell(raw_cell)
2848 transformed_cell = self.transform_cell(raw_cell)
2835 except Exception:
2849 except Exception:
2836 transformed_cell = raw_cell
2850 transformed_cell = raw_cell
2837 preprocessing_exc_tuple = sys.exc_info()
2851 preprocessing_exc_tuple = sys.exc_info()
2838
2852
2839 assert transformed_cell is not None
2853 assert transformed_cell is not None
2840 coro = self.run_cell_async(
2854 coro = self.run_cell_async(
2841 raw_cell,
2855 raw_cell,
2842 store_history=store_history,
2856 store_history=store_history,
2843 silent=silent,
2857 silent=silent,
2844 shell_futures=shell_futures,
2858 shell_futures=shell_futures,
2845 transformed_cell=transformed_cell,
2859 transformed_cell=transformed_cell,
2846 preprocessing_exc_tuple=preprocessing_exc_tuple,
2860 preprocessing_exc_tuple=preprocessing_exc_tuple,
2847 )
2861 )
2848
2862
2849 # run_cell_async is async, but may not actually need an eventloop.
2863 # run_cell_async is async, but may not actually need an eventloop.
2850 # when this is the case, we want to run it using the pseudo_sync_runner
2864 # when this is the case, we want to run it using the pseudo_sync_runner
2851 # so that code can invoke eventloops (for example via the %run , and
2865 # so that code can invoke eventloops (for example via the %run , and
2852 # `%paste` magic.
2866 # `%paste` magic.
2853 if self.trio_runner:
2867 if self.trio_runner:
2854 runner = self.trio_runner
2868 runner = self.trio_runner
2855 elif self.should_run_async(
2869 elif self.should_run_async(
2856 raw_cell,
2870 raw_cell,
2857 transformed_cell=transformed_cell,
2871 transformed_cell=transformed_cell,
2858 preprocessing_exc_tuple=preprocessing_exc_tuple,
2872 preprocessing_exc_tuple=preprocessing_exc_tuple,
2859 ):
2873 ):
2860 runner = self.loop_runner
2874 runner = self.loop_runner
2861 else:
2875 else:
2862 runner = _pseudo_sync_runner
2876 runner = _pseudo_sync_runner
2863
2877
2864 try:
2878 try:
2865 return runner(coro)
2879 return runner(coro)
2866 except BaseException as e:
2880 except BaseException as e:
2867 info = ExecutionInfo(raw_cell, store_history, silent, shell_futures)
2881 info = ExecutionInfo(raw_cell, store_history, silent, shell_futures)
2868 result = ExecutionResult(info)
2882 result = ExecutionResult(info)
2869 result.error_in_exec = e
2883 result.error_in_exec = e
2870 self.showtraceback(running_compiled_code=True)
2884 self.showtraceback(running_compiled_code=True)
2871 return result
2885 return result
2872
2886
2873 def should_run_async(
2887 def should_run_async(
2874 self, raw_cell: str, *, transformed_cell=None, preprocessing_exc_tuple=None
2888 self, raw_cell: str, *, transformed_cell=None, preprocessing_exc_tuple=None
2875 ) -> bool:
2889 ) -> bool:
2876 """Return whether a cell should be run asynchronously via a coroutine runner
2890 """Return whether a cell should be run asynchronously via a coroutine runner
2877
2891
2878 Parameters
2892 Parameters
2879 ----------
2893 ----------
2880 raw_cell : str
2894 raw_cell : str
2881 The code to be executed
2895 The code to be executed
2882
2896
2883 Returns
2897 Returns
2884 -------
2898 -------
2885 result: bool
2899 result: bool
2886 Whether the code needs to be run with a coroutine runner or not
2900 Whether the code needs to be run with a coroutine runner or not
2887 .. versionadded:: 7.0
2901 .. versionadded:: 7.0
2888 """
2902 """
2889 if not self.autoawait:
2903 if not self.autoawait:
2890 return False
2904 return False
2891 if preprocessing_exc_tuple is not None:
2905 if preprocessing_exc_tuple is not None:
2892 return False
2906 return False
2893 assert preprocessing_exc_tuple is None
2907 assert preprocessing_exc_tuple is None
2894 if transformed_cell is None:
2908 if transformed_cell is None:
2895 warnings.warn(
2909 warnings.warn(
2896 "`should_run_async` will not call `transform_cell`"
2910 "`should_run_async` will not call `transform_cell`"
2897 " automatically in the future. Please pass the result to"
2911 " automatically in the future. Please pass the result to"
2898 " `transformed_cell` argument and any exception that happen"
2912 " `transformed_cell` argument and any exception that happen"
2899 " during the"
2913 " during the"
2900 "transform in `preprocessing_exc_tuple` in"
2914 "transform in `preprocessing_exc_tuple` in"
2901 " IPython 7.17 and above.",
2915 " IPython 7.17 and above.",
2902 DeprecationWarning,
2916 DeprecationWarning,
2903 stacklevel=2,
2917 stacklevel=2,
2904 )
2918 )
2905 try:
2919 try:
2906 cell = self.transform_cell(raw_cell)
2920 cell = self.transform_cell(raw_cell)
2907 except Exception:
2921 except Exception:
2908 # any exception during transform will be raised
2922 # any exception during transform will be raised
2909 # prior to execution
2923 # prior to execution
2910 return False
2924 return False
2911 else:
2925 else:
2912 cell = transformed_cell
2926 cell = transformed_cell
2913 return _should_be_async(cell)
2927 return _should_be_async(cell)
2914
2928
2915 async def run_cell_async(
2929 async def run_cell_async(
2916 self,
2930 self,
2917 raw_cell: str,
2931 raw_cell: str,
2918 store_history=False,
2932 store_history=False,
2919 silent=False,
2933 silent=False,
2920 shell_futures=True,
2934 shell_futures=True,
2921 *,
2935 *,
2922 transformed_cell: Optional[str] = None,
2936 transformed_cell: Optional[str] = None,
2923 preprocessing_exc_tuple: Optional[Any] = None
2937 preprocessing_exc_tuple: Optional[Any] = None
2924 ) -> ExecutionResult:
2938 ) -> ExecutionResult:
2925 """Run a complete IPython cell asynchronously.
2939 """Run a complete IPython cell asynchronously.
2926
2940
2927 Parameters
2941 Parameters
2928 ----------
2942 ----------
2929 raw_cell : str
2943 raw_cell : str
2930 The code (including IPython code such as %magic functions) to run.
2944 The code (including IPython code such as %magic functions) to run.
2931 store_history : bool
2945 store_history : bool
2932 If True, the raw and translated cell will be stored in IPython's
2946 If True, the raw and translated cell will be stored in IPython's
2933 history. For user code calling back into IPython's machinery, this
2947 history. For user code calling back into IPython's machinery, this
2934 should be set to False.
2948 should be set to False.
2935 silent : bool
2949 silent : bool
2936 If True, avoid side-effects, such as implicit displayhooks and
2950 If True, avoid side-effects, such as implicit displayhooks and
2937 and logging. silent=True forces store_history=False.
2951 and logging. silent=True forces store_history=False.
2938 shell_futures : bool
2952 shell_futures : bool
2939 If True, the code will share future statements with the interactive
2953 If True, the code will share future statements with the interactive
2940 shell. It will both be affected by previous __future__ imports, and
2954 shell. It will both be affected by previous __future__ imports, and
2941 any __future__ imports in the code will affect the shell. If False,
2955 any __future__ imports in the code will affect the shell. If False,
2942 __future__ imports are not shared in either direction.
2956 __future__ imports are not shared in either direction.
2943 transformed_cell: str
2957 transformed_cell: str
2944 cell that was passed through transformers
2958 cell that was passed through transformers
2945 preprocessing_exc_tuple:
2959 preprocessing_exc_tuple:
2946 trace if the transformation failed.
2960 trace if the transformation failed.
2947
2961
2948 Returns
2962 Returns
2949 -------
2963 -------
2950 result : :class:`ExecutionResult`
2964 result : :class:`ExecutionResult`
2951
2965
2952 .. versionadded:: 7.0
2966 .. versionadded:: 7.0
2953 """
2967 """
2954 info = ExecutionInfo(
2968 info = ExecutionInfo(
2955 raw_cell, store_history, silent, shell_futures)
2969 raw_cell, store_history, silent, shell_futures)
2956 result = ExecutionResult(info)
2970 result = ExecutionResult(info)
2957
2971
2958 if (not raw_cell) or raw_cell.isspace():
2972 if (not raw_cell) or raw_cell.isspace():
2959 self.last_execution_succeeded = True
2973 self.last_execution_succeeded = True
2960 self.last_execution_result = result
2974 self.last_execution_result = result
2961 return result
2975 return result
2962
2976
2963 if silent:
2977 if silent:
2964 store_history = False
2978 store_history = False
2965
2979
2966 if store_history:
2980 if store_history:
2967 result.execution_count = self.execution_count
2981 result.execution_count = self.execution_count
2968
2982
2969 def error_before_exec(value):
2983 def error_before_exec(value):
2970 if store_history:
2984 if store_history:
2971 self.execution_count += 1
2985 self.execution_count += 1
2972 result.error_before_exec = value
2986 result.error_before_exec = value
2973 self.last_execution_succeeded = False
2987 self.last_execution_succeeded = False
2974 self.last_execution_result = result
2988 self.last_execution_result = result
2975 return result
2989 return result
2976
2990
2977 self.events.trigger('pre_execute')
2991 self.events.trigger('pre_execute')
2978 if not silent:
2992 if not silent:
2979 self.events.trigger('pre_run_cell', info)
2993 self.events.trigger('pre_run_cell', info)
2980
2994
2981 if transformed_cell is None:
2995 if transformed_cell is None:
2982 warnings.warn(
2996 warnings.warn(
2983 "`run_cell_async` will not call `transform_cell`"
2997 "`run_cell_async` will not call `transform_cell`"
2984 " automatically in the future. Please pass the result to"
2998 " automatically in the future. Please pass the result to"
2985 " `transformed_cell` argument and any exception that happen"
2999 " `transformed_cell` argument and any exception that happen"
2986 " during the"
3000 " during the"
2987 "transform in `preprocessing_exc_tuple` in"
3001 "transform in `preprocessing_exc_tuple` in"
2988 " IPython 7.17 and above.",
3002 " IPython 7.17 and above.",
2989 DeprecationWarning,
3003 DeprecationWarning,
2990 stacklevel=2,
3004 stacklevel=2,
2991 )
3005 )
2992 # If any of our input transformation (input_transformer_manager or
3006 # If any of our input transformation (input_transformer_manager or
2993 # prefilter_manager) raises an exception, we store it in this variable
3007 # prefilter_manager) raises an exception, we store it in this variable
2994 # so that we can display the error after logging the input and storing
3008 # so that we can display the error after logging the input and storing
2995 # it in the history.
3009 # it in the history.
2996 try:
3010 try:
2997 cell = self.transform_cell(raw_cell)
3011 cell = self.transform_cell(raw_cell)
2998 except Exception:
3012 except Exception:
2999 preprocessing_exc_tuple = sys.exc_info()
3013 preprocessing_exc_tuple = sys.exc_info()
3000 cell = raw_cell # cell has to exist so it can be stored/logged
3014 cell = raw_cell # cell has to exist so it can be stored/logged
3001 else:
3015 else:
3002 preprocessing_exc_tuple = None
3016 preprocessing_exc_tuple = None
3003 else:
3017 else:
3004 if preprocessing_exc_tuple is None:
3018 if preprocessing_exc_tuple is None:
3005 cell = transformed_cell
3019 cell = transformed_cell
3006 else:
3020 else:
3007 cell = raw_cell
3021 cell = raw_cell
3008
3022
3009 # Store raw and processed history
3023 # Store raw and processed history
3010 if store_history:
3024 if store_history:
3011 self.history_manager.store_inputs(self.execution_count,
3025 self.history_manager.store_inputs(self.execution_count,
3012 cell, raw_cell)
3026 cell, raw_cell)
3013 if not silent:
3027 if not silent:
3014 self.logger.log(cell, raw_cell)
3028 self.logger.log(cell, raw_cell)
3015
3029
3016 # Display the exception if input processing failed.
3030 # Display the exception if input processing failed.
3017 if preprocessing_exc_tuple is not None:
3031 if preprocessing_exc_tuple is not None:
3018 self.showtraceback(preprocessing_exc_tuple)
3032 self.showtraceback(preprocessing_exc_tuple)
3019 if store_history:
3033 if store_history:
3020 self.execution_count += 1
3034 self.execution_count += 1
3021 return error_before_exec(preprocessing_exc_tuple[1])
3035 return error_before_exec(preprocessing_exc_tuple[1])
3022
3036
3023 # Our own compiler remembers the __future__ environment. If we want to
3037 # Our own compiler remembers the __future__ environment. If we want to
3024 # run code with a separate __future__ environment, use the default
3038 # run code with a separate __future__ environment, use the default
3025 # compiler
3039 # compiler
3026 compiler = self.compile if shell_futures else self.compiler_class()
3040 compiler = self.compile if shell_futures else self.compiler_class()
3027
3041
3028 _run_async = False
3042 _run_async = False
3029
3043
3030 with self.builtin_trap:
3044 with self.builtin_trap:
3031 cell_name = compiler.cache(cell, self.execution_count, raw_code=raw_cell)
3045 cell_name = compiler.cache(cell, self.execution_count, raw_code=raw_cell)
3032
3046
3033 with self.display_trap:
3047 with self.display_trap:
3034 # Compile to bytecode
3048 # Compile to bytecode
3035 try:
3049 try:
3036 code_ast = compiler.ast_parse(cell, filename=cell_name)
3050 code_ast = compiler.ast_parse(cell, filename=cell_name)
3037 except self.custom_exceptions as e:
3051 except self.custom_exceptions as e:
3038 etype, value, tb = sys.exc_info()
3052 etype, value, tb = sys.exc_info()
3039 self.CustomTB(etype, value, tb)
3053 self.CustomTB(etype, value, tb)
3040 return error_before_exec(e)
3054 return error_before_exec(e)
3041 except IndentationError as e:
3055 except IndentationError as e:
3042 self.showindentationerror()
3056 self.showindentationerror()
3043 return error_before_exec(e)
3057 return error_before_exec(e)
3044 except (OverflowError, SyntaxError, ValueError, TypeError,
3058 except (OverflowError, SyntaxError, ValueError, TypeError,
3045 MemoryError) as e:
3059 MemoryError) as e:
3046 self.showsyntaxerror()
3060 self.showsyntaxerror()
3047 return error_before_exec(e)
3061 return error_before_exec(e)
3048
3062
3049 # Apply AST transformations
3063 # Apply AST transformations
3050 try:
3064 try:
3051 code_ast = self.transform_ast(code_ast)
3065 code_ast = self.transform_ast(code_ast)
3052 except InputRejected as e:
3066 except InputRejected as e:
3053 self.showtraceback()
3067 self.showtraceback()
3054 return error_before_exec(e)
3068 return error_before_exec(e)
3055
3069
3056 # Give the displayhook a reference to our ExecutionResult so it
3070 # Give the displayhook a reference to our ExecutionResult so it
3057 # can fill in the output value.
3071 # can fill in the output value.
3058 self.displayhook.exec_result = result
3072 self.displayhook.exec_result = result
3059
3073
3060 # Execute the user code
3074 # Execute the user code
3061 interactivity = "none" if silent else self.ast_node_interactivity
3075 interactivity = "none" if silent else self.ast_node_interactivity
3062
3076
3063 has_raised = await self.run_ast_nodes(code_ast.body, cell_name,
3077 has_raised = await self.run_ast_nodes(code_ast.body, cell_name,
3064 interactivity=interactivity, compiler=compiler, result=result)
3078 interactivity=interactivity, compiler=compiler, result=result)
3065
3079
3066 self.last_execution_succeeded = not has_raised
3080 self.last_execution_succeeded = not has_raised
3067 self.last_execution_result = result
3081 self.last_execution_result = result
3068
3082
3069 # Reset this so later displayed values do not modify the
3083 # Reset this so later displayed values do not modify the
3070 # ExecutionResult
3084 # ExecutionResult
3071 self.displayhook.exec_result = None
3085 self.displayhook.exec_result = None
3072
3086
3073 if store_history:
3087 if store_history:
3074 # Write output to the database. Does nothing unless
3088 # Write output to the database. Does nothing unless
3075 # history output logging is enabled.
3089 # history output logging is enabled.
3076 self.history_manager.store_output(self.execution_count)
3090 self.history_manager.store_output(self.execution_count)
3077 # Each cell is a *single* input, regardless of how many lines it has
3091 # Each cell is a *single* input, regardless of how many lines it has
3078 self.execution_count += 1
3092 self.execution_count += 1
3079
3093
3080 return result
3094 return result
3081
3095
3082 def transform_cell(self, raw_cell):
3096 def transform_cell(self, raw_cell):
3083 """Transform an input cell before parsing it.
3097 """Transform an input cell before parsing it.
3084
3098
3085 Static transformations, implemented in IPython.core.inputtransformer2,
3099 Static transformations, implemented in IPython.core.inputtransformer2,
3086 deal with things like ``%magic`` and ``!system`` commands.
3100 deal with things like ``%magic`` and ``!system`` commands.
3087 These run on all input.
3101 These run on all input.
3088 Dynamic transformations, for things like unescaped magics and the exit
3102 Dynamic transformations, for things like unescaped magics and the exit
3089 autocall, depend on the state of the interpreter.
3103 autocall, depend on the state of the interpreter.
3090 These only apply to single line inputs.
3104 These only apply to single line inputs.
3091
3105
3092 These string-based transformations are followed by AST transformations;
3106 These string-based transformations are followed by AST transformations;
3093 see :meth:`transform_ast`.
3107 see :meth:`transform_ast`.
3094 """
3108 """
3095 # Static input transformations
3109 # Static input transformations
3096 cell = self.input_transformer_manager.transform_cell(raw_cell)
3110 cell = self.input_transformer_manager.transform_cell(raw_cell)
3097
3111
3098 if len(cell.splitlines()) == 1:
3112 if len(cell.splitlines()) == 1:
3099 # Dynamic transformations - only applied for single line commands
3113 # Dynamic transformations - only applied for single line commands
3100 with self.builtin_trap:
3114 with self.builtin_trap:
3101 # use prefilter_lines to handle trailing newlines
3115 # use prefilter_lines to handle trailing newlines
3102 # restore trailing newline for ast.parse
3116 # restore trailing newline for ast.parse
3103 cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
3117 cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
3104
3118
3105 lines = cell.splitlines(keepends=True)
3119 lines = cell.splitlines(keepends=True)
3106 for transform in self.input_transformers_post:
3120 for transform in self.input_transformers_post:
3107 lines = transform(lines)
3121 lines = transform(lines)
3108 cell = ''.join(lines)
3122 cell = ''.join(lines)
3109
3123
3110 return cell
3124 return cell
3111
3125
3112 def transform_ast(self, node):
3126 def transform_ast(self, node):
3113 """Apply the AST transformations from self.ast_transformers
3127 """Apply the AST transformations from self.ast_transformers
3114
3128
3115 Parameters
3129 Parameters
3116 ----------
3130 ----------
3117 node : ast.Node
3131 node : ast.Node
3118 The root node to be transformed. Typically called with the ast.Module
3132 The root node to be transformed. Typically called with the ast.Module
3119 produced by parsing user input.
3133 produced by parsing user input.
3120
3134
3121 Returns
3135 Returns
3122 -------
3136 -------
3123 An ast.Node corresponding to the node it was called with. Note that it
3137 An ast.Node corresponding to the node it was called with. Note that it
3124 may also modify the passed object, so don't rely on references to the
3138 may also modify the passed object, so don't rely on references to the
3125 original AST.
3139 original AST.
3126 """
3140 """
3127 for transformer in self.ast_transformers:
3141 for transformer in self.ast_transformers:
3128 try:
3142 try:
3129 node = transformer.visit(node)
3143 node = transformer.visit(node)
3130 except InputRejected:
3144 except InputRejected:
3131 # User-supplied AST transformers can reject an input by raising
3145 # User-supplied AST transformers can reject an input by raising
3132 # an InputRejected. Short-circuit in this case so that we
3146 # an InputRejected. Short-circuit in this case so that we
3133 # don't unregister the transform.
3147 # don't unregister the transform.
3134 raise
3148 raise
3135 except Exception:
3149 except Exception:
3136 warn("AST transformer %r threw an error. It will be unregistered." % transformer)
3150 warn("AST transformer %r threw an error. It will be unregistered." % transformer)
3137 self.ast_transformers.remove(transformer)
3151 self.ast_transformers.remove(transformer)
3138
3152
3139 if self.ast_transformers:
3153 if self.ast_transformers:
3140 ast.fix_missing_locations(node)
3154 ast.fix_missing_locations(node)
3141 return node
3155 return node
3142
3156
3143 def _update_code_co_name(self, code):
3157 def _update_code_co_name(self, code):
3144 """Python 3.10 changed the behaviour so that whenever a code object
3158 """Python 3.10 changed the behaviour so that whenever a code object
3145 is assembled in the compile(ast) the co_firstlineno would be == 1.
3159 is assembled in the compile(ast) the co_firstlineno would be == 1.
3146
3160
3147 This makes pydevd/debugpy think that all cells invoked are the same
3161 This makes pydevd/debugpy think that all cells invoked are the same
3148 since it caches information based on (co_firstlineno, co_name, co_filename).
3162 since it caches information based on (co_firstlineno, co_name, co_filename).
3149
3163
3150 Given that, this function changes the code 'co_name' to be unique
3164 Given that, this function changes the code 'co_name' to be unique
3151 based on the first real lineno of the code (which also has a nice
3165 based on the first real lineno of the code (which also has a nice
3152 side effect of customizing the name so that it's not always <module>).
3166 side effect of customizing the name so that it's not always <module>).
3153
3167
3154 See: https://github.com/ipython/ipykernel/issues/841
3168 See: https://github.com/ipython/ipykernel/issues/841
3155 """
3169 """
3156 if not hasattr(code, "replace"):
3170 if not hasattr(code, "replace"):
3157 # It may not be available on older versions of Python (only
3171 # It may not be available on older versions of Python (only
3158 # available for 3.8 onwards).
3172 # available for 3.8 onwards).
3159 return code
3173 return code
3160 try:
3174 try:
3161 first_real_line = next(dis.findlinestarts(code))[1]
3175 first_real_line = next(dis.findlinestarts(code))[1]
3162 except StopIteration:
3176 except StopIteration:
3163 return code
3177 return code
3164 return code.replace(co_name="<cell line: %s>" % (first_real_line,))
3178 return code.replace(co_name="<cell line: %s>" % (first_real_line,))
3165
3179
3166 async def run_ast_nodes(
3180 async def run_ast_nodes(
3167 self,
3181 self,
3168 nodelist: ListType[stmt],
3182 nodelist: ListType[stmt],
3169 cell_name: str,
3183 cell_name: str,
3170 interactivity="last_expr",
3184 interactivity="last_expr",
3171 compiler=compile,
3185 compiler=compile,
3172 result=None,
3186 result=None,
3173 ):
3187 ):
3174 """Run a sequence of AST nodes. The execution mode depends on the
3188 """Run a sequence of AST nodes. The execution mode depends on the
3175 interactivity parameter.
3189 interactivity parameter.
3176
3190
3177 Parameters
3191 Parameters
3178 ----------
3192 ----------
3179 nodelist : list
3193 nodelist : list
3180 A sequence of AST nodes to run.
3194 A sequence of AST nodes to run.
3181 cell_name : str
3195 cell_name : str
3182 Will be passed to the compiler as the filename of the cell. Typically
3196 Will be passed to the compiler as the filename of the cell. Typically
3183 the value returned by ip.compile.cache(cell).
3197 the value returned by ip.compile.cache(cell).
3184 interactivity : str
3198 interactivity : str
3185 'all', 'last', 'last_expr' , 'last_expr_or_assign' or 'none',
3199 'all', 'last', 'last_expr' , 'last_expr_or_assign' or 'none',
3186 specifying which nodes should be run interactively (displaying output
3200 specifying which nodes should be run interactively (displaying output
3187 from expressions). 'last_expr' will run the last node interactively
3201 from expressions). 'last_expr' will run the last node interactively
3188 only if it is an expression (i.e. expressions in loops or other blocks
3202 only if it is an expression (i.e. expressions in loops or other blocks
3189 are not displayed) 'last_expr_or_assign' will run the last expression
3203 are not displayed) 'last_expr_or_assign' will run the last expression
3190 or the last assignment. Other values for this parameter will raise a
3204 or the last assignment. Other values for this parameter will raise a
3191 ValueError.
3205 ValueError.
3192
3206
3193 compiler : callable
3207 compiler : callable
3194 A function with the same interface as the built-in compile(), to turn
3208 A function with the same interface as the built-in compile(), to turn
3195 the AST nodes into code objects. Default is the built-in compile().
3209 the AST nodes into code objects. Default is the built-in compile().
3196 result : ExecutionResult, optional
3210 result : ExecutionResult, optional
3197 An object to store exceptions that occur during execution.
3211 An object to store exceptions that occur during execution.
3198
3212
3199 Returns
3213 Returns
3200 -------
3214 -------
3201 True if an exception occurred while running code, False if it finished
3215 True if an exception occurred while running code, False if it finished
3202 running.
3216 running.
3203 """
3217 """
3204 if not nodelist:
3218 if not nodelist:
3205 return
3219 return
3206
3220
3207
3221
3208 if interactivity == 'last_expr_or_assign':
3222 if interactivity == 'last_expr_or_assign':
3209 if isinstance(nodelist[-1], _assign_nodes):
3223 if isinstance(nodelist[-1], _assign_nodes):
3210 asg = nodelist[-1]
3224 asg = nodelist[-1]
3211 if isinstance(asg, ast.Assign) and len(asg.targets) == 1:
3225 if isinstance(asg, ast.Assign) and len(asg.targets) == 1:
3212 target = asg.targets[0]
3226 target = asg.targets[0]
3213 elif isinstance(asg, _single_targets_nodes):
3227 elif isinstance(asg, _single_targets_nodes):
3214 target = asg.target
3228 target = asg.target
3215 else:
3229 else:
3216 target = None
3230 target = None
3217 if isinstance(target, ast.Name):
3231 if isinstance(target, ast.Name):
3218 nnode = ast.Expr(ast.Name(target.id, ast.Load()))
3232 nnode = ast.Expr(ast.Name(target.id, ast.Load()))
3219 ast.fix_missing_locations(nnode)
3233 ast.fix_missing_locations(nnode)
3220 nodelist.append(nnode)
3234 nodelist.append(nnode)
3221 interactivity = 'last_expr'
3235 interactivity = 'last_expr'
3222
3236
3223 _async = False
3237 _async = False
3224 if interactivity == 'last_expr':
3238 if interactivity == 'last_expr':
3225 if isinstance(nodelist[-1], ast.Expr):
3239 if isinstance(nodelist[-1], ast.Expr):
3226 interactivity = "last"
3240 interactivity = "last"
3227 else:
3241 else:
3228 interactivity = "none"
3242 interactivity = "none"
3229
3243
3230 if interactivity == 'none':
3244 if interactivity == 'none':
3231 to_run_exec, to_run_interactive = nodelist, []
3245 to_run_exec, to_run_interactive = nodelist, []
3232 elif interactivity == 'last':
3246 elif interactivity == 'last':
3233 to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:]
3247 to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:]
3234 elif interactivity == 'all':
3248 elif interactivity == 'all':
3235 to_run_exec, to_run_interactive = [], nodelist
3249 to_run_exec, to_run_interactive = [], nodelist
3236 else:
3250 else:
3237 raise ValueError("Interactivity was %r" % interactivity)
3251 raise ValueError("Interactivity was %r" % interactivity)
3238
3252
3239 try:
3253 try:
3240
3254
3241 def compare(code):
3255 def compare(code):
3242 is_async = inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE
3256 is_async = inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE
3243 return is_async
3257 return is_async
3244
3258
3245 # refactor that to just change the mod constructor.
3259 # refactor that to just change the mod constructor.
3246 to_run = []
3260 to_run = []
3247 for node in to_run_exec:
3261 for node in to_run_exec:
3248 to_run.append((node, "exec"))
3262 to_run.append((node, "exec"))
3249
3263
3250 for node in to_run_interactive:
3264 for node in to_run_interactive:
3251 to_run.append((node, "single"))
3265 to_run.append((node, "single"))
3252
3266
3253 for node, mode in to_run:
3267 for node, mode in to_run:
3254 if mode == "exec":
3268 if mode == "exec":
3255 mod = Module([node], [])
3269 mod = Module([node], [])
3256 elif mode == "single":
3270 elif mode == "single":
3257 mod = ast.Interactive([node])
3271 mod = ast.Interactive([node])
3258 with compiler.extra_flags(
3272 with compiler.extra_flags(
3259 getattr(ast, "PyCF_ALLOW_TOP_LEVEL_AWAIT", 0x0)
3273 getattr(ast, "PyCF_ALLOW_TOP_LEVEL_AWAIT", 0x0)
3260 if self.autoawait
3274 if self.autoawait
3261 else 0x0
3275 else 0x0
3262 ):
3276 ):
3263 code = compiler(mod, cell_name, mode)
3277 code = compiler(mod, cell_name, mode)
3264 code = self._update_code_co_name(code)
3278 code = self._update_code_co_name(code)
3265 asy = compare(code)
3279 asy = compare(code)
3266 if await self.run_code(code, result, async_=asy):
3280 if await self.run_code(code, result, async_=asy):
3267 return True
3281 return True
3268
3282
3269 # Flush softspace
3283 # Flush softspace
3270 if softspace(sys.stdout, 0):
3284 if softspace(sys.stdout, 0):
3271 print()
3285 print()
3272
3286
3273 except:
3287 except:
3274 # It's possible to have exceptions raised here, typically by
3288 # It's possible to have exceptions raised here, typically by
3275 # compilation of odd code (such as a naked 'return' outside a
3289 # compilation of odd code (such as a naked 'return' outside a
3276 # function) that did parse but isn't valid. Typically the exception
3290 # function) that did parse but isn't valid. Typically the exception
3277 # is a SyntaxError, but it's safest just to catch anything and show
3291 # is a SyntaxError, but it's safest just to catch anything and show
3278 # the user a traceback.
3292 # the user a traceback.
3279
3293
3280 # We do only one try/except outside the loop to minimize the impact
3294 # We do only one try/except outside the loop to minimize the impact
3281 # on runtime, and also because if any node in the node list is
3295 # on runtime, and also because if any node in the node list is
3282 # broken, we should stop execution completely.
3296 # broken, we should stop execution completely.
3283 if result:
3297 if result:
3284 result.error_before_exec = sys.exc_info()[1]
3298 result.error_before_exec = sys.exc_info()[1]
3285 self.showtraceback()
3299 self.showtraceback()
3286 return True
3300 return True
3287
3301
3288 return False
3302 return False
3289
3303
3290 async def run_code(self, code_obj, result=None, *, async_=False):
3304 async def run_code(self, code_obj, result=None, *, async_=False):
3291 """Execute a code object.
3305 """Execute a code object.
3292
3306
3293 When an exception occurs, self.showtraceback() is called to display a
3307 When an exception occurs, self.showtraceback() is called to display a
3294 traceback.
3308 traceback.
3295
3309
3296 Parameters
3310 Parameters
3297 ----------
3311 ----------
3298 code_obj : code object
3312 code_obj : code object
3299 A compiled code object, to be executed
3313 A compiled code object, to be executed
3300 result : ExecutionResult, optional
3314 result : ExecutionResult, optional
3301 An object to store exceptions that occur during execution.
3315 An object to store exceptions that occur during execution.
3302 async_ : Bool (Experimental)
3316 async_ : Bool (Experimental)
3303 Attempt to run top-level asynchronous code in a default loop.
3317 Attempt to run top-level asynchronous code in a default loop.
3304
3318
3305 Returns
3319 Returns
3306 -------
3320 -------
3307 False : successful execution.
3321 False : successful execution.
3308 True : an error occurred.
3322 True : an error occurred.
3309 """
3323 """
3310 # special value to say that anything above is IPython and should be
3324 # special value to say that anything above is IPython and should be
3311 # hidden.
3325 # hidden.
3312 __tracebackhide__ = "__ipython_bottom__"
3326 __tracebackhide__ = "__ipython_bottom__"
3313 # Set our own excepthook in case the user code tries to call it
3327 # Set our own excepthook in case the user code tries to call it
3314 # directly, so that the IPython crash handler doesn't get triggered
3328 # directly, so that the IPython crash handler doesn't get triggered
3315 old_excepthook, sys.excepthook = sys.excepthook, self.excepthook
3329 old_excepthook, sys.excepthook = sys.excepthook, self.excepthook
3316
3330
3317 # we save the original sys.excepthook in the instance, in case config
3331 # we save the original sys.excepthook in the instance, in case config
3318 # code (such as magics) needs access to it.
3332 # code (such as magics) needs access to it.
3319 self.sys_excepthook = old_excepthook
3333 self.sys_excepthook = old_excepthook
3320 outflag = True # happens in more places, so it's easier as default
3334 outflag = True # happens in more places, so it's easier as default
3321 try:
3335 try:
3322 try:
3336 try:
3323 if async_:
3337 if async_:
3324 await eval(code_obj, self.user_global_ns, self.user_ns)
3338 await eval(code_obj, self.user_global_ns, self.user_ns)
3325 else:
3339 else:
3326 exec(code_obj, self.user_global_ns, self.user_ns)
3340 exec(code_obj, self.user_global_ns, self.user_ns)
3327 finally:
3341 finally:
3328 # Reset our crash handler in place
3342 # Reset our crash handler in place
3329 sys.excepthook = old_excepthook
3343 sys.excepthook = old_excepthook
3330 except SystemExit as e:
3344 except SystemExit as e:
3331 if result is not None:
3345 if result is not None:
3332 result.error_in_exec = e
3346 result.error_in_exec = e
3333 self.showtraceback(exception_only=True)
3347 self.showtraceback(exception_only=True)
3334 warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
3348 warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
3335 except self.custom_exceptions:
3349 except self.custom_exceptions:
3336 etype, value, tb = sys.exc_info()
3350 etype, value, tb = sys.exc_info()
3337 if result is not None:
3351 if result is not None:
3338 result.error_in_exec = value
3352 result.error_in_exec = value
3339 self.CustomTB(etype, value, tb)
3353 self.CustomTB(etype, value, tb)
3340 except:
3354 except:
3341 if result is not None:
3355 if result is not None:
3342 result.error_in_exec = sys.exc_info()[1]
3356 result.error_in_exec = sys.exc_info()[1]
3343 self.showtraceback(running_compiled_code=True)
3357 self.showtraceback(running_compiled_code=True)
3344 else:
3358 else:
3345 outflag = False
3359 outflag = False
3346 return outflag
3360 return outflag
3347
3361
3348 # For backwards compatibility
3362 # For backwards compatibility
3349 runcode = run_code
3363 runcode = run_code
3350
3364
3351 def check_complete(self, code: str) -> Tuple[str, str]:
3365 def check_complete(self, code: str) -> Tuple[str, str]:
3352 """Return whether a block of code is ready to execute, or should be continued
3366 """Return whether a block of code is ready to execute, or should be continued
3353
3367
3354 Parameters
3368 Parameters
3355 ----------
3369 ----------
3356 code : string
3370 code : string
3357 Python input code, which can be multiline.
3371 Python input code, which can be multiline.
3358
3372
3359 Returns
3373 Returns
3360 -------
3374 -------
3361 status : str
3375 status : str
3362 One of 'complete', 'incomplete', or 'invalid' if source is not a
3376 One of 'complete', 'incomplete', or 'invalid' if source is not a
3363 prefix of valid code.
3377 prefix of valid code.
3364 indent : str
3378 indent : str
3365 When status is 'incomplete', this is some whitespace to insert on
3379 When status is 'incomplete', this is some whitespace to insert on
3366 the next line of the prompt.
3380 the next line of the prompt.
3367 """
3381 """
3368 status, nspaces = self.input_transformer_manager.check_complete(code)
3382 status, nspaces = self.input_transformer_manager.check_complete(code)
3369 return status, ' ' * (nspaces or 0)
3383 return status, ' ' * (nspaces or 0)
3370
3384
3371 #-------------------------------------------------------------------------
3385 #-------------------------------------------------------------------------
3372 # Things related to GUI support and pylab
3386 # Things related to GUI support and pylab
3373 #-------------------------------------------------------------------------
3387 #-------------------------------------------------------------------------
3374
3388
3375 active_eventloop = None
3389 active_eventloop = None
3376
3390
3377 def enable_gui(self, gui=None):
3391 def enable_gui(self, gui=None):
3378 raise NotImplementedError('Implement enable_gui in a subclass')
3392 raise NotImplementedError('Implement enable_gui in a subclass')
3379
3393
3380 def enable_matplotlib(self, gui=None):
3394 def enable_matplotlib(self, gui=None):
3381 """Enable interactive matplotlib and inline figure support.
3395 """Enable interactive matplotlib and inline figure support.
3382
3396
3383 This takes the following steps:
3397 This takes the following steps:
3384
3398
3385 1. select the appropriate eventloop and matplotlib backend
3399 1. select the appropriate eventloop and matplotlib backend
3386 2. set up matplotlib for interactive use with that backend
3400 2. set up matplotlib for interactive use with that backend
3387 3. configure formatters for inline figure display
3401 3. configure formatters for inline figure display
3388 4. enable the selected gui eventloop
3402 4. enable the selected gui eventloop
3389
3403
3390 Parameters
3404 Parameters
3391 ----------
3405 ----------
3392 gui : optional, string
3406 gui : optional, string
3393 If given, dictates the choice of matplotlib GUI backend to use
3407 If given, dictates the choice of matplotlib GUI backend to use
3394 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3408 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3395 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3409 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3396 matplotlib (as dictated by the matplotlib build-time options plus the
3410 matplotlib (as dictated by the matplotlib build-time options plus the
3397 user's matplotlibrc configuration file). Note that not all backends
3411 user's matplotlibrc configuration file). Note that not all backends
3398 make sense in all contexts, for example a terminal ipython can't
3412 make sense in all contexts, for example a terminal ipython can't
3399 display figures inline.
3413 display figures inline.
3400 """
3414 """
3401 from IPython.core import pylabtools as pt
3402 from matplotlib_inline.backend_inline import configure_inline_support
3415 from matplotlib_inline.backend_inline import configure_inline_support
3416
3417 from IPython.core import pylabtools as pt
3403 gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select)
3418 gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select)
3404
3419
3405 if gui != 'inline':
3420 if gui != 'inline':
3406 # If we have our first gui selection, store it
3421 # If we have our first gui selection, store it
3407 if self.pylab_gui_select is None:
3422 if self.pylab_gui_select is None:
3408 self.pylab_gui_select = gui
3423 self.pylab_gui_select = gui
3409 # Otherwise if they are different
3424 # Otherwise if they are different
3410 elif gui != self.pylab_gui_select:
3425 elif gui != self.pylab_gui_select:
3411 print('Warning: Cannot change to a different GUI toolkit: %s.'
3426 print('Warning: Cannot change to a different GUI toolkit: %s.'
3412 ' Using %s instead.' % (gui, self.pylab_gui_select))
3427 ' Using %s instead.' % (gui, self.pylab_gui_select))
3413 gui, backend = pt.find_gui_and_backend(self.pylab_gui_select)
3428 gui, backend = pt.find_gui_and_backend(self.pylab_gui_select)
3414
3429
3415 pt.activate_matplotlib(backend)
3430 pt.activate_matplotlib(backend)
3416 configure_inline_support(self, backend)
3431 configure_inline_support(self, backend)
3417
3432
3418 # Now we must activate the gui pylab wants to use, and fix %run to take
3433 # Now we must activate the gui pylab wants to use, and fix %run to take
3419 # plot updates into account
3434 # plot updates into account
3420 self.enable_gui(gui)
3435 self.enable_gui(gui)
3421 self.magics_manager.registry['ExecutionMagics'].default_runner = \
3436 self.magics_manager.registry['ExecutionMagics'].default_runner = \
3422 pt.mpl_runner(self.safe_execfile)
3437 pt.mpl_runner(self.safe_execfile)
3423
3438
3424 return gui, backend
3439 return gui, backend
3425
3440
3426 def enable_pylab(self, gui=None, import_all=True, welcome_message=False):
3441 def enable_pylab(self, gui=None, import_all=True, welcome_message=False):
3427 """Activate pylab support at runtime.
3442 """Activate pylab support at runtime.
3428
3443
3429 This turns on support for matplotlib, preloads into the interactive
3444 This turns on support for matplotlib, preloads into the interactive
3430 namespace all of numpy and pylab, and configures IPython to correctly
3445 namespace all of numpy and pylab, and configures IPython to correctly
3431 interact with the GUI event loop. The GUI backend to be used can be
3446 interact with the GUI event loop. The GUI backend to be used can be
3432 optionally selected with the optional ``gui`` argument.
3447 optionally selected with the optional ``gui`` argument.
3433
3448
3434 This method only adds preloading the namespace to InteractiveShell.enable_matplotlib.
3449 This method only adds preloading the namespace to InteractiveShell.enable_matplotlib.
3435
3450
3436 Parameters
3451 Parameters
3437 ----------
3452 ----------
3438 gui : optional, string
3453 gui : optional, string
3439 If given, dictates the choice of matplotlib GUI backend to use
3454 If given, dictates the choice of matplotlib GUI backend to use
3440 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3455 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3441 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3456 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3442 matplotlib (as dictated by the matplotlib build-time options plus the
3457 matplotlib (as dictated by the matplotlib build-time options plus the
3443 user's matplotlibrc configuration file). Note that not all backends
3458 user's matplotlibrc configuration file). Note that not all backends
3444 make sense in all contexts, for example a terminal ipython can't
3459 make sense in all contexts, for example a terminal ipython can't
3445 display figures inline.
3460 display figures inline.
3446 import_all : optional, bool, default: True
3461 import_all : optional, bool, default: True
3447 Whether to do `from numpy import *` and `from pylab import *`
3462 Whether to do `from numpy import *` and `from pylab import *`
3448 in addition to module imports.
3463 in addition to module imports.
3449 welcome_message : deprecated
3464 welcome_message : deprecated
3450 This argument is ignored, no welcome message will be displayed.
3465 This argument is ignored, no welcome message will be displayed.
3451 """
3466 """
3452 from IPython.core.pylabtools import import_pylab
3467 from IPython.core.pylabtools import import_pylab
3453
3468
3454 gui, backend = self.enable_matplotlib(gui)
3469 gui, backend = self.enable_matplotlib(gui)
3455
3470
3456 # We want to prevent the loading of pylab to pollute the user's
3471 # We want to prevent the loading of pylab to pollute the user's
3457 # namespace as shown by the %who* magics, so we execute the activation
3472 # namespace as shown by the %who* magics, so we execute the activation
3458 # code in an empty namespace, and we update *both* user_ns and
3473 # code in an empty namespace, and we update *both* user_ns and
3459 # user_ns_hidden with this information.
3474 # user_ns_hidden with this information.
3460 ns = {}
3475 ns = {}
3461 import_pylab(ns, import_all)
3476 import_pylab(ns, import_all)
3462 # warn about clobbered names
3477 # warn about clobbered names
3463 ignored = {"__builtins__"}
3478 ignored = {"__builtins__"}
3464 both = set(ns).intersection(self.user_ns).difference(ignored)
3479 both = set(ns).intersection(self.user_ns).difference(ignored)
3465 clobbered = [ name for name in both if self.user_ns[name] is not ns[name] ]
3480 clobbered = [ name for name in both if self.user_ns[name] is not ns[name] ]
3466 self.user_ns.update(ns)
3481 self.user_ns.update(ns)
3467 self.user_ns_hidden.update(ns)
3482 self.user_ns_hidden.update(ns)
3468 return gui, backend, clobbered
3483 return gui, backend, clobbered
3469
3484
3470 #-------------------------------------------------------------------------
3485 #-------------------------------------------------------------------------
3471 # Utilities
3486 # Utilities
3472 #-------------------------------------------------------------------------
3487 #-------------------------------------------------------------------------
3473
3488
3474 def var_expand(self, cmd, depth=0, formatter=DollarFormatter()):
3489 def var_expand(self, cmd, depth=0, formatter=DollarFormatter()):
3475 """Expand python variables in a string.
3490 """Expand python variables in a string.
3476
3491
3477 The depth argument indicates how many frames above the caller should
3492 The depth argument indicates how many frames above the caller should
3478 be walked to look for the local namespace where to expand variables.
3493 be walked to look for the local namespace where to expand variables.
3479
3494
3480 The global namespace for expansion is always the user's interactive
3495 The global namespace for expansion is always the user's interactive
3481 namespace.
3496 namespace.
3482 """
3497 """
3483 ns = self.user_ns.copy()
3498 ns = self.user_ns.copy()
3484 try:
3499 try:
3485 frame = sys._getframe(depth+1)
3500 frame = sys._getframe(depth+1)
3486 except ValueError:
3501 except ValueError:
3487 # This is thrown if there aren't that many frames on the stack,
3502 # This is thrown if there aren't that many frames on the stack,
3488 # e.g. if a script called run_line_magic() directly.
3503 # e.g. if a script called run_line_magic() directly.
3489 pass
3504 pass
3490 else:
3505 else:
3491 ns.update(frame.f_locals)
3506 ns.update(frame.f_locals)
3492
3507
3493 try:
3508 try:
3494 # We have to use .vformat() here, because 'self' is a valid and common
3509 # We have to use .vformat() here, because 'self' is a valid and common
3495 # name, and expanding **ns for .format() would make it collide with
3510 # name, and expanding **ns for .format() would make it collide with
3496 # the 'self' argument of the method.
3511 # the 'self' argument of the method.
3497 cmd = formatter.vformat(cmd, args=[], kwargs=ns)
3512 cmd = formatter.vformat(cmd, args=[], kwargs=ns)
3498 except Exception:
3513 except Exception:
3499 # if formatter couldn't format, just let it go untransformed
3514 # if formatter couldn't format, just let it go untransformed
3500 pass
3515 pass
3501 return cmd
3516 return cmd
3502
3517
3503 def mktempfile(self, data=None, prefix='ipython_edit_'):
3518 def mktempfile(self, data=None, prefix='ipython_edit_'):
3504 """Make a new tempfile and return its filename.
3519 """Make a new tempfile and return its filename.
3505
3520
3506 This makes a call to tempfile.mkstemp (created in a tempfile.mkdtemp),
3521 This makes a call to tempfile.mkstemp (created in a tempfile.mkdtemp),
3507 but it registers the created filename internally so ipython cleans it up
3522 but it registers the created filename internally so ipython cleans it up
3508 at exit time.
3523 at exit time.
3509
3524
3510 Optional inputs:
3525 Optional inputs:
3511
3526
3512 - data(None): if data is given, it gets written out to the temp file
3527 - data(None): if data is given, it gets written out to the temp file
3513 immediately, and the file is closed again."""
3528 immediately, and the file is closed again."""
3514
3529
3515 dir_path = Path(tempfile.mkdtemp(prefix=prefix))
3530 dir_path = Path(tempfile.mkdtemp(prefix=prefix))
3516 self.tempdirs.append(dir_path)
3531 self.tempdirs.append(dir_path)
3517
3532
3518 handle, filename = tempfile.mkstemp(".py", prefix, dir=str(dir_path))
3533 handle, filename = tempfile.mkstemp(".py", prefix, dir=str(dir_path))
3519 os.close(handle) # On Windows, there can only be one open handle on a file
3534 os.close(handle) # On Windows, there can only be one open handle on a file
3520
3535
3521 file_path = Path(filename)
3536 file_path = Path(filename)
3522 self.tempfiles.append(file_path)
3537 self.tempfiles.append(file_path)
3523
3538
3524 if data:
3539 if data:
3525 file_path.write_text(data, encoding="utf-8")
3540 file_path.write_text(data, encoding="utf-8")
3526 return filename
3541 return filename
3527
3542
3528 def ask_yes_no(self, prompt, default=None, interrupt=None):
3543 def ask_yes_no(self, prompt, default=None, interrupt=None):
3529 if self.quiet:
3544 if self.quiet:
3530 return True
3545 return True
3531 return ask_yes_no(prompt,default,interrupt)
3546 return ask_yes_no(prompt,default,interrupt)
3532
3547
3533 def show_usage(self):
3548 def show_usage(self):
3534 """Show a usage message"""
3549 """Show a usage message"""
3535 page.page(IPython.core.usage.interactive_usage)
3550 page.page(IPython.core.usage.interactive_usage)
3536
3551
3537 def extract_input_lines(self, range_str, raw=False):
3552 def extract_input_lines(self, range_str, raw=False):
3538 """Return as a string a set of input history slices.
3553 """Return as a string a set of input history slices.
3539
3554
3540 Parameters
3555 Parameters
3541 ----------
3556 ----------
3542 range_str : str
3557 range_str : str
3543 The set of slices is given as a string, like "~5/6-~4/2 4:8 9",
3558 The set of slices is given as a string, like "~5/6-~4/2 4:8 9",
3544 since this function is for use by magic functions which get their
3559 since this function is for use by magic functions which get their
3545 arguments as strings. The number before the / is the session
3560 arguments as strings. The number before the / is the session
3546 number: ~n goes n back from the current session.
3561 number: ~n goes n back from the current session.
3547
3562
3548 If empty string is given, returns history of current session
3563 If empty string is given, returns history of current session
3549 without the last input.
3564 without the last input.
3550
3565
3551 raw : bool, optional
3566 raw : bool, optional
3552 By default, the processed input is used. If this is true, the raw
3567 By default, the processed input is used. If this is true, the raw
3553 input history is used instead.
3568 input history is used instead.
3554
3569
3555 Notes
3570 Notes
3556 -----
3571 -----
3557 Slices can be described with two notations:
3572 Slices can be described with two notations:
3558
3573
3559 * ``N:M`` -> standard python form, means including items N...(M-1).
3574 * ``N:M`` -> standard python form, means including items N...(M-1).
3560 * ``N-M`` -> include items N..M (closed endpoint).
3575 * ``N-M`` -> include items N..M (closed endpoint).
3561 """
3576 """
3562 lines = self.history_manager.get_range_by_str(range_str, raw=raw)
3577 lines = self.history_manager.get_range_by_str(range_str, raw=raw)
3563 text = "\n".join(x for _, _, x in lines)
3578 text = "\n".join(x for _, _, x in lines)
3564
3579
3565 # Skip the last line, as it's probably the magic that called this
3580 # Skip the last line, as it's probably the magic that called this
3566 if not range_str:
3581 if not range_str:
3567 if "\n" not in text:
3582 if "\n" not in text:
3568 text = ""
3583 text = ""
3569 else:
3584 else:
3570 text = text[: text.rfind("\n")]
3585 text = text[: text.rfind("\n")]
3571
3586
3572 return text
3587 return text
3573
3588
3574 def find_user_code(self, target, raw=True, py_only=False, skip_encoding_cookie=True, search_ns=False):
3589 def find_user_code(self, target, raw=True, py_only=False, skip_encoding_cookie=True, search_ns=False):
3575 """Get a code string from history, file, url, or a string or macro.
3590 """Get a code string from history, file, url, or a string or macro.
3576
3591
3577 This is mainly used by magic functions.
3592 This is mainly used by magic functions.
3578
3593
3579 Parameters
3594 Parameters
3580 ----------
3595 ----------
3581 target : str
3596 target : str
3582 A string specifying code to retrieve. This will be tried respectively
3597 A string specifying code to retrieve. This will be tried respectively
3583 as: ranges of input history (see %history for syntax), url,
3598 as: ranges of input history (see %history for syntax), url,
3584 corresponding .py file, filename, or an expression evaluating to a
3599 corresponding .py file, filename, or an expression evaluating to a
3585 string or Macro in the user namespace.
3600 string or Macro in the user namespace.
3586
3601
3587 If empty string is given, returns complete history of current
3602 If empty string is given, returns complete history of current
3588 session, without the last line.
3603 session, without the last line.
3589
3604
3590 raw : bool
3605 raw : bool
3591 If true (default), retrieve raw history. Has no effect on the other
3606 If true (default), retrieve raw history. Has no effect on the other
3592 retrieval mechanisms.
3607 retrieval mechanisms.
3593
3608
3594 py_only : bool (default False)
3609 py_only : bool (default False)
3595 Only try to fetch python code, do not try alternative methods to decode file
3610 Only try to fetch python code, do not try alternative methods to decode file
3596 if unicode fails.
3611 if unicode fails.
3597
3612
3598 Returns
3613 Returns
3599 -------
3614 -------
3600 A string of code.
3615 A string of code.
3601 ValueError is raised if nothing is found, and TypeError if it evaluates
3616 ValueError is raised if nothing is found, and TypeError if it evaluates
3602 to an object of another type. In each case, .args[0] is a printable
3617 to an object of another type. In each case, .args[0] is a printable
3603 message.
3618 message.
3604 """
3619 """
3605 code = self.extract_input_lines(target, raw=raw) # Grab history
3620 code = self.extract_input_lines(target, raw=raw) # Grab history
3606 if code:
3621 if code:
3607 return code
3622 return code
3608 try:
3623 try:
3609 if target.startswith(('http://', 'https://')):
3624 if target.startswith(('http://', 'https://')):
3610 return openpy.read_py_url(target, skip_encoding_cookie=skip_encoding_cookie)
3625 return openpy.read_py_url(target, skip_encoding_cookie=skip_encoding_cookie)
3611 except UnicodeDecodeError as e:
3626 except UnicodeDecodeError as e:
3612 if not py_only :
3627 if not py_only :
3613 # Deferred import
3628 # Deferred import
3614 from urllib.request import urlopen
3629 from urllib.request import urlopen
3615 response = urlopen(target)
3630 response = urlopen(target)
3616 return response.read().decode('latin1')
3631 return response.read().decode('latin1')
3617 raise ValueError(("'%s' seem to be unreadable.") % target) from e
3632 raise ValueError(("'%s' seem to be unreadable.") % target) from e
3618
3633
3619 potential_target = [target]
3634 potential_target = [target]
3620 try :
3635 try :
3621 potential_target.insert(0,get_py_filename(target))
3636 potential_target.insert(0,get_py_filename(target))
3622 except IOError:
3637 except IOError:
3623 pass
3638 pass
3624
3639
3625 for tgt in potential_target :
3640 for tgt in potential_target :
3626 if os.path.isfile(tgt): # Read file
3641 if os.path.isfile(tgt): # Read file
3627 try :
3642 try :
3628 return openpy.read_py_file(tgt, skip_encoding_cookie=skip_encoding_cookie)
3643 return openpy.read_py_file(tgt, skip_encoding_cookie=skip_encoding_cookie)
3629 except UnicodeDecodeError as e:
3644 except UnicodeDecodeError as e:
3630 if not py_only :
3645 if not py_only :
3631 with io_open(tgt,'r', encoding='latin1') as f :
3646 with io_open(tgt,'r', encoding='latin1') as f :
3632 return f.read()
3647 return f.read()
3633 raise ValueError(("'%s' seem to be unreadable.") % target) from e
3648 raise ValueError(("'%s' seem to be unreadable.") % target) from e
3634 elif os.path.isdir(os.path.expanduser(tgt)):
3649 elif os.path.isdir(os.path.expanduser(tgt)):
3635 raise ValueError("'%s' is a directory, not a regular file." % target)
3650 raise ValueError("'%s' is a directory, not a regular file." % target)
3636
3651
3637 if search_ns:
3652 if search_ns:
3638 # Inspect namespace to load object source
3653 # Inspect namespace to load object source
3639 object_info = self.object_inspect(target, detail_level=1)
3654 object_info = self.object_inspect(target, detail_level=1)
3640 if object_info['found'] and object_info['source']:
3655 if object_info['found'] and object_info['source']:
3641 return object_info['source']
3656 return object_info['source']
3642
3657
3643 try: # User namespace
3658 try: # User namespace
3644 codeobj = eval(target, self.user_ns)
3659 codeobj = eval(target, self.user_ns)
3645 except Exception as e:
3660 except Exception as e:
3646 raise ValueError(("'%s' was not found in history, as a file, url, "
3661 raise ValueError(("'%s' was not found in history, as a file, url, "
3647 "nor in the user namespace.") % target) from e
3662 "nor in the user namespace.") % target) from e
3648
3663
3649 if isinstance(codeobj, str):
3664 if isinstance(codeobj, str):
3650 return codeobj
3665 return codeobj
3651 elif isinstance(codeobj, Macro):
3666 elif isinstance(codeobj, Macro):
3652 return codeobj.value
3667 return codeobj.value
3653
3668
3654 raise TypeError("%s is neither a string nor a macro." % target,
3669 raise TypeError("%s is neither a string nor a macro." % target,
3655 codeobj)
3670 codeobj)
3656
3671
3657 def _atexit_once(self):
3672 def _atexit_once(self):
3658 """
3673 """
3659 At exist operation that need to be called at most once.
3674 At exist operation that need to be called at most once.
3660 Second call to this function per instance will do nothing.
3675 Second call to this function per instance will do nothing.
3661 """
3676 """
3662
3677
3663 if not getattr(self, "_atexit_once_called", False):
3678 if not getattr(self, "_atexit_once_called", False):
3664 self._atexit_once_called = True
3679 self._atexit_once_called = True
3665 # Clear all user namespaces to release all references cleanly.
3680 # Clear all user namespaces to release all references cleanly.
3666 self.reset(new_session=False)
3681 self.reset(new_session=False)
3667 # Close the history session (this stores the end time and line count)
3682 # Close the history session (this stores the end time and line count)
3668 # this must be *before* the tempfile cleanup, in case of temporary
3683 # this must be *before* the tempfile cleanup, in case of temporary
3669 # history db
3684 # history db
3670 self.history_manager.end_session()
3685 self.history_manager.end_session()
3671 self.history_manager = None
3686 self.history_manager = None
3672
3687
3673 #-------------------------------------------------------------------------
3688 #-------------------------------------------------------------------------
3674 # Things related to IPython exiting
3689 # Things related to IPython exiting
3675 #-------------------------------------------------------------------------
3690 #-------------------------------------------------------------------------
3676 def atexit_operations(self):
3691 def atexit_operations(self):
3677 """This will be executed at the time of exit.
3692 """This will be executed at the time of exit.
3678
3693
3679 Cleanup operations and saving of persistent data that is done
3694 Cleanup operations and saving of persistent data that is done
3680 unconditionally by IPython should be performed here.
3695 unconditionally by IPython should be performed here.
3681
3696
3682 For things that may depend on startup flags or platform specifics (such
3697 For things that may depend on startup flags or platform specifics (such
3683 as having readline or not), register a separate atexit function in the
3698 as having readline or not), register a separate atexit function in the
3684 code that has the appropriate information, rather than trying to
3699 code that has the appropriate information, rather than trying to
3685 clutter
3700 clutter
3686 """
3701 """
3687 self._atexit_once()
3702 self._atexit_once()
3688
3703
3689 # Cleanup all tempfiles and folders left around
3704 # Cleanup all tempfiles and folders left around
3690 for tfile in self.tempfiles:
3705 for tfile in self.tempfiles:
3691 try:
3706 try:
3692 tfile.unlink()
3707 tfile.unlink()
3693 self.tempfiles.remove(tfile)
3708 self.tempfiles.remove(tfile)
3694 except FileNotFoundError:
3709 except FileNotFoundError:
3695 pass
3710 pass
3696 del self.tempfiles
3711 del self.tempfiles
3697 for tdir in self.tempdirs:
3712 for tdir in self.tempdirs:
3698 try:
3713 try:
3699 tdir.rmdir()
3714 tdir.rmdir()
3700 self.tempdirs.remove(tdir)
3715 self.tempdirs.remove(tdir)
3701 except FileNotFoundError:
3716 except FileNotFoundError:
3702 pass
3717 pass
3703 del self.tempdirs
3718 del self.tempdirs
3704
3719
3705 # Restore user's cursor
3720 # Restore user's cursor
3706 if hasattr(self, "editing_mode") and self.editing_mode == "vi":
3721 if hasattr(self, "editing_mode") and self.editing_mode == "vi":
3707 sys.stdout.write("\x1b[0 q")
3722 sys.stdout.write("\x1b[0 q")
3708 sys.stdout.flush()
3723 sys.stdout.flush()
3709
3724
3710 def cleanup(self):
3725 def cleanup(self):
3711 self.restore_sys_module_state()
3726 self.restore_sys_module_state()
3712
3727
3713
3728
3714 # Overridden in terminal subclass to change prompts
3729 # Overridden in terminal subclass to change prompts
3715 def switch_doctest_mode(self, mode):
3730 def switch_doctest_mode(self, mode):
3716 pass
3731 pass
3717
3732
3718
3733
3719 class InteractiveShellABC(metaclass=abc.ABCMeta):
3734 class InteractiveShellABC(metaclass=abc.ABCMeta):
3720 """An abstract base class for InteractiveShell."""
3735 """An abstract base class for InteractiveShell."""
3721
3736
3722 InteractiveShellABC.register(InteractiveShell)
3737 InteractiveShellABC.register(InteractiveShell)
@@ -1,70 +1,70 b''
1 # coding: utf-8
1 # coding: utf-8
2 """Tests for IPython.core.application"""
2 """Tests for IPython.core.application"""
3
3
4 import os
4 import os
5 import tempfile
5 import tempfile
6
6
7 from tempfile import TemporaryDirectory
7 from traitlets import Unicode
8 from traitlets import Unicode
8
9
9 from IPython.core.application import BaseIPythonApplication
10 from IPython.core.application import BaseIPythonApplication
10 from IPython.testing import decorators as dec
11 from IPython.testing import decorators as dec
11 from IPython.utils.tempdir import TemporaryDirectory
12
12
13
13
14 @dec.onlyif_unicode_paths
14 @dec.onlyif_unicode_paths
15 def test_unicode_cwd():
15 def test_unicode_cwd():
16 """Check that IPython starts with non-ascii characters in the path."""
16 """Check that IPython starts with non-ascii characters in the path."""
17 wd = tempfile.mkdtemp(suffix=u"€")
17 wd = tempfile.mkdtemp(suffix=u"€")
18
18
19 old_wd = os.getcwd()
19 old_wd = os.getcwd()
20 os.chdir(wd)
20 os.chdir(wd)
21 #raise Exception(repr(os.getcwd()))
21 #raise Exception(repr(os.getcwd()))
22 try:
22 try:
23 app = BaseIPythonApplication()
23 app = BaseIPythonApplication()
24 # The lines below are copied from Application.initialize()
24 # The lines below are copied from Application.initialize()
25 app.init_profile_dir()
25 app.init_profile_dir()
26 app.init_config_files()
26 app.init_config_files()
27 app.load_config_file(suppress_errors=False)
27 app.load_config_file(suppress_errors=False)
28 finally:
28 finally:
29 os.chdir(old_wd)
29 os.chdir(old_wd)
30
30
31 @dec.onlyif_unicode_paths
31 @dec.onlyif_unicode_paths
32 def test_unicode_ipdir():
32 def test_unicode_ipdir():
33 """Check that IPython starts with non-ascii characters in the IP dir."""
33 """Check that IPython starts with non-ascii characters in the IP dir."""
34 ipdir = tempfile.mkdtemp(suffix=u"€")
34 ipdir = tempfile.mkdtemp(suffix=u"€")
35
35
36 # Create the config file, so it tries to load it.
36 # Create the config file, so it tries to load it.
37 with open(os.path.join(ipdir, "ipython_config.py"), "w", encoding="utf-8") as f:
37 with open(os.path.join(ipdir, "ipython_config.py"), "w", encoding="utf-8") as f:
38 pass
38 pass
39
39
40 old_ipdir1 = os.environ.pop("IPYTHONDIR", None)
40 old_ipdir1 = os.environ.pop("IPYTHONDIR", None)
41 old_ipdir2 = os.environ.pop("IPYTHON_DIR", None)
41 old_ipdir2 = os.environ.pop("IPYTHON_DIR", None)
42 os.environ["IPYTHONDIR"] = ipdir
42 os.environ["IPYTHONDIR"] = ipdir
43 try:
43 try:
44 app = BaseIPythonApplication()
44 app = BaseIPythonApplication()
45 # The lines below are copied from Application.initialize()
45 # The lines below are copied from Application.initialize()
46 app.init_profile_dir()
46 app.init_profile_dir()
47 app.init_config_files()
47 app.init_config_files()
48 app.load_config_file(suppress_errors=False)
48 app.load_config_file(suppress_errors=False)
49 finally:
49 finally:
50 if old_ipdir1:
50 if old_ipdir1:
51 os.environ["IPYTHONDIR"] = old_ipdir1
51 os.environ["IPYTHONDIR"] = old_ipdir1
52 if old_ipdir2:
52 if old_ipdir2:
53 os.environ["IPYTHONDIR"] = old_ipdir2
53 os.environ["IPYTHONDIR"] = old_ipdir2
54
54
55 def test_cli_priority():
55 def test_cli_priority():
56 with TemporaryDirectory() as td:
56 with TemporaryDirectory() as td:
57
57
58 class TestApp(BaseIPythonApplication):
58 class TestApp(BaseIPythonApplication):
59 test = Unicode().tag(config=True)
59 test = Unicode().tag(config=True)
60
60
61 # Create the config file, so it tries to load it.
61 # Create the config file, so it tries to load it.
62 with open(os.path.join(td, "ipython_config.py"), "w", encoding="utf-8") as f:
62 with open(os.path.join(td, "ipython_config.py"), "w", encoding="utf-8") as f:
63 f.write("c.TestApp.test = 'config file'")
63 f.write("c.TestApp.test = 'config file'")
64
64
65 app = TestApp()
65 app = TestApp()
66 app.initialize(["--profile-dir", td])
66 app.initialize(["--profile-dir", td])
67 assert app.test == "config file"
67 assert app.test == "config file"
68 app = TestApp()
68 app = TestApp()
69 app.initialize(["--profile-dir", td, "--TestApp.test=cli"])
69 app.initialize(["--profile-dir", td, "--TestApp.test=cli"])
70 assert app.test == "cli"
70 assert app.test == "cli"
@@ -1,192 +1,193 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for completerlib.
2 """Tests for completerlib.
3
3
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Imports
7 # Imports
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9
9
10 import os
10 import os
11 import shutil
11 import shutil
12 import sys
12 import sys
13 import tempfile
13 import tempfile
14 import unittest
14 import unittest
15 from os.path import join
15 from os.path import join
16
16
17 from tempfile import TemporaryDirectory
18
17 from IPython.core.completerlib import magic_run_completer, module_completion, try_import
19 from IPython.core.completerlib import magic_run_completer, module_completion, try_import
18 from IPython.utils.tempdir import TemporaryDirectory
19 from IPython.testing.decorators import onlyif_unicode_paths
20 from IPython.testing.decorators import onlyif_unicode_paths
20
21
21
22
22 class MockEvent(object):
23 class MockEvent(object):
23 def __init__(self, line):
24 def __init__(self, line):
24 self.line = line
25 self.line = line
25
26
26 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
27 # Test functions begin
28 # Test functions begin
28 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
29 class Test_magic_run_completer(unittest.TestCase):
30 class Test_magic_run_completer(unittest.TestCase):
30 files = [u"aao.py", u"a.py", u"b.py", u"aao.txt"]
31 files = [u"aao.py", u"a.py", u"b.py", u"aao.txt"]
31 dirs = [u"adir/", "bdir/"]
32 dirs = [u"adir/", "bdir/"]
32
33
33 def setUp(self):
34 def setUp(self):
34 self.BASETESTDIR = tempfile.mkdtemp()
35 self.BASETESTDIR = tempfile.mkdtemp()
35 for fil in self.files:
36 for fil in self.files:
36 with open(join(self.BASETESTDIR, fil), "w", encoding="utf-8") as sfile:
37 with open(join(self.BASETESTDIR, fil), "w", encoding="utf-8") as sfile:
37 sfile.write("pass\n")
38 sfile.write("pass\n")
38 for d in self.dirs:
39 for d in self.dirs:
39 os.mkdir(join(self.BASETESTDIR, d))
40 os.mkdir(join(self.BASETESTDIR, d))
40
41
41 self.oldpath = os.getcwd()
42 self.oldpath = os.getcwd()
42 os.chdir(self.BASETESTDIR)
43 os.chdir(self.BASETESTDIR)
43
44
44 def tearDown(self):
45 def tearDown(self):
45 os.chdir(self.oldpath)
46 os.chdir(self.oldpath)
46 shutil.rmtree(self.BASETESTDIR)
47 shutil.rmtree(self.BASETESTDIR)
47
48
48 def test_1(self):
49 def test_1(self):
49 """Test magic_run_completer, should match two alternatives
50 """Test magic_run_completer, should match two alternatives
50 """
51 """
51 event = MockEvent(u"%run a")
52 event = MockEvent(u"%run a")
52 mockself = None
53 mockself = None
53 match = set(magic_run_completer(mockself, event))
54 match = set(magic_run_completer(mockself, event))
54 self.assertEqual(match, {u"a.py", u"aao.py", u"adir/"})
55 self.assertEqual(match, {u"a.py", u"aao.py", u"adir/"})
55
56
56 def test_2(self):
57 def test_2(self):
57 """Test magic_run_completer, should match one alternative
58 """Test magic_run_completer, should match one alternative
58 """
59 """
59 event = MockEvent(u"%run aa")
60 event = MockEvent(u"%run aa")
60 mockself = None
61 mockself = None
61 match = set(magic_run_completer(mockself, event))
62 match = set(magic_run_completer(mockself, event))
62 self.assertEqual(match, {u"aao.py"})
63 self.assertEqual(match, {u"aao.py"})
63
64
64 def test_3(self):
65 def test_3(self):
65 """Test magic_run_completer with unterminated " """
66 """Test magic_run_completer with unterminated " """
66 event = MockEvent(u'%run "a')
67 event = MockEvent(u'%run "a')
67 mockself = None
68 mockself = None
68 match = set(magic_run_completer(mockself, event))
69 match = set(magic_run_completer(mockself, event))
69 self.assertEqual(match, {u"a.py", u"aao.py", u"adir/"})
70 self.assertEqual(match, {u"a.py", u"aao.py", u"adir/"})
70
71
71 def test_completion_more_args(self):
72 def test_completion_more_args(self):
72 event = MockEvent(u'%run a.py ')
73 event = MockEvent(u'%run a.py ')
73 match = set(magic_run_completer(None, event))
74 match = set(magic_run_completer(None, event))
74 self.assertEqual(match, set(self.files + self.dirs))
75 self.assertEqual(match, set(self.files + self.dirs))
75
76
76 def test_completion_in_dir(self):
77 def test_completion_in_dir(self):
77 # Github issue #3459
78 # Github issue #3459
78 event = MockEvent(u'%run a.py {}'.format(join(self.BASETESTDIR, 'a')))
79 event = MockEvent(u'%run a.py {}'.format(join(self.BASETESTDIR, 'a')))
79 print(repr(event.line))
80 print(repr(event.line))
80 match = set(magic_run_completer(None, event))
81 match = set(magic_run_completer(None, event))
81 # We specifically use replace here rather than normpath, because
82 # We specifically use replace here rather than normpath, because
82 # at one point there were duplicates 'adir' and 'adir/', and normpath
83 # at one point there were duplicates 'adir' and 'adir/', and normpath
83 # would hide the failure for that.
84 # would hide the failure for that.
84 self.assertEqual(match, {join(self.BASETESTDIR, f).replace('\\','/')
85 self.assertEqual(match, {join(self.BASETESTDIR, f).replace('\\','/')
85 for f in (u'a.py', u'aao.py', u'aao.txt', u'adir/')})
86 for f in (u'a.py', u'aao.py', u'aao.txt', u'adir/')})
86
87
87 class Test_magic_run_completer_nonascii(unittest.TestCase):
88 class Test_magic_run_completer_nonascii(unittest.TestCase):
88 @onlyif_unicode_paths
89 @onlyif_unicode_paths
89 def setUp(self):
90 def setUp(self):
90 self.BASETESTDIR = tempfile.mkdtemp()
91 self.BASETESTDIR = tempfile.mkdtemp()
91 for fil in [u"aaΓΈ.py", u"a.py", u"b.py"]:
92 for fil in [u"aaΓΈ.py", u"a.py", u"b.py"]:
92 with open(join(self.BASETESTDIR, fil), "w", encoding="utf-8") as sfile:
93 with open(join(self.BASETESTDIR, fil), "w", encoding="utf-8") as sfile:
93 sfile.write("pass\n")
94 sfile.write("pass\n")
94 self.oldpath = os.getcwd()
95 self.oldpath = os.getcwd()
95 os.chdir(self.BASETESTDIR)
96 os.chdir(self.BASETESTDIR)
96
97
97 def tearDown(self):
98 def tearDown(self):
98 os.chdir(self.oldpath)
99 os.chdir(self.oldpath)
99 shutil.rmtree(self.BASETESTDIR)
100 shutil.rmtree(self.BASETESTDIR)
100
101
101 @onlyif_unicode_paths
102 @onlyif_unicode_paths
102 def test_1(self):
103 def test_1(self):
103 """Test magic_run_completer, should match two alternatives
104 """Test magic_run_completer, should match two alternatives
104 """
105 """
105 event = MockEvent(u"%run a")
106 event = MockEvent(u"%run a")
106 mockself = None
107 mockself = None
107 match = set(magic_run_completer(mockself, event))
108 match = set(magic_run_completer(mockself, event))
108 self.assertEqual(match, {u"a.py", u"aaΓΈ.py"})
109 self.assertEqual(match, {u"a.py", u"aaΓΈ.py"})
109
110
110 @onlyif_unicode_paths
111 @onlyif_unicode_paths
111 def test_2(self):
112 def test_2(self):
112 """Test magic_run_completer, should match one alternative
113 """Test magic_run_completer, should match one alternative
113 """
114 """
114 event = MockEvent(u"%run aa")
115 event = MockEvent(u"%run aa")
115 mockself = None
116 mockself = None
116 match = set(magic_run_completer(mockself, event))
117 match = set(magic_run_completer(mockself, event))
117 self.assertEqual(match, {u"aaΓΈ.py"})
118 self.assertEqual(match, {u"aaΓΈ.py"})
118
119
119 @onlyif_unicode_paths
120 @onlyif_unicode_paths
120 def test_3(self):
121 def test_3(self):
121 """Test magic_run_completer with unterminated " """
122 """Test magic_run_completer with unterminated " """
122 event = MockEvent(u'%run "a')
123 event = MockEvent(u'%run "a')
123 mockself = None
124 mockself = None
124 match = set(magic_run_completer(mockself, event))
125 match = set(magic_run_completer(mockself, event))
125 self.assertEqual(match, {u"a.py", u"aaΓΈ.py"})
126 self.assertEqual(match, {u"a.py", u"aaΓΈ.py"})
126
127
127 # module_completer:
128 # module_completer:
128
129
129 def test_import_invalid_module():
130 def test_import_invalid_module():
130 """Testing of issue https://github.com/ipython/ipython/issues/1107"""
131 """Testing of issue https://github.com/ipython/ipython/issues/1107"""
131 invalid_module_names = {'foo-bar', 'foo:bar', '10foo'}
132 invalid_module_names = {'foo-bar', 'foo:bar', '10foo'}
132 valid_module_names = {'foobar'}
133 valid_module_names = {'foobar'}
133 with TemporaryDirectory() as tmpdir:
134 with TemporaryDirectory() as tmpdir:
134 sys.path.insert( 0, tmpdir )
135 sys.path.insert( 0, tmpdir )
135 for name in invalid_module_names | valid_module_names:
136 for name in invalid_module_names | valid_module_names:
136 filename = os.path.join(tmpdir, name + ".py")
137 filename = os.path.join(tmpdir, name + ".py")
137 open(filename, "w", encoding="utf-8").close()
138 open(filename, "w", encoding="utf-8").close()
138
139
139 s = set( module_completion('import foo') )
140 s = set( module_completion('import foo') )
140 intersection = s.intersection(invalid_module_names)
141 intersection = s.intersection(invalid_module_names)
141 assert intersection == set()
142 assert intersection == set()
142
143
143 assert valid_module_names.issubset(s), valid_module_names.intersection(s)
144 assert valid_module_names.issubset(s), valid_module_names.intersection(s)
144
145
145
146
146 def test_bad_module_all():
147 def test_bad_module_all():
147 """Test module with invalid __all__
148 """Test module with invalid __all__
148
149
149 https://github.com/ipython/ipython/issues/9678
150 https://github.com/ipython/ipython/issues/9678
150 """
151 """
151 testsdir = os.path.dirname(__file__)
152 testsdir = os.path.dirname(__file__)
152 sys.path.insert(0, testsdir)
153 sys.path.insert(0, testsdir)
153 try:
154 try:
154 results = module_completion("from bad_all import ")
155 results = module_completion("from bad_all import ")
155 assert "puppies" in results
156 assert "puppies" in results
156 for r in results:
157 for r in results:
157 assert isinstance(r, str)
158 assert isinstance(r, str)
158
159
159 # bad_all doesn't contain submodules, but this completion
160 # bad_all doesn't contain submodules, but this completion
160 # should finish without raising an exception:
161 # should finish without raising an exception:
161 results = module_completion("import bad_all.")
162 results = module_completion("import bad_all.")
162 assert results == []
163 assert results == []
163 finally:
164 finally:
164 sys.path.remove(testsdir)
165 sys.path.remove(testsdir)
165
166
166
167
167 def test_module_without_init():
168 def test_module_without_init():
168 """
169 """
169 Test module without __init__.py.
170 Test module without __init__.py.
170
171
171 https://github.com/ipython/ipython/issues/11226
172 https://github.com/ipython/ipython/issues/11226
172 """
173 """
173 fake_module_name = "foo"
174 fake_module_name = "foo"
174 with TemporaryDirectory() as tmpdir:
175 with TemporaryDirectory() as tmpdir:
175 sys.path.insert(0, tmpdir)
176 sys.path.insert(0, tmpdir)
176 try:
177 try:
177 os.makedirs(os.path.join(tmpdir, fake_module_name))
178 os.makedirs(os.path.join(tmpdir, fake_module_name))
178 s = try_import(mod=fake_module_name)
179 s = try_import(mod=fake_module_name)
179 assert s == []
180 assert s == []
180 finally:
181 finally:
181 sys.path.remove(tmpdir)
182 sys.path.remove(tmpdir)
182
183
183
184
184 def test_valid_exported_submodules():
185 def test_valid_exported_submodules():
185 """
186 """
186 Test checking exported (__all__) objects are submodules
187 Test checking exported (__all__) objects are submodules
187 """
188 """
188 results = module_completion("import os.pa")
189 results = module_completion("import os.pa")
189 # ensure we get a valid submodule:
190 # ensure we get a valid submodule:
190 assert "os.path" in results
191 assert "os.path" in results
191 # ensure we don't get objects that aren't submodules:
192 # ensure we don't get objects that aren't submodules:
192 assert "os.pathconf" not in results
193 assert "os.pathconf" not in results
@@ -1,94 +1,95 b''
1 import os.path
1 import os.path
2
2
3 from tempfile import TemporaryDirectory
4
3 import IPython.testing.tools as tt
5 import IPython.testing.tools as tt
4 from IPython.utils.syspathcontext import prepended_to_syspath
6 from IPython.utils.syspathcontext import prepended_to_syspath
5 from IPython.utils.tempdir import TemporaryDirectory
6
7
7 ext1_content = """
8 ext1_content = """
8 def load_ipython_extension(ip):
9 def load_ipython_extension(ip):
9 print("Running ext1 load")
10 print("Running ext1 load")
10
11
11 def unload_ipython_extension(ip):
12 def unload_ipython_extension(ip):
12 print("Running ext1 unload")
13 print("Running ext1 unload")
13 """
14 """
14
15
15 ext2_content = """
16 ext2_content = """
16 def load_ipython_extension(ip):
17 def load_ipython_extension(ip):
17 print("Running ext2 load")
18 print("Running ext2 load")
18 """
19 """
19
20
20 ext3_content = """
21 ext3_content = """
21 def load_ipython_extension(ip):
22 def load_ipython_extension(ip):
22 ip2 = get_ipython()
23 ip2 = get_ipython()
23 print(ip is ip2)
24 print(ip is ip2)
24 """
25 """
25
26
26 def test_extension_loading():
27 def test_extension_loading():
27 em = get_ipython().extension_manager
28 em = get_ipython().extension_manager
28 with TemporaryDirectory() as td:
29 with TemporaryDirectory() as td:
29 ext1 = os.path.join(td, "ext1.py")
30 ext1 = os.path.join(td, "ext1.py")
30 with open(ext1, "w", encoding="utf-8") as f:
31 with open(ext1, "w", encoding="utf-8") as f:
31 f.write(ext1_content)
32 f.write(ext1_content)
32
33
33 ext2 = os.path.join(td, "ext2.py")
34 ext2 = os.path.join(td, "ext2.py")
34 with open(ext2, "w", encoding="utf-8") as f:
35 with open(ext2, "w", encoding="utf-8") as f:
35 f.write(ext2_content)
36 f.write(ext2_content)
36
37
37 with prepended_to_syspath(td):
38 with prepended_to_syspath(td):
38 assert 'ext1' not in em.loaded
39 assert 'ext1' not in em.loaded
39 assert 'ext2' not in em.loaded
40 assert 'ext2' not in em.loaded
40
41
41 # Load extension
42 # Load extension
42 with tt.AssertPrints("Running ext1 load"):
43 with tt.AssertPrints("Running ext1 load"):
43 assert em.load_extension('ext1') is None
44 assert em.load_extension('ext1') is None
44 assert 'ext1' in em.loaded
45 assert 'ext1' in em.loaded
45
46
46 # Should refuse to load it again
47 # Should refuse to load it again
47 with tt.AssertNotPrints("Running ext1 load"):
48 with tt.AssertNotPrints("Running ext1 load"):
48 assert em.load_extension('ext1') == 'already loaded'
49 assert em.load_extension('ext1') == 'already loaded'
49
50
50 # Reload
51 # Reload
51 with tt.AssertPrints("Running ext1 unload"):
52 with tt.AssertPrints("Running ext1 unload"):
52 with tt.AssertPrints("Running ext1 load", suppress=False):
53 with tt.AssertPrints("Running ext1 load", suppress=False):
53 em.reload_extension('ext1')
54 em.reload_extension('ext1')
54
55
55 # Unload
56 # Unload
56 with tt.AssertPrints("Running ext1 unload"):
57 with tt.AssertPrints("Running ext1 unload"):
57 assert em.unload_extension('ext1') is None
58 assert em.unload_extension('ext1') is None
58
59
59 # Can't unload again
60 # Can't unload again
60 with tt.AssertNotPrints("Running ext1 unload"):
61 with tt.AssertNotPrints("Running ext1 unload"):
61 assert em.unload_extension('ext1') == 'not loaded'
62 assert em.unload_extension('ext1') == 'not loaded'
62 assert em.unload_extension('ext2') == 'not loaded'
63 assert em.unload_extension('ext2') == 'not loaded'
63
64
64 # Load extension 2
65 # Load extension 2
65 with tt.AssertPrints("Running ext2 load"):
66 with tt.AssertPrints("Running ext2 load"):
66 assert em.load_extension('ext2') is None
67 assert em.load_extension('ext2') is None
67
68
68 # Can't unload this
69 # Can't unload this
69 assert em.unload_extension('ext2') == 'no unload function'
70 assert em.unload_extension('ext2') == 'no unload function'
70
71
71 # But can reload it
72 # But can reload it
72 with tt.AssertPrints("Running ext2 load"):
73 with tt.AssertPrints("Running ext2 load"):
73 em.reload_extension('ext2')
74 em.reload_extension('ext2')
74
75
75
76
76 def test_extension_builtins():
77 def test_extension_builtins():
77 em = get_ipython().extension_manager
78 em = get_ipython().extension_manager
78 with TemporaryDirectory() as td:
79 with TemporaryDirectory() as td:
79 ext3 = os.path.join(td, "ext3.py")
80 ext3 = os.path.join(td, "ext3.py")
80 with open(ext3, "w", encoding="utf-8") as f:
81 with open(ext3, "w", encoding="utf-8") as f:
81 f.write(ext3_content)
82 f.write(ext3_content)
82
83
83 assert 'ext3' not in em.loaded
84 assert 'ext3' not in em.loaded
84
85
85 with prepended_to_syspath(td):
86 with prepended_to_syspath(td):
86 # Load extension
87 # Load extension
87 with tt.AssertPrints("True"):
88 with tt.AssertPrints("True"):
88 assert em.load_extension('ext3') is None
89 assert em.load_extension('ext3') is None
89 assert 'ext3' in em.loaded
90 assert 'ext3' in em.loaded
90
91
91
92
92 def test_non_extension():
93 def test_non_extension():
93 em = get_ipython().extension_manager
94 em = get_ipython().extension_manager
94 assert em.load_extension("sys") == "no load function"
95 assert em.load_extension("sys") == "no load function"
@@ -1,227 +1,229 b''
1 # coding: utf-8
1 # coding: utf-8
2 """Tests for the IPython tab-completion machinery.
2 """Tests for the IPython tab-completion machinery.
3 """
3 """
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Module imports
5 # Module imports
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7
7
8 # stdlib
8 # stdlib
9 import io
9 import io
10 from pathlib import Path
10 import sqlite3
11 import sys
11 import sys
12 import tempfile
12 import tempfile
13 from datetime import datetime
13 from datetime import datetime
14 import sqlite3
14 from pathlib import Path
15
15
16 from tempfile import TemporaryDirectory
16 # our own packages
17 # our own packages
17 from traitlets.config.loader import Config
18 from traitlets.config.loader import Config
18 from IPython.utils.tempdir import TemporaryDirectory
19
19 from IPython.core.history import HistoryManager, extract_hist_ranges
20 from IPython.core.history import HistoryManager, extract_hist_ranges
20
21
22
21 def test_proper_default_encoding():
23 def test_proper_default_encoding():
22 assert sys.getdefaultencoding() == "utf-8"
24 assert sys.getdefaultencoding() == "utf-8"
23
25
24 def test_history():
26 def test_history():
25 ip = get_ipython()
27 ip = get_ipython()
26 with TemporaryDirectory() as tmpdir:
28 with TemporaryDirectory() as tmpdir:
27 tmp_path = Path(tmpdir)
29 tmp_path = Path(tmpdir)
28 hist_manager_ori = ip.history_manager
30 hist_manager_ori = ip.history_manager
29 hist_file = tmp_path / "history.sqlite"
31 hist_file = tmp_path / "history.sqlite"
30 try:
32 try:
31 ip.history_manager = HistoryManager(shell=ip, hist_file=hist_file)
33 ip.history_manager = HistoryManager(shell=ip, hist_file=hist_file)
32 hist = ["a=1", "def f():\n test = 1\n return test", "b='β‚¬Γ†ΒΎΓ·ΓŸ'"]
34 hist = ["a=1", "def f():\n test = 1\n return test", "b='β‚¬Γ†ΒΎΓ·ΓŸ'"]
33 for i, h in enumerate(hist, start=1):
35 for i, h in enumerate(hist, start=1):
34 ip.history_manager.store_inputs(i, h)
36 ip.history_manager.store_inputs(i, h)
35
37
36 ip.history_manager.db_log_output = True
38 ip.history_manager.db_log_output = True
37 # Doesn't match the input, but we'll just check it's stored.
39 # Doesn't match the input, but we'll just check it's stored.
38 ip.history_manager.output_hist_reprs[3] = "spam"
40 ip.history_manager.output_hist_reprs[3] = "spam"
39 ip.history_manager.store_output(3)
41 ip.history_manager.store_output(3)
40
42
41 assert ip.history_manager.input_hist_raw == [""] + hist
43 assert ip.history_manager.input_hist_raw == [""] + hist
42
44
43 # Detailed tests for _get_range_session
45 # Detailed tests for _get_range_session
44 grs = ip.history_manager._get_range_session
46 grs = ip.history_manager._get_range_session
45 assert list(grs(start=2, stop=-1)) == list(zip([0], [2], hist[1:-1]))
47 assert list(grs(start=2, stop=-1)) == list(zip([0], [2], hist[1:-1]))
46 assert list(grs(start=-2)) == list(zip([0, 0], [2, 3], hist[-2:]))
48 assert list(grs(start=-2)) == list(zip([0, 0], [2, 3], hist[-2:]))
47 assert list(grs(output=True)) == list(
49 assert list(grs(output=True)) == list(
48 zip([0, 0, 0], [1, 2, 3], zip(hist, [None, None, "spam"]))
50 zip([0, 0, 0], [1, 2, 3], zip(hist, [None, None, "spam"]))
49 )
51 )
50
52
51 # Check whether specifying a range beyond the end of the current
53 # Check whether specifying a range beyond the end of the current
52 # session results in an error (gh-804)
54 # session results in an error (gh-804)
53 ip.magic('%hist 2-500')
55 ip.magic('%hist 2-500')
54
56
55 # Check that we can write non-ascii characters to a file
57 # Check that we can write non-ascii characters to a file
56 ip.magic("%%hist -f %s" % (tmp_path / "test1"))
58 ip.magic("%%hist -f %s" % (tmp_path / "test1"))
57 ip.magic("%%hist -pf %s" % (tmp_path / "test2"))
59 ip.magic("%%hist -pf %s" % (tmp_path / "test2"))
58 ip.magic("%%hist -nf %s" % (tmp_path / "test3"))
60 ip.magic("%%hist -nf %s" % (tmp_path / "test3"))
59 ip.magic("%%save %s 1-10" % (tmp_path / "test4"))
61 ip.magic("%%save %s 1-10" % (tmp_path / "test4"))
60
62
61 # New session
63 # New session
62 ip.history_manager.reset()
64 ip.history_manager.reset()
63 newcmds = ["z=5", "class X(object):\n pass", "k='p'", "z=5"]
65 newcmds = ["z=5", "class X(object):\n pass", "k='p'", "z=5"]
64 for i, cmd in enumerate(newcmds, start=1):
66 for i, cmd in enumerate(newcmds, start=1):
65 ip.history_manager.store_inputs(i, cmd)
67 ip.history_manager.store_inputs(i, cmd)
66 gothist = ip.history_manager.get_range(start=1, stop=4)
68 gothist = ip.history_manager.get_range(start=1, stop=4)
67 assert list(gothist) == list(zip([0, 0, 0], [1, 2, 3], newcmds))
69 assert list(gothist) == list(zip([0, 0, 0], [1, 2, 3], newcmds))
68 # Previous session:
70 # Previous session:
69 gothist = ip.history_manager.get_range(-1, 1, 4)
71 gothist = ip.history_manager.get_range(-1, 1, 4)
70 assert list(gothist) == list(zip([1, 1, 1], [1, 2, 3], hist))
72 assert list(gothist) == list(zip([1, 1, 1], [1, 2, 3], hist))
71
73
72 newhist = [(2, i, c) for (i, c) in enumerate(newcmds, 1)]
74 newhist = [(2, i, c) for (i, c) in enumerate(newcmds, 1)]
73
75
74 # Check get_hist_tail
76 # Check get_hist_tail
75 gothist = ip.history_manager.get_tail(5, output=True,
77 gothist = ip.history_manager.get_tail(5, output=True,
76 include_latest=True)
78 include_latest=True)
77 expected = [(1, 3, (hist[-1], "spam"))] \
79 expected = [(1, 3, (hist[-1], "spam"))] \
78 + [(s, n, (c, None)) for (s, n, c) in newhist]
80 + [(s, n, (c, None)) for (s, n, c) in newhist]
79 assert list(gothist) == expected
81 assert list(gothist) == expected
80
82
81 gothist = ip.history_manager.get_tail(2)
83 gothist = ip.history_manager.get_tail(2)
82 expected = newhist[-3:-1]
84 expected = newhist[-3:-1]
83 assert list(gothist) == expected
85 assert list(gothist) == expected
84
86
85 # Check get_hist_search
87 # Check get_hist_search
86
88
87 gothist = ip.history_manager.search("*test*")
89 gothist = ip.history_manager.search("*test*")
88 assert list(gothist) == [(1, 2, hist[1])]
90 assert list(gothist) == [(1, 2, hist[1])]
89
91
90 gothist = ip.history_manager.search("*=*")
92 gothist = ip.history_manager.search("*=*")
91 assert list(gothist) == [
93 assert list(gothist) == [
92 (1, 1, hist[0]),
94 (1, 1, hist[0]),
93 (1, 2, hist[1]),
95 (1, 2, hist[1]),
94 (1, 3, hist[2]),
96 (1, 3, hist[2]),
95 newhist[0],
97 newhist[0],
96 newhist[2],
98 newhist[2],
97 newhist[3],
99 newhist[3],
98 ]
100 ]
99
101
100 gothist = ip.history_manager.search("*=*", n=4)
102 gothist = ip.history_manager.search("*=*", n=4)
101 assert list(gothist) == [
103 assert list(gothist) == [
102 (1, 3, hist[2]),
104 (1, 3, hist[2]),
103 newhist[0],
105 newhist[0],
104 newhist[2],
106 newhist[2],
105 newhist[3],
107 newhist[3],
106 ]
108 ]
107
109
108 gothist = ip.history_manager.search("*=*", unique=True)
110 gothist = ip.history_manager.search("*=*", unique=True)
109 assert list(gothist) == [
111 assert list(gothist) == [
110 (1, 1, hist[0]),
112 (1, 1, hist[0]),
111 (1, 2, hist[1]),
113 (1, 2, hist[1]),
112 (1, 3, hist[2]),
114 (1, 3, hist[2]),
113 newhist[2],
115 newhist[2],
114 newhist[3],
116 newhist[3],
115 ]
117 ]
116
118
117 gothist = ip.history_manager.search("*=*", unique=True, n=3)
119 gothist = ip.history_manager.search("*=*", unique=True, n=3)
118 assert list(gothist) == [(1, 3, hist[2]), newhist[2], newhist[3]]
120 assert list(gothist) == [(1, 3, hist[2]), newhist[2], newhist[3]]
119
121
120 gothist = ip.history_manager.search("b*", output=True)
122 gothist = ip.history_manager.search("b*", output=True)
121 assert list(gothist) == [(1, 3, (hist[2], "spam"))]
123 assert list(gothist) == [(1, 3, (hist[2], "spam"))]
122
124
123 # Cross testing: check that magic %save can get previous session.
125 # Cross testing: check that magic %save can get previous session.
124 testfilename = (tmp_path / "test.py").resolve()
126 testfilename = (tmp_path / "test.py").resolve()
125 ip.magic("save " + str(testfilename) + " ~1/1-3")
127 ip.magic("save " + str(testfilename) + " ~1/1-3")
126 with io.open(testfilename, encoding="utf-8") as testfile:
128 with io.open(testfilename, encoding="utf-8") as testfile:
127 assert testfile.read() == "# coding: utf-8\n" + "\n".join(hist) + "\n"
129 assert testfile.read() == "# coding: utf-8\n" + "\n".join(hist) + "\n"
128
130
129 # Duplicate line numbers - check that it doesn't crash, and
131 # Duplicate line numbers - check that it doesn't crash, and
130 # gets a new session
132 # gets a new session
131 ip.history_manager.store_inputs(1, "rogue")
133 ip.history_manager.store_inputs(1, "rogue")
132 ip.history_manager.writeout_cache()
134 ip.history_manager.writeout_cache()
133 assert ip.history_manager.session_number == 3
135 assert ip.history_manager.session_number == 3
134
136
135 # Check that session and line values are not just max values
137 # Check that session and line values are not just max values
136 sessid, lineno, entry = newhist[-1]
138 sessid, lineno, entry = newhist[-1]
137 assert lineno > 1
139 assert lineno > 1
138 ip.history_manager.reset()
140 ip.history_manager.reset()
139 lineno = 1
141 lineno = 1
140 ip.history_manager.store_inputs(lineno, entry)
142 ip.history_manager.store_inputs(lineno, entry)
141 gothist = ip.history_manager.search("*=*", unique=True)
143 gothist = ip.history_manager.search("*=*", unique=True)
142 hist = list(gothist)[-1]
144 hist = list(gothist)[-1]
143 assert sessid < hist[0]
145 assert sessid < hist[0]
144 assert hist[1:] == (lineno, entry)
146 assert hist[1:] == (lineno, entry)
145 finally:
147 finally:
146 # Ensure saving thread is shut down before we try to clean up the files
148 # Ensure saving thread is shut down before we try to clean up the files
147 ip.history_manager.save_thread.stop()
149 ip.history_manager.save_thread.stop()
148 # Forcibly close database rather than relying on garbage collection
150 # Forcibly close database rather than relying on garbage collection
149 ip.history_manager.db.close()
151 ip.history_manager.db.close()
150 # Restore history manager
152 # Restore history manager
151 ip.history_manager = hist_manager_ori
153 ip.history_manager = hist_manager_ori
152
154
153
155
154 def test_extract_hist_ranges():
156 def test_extract_hist_ranges():
155 instr = "1 2/3 ~4/5-6 ~4/7-~4/9 ~9/2-~7/5 ~10/"
157 instr = "1 2/3 ~4/5-6 ~4/7-~4/9 ~9/2-~7/5 ~10/"
156 expected = [(0, 1, 2), # 0 == current session
158 expected = [(0, 1, 2), # 0 == current session
157 (2, 3, 4),
159 (2, 3, 4),
158 (-4, 5, 7),
160 (-4, 5, 7),
159 (-4, 7, 10),
161 (-4, 7, 10),
160 (-9, 2, None), # None == to end
162 (-9, 2, None), # None == to end
161 (-8, 1, None),
163 (-8, 1, None),
162 (-7, 1, 6),
164 (-7, 1, 6),
163 (-10, 1, None)]
165 (-10, 1, None)]
164 actual = list(extract_hist_ranges(instr))
166 actual = list(extract_hist_ranges(instr))
165 assert actual == expected
167 assert actual == expected
166
168
167
169
168 def test_extract_hist_ranges_empty_str():
170 def test_extract_hist_ranges_empty_str():
169 instr = ""
171 instr = ""
170 expected = [(0, 1, None)] # 0 == current session, None == to end
172 expected = [(0, 1, None)] # 0 == current session, None == to end
171 actual = list(extract_hist_ranges(instr))
173 actual = list(extract_hist_ranges(instr))
172 assert actual == expected
174 assert actual == expected
173
175
174
176
175 def test_magic_rerun():
177 def test_magic_rerun():
176 """Simple test for %rerun (no args -> rerun last line)"""
178 """Simple test for %rerun (no args -> rerun last line)"""
177 ip = get_ipython()
179 ip = get_ipython()
178 ip.run_cell("a = 10", store_history=True)
180 ip.run_cell("a = 10", store_history=True)
179 ip.run_cell("a += 1", store_history=True)
181 ip.run_cell("a += 1", store_history=True)
180 assert ip.user_ns["a"] == 11
182 assert ip.user_ns["a"] == 11
181 ip.run_cell("%rerun", store_history=True)
183 ip.run_cell("%rerun", store_history=True)
182 assert ip.user_ns["a"] == 12
184 assert ip.user_ns["a"] == 12
183
185
184 def test_timestamp_type():
186 def test_timestamp_type():
185 ip = get_ipython()
187 ip = get_ipython()
186 info = ip.history_manager.get_session_info()
188 info = ip.history_manager.get_session_info()
187 assert isinstance(info[1], datetime)
189 assert isinstance(info[1], datetime)
188
190
189 def test_hist_file_config():
191 def test_hist_file_config():
190 cfg = Config()
192 cfg = Config()
191 tfile = tempfile.NamedTemporaryFile(delete=False)
193 tfile = tempfile.NamedTemporaryFile(delete=False)
192 cfg.HistoryManager.hist_file = Path(tfile.name)
194 cfg.HistoryManager.hist_file = Path(tfile.name)
193 try:
195 try:
194 hm = HistoryManager(shell=get_ipython(), config=cfg)
196 hm = HistoryManager(shell=get_ipython(), config=cfg)
195 assert hm.hist_file == cfg.HistoryManager.hist_file
197 assert hm.hist_file == cfg.HistoryManager.hist_file
196 finally:
198 finally:
197 try:
199 try:
198 Path(tfile.name).unlink()
200 Path(tfile.name).unlink()
199 except OSError:
201 except OSError:
200 # same catch as in testing.tools.TempFileMixin
202 # same catch as in testing.tools.TempFileMixin
201 # On Windows, even though we close the file, we still can't
203 # On Windows, even though we close the file, we still can't
202 # delete it. I have no clue why
204 # delete it. I have no clue why
203 pass
205 pass
204
206
205 def test_histmanager_disabled():
207 def test_histmanager_disabled():
206 """Ensure that disabling the history manager doesn't create a database."""
208 """Ensure that disabling the history manager doesn't create a database."""
207 cfg = Config()
209 cfg = Config()
208 cfg.HistoryAccessor.enabled = False
210 cfg.HistoryAccessor.enabled = False
209
211
210 ip = get_ipython()
212 ip = get_ipython()
211 with TemporaryDirectory() as tmpdir:
213 with TemporaryDirectory() as tmpdir:
212 hist_manager_ori = ip.history_manager
214 hist_manager_ori = ip.history_manager
213 hist_file = Path(tmpdir) / "history.sqlite"
215 hist_file = Path(tmpdir) / "history.sqlite"
214 cfg.HistoryManager.hist_file = hist_file
216 cfg.HistoryManager.hist_file = hist_file
215 try:
217 try:
216 ip.history_manager = HistoryManager(shell=ip, config=cfg)
218 ip.history_manager = HistoryManager(shell=ip, config=cfg)
217 hist = ["a=1", "def f():\n test = 1\n return test", "b='β‚¬Γ†ΒΎΓ·ΓŸ'"]
219 hist = ["a=1", "def f():\n test = 1\n return test", "b='β‚¬Γ†ΒΎΓ·ΓŸ'"]
218 for i, h in enumerate(hist, start=1):
220 for i, h in enumerate(hist, start=1):
219 ip.history_manager.store_inputs(i, h)
221 ip.history_manager.store_inputs(i, h)
220 assert ip.history_manager.input_hist_raw == [""] + hist
222 assert ip.history_manager.input_hist_raw == [""] + hist
221 ip.history_manager.reset()
223 ip.history_manager.reset()
222 ip.history_manager.end_session()
224 ip.history_manager.end_session()
223 finally:
225 finally:
224 ip.history_manager = hist_manager_ori
226 ip.history_manager = hist_manager_ori
225
227
226 # hist_file should not be created
228 # hist_file should not be created
227 assert hist_file.exists() is False
229 assert hist_file.exists() is False
@@ -1,26 +1,27 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Test IPython.core.logger"""
2 """Test IPython.core.logger"""
3
3
4 import os.path
4 import os.path
5
5 import pytest
6 import pytest
7 from tempfile import TemporaryDirectory
6
8
7 from IPython.utils.tempdir import TemporaryDirectory
8
9
9 def test_logstart_inaccessible_file():
10 def test_logstart_inaccessible_file():
10 with pytest.raises(IOError):
11 with pytest.raises(IOError):
11 _ip.logger.logstart(logfname="/") # Opening that filename will fail.
12 _ip.logger.logstart(logfname="/") # Opening that filename will fail.
12
13
13 try:
14 try:
14 _ip.run_cell("a=1") # Check it doesn't try to log this
15 _ip.run_cell("a=1") # Check it doesn't try to log this
15 finally:
16 finally:
16 _ip.logger.log_active = False # If this fails, don't let later tests fail
17 _ip.logger.log_active = False # If this fails, don't let later tests fail
17
18
18 def test_logstart_unicode():
19 def test_logstart_unicode():
19 with TemporaryDirectory() as tdir:
20 with TemporaryDirectory() as tdir:
20 logfname = os.path.join(tdir, "test_unicode.log")
21 logfname = os.path.join(tdir, "test_unicode.log")
21 _ip.run_cell("'abc€'")
22 _ip.run_cell("'abc€'")
22 try:
23 try:
23 _ip.magic("logstart -to %s" % logfname)
24 _ip.magic("logstart -to %s" % logfname)
24 _ip.run_cell("'abc€'")
25 _ip.run_cell("'abc€'")
25 finally:
26 finally:
26 _ip.logger.logstop()
27 _ip.logger.logstop()
@@ -1,201 +1,201 b''
1 import errno
1 import errno
2 import os
2 import os
3 import shutil
3 import shutil
4 import sys
4 import sys
5 import tempfile
5 import tempfile
6 import warnings
6 import warnings
7 from unittest.mock import patch
7 from unittest.mock import patch
8
8
9 from testpath import modified_env, assert_isdir, assert_isfile
9 from tempfile import TemporaryDirectory
10 from testpath import assert_isdir, assert_isfile, modified_env
10
11
11 from IPython import paths
12 from IPython import paths
12 from IPython.testing.decorators import skip_win32
13 from IPython.testing.decorators import skip_win32
13 from IPython.utils.tempdir import TemporaryDirectory
14
14
15 TMP_TEST_DIR = os.path.realpath(tempfile.mkdtemp())
15 TMP_TEST_DIR = os.path.realpath(tempfile.mkdtemp())
16 HOME_TEST_DIR = os.path.join(TMP_TEST_DIR, "home_test_dir")
16 HOME_TEST_DIR = os.path.join(TMP_TEST_DIR, "home_test_dir")
17 XDG_TEST_DIR = os.path.join(HOME_TEST_DIR, "xdg_test_dir")
17 XDG_TEST_DIR = os.path.join(HOME_TEST_DIR, "xdg_test_dir")
18 XDG_CACHE_DIR = os.path.join(HOME_TEST_DIR, "xdg_cache_dir")
18 XDG_CACHE_DIR = os.path.join(HOME_TEST_DIR, "xdg_cache_dir")
19 IP_TEST_DIR = os.path.join(HOME_TEST_DIR,'.ipython')
19 IP_TEST_DIR = os.path.join(HOME_TEST_DIR,'.ipython')
20
20
21 def setup_module():
21 def setup_module():
22 """Setup testenvironment for the module:
22 """Setup testenvironment for the module:
23
23
24 - Adds dummy home dir tree
24 - Adds dummy home dir tree
25 """
25 """
26 # Do not mask exceptions here. In particular, catching WindowsError is a
26 # Do not mask exceptions here. In particular, catching WindowsError is a
27 # problem because that exception is only defined on Windows...
27 # problem because that exception is only defined on Windows...
28 os.makedirs(IP_TEST_DIR)
28 os.makedirs(IP_TEST_DIR)
29 os.makedirs(os.path.join(XDG_TEST_DIR, 'ipython'))
29 os.makedirs(os.path.join(XDG_TEST_DIR, 'ipython'))
30 os.makedirs(os.path.join(XDG_CACHE_DIR, 'ipython'))
30 os.makedirs(os.path.join(XDG_CACHE_DIR, 'ipython'))
31
31
32
32
33 def teardown_module():
33 def teardown_module():
34 """Teardown testenvironment for the module:
34 """Teardown testenvironment for the module:
35
35
36 - Remove dummy home dir tree
36 - Remove dummy home dir tree
37 """
37 """
38 # Note: we remove the parent test dir, which is the root of all test
38 # Note: we remove the parent test dir, which is the root of all test
39 # subdirs we may have created. Use shutil instead of os.removedirs, so
39 # subdirs we may have created. Use shutil instead of os.removedirs, so
40 # that non-empty directories are all recursively removed.
40 # that non-empty directories are all recursively removed.
41 shutil.rmtree(TMP_TEST_DIR)
41 shutil.rmtree(TMP_TEST_DIR)
42
42
43 def patch_get_home_dir(dirpath):
43 def patch_get_home_dir(dirpath):
44 return patch.object(paths, 'get_home_dir', return_value=dirpath)
44 return patch.object(paths, 'get_home_dir', return_value=dirpath)
45
45
46
46
47 def test_get_ipython_dir_1():
47 def test_get_ipython_dir_1():
48 """test_get_ipython_dir_1, Testcase to see if we can call get_ipython_dir without Exceptions."""
48 """test_get_ipython_dir_1, Testcase to see if we can call get_ipython_dir without Exceptions."""
49 env_ipdir = os.path.join("someplace", ".ipython")
49 env_ipdir = os.path.join("someplace", ".ipython")
50 with patch.object(paths, '_writable_dir', return_value=True), \
50 with patch.object(paths, '_writable_dir', return_value=True), \
51 modified_env({'IPYTHONDIR': env_ipdir}):
51 modified_env({'IPYTHONDIR': env_ipdir}):
52 ipdir = paths.get_ipython_dir()
52 ipdir = paths.get_ipython_dir()
53
53
54 assert ipdir == env_ipdir
54 assert ipdir == env_ipdir
55
55
56 def test_get_ipython_dir_2():
56 def test_get_ipython_dir_2():
57 """test_get_ipython_dir_2, Testcase to see if we can call get_ipython_dir without Exceptions."""
57 """test_get_ipython_dir_2, Testcase to see if we can call get_ipython_dir without Exceptions."""
58 with patch_get_home_dir('someplace'), \
58 with patch_get_home_dir('someplace'), \
59 patch.object(paths, 'get_xdg_dir', return_value=None), \
59 patch.object(paths, 'get_xdg_dir', return_value=None), \
60 patch.object(paths, '_writable_dir', return_value=True), \
60 patch.object(paths, '_writable_dir', return_value=True), \
61 patch('os.name', "posix"), \
61 patch('os.name', "posix"), \
62 modified_env({'IPYTHON_DIR': None,
62 modified_env({'IPYTHON_DIR': None,
63 'IPYTHONDIR': None,
63 'IPYTHONDIR': None,
64 'XDG_CONFIG_HOME': None
64 'XDG_CONFIG_HOME': None
65 }):
65 }):
66 ipdir = paths.get_ipython_dir()
66 ipdir = paths.get_ipython_dir()
67
67
68 assert ipdir == os.path.join("someplace", ".ipython")
68 assert ipdir == os.path.join("someplace", ".ipython")
69
69
70 def test_get_ipython_dir_3():
70 def test_get_ipython_dir_3():
71 """test_get_ipython_dir_3, use XDG if defined and exists, and .ipython doesn't exist."""
71 """test_get_ipython_dir_3, use XDG if defined and exists, and .ipython doesn't exist."""
72 tmphome = TemporaryDirectory()
72 tmphome = TemporaryDirectory()
73 try:
73 try:
74 with patch_get_home_dir(tmphome.name), \
74 with patch_get_home_dir(tmphome.name), \
75 patch('os.name', 'posix'), \
75 patch('os.name', 'posix'), \
76 modified_env({
76 modified_env({
77 'IPYTHON_DIR': None,
77 'IPYTHON_DIR': None,
78 'IPYTHONDIR': None,
78 'IPYTHONDIR': None,
79 'XDG_CONFIG_HOME': XDG_TEST_DIR,
79 'XDG_CONFIG_HOME': XDG_TEST_DIR,
80 }), warnings.catch_warnings(record=True) as w:
80 }), warnings.catch_warnings(record=True) as w:
81 ipdir = paths.get_ipython_dir()
81 ipdir = paths.get_ipython_dir()
82
82
83 assert ipdir == os.path.join(tmphome.name, XDG_TEST_DIR, "ipython")
83 assert ipdir == os.path.join(tmphome.name, XDG_TEST_DIR, "ipython")
84 assert len(w) == 0
84 assert len(w) == 0
85 finally:
85 finally:
86 tmphome.cleanup()
86 tmphome.cleanup()
87
87
88 def test_get_ipython_dir_4():
88 def test_get_ipython_dir_4():
89 """test_get_ipython_dir_4, warn if XDG and home both exist."""
89 """test_get_ipython_dir_4, warn if XDG and home both exist."""
90 with patch_get_home_dir(HOME_TEST_DIR), \
90 with patch_get_home_dir(HOME_TEST_DIR), \
91 patch('os.name', 'posix'):
91 patch('os.name', 'posix'):
92 try:
92 try:
93 os.mkdir(os.path.join(XDG_TEST_DIR, 'ipython'))
93 os.mkdir(os.path.join(XDG_TEST_DIR, 'ipython'))
94 except OSError as e:
94 except OSError as e:
95 if e.errno != errno.EEXIST:
95 if e.errno != errno.EEXIST:
96 raise
96 raise
97
97
98
98
99 with modified_env({
99 with modified_env({
100 'IPYTHON_DIR': None,
100 'IPYTHON_DIR': None,
101 'IPYTHONDIR': None,
101 'IPYTHONDIR': None,
102 'XDG_CONFIG_HOME': XDG_TEST_DIR,
102 'XDG_CONFIG_HOME': XDG_TEST_DIR,
103 }), warnings.catch_warnings(record=True) as w:
103 }), warnings.catch_warnings(record=True) as w:
104 ipdir = paths.get_ipython_dir()
104 ipdir = paths.get_ipython_dir()
105
105
106 assert len(w) == 1
106 assert len(w) == 1
107 assert "Ignoring" in str(w[0])
107 assert "Ignoring" in str(w[0])
108
108
109
109
110 def test_get_ipython_dir_5():
110 def test_get_ipython_dir_5():
111 """test_get_ipython_dir_5, use .ipython if exists and XDG defined, but doesn't exist."""
111 """test_get_ipython_dir_5, use .ipython if exists and XDG defined, but doesn't exist."""
112 with patch_get_home_dir(HOME_TEST_DIR), \
112 with patch_get_home_dir(HOME_TEST_DIR), \
113 patch('os.name', 'posix'):
113 patch('os.name', 'posix'):
114 try:
114 try:
115 os.rmdir(os.path.join(XDG_TEST_DIR, 'ipython'))
115 os.rmdir(os.path.join(XDG_TEST_DIR, 'ipython'))
116 except OSError as e:
116 except OSError as e:
117 if e.errno != errno.ENOENT:
117 if e.errno != errno.ENOENT:
118 raise
118 raise
119
119
120 with modified_env({
120 with modified_env({
121 'IPYTHON_DIR': None,
121 'IPYTHON_DIR': None,
122 'IPYTHONDIR': None,
122 'IPYTHONDIR': None,
123 'XDG_CONFIG_HOME': XDG_TEST_DIR,
123 'XDG_CONFIG_HOME': XDG_TEST_DIR,
124 }):
124 }):
125 ipdir = paths.get_ipython_dir()
125 ipdir = paths.get_ipython_dir()
126
126
127 assert ipdir == IP_TEST_DIR
127 assert ipdir == IP_TEST_DIR
128
128
129 def test_get_ipython_dir_6():
129 def test_get_ipython_dir_6():
130 """test_get_ipython_dir_6, use home over XDG if defined and neither exist."""
130 """test_get_ipython_dir_6, use home over XDG if defined and neither exist."""
131 xdg = os.path.join(HOME_TEST_DIR, 'somexdg')
131 xdg = os.path.join(HOME_TEST_DIR, 'somexdg')
132 os.mkdir(xdg)
132 os.mkdir(xdg)
133 shutil.rmtree(os.path.join(HOME_TEST_DIR, '.ipython'))
133 shutil.rmtree(os.path.join(HOME_TEST_DIR, '.ipython'))
134 print(paths._writable_dir)
134 print(paths._writable_dir)
135 with patch_get_home_dir(HOME_TEST_DIR), \
135 with patch_get_home_dir(HOME_TEST_DIR), \
136 patch.object(paths, 'get_xdg_dir', return_value=xdg), \
136 patch.object(paths, 'get_xdg_dir', return_value=xdg), \
137 patch('os.name', 'posix'), \
137 patch('os.name', 'posix'), \
138 modified_env({
138 modified_env({
139 'IPYTHON_DIR': None,
139 'IPYTHON_DIR': None,
140 'IPYTHONDIR': None,
140 'IPYTHONDIR': None,
141 'XDG_CONFIG_HOME': None,
141 'XDG_CONFIG_HOME': None,
142 }), warnings.catch_warnings(record=True) as w:
142 }), warnings.catch_warnings(record=True) as w:
143 ipdir = paths.get_ipython_dir()
143 ipdir = paths.get_ipython_dir()
144
144
145 assert ipdir == os.path.join(HOME_TEST_DIR, ".ipython")
145 assert ipdir == os.path.join(HOME_TEST_DIR, ".ipython")
146 assert len(w) == 0
146 assert len(w) == 0
147
147
148 def test_get_ipython_dir_7():
148 def test_get_ipython_dir_7():
149 """test_get_ipython_dir_7, test home directory expansion on IPYTHONDIR"""
149 """test_get_ipython_dir_7, test home directory expansion on IPYTHONDIR"""
150 home_dir = os.path.normpath(os.path.expanduser('~'))
150 home_dir = os.path.normpath(os.path.expanduser('~'))
151 with modified_env({'IPYTHONDIR': os.path.join('~', 'somewhere')}), \
151 with modified_env({'IPYTHONDIR': os.path.join('~', 'somewhere')}), \
152 patch.object(paths, '_writable_dir', return_value=True):
152 patch.object(paths, '_writable_dir', return_value=True):
153 ipdir = paths.get_ipython_dir()
153 ipdir = paths.get_ipython_dir()
154 assert ipdir == os.path.join(home_dir, "somewhere")
154 assert ipdir == os.path.join(home_dir, "somewhere")
155
155
156
156
157 @skip_win32
157 @skip_win32
158 def test_get_ipython_dir_8():
158 def test_get_ipython_dir_8():
159 """test_get_ipython_dir_8, test / home directory"""
159 """test_get_ipython_dir_8, test / home directory"""
160 if not os.access("/", os.W_OK):
160 if not os.access("/", os.W_OK):
161 # test only when HOME directory actually writable
161 # test only when HOME directory actually writable
162 return
162 return
163
163
164 with patch.object(paths, "_writable_dir", lambda path: bool(path)), patch.object(
164 with patch.object(paths, "_writable_dir", lambda path: bool(path)), patch.object(
165 paths, "get_xdg_dir", return_value=None
165 paths, "get_xdg_dir", return_value=None
166 ), modified_env(
166 ), modified_env(
167 {
167 {
168 "IPYTHON_DIR": None,
168 "IPYTHON_DIR": None,
169 "IPYTHONDIR": None,
169 "IPYTHONDIR": None,
170 "HOME": "/",
170 "HOME": "/",
171 }
171 }
172 ):
172 ):
173 assert paths.get_ipython_dir() == "/.ipython"
173 assert paths.get_ipython_dir() == "/.ipython"
174
174
175
175
176 def test_get_ipython_cache_dir():
176 def test_get_ipython_cache_dir():
177 with modified_env({'HOME': HOME_TEST_DIR}):
177 with modified_env({'HOME': HOME_TEST_DIR}):
178 if os.name == "posix":
178 if os.name == "posix":
179 # test default
179 # test default
180 os.makedirs(os.path.join(HOME_TEST_DIR, ".cache"))
180 os.makedirs(os.path.join(HOME_TEST_DIR, ".cache"))
181 with modified_env({'XDG_CACHE_HOME': None}):
181 with modified_env({'XDG_CACHE_HOME': None}):
182 ipdir = paths.get_ipython_cache_dir()
182 ipdir = paths.get_ipython_cache_dir()
183 assert os.path.join(HOME_TEST_DIR, ".cache", "ipython") == ipdir
183 assert os.path.join(HOME_TEST_DIR, ".cache", "ipython") == ipdir
184 assert_isdir(ipdir)
184 assert_isdir(ipdir)
185
185
186 # test env override
186 # test env override
187 with modified_env({"XDG_CACHE_HOME": XDG_CACHE_DIR}):
187 with modified_env({"XDG_CACHE_HOME": XDG_CACHE_DIR}):
188 ipdir = paths.get_ipython_cache_dir()
188 ipdir = paths.get_ipython_cache_dir()
189 assert_isdir(ipdir)
189 assert_isdir(ipdir)
190 assert ipdir == os.path.join(XDG_CACHE_DIR, "ipython")
190 assert ipdir == os.path.join(XDG_CACHE_DIR, "ipython")
191 else:
191 else:
192 assert paths.get_ipython_cache_dir() == paths.get_ipython_dir()
192 assert paths.get_ipython_cache_dir() == paths.get_ipython_dir()
193
193
194 def test_get_ipython_package_dir():
194 def test_get_ipython_package_dir():
195 ipdir = paths.get_ipython_package_dir()
195 ipdir = paths.get_ipython_package_dir()
196 assert_isdir(ipdir)
196 assert_isdir(ipdir)
197
197
198
198
199 def test_get_ipython_module_path():
199 def test_get_ipython_module_path():
200 ipapp_path = paths.get_ipython_module_path('IPython.terminal.ipapp')
200 ipapp_path = paths.get_ipython_module_path('IPython.terminal.ipapp')
201 assert_isfile(ipapp_path)
201 assert_isfile(ipapp_path)
@@ -1,156 +1,155 b''
1 # coding: utf-8
1 # coding: utf-8
2 """Tests for profile-related functions.
2 """Tests for profile-related functions.
3
3
4 Currently only the startup-dir functionality is tested, but more tests should
4 Currently only the startup-dir functionality is tested, but more tests should
5 be added for:
5 be added for:
6
6
7 * ipython profile create
7 * ipython profile create
8 * ipython profile list
8 * ipython profile list
9 * ipython profile create --parallel
9 * ipython profile create --parallel
10 * security dir permissions
10 * security dir permissions
11
11
12 Authors
12 Authors
13 -------
13 -------
14
14
15 * MinRK
15 * MinRK
16
16
17 """
17 """
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 import shutil
23 import shutil
24 import sys
24 import sys
25 import tempfile
25 import tempfile
26
27 from pathlib import Path
26 from pathlib import Path
28 from unittest import TestCase
27 from unittest import TestCase
29
28
30 from IPython.core.profileapp import list_profiles_in, list_bundled_profiles
29 from tempfile import TemporaryDirectory
31 from IPython.core.profiledir import ProfileDir
32
30
31 from IPython.core.profileapp import list_bundled_profiles, list_profiles_in
32 from IPython.core.profiledir import ProfileDir
33 from IPython.testing import decorators as dec
33 from IPython.testing import decorators as dec
34 from IPython.testing import tools as tt
34 from IPython.testing import tools as tt
35 from IPython.utils.process import getoutput
35 from IPython.utils.process import getoutput
36 from IPython.utils.tempdir import TemporaryDirectory
37
36
38 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
39 # Globals
38 # Globals
40 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
41 TMP_TEST_DIR = Path(tempfile.mkdtemp())
40 TMP_TEST_DIR = Path(tempfile.mkdtemp())
42 HOME_TEST_DIR = TMP_TEST_DIR / "home_test_dir"
41 HOME_TEST_DIR = TMP_TEST_DIR / "home_test_dir"
43 IP_TEST_DIR = HOME_TEST_DIR / ".ipython"
42 IP_TEST_DIR = HOME_TEST_DIR / ".ipython"
44
43
45 #
44 #
46 # Setup/teardown functions/decorators
45 # Setup/teardown functions/decorators
47 #
46 #
48
47
49 def setup_module():
48 def setup_module():
50 """Setup test environment for the module:
49 """Setup test environment for the module:
51
50
52 - Adds dummy home dir tree
51 - Adds dummy home dir tree
53 """
52 """
54 # Do not mask exceptions here. In particular, catching WindowsError is a
53 # Do not mask exceptions here. In particular, catching WindowsError is a
55 # problem because that exception is only defined on Windows...
54 # problem because that exception is only defined on Windows...
56 (Path.cwd() / IP_TEST_DIR).mkdir(parents=True)
55 (Path.cwd() / IP_TEST_DIR).mkdir(parents=True)
57
56
58
57
59 def teardown_module():
58 def teardown_module():
60 """Teardown test environment for the module:
59 """Teardown test environment for the module:
61
60
62 - Remove dummy home dir tree
61 - Remove dummy home dir tree
63 """
62 """
64 # Note: we remove the parent test dir, which is the root of all test
63 # Note: we remove the parent test dir, which is the root of all test
65 # subdirs we may have created. Use shutil instead of os.removedirs, so
64 # subdirs we may have created. Use shutil instead of os.removedirs, so
66 # that non-empty directories are all recursively removed.
65 # that non-empty directories are all recursively removed.
67 shutil.rmtree(TMP_TEST_DIR)
66 shutil.rmtree(TMP_TEST_DIR)
68
67
69
68
70 #-----------------------------------------------------------------------------
69 #-----------------------------------------------------------------------------
71 # Test functions
70 # Test functions
72 #-----------------------------------------------------------------------------
71 #-----------------------------------------------------------------------------
73 class ProfileStartupTest(TestCase):
72 class ProfileStartupTest(TestCase):
74 def setUp(self):
73 def setUp(self):
75 # create profile dir
74 # create profile dir
76 self.pd = ProfileDir.create_profile_dir_by_name(IP_TEST_DIR, "test")
75 self.pd = ProfileDir.create_profile_dir_by_name(IP_TEST_DIR, "test")
77 self.options = ["--ipython-dir", IP_TEST_DIR, "--profile", "test"]
76 self.options = ["--ipython-dir", IP_TEST_DIR, "--profile", "test"]
78 self.fname = TMP_TEST_DIR / "test.py"
77 self.fname = TMP_TEST_DIR / "test.py"
79
78
80 def tearDown(self):
79 def tearDown(self):
81 # We must remove this profile right away so its presence doesn't
80 # We must remove this profile right away so its presence doesn't
82 # confuse other tests.
81 # confuse other tests.
83 shutil.rmtree(self.pd.location)
82 shutil.rmtree(self.pd.location)
84
83
85 def init(self, startup_file, startup, test):
84 def init(self, startup_file, startup, test):
86 # write startup python file
85 # write startup python file
87 with open(Path(self.pd.startup_dir) / startup_file, "w", encoding="utf-8") as f:
86 with open(Path(self.pd.startup_dir) / startup_file, "w", encoding="utf-8") as f:
88 f.write(startup)
87 f.write(startup)
89 # write simple test file, to check that the startup file was run
88 # write simple test file, to check that the startup file was run
90 with open(self.fname, "w", encoding="utf-8") as f:
89 with open(self.fname, "w", encoding="utf-8") as f:
91 f.write(test)
90 f.write(test)
92
91
93 def validate(self, output):
92 def validate(self, output):
94 tt.ipexec_validate(self.fname, output, "", options=self.options)
93 tt.ipexec_validate(self.fname, output, "", options=self.options)
95
94
96 def test_startup_py(self):
95 def test_startup_py(self):
97 self.init('00-start.py', 'zzz=123\n', 'print(zzz)\n')
96 self.init('00-start.py', 'zzz=123\n', 'print(zzz)\n')
98 self.validate('123')
97 self.validate('123')
99
98
100 def test_startup_ipy(self):
99 def test_startup_ipy(self):
101 self.init('00-start.ipy', '%xmode plain\n', '')
100 self.init('00-start.ipy', '%xmode plain\n', '')
102 self.validate('Exception reporting mode: Plain')
101 self.validate('Exception reporting mode: Plain')
103
102
104
103
105 def test_list_profiles_in():
104 def test_list_profiles_in():
106 # No need to remove these directories and files, as they will get nuked in
105 # No need to remove these directories and files, as they will get nuked in
107 # the module-level teardown.
106 # the module-level teardown.
108 td = Path(tempfile.mkdtemp(dir=TMP_TEST_DIR))
107 td = Path(tempfile.mkdtemp(dir=TMP_TEST_DIR))
109 for name in ("profile_foo", "profile_hello", "not_a_profile"):
108 for name in ("profile_foo", "profile_hello", "not_a_profile"):
110 Path(td / name).mkdir(parents=True)
109 Path(td / name).mkdir(parents=True)
111 if dec.unicode_paths:
110 if dec.unicode_paths:
112 Path(td / u"profile_ΓΌnicode").mkdir(parents=True)
111 Path(td / u"profile_ΓΌnicode").mkdir(parents=True)
113
112
114 with open(td / "profile_file", "w", encoding="utf-8") as f:
113 with open(td / "profile_file", "w", encoding="utf-8") as f:
115 f.write("I am not a profile directory")
114 f.write("I am not a profile directory")
116 profiles = list_profiles_in(td)
115 profiles = list_profiles_in(td)
117
116
118 # unicode normalization can turn u'ΓΌnicode' into u'u\0308nicode',
117 # unicode normalization can turn u'ΓΌnicode' into u'u\0308nicode',
119 # so only check for *nicode, and that creating a ProfileDir from the
118 # so only check for *nicode, and that creating a ProfileDir from the
120 # name remains valid
119 # name remains valid
121 found_unicode = False
120 found_unicode = False
122 for p in list(profiles):
121 for p in list(profiles):
123 if p.endswith('nicode'):
122 if p.endswith('nicode'):
124 pd = ProfileDir.find_profile_dir_by_name(td, p)
123 pd = ProfileDir.find_profile_dir_by_name(td, p)
125 profiles.remove(p)
124 profiles.remove(p)
126 found_unicode = True
125 found_unicode = True
127 break
126 break
128 if dec.unicode_paths:
127 if dec.unicode_paths:
129 assert found_unicode is True
128 assert found_unicode is True
130 assert set(profiles) == {"foo", "hello"}
129 assert set(profiles) == {"foo", "hello"}
131
130
132
131
133 def test_list_bundled_profiles():
132 def test_list_bundled_profiles():
134 # This variable will need to be updated when a new profile gets bundled
133 # This variable will need to be updated when a new profile gets bundled
135 bundled = sorted(list_bundled_profiles())
134 bundled = sorted(list_bundled_profiles())
136 assert bundled == []
135 assert bundled == []
137
136
138
137
139 def test_profile_create_ipython_dir():
138 def test_profile_create_ipython_dir():
140 """ipython profile create respects --ipython-dir"""
139 """ipython profile create respects --ipython-dir"""
141 with TemporaryDirectory() as td:
140 with TemporaryDirectory() as td:
142 getoutput(
141 getoutput(
143 [
142 [
144 sys.executable,
143 sys.executable,
145 "-m",
144 "-m",
146 "IPython",
145 "IPython",
147 "profile",
146 "profile",
148 "create",
147 "create",
149 "foo",
148 "foo",
150 "--ipython-dir=%s" % td,
149 "--ipython-dir=%s" % td,
151 ]
150 ]
152 )
151 )
153 profile_dir = Path(td) / "profile_foo"
152 profile_dir = Path(td) / "profile_foo"
154 assert Path(profile_dir).exists()
153 assert Path(profile_dir).exists()
155 ipython_config = profile_dir / "ipython_config.py"
154 ipython_config = profile_dir / "ipython_config.py"
156 assert Path(ipython_config).exists()
155 assert Path(ipython_config).exists()
@@ -1,620 +1,622 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for code execution (%run and related), which is particularly tricky.
2 """Tests for code execution (%run and related), which is particularly tricky.
3
3
4 Because of how %run manages namespaces, and the fact that we are trying here to
4 Because of how %run manages namespaces, and the fact that we are trying here to
5 verify subtle object deletion and reference counting issues, the %run tests
5 verify subtle object deletion and reference counting issues, the %run tests
6 will be kept in this separate file. This makes it easier to aggregate in one
6 will be kept in this separate file. This makes it easier to aggregate in one
7 place the tricks needed to handle it; most other magics are much easier to test
7 place the tricks needed to handle it; most other magics are much easier to test
8 and we do so in a common test_magic file.
8 and we do so in a common test_magic file.
9
9
10 Note that any test using `run -i` should make sure to do a `reset` afterwards,
10 Note that any test using `run -i` should make sure to do a `reset` afterwards,
11 as otherwise it may influence later tests.
11 as otherwise it may influence later tests.
12 """
12 """
13
13
14 # Copyright (c) IPython Development Team.
14 # Copyright (c) IPython Development Team.
15 # Distributed under the terms of the Modified BSD License.
15 # Distributed under the terms of the Modified BSD License.
16
16
17
17
18
18
19 import functools
19 import functools
20 import os
20 import os
21 import platform
21 import platform
22 from os.path import join as pjoin
23 import random
22 import random
24 import string
23 import string
25 import sys
24 import sys
26 import textwrap
25 import textwrap
27 import unittest
26 import unittest
27 from os.path import join as pjoin
28 from unittest.mock import patch
28 from unittest.mock import patch
29
29
30 import pytest
30 import pytest
31 from tempfile import TemporaryDirectory
31
32
33 from IPython.core import debugger
32 from IPython.testing import decorators as dec
34 from IPython.testing import decorators as dec
33 from IPython.testing import tools as tt
35 from IPython.testing import tools as tt
34 from IPython.utils.io import capture_output
36 from IPython.utils.io import capture_output
35 from IPython.utils.tempdir import TemporaryDirectory
37
36 from IPython.core import debugger
37
38
38 def doctest_refbug():
39 def doctest_refbug():
39 """Very nasty problem with references held by multiple runs of a script.
40 """Very nasty problem with references held by multiple runs of a script.
40 See: https://github.com/ipython/ipython/issues/141
41 See: https://github.com/ipython/ipython/issues/141
41
42
42 In [1]: _ip.clear_main_mod_cache()
43 In [1]: _ip.clear_main_mod_cache()
43 # random
44 # random
44
45
45 In [2]: %run refbug
46 In [2]: %run refbug
46
47
47 In [3]: call_f()
48 In [3]: call_f()
48 lowercased: hello
49 lowercased: hello
49
50
50 In [4]: %run refbug
51 In [4]: %run refbug
51
52
52 In [5]: call_f()
53 In [5]: call_f()
53 lowercased: hello
54 lowercased: hello
54 lowercased: hello
55 lowercased: hello
55 """
56 """
56
57
57
58
58 def doctest_run_builtins():
59 def doctest_run_builtins():
59 r"""Check that %run doesn't damage __builtins__.
60 r"""Check that %run doesn't damage __builtins__.
60
61
61 In [1]: import tempfile
62 In [1]: import tempfile
62
63
63 In [2]: bid1 = id(__builtins__)
64 In [2]: bid1 = id(__builtins__)
64
65
65 In [3]: fname = tempfile.mkstemp('.py')[1]
66 In [3]: fname = tempfile.mkstemp('.py')[1]
66
67
67 In [3]: f = open(fname, 'w', encoding='utf-8')
68 In [3]: f = open(fname, 'w', encoding='utf-8')
68
69
69 In [4]: dummy= f.write('pass\n')
70 In [4]: dummy= f.write('pass\n')
70
71
71 In [5]: f.flush()
72 In [5]: f.flush()
72
73
73 In [6]: t1 = type(__builtins__)
74 In [6]: t1 = type(__builtins__)
74
75
75 In [7]: %run $fname
76 In [7]: %run $fname
76
77
77 In [7]: f.close()
78 In [7]: f.close()
78
79
79 In [8]: bid2 = id(__builtins__)
80 In [8]: bid2 = id(__builtins__)
80
81
81 In [9]: t2 = type(__builtins__)
82 In [9]: t2 = type(__builtins__)
82
83
83 In [10]: t1 == t2
84 In [10]: t1 == t2
84 Out[10]: True
85 Out[10]: True
85
86
86 In [10]: bid1 == bid2
87 In [10]: bid1 == bid2
87 Out[10]: True
88 Out[10]: True
88
89
89 In [12]: try:
90 In [12]: try:
90 ....: os.unlink(fname)
91 ....: os.unlink(fname)
91 ....: except:
92 ....: except:
92 ....: pass
93 ....: pass
93 ....:
94 ....:
94 """
95 """
95
96
96
97
97 def doctest_run_option_parser():
98 def doctest_run_option_parser():
98 r"""Test option parser in %run.
99 r"""Test option parser in %run.
99
100
100 In [1]: %run print_argv.py
101 In [1]: %run print_argv.py
101 []
102 []
102
103
103 In [2]: %run print_argv.py print*.py
104 In [2]: %run print_argv.py print*.py
104 ['print_argv.py']
105 ['print_argv.py']
105
106
106 In [3]: %run -G print_argv.py print*.py
107 In [3]: %run -G print_argv.py print*.py
107 ['print*.py']
108 ['print*.py']
108
109
109 """
110 """
110
111
111
112
112 @dec.skip_win32
113 @dec.skip_win32
113 def doctest_run_option_parser_for_posix():
114 def doctest_run_option_parser_for_posix():
114 r"""Test option parser in %run (Linux/OSX specific).
115 r"""Test option parser in %run (Linux/OSX specific).
115
116
116 You need double quote to escape glob in POSIX systems:
117 You need double quote to escape glob in POSIX systems:
117
118
118 In [1]: %run print_argv.py print\\*.py
119 In [1]: %run print_argv.py print\\*.py
119 ['print*.py']
120 ['print*.py']
120
121
121 You can't use quote to escape glob in POSIX systems:
122 You can't use quote to escape glob in POSIX systems:
122
123
123 In [2]: %run print_argv.py 'print*.py'
124 In [2]: %run print_argv.py 'print*.py'
124 ['print_argv.py']
125 ['print_argv.py']
125
126
126 """
127 """
127
128
128
129
129 doctest_run_option_parser_for_posix.__skip_doctest__ = sys.platform == "win32"
130 doctest_run_option_parser_for_posix.__skip_doctest__ = sys.platform == "win32"
130
131
131
132
132 @dec.skip_if_not_win32
133 @dec.skip_if_not_win32
133 def doctest_run_option_parser_for_windows():
134 def doctest_run_option_parser_for_windows():
134 r"""Test option parser in %run (Windows specific).
135 r"""Test option parser in %run (Windows specific).
135
136
136 In Windows, you can't escape ``*` `by backslash:
137 In Windows, you can't escape ``*` `by backslash:
137
138
138 In [1]: %run print_argv.py print\\*.py
139 In [1]: %run print_argv.py print\\*.py
139 ['print\\\\*.py']
140 ['print\\\\*.py']
140
141
141 You can use quote to escape glob:
142 You can use quote to escape glob:
142
143
143 In [2]: %run print_argv.py 'print*.py'
144 In [2]: %run print_argv.py 'print*.py'
144 ["'print*.py'"]
145 ["'print*.py'"]
145
146
146 """
147 """
147
148
148
149
149 doctest_run_option_parser_for_windows.__skip_doctest__ = sys.platform != "win32"
150 doctest_run_option_parser_for_windows.__skip_doctest__ = sys.platform != "win32"
150
151
151
152
152 def doctest_reset_del():
153 def doctest_reset_del():
153 """Test that resetting doesn't cause errors in __del__ methods.
154 """Test that resetting doesn't cause errors in __del__ methods.
154
155
155 In [2]: class A(object):
156 In [2]: class A(object):
156 ...: def __del__(self):
157 ...: def __del__(self):
157 ...: print(str("Hi"))
158 ...: print(str("Hi"))
158 ...:
159 ...:
159
160
160 In [3]: a = A()
161 In [3]: a = A()
161
162
162 In [4]: get_ipython().reset(); import gc; x = gc.collect(0)
163 In [4]: get_ipython().reset(); import gc; x = gc.collect(0)
163 Hi
164 Hi
164
165
165 In [5]: 1+1
166 In [5]: 1+1
166 Out[5]: 2
167 Out[5]: 2
167 """
168 """
168
169
169 # For some tests, it will be handy to organize them in a class with a common
170 # For some tests, it will be handy to organize them in a class with a common
170 # setup that makes a temp file
171 # setup that makes a temp file
171
172
172 class TestMagicRunPass(tt.TempFileMixin):
173 class TestMagicRunPass(tt.TempFileMixin):
173
174
174 def setUp(self):
175 def setUp(self):
175 content = "a = [1,2,3]\nb = 1"
176 content = "a = [1,2,3]\nb = 1"
176 self.mktmp(content)
177 self.mktmp(content)
177
178
178 def run_tmpfile(self):
179 def run_tmpfile(self):
179 _ip = get_ipython()
180 _ip = get_ipython()
180 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
181 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
181 # See below and ticket https://bugs.launchpad.net/bugs/366353
182 # See below and ticket https://bugs.launchpad.net/bugs/366353
182 _ip.magic('run %s' % self.fname)
183 _ip.magic('run %s' % self.fname)
183
184
184 def run_tmpfile_p(self):
185 def run_tmpfile_p(self):
185 _ip = get_ipython()
186 _ip = get_ipython()
186 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
187 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
187 # See below and ticket https://bugs.launchpad.net/bugs/366353
188 # See below and ticket https://bugs.launchpad.net/bugs/366353
188 _ip.magic('run -p %s' % self.fname)
189 _ip.magic('run -p %s' % self.fname)
189
190
190 def test_builtins_id(self):
191 def test_builtins_id(self):
191 """Check that %run doesn't damage __builtins__ """
192 """Check that %run doesn't damage __builtins__ """
192 _ip = get_ipython()
193 _ip = get_ipython()
193 # Test that the id of __builtins__ is not modified by %run
194 # Test that the id of __builtins__ is not modified by %run
194 bid1 = id(_ip.user_ns['__builtins__'])
195 bid1 = id(_ip.user_ns['__builtins__'])
195 self.run_tmpfile()
196 self.run_tmpfile()
196 bid2 = id(_ip.user_ns['__builtins__'])
197 bid2 = id(_ip.user_ns['__builtins__'])
197 assert bid1 == bid2
198 assert bid1 == bid2
198
199
199 def test_builtins_type(self):
200 def test_builtins_type(self):
200 """Check that the type of __builtins__ doesn't change with %run.
201 """Check that the type of __builtins__ doesn't change with %run.
201
202
202 However, the above could pass if __builtins__ was already modified to
203 However, the above could pass if __builtins__ was already modified to
203 be a dict (it should be a module) by a previous use of %run. So we
204 be a dict (it should be a module) by a previous use of %run. So we
204 also check explicitly that it really is a module:
205 also check explicitly that it really is a module:
205 """
206 """
206 _ip = get_ipython()
207 _ip = get_ipython()
207 self.run_tmpfile()
208 self.run_tmpfile()
208 assert type(_ip.user_ns["__builtins__"]) == type(sys)
209 assert type(_ip.user_ns["__builtins__"]) == type(sys)
209
210
210 def test_run_profile(self):
211 def test_run_profile(self):
211 """Test that the option -p, which invokes the profiler, do not
212 """Test that the option -p, which invokes the profiler, do not
212 crash by invoking execfile"""
213 crash by invoking execfile"""
213 self.run_tmpfile_p()
214 self.run_tmpfile_p()
214
215
215 def test_run_debug_twice(self):
216 def test_run_debug_twice(self):
216 # https://github.com/ipython/ipython/issues/10028
217 # https://github.com/ipython/ipython/issues/10028
217 _ip = get_ipython()
218 _ip = get_ipython()
218 with tt.fake_input(['c']):
219 with tt.fake_input(['c']):
219 _ip.magic('run -d %s' % self.fname)
220 _ip.magic('run -d %s' % self.fname)
220 with tt.fake_input(['c']):
221 with tt.fake_input(['c']):
221 _ip.magic('run -d %s' % self.fname)
222 _ip.magic('run -d %s' % self.fname)
222
223
223 def test_run_debug_twice_with_breakpoint(self):
224 def test_run_debug_twice_with_breakpoint(self):
224 """Make a valid python temp file."""
225 """Make a valid python temp file."""
225 _ip = get_ipython()
226 _ip = get_ipython()
226 with tt.fake_input(['b 2', 'c', 'c']):
227 with tt.fake_input(['b 2', 'c', 'c']):
227 _ip.magic('run -d %s' % self.fname)
228 _ip.magic('run -d %s' % self.fname)
228
229
229 with tt.fake_input(['c']):
230 with tt.fake_input(['c']):
230 with tt.AssertNotPrints('KeyError'):
231 with tt.AssertNotPrints('KeyError'):
231 _ip.magic('run -d %s' % self.fname)
232 _ip.magic('run -d %s' % self.fname)
232
233
233
234
234 class TestMagicRunSimple(tt.TempFileMixin):
235 class TestMagicRunSimple(tt.TempFileMixin):
235
236
236 def test_simpledef(self):
237 def test_simpledef(self):
237 """Test that simple class definitions work."""
238 """Test that simple class definitions work."""
238 src = ("class foo: pass\n"
239 src = ("class foo: pass\n"
239 "def f(): return foo()")
240 "def f(): return foo()")
240 self.mktmp(src)
241 self.mktmp(src)
241 _ip.magic("run %s" % self.fname)
242 _ip.magic("run %s" % self.fname)
242 _ip.run_cell("t = isinstance(f(), foo)")
243 _ip.run_cell("t = isinstance(f(), foo)")
243 assert _ip.user_ns["t"] is True
244 assert _ip.user_ns["t"] is True
244
245
245 @pytest.mark.xfail(
246 @pytest.mark.xfail(
246 platform.python_implementation() == "PyPy",
247 platform.python_implementation() == "PyPy",
247 reason="expecting __del__ call on exit is unreliable and doesn't happen on PyPy",
248 reason="expecting __del__ call on exit is unreliable and doesn't happen on PyPy",
248 )
249 )
249 def test_obj_del(self):
250 def test_obj_del(self):
250 """Test that object's __del__ methods are called on exit."""
251 """Test that object's __del__ methods are called on exit."""
251 src = ("class A(object):\n"
252 src = ("class A(object):\n"
252 " def __del__(self):\n"
253 " def __del__(self):\n"
253 " print('object A deleted')\n"
254 " print('object A deleted')\n"
254 "a = A()\n")
255 "a = A()\n")
255 self.mktmp(src)
256 self.mktmp(src)
256 err = None
257 err = None
257 tt.ipexec_validate(self.fname, 'object A deleted', err)
258 tt.ipexec_validate(self.fname, 'object A deleted', err)
258
259
259 def test_aggressive_namespace_cleanup(self):
260 def test_aggressive_namespace_cleanup(self):
260 """Test that namespace cleanup is not too aggressive GH-238
261 """Test that namespace cleanup is not too aggressive GH-238
261
262
262 Returning from another run magic deletes the namespace"""
263 Returning from another run magic deletes the namespace"""
263 # see ticket https://github.com/ipython/ipython/issues/238
264 # see ticket https://github.com/ipython/ipython/issues/238
264
265
265 with tt.TempFileMixin() as empty:
266 with tt.TempFileMixin() as empty:
266 empty.mktmp("")
267 empty.mktmp("")
267 # On Windows, the filename will have \users in it, so we need to use the
268 # On Windows, the filename will have \users in it, so we need to use the
268 # repr so that the \u becomes \\u.
269 # repr so that the \u becomes \\u.
269 src = (
270 src = (
270 "ip = get_ipython()\n"
271 "ip = get_ipython()\n"
271 "for i in range(5):\n"
272 "for i in range(5):\n"
272 " try:\n"
273 " try:\n"
273 " ip.magic(%r)\n"
274 " ip.magic(%r)\n"
274 " except NameError as e:\n"
275 " except NameError as e:\n"
275 " print(i)\n"
276 " print(i)\n"
276 " break\n" % ("run " + empty.fname)
277 " break\n" % ("run " + empty.fname)
277 )
278 )
278 self.mktmp(src)
279 self.mktmp(src)
279 _ip.magic("run %s" % self.fname)
280 _ip.magic("run %s" % self.fname)
280 _ip.run_cell("ip == get_ipython()")
281 _ip.run_cell("ip == get_ipython()")
281 assert _ip.user_ns["i"] == 4
282 assert _ip.user_ns["i"] == 4
282
283
283 def test_run_second(self):
284 def test_run_second(self):
284 """Test that running a second file doesn't clobber the first, gh-3547"""
285 """Test that running a second file doesn't clobber the first, gh-3547"""
285 self.mktmp("avar = 1\n" "def afunc():\n" " return avar\n")
286 self.mktmp("avar = 1\n" "def afunc():\n" " return avar\n")
286
287
287 with tt.TempFileMixin() as empty:
288 with tt.TempFileMixin() as empty:
288 empty.mktmp("")
289 empty.mktmp("")
289
290
290 _ip.magic("run %s" % self.fname)
291 _ip.magic("run %s" % self.fname)
291 _ip.magic("run %s" % empty.fname)
292 _ip.magic("run %s" % empty.fname)
292 assert _ip.user_ns["afunc"]() == 1
293 assert _ip.user_ns["afunc"]() == 1
293
294
294 def test_tclass(self):
295 def test_tclass(self):
295 mydir = os.path.dirname(__file__)
296 mydir = os.path.dirname(__file__)
296 tc = os.path.join(mydir, "tclass")
297 tc = os.path.join(mydir, "tclass")
297 src = f"""\
298 src = f"""\
298 import gc
299 import gc
299 %run "{tc}" C-first
300 %run "{tc}" C-first
300 gc.collect(0)
301 gc.collect(0)
301 %run "{tc}" C-second
302 %run "{tc}" C-second
302 gc.collect(0)
303 gc.collect(0)
303 %run "{tc}" C-third
304 %run "{tc}" C-third
304 gc.collect(0)
305 gc.collect(0)
305 %reset -f
306 %reset -f
306 """
307 """
307 self.mktmp(src, ".ipy")
308 self.mktmp(src, ".ipy")
308 out = """\
309 out = """\
309 ARGV 1-: ['C-first']
310 ARGV 1-: ['C-first']
310 ARGV 1-: ['C-second']
311 ARGV 1-: ['C-second']
311 tclass.py: deleting object: C-first
312 tclass.py: deleting object: C-first
312 ARGV 1-: ['C-third']
313 ARGV 1-: ['C-third']
313 tclass.py: deleting object: C-second
314 tclass.py: deleting object: C-second
314 tclass.py: deleting object: C-third
315 tclass.py: deleting object: C-third
315 """
316 """
316 err = None
317 err = None
317 tt.ipexec_validate(self.fname, out, err)
318 tt.ipexec_validate(self.fname, out, err)
318
319
319 def test_run_i_after_reset(self):
320 def test_run_i_after_reset(self):
320 """Check that %run -i still works after %reset (gh-693)"""
321 """Check that %run -i still works after %reset (gh-693)"""
321 src = "yy = zz\n"
322 src = "yy = zz\n"
322 self.mktmp(src)
323 self.mktmp(src)
323 _ip.run_cell("zz = 23")
324 _ip.run_cell("zz = 23")
324 try:
325 try:
325 _ip.magic("run -i %s" % self.fname)
326 _ip.magic("run -i %s" % self.fname)
326 assert _ip.user_ns["yy"] == 23
327 assert _ip.user_ns["yy"] == 23
327 finally:
328 finally:
328 _ip.magic('reset -f')
329 _ip.magic('reset -f')
329
330
330 _ip.run_cell("zz = 23")
331 _ip.run_cell("zz = 23")
331 try:
332 try:
332 _ip.magic("run -i %s" % self.fname)
333 _ip.magic("run -i %s" % self.fname)
333 assert _ip.user_ns["yy"] == 23
334 assert _ip.user_ns["yy"] == 23
334 finally:
335 finally:
335 _ip.magic('reset -f')
336 _ip.magic('reset -f')
336
337
337 def test_unicode(self):
338 def test_unicode(self):
338 """Check that files in odd encodings are accepted."""
339 """Check that files in odd encodings are accepted."""
339 mydir = os.path.dirname(__file__)
340 mydir = os.path.dirname(__file__)
340 na = os.path.join(mydir, 'nonascii.py')
341 na = os.path.join(mydir, 'nonascii.py')
341 _ip.magic('run "%s"' % na)
342 _ip.magic('run "%s"' % na)
342 assert _ip.user_ns["u"] == "ΠŽΡ‚β„–Π€"
343 assert _ip.user_ns["u"] == "ΠŽΡ‚β„–Π€"
343
344
344 def test_run_py_file_attribute(self):
345 def test_run_py_file_attribute(self):
345 """Test handling of `__file__` attribute in `%run <file>.py`."""
346 """Test handling of `__file__` attribute in `%run <file>.py`."""
346 src = "t = __file__\n"
347 src = "t = __file__\n"
347 self.mktmp(src)
348 self.mktmp(src)
348 _missing = object()
349 _missing = object()
349 file1 = _ip.user_ns.get('__file__', _missing)
350 file1 = _ip.user_ns.get('__file__', _missing)
350 _ip.magic('run %s' % self.fname)
351 _ip.magic('run %s' % self.fname)
351 file2 = _ip.user_ns.get('__file__', _missing)
352 file2 = _ip.user_ns.get('__file__', _missing)
352
353
353 # Check that __file__ was equal to the filename in the script's
354 # Check that __file__ was equal to the filename in the script's
354 # namespace.
355 # namespace.
355 assert _ip.user_ns["t"] == self.fname
356 assert _ip.user_ns["t"] == self.fname
356
357
357 # Check that __file__ was not leaked back into user_ns.
358 # Check that __file__ was not leaked back into user_ns.
358 assert file1 == file2
359 assert file1 == file2
359
360
360 def test_run_ipy_file_attribute(self):
361 def test_run_ipy_file_attribute(self):
361 """Test handling of `__file__` attribute in `%run <file.ipy>`."""
362 """Test handling of `__file__` attribute in `%run <file.ipy>`."""
362 src = "t = __file__\n"
363 src = "t = __file__\n"
363 self.mktmp(src, ext='.ipy')
364 self.mktmp(src, ext='.ipy')
364 _missing = object()
365 _missing = object()
365 file1 = _ip.user_ns.get('__file__', _missing)
366 file1 = _ip.user_ns.get('__file__', _missing)
366 _ip.magic('run %s' % self.fname)
367 _ip.magic('run %s' % self.fname)
367 file2 = _ip.user_ns.get('__file__', _missing)
368 file2 = _ip.user_ns.get('__file__', _missing)
368
369
369 # Check that __file__ was equal to the filename in the script's
370 # Check that __file__ was equal to the filename in the script's
370 # namespace.
371 # namespace.
371 assert _ip.user_ns["t"] == self.fname
372 assert _ip.user_ns["t"] == self.fname
372
373
373 # Check that __file__ was not leaked back into user_ns.
374 # Check that __file__ was not leaked back into user_ns.
374 assert file1 == file2
375 assert file1 == file2
375
376
376 def test_run_formatting(self):
377 def test_run_formatting(self):
377 """ Test that %run -t -N<N> does not raise a TypeError for N > 1."""
378 """ Test that %run -t -N<N> does not raise a TypeError for N > 1."""
378 src = "pass"
379 src = "pass"
379 self.mktmp(src)
380 self.mktmp(src)
380 _ip.magic('run -t -N 1 %s' % self.fname)
381 _ip.magic('run -t -N 1 %s' % self.fname)
381 _ip.magic('run -t -N 10 %s' % self.fname)
382 _ip.magic('run -t -N 10 %s' % self.fname)
382
383
383 def test_ignore_sys_exit(self):
384 def test_ignore_sys_exit(self):
384 """Test the -e option to ignore sys.exit()"""
385 """Test the -e option to ignore sys.exit()"""
385 src = "import sys; sys.exit(1)"
386 src = "import sys; sys.exit(1)"
386 self.mktmp(src)
387 self.mktmp(src)
387 with tt.AssertPrints('SystemExit'):
388 with tt.AssertPrints('SystemExit'):
388 _ip.magic('run %s' % self.fname)
389 _ip.magic('run %s' % self.fname)
389
390
390 with tt.AssertNotPrints('SystemExit'):
391 with tt.AssertNotPrints('SystemExit'):
391 _ip.magic('run -e %s' % self.fname)
392 _ip.magic('run -e %s' % self.fname)
392
393
393 def test_run_nb(self):
394 def test_run_nb(self):
394 """Test %run notebook.ipynb"""
395 """Test %run notebook.ipynb"""
395 pytest.importorskip("nbformat")
396 pytest.importorskip("nbformat")
396 from nbformat import v4, writes
397 from nbformat import v4, writes
397 nb = v4.new_notebook(
398 nb = v4.new_notebook(
398 cells=[
399 cells=[
399 v4.new_markdown_cell("The Ultimate Question of Everything"),
400 v4.new_markdown_cell("The Ultimate Question of Everything"),
400 v4.new_code_cell("answer=42")
401 v4.new_code_cell("answer=42")
401 ]
402 ]
402 )
403 )
403 src = writes(nb, version=4)
404 src = writes(nb, version=4)
404 self.mktmp(src, ext='.ipynb')
405 self.mktmp(src, ext='.ipynb')
405
406
406 _ip.magic("run %s" % self.fname)
407 _ip.magic("run %s" % self.fname)
407
408
408 assert _ip.user_ns["answer"] == 42
409 assert _ip.user_ns["answer"] == 42
409
410
410 def test_run_nb_error(self):
411 def test_run_nb_error(self):
411 """Test %run notebook.ipynb error"""
412 """Test %run notebook.ipynb error"""
412 pytest.importorskip("nbformat")
413 pytest.importorskip("nbformat")
413 from nbformat import v4, writes
414 from nbformat import v4, writes
415
414 # %run when a file name isn't provided
416 # %run when a file name isn't provided
415 pytest.raises(Exception, _ip.magic, "run")
417 pytest.raises(Exception, _ip.magic, "run")
416
418
417 # %run when a file doesn't exist
419 # %run when a file doesn't exist
418 pytest.raises(Exception, _ip.magic, "run foobar.ipynb")
420 pytest.raises(Exception, _ip.magic, "run foobar.ipynb")
419
421
420 # %run on a notebook with an error
422 # %run on a notebook with an error
421 nb = v4.new_notebook(
423 nb = v4.new_notebook(
422 cells=[
424 cells=[
423 v4.new_code_cell("0/0")
425 v4.new_code_cell("0/0")
424 ]
426 ]
425 )
427 )
426 src = writes(nb, version=4)
428 src = writes(nb, version=4)
427 self.mktmp(src, ext='.ipynb')
429 self.mktmp(src, ext='.ipynb')
428 pytest.raises(Exception, _ip.magic, "run %s" % self.fname)
430 pytest.raises(Exception, _ip.magic, "run %s" % self.fname)
429
431
430 def test_file_options(self):
432 def test_file_options(self):
431 src = ('import sys\n'
433 src = ('import sys\n'
432 'a = " ".join(sys.argv[1:])\n')
434 'a = " ".join(sys.argv[1:])\n')
433 self.mktmp(src)
435 self.mktmp(src)
434 test_opts = "-x 3 --verbose"
436 test_opts = "-x 3 --verbose"
435 _ip.run_line_magic("run", "{0} {1}".format(self.fname, test_opts))
437 _ip.run_line_magic("run", "{0} {1}".format(self.fname, test_opts))
436 assert _ip.user_ns["a"] == test_opts
438 assert _ip.user_ns["a"] == test_opts
437
439
438
440
439 class TestMagicRunWithPackage(unittest.TestCase):
441 class TestMagicRunWithPackage(unittest.TestCase):
440
442
441 def writefile(self, name, content):
443 def writefile(self, name, content):
442 path = os.path.join(self.tempdir.name, name)
444 path = os.path.join(self.tempdir.name, name)
443 d = os.path.dirname(path)
445 d = os.path.dirname(path)
444 if not os.path.isdir(d):
446 if not os.path.isdir(d):
445 os.makedirs(d)
447 os.makedirs(d)
446 with open(path, "w", encoding="utf-8") as f:
448 with open(path, "w", encoding="utf-8") as f:
447 f.write(textwrap.dedent(content))
449 f.write(textwrap.dedent(content))
448
450
449 def setUp(self):
451 def setUp(self):
450 self.package = package = 'tmp{0}'.format(''.join([random.choice(string.ascii_letters) for i in range(10)]))
452 self.package = package = 'tmp{0}'.format(''.join([random.choice(string.ascii_letters) for i in range(10)]))
451 """Temporary (probably) valid python package name."""
453 """Temporary (probably) valid python package name."""
452
454
453 self.value = int(random.random() * 10000)
455 self.value = int(random.random() * 10000)
454
456
455 self.tempdir = TemporaryDirectory()
457 self.tempdir = TemporaryDirectory()
456 self.__orig_cwd = os.getcwd()
458 self.__orig_cwd = os.getcwd()
457 sys.path.insert(0, self.tempdir.name)
459 sys.path.insert(0, self.tempdir.name)
458
460
459 self.writefile(os.path.join(package, '__init__.py'), '')
461 self.writefile(os.path.join(package, '__init__.py'), '')
460 self.writefile(os.path.join(package, 'sub.py'), """
462 self.writefile(os.path.join(package, 'sub.py'), """
461 x = {0!r}
463 x = {0!r}
462 """.format(self.value))
464 """.format(self.value))
463 self.writefile(os.path.join(package, 'relative.py'), """
465 self.writefile(os.path.join(package, 'relative.py'), """
464 from .sub import x
466 from .sub import x
465 """)
467 """)
466 self.writefile(os.path.join(package, 'absolute.py'), """
468 self.writefile(os.path.join(package, 'absolute.py'), """
467 from {0}.sub import x
469 from {0}.sub import x
468 """.format(package))
470 """.format(package))
469 self.writefile(os.path.join(package, 'args.py'), """
471 self.writefile(os.path.join(package, 'args.py'), """
470 import sys
472 import sys
471 a = " ".join(sys.argv[1:])
473 a = " ".join(sys.argv[1:])
472 """.format(package))
474 """.format(package))
473
475
474 def tearDown(self):
476 def tearDown(self):
475 os.chdir(self.__orig_cwd)
477 os.chdir(self.__orig_cwd)
476 sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
478 sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
477 self.tempdir.cleanup()
479 self.tempdir.cleanup()
478
480
479 def check_run_submodule(self, submodule, opts=''):
481 def check_run_submodule(self, submodule, opts=''):
480 _ip.user_ns.pop('x', None)
482 _ip.user_ns.pop('x', None)
481 _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
483 _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
482 self.assertEqual(_ip.user_ns['x'], self.value,
484 self.assertEqual(_ip.user_ns['x'], self.value,
483 'Variable `x` is not loaded from module `{0}`.'
485 'Variable `x` is not loaded from module `{0}`.'
484 .format(submodule))
486 .format(submodule))
485
487
486 def test_run_submodule_with_absolute_import(self):
488 def test_run_submodule_with_absolute_import(self):
487 self.check_run_submodule('absolute')
489 self.check_run_submodule('absolute')
488
490
489 def test_run_submodule_with_relative_import(self):
491 def test_run_submodule_with_relative_import(self):
490 """Run submodule that has a relative import statement (#2727)."""
492 """Run submodule that has a relative import statement (#2727)."""
491 self.check_run_submodule('relative')
493 self.check_run_submodule('relative')
492
494
493 def test_prun_submodule_with_absolute_import(self):
495 def test_prun_submodule_with_absolute_import(self):
494 self.check_run_submodule('absolute', '-p')
496 self.check_run_submodule('absolute', '-p')
495
497
496 def test_prun_submodule_with_relative_import(self):
498 def test_prun_submodule_with_relative_import(self):
497 self.check_run_submodule('relative', '-p')
499 self.check_run_submodule('relative', '-p')
498
500
499 def with_fake_debugger(func):
501 def with_fake_debugger(func):
500 @functools.wraps(func)
502 @functools.wraps(func)
501 def wrapper(*args, **kwds):
503 def wrapper(*args, **kwds):
502 with patch.object(debugger.Pdb, 'run', staticmethod(eval)):
504 with patch.object(debugger.Pdb, 'run', staticmethod(eval)):
503 return func(*args, **kwds)
505 return func(*args, **kwds)
504 return wrapper
506 return wrapper
505
507
506 @with_fake_debugger
508 @with_fake_debugger
507 def test_debug_run_submodule_with_absolute_import(self):
509 def test_debug_run_submodule_with_absolute_import(self):
508 self.check_run_submodule('absolute', '-d')
510 self.check_run_submodule('absolute', '-d')
509
511
510 @with_fake_debugger
512 @with_fake_debugger
511 def test_debug_run_submodule_with_relative_import(self):
513 def test_debug_run_submodule_with_relative_import(self):
512 self.check_run_submodule('relative', '-d')
514 self.check_run_submodule('relative', '-d')
513
515
514 def test_module_options(self):
516 def test_module_options(self):
515 _ip.user_ns.pop("a", None)
517 _ip.user_ns.pop("a", None)
516 test_opts = "-x abc -m test"
518 test_opts = "-x abc -m test"
517 _ip.run_line_magic("run", "-m {0}.args {1}".format(self.package, test_opts))
519 _ip.run_line_magic("run", "-m {0}.args {1}".format(self.package, test_opts))
518 assert _ip.user_ns["a"] == test_opts
520 assert _ip.user_ns["a"] == test_opts
519
521
520 def test_module_options_with_separator(self):
522 def test_module_options_with_separator(self):
521 _ip.user_ns.pop("a", None)
523 _ip.user_ns.pop("a", None)
522 test_opts = "-x abc -m test"
524 test_opts = "-x abc -m test"
523 _ip.run_line_magic("run", "-m {0}.args -- {1}".format(self.package, test_opts))
525 _ip.run_line_magic("run", "-m {0}.args -- {1}".format(self.package, test_opts))
524 assert _ip.user_ns["a"] == test_opts
526 assert _ip.user_ns["a"] == test_opts
525
527
526
528
527 def test_run__name__():
529 def test_run__name__():
528 with TemporaryDirectory() as td:
530 with TemporaryDirectory() as td:
529 path = pjoin(td, "foo.py")
531 path = pjoin(td, "foo.py")
530 with open(path, "w", encoding="utf-8") as f:
532 with open(path, "w", encoding="utf-8") as f:
531 f.write("q = __name__")
533 f.write("q = __name__")
532
534
533 _ip.user_ns.pop("q", None)
535 _ip.user_ns.pop("q", None)
534 _ip.magic("run {}".format(path))
536 _ip.magic("run {}".format(path))
535 assert _ip.user_ns.pop("q") == "__main__"
537 assert _ip.user_ns.pop("q") == "__main__"
536
538
537 _ip.magic("run -n {}".format(path))
539 _ip.magic("run -n {}".format(path))
538 assert _ip.user_ns.pop("q") == "foo"
540 assert _ip.user_ns.pop("q") == "foo"
539
541
540 try:
542 try:
541 _ip.magic("run -i -n {}".format(path))
543 _ip.magic("run -i -n {}".format(path))
542 assert _ip.user_ns.pop("q") == "foo"
544 assert _ip.user_ns.pop("q") == "foo"
543 finally:
545 finally:
544 _ip.magic('reset -f')
546 _ip.magic('reset -f')
545
547
546
548
547 def test_run_tb():
549 def test_run_tb():
548 """Test traceback offset in %run"""
550 """Test traceback offset in %run"""
549 with TemporaryDirectory() as td:
551 with TemporaryDirectory() as td:
550 path = pjoin(td, "foo.py")
552 path = pjoin(td, "foo.py")
551 with open(path, "w", encoding="utf-8") as f:
553 with open(path, "w", encoding="utf-8") as f:
552 f.write(
554 f.write(
553 "\n".join(
555 "\n".join(
554 [
556 [
555 "def foo():",
557 "def foo():",
556 " return bar()",
558 " return bar()",
557 "def bar():",
559 "def bar():",
558 " raise RuntimeError('hello!')",
560 " raise RuntimeError('hello!')",
559 "foo()",
561 "foo()",
560 ]
562 ]
561 )
563 )
562 )
564 )
563 with capture_output() as io:
565 with capture_output() as io:
564 _ip.magic('run {}'.format(path))
566 _ip.magic('run {}'.format(path))
565 out = io.stdout
567 out = io.stdout
566 assert "execfile" not in out
568 assert "execfile" not in out
567 assert "RuntimeError" in out
569 assert "RuntimeError" in out
568 assert out.count("---->") == 3
570 assert out.count("---->") == 3
569 del ip.user_ns['bar']
571 del ip.user_ns['bar']
570 del ip.user_ns['foo']
572 del ip.user_ns['foo']
571
573
572
574
573 def test_multiprocessing_run():
575 def test_multiprocessing_run():
574 """Set we can run mutiprocesgin without messing up up main namespace
576 """Set we can run mutiprocesgin without messing up up main namespace
575
577
576 Note that import `nose.tools as nt` mdify the value s
578 Note that import `nose.tools as nt` mdify the value s
577 sys.module['__mp_main__'] so we need to temporarily set it to None to test
579 sys.module['__mp_main__'] so we need to temporarily set it to None to test
578 the issue.
580 the issue.
579 """
581 """
580 with TemporaryDirectory() as td:
582 with TemporaryDirectory() as td:
581 mpm = sys.modules.get('__mp_main__')
583 mpm = sys.modules.get('__mp_main__')
582 sys.modules['__mp_main__'] = None
584 sys.modules['__mp_main__'] = None
583 try:
585 try:
584 path = pjoin(td, "test.py")
586 path = pjoin(td, "test.py")
585 with open(path, "w", encoding="utf-8") as f:
587 with open(path, "w", encoding="utf-8") as f:
586 f.write("import multiprocessing\nprint('hoy')")
588 f.write("import multiprocessing\nprint('hoy')")
587 with capture_output() as io:
589 with capture_output() as io:
588 _ip.run_line_magic('run', path)
590 _ip.run_line_magic('run', path)
589 _ip.run_cell("i_m_undefined")
591 _ip.run_cell("i_m_undefined")
590 out = io.stdout
592 out = io.stdout
591 assert "hoy" in out
593 assert "hoy" in out
592 assert "AttributeError" not in out
594 assert "AttributeError" not in out
593 assert "NameError" in out
595 assert "NameError" in out
594 assert out.count("---->") == 1
596 assert out.count("---->") == 1
595 except:
597 except:
596 raise
598 raise
597 finally:
599 finally:
598 sys.modules['__mp_main__'] = mpm
600 sys.modules['__mp_main__'] = mpm
599
601
600
602
601 def test_script_tb():
603 def test_script_tb():
602 """Test traceback offset in `ipython script.py`"""
604 """Test traceback offset in `ipython script.py`"""
603 with TemporaryDirectory() as td:
605 with TemporaryDirectory() as td:
604 path = pjoin(td, "foo.py")
606 path = pjoin(td, "foo.py")
605 with open(path, "w", encoding="utf-8") as f:
607 with open(path, "w", encoding="utf-8") as f:
606 f.write(
608 f.write(
607 "\n".join(
609 "\n".join(
608 [
610 [
609 "def foo():",
611 "def foo():",
610 " return bar()",
612 " return bar()",
611 "def bar():",
613 "def bar():",
612 " raise RuntimeError('hello!')",
614 " raise RuntimeError('hello!')",
613 "foo()",
615 "foo()",
614 ]
616 ]
615 )
617 )
616 )
618 )
617 out, err = tt.ipexec(path)
619 out, err = tt.ipexec(path)
618 assert "execfile" not in out
620 assert "execfile" not in out
619 assert "RuntimeError" in out
621 assert "RuntimeError" in out
620 assert out.count("---->") == 3
622 assert out.count("---->") == 3
@@ -1,410 +1,409 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for IPython.core.ultratb
2 """Tests for IPython.core.ultratb
3 """
3 """
4 import io
4 import io
5 import logging
5 import logging
6 import os.path
6 import platform
7 import platform
7 import re
8 import re
8 import sys
9 import sys
9 import os.path
10 from textwrap import dedent
11 import traceback
10 import traceback
12 import unittest
11 import unittest
12 from textwrap import dedent
13
13
14 from IPython.core.ultratb import ColorTB, VerboseTB
14 from tempfile import TemporaryDirectory
15
16
15
16 from IPython.core.ultratb import ColorTB, VerboseTB
17 from IPython.testing import tools as tt
17 from IPython.testing import tools as tt
18 from IPython.testing.decorators import onlyif_unicode_paths
18 from IPython.testing.decorators import onlyif_unicode_paths
19 from IPython.utils.syspathcontext import prepended_to_syspath
19 from IPython.utils.syspathcontext import prepended_to_syspath
20 from IPython.utils.tempdir import TemporaryDirectory
21
20
22 file_1 = """1
21 file_1 = """1
23 2
22 2
24 3
23 3
25 def f():
24 def f():
26 1/0
25 1/0
27 """
26 """
28
27
29 file_2 = """def f():
28 file_2 = """def f():
30 1/0
29 1/0
31 """
30 """
32
31
33
32
34 def recursionlimit(frames):
33 def recursionlimit(frames):
35 """
34 """
36 decorator to set the recursion limit temporarily
35 decorator to set the recursion limit temporarily
37 """
36 """
38
37
39 def inner(test_function):
38 def inner(test_function):
40 def wrapper(*args, **kwargs):
39 def wrapper(*args, **kwargs):
41 rl = sys.getrecursionlimit()
40 rl = sys.getrecursionlimit()
42 sys.setrecursionlimit(frames)
41 sys.setrecursionlimit(frames)
43 try:
42 try:
44 return test_function(*args, **kwargs)
43 return test_function(*args, **kwargs)
45 finally:
44 finally:
46 sys.setrecursionlimit(rl)
45 sys.setrecursionlimit(rl)
47
46
48 return wrapper
47 return wrapper
49
48
50 return inner
49 return inner
51
50
52
51
53 class ChangedPyFileTest(unittest.TestCase):
52 class ChangedPyFileTest(unittest.TestCase):
54 def test_changing_py_file(self):
53 def test_changing_py_file(self):
55 """Traceback produced if the line where the error occurred is missing?
54 """Traceback produced if the line where the error occurred is missing?
56
55
57 https://github.com/ipython/ipython/issues/1456
56 https://github.com/ipython/ipython/issues/1456
58 """
57 """
59 with TemporaryDirectory() as td:
58 with TemporaryDirectory() as td:
60 fname = os.path.join(td, "foo.py")
59 fname = os.path.join(td, "foo.py")
61 with open(fname, "w", encoding="utf-8") as f:
60 with open(fname, "w", encoding="utf-8") as f:
62 f.write(file_1)
61 f.write(file_1)
63
62
64 with prepended_to_syspath(td):
63 with prepended_to_syspath(td):
65 ip.run_cell("import foo")
64 ip.run_cell("import foo")
66
65
67 with tt.AssertPrints("ZeroDivisionError"):
66 with tt.AssertPrints("ZeroDivisionError"):
68 ip.run_cell("foo.f()")
67 ip.run_cell("foo.f()")
69
68
70 # Make the file shorter, so the line of the error is missing.
69 # Make the file shorter, so the line of the error is missing.
71 with open(fname, "w", encoding="utf-8") as f:
70 with open(fname, "w", encoding="utf-8") as f:
72 f.write(file_2)
71 f.write(file_2)
73
72
74 # For some reason, this was failing on the *second* call after
73 # For some reason, this was failing on the *second* call after
75 # changing the file, so we call f() twice.
74 # changing the file, so we call f() twice.
76 with tt.AssertNotPrints("Internal Python error", channel='stderr'):
75 with tt.AssertNotPrints("Internal Python error", channel='stderr'):
77 with tt.AssertPrints("ZeroDivisionError"):
76 with tt.AssertPrints("ZeroDivisionError"):
78 ip.run_cell("foo.f()")
77 ip.run_cell("foo.f()")
79 with tt.AssertPrints("ZeroDivisionError"):
78 with tt.AssertPrints("ZeroDivisionError"):
80 ip.run_cell("foo.f()")
79 ip.run_cell("foo.f()")
81
80
82 iso_8859_5_file = u'''# coding: iso-8859-5
81 iso_8859_5_file = u'''# coding: iso-8859-5
83
82
84 def fail():
83 def fail():
85 """Π΄Π±Π˜Π–"""
84 """Π΄Π±Π˜Π–"""
86 1/0 # Π΄Π±Π˜Π–
85 1/0 # Π΄Π±Π˜Π–
87 '''
86 '''
88
87
89 class NonAsciiTest(unittest.TestCase):
88 class NonAsciiTest(unittest.TestCase):
90 @onlyif_unicode_paths
89 @onlyif_unicode_paths
91 def test_nonascii_path(self):
90 def test_nonascii_path(self):
92 # Non-ascii directory name as well.
91 # Non-ascii directory name as well.
93 with TemporaryDirectory(suffix=u'Γ©') as td:
92 with TemporaryDirectory(suffix=u'Γ©') as td:
94 fname = os.path.join(td, u"fooΓ©.py")
93 fname = os.path.join(td, u"fooΓ©.py")
95 with open(fname, "w", encoding="utf-8") as f:
94 with open(fname, "w", encoding="utf-8") as f:
96 f.write(file_1)
95 f.write(file_1)
97
96
98 with prepended_to_syspath(td):
97 with prepended_to_syspath(td):
99 ip.run_cell("import foo")
98 ip.run_cell("import foo")
100
99
101 with tt.AssertPrints("ZeroDivisionError"):
100 with tt.AssertPrints("ZeroDivisionError"):
102 ip.run_cell("foo.f()")
101 ip.run_cell("foo.f()")
103
102
104 def test_iso8859_5(self):
103 def test_iso8859_5(self):
105 with TemporaryDirectory() as td:
104 with TemporaryDirectory() as td:
106 fname = os.path.join(td, 'dfghjkl.py')
105 fname = os.path.join(td, 'dfghjkl.py')
107
106
108 with io.open(fname, 'w', encoding='iso-8859-5') as f:
107 with io.open(fname, 'w', encoding='iso-8859-5') as f:
109 f.write(iso_8859_5_file)
108 f.write(iso_8859_5_file)
110
109
111 with prepended_to_syspath(td):
110 with prepended_to_syspath(td):
112 ip.run_cell("from dfghjkl import fail")
111 ip.run_cell("from dfghjkl import fail")
113
112
114 with tt.AssertPrints("ZeroDivisionError"):
113 with tt.AssertPrints("ZeroDivisionError"):
115 with tt.AssertPrints(u'Π΄Π±Π˜Π–', suppress=False):
114 with tt.AssertPrints(u'Π΄Π±Π˜Π–', suppress=False):
116 ip.run_cell('fail()')
115 ip.run_cell('fail()')
117
116
118 def test_nonascii_msg(self):
117 def test_nonascii_msg(self):
119 cell = u"raise Exception('Γ©')"
118 cell = u"raise Exception('Γ©')"
120 expected = u"Exception('Γ©')"
119 expected = u"Exception('Γ©')"
121 ip.run_cell("%xmode plain")
120 ip.run_cell("%xmode plain")
122 with tt.AssertPrints(expected):
121 with tt.AssertPrints(expected):
123 ip.run_cell(cell)
122 ip.run_cell(cell)
124
123
125 ip.run_cell("%xmode verbose")
124 ip.run_cell("%xmode verbose")
126 with tt.AssertPrints(expected):
125 with tt.AssertPrints(expected):
127 ip.run_cell(cell)
126 ip.run_cell(cell)
128
127
129 ip.run_cell("%xmode context")
128 ip.run_cell("%xmode context")
130 with tt.AssertPrints(expected):
129 with tt.AssertPrints(expected):
131 ip.run_cell(cell)
130 ip.run_cell(cell)
132
131
133 ip.run_cell("%xmode minimal")
132 ip.run_cell("%xmode minimal")
134 with tt.AssertPrints(u"Exception: Γ©"):
133 with tt.AssertPrints(u"Exception: Γ©"):
135 ip.run_cell(cell)
134 ip.run_cell(cell)
136
135
137 # Put this back into Context mode for later tests.
136 # Put this back into Context mode for later tests.
138 ip.run_cell("%xmode context")
137 ip.run_cell("%xmode context")
139
138
140 class NestedGenExprTestCase(unittest.TestCase):
139 class NestedGenExprTestCase(unittest.TestCase):
141 """
140 """
142 Regression test for the following issues:
141 Regression test for the following issues:
143 https://github.com/ipython/ipython/issues/8293
142 https://github.com/ipython/ipython/issues/8293
144 https://github.com/ipython/ipython/issues/8205
143 https://github.com/ipython/ipython/issues/8205
145 """
144 """
146 def test_nested_genexpr(self):
145 def test_nested_genexpr(self):
147 code = dedent(
146 code = dedent(
148 """\
147 """\
149 class SpecificException(Exception):
148 class SpecificException(Exception):
150 pass
149 pass
151
150
152 def foo(x):
151 def foo(x):
153 raise SpecificException("Success!")
152 raise SpecificException("Success!")
154
153
155 sum(sum(foo(x) for _ in [0]) for x in [0])
154 sum(sum(foo(x) for _ in [0]) for x in [0])
156 """
155 """
157 )
156 )
158 with tt.AssertPrints('SpecificException: Success!', suppress=False):
157 with tt.AssertPrints('SpecificException: Success!', suppress=False):
159 ip.run_cell(code)
158 ip.run_cell(code)
160
159
161
160
162 indentationerror_file = """if True:
161 indentationerror_file = """if True:
163 zoon()
162 zoon()
164 """
163 """
165
164
166 class IndentationErrorTest(unittest.TestCase):
165 class IndentationErrorTest(unittest.TestCase):
167 def test_indentationerror_shows_line(self):
166 def test_indentationerror_shows_line(self):
168 # See issue gh-2398
167 # See issue gh-2398
169 with tt.AssertPrints("IndentationError"):
168 with tt.AssertPrints("IndentationError"):
170 with tt.AssertPrints("zoon()", suppress=False):
169 with tt.AssertPrints("zoon()", suppress=False):
171 ip.run_cell(indentationerror_file)
170 ip.run_cell(indentationerror_file)
172
171
173 with TemporaryDirectory() as td:
172 with TemporaryDirectory() as td:
174 fname = os.path.join(td, "foo.py")
173 fname = os.path.join(td, "foo.py")
175 with open(fname, "w", encoding="utf-8") as f:
174 with open(fname, "w", encoding="utf-8") as f:
176 f.write(indentationerror_file)
175 f.write(indentationerror_file)
177
176
178 with tt.AssertPrints("IndentationError"):
177 with tt.AssertPrints("IndentationError"):
179 with tt.AssertPrints("zoon()", suppress=False):
178 with tt.AssertPrints("zoon()", suppress=False):
180 ip.magic('run %s' % fname)
179 ip.magic('run %s' % fname)
181
180
182 se_file_1 = """1
181 se_file_1 = """1
183 2
182 2
184 7/
183 7/
185 """
184 """
186
185
187 se_file_2 = """7/
186 se_file_2 = """7/
188 """
187 """
189
188
190 class SyntaxErrorTest(unittest.TestCase):
189 class SyntaxErrorTest(unittest.TestCase):
191
190
192 def test_syntaxerror_no_stacktrace_at_compile_time(self):
191 def test_syntaxerror_no_stacktrace_at_compile_time(self):
193 syntax_error_at_compile_time = """
192 syntax_error_at_compile_time = """
194 def foo():
193 def foo():
195 ..
194 ..
196 """
195 """
197 with tt.AssertPrints("SyntaxError"):
196 with tt.AssertPrints("SyntaxError"):
198 ip.run_cell(syntax_error_at_compile_time)
197 ip.run_cell(syntax_error_at_compile_time)
199
198
200 with tt.AssertNotPrints("foo()"):
199 with tt.AssertNotPrints("foo()"):
201 ip.run_cell(syntax_error_at_compile_time)
200 ip.run_cell(syntax_error_at_compile_time)
202
201
203 def test_syntaxerror_stacktrace_when_running_compiled_code(self):
202 def test_syntaxerror_stacktrace_when_running_compiled_code(self):
204 syntax_error_at_runtime = """
203 syntax_error_at_runtime = """
205 def foo():
204 def foo():
206 eval("..")
205 eval("..")
207
206
208 def bar():
207 def bar():
209 foo()
208 foo()
210
209
211 bar()
210 bar()
212 """
211 """
213 with tt.AssertPrints("SyntaxError"):
212 with tt.AssertPrints("SyntaxError"):
214 ip.run_cell(syntax_error_at_runtime)
213 ip.run_cell(syntax_error_at_runtime)
215 # Assert syntax error during runtime generate stacktrace
214 # Assert syntax error during runtime generate stacktrace
216 with tt.AssertPrints(["foo()", "bar()"]):
215 with tt.AssertPrints(["foo()", "bar()"]):
217 ip.run_cell(syntax_error_at_runtime)
216 ip.run_cell(syntax_error_at_runtime)
218 del ip.user_ns['bar']
217 del ip.user_ns['bar']
219 del ip.user_ns['foo']
218 del ip.user_ns['foo']
220
219
221 def test_changing_py_file(self):
220 def test_changing_py_file(self):
222 with TemporaryDirectory() as td:
221 with TemporaryDirectory() as td:
223 fname = os.path.join(td, "foo.py")
222 fname = os.path.join(td, "foo.py")
224 with open(fname, "w", encoding="utf-8") as f:
223 with open(fname, "w", encoding="utf-8") as f:
225 f.write(se_file_1)
224 f.write(se_file_1)
226
225
227 with tt.AssertPrints(["7/", "SyntaxError"]):
226 with tt.AssertPrints(["7/", "SyntaxError"]):
228 ip.magic("run " + fname)
227 ip.magic("run " + fname)
229
228
230 # Modify the file
229 # Modify the file
231 with open(fname, "w", encoding="utf-8") as f:
230 with open(fname, "w", encoding="utf-8") as f:
232 f.write(se_file_2)
231 f.write(se_file_2)
233
232
234 # The SyntaxError should point to the correct line
233 # The SyntaxError should point to the correct line
235 with tt.AssertPrints(["7/", "SyntaxError"]):
234 with tt.AssertPrints(["7/", "SyntaxError"]):
236 ip.magic("run " + fname)
235 ip.magic("run " + fname)
237
236
238 def test_non_syntaxerror(self):
237 def test_non_syntaxerror(self):
239 # SyntaxTB may be called with an error other than a SyntaxError
238 # SyntaxTB may be called with an error other than a SyntaxError
240 # See e.g. gh-4361
239 # See e.g. gh-4361
241 try:
240 try:
242 raise ValueError('QWERTY')
241 raise ValueError('QWERTY')
243 except ValueError:
242 except ValueError:
244 with tt.AssertPrints('QWERTY'):
243 with tt.AssertPrints('QWERTY'):
245 ip.showsyntaxerror()
244 ip.showsyntaxerror()
246
245
247 import sys
246 import sys
248
247
249 if sys.version_info < (3, 9) and platform.python_implementation() != "PyPy":
248 if sys.version_info < (3, 9) and platform.python_implementation() != "PyPy":
250 """
249 """
251 New 3.9 Pgen Parser does not raise Memory error, except on failed malloc.
250 New 3.9 Pgen Parser does not raise Memory error, except on failed malloc.
252 """
251 """
253 class MemoryErrorTest(unittest.TestCase):
252 class MemoryErrorTest(unittest.TestCase):
254 def test_memoryerror(self):
253 def test_memoryerror(self):
255 memoryerror_code = "(" * 200 + ")" * 200
254 memoryerror_code = "(" * 200 + ")" * 200
256 with tt.AssertPrints("MemoryError"):
255 with tt.AssertPrints("MemoryError"):
257 ip.run_cell(memoryerror_code)
256 ip.run_cell(memoryerror_code)
258
257
259
258
260 class Python3ChainedExceptionsTest(unittest.TestCase):
259 class Python3ChainedExceptionsTest(unittest.TestCase):
261 DIRECT_CAUSE_ERROR_CODE = """
260 DIRECT_CAUSE_ERROR_CODE = """
262 try:
261 try:
263 x = 1 + 2
262 x = 1 + 2
264 print(not_defined_here)
263 print(not_defined_here)
265 except Exception as e:
264 except Exception as e:
266 x += 55
265 x += 55
267 x - 1
266 x - 1
268 y = {}
267 y = {}
269 raise KeyError('uh') from e
268 raise KeyError('uh') from e
270 """
269 """
271
270
272 EXCEPTION_DURING_HANDLING_CODE = """
271 EXCEPTION_DURING_HANDLING_CODE = """
273 try:
272 try:
274 x = 1 + 2
273 x = 1 + 2
275 print(not_defined_here)
274 print(not_defined_here)
276 except Exception as e:
275 except Exception as e:
277 x += 55
276 x += 55
278 x - 1
277 x - 1
279 y = {}
278 y = {}
280 raise KeyError('uh')
279 raise KeyError('uh')
281 """
280 """
282
281
283 SUPPRESS_CHAINING_CODE = """
282 SUPPRESS_CHAINING_CODE = """
284 try:
283 try:
285 1/0
284 1/0
286 except Exception:
285 except Exception:
287 raise ValueError("Yikes") from None
286 raise ValueError("Yikes") from None
288 """
287 """
289
288
290 def test_direct_cause_error(self):
289 def test_direct_cause_error(self):
291 with tt.AssertPrints(["KeyError", "NameError", "direct cause"]):
290 with tt.AssertPrints(["KeyError", "NameError", "direct cause"]):
292 ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE)
291 ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE)
293
292
294 def test_exception_during_handling_error(self):
293 def test_exception_during_handling_error(self):
295 with tt.AssertPrints(["KeyError", "NameError", "During handling"]):
294 with tt.AssertPrints(["KeyError", "NameError", "During handling"]):
296 ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE)
295 ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE)
297
296
298 def test_suppress_exception_chaining(self):
297 def test_suppress_exception_chaining(self):
299 with tt.AssertNotPrints("ZeroDivisionError"), \
298 with tt.AssertNotPrints("ZeroDivisionError"), \
300 tt.AssertPrints("ValueError", suppress=False):
299 tt.AssertPrints("ValueError", suppress=False):
301 ip.run_cell(self.SUPPRESS_CHAINING_CODE)
300 ip.run_cell(self.SUPPRESS_CHAINING_CODE)
302
301
303 def test_plain_direct_cause_error(self):
302 def test_plain_direct_cause_error(self):
304 with tt.AssertPrints(["KeyError", "NameError", "direct cause"]):
303 with tt.AssertPrints(["KeyError", "NameError", "direct cause"]):
305 ip.run_cell("%xmode Plain")
304 ip.run_cell("%xmode Plain")
306 ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE)
305 ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE)
307 ip.run_cell("%xmode Verbose")
306 ip.run_cell("%xmode Verbose")
308
307
309 def test_plain_exception_during_handling_error(self):
308 def test_plain_exception_during_handling_error(self):
310 with tt.AssertPrints(["KeyError", "NameError", "During handling"]):
309 with tt.AssertPrints(["KeyError", "NameError", "During handling"]):
311 ip.run_cell("%xmode Plain")
310 ip.run_cell("%xmode Plain")
312 ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE)
311 ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE)
313 ip.run_cell("%xmode Verbose")
312 ip.run_cell("%xmode Verbose")
314
313
315 def test_plain_suppress_exception_chaining(self):
314 def test_plain_suppress_exception_chaining(self):
316 with tt.AssertNotPrints("ZeroDivisionError"), \
315 with tt.AssertNotPrints("ZeroDivisionError"), \
317 tt.AssertPrints("ValueError", suppress=False):
316 tt.AssertPrints("ValueError", suppress=False):
318 ip.run_cell("%xmode Plain")
317 ip.run_cell("%xmode Plain")
319 ip.run_cell(self.SUPPRESS_CHAINING_CODE)
318 ip.run_cell(self.SUPPRESS_CHAINING_CODE)
320 ip.run_cell("%xmode Verbose")
319 ip.run_cell("%xmode Verbose")
321
320
322
321
323 class RecursionTest(unittest.TestCase):
322 class RecursionTest(unittest.TestCase):
324 DEFINITIONS = """
323 DEFINITIONS = """
325 def non_recurs():
324 def non_recurs():
326 1/0
325 1/0
327
326
328 def r1():
327 def r1():
329 r1()
328 r1()
330
329
331 def r3a():
330 def r3a():
332 r3b()
331 r3b()
333
332
334 def r3b():
333 def r3b():
335 r3c()
334 r3c()
336
335
337 def r3c():
336 def r3c():
338 r3a()
337 r3a()
339
338
340 def r3o1():
339 def r3o1():
341 r3a()
340 r3a()
342
341
343 def r3o2():
342 def r3o2():
344 r3o1()
343 r3o1()
345 """
344 """
346 def setUp(self):
345 def setUp(self):
347 ip.run_cell(self.DEFINITIONS)
346 ip.run_cell(self.DEFINITIONS)
348
347
349 def test_no_recursion(self):
348 def test_no_recursion(self):
350 with tt.AssertNotPrints("skipping similar frames"):
349 with tt.AssertNotPrints("skipping similar frames"):
351 ip.run_cell("non_recurs()")
350 ip.run_cell("non_recurs()")
352
351
353 @recursionlimit(200)
352 @recursionlimit(200)
354 def test_recursion_one_frame(self):
353 def test_recursion_one_frame(self):
355 with tt.AssertPrints(re.compile(
354 with tt.AssertPrints(re.compile(
356 r"\[\.\.\. skipping similar frames: r1 at line 5 \(\d{2,3} times\)\]")
355 r"\[\.\.\. skipping similar frames: r1 at line 5 \(\d{2,3} times\)\]")
357 ):
356 ):
358 ip.run_cell("r1()")
357 ip.run_cell("r1()")
359
358
360 @recursionlimit(160)
359 @recursionlimit(160)
361 def test_recursion_three_frames(self):
360 def test_recursion_three_frames(self):
362 with tt.AssertPrints("[... skipping similar frames: "), \
361 with tt.AssertPrints("[... skipping similar frames: "), \
363 tt.AssertPrints(re.compile(r"r3a at line 8 \(\d{2} times\)"), suppress=False), \
362 tt.AssertPrints(re.compile(r"r3a at line 8 \(\d{2} times\)"), suppress=False), \
364 tt.AssertPrints(re.compile(r"r3b at line 11 \(\d{2} times\)"), suppress=False), \
363 tt.AssertPrints(re.compile(r"r3b at line 11 \(\d{2} times\)"), suppress=False), \
365 tt.AssertPrints(re.compile(r"r3c at line 14 \(\d{2} times\)"), suppress=False):
364 tt.AssertPrints(re.compile(r"r3c at line 14 \(\d{2} times\)"), suppress=False):
366 ip.run_cell("r3o2()")
365 ip.run_cell("r3o2()")
367
366
368
367
369 #----------------------------------------------------------------------------
368 #----------------------------------------------------------------------------
370
369
371 # module testing (minimal)
370 # module testing (minimal)
372 def test_handlers():
371 def test_handlers():
373 def spam(c, d_e):
372 def spam(c, d_e):
374 (d, e) = d_e
373 (d, e) = d_e
375 x = c + d
374 x = c + d
376 y = c * d
375 y = c * d
377 foo(x, y)
376 foo(x, y)
378
377
379 def foo(a, b, bar=1):
378 def foo(a, b, bar=1):
380 eggs(a, b + bar)
379 eggs(a, b + bar)
381
380
382 def eggs(f, g, z=globals()):
381 def eggs(f, g, z=globals()):
383 h = f + g
382 h = f + g
384 i = f - g
383 i = f - g
385 return h / i
384 return h / i
386
385
387 buff = io.StringIO()
386 buff = io.StringIO()
388
387
389 buff.write('')
388 buff.write('')
390 buff.write('*** Before ***')
389 buff.write('*** Before ***')
391 try:
390 try:
392 buff.write(spam(1, (2, 3)))
391 buff.write(spam(1, (2, 3)))
393 except:
392 except:
394 traceback.print_exc(file=buff)
393 traceback.print_exc(file=buff)
395
394
396 handler = ColorTB(ostream=buff)
395 handler = ColorTB(ostream=buff)
397 buff.write('*** ColorTB ***')
396 buff.write('*** ColorTB ***')
398 try:
397 try:
399 buff.write(spam(1, (2, 3)))
398 buff.write(spam(1, (2, 3)))
400 except:
399 except:
401 handler(*sys.exc_info())
400 handler(*sys.exc_info())
402 buff.write('')
401 buff.write('')
403
402
404 handler = VerboseTB(ostream=buff)
403 handler = VerboseTB(ostream=buff)
405 buff.write('*** VerboseTB ***')
404 buff.write('*** VerboseTB ***')
406 try:
405 try:
407 buff.write(spam(1, (2, 3)))
406 buff.write(spam(1, (2, 3)))
408 except:
407 except:
409 handler(*sys.exc_info())
408 handler(*sys.exc_info())
410 buff.write('')
409 buff.write('')
@@ -1,56 +1,57 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Test suite for the deepreload module."""
2 """Test suite for the deepreload module."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 import pytest
8 import types
7 import types
9
10 from pathlib import Path
8 from pathlib import Path
11
9
10 import pytest
11 from tempfile import TemporaryDirectory
12
13 from IPython.lib.deepreload import modules_reloading
14 from IPython.lib.deepreload import reload as dreload
12 from IPython.utils.syspathcontext import prepended_to_syspath
15 from IPython.utils.syspathcontext import prepended_to_syspath
13 from IPython.utils.tempdir import TemporaryDirectory
14 from IPython.lib.deepreload import reload as dreload, modules_reloading
15
16
16
17
17 def test_deepreload():
18 def test_deepreload():
18 "Test that dreload does deep reloads and skips excluded modules."
19 "Test that dreload does deep reloads and skips excluded modules."
19 with TemporaryDirectory() as tmpdir:
20 with TemporaryDirectory() as tmpdir:
20 with prepended_to_syspath(tmpdir):
21 with prepended_to_syspath(tmpdir):
21 tmpdirpath = Path(tmpdir)
22 tmpdirpath = Path(tmpdir)
22 with open(tmpdirpath / "A.py", "w", encoding="utf-8") as f:
23 with open(tmpdirpath / "A.py", "w", encoding="utf-8") as f:
23 f.write("class Object:\n pass\nok = True\n")
24 f.write("class Object:\n pass\nok = True\n")
24 with open(tmpdirpath / "B.py", "w", encoding="utf-8") as f:
25 with open(tmpdirpath / "B.py", "w", encoding="utf-8") as f:
25 f.write("import A\nassert A.ok, 'we are fine'\n")
26 f.write("import A\nassert A.ok, 'we are fine'\n")
26 import A
27 import A
27 import B
28 import B
28
29
29 # Test that A is not reloaded.
30 # Test that A is not reloaded.
30 obj = A.Object()
31 obj = A.Object()
31 dreload(B, exclude=["A"])
32 dreload(B, exclude=["A"])
32 assert isinstance(obj, A.Object) is True
33 assert isinstance(obj, A.Object) is True
33
34
34 # Test that an import failure will not blow-up us.
35 # Test that an import failure will not blow-up us.
35 A.ok = False
36 A.ok = False
36 with pytest.raises(AssertionError, match="we are fine"):
37 with pytest.raises(AssertionError, match="we are fine"):
37 dreload(B, exclude=["A"])
38 dreload(B, exclude=["A"])
38 assert len(modules_reloading) == 0
39 assert len(modules_reloading) == 0
39 assert not A.ok
40 assert not A.ok
40
41
41 # Test that A is reloaded.
42 # Test that A is reloaded.
42 obj = A.Object()
43 obj = A.Object()
43 A.ok = False
44 A.ok = False
44 dreload(B)
45 dreload(B)
45 assert A.ok
46 assert A.ok
46 assert isinstance(obj, A.Object) is False
47 assert isinstance(obj, A.Object) is False
47
48
48
49
49 def test_not_module():
50 def test_not_module():
50 pytest.raises(TypeError, dreload, "modulename")
51 pytest.raises(TypeError, dreload, "modulename")
51
52
52
53
53 def test_not_in_sys_modules():
54 def test_not_in_sys_modules():
54 fake_module = types.ModuleType("fake_module")
55 fake_module = types.ModuleType("fake_module")
55 with pytest.raises(ImportError, match="not in sys.modules"):
56 with pytest.raises(ImportError, match="not in sys.modules"):
56 dreload(fake_module)
57 dreload(fake_module)
@@ -1,59 +1,58 b''
1 """ This module contains classes - NamedFileInTemporaryDirectory, TemporaryWorkingDirectory.
1 """ This module contains classes - NamedFileInTemporaryDirectory, TemporaryWorkingDirectory.
2
2
3 These classes add extra features such as creating a named file in temporary directory and
3 These classes add extra features such as creating a named file in temporary directory and
4 creating a context manager for the working directory which is also temporary.
4 creating a context manager for the working directory which is also temporary.
5 """
5 """
6
6
7 import os as _os
7 import os as _os
8 from pathlib import Path
8 from pathlib import Path
9 from tempfile import TemporaryDirectory
9 from tempfile import TemporaryDirectory
10
10
11
11
12 class NamedFileInTemporaryDirectory(object):
12 class NamedFileInTemporaryDirectory(object):
13
13 def __init__(self, filename, mode="w+b", bufsize=-1, add_to_syspath=False, **kwds):
14 def __init__(self, filename, mode='w+b', bufsize=-1, **kwds):
15 """
14 """
16 Open a file named `filename` in a temporary directory.
15 Open a file named `filename` in a temporary directory.
17
16
18 This context manager is preferred over `NamedTemporaryFile` in
17 This context manager is preferred over `NamedTemporaryFile` in
19 stdlib `tempfile` when one needs to reopen the file.
18 stdlib `tempfile` when one needs to reopen the file.
20
19
21 Arguments `mode` and `bufsize` are passed to `open`.
20 Arguments `mode` and `bufsize` are passed to `open`.
22 Rest of the arguments are passed to `TemporaryDirectory`.
21 Rest of the arguments are passed to `TemporaryDirectory`.
23
22
24 """
23 """
25 self._tmpdir = TemporaryDirectory(**kwds)
24 self._tmpdir = TemporaryDirectory(**kwds)
26 path = Path(self._tmpdir.name) / filename
25 path = Path(self._tmpdir.name) / filename
27 encoding = None if "b" in mode else "utf-8"
26 encoding = None if "b" in mode else "utf-8"
28 self.file = open(path, mode, bufsize, encoding=encoding)
27 self.file = open(path, mode, bufsize, encoding=encoding)
29
28
30 def cleanup(self):
29 def cleanup(self):
31 self.file.close()
30 self.file.close()
32 self._tmpdir.cleanup()
31 self._tmpdir.cleanup()
33
32
34 __del__ = cleanup
33 __del__ = cleanup
35
34
36 def __enter__(self):
35 def __enter__(self):
37 return self.file
36 return self.file
38
37
39 def __exit__(self, type, value, traceback):
38 def __exit__(self, type, value, traceback):
40 self.cleanup()
39 self.cleanup()
41
40
42
41
43 class TemporaryWorkingDirectory(TemporaryDirectory):
42 class TemporaryWorkingDirectory(TemporaryDirectory):
44 """
43 """
45 Creates a temporary directory and sets the cwd to that directory.
44 Creates a temporary directory and sets the cwd to that directory.
46 Automatically reverts to previous cwd upon cleanup.
45 Automatically reverts to previous cwd upon cleanup.
47 Usage example:
46 Usage example:
48
47
49 with TemporaryWorkingDirectory() as tmpdir:
48 with TemporaryWorkingDirectory() as tmpdir:
50 ...
49 ...
51 """
50 """
52 def __enter__(self):
51 def __enter__(self):
53 self.old_wd = Path.cwd()
52 self.old_wd = Path.cwd()
54 _os.chdir(self.name)
53 _os.chdir(self.name)
55 return super(TemporaryWorkingDirectory, self).__enter__()
54 return super(TemporaryWorkingDirectory, self).__enter__()
56
55
57 def __exit__(self, exc, value, tb):
56 def __exit__(self, exc, value, tb):
58 _os.chdir(self.old_wd)
57 _os.chdir(self.old_wd)
59 return super(TemporaryWorkingDirectory, self).__exit__(exc, value, tb)
58 return super(TemporaryWorkingDirectory, self).__exit__(exc, value, tb)
@@ -1,509 +1,509 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for IPython.utils.path.py"""
2 """Tests for IPython.utils.path.py"""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 import os
7 import os
8 import shutil
8 import shutil
9 import sys
9 import sys
10 import tempfile
10 import tempfile
11 import unittest
11 import unittest
12 from contextlib import contextmanager
12 from contextlib import contextmanager
13 from unittest.mock import patch
14 from os.path import join, abspath
15 from importlib import reload
13 from importlib import reload
14 from os.path import abspath, join
15 from unittest.mock import patch
16
16
17 import pytest
17 import pytest
18 from tempfile import TemporaryDirectory
18
19
19 import IPython
20 import IPython
20 from IPython import paths
21 from IPython import paths
21 from IPython.testing import decorators as dec
22 from IPython.testing import decorators as dec
22 from IPython.testing.decorators import (
23 from IPython.testing.decorators import (
24 onlyif_unicode_paths,
23 skip_if_not_win32,
25 skip_if_not_win32,
24 skip_win32,
26 skip_win32,
25 onlyif_unicode_paths,
26 )
27 )
27 from IPython.testing.tools import make_tempfile
28 from IPython.testing.tools import make_tempfile
28 from IPython.utils import path
29 from IPython.utils import path
29 from IPython.utils.tempdir import TemporaryDirectory
30
31
30
32 # Platform-dependent imports
31 # Platform-dependent imports
33 try:
32 try:
34 import winreg as wreg
33 import winreg as wreg
35 except ImportError:
34 except ImportError:
36 #Fake _winreg module on non-windows platforms
35 #Fake _winreg module on non-windows platforms
37 import types
36 import types
38 wr_name = "winreg"
37 wr_name = "winreg"
39 sys.modules[wr_name] = types.ModuleType(wr_name)
38 sys.modules[wr_name] = types.ModuleType(wr_name)
40 try:
39 try:
41 import winreg as wreg
40 import winreg as wreg
42 except ImportError:
41 except ImportError:
43 import _winreg as wreg
42 import _winreg as wreg
43
44 #Add entries that needs to be stubbed by the testing code
44 #Add entries that needs to be stubbed by the testing code
45 (wreg.OpenKey, wreg.QueryValueEx,) = (None, None)
45 (wreg.OpenKey, wreg.QueryValueEx,) = (None, None)
46
46
47 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
48 # Globals
48 # Globals
49 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
50 env = os.environ
50 env = os.environ
51 TMP_TEST_DIR = tempfile.mkdtemp()
51 TMP_TEST_DIR = tempfile.mkdtemp()
52 HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir")
52 HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir")
53 #
53 #
54 # Setup/teardown functions/decorators
54 # Setup/teardown functions/decorators
55 #
55 #
56
56
57 def setup_module():
57 def setup_module():
58 """Setup testenvironment for the module:
58 """Setup testenvironment for the module:
59
59
60 - Adds dummy home dir tree
60 - Adds dummy home dir tree
61 """
61 """
62 # Do not mask exceptions here. In particular, catching WindowsError is a
62 # Do not mask exceptions here. In particular, catching WindowsError is a
63 # problem because that exception is only defined on Windows...
63 # problem because that exception is only defined on Windows...
64 os.makedirs(os.path.join(HOME_TEST_DIR, 'ipython'))
64 os.makedirs(os.path.join(HOME_TEST_DIR, 'ipython'))
65
65
66
66
67 def teardown_module():
67 def teardown_module():
68 """Teardown testenvironment for the module:
68 """Teardown testenvironment for the module:
69
69
70 - Remove dummy home dir tree
70 - Remove dummy home dir tree
71 """
71 """
72 # Note: we remove the parent test dir, which is the root of all test
72 # Note: we remove the parent test dir, which is the root of all test
73 # subdirs we may have created. Use shutil instead of os.removedirs, so
73 # subdirs we may have created. Use shutil instead of os.removedirs, so
74 # that non-empty directories are all recursively removed.
74 # that non-empty directories are all recursively removed.
75 shutil.rmtree(TMP_TEST_DIR)
75 shutil.rmtree(TMP_TEST_DIR)
76
76
77
77
78 def setup_environment():
78 def setup_environment():
79 """Setup testenvironment for some functions that are tested
79 """Setup testenvironment for some functions that are tested
80 in this module. In particular this functions stores attributes
80 in this module. In particular this functions stores attributes
81 and other things that we need to stub in some test functions.
81 and other things that we need to stub in some test functions.
82 This needs to be done on a function level and not module level because
82 This needs to be done on a function level and not module level because
83 each testfunction needs a pristine environment.
83 each testfunction needs a pristine environment.
84 """
84 """
85 global oldstuff, platformstuff
85 global oldstuff, platformstuff
86 oldstuff = (env.copy(), os.name, sys.platform, path.get_home_dir, IPython.__file__, os.getcwd())
86 oldstuff = (env.copy(), os.name, sys.platform, path.get_home_dir, IPython.__file__, os.getcwd())
87
87
88 def teardown_environment():
88 def teardown_environment():
89 """Restore things that were remembered by the setup_environment function
89 """Restore things that were remembered by the setup_environment function
90 """
90 """
91 (oldenv, os.name, sys.platform, path.get_home_dir, IPython.__file__, old_wd) = oldstuff
91 (oldenv, os.name, sys.platform, path.get_home_dir, IPython.__file__, old_wd) = oldstuff
92 os.chdir(old_wd)
92 os.chdir(old_wd)
93 reload(path)
93 reload(path)
94
94
95 for key in list(env):
95 for key in list(env):
96 if key not in oldenv:
96 if key not in oldenv:
97 del env[key]
97 del env[key]
98 env.update(oldenv)
98 env.update(oldenv)
99 if hasattr(sys, 'frozen'):
99 if hasattr(sys, 'frozen'):
100 del sys.frozen
100 del sys.frozen
101
101
102
102
103 # Build decorator that uses the setup_environment/setup_environment
103 # Build decorator that uses the setup_environment/setup_environment
104 @pytest.fixture
104 @pytest.fixture
105 def environment():
105 def environment():
106 setup_environment()
106 setup_environment()
107 yield
107 yield
108 teardown_environment()
108 teardown_environment()
109
109
110
110
111 with_environment = pytest.mark.usefixtures("environment")
111 with_environment = pytest.mark.usefixtures("environment")
112
112
113
113
114 @skip_if_not_win32
114 @skip_if_not_win32
115 @with_environment
115 @with_environment
116 def test_get_home_dir_1():
116 def test_get_home_dir_1():
117 """Testcase for py2exe logic, un-compressed lib
117 """Testcase for py2exe logic, un-compressed lib
118 """
118 """
119 unfrozen = path.get_home_dir()
119 unfrozen = path.get_home_dir()
120 sys.frozen = True
120 sys.frozen = True
121
121
122 #fake filename for IPython.__init__
122 #fake filename for IPython.__init__
123 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Lib/IPython/__init__.py"))
123 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Lib/IPython/__init__.py"))
124
124
125 home_dir = path.get_home_dir()
125 home_dir = path.get_home_dir()
126 assert home_dir == unfrozen
126 assert home_dir == unfrozen
127
127
128
128
129 @skip_if_not_win32
129 @skip_if_not_win32
130 @with_environment
130 @with_environment
131 def test_get_home_dir_2():
131 def test_get_home_dir_2():
132 """Testcase for py2exe logic, compressed lib
132 """Testcase for py2exe logic, compressed lib
133 """
133 """
134 unfrozen = path.get_home_dir()
134 unfrozen = path.get_home_dir()
135 sys.frozen = True
135 sys.frozen = True
136 #fake filename for IPython.__init__
136 #fake filename for IPython.__init__
137 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Library.zip/IPython/__init__.py")).lower()
137 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Library.zip/IPython/__init__.py")).lower()
138
138
139 home_dir = path.get_home_dir(True)
139 home_dir = path.get_home_dir(True)
140 assert home_dir == unfrozen
140 assert home_dir == unfrozen
141
141
142
142
143 @skip_win32
143 @skip_win32
144 @with_environment
144 @with_environment
145 def test_get_home_dir_3():
145 def test_get_home_dir_3():
146 """get_home_dir() uses $HOME if set"""
146 """get_home_dir() uses $HOME if set"""
147 env["HOME"] = HOME_TEST_DIR
147 env["HOME"] = HOME_TEST_DIR
148 home_dir = path.get_home_dir(True)
148 home_dir = path.get_home_dir(True)
149 # get_home_dir expands symlinks
149 # get_home_dir expands symlinks
150 assert home_dir == os.path.realpath(env["HOME"])
150 assert home_dir == os.path.realpath(env["HOME"])
151
151
152
152
153 @with_environment
153 @with_environment
154 def test_get_home_dir_4():
154 def test_get_home_dir_4():
155 """get_home_dir() still works if $HOME is not set"""
155 """get_home_dir() still works if $HOME is not set"""
156
156
157 if 'HOME' in env: del env['HOME']
157 if 'HOME' in env: del env['HOME']
158 # this should still succeed, but we don't care what the answer is
158 # this should still succeed, but we don't care what the answer is
159 home = path.get_home_dir(False)
159 home = path.get_home_dir(False)
160
160
161 @skip_win32
161 @skip_win32
162 @with_environment
162 @with_environment
163 def test_get_home_dir_5():
163 def test_get_home_dir_5():
164 """raise HomeDirError if $HOME is specified, but not a writable dir"""
164 """raise HomeDirError if $HOME is specified, but not a writable dir"""
165 env['HOME'] = abspath(HOME_TEST_DIR+'garbage')
165 env['HOME'] = abspath(HOME_TEST_DIR+'garbage')
166 # set os.name = posix, to prevent My Documents fallback on Windows
166 # set os.name = posix, to prevent My Documents fallback on Windows
167 os.name = 'posix'
167 os.name = 'posix'
168 pytest.raises(path.HomeDirError, path.get_home_dir, True)
168 pytest.raises(path.HomeDirError, path.get_home_dir, True)
169
169
170 # Should we stub wreg fully so we can run the test on all platforms?
170 # Should we stub wreg fully so we can run the test on all platforms?
171 @skip_if_not_win32
171 @skip_if_not_win32
172 @with_environment
172 @with_environment
173 def test_get_home_dir_8():
173 def test_get_home_dir_8():
174 """Using registry hack for 'My Documents', os=='nt'
174 """Using registry hack for 'My Documents', os=='nt'
175
175
176 HOMESHARE, HOMEDRIVE, HOMEPATH, USERPROFILE and others are missing.
176 HOMESHARE, HOMEDRIVE, HOMEPATH, USERPROFILE and others are missing.
177 """
177 """
178 os.name = 'nt'
178 os.name = 'nt'
179 # Remove from stub environment all keys that may be set
179 # Remove from stub environment all keys that may be set
180 for key in ['HOME', 'HOMESHARE', 'HOMEDRIVE', 'HOMEPATH', 'USERPROFILE']:
180 for key in ['HOME', 'HOMESHARE', 'HOMEDRIVE', 'HOMEPATH', 'USERPROFILE']:
181 env.pop(key, None)
181 env.pop(key, None)
182
182
183 class key:
183 class key:
184 def __enter__(self):
184 def __enter__(self):
185 pass
185 pass
186 def Close(self):
186 def Close(self):
187 pass
187 pass
188 def __exit__(*args, **kwargs):
188 def __exit__(*args, **kwargs):
189 pass
189 pass
190
190
191 with patch.object(wreg, 'OpenKey', return_value=key()), \
191 with patch.object(wreg, 'OpenKey', return_value=key()), \
192 patch.object(wreg, 'QueryValueEx', return_value=[abspath(HOME_TEST_DIR)]):
192 patch.object(wreg, 'QueryValueEx', return_value=[abspath(HOME_TEST_DIR)]):
193 home_dir = path.get_home_dir()
193 home_dir = path.get_home_dir()
194 assert home_dir == abspath(HOME_TEST_DIR)
194 assert home_dir == abspath(HOME_TEST_DIR)
195
195
196 @with_environment
196 @with_environment
197 def test_get_xdg_dir_0():
197 def test_get_xdg_dir_0():
198 """test_get_xdg_dir_0, check xdg_dir"""
198 """test_get_xdg_dir_0, check xdg_dir"""
199 reload(path)
199 reload(path)
200 path._writable_dir = lambda path: True
200 path._writable_dir = lambda path: True
201 path.get_home_dir = lambda : 'somewhere'
201 path.get_home_dir = lambda : 'somewhere'
202 os.name = "posix"
202 os.name = "posix"
203 sys.platform = "linux2"
203 sys.platform = "linux2"
204 env.pop('IPYTHON_DIR', None)
204 env.pop('IPYTHON_DIR', None)
205 env.pop('IPYTHONDIR', None)
205 env.pop('IPYTHONDIR', None)
206 env.pop('XDG_CONFIG_HOME', None)
206 env.pop('XDG_CONFIG_HOME', None)
207
207
208 assert path.get_xdg_dir() == os.path.join("somewhere", ".config")
208 assert path.get_xdg_dir() == os.path.join("somewhere", ".config")
209
209
210
210
211 @with_environment
211 @with_environment
212 def test_get_xdg_dir_1():
212 def test_get_xdg_dir_1():
213 """test_get_xdg_dir_1, check nonexistent xdg_dir"""
213 """test_get_xdg_dir_1, check nonexistent xdg_dir"""
214 reload(path)
214 reload(path)
215 path.get_home_dir = lambda : HOME_TEST_DIR
215 path.get_home_dir = lambda : HOME_TEST_DIR
216 os.name = "posix"
216 os.name = "posix"
217 sys.platform = "linux2"
217 sys.platform = "linux2"
218 env.pop('IPYTHON_DIR', None)
218 env.pop('IPYTHON_DIR', None)
219 env.pop('IPYTHONDIR', None)
219 env.pop('IPYTHONDIR', None)
220 env.pop('XDG_CONFIG_HOME', None)
220 env.pop('XDG_CONFIG_HOME', None)
221 assert path.get_xdg_dir() is None
221 assert path.get_xdg_dir() is None
222
222
223 @with_environment
223 @with_environment
224 def test_get_xdg_dir_2():
224 def test_get_xdg_dir_2():
225 """test_get_xdg_dir_2, check xdg_dir default to ~/.config"""
225 """test_get_xdg_dir_2, check xdg_dir default to ~/.config"""
226 reload(path)
226 reload(path)
227 path.get_home_dir = lambda : HOME_TEST_DIR
227 path.get_home_dir = lambda : HOME_TEST_DIR
228 os.name = "posix"
228 os.name = "posix"
229 sys.platform = "linux2"
229 sys.platform = "linux2"
230 env.pop('IPYTHON_DIR', None)
230 env.pop('IPYTHON_DIR', None)
231 env.pop('IPYTHONDIR', None)
231 env.pop('IPYTHONDIR', None)
232 env.pop('XDG_CONFIG_HOME', None)
232 env.pop('XDG_CONFIG_HOME', None)
233 cfgdir=os.path.join(path.get_home_dir(), '.config')
233 cfgdir=os.path.join(path.get_home_dir(), '.config')
234 if not os.path.exists(cfgdir):
234 if not os.path.exists(cfgdir):
235 os.makedirs(cfgdir)
235 os.makedirs(cfgdir)
236
236
237 assert path.get_xdg_dir() == cfgdir
237 assert path.get_xdg_dir() == cfgdir
238
238
239 @with_environment
239 @with_environment
240 def test_get_xdg_dir_3():
240 def test_get_xdg_dir_3():
241 """test_get_xdg_dir_3, check xdg_dir not used on non-posix systems"""
241 """test_get_xdg_dir_3, check xdg_dir not used on non-posix systems"""
242 reload(path)
242 reload(path)
243 path.get_home_dir = lambda : HOME_TEST_DIR
243 path.get_home_dir = lambda : HOME_TEST_DIR
244 os.name = "nt"
244 os.name = "nt"
245 sys.platform = "win32"
245 sys.platform = "win32"
246 env.pop('IPYTHON_DIR', None)
246 env.pop('IPYTHON_DIR', None)
247 env.pop('IPYTHONDIR', None)
247 env.pop('IPYTHONDIR', None)
248 env.pop('XDG_CONFIG_HOME', None)
248 env.pop('XDG_CONFIG_HOME', None)
249 cfgdir=os.path.join(path.get_home_dir(), '.config')
249 cfgdir=os.path.join(path.get_home_dir(), '.config')
250 os.makedirs(cfgdir, exist_ok=True)
250 os.makedirs(cfgdir, exist_ok=True)
251
251
252 assert path.get_xdg_dir() is None
252 assert path.get_xdg_dir() is None
253
253
254 def test_filefind():
254 def test_filefind():
255 """Various tests for filefind"""
255 """Various tests for filefind"""
256 f = tempfile.NamedTemporaryFile()
256 f = tempfile.NamedTemporaryFile()
257 # print 'fname:',f.name
257 # print 'fname:',f.name
258 alt_dirs = paths.get_ipython_dir()
258 alt_dirs = paths.get_ipython_dir()
259 t = path.filefind(f.name, alt_dirs)
259 t = path.filefind(f.name, alt_dirs)
260 # print 'found:',t
260 # print 'found:',t
261
261
262
262
263 @dec.skip_if_not_win32
263 @dec.skip_if_not_win32
264 def test_get_long_path_name_win32():
264 def test_get_long_path_name_win32():
265 with TemporaryDirectory() as tmpdir:
265 with TemporaryDirectory() as tmpdir:
266
266
267 # Make a long path. Expands the path of tmpdir prematurely as it may already have a long
267 # Make a long path. Expands the path of tmpdir prematurely as it may already have a long
268 # path component, so ensure we include the long form of it
268 # path component, so ensure we include the long form of it
269 long_path = os.path.join(path.get_long_path_name(tmpdir), 'this is my long path name')
269 long_path = os.path.join(path.get_long_path_name(tmpdir), 'this is my long path name')
270 os.makedirs(long_path)
270 os.makedirs(long_path)
271
271
272 # Test to see if the short path evaluates correctly.
272 # Test to see if the short path evaluates correctly.
273 short_path = os.path.join(tmpdir, 'THISIS~1')
273 short_path = os.path.join(tmpdir, 'THISIS~1')
274 evaluated_path = path.get_long_path_name(short_path)
274 evaluated_path = path.get_long_path_name(short_path)
275 assert evaluated_path.lower() == long_path.lower()
275 assert evaluated_path.lower() == long_path.lower()
276
276
277
277
278 @dec.skip_win32
278 @dec.skip_win32
279 def test_get_long_path_name():
279 def test_get_long_path_name():
280 p = path.get_long_path_name("/usr/local")
280 p = path.get_long_path_name("/usr/local")
281 assert p == "/usr/local"
281 assert p == "/usr/local"
282
282
283
283
284 class TestRaiseDeprecation(unittest.TestCase):
284 class TestRaiseDeprecation(unittest.TestCase):
285
285
286 @dec.skip_win32 # can't create not-user-writable dir on win
286 @dec.skip_win32 # can't create not-user-writable dir on win
287 @with_environment
287 @with_environment
288 def test_not_writable_ipdir(self):
288 def test_not_writable_ipdir(self):
289 tmpdir = tempfile.mkdtemp()
289 tmpdir = tempfile.mkdtemp()
290 os.name = "posix"
290 os.name = "posix"
291 env.pop('IPYTHON_DIR', None)
291 env.pop('IPYTHON_DIR', None)
292 env.pop('IPYTHONDIR', None)
292 env.pop('IPYTHONDIR', None)
293 env.pop('XDG_CONFIG_HOME', None)
293 env.pop('XDG_CONFIG_HOME', None)
294 env['HOME'] = tmpdir
294 env['HOME'] = tmpdir
295 ipdir = os.path.join(tmpdir, '.ipython')
295 ipdir = os.path.join(tmpdir, '.ipython')
296 os.mkdir(ipdir, 0o555)
296 os.mkdir(ipdir, 0o555)
297 try:
297 try:
298 open(os.path.join(ipdir, "_foo_"), "w", encoding="utf-8").close()
298 open(os.path.join(ipdir, "_foo_"), "w", encoding="utf-8").close()
299 except IOError:
299 except IOError:
300 pass
300 pass
301 else:
301 else:
302 # I can still write to an unwritable dir,
302 # I can still write to an unwritable dir,
303 # assume I'm root and skip the test
303 # assume I'm root and skip the test
304 pytest.skip("I can't create directories that I can't write to")
304 pytest.skip("I can't create directories that I can't write to")
305
305
306 with self.assertWarnsRegex(UserWarning, 'is not a writable location'):
306 with self.assertWarnsRegex(UserWarning, 'is not a writable location'):
307 ipdir = paths.get_ipython_dir()
307 ipdir = paths.get_ipython_dir()
308 env.pop('IPYTHON_DIR', None)
308 env.pop('IPYTHON_DIR', None)
309
309
310 @with_environment
310 @with_environment
311 def test_get_py_filename():
311 def test_get_py_filename():
312 os.chdir(TMP_TEST_DIR)
312 os.chdir(TMP_TEST_DIR)
313 with make_tempfile("foo.py"):
313 with make_tempfile("foo.py"):
314 assert path.get_py_filename("foo.py") == "foo.py"
314 assert path.get_py_filename("foo.py") == "foo.py"
315 assert path.get_py_filename("foo") == "foo.py"
315 assert path.get_py_filename("foo") == "foo.py"
316 with make_tempfile("foo"):
316 with make_tempfile("foo"):
317 assert path.get_py_filename("foo") == "foo"
317 assert path.get_py_filename("foo") == "foo"
318 pytest.raises(IOError, path.get_py_filename, "foo.py")
318 pytest.raises(IOError, path.get_py_filename, "foo.py")
319 pytest.raises(IOError, path.get_py_filename, "foo")
319 pytest.raises(IOError, path.get_py_filename, "foo")
320 pytest.raises(IOError, path.get_py_filename, "foo.py")
320 pytest.raises(IOError, path.get_py_filename, "foo.py")
321 true_fn = "foo with spaces.py"
321 true_fn = "foo with spaces.py"
322 with make_tempfile(true_fn):
322 with make_tempfile(true_fn):
323 assert path.get_py_filename("foo with spaces") == true_fn
323 assert path.get_py_filename("foo with spaces") == true_fn
324 assert path.get_py_filename("foo with spaces.py") == true_fn
324 assert path.get_py_filename("foo with spaces.py") == true_fn
325 pytest.raises(IOError, path.get_py_filename, '"foo with spaces.py"')
325 pytest.raises(IOError, path.get_py_filename, '"foo with spaces.py"')
326 pytest.raises(IOError, path.get_py_filename, "'foo with spaces.py'")
326 pytest.raises(IOError, path.get_py_filename, "'foo with spaces.py'")
327
327
328 @onlyif_unicode_paths
328 @onlyif_unicode_paths
329 def test_unicode_in_filename():
329 def test_unicode_in_filename():
330 """When a file doesn't exist, the exception raised should be safe to call
330 """When a file doesn't exist, the exception raised should be safe to call
331 str() on - i.e. in Python 2 it must only have ASCII characters.
331 str() on - i.e. in Python 2 it must only have ASCII characters.
332
332
333 https://github.com/ipython/ipython/issues/875
333 https://github.com/ipython/ipython/issues/875
334 """
334 """
335 try:
335 try:
336 # these calls should not throw unicode encode exceptions
336 # these calls should not throw unicode encode exceptions
337 path.get_py_filename('fooéè.py')
337 path.get_py_filename('fooéè.py')
338 except IOError as ex:
338 except IOError as ex:
339 str(ex)
339 str(ex)
340
340
341
341
342 class TestShellGlob(unittest.TestCase):
342 class TestShellGlob(unittest.TestCase):
343
343
344 @classmethod
344 @classmethod
345 def setUpClass(cls):
345 def setUpClass(cls):
346 cls.filenames_start_with_a = ['a0', 'a1', 'a2']
346 cls.filenames_start_with_a = ['a0', 'a1', 'a2']
347 cls.filenames_end_with_b = ['0b', '1b', '2b']
347 cls.filenames_end_with_b = ['0b', '1b', '2b']
348 cls.filenames = cls.filenames_start_with_a + cls.filenames_end_with_b
348 cls.filenames = cls.filenames_start_with_a + cls.filenames_end_with_b
349 cls.tempdir = TemporaryDirectory()
349 cls.tempdir = TemporaryDirectory()
350 td = cls.tempdir.name
350 td = cls.tempdir.name
351
351
352 with cls.in_tempdir():
352 with cls.in_tempdir():
353 # Create empty files
353 # Create empty files
354 for fname in cls.filenames:
354 for fname in cls.filenames:
355 open(os.path.join(td, fname), "w", encoding="utf-8").close()
355 open(os.path.join(td, fname), "w", encoding="utf-8").close()
356
356
357 @classmethod
357 @classmethod
358 def tearDownClass(cls):
358 def tearDownClass(cls):
359 cls.tempdir.cleanup()
359 cls.tempdir.cleanup()
360
360
361 @classmethod
361 @classmethod
362 @contextmanager
362 @contextmanager
363 def in_tempdir(cls):
363 def in_tempdir(cls):
364 save = os.getcwd()
364 save = os.getcwd()
365 try:
365 try:
366 os.chdir(cls.tempdir.name)
366 os.chdir(cls.tempdir.name)
367 yield
367 yield
368 finally:
368 finally:
369 os.chdir(save)
369 os.chdir(save)
370
370
371 def check_match(self, patterns, matches):
371 def check_match(self, patterns, matches):
372 with self.in_tempdir():
372 with self.in_tempdir():
373 # glob returns unordered list. that's why sorted is required.
373 # glob returns unordered list. that's why sorted is required.
374 assert sorted(path.shellglob(patterns)) == sorted(matches)
374 assert sorted(path.shellglob(patterns)) == sorted(matches)
375
375
376 def common_cases(self):
376 def common_cases(self):
377 return [
377 return [
378 (['*'], self.filenames),
378 (['*'], self.filenames),
379 (['a*'], self.filenames_start_with_a),
379 (['a*'], self.filenames_start_with_a),
380 (['*c'], ['*c']),
380 (['*c'], ['*c']),
381 (['*', 'a*', '*b', '*c'], self.filenames
381 (['*', 'a*', '*b', '*c'], self.filenames
382 + self.filenames_start_with_a
382 + self.filenames_start_with_a
383 + self.filenames_end_with_b
383 + self.filenames_end_with_b
384 + ['*c']),
384 + ['*c']),
385 (['a[012]'], self.filenames_start_with_a),
385 (['a[012]'], self.filenames_start_with_a),
386 ]
386 ]
387
387
388 @skip_win32
388 @skip_win32
389 def test_match_posix(self):
389 def test_match_posix(self):
390 for (patterns, matches) in self.common_cases() + [
390 for (patterns, matches) in self.common_cases() + [
391 ([r'\*'], ['*']),
391 ([r'\*'], ['*']),
392 ([r'a\*', 'a*'], ['a*'] + self.filenames_start_with_a),
392 ([r'a\*', 'a*'], ['a*'] + self.filenames_start_with_a),
393 ([r'a\[012]'], ['a[012]']),
393 ([r'a\[012]'], ['a[012]']),
394 ]:
394 ]:
395 self.check_match(patterns, matches)
395 self.check_match(patterns, matches)
396
396
397 @skip_if_not_win32
397 @skip_if_not_win32
398 def test_match_windows(self):
398 def test_match_windows(self):
399 for (patterns, matches) in self.common_cases() + [
399 for (patterns, matches) in self.common_cases() + [
400 # In windows, backslash is interpreted as path
400 # In windows, backslash is interpreted as path
401 # separator. Therefore, you can't escape glob
401 # separator. Therefore, you can't escape glob
402 # using it.
402 # using it.
403 ([r'a\*', 'a*'], [r'a\*'] + self.filenames_start_with_a),
403 ([r'a\*', 'a*'], [r'a\*'] + self.filenames_start_with_a),
404 ([r'a\[012]'], [r'a\[012]']),
404 ([r'a\[012]'], [r'a\[012]']),
405 ]:
405 ]:
406 self.check_match(patterns, matches)
406 self.check_match(patterns, matches)
407
407
408
408
409 @pytest.mark.parametrize(
409 @pytest.mark.parametrize(
410 "globstr, unescaped_globstr",
410 "globstr, unescaped_globstr",
411 [
411 [
412 (r"\*\[\!\]\?", "*[!]?"),
412 (r"\*\[\!\]\?", "*[!]?"),
413 (r"\\*", r"\*"),
413 (r"\\*", r"\*"),
414 (r"\\\*", r"\*"),
414 (r"\\\*", r"\*"),
415 (r"\\a", r"\a"),
415 (r"\\a", r"\a"),
416 (r"\a", r"\a"),
416 (r"\a", r"\a"),
417 ],
417 ],
418 )
418 )
419 def test_unescape_glob(globstr, unescaped_globstr):
419 def test_unescape_glob(globstr, unescaped_globstr):
420 assert path.unescape_glob(globstr) == unescaped_globstr
420 assert path.unescape_glob(globstr) == unescaped_globstr
421
421
422
422
423 @onlyif_unicode_paths
423 @onlyif_unicode_paths
424 def test_ensure_dir_exists():
424 def test_ensure_dir_exists():
425 with TemporaryDirectory() as td:
425 with TemporaryDirectory() as td:
426 d = os.path.join(td, 'βˆ‚ir')
426 d = os.path.join(td, 'βˆ‚ir')
427 path.ensure_dir_exists(d) # create it
427 path.ensure_dir_exists(d) # create it
428 assert os.path.isdir(d)
428 assert os.path.isdir(d)
429 path.ensure_dir_exists(d) # no-op
429 path.ensure_dir_exists(d) # no-op
430 f = os.path.join(td, "Ζ’ile")
430 f = os.path.join(td, "Ζ’ile")
431 open(f, "w", encoding="utf-8").close() # touch
431 open(f, "w", encoding="utf-8").close() # touch
432 with pytest.raises(IOError):
432 with pytest.raises(IOError):
433 path.ensure_dir_exists(f)
433 path.ensure_dir_exists(f)
434
434
435 class TestLinkOrCopy(unittest.TestCase):
435 class TestLinkOrCopy(unittest.TestCase):
436 def setUp(self):
436 def setUp(self):
437 self.tempdir = TemporaryDirectory()
437 self.tempdir = TemporaryDirectory()
438 self.src = self.dst("src")
438 self.src = self.dst("src")
439 with open(self.src, "w", encoding="utf-8") as f:
439 with open(self.src, "w", encoding="utf-8") as f:
440 f.write("Hello, world!")
440 f.write("Hello, world!")
441
441
442 def tearDown(self):
442 def tearDown(self):
443 self.tempdir.cleanup()
443 self.tempdir.cleanup()
444
444
445 def dst(self, *args):
445 def dst(self, *args):
446 return os.path.join(self.tempdir.name, *args)
446 return os.path.join(self.tempdir.name, *args)
447
447
448 def assert_inode_not_equal(self, a, b):
448 def assert_inode_not_equal(self, a, b):
449 assert (
449 assert (
450 os.stat(a).st_ino != os.stat(b).st_ino
450 os.stat(a).st_ino != os.stat(b).st_ino
451 ), "%r and %r do reference the same indoes" % (a, b)
451 ), "%r and %r do reference the same indoes" % (a, b)
452
452
453 def assert_inode_equal(self, a, b):
453 def assert_inode_equal(self, a, b):
454 assert (
454 assert (
455 os.stat(a).st_ino == os.stat(b).st_ino
455 os.stat(a).st_ino == os.stat(b).st_ino
456 ), "%r and %r do not reference the same indoes" % (a, b)
456 ), "%r and %r do not reference the same indoes" % (a, b)
457
457
458 def assert_content_equal(self, a, b):
458 def assert_content_equal(self, a, b):
459 with open(a, "rb") as a_f:
459 with open(a, "rb") as a_f:
460 with open(b, "rb") as b_f:
460 with open(b, "rb") as b_f:
461 assert a_f.read() == b_f.read()
461 assert a_f.read() == b_f.read()
462
462
463 @skip_win32
463 @skip_win32
464 def test_link_successful(self):
464 def test_link_successful(self):
465 dst = self.dst("target")
465 dst = self.dst("target")
466 path.link_or_copy(self.src, dst)
466 path.link_or_copy(self.src, dst)
467 self.assert_inode_equal(self.src, dst)
467 self.assert_inode_equal(self.src, dst)
468
468
469 @skip_win32
469 @skip_win32
470 def test_link_into_dir(self):
470 def test_link_into_dir(self):
471 dst = self.dst("some_dir")
471 dst = self.dst("some_dir")
472 os.mkdir(dst)
472 os.mkdir(dst)
473 path.link_or_copy(self.src, dst)
473 path.link_or_copy(self.src, dst)
474 expected_dst = self.dst("some_dir", os.path.basename(self.src))
474 expected_dst = self.dst("some_dir", os.path.basename(self.src))
475 self.assert_inode_equal(self.src, expected_dst)
475 self.assert_inode_equal(self.src, expected_dst)
476
476
477 @skip_win32
477 @skip_win32
478 def test_target_exists(self):
478 def test_target_exists(self):
479 dst = self.dst("target")
479 dst = self.dst("target")
480 open(dst, "w", encoding="utf-8").close()
480 open(dst, "w", encoding="utf-8").close()
481 path.link_or_copy(self.src, dst)
481 path.link_or_copy(self.src, dst)
482 self.assert_inode_equal(self.src, dst)
482 self.assert_inode_equal(self.src, dst)
483
483
484 @skip_win32
484 @skip_win32
485 def test_no_link(self):
485 def test_no_link(self):
486 real_link = os.link
486 real_link = os.link
487 try:
487 try:
488 del os.link
488 del os.link
489 dst = self.dst("target")
489 dst = self.dst("target")
490 path.link_or_copy(self.src, dst)
490 path.link_or_copy(self.src, dst)
491 self.assert_content_equal(self.src, dst)
491 self.assert_content_equal(self.src, dst)
492 self.assert_inode_not_equal(self.src, dst)
492 self.assert_inode_not_equal(self.src, dst)
493 finally:
493 finally:
494 os.link = real_link
494 os.link = real_link
495
495
496 @skip_if_not_win32
496 @skip_if_not_win32
497 def test_windows(self):
497 def test_windows(self):
498 dst = self.dst("target")
498 dst = self.dst("target")
499 path.link_or_copy(self.src, dst)
499 path.link_or_copy(self.src, dst)
500 self.assert_content_equal(self.src, dst)
500 self.assert_content_equal(self.src, dst)
501
501
502 def test_link_twice(self):
502 def test_link_twice(self):
503 # Linking the same file twice shouldn't leave duplicates around.
503 # Linking the same file twice shouldn't leave duplicates around.
504 # See https://github.com/ipython/ipython/issues/6450
504 # See https://github.com/ipython/ipython/issues/6450
505 dst = self.dst('target')
505 dst = self.dst('target')
506 path.link_or_copy(self.src, dst)
506 path.link_or_copy(self.src, dst)
507 path.link_or_copy(self.src, dst)
507 path.link_or_copy(self.src, dst)
508 self.assert_inode_equal(self.src, dst)
508 self.assert_inode_equal(self.src, dst)
509 assert sorted(os.listdir(self.tempdir.name)) == ["src", "target"]
509 assert sorted(os.listdir(self.tempdir.name)) == ["src", "target"]
General Comments 0
You need to be logged in to leave comments. Login now