##// END OF EJS Templates
Revert "Ruffisation"
M Bussonnier -
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,492 +1,492
1 1 # encoding: utf-8
2 2 """
3 3 An application for IPython.
4 4
5 5 All top-level applications should use the classes in this module for
6 6 handling configuration and creating configurables.
7 7
8 8 The job of an :class:`Application` is to create the master configuration
9 9 object and then create the configurable objects, passing the config to them.
10 10 """
11 11
12 12 # Copyright (c) IPython Development Team.
13 13 # Distributed under the terms of the Modified BSD License.
14 14
15 15 import atexit
16 16 from copy import deepcopy
17 17 import logging
18 18 import os
19 19 import shutil
20 20 import sys
21 21
22 22 from pathlib import Path
23 23
24 24 from traitlets.config.application import Application, catch_config_error
25 25 from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader
26 26 from IPython.core import release, crashhandler
27 27 from IPython.core.profiledir import ProfileDir, ProfileDirError
28 28 from IPython.paths import get_ipython_dir, get_ipython_package_dir
29 29 from IPython.utils.path import ensure_dir_exists
30 30 from traitlets import (
31 31 List, Unicode, Type, Bool, Set, Instance, Undefined,
32 32 default, observe,
33 33 )
34 34
35 35 if os.name == "nt":
36 36 programdata = os.environ.get("PROGRAMDATA", None)
37 37 if programdata is not None:
38 38 SYSTEM_CONFIG_DIRS = [str(Path(programdata) / "ipython")]
39 39 else: # PROGRAMDATA is not defined by default on XP.
40 40 SYSTEM_CONFIG_DIRS = []
41 41 else:
42 42 SYSTEM_CONFIG_DIRS = [
43 43 "/usr/local/etc/ipython",
44 44 "/etc/ipython",
45 45 ]
46 46
47 47
48 48 ENV_CONFIG_DIRS = []
49 49 _env_config_dir = os.path.join(sys.prefix, 'etc', 'ipython')
50 50 if _env_config_dir not in SYSTEM_CONFIG_DIRS:
51 51 # only add ENV_CONFIG if sys.prefix is not already included
52 52 ENV_CONFIG_DIRS.append(_env_config_dir)
53 53
54 54
55 55 _envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS')
56 56 if _envvar in {None, ''}:
57 57 IPYTHON_SUPPRESS_CONFIG_ERRORS = None
58 58 else:
59 59 if _envvar.lower() in {'1','true'}:
60 60 IPYTHON_SUPPRESS_CONFIG_ERRORS = True
61 61 elif _envvar.lower() in {'0','false'} :
62 62 IPYTHON_SUPPRESS_CONFIG_ERRORS = False
63 63 else:
64 64 sys.exit("Unsupported value for environment variable: 'IPYTHON_SUPPRESS_CONFIG_ERRORS' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar )
65 65
66 66 # aliases and flags
67 67
68 68 base_aliases = {}
69 69 if isinstance(Application.aliases, dict):
70 70 # traitlets 5
71 71 base_aliases.update(Application.aliases)
72 72 base_aliases.update(
73 73 {
74 74 "profile-dir": "ProfileDir.location",
75 75 "profile": "BaseIPythonApplication.profile",
76 76 "ipython-dir": "BaseIPythonApplication.ipython_dir",
77 77 "log-level": "Application.log_level",
78 78 "config": "BaseIPythonApplication.extra_config_file",
79 79 }
80 80 )
81 81
82 82 base_flags = dict()
83 83 if isinstance(Application.flags, dict):
84 84 # traitlets 5
85 85 base_flags.update(Application.flags)
86 86 base_flags.update(
87 87 dict(
88 88 debug=(
89 89 {"Application": {"log_level": logging.DEBUG}},
90 90 "set log level to logging.DEBUG (maximize logging output)",
91 91 ),
92 92 quiet=(
93 93 {"Application": {"log_level": logging.CRITICAL}},
94 94 "set log level to logging.CRITICAL (minimize logging output)",
95 95 ),
96 96 init=(
97 97 {
98 98 "BaseIPythonApplication": {
99 99 "copy_config_files": True,
100 100 "auto_create": True,
101 101 }
102 102 },
103 103 """Initialize profile with default config files. This is equivalent
104 104 to running `ipython profile create <profile>` prior to startup.
105 105 """,
106 106 ),
107 107 )
108 108 )
109 109
110 110
111 111 class ProfileAwareConfigLoader(PyFileConfigLoader):
112 112 """A Python file config loader that is aware of IPython profiles."""
113 113 def load_subconfig(self, fname, path=None, profile=None):
114 114 if profile is not None:
115 115 try:
116 116 profile_dir = ProfileDir.find_profile_dir_by_name(
117 117 get_ipython_dir(),
118 118 profile,
119 119 )
120 120 except ProfileDirError:
121 121 return
122 122 path = profile_dir.location
123 123 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
124 124
125 125 class BaseIPythonApplication(Application):
126 126 name = "ipython"
127 127 description = "IPython: an enhanced interactive Python shell."
128 128 version = Unicode(release.version)
129 129
130 130 aliases = base_aliases
131 131 flags = base_flags
132 132 classes = List([ProfileDir])
133 133
134 134 # enable `load_subconfig('cfg.py', profile='name')`
135 135 python_config_loader_class = ProfileAwareConfigLoader
136 136
137 137 # Track whether the config_file has changed,
138 138 # because some logic happens only if we aren't using the default.
139 139 config_file_specified = Set()
140 140
141 141 config_file_name = Unicode()
142 142 @default('config_file_name')
143 143 def _config_file_name_default(self):
144 144 return self.name.replace('-','_') + u'_config.py'
145 145 @observe('config_file_name')
146 146 def _config_file_name_changed(self, change):
147 147 if change['new'] != change['old']:
148 148 self.config_file_specified.add(change['new'])
149 149
150 150 # The directory that contains IPython's builtin profiles.
151 151 builtin_profile_dir = Unicode(
152 152 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
153 153 )
154 154
155 155 config_file_paths = List(Unicode())
156 156 @default('config_file_paths')
157 157 def _config_file_paths_default(self):
158 158 return []
159 159
160 160 extra_config_file = Unicode(
161 161 help="""Path to an extra config file to load.
162 162
163 163 If specified, load this config file in addition to any other IPython config.
164 164 """).tag(config=True)
165 165 @observe('extra_config_file')
166 166 def _extra_config_file_changed(self, change):
167 167 old = change['old']
168 168 new = change['new']
169 169 try:
170 170 self.config_files.remove(old)
171 171 except ValueError:
172 172 pass
173 173 self.config_file_specified.add(new)
174 174 self.config_files.append(new)
175 175
176 176 profile = Unicode(u'default',
177 177 help="""The IPython profile to use."""
178 178 ).tag(config=True)
179 179
180 180 @observe('profile')
181 181 def _profile_changed(self, change):
182 182 self.builtin_profile_dir = os.path.join(
183 183 get_ipython_package_dir(), u'config', u'profile', change['new']
184 184 )
185 185
186 186 add_ipython_dir_to_sys_path = Bool(
187 187 False,
188 188 """Should the IPython profile directory be added to sys path ?
189 189
190 190 This option was non-existing before IPython 8.0, and ipython_dir was added to
191 191 sys path to allow import of extensions present there. This was historical
192 192 baggage from when pip did not exist. This now default to false,
193 193 but can be set to true for legacy reasons.
194 194 """,
195 195 ).tag(config=True)
196 196
197 197 ipython_dir = Unicode(
198 198 help="""
199 199 The name of the IPython directory. This directory is used for logging
200 200 configuration (through profiles), history storage, etc. The default
201 201 is usually $HOME/.ipython. This option can also be specified through
202 202 the environment variable IPYTHONDIR.
203 203 """
204 204 ).tag(config=True)
205 205 @default('ipython_dir')
206 206 def _ipython_dir_default(self):
207 207 d = get_ipython_dir()
208 208 self._ipython_dir_changed({
209 209 'name': 'ipython_dir',
210 210 'old': d,
211 211 'new': d,
212 212 })
213 213 return d
214 214
215 215 _in_init_profile_dir = False
216 216
217 217 profile_dir = Instance(ProfileDir, allow_none=True)
218 218
219 219 @default('profile_dir')
220 220 def _profile_dir_default(self):
221 221 # avoid recursion
222 222 if self._in_init_profile_dir:
223 223 return
224 224 # profile_dir requested early, force initialization
225 225 self.init_profile_dir()
226 226 return self.profile_dir
227 227
228 228 overwrite = Bool(False,
229 229 help="""Whether to overwrite existing config files when copying"""
230 230 ).tag(config=True)
231 231
232 232 auto_create = Bool(False,
233 233 help="""Whether to create profile dir if it doesn't exist"""
234 234 ).tag(config=True)
235 235
236 236 config_files = List(Unicode())
237 237
238 238 @default('config_files')
239 239 def _config_files_default(self):
240 240 return [self.config_file_name]
241 241
242 242 copy_config_files = Bool(False,
243 243 help="""Whether to install the default config files into the profile dir.
244 244 If a new profile is being created, and IPython contains config files for that
245 245 profile, then they will be staged into the new directory. Otherwise,
246 246 default config files will be automatically generated.
247 247 """).tag(config=True)
248 248
249 249 verbose_crash = Bool(False,
250 250 help="""Create a massive crash report when IPython encounters what may be an
251 251 internal error. The default is to append a short message to the
252 252 usual traceback""").tag(config=True)
253 253
254 254 # The class to use as the crash handler.
255 255 crash_handler_class = Type(crashhandler.CrashHandler)
256 256
257 257 @catch_config_error
258 258 def __init__(self, **kwargs):
259 259 super(BaseIPythonApplication, self).__init__(**kwargs)
260 260 # ensure current working directory exists
261 261 try:
262 262 os.getcwd()
263 except Exception:
263 except:
264 264 # exit if cwd doesn't exist
265 265 self.log.error("Current working directory doesn't exist.")
266 266 self.exit(1)
267 267
268 268 #-------------------------------------------------------------------------
269 269 # Various stages of Application creation
270 270 #-------------------------------------------------------------------------
271 271
272 272 def init_crash_handler(self):
273 273 """Create a crash handler, typically setting sys.excepthook to it."""
274 274 self.crash_handler = self.crash_handler_class(self)
275 275 sys.excepthook = self.excepthook
276 276 def unset_crashhandler():
277 277 sys.excepthook = sys.__excepthook__
278 278 atexit.register(unset_crashhandler)
279 279
280 280 def excepthook(self, etype, evalue, tb):
281 281 """this is sys.excepthook after init_crashhandler
282 282
283 283 set self.verbose_crash=True to use our full crashhandler, instead of
284 284 a regular traceback with a short message (crash_handler_lite)
285 285 """
286 286
287 287 if self.verbose_crash:
288 288 return self.crash_handler(etype, evalue, tb)
289 289 else:
290 290 return crashhandler.crash_handler_lite(etype, evalue, tb)
291 291
292 292 @observe('ipython_dir')
293 293 def _ipython_dir_changed(self, change):
294 294 old = change['old']
295 295 new = change['new']
296 296 if old is not Undefined:
297 297 str_old = os.path.abspath(old)
298 298 if str_old in sys.path:
299 299 sys.path.remove(str_old)
300 300 if self.add_ipython_dir_to_sys_path:
301 301 str_path = os.path.abspath(new)
302 302 sys.path.append(str_path)
303 303 ensure_dir_exists(new)
304 304 readme = os.path.join(new, "README")
305 305 readme_src = os.path.join(
306 306 get_ipython_package_dir(), "config", "profile", "README"
307 307 )
308 308 if not os.path.exists(readme) and os.path.exists(readme_src):
309 309 shutil.copy(readme_src, readme)
310 310 for d in ("extensions", "nbextensions"):
311 311 path = os.path.join(new, d)
312 312 try:
313 313 ensure_dir_exists(path)
314 314 except OSError as e:
315 315 # this will not be EEXIST
316 316 self.log.error("couldn't create path %s: %s", path, e)
317 317 self.log.debug("IPYTHONDIR set to: %s", new)
318 318
319 319 def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
320 320 """Load the config file.
321 321
322 322 By default, errors in loading config are handled, and a warning
323 323 printed on screen. For testing, the suppress_errors option is set
324 324 to False, so errors will make tests fail.
325 325
326 326 `suppress_errors` default value is to be `None` in which case the
327 327 behavior default to the one of `traitlets.Application`.
328 328
329 329 The default value can be set :
330 330 - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive).
331 331 - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive).
332 332 - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset.
333 333
334 334 Any other value are invalid, and will make IPython exit with a non-zero return code.
335 335 """
336 336
337 337
338 338 self.log.debug("Searching path %s for config files", self.config_file_paths)
339 339 base_config = 'ipython_config.py'
340 340 self.log.debug("Attempting to load config file: %s" %
341 341 base_config)
342 342 try:
343 343 if suppress_errors is not None:
344 344 old_value = Application.raise_config_file_errors
345 Application.raise_config_file_errors = not suppress_errors
345 Application.raise_config_file_errors = not suppress_errors;
346 346 Application.load_config_file(
347 347 self,
348 348 base_config,
349 349 path=self.config_file_paths
350 350 )
351 351 except ConfigFileNotFound:
352 352 # ignore errors loading parent
353 353 self.log.debug("Config file %s not found", base_config)
354 354 pass
355 355 if suppress_errors is not None:
356 356 Application.raise_config_file_errors = old_value
357 357
358 358 for config_file_name in self.config_files:
359 359 if not config_file_name or config_file_name == base_config:
360 360 continue
361 361 self.log.debug("Attempting to load config file: %s" %
362 362 self.config_file_name)
363 363 try:
364 364 Application.load_config_file(
365 365 self,
366 366 config_file_name,
367 367 path=self.config_file_paths
368 368 )
369 369 except ConfigFileNotFound:
370 370 # Only warn if the default config file was NOT being used.
371 371 if config_file_name in self.config_file_specified:
372 372 msg = self.log.warning
373 373 else:
374 374 msg = self.log.debug
375 375 msg("Config file not found, skipping: %s", config_file_name)
376 376 except Exception:
377 377 # For testing purposes.
378 378 if not suppress_errors:
379 379 raise
380 380 self.log.warning("Error loading config file: %s" %
381 381 self.config_file_name, exc_info=True)
382 382
383 383 def init_profile_dir(self):
384 384 """initialize the profile dir"""
385 385 self._in_init_profile_dir = True
386 386 if self.profile_dir is not None:
387 387 # already ran
388 388 return
389 389 if 'ProfileDir.location' not in self.config:
390 390 # location not specified, find by profile name
391 391 try:
392 392 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
393 393 except ProfileDirError:
394 394 # not found, maybe create it (always create default profile)
395 395 if self.auto_create or self.profile == 'default':
396 396 try:
397 397 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
398 398 except ProfileDirError:
399 399 self.log.fatal("Could not create profile: %r"%self.profile)
400 400 self.exit(1)
401 401 else:
402 402 self.log.info("Created profile dir: %r"%p.location)
403 403 else:
404 404 self.log.fatal("Profile %r not found."%self.profile)
405 405 self.exit(1)
406 406 else:
407 407 self.log.debug("Using existing profile dir: %r", p.location)
408 408 else:
409 409 location = self.config.ProfileDir.location
410 410 # location is fully specified
411 411 try:
412 412 p = ProfileDir.find_profile_dir(location, self.config)
413 413 except ProfileDirError:
414 414 # not found, maybe create it
415 415 if self.auto_create:
416 416 try:
417 417 p = ProfileDir.create_profile_dir(location, self.config)
418 418 except ProfileDirError:
419 419 self.log.fatal("Could not create profile directory: %r"%location)
420 420 self.exit(1)
421 421 else:
422 422 self.log.debug("Creating new profile dir: %r"%location)
423 423 else:
424 424 self.log.fatal("Profile directory %r not found."%location)
425 425 self.exit(1)
426 426 else:
427 427 self.log.debug("Using existing profile dir: %r", p.location)
428 428 # if profile_dir is specified explicitly, set profile name
429 429 dir_name = os.path.basename(p.location)
430 430 if dir_name.startswith('profile_'):
431 431 self.profile = dir_name[8:]
432 432
433 433 self.profile_dir = p
434 434 self.config_file_paths.append(p.location)
435 435 self._in_init_profile_dir = False
436 436
437 437 def init_config_files(self):
438 438 """[optionally] copy default config files into profile dir."""
439 439 self.config_file_paths.extend(ENV_CONFIG_DIRS)
440 440 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
441 441 # copy config files
442 442 path = Path(self.builtin_profile_dir)
443 443 if self.copy_config_files:
444 444 src = self.profile
445 445
446 446 cfg = self.config_file_name
447 447 if path and (path / cfg).exists():
448 448 self.log.warning(
449 449 "Staging %r from %s into %r [overwrite=%s]"
450 450 % (cfg, src, self.profile_dir.location, self.overwrite)
451 451 )
452 452 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
453 453 else:
454 454 self.stage_default_config_file()
455 455 else:
456 456 # Still stage *bundled* config files, but not generated ones
457 457 # This is necessary for `ipython profile=sympy` to load the profile
458 458 # on the first go
459 459 files = path.glob("*.py")
460 460 for fullpath in files:
461 461 cfg = fullpath.name
462 462 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
463 463 # file was copied
464 464 self.log.warning("Staging bundled %s from %s into %r"%(
465 465 cfg, self.profile, self.profile_dir.location)
466 466 )
467 467
468 468
469 469 def stage_default_config_file(self):
470 470 """auto generate default config file, and stage it into the profile."""
471 471 s = self.generate_config_file()
472 472 config_file = Path(self.profile_dir.location) / self.config_file_name
473 473 if self.overwrite or not config_file.exists():
474 474 self.log.warning("Generating default config file: %r", (config_file))
475 475 config_file.write_text(s, encoding="utf-8")
476 476
477 477 @catch_config_error
478 478 def initialize(self, argv=None):
479 479 # don't hook up crash handler before parsing command-line
480 480 self.parse_command_line(argv)
481 481 self.init_crash_handler()
482 482 if self.subapp is not None:
483 483 # stop here if subapp is taking over
484 484 return
485 485 # save a copy of CLI config to re-load after config files
486 486 # so that it has highest priority
487 487 cl_config = deepcopy(self.config)
488 488 self.init_profile_dir()
489 489 self.init_config_files()
490 490 self.load_config_file()
491 491 # enforce cl-opts override configfile opts:
492 492 self.update_config(cl_config)
@@ -1,89 +1,86
1 1 """
2 2 A context manager for managing things injected into :mod:`builtins`.
3 3 """
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6 import builtins as builtin_mod
7 7
8 8 from traitlets.config.configurable import Configurable
9 9
10 10 from traitlets import Instance
11 11
12 12
13 class __BuiltinUndefined:
14 pass
13 class __BuiltinUndefined(object): pass
15 14 BuiltinUndefined = __BuiltinUndefined()
16 15
17
18 class __HideBuiltin:
19 pass
16 class __HideBuiltin(object): pass
20 17 HideBuiltin = __HideBuiltin()
21 18
22 19
23 20 class BuiltinTrap(Configurable):
24 21
25 22 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
26 23 allow_none=True)
27 24
28 25 def __init__(self, shell=None):
29 26 super(BuiltinTrap, self).__init__(shell=shell, config=None)
30 27 self._orig_builtins = {}
31 28 # We define this to track if a single BuiltinTrap is nested.
32 29 # Only turn off the trap when the outermost call to __exit__ is made.
33 30 self._nested_level = 0
34 31 self.shell = shell
35 32 # builtins we always add - if set to HideBuiltin, they will just
36 33 # be removed instead of being replaced by something else
37 34 self.auto_builtins = {'exit': HideBuiltin,
38 35 'quit': HideBuiltin,
39 36 'get_ipython': self.shell.get_ipython,
40 37 }
41 38
42 39 def __enter__(self):
43 40 if self._nested_level == 0:
44 41 self.activate()
45 42 self._nested_level += 1
46 43 # I return self, so callers can use add_builtin in a with clause.
47 44 return self
48 45
49 46 def __exit__(self, type, value, traceback):
50 47 if self._nested_level == 1:
51 48 self.deactivate()
52 49 self._nested_level -= 1
53 50 # Returning False will cause exceptions to propagate
54 51 return False
55 52
56 53 def add_builtin(self, key, value):
57 54 """Add a builtin and save the original."""
58 55 bdict = builtin_mod.__dict__
59 56 orig = bdict.get(key, BuiltinUndefined)
60 57 if value is HideBuiltin:
61 58 if orig is not BuiltinUndefined: #same as 'key in bdict'
62 59 self._orig_builtins[key] = orig
63 60 del bdict[key]
64 61 else:
65 62 self._orig_builtins[key] = orig
66 63 bdict[key] = value
67 64
68 65 def remove_builtin(self, key, orig):
69 66 """Remove an added builtin and re-set the original."""
70 67 if orig is BuiltinUndefined:
71 68 del builtin_mod.__dict__[key]
72 69 else:
73 70 builtin_mod.__dict__[key] = orig
74 71
75 72 def activate(self):
76 73 """Store ipython references in the __builtin__ namespace."""
77 74
78 75 add_builtin = self.add_builtin
79 76 for name, func in self.auto_builtins.items():
80 77 add_builtin(name, func)
81 78
82 79 def deactivate(self):
83 80 """Remove any builtins which might have been added by add_builtins, or
84 81 restore overwritten ones to their previous values."""
85 82 remove_builtin = self.remove_builtin
86 83 for key, val in self._orig_builtins.items():
87 84 remove_builtin(key, val)
88 85 self._orig_builtins.clear()
89 86 self._builtins_added = False
@@ -1,213 +1,214
1 1 """Compiler tools with improved interactive support.
2 2
3 3 Provides compilation machinery similar to codeop, but with caching support so
4 4 we can provide interactive tracebacks.
5 5
6 6 Authors
7 7 -------
8 8 * Robert Kern
9 9 * Fernando Perez
10 10 * Thomas Kluyver
11 11 """
12 12
13 13 # Note: though it might be more natural to name this module 'compiler', that
14 14 # name is in the stdlib and name collisions with the stdlib tend to produce
15 15 # weird problems (often with third-party tools).
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Copyright (C) 2010-2011 The IPython Development Team.
19 19 #
20 20 # Distributed under the terms of the BSD License.
21 21 #
22 22 # The full license is in the file COPYING.txt, distributed with this software.
23 23 #-----------------------------------------------------------------------------
24 24
25 25 #-----------------------------------------------------------------------------
26 26 # Imports
27 27 #-----------------------------------------------------------------------------
28 28
29 29 # Stdlib imports
30 30 import __future__
31 31 from ast import PyCF_ONLY_AST
32 32 import codeop
33 33 import functools
34 34 import hashlib
35 35 import linecache
36 36 import operator
37 import time
37 38 from contextlib import contextmanager
38 39
39 40 #-----------------------------------------------------------------------------
40 41 # Constants
41 42 #-----------------------------------------------------------------------------
42 43
43 44 # Roughly equal to PyCF_MASK | PyCF_MASK_OBSOLETE as defined in pythonrun.h,
44 45 # this is used as a bitmask to extract future-related code flags.
45 46 PyCF_MASK = functools.reduce(operator.or_,
46 47 (getattr(__future__, fname).compiler_flag
47 48 for fname in __future__.all_feature_names))
48 49
49 50 #-----------------------------------------------------------------------------
50 51 # Local utilities
51 52 #-----------------------------------------------------------------------------
52 53
53 54 def code_name(code, number=0):
54 55 """ Compute a (probably) unique name for code for caching.
55 56
56 57 This now expects code to be unicode.
57 58 """
58 59 hash_digest = hashlib.sha1(code.encode("utf-8")).hexdigest()
59 60 # Include the number and 12 characters of the hash in the name. It's
60 61 # pretty much impossible that in a single session we'll have collisions
61 62 # even with truncated hashes, and the full one makes tracebacks too long
62 63 return '<ipython-input-{0}-{1}>'.format(number, hash_digest[:12])
63 64
64 65 #-----------------------------------------------------------------------------
65 66 # Classes and functions
66 67 #-----------------------------------------------------------------------------
67 68
68 69 class CachingCompiler(codeop.Compile):
69 70 """A compiler that caches code compiled from interactive statements.
70 71 """
71 72
72 73 def __init__(self):
73 74 codeop.Compile.__init__(self)
74 75
75 76 # Caching a dictionary { filename: execution_count } for nicely
76 77 # rendered tracebacks. The filename corresponds to the filename
77 78 # argument used for the builtins.compile function.
78 79 self._filename_map = {}
79 80
80 81 def ast_parse(self, source, filename='<unknown>', symbol='exec'):
81 82 """Parse code to an AST with the current compiler flags active.
82 83
83 84 Arguments are exactly the same as ast.parse (in the standard library),
84 85 and are passed to the built-in compile function."""
85 86 return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1)
86 87
87 88 def reset_compiler_flags(self):
88 89 """Reset compiler flags to default state."""
89 90 # This value is copied from codeop.Compile.__init__, so if that ever
90 91 # changes, it will need to be updated.
91 92 self.flags = codeop.PyCF_DONT_IMPLY_DEDENT
92 93
93 94 @property
94 95 def compiler_flags(self):
95 96 """Flags currently active in the compilation process.
96 97 """
97 98 return self.flags
98 99
99 100 def get_code_name(self, raw_code, transformed_code, number):
100 101 """Compute filename given the code, and the cell number.
101 102
102 103 Parameters
103 104 ----------
104 105 raw_code : str
105 106 The raw cell code.
106 107 transformed_code : str
107 108 The executable Python source code to cache and compile.
108 109 number : int
109 110 A number which forms part of the code's name. Used for the execution
110 111 counter.
111 112
112 113 Returns
113 114 -------
114 115 The computed filename.
115 116 """
116 117 return code_name(transformed_code, number)
117 118
118 119 def format_code_name(self, name):
119 120 """Return a user-friendly label and name for a code block.
120 121
121 122 Parameters
122 123 ----------
123 124 name : str
124 125 The name for the code block returned from get_code_name
125 126
126 127 Returns
127 128 -------
128 129 A (label, name) pair that can be used in tracebacks, or None if the default formatting should be used.
129 130 """
130 131 if name in self._filename_map:
131 132 return "Cell", "In[%s]" % self._filename_map[name]
132 133
133 134 def cache(self, transformed_code, number=0, raw_code=None):
134 135 """Make a name for a block of code, and cache the code.
135 136
136 137 Parameters
137 138 ----------
138 139 transformed_code : str
139 140 The executable Python source code to cache and compile.
140 141 number : int
141 142 A number which forms part of the code's name. Used for the execution
142 143 counter.
143 144 raw_code : str
144 145 The raw code before transformation, if None, set to `transformed_code`.
145 146
146 147 Returns
147 148 -------
148 149 The name of the cached code (as a string). Pass this as the filename
149 150 argument to compilation, so that tracebacks are correctly hooked up.
150 151 """
151 152 if raw_code is None:
152 153 raw_code = transformed_code
153 154
154 155 name = self.get_code_name(raw_code, transformed_code, number)
155 156
156 157 # Save the execution count
157 158 self._filename_map[name] = number
158 159
159 160 # Since Python 2.5, setting mtime to `None` means the lines will
160 161 # never be removed by `linecache.checkcache`. This means all the
161 162 # monkeypatching has *never* been necessary, since this code was
162 163 # only added in 2010, at which point IPython had already stopped
163 164 # supporting Python 2.4.
164 165 #
165 166 # Note that `linecache.clearcache` and `linecache.updatecache` may
166 167 # still remove our code from the cache, but those show explicit
167 168 # intent, and we should not try to interfere. Normally the former
168 169 # is never called except when out of memory, and the latter is only
169 170 # called for lines *not* in the cache.
170 171 entry = (
171 172 len(transformed_code),
172 173 None,
173 174 [line + "\n" for line in transformed_code.splitlines()],
174 175 name,
175 176 )
176 177 linecache.cache[name] = entry
177 178 return name
178 179
179 180 @contextmanager
180 181 def extra_flags(self, flags):
181 182 ## bits that we'll set to 1
182 183 turn_on_bits = ~self.flags & flags
183 184
184 185
185 186 self.flags = self.flags | flags
186 187 try:
187 188 yield
188 189 finally:
189 190 # turn off only the bits we turned on so that something like
190 191 # __future__ that set flags stays.
191 192 self.flags &= ~turn_on_bits
192 193
193 194
194 195 def check_linecache_ipython(*args):
195 196 """Deprecated since IPython 8.6. Call linecache.checkcache() directly.
196 197
197 198 It was already not necessary to call this function directly. If no
198 199 CachingCompiler had been created, this function would fail badly. If
199 200 an instance had been created, this function would've been monkeypatched
200 201 into place.
201 202
202 203 As of IPython 8.6, the monkeypatching has gone away entirely. But there
203 204 were still internal callers of this function, so maybe external callers
204 205 also existed?
205 206 """
206 207 import warnings
207 208
208 209 warnings.warn(
209 210 "Deprecated Since IPython 8.6, Just call linecache.checkcache() directly.",
210 211 DeprecationWarning,
211 212 stacklevel=2,
212 213 )
213 214 linecache.checkcache()
@@ -1,3409 +1,3410
1 1 """Completion for IPython.
2 2
3 3 This module started as fork of the rlcompleter module in the Python standard
4 4 library. The original enhancements made to rlcompleter have been sent
5 5 upstream and were accepted as of Python 2.3,
6 6
7 7 This module now support a wide variety of completion mechanism both available
8 8 for normal classic Python code, as well as completer for IPython specific
9 9 Syntax like magics.
10 10
11 11 Latex and Unicode completion
12 12 ============================
13 13
14 14 IPython and compatible frontends not only can complete your code, but can help
15 15 you to input a wide range of characters. In particular we allow you to insert
16 16 a unicode character using the tab completion mechanism.
17 17
18 18 Forward latex/unicode completion
19 19 --------------------------------
20 20
21 21 Forward completion allows you to easily type a unicode character using its latex
22 22 name, or unicode long description. To do so type a backslash follow by the
23 23 relevant name and press tab:
24 24
25 25
26 26 Using latex completion:
27 27
28 28 .. code::
29 29
30 30 \\alpha<tab>
31 31 α
32 32
33 33 or using unicode completion:
34 34
35 35
36 36 .. code::
37 37
38 38 \\GREEK SMALL LETTER ALPHA<tab>
39 39 α
40 40
41 41
42 42 Only valid Python identifiers will complete. Combining characters (like arrow or
43 43 dots) are also available, unlike latex they need to be put after the their
44 44 counterpart that is to say, ``F\\\\vec<tab>`` is correct, not ``\\\\vec<tab>F``.
45 45
46 46 Some browsers are known to display combining characters incorrectly.
47 47
48 48 Backward latex completion
49 49 -------------------------
50 50
51 51 It is sometime challenging to know how to type a character, if you are using
52 52 IPython, or any compatible frontend you can prepend backslash to the character
53 53 and press :kbd:`Tab` to expand it to its latex form.
54 54
55 55 .. code::
56 56
57 57 \\α<tab>
58 58 \\alpha
59 59
60 60
61 61 Both forward and backward completions can be deactivated by setting the
62 62 :std:configtrait:`Completer.backslash_combining_completions` option to
63 63 ``False``.
64 64
65 65
66 66 Experimental
67 67 ============
68 68
69 69 Starting with IPython 6.0, this module can make use of the Jedi library to
70 70 generate completions both using static analysis of the code, and dynamically
71 71 inspecting multiple namespaces. Jedi is an autocompletion and static analysis
72 72 for Python. The APIs attached to this new mechanism is unstable and will
73 73 raise unless use in an :any:`provisionalcompleter` context manager.
74 74
75 75 You will find that the following are experimental:
76 76
77 77 - :any:`provisionalcompleter`
78 78 - :any:`IPCompleter.completions`
79 79 - :any:`Completion`
80 80 - :any:`rectify_completions`
81 81
82 82 .. note::
83 83
84 84 better name for :any:`rectify_completions` ?
85 85
86 86 We welcome any feedback on these new API, and we also encourage you to try this
87 87 module in debug mode (start IPython with ``--Completer.debug=True``) in order
88 88 to have extra logging information if :any:`jedi` is crashing, or if current
89 89 IPython completer pending deprecations are returning results not yet handled
90 90 by :any:`jedi`
91 91
92 92 Using Jedi for tab completion allow snippets like the following to work without
93 93 having to execute any code:
94 94
95 95 >>> myvar = ['hello', 42]
96 96 ... myvar[1].bi<tab>
97 97
98 98 Tab completion will be able to infer that ``myvar[1]`` is a real number without
99 99 executing almost any code unlike the deprecated :any:`IPCompleter.greedy`
100 100 option.
101 101
102 102 Be sure to update :any:`jedi` to the latest stable version or to try the
103 103 current development version to get better completions.
104 104
105 105 Matchers
106 106 ========
107 107
108 108 All completions routines are implemented using unified *Matchers* API.
109 109 The matchers API is provisional and subject to change without notice.
110 110
111 111 The built-in matchers include:
112 112
113 113 - :any:`IPCompleter.dict_key_matcher`: dictionary key completions,
114 114 - :any:`IPCompleter.magic_matcher`: completions for magics,
115 115 - :any:`IPCompleter.unicode_name_matcher`,
116 116 :any:`IPCompleter.fwd_unicode_matcher`
117 117 and :any:`IPCompleter.latex_name_matcher`: see `Forward latex/unicode completion`_,
118 118 - :any:`back_unicode_name_matcher` and :any:`back_latex_name_matcher`: see `Backward latex completion`_,
119 119 - :any:`IPCompleter.file_matcher`: paths to files and directories,
120 120 - :any:`IPCompleter.python_func_kw_matcher` - function keywords,
121 121 - :any:`IPCompleter.python_matches` - globals and attributes (v1 API),
122 122 - ``IPCompleter.jedi_matcher`` - static analysis with Jedi,
123 123 - :any:`IPCompleter.custom_completer_matcher` - pluggable completer with a default
124 124 implementation in :any:`InteractiveShell` which uses IPython hooks system
125 125 (`complete_command`) with string dispatch (including regular expressions).
126 126 Differently to other matchers, ``custom_completer_matcher`` will not suppress
127 127 Jedi results to match behaviour in earlier IPython versions.
128 128
129 129 Custom matchers can be added by appending to ``IPCompleter.custom_matchers`` list.
130 130
131 131 Matcher API
132 132 -----------
133 133
134 134 Simplifying some details, the ``Matcher`` interface can described as
135 135
136 136 .. code-block::
137 137
138 138 MatcherAPIv1 = Callable[[str], list[str]]
139 139 MatcherAPIv2 = Callable[[CompletionContext], SimpleMatcherResult]
140 140
141 141 Matcher = MatcherAPIv1 | MatcherAPIv2
142 142
143 143 The ``MatcherAPIv1`` reflects the matcher API as available prior to IPython 8.6.0
144 144 and remains supported as a simplest way for generating completions. This is also
145 145 currently the only API supported by the IPython hooks system `complete_command`.
146 146
147 147 To distinguish between matcher versions ``matcher_api_version`` attribute is used.
148 148 More precisely, the API allows to omit ``matcher_api_version`` for v1 Matchers,
149 149 and requires a literal ``2`` for v2 Matchers.
150 150
151 151 Once the API stabilises future versions may relax the requirement for specifying
152 152 ``matcher_api_version`` by switching to :any:`functools.singledispatch`, therefore
153 153 please do not rely on the presence of ``matcher_api_version`` for any purposes.
154 154
155 155 Suppression of competing matchers
156 156 ---------------------------------
157 157
158 158 By default results from all matchers are combined, in the order determined by
159 159 their priority. Matchers can request to suppress results from subsequent
160 160 matchers by setting ``suppress`` to ``True`` in the ``MatcherResult``.
161 161
162 162 When multiple matchers simultaneously request suppression, the results from of
163 163 the matcher with higher priority will be returned.
164 164
165 165 Sometimes it is desirable to suppress most but not all other matchers;
166 166 this can be achieved by adding a set of identifiers of matchers which
167 167 should not be suppressed to ``MatcherResult`` under ``do_not_suppress`` key.
168 168
169 169 The suppression behaviour can is user-configurable via
170 170 :std:configtrait:`IPCompleter.suppress_competing_matchers`.
171 171 """
172 172
173 173
174 174 # Copyright (c) IPython Development Team.
175 175 # Distributed under the terms of the Modified BSD License.
176 176 #
177 177 # Some of this code originated from rlcompleter in the Python standard library
178 178 # Copyright (C) 2001 Python Software Foundation, www.python.org
179 179
180 180 from __future__ import annotations
181 181 import builtins as builtin_mod
182 182 import enum
183 183 import glob
184 184 import inspect
185 185 import itertools
186 186 import keyword
187 187 import ast
188 188 import os
189 189 import re
190 190 import string
191 191 import sys
192 192 import tokenize
193 193 import time
194 194 import unicodedata
195 195 import uuid
196 196 import warnings
197 197 from ast import literal_eval
198 198 from collections import defaultdict
199 199 from contextlib import contextmanager
200 200 from dataclasses import dataclass
201 201 from functools import cached_property, partial
202 202 from types import SimpleNamespace
203 203 from typing import (
204 204 Iterable,
205 205 Iterator,
206 206 List,
207 207 Tuple,
208 208 Union,
209 209 Any,
210 210 Sequence,
211 211 Dict,
212 212 Optional,
213 213 TYPE_CHECKING,
214 214 Set,
215 215 Sized,
216 216 TypeVar,
217 217 Literal,
218 218 )
219 219
220 220 from IPython.core.guarded_eval import guarded_eval, EvaluationContext
221 221 from IPython.core.error import TryNext
222 222 from IPython.core.inputtransformer2 import ESC_MAGIC
223 223 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
224 224 from IPython.core.oinspect import InspectColors
225 225 from IPython.testing.skipdoctest import skip_doctest
226 226 from IPython.utils import generics
227 227 from IPython.utils.decorators import sphinx_options
228 228 from IPython.utils.dir2 import dir2, get_real_method
229 from IPython.utils.docs import GENERATING_DOCUMENTATION
229 230 from IPython.utils.path import ensure_dir_exists
230 231 from IPython.utils.process import arg_split
231 232 from traitlets import (
232 233 Bool,
233 234 Enum,
234 235 Int,
235 236 List as ListTrait,
236 237 Unicode,
237 238 Dict as DictTrait,
238 239 Union as UnionTrait,
239 240 observe,
240 241 )
241 242 from traitlets.config.configurable import Configurable
242 243
243 244 import __main__
244 245
245 246 from typing import cast
246 247
247 248 if sys.version_info < (3, 12):
248 249 from typing_extensions import TypedDict, NotRequired, Protocol, TypeAlias, TypeGuard
249 250 else:
250 251 from typing import TypedDict, NotRequired, Protocol, TypeAlias, TypeGuard
251 252
252 253
253 254 # skip module docstests
254 255 __skip_doctest__ = True
255 256
256 257
257 258 try:
258 259 import jedi
259 260 jedi.settings.case_insensitive_completion = False
260 261 import jedi.api.helpers
261 262 import jedi.api.classes
262 263 JEDI_INSTALLED = True
263 264 except ImportError:
264 265 JEDI_INSTALLED = False
265 266
266 267
267 268 # -----------------------------------------------------------------------------
268 269 # Globals
269 270 #-----------------------------------------------------------------------------
270 271
271 272 # ranges where we have most of the valid unicode names. We could be more finer
272 273 # grained but is it worth it for performance While unicode have character in the
273 274 # range 0, 0x110000, we seem to have name for about 10% of those. (131808 as I
274 275 # write this). With below range we cover them all, with a density of ~67%
275 276 # biggest next gap we consider only adds up about 1% density and there are 600
276 277 # gaps that would need hard coding.
277 278 _UNICODE_RANGES = [(32, 0x323B0), (0xE0001, 0xE01F0)]
278 279
279 280 # Public API
280 281 __all__ = ["Completer", "IPCompleter"]
281 282
282 283 if sys.platform == 'win32':
283 284 PROTECTABLES = ' '
284 285 else:
285 286 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
286 287
287 288 # Protect against returning an enormous number of completions which the frontend
288 289 # may have trouble processing.
289 290 MATCHES_LIMIT = 500
290 291
291 292 # Completion type reported when no type can be inferred.
292 293 _UNKNOWN_TYPE = "<unknown>"
293 294
294 295 # sentinel value to signal lack of a match
295 296 not_found = object()
296 297
297 298 class ProvisionalCompleterWarning(FutureWarning):
298 299 """
299 300 Exception raise by an experimental feature in this module.
300 301
301 302 Wrap code in :any:`provisionalcompleter` context manager if you
302 303 are certain you want to use an unstable feature.
303 304 """
304 305 pass
305 306
306 307 warnings.filterwarnings('error', category=ProvisionalCompleterWarning)
307 308
308 309
309 310 @skip_doctest
310 311 @contextmanager
311 312 def provisionalcompleter(action='ignore'):
312 313 """
313 314 This context manager has to be used in any place where unstable completer
314 315 behavior and API may be called.
315 316
316 317 >>> with provisionalcompleter():
317 318 ... completer.do_experimental_things() # works
318 319
319 320 >>> completer.do_experimental_things() # raises.
320 321
321 322 .. note::
322 323
323 324 Unstable
324 325
325 326 By using this context manager you agree that the API in use may change
326 327 without warning, and that you won't complain if they do so.
327 328
328 329 You also understand that, if the API is not to your liking, you should report
329 330 a bug to explain your use case upstream.
330 331
331 332 We'll be happy to get your feedback, feature requests, and improvements on
332 333 any of the unstable APIs!
333 334 """
334 335 with warnings.catch_warnings():
335 336 warnings.filterwarnings(action, category=ProvisionalCompleterWarning)
336 337 yield
337 338
338 339
339 340 def has_open_quotes(s: str) -> Union[str, bool]:
340 341 """Return whether a string has open quotes.
341 342
342 343 This simply counts whether the number of quote characters of either type in
343 344 the string is odd.
344 345
345 346 Returns
346 347 -------
347 348 If there is an open quote, the quote character is returned. Else, return
348 349 False.
349 350 """
350 351 # We check " first, then ', so complex cases with nested quotes will get
351 352 # the " to take precedence.
352 353 if s.count('"') % 2:
353 354 return '"'
354 355 elif s.count("'") % 2:
355 356 return "'"
356 357 else:
357 358 return False
358 359
359 360
360 361 def protect_filename(s: str, protectables: str = PROTECTABLES) -> str:
361 362 """Escape a string to protect certain characters."""
362 363 if set(s) & set(protectables):
363 364 if sys.platform == "win32":
364 365 return '"' + s + '"'
365 366 else:
366 367 return "".join(("\\" + c if c in protectables else c) for c in s)
367 368 else:
368 369 return s
369 370
370 371
371 372 def expand_user(path:str) -> Tuple[str, bool, str]:
372 373 """Expand ``~``-style usernames in strings.
373 374
374 375 This is similar to :func:`os.path.expanduser`, but it computes and returns
375 376 extra information that will be useful if the input was being used in
376 377 computing completions, and you wish to return the completions with the
377 378 original '~' instead of its expanded value.
378 379
379 380 Parameters
380 381 ----------
381 382 path : str
382 383 String to be expanded. If no ~ is present, the output is the same as the
383 384 input.
384 385
385 386 Returns
386 387 -------
387 388 newpath : str
388 389 Result of ~ expansion in the input path.
389 390 tilde_expand : bool
390 391 Whether any expansion was performed or not.
391 392 tilde_val : str
392 393 The value that ~ was replaced with.
393 394 """
394 395 # Default values
395 396 tilde_expand = False
396 397 tilde_val = ''
397 398 newpath = path
398 399
399 400 if path.startswith('~'):
400 401 tilde_expand = True
401 402 rest = len(path)-1
402 403 newpath = os.path.expanduser(path)
403 404 if rest:
404 405 tilde_val = newpath[:-rest]
405 406 else:
406 407 tilde_val = newpath
407 408
408 409 return newpath, tilde_expand, tilde_val
409 410
410 411
411 412 def compress_user(path:str, tilde_expand:bool, tilde_val:str) -> str:
412 413 """Does the opposite of expand_user, with its outputs.
413 414 """
414 415 if tilde_expand:
415 416 return path.replace(tilde_val, '~')
416 417 else:
417 418 return path
418 419
419 420
420 421 def completions_sorting_key(word):
421 422 """key for sorting completions
422 423
423 424 This does several things:
424 425
425 426 - Demote any completions starting with underscores to the end
426 427 - Insert any %magic and %%cellmagic completions in the alphabetical order
427 428 by their name
428 429 """
429 430 prio1, prio2 = 0, 0
430 431
431 432 if word.startswith('__'):
432 433 prio1 = 2
433 434 elif word.startswith('_'):
434 435 prio1 = 1
435 436
436 437 if word.endswith('='):
437 438 prio1 = -1
438 439
439 440 if word.startswith('%%'):
440 441 # If there's another % in there, this is something else, so leave it alone
441 442 if "%" not in word[2:]:
442 443 word = word[2:]
443 444 prio2 = 2
444 445 elif word.startswith('%'):
445 446 if "%" not in word[1:]:
446 447 word = word[1:]
447 448 prio2 = 1
448 449
449 450 return prio1, word, prio2
450 451
451 452
452 453 class _FakeJediCompletion:
453 454 """
454 455 This is a workaround to communicate to the UI that Jedi has crashed and to
455 456 report a bug. Will be used only id :any:`IPCompleter.debug` is set to true.
456 457
457 458 Added in IPython 6.0 so should likely be removed for 7.0
458 459
459 460 """
460 461
461 462 def __init__(self, name):
462 463
463 464 self.name = name
464 465 self.complete = name
465 466 self.type = 'crashed'
466 467 self.name_with_symbols = name
467 468 self.signature = ""
468 469 self._origin = "fake"
469 470 self.text = "crashed"
470 471
471 472 def __repr__(self):
472 473 return '<Fake completion object jedi has crashed>'
473 474
474 475
475 476 _JediCompletionLike = Union["jedi.api.Completion", _FakeJediCompletion]
476 477
477 478
478 479 class Completion:
479 480 """
480 481 Completion object used and returned by IPython completers.
481 482
482 483 .. warning::
483 484
484 485 Unstable
485 486
486 487 This function is unstable, API may change without warning.
487 488 It will also raise unless use in proper context manager.
488 489
489 490 This act as a middle ground :any:`Completion` object between the
490 491 :any:`jedi.api.classes.Completion` object and the Prompt Toolkit completion
491 492 object. While Jedi need a lot of information about evaluator and how the
492 493 code should be ran/inspected, PromptToolkit (and other frontend) mostly
493 494 need user facing information.
494 495
495 496 - Which range should be replaced replaced by what.
496 497 - Some metadata (like completion type), or meta information to displayed to
497 498 the use user.
498 499
499 500 For debugging purpose we can also store the origin of the completion (``jedi``,
500 501 ``IPython.python_matches``, ``IPython.magics_matches``...).
501 502 """
502 503
503 504 __slots__ = ['start', 'end', 'text', 'type', 'signature', '_origin']
504 505
505 506 def __init__(
506 507 self,
507 508 start: int,
508 509 end: int,
509 510 text: str,
510 511 *,
511 512 type: Optional[str] = None,
512 513 _origin="",
513 514 signature="",
514 515 ) -> None:
515 516 warnings.warn(
516 517 "``Completion`` is a provisional API (as of IPython 6.0). "
517 518 "It may change without warnings. "
518 519 "Use in corresponding context manager.",
519 520 category=ProvisionalCompleterWarning,
520 521 stacklevel=2,
521 522 )
522 523
523 524 self.start = start
524 525 self.end = end
525 526 self.text = text
526 527 self.type = type
527 528 self.signature = signature
528 529 self._origin = _origin
529 530
530 531 def __repr__(self):
531 532 return '<Completion start=%s end=%s text=%r type=%r, signature=%r,>' % \
532 533 (self.start, self.end, self.text, self.type or '?', self.signature or '?')
533 534
534 535 def __eq__(self, other) -> bool:
535 536 """
536 537 Equality and hash do not hash the type (as some completer may not be
537 538 able to infer the type), but are use to (partially) de-duplicate
538 539 completion.
539 540
540 541 Completely de-duplicating completion is a bit tricker that just
541 542 comparing as it depends on surrounding text, which Completions are not
542 543 aware of.
543 544 """
544 545 return self.start == other.start and \
545 546 self.end == other.end and \
546 547 self.text == other.text
547 548
548 549 def __hash__(self):
549 550 return hash((self.start, self.end, self.text))
550 551
551 552
552 553 class SimpleCompletion:
553 554 """Completion item to be included in the dictionary returned by new-style Matcher (API v2).
554 555
555 556 .. warning::
556 557
557 558 Provisional
558 559
559 560 This class is used to describe the currently supported attributes of
560 561 simple completion items, and any additional implementation details
561 562 should not be relied on. Additional attributes may be included in
562 563 future versions, and meaning of text disambiguated from the current
563 564 dual meaning of "text to insert" and "text to used as a label".
564 565 """
565 566
566 567 __slots__ = ["text", "type"]
567 568
568 569 def __init__(self, text: str, *, type: Optional[str] = None):
569 570 self.text = text
570 571 self.type = type
571 572
572 573 def __repr__(self):
573 574 return f"<SimpleCompletion text={self.text!r} type={self.type!r}>"
574 575
575 576
576 577 class _MatcherResultBase(TypedDict):
577 578 """Definition of dictionary to be returned by new-style Matcher (API v2)."""
578 579
579 580 #: Suffix of the provided ``CompletionContext.token``, if not given defaults to full token.
580 581 matched_fragment: NotRequired[str]
581 582
582 583 #: Whether to suppress results from all other matchers (True), some
583 584 #: matchers (set of identifiers) or none (False); default is False.
584 585 suppress: NotRequired[Union[bool, Set[str]]]
585 586
586 587 #: Identifiers of matchers which should NOT be suppressed when this matcher
587 588 #: requests to suppress all other matchers; defaults to an empty set.
588 589 do_not_suppress: NotRequired[Set[str]]
589 590
590 591 #: Are completions already ordered and should be left as-is? default is False.
591 592 ordered: NotRequired[bool]
592 593
593 594
594 595 @sphinx_options(show_inherited_members=True, exclude_inherited_from=["dict"])
595 596 class SimpleMatcherResult(_MatcherResultBase, TypedDict):
596 597 """Result of new-style completion matcher."""
597 598
598 599 # note: TypedDict is added again to the inheritance chain
599 600 # in order to get __orig_bases__ for documentation
600 601
601 602 #: List of candidate completions
602 603 completions: Sequence[SimpleCompletion] | Iterator[SimpleCompletion]
603 604
604 605
605 606 class _JediMatcherResult(_MatcherResultBase):
606 607 """Matching result returned by Jedi (will be processed differently)"""
607 608
608 609 #: list of candidate completions
609 610 completions: Iterator[_JediCompletionLike]
610 611
611 612
612 613 AnyMatcherCompletion = Union[_JediCompletionLike, SimpleCompletion]
613 614 AnyCompletion = TypeVar("AnyCompletion", AnyMatcherCompletion, Completion)
614 615
615 616
616 617 @dataclass
617 618 class CompletionContext:
618 619 """Completion context provided as an argument to matchers in the Matcher API v2."""
619 620
620 621 # rationale: many legacy matchers relied on completer state (`self.text_until_cursor`)
621 622 # which was not explicitly visible as an argument of the matcher, making any refactor
622 623 # prone to errors; by explicitly passing `cursor_position` we can decouple the matchers
623 624 # from the completer, and make substituting them in sub-classes easier.
624 625
625 626 #: Relevant fragment of code directly preceding the cursor.
626 627 #: The extraction of token is implemented via splitter heuristic
627 628 #: (following readline behaviour for legacy reasons), which is user configurable
628 629 #: (by switching the greedy mode).
629 630 token: str
630 631
631 632 #: The full available content of the editor or buffer
632 633 full_text: str
633 634
634 635 #: Cursor position in the line (the same for ``full_text`` and ``text``).
635 636 cursor_position: int
636 637
637 638 #: Cursor line in ``full_text``.
638 639 cursor_line: int
639 640
640 641 #: The maximum number of completions that will be used downstream.
641 642 #: Matchers can use this information to abort early.
642 643 #: The built-in Jedi matcher is currently excepted from this limit.
643 644 # If not given, return all possible completions.
644 645 limit: Optional[int]
645 646
646 647 @cached_property
647 648 def text_until_cursor(self) -> str:
648 649 return self.line_with_cursor[: self.cursor_position]
649 650
650 651 @cached_property
651 652 def line_with_cursor(self) -> str:
652 653 return self.full_text.split("\n")[self.cursor_line]
653 654
654 655
655 656 #: Matcher results for API v2.
656 657 MatcherResult = Union[SimpleMatcherResult, _JediMatcherResult]
657 658
658 659
659 660 class _MatcherAPIv1Base(Protocol):
660 661 def __call__(self, text: str) -> List[str]:
661 662 """Call signature."""
662 663 ...
663 664
664 665 #: Used to construct the default matcher identifier
665 666 __qualname__: str
666 667
667 668
668 669 class _MatcherAPIv1Total(_MatcherAPIv1Base, Protocol):
669 670 #: API version
670 671 matcher_api_version: Optional[Literal[1]]
671 672
672 673 def __call__(self, text: str) -> List[str]:
673 674 """Call signature."""
674 675 ...
675 676
676 677
677 678 #: Protocol describing Matcher API v1.
678 679 MatcherAPIv1: TypeAlias = Union[_MatcherAPIv1Base, _MatcherAPIv1Total]
679 680
680 681
681 682 class MatcherAPIv2(Protocol):
682 683 """Protocol describing Matcher API v2."""
683 684
684 685 #: API version
685 686 matcher_api_version: Literal[2] = 2
686 687
687 688 def __call__(self, context: CompletionContext) -> MatcherResult:
688 689 """Call signature."""
689 690 ...
690 691
691 692 #: Used to construct the default matcher identifier
692 693 __qualname__: str
693 694
694 695
695 696 Matcher: TypeAlias = Union[MatcherAPIv1, MatcherAPIv2]
696 697
697 698
698 699 def _is_matcher_v1(matcher: Matcher) -> TypeGuard[MatcherAPIv1]:
699 700 api_version = _get_matcher_api_version(matcher)
700 701 return api_version == 1
701 702
702 703
703 704 def _is_matcher_v2(matcher: Matcher) -> TypeGuard[MatcherAPIv2]:
704 705 api_version = _get_matcher_api_version(matcher)
705 706 return api_version == 2
706 707
707 708
708 709 def _is_sizable(value: Any) -> TypeGuard[Sized]:
709 710 """Determines whether objects is sizable"""
710 711 return hasattr(value, "__len__")
711 712
712 713
713 714 def _is_iterator(value: Any) -> TypeGuard[Iterator]:
714 715 """Determines whether objects is sizable"""
715 716 return hasattr(value, "__next__")
716 717
717 718
718 719 def has_any_completions(result: MatcherResult) -> bool:
719 720 """Check if any result includes any completions."""
720 721 completions = result["completions"]
721 722 if _is_sizable(completions):
722 723 return len(completions) != 0
723 724 if _is_iterator(completions):
724 725 try:
725 726 old_iterator = completions
726 727 first = next(old_iterator)
727 728 result["completions"] = cast(
728 729 Iterator[SimpleCompletion],
729 730 itertools.chain([first], old_iterator),
730 731 )
731 732 return True
732 733 except StopIteration:
733 734 return False
734 735 raise ValueError(
735 736 "Completions returned by matcher need to be an Iterator or a Sizable"
736 737 )
737 738
738 739
739 740 def completion_matcher(
740 741 *,
741 742 priority: Optional[float] = None,
742 743 identifier: Optional[str] = None,
743 744 api_version: int = 1,
744 745 ) -> Callable[[Matcher], Matcher]:
745 746 """Adds attributes describing the matcher.
746 747
747 748 Parameters
748 749 ----------
749 750 priority : Optional[float]
750 751 The priority of the matcher, determines the order of execution of matchers.
751 752 Higher priority means that the matcher will be executed first. Defaults to 0.
752 753 identifier : Optional[str]
753 754 identifier of the matcher allowing users to modify the behaviour via traitlets,
754 755 and also used to for debugging (will be passed as ``origin`` with the completions).
755 756
756 757 Defaults to matcher function's ``__qualname__`` (for example,
757 758 ``IPCompleter.file_matcher`` for the built-in matched defined
758 759 as a ``file_matcher`` method of the ``IPCompleter`` class).
759 760 api_version: Optional[int]
760 761 version of the Matcher API used by this matcher.
761 762 Currently supported values are 1 and 2.
762 763 Defaults to 1.
763 764 """
764 765
765 766 def wrapper(func: Matcher):
766 767 func.matcher_priority = priority or 0 # type: ignore
767 768 func.matcher_identifier = identifier or func.__qualname__ # type: ignore
768 769 func.matcher_api_version = api_version # type: ignore
769 770 if TYPE_CHECKING:
770 771 if api_version == 1:
771 772 func = cast(MatcherAPIv1, func)
772 773 elif api_version == 2:
773 774 func = cast(MatcherAPIv2, func)
774 775 return func
775 776
776 777 return wrapper
777 778
778 779
779 780 def _get_matcher_priority(matcher: Matcher):
780 781 return getattr(matcher, "matcher_priority", 0)
781 782
782 783
783 784 def _get_matcher_id(matcher: Matcher):
784 785 return getattr(matcher, "matcher_identifier", matcher.__qualname__)
785 786
786 787
787 788 def _get_matcher_api_version(matcher):
788 789 return getattr(matcher, "matcher_api_version", 1)
789 790
790 791
791 792 context_matcher = partial(completion_matcher, api_version=2)
792 793
793 794
794 795 _IC = Iterable[Completion]
795 796
796 797
797 798 def _deduplicate_completions(text: str, completions: _IC)-> _IC:
798 799 """
799 800 Deduplicate a set of completions.
800 801
801 802 .. warning::
802 803
803 804 Unstable
804 805
805 806 This function is unstable, API may change without warning.
806 807
807 808 Parameters
808 809 ----------
809 810 text : str
810 811 text that should be completed.
811 812 completions : Iterator[Completion]
812 813 iterator over the completions to deduplicate
813 814
814 815 Yields
815 816 ------
816 817 `Completions` objects
817 818 Completions coming from multiple sources, may be different but end up having
818 819 the same effect when applied to ``text``. If this is the case, this will
819 820 consider completions as equal and only emit the first encountered.
820 821 Not folded in `completions()` yet for debugging purpose, and to detect when
821 822 the IPython completer does return things that Jedi does not, but should be
822 823 at some point.
823 824 """
824 825 completions = list(completions)
825 826 if not completions:
826 827 return
827 828
828 829 new_start = min(c.start for c in completions)
829 830 new_end = max(c.end for c in completions)
830 831
831 832 seen = set()
832 833 for c in completions:
833 834 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
834 835 if new_text not in seen:
835 836 yield c
836 837 seen.add(new_text)
837 838
838 839
839 840 def rectify_completions(text: str, completions: _IC, *, _debug: bool = False) -> _IC:
840 841 """
841 842 Rectify a set of completions to all have the same ``start`` and ``end``
842 843
843 844 .. warning::
844 845
845 846 Unstable
846 847
847 848 This function is unstable, API may change without warning.
848 849 It will also raise unless use in proper context manager.
849 850
850 851 Parameters
851 852 ----------
852 853 text : str
853 854 text that should be completed.
854 855 completions : Iterator[Completion]
855 856 iterator over the completions to rectify
856 857 _debug : bool
857 858 Log failed completion
858 859
859 860 Notes
860 861 -----
861 862 :any:`jedi.api.classes.Completion` s returned by Jedi may not have the same start and end, though
862 863 the Jupyter Protocol requires them to behave like so. This will readjust
863 864 the completion to have the same ``start`` and ``end`` by padding both
864 865 extremities with surrounding text.
865 866
866 867 During stabilisation should support a ``_debug`` option to log which
867 868 completion are return by the IPython completer and not found in Jedi in
868 869 order to make upstream bug report.
869 870 """
870 871 warnings.warn("`rectify_completions` is a provisional API (as of IPython 6.0). "
871 872 "It may change without warnings. "
872 873 "Use in corresponding context manager.",
873 874 category=ProvisionalCompleterWarning, stacklevel=2)
874 875
875 876 completions = list(completions)
876 877 if not completions:
877 878 return
878 879 starts = (c.start for c in completions)
879 880 ends = (c.end for c in completions)
880 881
881 882 new_start = min(starts)
882 883 new_end = max(ends)
883 884
884 885 seen_jedi = set()
885 886 seen_python_matches = set()
886 887 for c in completions:
887 888 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
888 889 if c._origin == 'jedi':
889 890 seen_jedi.add(new_text)
890 891 elif c._origin == "IPCompleter.python_matcher":
891 892 seen_python_matches.add(new_text)
892 893 yield Completion(new_start, new_end, new_text, type=c.type, _origin=c._origin, signature=c.signature)
893 894 diff = seen_python_matches.difference(seen_jedi)
894 895 if diff and _debug:
895 896 print('IPython.python matches have extras:', diff)
896 897
897 898
898 899 if sys.platform == 'win32':
899 900 DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?'
900 901 else:
901 902 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
902 903
903 904 GREEDY_DELIMS = ' =\r\n'
904 905
905 906
906 907 class CompletionSplitter(object):
907 908 """An object to split an input line in a manner similar to readline.
908 909
909 910 By having our own implementation, we can expose readline-like completion in
910 911 a uniform manner to all frontends. This object only needs to be given the
911 912 line of text to be split and the cursor position on said line, and it
912 913 returns the 'word' to be completed on at the cursor after splitting the
913 914 entire line.
914 915
915 916 What characters are used as splitting delimiters can be controlled by
916 917 setting the ``delims`` attribute (this is a property that internally
917 918 automatically builds the necessary regular expression)"""
918 919
919 920 # Private interface
920 921
921 922 # A string of delimiter characters. The default value makes sense for
922 923 # IPython's most typical usage patterns.
923 924 _delims = DELIMS
924 925
925 926 # The expression (a normal string) to be compiled into a regular expression
926 927 # for actual splitting. We store it as an attribute mostly for ease of
927 928 # debugging, since this type of code can be so tricky to debug.
928 929 _delim_expr = None
929 930
930 931 # The regular expression that does the actual splitting
931 932 _delim_re = None
932 933
933 934 def __init__(self, delims=None):
934 935 delims = CompletionSplitter._delims if delims is None else delims
935 936 self.delims = delims
936 937
937 938 @property
938 939 def delims(self):
939 940 """Return the string of delimiter characters."""
940 941 return self._delims
941 942
942 943 @delims.setter
943 944 def delims(self, delims):
944 945 """Set the delimiters for line splitting."""
945 946 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
946 947 self._delim_re = re.compile(expr)
947 948 self._delims = delims
948 949 self._delim_expr = expr
949 950
950 951 def split_line(self, line, cursor_pos=None):
951 952 """Split a line of text with a cursor at the given position.
952 953 """
953 954 cut_line = line if cursor_pos is None else line[:cursor_pos]
954 955 return self._delim_re.split(cut_line)[-1]
955 956
956 957
957 958
958 959 class Completer(Configurable):
959 960
960 961 greedy = Bool(
961 962 False,
962 963 help="""Activate greedy completion.
963 964
964 965 .. deprecated:: 8.8
965 966 Use :std:configtrait:`Completer.evaluation` and :std:configtrait:`Completer.auto_close_dict_keys` instead.
966 967
967 968 When enabled in IPython 8.8 or newer, changes configuration as follows:
968 969
969 970 - ``Completer.evaluation = 'unsafe'``
970 971 - ``Completer.auto_close_dict_keys = True``
971 972 """,
972 973 ).tag(config=True)
973 974
974 975 evaluation = Enum(
975 976 ("forbidden", "minimal", "limited", "unsafe", "dangerous"),
976 977 default_value="limited",
977 978 help="""Policy for code evaluation under completion.
978 979
979 980 Successive options allow to enable more eager evaluation for better
980 981 completion suggestions, including for nested dictionaries, nested lists,
981 982 or even results of function calls.
982 983 Setting ``unsafe`` or higher can lead to evaluation of arbitrary user
983 984 code on :kbd:`Tab` with potentially unwanted or dangerous side effects.
984 985
985 986 Allowed values are:
986 987
987 988 - ``forbidden``: no evaluation of code is permitted,
988 989 - ``minimal``: evaluation of literals and access to built-in namespace;
989 990 no item/attribute evaluationm no access to locals/globals,
990 991 no evaluation of any operations or comparisons.
991 992 - ``limited``: access to all namespaces, evaluation of hard-coded methods
992 993 (for example: :any:`dict.keys`, :any:`object.__getattr__`,
993 994 :any:`object.__getitem__`) on allow-listed objects (for example:
994 995 :any:`dict`, :any:`list`, :any:`tuple`, ``pandas.Series``),
995 996 - ``unsafe``: evaluation of all methods and function calls but not of
996 997 syntax with side-effects like `del x`,
997 998 - ``dangerous``: completely arbitrary evaluation.
998 999 """,
999 1000 ).tag(config=True)
1000 1001
1001 1002 use_jedi = Bool(default_value=JEDI_INSTALLED,
1002 1003 help="Experimental: Use Jedi to generate autocompletions. "
1003 1004 "Default to True if jedi is installed.").tag(config=True)
1004 1005
1005 1006 jedi_compute_type_timeout = Int(default_value=400,
1006 1007 help="""Experimental: restrict time (in milliseconds) during which Jedi can compute types.
1007 1008 Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt
1008 1009 performance by preventing jedi to build its cache.
1009 1010 """).tag(config=True)
1010 1011
1011 1012 debug = Bool(default_value=False,
1012 1013 help='Enable debug for the Completer. Mostly print extra '
1013 1014 'information for experimental jedi integration.')\
1014 1015 .tag(config=True)
1015 1016
1016 1017 backslash_combining_completions = Bool(True,
1017 1018 help="Enable unicode completions, e.g. \\alpha<tab> . "
1018 1019 "Includes completion of latex commands, unicode names, and expanding "
1019 1020 "unicode characters back to latex commands.").tag(config=True)
1020 1021
1021 1022 auto_close_dict_keys = Bool(
1022 1023 False,
1023 1024 help="""
1024 1025 Enable auto-closing dictionary keys.
1025 1026
1026 1027 When enabled string keys will be suffixed with a final quote
1027 1028 (matching the opening quote), tuple keys will also receive a
1028 1029 separating comma if needed, and keys which are final will
1029 1030 receive a closing bracket (``]``).
1030 1031 """,
1031 1032 ).tag(config=True)
1032 1033
1033 1034 def __init__(self, namespace=None, global_namespace=None, **kwargs):
1034 1035 """Create a new completer for the command line.
1035 1036
1036 1037 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
1037 1038
1038 1039 If unspecified, the default namespace where completions are performed
1039 1040 is __main__ (technically, __main__.__dict__). Namespaces should be
1040 1041 given as dictionaries.
1041 1042
1042 1043 An optional second namespace can be given. This allows the completer
1043 1044 to handle cases where both the local and global scopes need to be
1044 1045 distinguished.
1045 1046 """
1046 1047
1047 1048 # Don't bind to namespace quite yet, but flag whether the user wants a
1048 1049 # specific namespace or to use __main__.__dict__. This will allow us
1049 1050 # to bind to __main__.__dict__ at completion time, not now.
1050 1051 if namespace is None:
1051 1052 self.use_main_ns = True
1052 1053 else:
1053 1054 self.use_main_ns = False
1054 1055 self.namespace = namespace
1055 1056
1056 1057 # The global namespace, if given, can be bound directly
1057 1058 if global_namespace is None:
1058 1059 self.global_namespace = {}
1059 1060 else:
1060 1061 self.global_namespace = global_namespace
1061 1062
1062 1063 self.custom_matchers = []
1063 1064
1064 1065 super(Completer, self).__init__(**kwargs)
1065 1066
1066 1067 def complete(self, text, state):
1067 1068 """Return the next possible completion for 'text'.
1068 1069
1069 1070 This is called successively with state == 0, 1, 2, ... until it
1070 1071 returns None. The completion should begin with 'text'.
1071 1072
1072 1073 """
1073 1074 if self.use_main_ns:
1074 1075 self.namespace = __main__.__dict__
1075 1076
1076 1077 if state == 0:
1077 1078 if "." in text:
1078 1079 self.matches = self.attr_matches(text)
1079 1080 else:
1080 1081 self.matches = self.global_matches(text)
1081 1082 try:
1082 1083 return self.matches[state]
1083 1084 except IndexError:
1084 1085 return None
1085 1086
1086 1087 def global_matches(self, text):
1087 1088 """Compute matches when text is a simple name.
1088 1089
1089 1090 Return a list of all keywords, built-in functions and names currently
1090 1091 defined in self.namespace or self.global_namespace that match.
1091 1092
1092 1093 """
1093 1094 matches = []
1094 1095 match_append = matches.append
1095 1096 n = len(text)
1096 1097 for lst in [
1097 1098 keyword.kwlist,
1098 1099 builtin_mod.__dict__.keys(),
1099 1100 list(self.namespace.keys()),
1100 1101 list(self.global_namespace.keys()),
1101 1102 ]:
1102 1103 for word in lst:
1103 1104 if word[:n] == text and word != "__builtins__":
1104 1105 match_append(word)
1105 1106
1106 1107 snake_case_re = re.compile(r"[^_]+(_[^_]+)+?\Z")
1107 1108 for lst in [list(self.namespace.keys()), list(self.global_namespace.keys())]:
1108 1109 shortened = {
1109 1110 "_".join([sub[0] for sub in word.split("_")]): word
1110 1111 for word in lst
1111 1112 if snake_case_re.match(word)
1112 1113 }
1113 1114 for word in shortened.keys():
1114 1115 if word[:n] == text and word != "__builtins__":
1115 1116 match_append(shortened[word])
1116 1117 return matches
1117 1118
1118 1119 def attr_matches(self, text):
1119 1120 """Compute matches when text contains a dot.
1120 1121
1121 1122 Assuming the text is of the form NAME.NAME....[NAME], and is
1122 1123 evaluatable in self.namespace or self.global_namespace, it will be
1123 1124 evaluated and its attributes (as revealed by dir()) are used as
1124 1125 possible completions. (For class instances, class members are
1125 1126 also considered.)
1126 1127
1127 1128 WARNING: this can still invoke arbitrary C code, if an object
1128 1129 with a __getattr__ hook is evaluated.
1129 1130
1130 1131 """
1131 1132 return self._attr_matches(text)[0]
1132 1133
1133 1134 # we simple attribute matching with normal identifiers.
1134 1135 _ATTR_MATCH_RE = re.compile(r"(.+)\.(\w*)$")
1135 1136
1136 1137 def _attr_matches(
1137 1138 self, text: str, include_prefix: bool = True
1138 1139 ) -> Tuple[Sequence[str], str]:
1139 1140 m2 = self._ATTR_MATCH_RE.match(self.line_buffer)
1140 1141 if not m2:
1141 1142 return [], ""
1142 1143 expr, attr = m2.group(1, 2)
1143 1144
1144 1145 obj = self._evaluate_expr(expr)
1145 1146
1146 1147 if obj is not_found:
1147 1148 return [], ""
1148 1149
1149 1150 if self.limit_to__all__ and hasattr(obj, '__all__'):
1150 1151 words = get__all__entries(obj)
1151 1152 else:
1152 1153 words = dir2(obj)
1153 1154
1154 1155 try:
1155 1156 words = generics.complete_object(obj, words)
1156 1157 except TryNext:
1157 1158 pass
1158 1159 except AssertionError:
1159 1160 raise
1160 1161 except Exception:
1161 1162 # Silence errors from completion function
1162 1163 pass
1163 1164 # Build match list to return
1164 1165 n = len(attr)
1165 1166
1166 1167 # Note: ideally we would just return words here and the prefix
1167 1168 # reconciliator would know that we intend to append to rather than
1168 1169 # replace the input text; this requires refactoring to return range
1169 1170 # which ought to be replaced (as does jedi).
1170 1171 if include_prefix:
1171 1172 tokens = _parse_tokens(expr)
1172 1173 rev_tokens = reversed(tokens)
1173 1174 skip_over = {tokenize.ENDMARKER, tokenize.NEWLINE}
1174 1175 name_turn = True
1175 1176
1176 1177 parts = []
1177 1178 for token in rev_tokens:
1178 1179 if token.type in skip_over:
1179 1180 continue
1180 1181 if token.type == tokenize.NAME and name_turn:
1181 1182 parts.append(token.string)
1182 1183 name_turn = False
1183 1184 elif (
1184 1185 token.type == tokenize.OP and token.string == "." and not name_turn
1185 1186 ):
1186 1187 parts.append(token.string)
1187 1188 name_turn = True
1188 1189 else:
1189 1190 # short-circuit if not empty nor name token
1190 1191 break
1191 1192
1192 1193 prefix_after_space = "".join(reversed(parts))
1193 1194 else:
1194 1195 prefix_after_space = ""
1195 1196
1196 1197 return (
1197 1198 ["%s.%s" % (prefix_after_space, w) for w in words if w[:n] == attr],
1198 1199 "." + attr,
1199 1200 )
1200 1201
1201 1202 def _trim_expr(self, code: str) -> str:
1202 1203 """
1203 1204 Trim the code until it is a valid expression and not a tuple;
1204 1205
1205 1206 return the trimmed expression for guarded_eval.
1206 1207 """
1207 1208 while code:
1208 1209 code = code[1:]
1209 1210 try:
1210 1211 res = ast.parse(code)
1211 1212 except SyntaxError:
1212 1213 continue
1213 1214
1214 1215 assert res is not None
1215 1216 if len(res.body) != 1:
1216 1217 continue
1217 1218 expr = res.body[0].value
1218 1219 if isinstance(expr, ast.Tuple) and not code[-1] == ")":
1219 1220 # we skip implicit tuple, like when trimming `fun(a,b`<completion>
1220 1221 # as `a,b` would be a tuple, and we actually expect to get only `b`
1221 1222 continue
1222 1223 return code
1223 1224 return ""
1224 1225
1225 1226 def _evaluate_expr(self, expr):
1226 1227 obj = not_found
1227 1228 done = False
1228 1229 while not done and expr:
1229 1230 try:
1230 1231 obj = guarded_eval(
1231 1232 expr,
1232 1233 EvaluationContext(
1233 1234 globals=self.global_namespace,
1234 1235 locals=self.namespace,
1235 1236 evaluation=self.evaluation,
1236 1237 ),
1237 1238 )
1238 1239 done = True
1239 1240 except Exception as e:
1240 1241 if self.debug:
1241 1242 print("Evaluation exception", e)
1242 1243 # trim the expression to remove any invalid prefix
1243 1244 # e.g. user starts `(d[`, so we get `expr = '(d'`,
1244 1245 # where parenthesis is not closed.
1245 1246 # TODO: make this faster by reusing parts of the computation?
1246 1247 expr = self._trim_expr(expr)
1247 1248 return obj
1248 1249
1249 1250 def get__all__entries(obj):
1250 1251 """returns the strings in the __all__ attribute"""
1251 1252 try:
1252 1253 words = getattr(obj, '__all__')
1253 1254 except Exception:
1254 1255 return []
1255 1256
1256 1257 return [w for w in words if isinstance(w, str)]
1257 1258
1258 1259
1259 1260 class _DictKeyState(enum.Flag):
1260 1261 """Represent state of the key match in context of other possible matches.
1261 1262
1262 1263 - given `d1 = {'a': 1}` completion on `d1['<tab>` will yield `{'a': END_OF_ITEM}` as there is no tuple.
1263 1264 - given `d2 = {('a', 'b'): 1}`: `d2['a', '<tab>` will yield `{'b': END_OF_TUPLE}` as there is no tuple members to add beyond `'b'`.
1264 1265 - given `d3 = {('a', 'b'): 1}`: `d3['<tab>` will yield `{'a': IN_TUPLE}` as `'a'` can be added.
1265 1266 - given `d4 = {'a': 1, ('a', 'b'): 2}`: `d4['<tab>` will yield `{'a': END_OF_ITEM & END_OF_TUPLE}`
1266 1267 """
1267 1268
1268 1269 BASELINE = 0
1269 1270 END_OF_ITEM = enum.auto()
1270 1271 END_OF_TUPLE = enum.auto()
1271 1272 IN_TUPLE = enum.auto()
1272 1273
1273 1274
1274 1275 def _parse_tokens(c):
1275 1276 """Parse tokens even if there is an error."""
1276 1277 tokens = []
1277 1278 token_generator = tokenize.generate_tokens(iter(c.splitlines()).__next__)
1278 1279 while True:
1279 1280 try:
1280 1281 tokens.append(next(token_generator))
1281 1282 except tokenize.TokenError:
1282 1283 return tokens
1283 1284 except StopIteration:
1284 1285 return tokens
1285 1286
1286 1287
1287 1288 def _match_number_in_dict_key_prefix(prefix: str) -> Union[str, None]:
1288 1289 """Match any valid Python numeric literal in a prefix of dictionary keys.
1289 1290
1290 1291 References:
1291 1292 - https://docs.python.org/3/reference/lexical_analysis.html#numeric-literals
1292 1293 - https://docs.python.org/3/library/tokenize.html
1293 1294 """
1294 1295 if prefix[-1].isspace():
1295 1296 # if user typed a space we do not have anything to complete
1296 1297 # even if there was a valid number token before
1297 1298 return None
1298 1299 tokens = _parse_tokens(prefix)
1299 1300 rev_tokens = reversed(tokens)
1300 1301 skip_over = {tokenize.ENDMARKER, tokenize.NEWLINE}
1301 1302 number = None
1302 1303 for token in rev_tokens:
1303 1304 if token.type in skip_over:
1304 1305 continue
1305 1306 if number is None:
1306 1307 if token.type == tokenize.NUMBER:
1307 1308 number = token.string
1308 1309 continue
1309 1310 else:
1310 1311 # we did not match a number
1311 1312 return None
1312 1313 if token.type == tokenize.OP:
1313 1314 if token.string == ",":
1314 1315 break
1315 1316 if token.string in {"+", "-"}:
1316 1317 number = token.string + number
1317 1318 else:
1318 1319 return None
1319 1320 return number
1320 1321
1321 1322
1322 1323 _INT_FORMATS = {
1323 1324 "0b": bin,
1324 1325 "0o": oct,
1325 1326 "0x": hex,
1326 1327 }
1327 1328
1328 1329
1329 1330 def match_dict_keys(
1330 1331 keys: List[Union[str, bytes, Tuple[Union[str, bytes], ...]]],
1331 1332 prefix: str,
1332 1333 delims: str,
1333 1334 extra_prefix: Optional[Tuple[Union[str, bytes], ...]] = None,
1334 1335 ) -> Tuple[str, int, Dict[str, _DictKeyState]]:
1335 1336 """Used by dict_key_matches, matching the prefix to a list of keys
1336 1337
1337 1338 Parameters
1338 1339 ----------
1339 1340 keys
1340 1341 list of keys in dictionary currently being completed.
1341 1342 prefix
1342 1343 Part of the text already typed by the user. E.g. `mydict[b'fo`
1343 1344 delims
1344 1345 String of delimiters to consider when finding the current key.
1345 1346 extra_prefix : optional
1346 1347 Part of the text already typed in multi-key index cases. E.g. for
1347 1348 `mydict['foo', "bar", 'b`, this would be `('foo', 'bar')`.
1348 1349
1349 1350 Returns
1350 1351 -------
1351 1352 A tuple of three elements: ``quote``, ``token_start``, ``matched``, with
1352 1353 ``quote`` being the quote that need to be used to close current string.
1353 1354 ``token_start`` the position where the replacement should start occurring,
1354 1355 ``matches`` a dictionary of replacement/completion keys on keys and values
1355 1356 indicating whether the state.
1356 1357 """
1357 1358 prefix_tuple = extra_prefix if extra_prefix else ()
1358 1359
1359 1360 prefix_tuple_size = sum(
1360 1361 [
1361 1362 # for pandas, do not count slices as taking space
1362 1363 not isinstance(k, slice)
1363 1364 for k in prefix_tuple
1364 1365 ]
1365 1366 )
1366 1367 text_serializable_types = (str, bytes, int, float, slice)
1367 1368
1368 1369 def filter_prefix_tuple(key):
1369 1370 # Reject too short keys
1370 1371 if len(key) <= prefix_tuple_size:
1371 1372 return False
1372 1373 # Reject keys which cannot be serialised to text
1373 1374 for k in key:
1374 1375 if not isinstance(k, text_serializable_types):
1375 1376 return False
1376 1377 # Reject keys that do not match the prefix
1377 1378 for k, pt in zip(key, prefix_tuple):
1378 1379 if k != pt and not isinstance(pt, slice):
1379 1380 return False
1380 1381 # All checks passed!
1381 1382 return True
1382 1383
1383 1384 filtered_key_is_final: Dict[Union[str, bytes, int, float], _DictKeyState] = (
1384 1385 defaultdict(lambda: _DictKeyState.BASELINE)
1385 1386 )
1386 1387
1387 1388 for k in keys:
1388 1389 # If at least one of the matches is not final, mark as undetermined.
1389 1390 # This can happen with `d = {111: 'b', (111, 222): 'a'}` where
1390 1391 # `111` appears final on first match but is not final on the second.
1391 1392
1392 1393 if isinstance(k, tuple):
1393 1394 if filter_prefix_tuple(k):
1394 1395 key_fragment = k[prefix_tuple_size]
1395 1396 filtered_key_is_final[key_fragment] |= (
1396 1397 _DictKeyState.END_OF_TUPLE
1397 1398 if len(k) == prefix_tuple_size + 1
1398 1399 else _DictKeyState.IN_TUPLE
1399 1400 )
1400 1401 elif prefix_tuple_size > 0:
1401 1402 # we are completing a tuple but this key is not a tuple,
1402 1403 # so we should ignore it
1403 1404 pass
1404 1405 else:
1405 1406 if isinstance(k, text_serializable_types):
1406 1407 filtered_key_is_final[k] |= _DictKeyState.END_OF_ITEM
1407 1408
1408 1409 filtered_keys = filtered_key_is_final.keys()
1409 1410
1410 1411 if not prefix:
1411 1412 return "", 0, {repr(k): v for k, v in filtered_key_is_final.items()}
1412 1413
1413 1414 quote_match = re.search("(?:\"|')", prefix)
1414 1415 is_user_prefix_numeric = False
1415 1416
1416 1417 if quote_match:
1417 1418 quote = quote_match.group()
1418 1419 valid_prefix = prefix + quote
1419 1420 try:
1420 1421 prefix_str = literal_eval(valid_prefix)
1421 1422 except Exception:
1422 1423 return "", 0, {}
1423 1424 else:
1424 1425 # If it does not look like a string, let's assume
1425 1426 # we are dealing with a number or variable.
1426 1427 number_match = _match_number_in_dict_key_prefix(prefix)
1427 1428
1428 1429 # We do not want the key matcher to suggest variable names so we yield:
1429 1430 if number_match is None:
1430 1431 # The alternative would be to assume that user forgort the quote
1431 1432 # and if the substring matches, suggest adding it at the start.
1432 1433 return "", 0, {}
1433 1434
1434 1435 prefix_str = number_match
1435 1436 is_user_prefix_numeric = True
1436 1437 quote = ""
1437 1438
1438 1439 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
1439 1440 token_match = re.search(pattern, prefix, re.UNICODE)
1440 1441 assert token_match is not None # silence mypy
1441 1442 token_start = token_match.start()
1442 1443 token_prefix = token_match.group()
1443 1444
1444 1445 matched: Dict[str, _DictKeyState] = {}
1445 1446
1446 1447 str_key: Union[str, bytes]
1447 1448
1448 1449 for key in filtered_keys:
1449 1450 if isinstance(key, (int, float)):
1450 1451 # User typed a number but this key is not a number.
1451 1452 if not is_user_prefix_numeric:
1452 1453 continue
1453 1454 str_key = str(key)
1454 1455 if isinstance(key, int):
1455 1456 int_base = prefix_str[:2].lower()
1456 1457 # if user typed integer using binary/oct/hex notation:
1457 1458 if int_base in _INT_FORMATS:
1458 1459 int_format = _INT_FORMATS[int_base]
1459 1460 str_key = int_format(key)
1460 1461 else:
1461 1462 # User typed a string but this key is a number.
1462 1463 if is_user_prefix_numeric:
1463 1464 continue
1464 1465 str_key = key
1465 1466 try:
1466 1467 if not str_key.startswith(prefix_str):
1467 1468 continue
1468 1469 except (AttributeError, TypeError, UnicodeError):
1469 1470 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
1470 1471 continue
1471 1472
1472 1473 # reformat remainder of key to begin with prefix
1473 1474 rem = str_key[len(prefix_str) :]
1474 1475 # force repr wrapped in '
1475 1476 rem_repr = repr(rem + '"') if isinstance(rem, str) else repr(rem + b'"')
1476 1477 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
1477 1478 if quote == '"':
1478 1479 # The entered prefix is quoted with ",
1479 1480 # but the match is quoted with '.
1480 1481 # A contained " hence needs escaping for comparison:
1481 1482 rem_repr = rem_repr.replace('"', '\\"')
1482 1483
1483 1484 # then reinsert prefix from start of token
1484 1485 match = "%s%s" % (token_prefix, rem_repr)
1485 1486
1486 1487 matched[match] = filtered_key_is_final[key]
1487 1488 return quote, token_start, matched
1488 1489
1489 1490
1490 1491 def cursor_to_position(text:str, line:int, column:int)->int:
1491 1492 """
1492 1493 Convert the (line,column) position of the cursor in text to an offset in a
1493 1494 string.
1494 1495
1495 1496 Parameters
1496 1497 ----------
1497 1498 text : str
1498 1499 The text in which to calculate the cursor offset
1499 1500 line : int
1500 1501 Line of the cursor; 0-indexed
1501 1502 column : int
1502 1503 Column of the cursor 0-indexed
1503 1504
1504 1505 Returns
1505 1506 -------
1506 1507 Position of the cursor in ``text``, 0-indexed.
1507 1508
1508 1509 See Also
1509 1510 --------
1510 1511 position_to_cursor : reciprocal of this function
1511 1512
1512 1513 """
1513 1514 lines = text.split('\n')
1514 1515 assert line <= len(lines), '{} <= {}'.format(str(line), str(len(lines)))
1515 1516
1516 1517 return sum(len(line) + 1 for line in lines[:line]) + column
1517 1518
1518 1519 def position_to_cursor(text:str, offset:int)->Tuple[int, int]:
1519 1520 """
1520 1521 Convert the position of the cursor in text (0 indexed) to a line
1521 1522 number(0-indexed) and a column number (0-indexed) pair
1522 1523
1523 1524 Position should be a valid position in ``text``.
1524 1525
1525 1526 Parameters
1526 1527 ----------
1527 1528 text : str
1528 1529 The text in which to calculate the cursor offset
1529 1530 offset : int
1530 1531 Position of the cursor in ``text``, 0-indexed.
1531 1532
1532 1533 Returns
1533 1534 -------
1534 1535 (line, column) : (int, int)
1535 1536 Line of the cursor; 0-indexed, column of the cursor 0-indexed
1536 1537
1537 1538 See Also
1538 1539 --------
1539 1540 cursor_to_position : reciprocal of this function
1540 1541
1541 1542 """
1542 1543
1543 1544 assert 0 <= offset <= len(text) , "0 <= %s <= %s" % (offset , len(text))
1544 1545
1545 1546 before = text[:offset]
1546 1547 blines = before.split('\n') # ! splitnes trim trailing \n
1547 1548 line = before.count('\n')
1548 1549 col = len(blines[-1])
1549 1550 return line, col
1550 1551
1551 1552
1552 1553 def _safe_isinstance(obj, module, class_name, *attrs):
1553 1554 """Checks if obj is an instance of module.class_name if loaded
1554 1555 """
1555 1556 if module in sys.modules:
1556 1557 m = sys.modules[module]
1557 1558 for attr in [class_name, *attrs]:
1558 1559 m = getattr(m, attr)
1559 1560 return isinstance(obj, m)
1560 1561
1561 1562
1562 1563 @context_matcher()
1563 1564 def back_unicode_name_matcher(context: CompletionContext):
1564 1565 """Match Unicode characters back to Unicode name
1565 1566
1566 1567 Same as :any:`back_unicode_name_matches`, but adopted to new Matcher API.
1567 1568 """
1568 1569 fragment, matches = back_unicode_name_matches(context.text_until_cursor)
1569 1570 return _convert_matcher_v1_result_to_v2(
1570 1571 matches, type="unicode", fragment=fragment, suppress_if_matches=True
1571 1572 )
1572 1573
1573 1574
1574 1575 def back_unicode_name_matches(text: str) -> Tuple[str, Sequence[str]]:
1575 1576 """Match Unicode characters back to Unicode name
1576 1577
1577 1578 This does ``☃`` -> ``\\snowman``
1578 1579
1579 1580 Note that snowman is not a valid python3 combining character but will be expanded.
1580 1581 Though it will not recombine back to the snowman character by the completion machinery.
1581 1582
1582 1583 This will not either back-complete standard sequences like \\n, \\b ...
1583 1584
1584 1585 .. deprecated:: 8.6
1585 1586 You can use :meth:`back_unicode_name_matcher` instead.
1586 1587
1587 1588 Returns
1588 1589 =======
1589 1590
1590 1591 Return a tuple with two elements:
1591 1592
1592 1593 - The Unicode character that was matched (preceded with a backslash), or
1593 1594 empty string,
1594 1595 - a sequence (of 1), name for the match Unicode character, preceded by
1595 1596 backslash, or empty if no match.
1596 1597 """
1597 1598 if len(text)<2:
1598 1599 return '', ()
1599 1600 maybe_slash = text[-2]
1600 1601 if maybe_slash != '\\':
1601 1602 return '', ()
1602 1603
1603 1604 char = text[-1]
1604 1605 # no expand on quote for completion in strings.
1605 1606 # nor backcomplete standard ascii keys
1606 1607 if char in string.ascii_letters or char in ('"',"'"):
1607 1608 return '', ()
1608 1609 try :
1609 1610 unic = unicodedata.name(char)
1610 1611 return '\\'+char,('\\'+unic,)
1611 1612 except KeyError:
1612 1613 pass
1613 1614 return '', ()
1614 1615
1615 1616
1616 1617 @context_matcher()
1617 1618 def back_latex_name_matcher(context: CompletionContext):
1618 1619 """Match latex characters back to unicode name
1619 1620
1620 1621 Same as :any:`back_latex_name_matches`, but adopted to new Matcher API.
1621 1622 """
1622 1623 fragment, matches = back_latex_name_matches(context.text_until_cursor)
1623 1624 return _convert_matcher_v1_result_to_v2(
1624 1625 matches, type="latex", fragment=fragment, suppress_if_matches=True
1625 1626 )
1626 1627
1627 1628
1628 1629 def back_latex_name_matches(text: str) -> Tuple[str, Sequence[str]]:
1629 1630 """Match latex characters back to unicode name
1630 1631
1631 1632 This does ``\\ℵ`` -> ``\\aleph``
1632 1633
1633 1634 .. deprecated:: 8.6
1634 1635 You can use :meth:`back_latex_name_matcher` instead.
1635 1636 """
1636 1637 if len(text)<2:
1637 1638 return '', ()
1638 1639 maybe_slash = text[-2]
1639 1640 if maybe_slash != '\\':
1640 1641 return '', ()
1641 1642
1642 1643
1643 1644 char = text[-1]
1644 1645 # no expand on quote for completion in strings.
1645 1646 # nor backcomplete standard ascii keys
1646 1647 if char in string.ascii_letters or char in ('"',"'"):
1647 1648 return '', ()
1648 1649 try :
1649 1650 latex = reverse_latex_symbol[char]
1650 1651 # '\\' replace the \ as well
1651 1652 return '\\'+char,[latex]
1652 1653 except KeyError:
1653 1654 pass
1654 1655 return '', ()
1655 1656
1656 1657
1657 1658 def _formatparamchildren(parameter) -> str:
1658 1659 """
1659 1660 Get parameter name and value from Jedi Private API
1660 1661
1661 1662 Jedi does not expose a simple way to get `param=value` from its API.
1662 1663
1663 1664 Parameters
1664 1665 ----------
1665 1666 parameter
1666 1667 Jedi's function `Param`
1667 1668
1668 1669 Returns
1669 1670 -------
1670 1671 A string like 'a', 'b=1', '*args', '**kwargs'
1671 1672
1672 1673 """
1673 1674 description = parameter.description
1674 1675 if not description.startswith('param '):
1675 1676 raise ValueError('Jedi function parameter description have change format.'
1676 1677 'Expected "param ...", found %r".' % description)
1677 1678 return description[6:]
1678 1679
1679 1680 def _make_signature(completion)-> str:
1680 1681 """
1681 1682 Make the signature from a jedi completion
1682 1683
1683 1684 Parameters
1684 1685 ----------
1685 1686 completion : jedi.Completion
1686 1687 object does not complete a function type
1687 1688
1688 1689 Returns
1689 1690 -------
1690 1691 a string consisting of the function signature, with the parenthesis but
1691 1692 without the function name. example:
1692 1693 `(a, *args, b=1, **kwargs)`
1693 1694
1694 1695 """
1695 1696
1696 1697 # it looks like this might work on jedi 0.17
1697 1698 if hasattr(completion, 'get_signatures'):
1698 1699 signatures = completion.get_signatures()
1699 1700 if not signatures:
1700 1701 return '(?)'
1701 1702
1702 1703 c0 = completion.get_signatures()[0]
1703 1704 return '('+c0.to_string().split('(', maxsplit=1)[1]
1704 1705
1705 1706 return '(%s)'% ', '.join([f for f in (_formatparamchildren(p) for signature in completion.get_signatures()
1706 1707 for p in signature.defined_names()) if f])
1707 1708
1708 1709
1709 1710 _CompleteResult = Dict[str, MatcherResult]
1710 1711
1711 1712
1712 1713 DICT_MATCHER_REGEX = re.compile(
1713 1714 r"""(?x)
1714 1715 ( # match dict-referring - or any get item object - expression
1715 1716 .+
1716 1717 )
1717 1718 \[ # open bracket
1718 1719 \s* # and optional whitespace
1719 1720 # Capture any number of serializable objects (e.g. "a", "b", 'c')
1720 1721 # and slices
1721 1722 ((?:(?:
1722 1723 (?: # closed string
1723 1724 [uUbB]? # string prefix (r not handled)
1724 1725 (?:
1725 1726 '(?:[^']|(?<!\\)\\')*'
1726 1727 |
1727 1728 "(?:[^"]|(?<!\\)\\")*"
1728 1729 )
1729 1730 )
1730 1731 |
1731 1732 # capture integers and slices
1732 1733 (?:[-+]?\d+)?(?::(?:[-+]?\d+)?){0,2}
1733 1734 |
1734 1735 # integer in bin/hex/oct notation
1735 1736 0[bBxXoO]_?(?:\w|\d)+
1736 1737 )
1737 1738 \s*,\s*
1738 1739 )*)
1739 1740 ((?:
1740 1741 (?: # unclosed string
1741 1742 [uUbB]? # string prefix (r not handled)
1742 1743 (?:
1743 1744 '(?:[^']|(?<!\\)\\')*
1744 1745 |
1745 1746 "(?:[^"]|(?<!\\)\\")*
1746 1747 )
1747 1748 )
1748 1749 |
1749 1750 # unfinished integer
1750 1751 (?:[-+]?\d+)
1751 1752 |
1752 1753 # integer in bin/hex/oct notation
1753 1754 0[bBxXoO]_?(?:\w|\d)+
1754 1755 )
1755 1756 )?
1756 1757 $
1757 1758 """
1758 1759 )
1759 1760
1760 1761
1761 1762 def _convert_matcher_v1_result_to_v2(
1762 1763 matches: Sequence[str],
1763 1764 type: str,
1764 1765 fragment: Optional[str] = None,
1765 1766 suppress_if_matches: bool = False,
1766 1767 ) -> SimpleMatcherResult:
1767 1768 """Utility to help with transition"""
1768 1769 result = {
1769 1770 "completions": [SimpleCompletion(text=match, type=type) for match in matches],
1770 1771 "suppress": (True if matches else False) if suppress_if_matches else False,
1771 1772 }
1772 1773 if fragment is not None:
1773 1774 result["matched_fragment"] = fragment
1774 1775 return cast(SimpleMatcherResult, result)
1775 1776
1776 1777
1777 1778 class IPCompleter(Completer):
1778 1779 """Extension of the completer class with IPython-specific features"""
1779 1780
1780 1781 @observe('greedy')
1781 1782 def _greedy_changed(self, change):
1782 1783 """update the splitter and readline delims when greedy is changed"""
1783 1784 if change["new"]:
1784 1785 self.evaluation = "unsafe"
1785 1786 self.auto_close_dict_keys = True
1786 1787 self.splitter.delims = GREEDY_DELIMS
1787 1788 else:
1788 1789 self.evaluation = "limited"
1789 1790 self.auto_close_dict_keys = False
1790 1791 self.splitter.delims = DELIMS
1791 1792
1792 1793 dict_keys_only = Bool(
1793 1794 False,
1794 1795 help="""
1795 1796 Whether to show dict key matches only.
1796 1797
1797 1798 (disables all matchers except for `IPCompleter.dict_key_matcher`).
1798 1799 """,
1799 1800 )
1800 1801
1801 1802 suppress_competing_matchers = UnionTrait(
1802 1803 [Bool(allow_none=True), DictTrait(Bool(None, allow_none=True))],
1803 1804 default_value=None,
1804 1805 help="""
1805 1806 Whether to suppress completions from other *Matchers*.
1806 1807
1807 1808 When set to ``None`` (default) the matchers will attempt to auto-detect
1808 1809 whether suppression of other matchers is desirable. For example, at
1809 1810 the beginning of a line followed by `%` we expect a magic completion
1810 1811 to be the only applicable option, and after ``my_dict['`` we usually
1811 1812 expect a completion with an existing dictionary key.
1812 1813
1813 1814 If you want to disable this heuristic and see completions from all matchers,
1814 1815 set ``IPCompleter.suppress_competing_matchers = False``.
1815 1816 To disable the heuristic for specific matchers provide a dictionary mapping:
1816 1817 ``IPCompleter.suppress_competing_matchers = {'IPCompleter.dict_key_matcher': False}``.
1817 1818
1818 1819 Set ``IPCompleter.suppress_competing_matchers = True`` to limit
1819 1820 completions to the set of matchers with the highest priority;
1820 1821 this is equivalent to ``IPCompleter.merge_completions`` and
1821 1822 can be beneficial for performance, but will sometimes omit relevant
1822 1823 candidates from matchers further down the priority list.
1823 1824 """,
1824 1825 ).tag(config=True)
1825 1826
1826 1827 merge_completions = Bool(
1827 1828 True,
1828 1829 help="""Whether to merge completion results into a single list
1829 1830
1830 1831 If False, only the completion results from the first non-empty
1831 1832 completer will be returned.
1832 1833
1833 1834 As of version 8.6.0, setting the value to ``False`` is an alias for:
1834 1835 ``IPCompleter.suppress_competing_matchers = True.``.
1835 1836 """,
1836 1837 ).tag(config=True)
1837 1838
1838 1839 disable_matchers = ListTrait(
1839 1840 Unicode(),
1840 1841 help="""List of matchers to disable.
1841 1842
1842 1843 The list should contain matcher identifiers (see :any:`completion_matcher`).
1843 1844 """,
1844 1845 ).tag(config=True)
1845 1846
1846 1847 omit__names = Enum(
1847 1848 (0, 1, 2),
1848 1849 default_value=2,
1849 1850 help="""Instruct the completer to omit private method names
1850 1851
1851 1852 Specifically, when completing on ``object.<tab>``.
1852 1853
1853 1854 When 2 [default]: all names that start with '_' will be excluded.
1854 1855
1855 1856 When 1: all 'magic' names (``__foo__``) will be excluded.
1856 1857
1857 1858 When 0: nothing will be excluded.
1858 1859 """
1859 1860 ).tag(config=True)
1860 1861 limit_to__all__ = Bool(False,
1861 1862 help="""
1862 1863 DEPRECATED as of version 5.0.
1863 1864
1864 1865 Instruct the completer to use __all__ for the completion
1865 1866
1866 1867 Specifically, when completing on ``object.<tab>``.
1867 1868
1868 1869 When True: only those names in obj.__all__ will be included.
1869 1870
1870 1871 When False [default]: the __all__ attribute is ignored
1871 1872 """,
1872 1873 ).tag(config=True)
1873 1874
1874 1875 profile_completions = Bool(
1875 1876 default_value=False,
1876 1877 help="If True, emit profiling data for completion subsystem using cProfile."
1877 1878 ).tag(config=True)
1878 1879
1879 1880 profiler_output_dir = Unicode(
1880 1881 default_value=".completion_profiles",
1881 1882 help="Template for path at which to output profile data for completions."
1882 1883 ).tag(config=True)
1883 1884
1884 1885 @observe('limit_to__all__')
1885 1886 def _limit_to_all_changed(self, change):
1886 1887 warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration '
1887 1888 'value has been deprecated since IPython 5.0, will be made to have '
1888 1889 'no effects and then removed in future version of IPython.',
1889 1890 UserWarning)
1890 1891
1891 1892 def __init__(
1892 1893 self, shell=None, namespace=None, global_namespace=None, config=None, **kwargs
1893 1894 ):
1894 1895 """IPCompleter() -> completer
1895 1896
1896 1897 Return a completer object.
1897 1898
1898 1899 Parameters
1899 1900 ----------
1900 1901 shell
1901 1902 a pointer to the ipython shell itself. This is needed
1902 1903 because this completer knows about magic functions, and those can
1903 1904 only be accessed via the ipython instance.
1904 1905 namespace : dict, optional
1905 1906 an optional dict where completions are performed.
1906 1907 global_namespace : dict, optional
1907 1908 secondary optional dict for completions, to
1908 1909 handle cases (such as IPython embedded inside functions) where
1909 1910 both Python scopes are visible.
1910 1911 config : Config
1911 1912 traitlet's config object
1912 1913 **kwargs
1913 1914 passed to super class unmodified.
1914 1915 """
1915 1916
1916 1917 self.magic_escape = ESC_MAGIC
1917 1918 self.splitter = CompletionSplitter()
1918 1919
1919 1920 # _greedy_changed() depends on splitter and readline being defined:
1920 1921 super().__init__(
1921 1922 namespace=namespace,
1922 1923 global_namespace=global_namespace,
1923 1924 config=config,
1924 1925 **kwargs,
1925 1926 )
1926 1927
1927 1928 # List where completion matches will be stored
1928 1929 self.matches = []
1929 1930 self.shell = shell
1930 1931 # Regexp to split filenames with spaces in them
1931 1932 self.space_name_re = re.compile(r'([^\\] )')
1932 1933 # Hold a local ref. to glob.glob for speed
1933 1934 self.glob = glob.glob
1934 1935
1935 1936 # Determine if we are running on 'dumb' terminals, like (X)Emacs
1936 1937 # buffers, to avoid completion problems.
1937 1938 term = os.environ.get('TERM','xterm')
1938 1939 self.dumb_terminal = term in ['dumb','emacs']
1939 1940
1940 1941 # Special handling of backslashes needed in win32 platforms
1941 1942 if sys.platform == "win32":
1942 1943 self.clean_glob = self._clean_glob_win32
1943 1944 else:
1944 1945 self.clean_glob = self._clean_glob
1945 1946
1946 1947 #regexp to parse docstring for function signature
1947 1948 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1948 1949 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1949 1950 #use this if positional argument name is also needed
1950 1951 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
1951 1952
1952 1953 self.magic_arg_matchers = [
1953 1954 self.magic_config_matcher,
1954 1955 self.magic_color_matcher,
1955 1956 ]
1956 1957
1957 1958 # This is set externally by InteractiveShell
1958 1959 self.custom_completers = None
1959 1960
1960 1961 # This is a list of names of unicode characters that can be completed
1961 1962 # into their corresponding unicode value. The list is large, so we
1962 1963 # lazily initialize it on first use. Consuming code should access this
1963 1964 # attribute through the `@unicode_names` property.
1964 1965 self._unicode_names = None
1965 1966
1966 1967 self._backslash_combining_matchers = [
1967 1968 self.latex_name_matcher,
1968 1969 self.unicode_name_matcher,
1969 1970 back_latex_name_matcher,
1970 1971 back_unicode_name_matcher,
1971 1972 self.fwd_unicode_matcher,
1972 1973 ]
1973 1974
1974 1975 if not self.backslash_combining_completions:
1975 1976 for matcher in self._backslash_combining_matchers:
1976 1977 self.disable_matchers.append(_get_matcher_id(matcher))
1977 1978
1978 1979 if not self.merge_completions:
1979 1980 self.suppress_competing_matchers = True
1980 1981
1981 1982 @property
1982 1983 def matchers(self) -> List[Matcher]:
1983 1984 """All active matcher routines for completion"""
1984 1985 if self.dict_keys_only:
1985 1986 return [self.dict_key_matcher]
1986 1987
1987 1988 if self.use_jedi:
1988 1989 return [
1989 1990 *self.custom_matchers,
1990 1991 *self._backslash_combining_matchers,
1991 1992 *self.magic_arg_matchers,
1992 1993 self.custom_completer_matcher,
1993 1994 self.magic_matcher,
1994 1995 self._jedi_matcher,
1995 1996 self.dict_key_matcher,
1996 1997 self.file_matcher,
1997 1998 ]
1998 1999 else:
1999 2000 return [
2000 2001 *self.custom_matchers,
2001 2002 *self._backslash_combining_matchers,
2002 2003 *self.magic_arg_matchers,
2003 2004 self.custom_completer_matcher,
2004 2005 self.dict_key_matcher,
2005 2006 self.magic_matcher,
2006 2007 self.python_matcher,
2007 2008 self.file_matcher,
2008 2009 self.python_func_kw_matcher,
2009 2010 ]
2010 2011
2011 2012 def all_completions(self, text:str) -> List[str]:
2012 2013 """
2013 2014 Wrapper around the completion methods for the benefit of emacs.
2014 2015 """
2015 2016 prefix = text.rpartition('.')[0]
2016 2017 with provisionalcompleter():
2017 2018 return ['.'.join([prefix, c.text]) if prefix and self.use_jedi else c.text
2018 2019 for c in self.completions(text, len(text))]
2019 2020
2020 2021 return self.complete(text)[1]
2021 2022
2022 2023 def _clean_glob(self, text:str):
2023 2024 return self.glob("%s*" % text)
2024 2025
2025 2026 def _clean_glob_win32(self, text:str):
2026 2027 return [f.replace("\\","/")
2027 2028 for f in self.glob("%s*" % text)]
2028 2029
2029 2030 @context_matcher()
2030 2031 def file_matcher(self, context: CompletionContext) -> SimpleMatcherResult:
2031 2032 """Same as :any:`file_matches`, but adopted to new Matcher API."""
2032 2033 matches = self.file_matches(context.token)
2033 2034 # TODO: add a heuristic for suppressing (e.g. if it has OS-specific delimiter,
2034 2035 # starts with `/home/`, `C:\`, etc)
2035 2036 return _convert_matcher_v1_result_to_v2(matches, type="path")
2036 2037
2037 2038 def file_matches(self, text: str) -> List[str]:
2038 2039 """Match filenames, expanding ~USER type strings.
2039 2040
2040 2041 Most of the seemingly convoluted logic in this completer is an
2041 2042 attempt to handle filenames with spaces in them. And yet it's not
2042 2043 quite perfect, because Python's readline doesn't expose all of the
2043 2044 GNU readline details needed for this to be done correctly.
2044 2045
2045 2046 For a filename with a space in it, the printed completions will be
2046 2047 only the parts after what's already been typed (instead of the
2047 2048 full completions, as is normally done). I don't think with the
2048 2049 current (as of Python 2.3) Python readline it's possible to do
2049 2050 better.
2050 2051
2051 2052 .. deprecated:: 8.6
2052 2053 You can use :meth:`file_matcher` instead.
2053 2054 """
2054 2055
2055 2056 # chars that require escaping with backslash - i.e. chars
2056 2057 # that readline treats incorrectly as delimiters, but we
2057 2058 # don't want to treat as delimiters in filename matching
2058 2059 # when escaped with backslash
2059 2060 if text.startswith('!'):
2060 2061 text = text[1:]
2061 2062 text_prefix = u'!'
2062 2063 else:
2063 2064 text_prefix = u''
2064 2065
2065 2066 text_until_cursor = self.text_until_cursor
2066 2067 # track strings with open quotes
2067 2068 open_quotes = has_open_quotes(text_until_cursor)
2068 2069
2069 2070 if '(' in text_until_cursor or '[' in text_until_cursor:
2070 2071 lsplit = text
2071 2072 else:
2072 2073 try:
2073 2074 # arg_split ~ shlex.split, but with unicode bugs fixed by us
2074 2075 lsplit = arg_split(text_until_cursor)[-1]
2075 2076 except ValueError:
2076 2077 # typically an unmatched ", or backslash without escaped char.
2077 2078 if open_quotes:
2078 2079 lsplit = text_until_cursor.split(open_quotes)[-1]
2079 2080 else:
2080 2081 return []
2081 2082 except IndexError:
2082 2083 # tab pressed on empty line
2083 2084 lsplit = ""
2084 2085
2085 2086 if not open_quotes and lsplit != protect_filename(lsplit):
2086 2087 # if protectables are found, do matching on the whole escaped name
2087 2088 has_protectables = True
2088 2089 text0,text = text,lsplit
2089 2090 else:
2090 2091 has_protectables = False
2091 2092 text = os.path.expanduser(text)
2092 2093
2093 2094 if text == "":
2094 2095 return [text_prefix + protect_filename(f) for f in self.glob("*")]
2095 2096
2096 2097 # Compute the matches from the filesystem
2097 2098 if sys.platform == 'win32':
2098 2099 m0 = self.clean_glob(text)
2099 2100 else:
2100 2101 m0 = self.clean_glob(text.replace('\\', ''))
2101 2102
2102 2103 if has_protectables:
2103 2104 # If we had protectables, we need to revert our changes to the
2104 2105 # beginning of filename so that we don't double-write the part
2105 2106 # of the filename we have so far
2106 2107 len_lsplit = len(lsplit)
2107 2108 matches = [text_prefix + text0 +
2108 2109 protect_filename(f[len_lsplit:]) for f in m0]
2109 2110 else:
2110 2111 if open_quotes:
2111 2112 # if we have a string with an open quote, we don't need to
2112 2113 # protect the names beyond the quote (and we _shouldn't_, as
2113 2114 # it would cause bugs when the filesystem call is made).
2114 2115 matches = m0 if sys.platform == "win32" else\
2115 2116 [protect_filename(f, open_quotes) for f in m0]
2116 2117 else:
2117 2118 matches = [text_prefix +
2118 2119 protect_filename(f) for f in m0]
2119 2120
2120 2121 # Mark directories in input list by appending '/' to their names.
2121 2122 return [x+'/' if os.path.isdir(x) else x for x in matches]
2122 2123
2123 2124 @context_matcher()
2124 2125 def magic_matcher(self, context: CompletionContext) -> SimpleMatcherResult:
2125 2126 """Match magics."""
2126 2127 text = context.token
2127 2128 matches = self.magic_matches(text)
2128 2129 result = _convert_matcher_v1_result_to_v2(matches, type="magic")
2129 2130 is_magic_prefix = len(text) > 0 and text[0] == "%"
2130 2131 result["suppress"] = is_magic_prefix and bool(result["completions"])
2131 2132 return result
2132 2133
2133 2134 def magic_matches(self, text: str) -> List[str]:
2134 2135 """Match magics.
2135 2136
2136 2137 .. deprecated:: 8.6
2137 2138 You can use :meth:`magic_matcher` instead.
2138 2139 """
2139 2140 # Get all shell magics now rather than statically, so magics loaded at
2140 2141 # runtime show up too.
2141 2142 lsm = self.shell.magics_manager.lsmagic()
2142 2143 line_magics = lsm['line']
2143 2144 cell_magics = lsm['cell']
2144 2145 pre = self.magic_escape
2145 2146 pre2 = pre+pre
2146 2147
2147 2148 explicit_magic = text.startswith(pre)
2148 2149
2149 2150 # Completion logic:
2150 2151 # - user gives %%: only do cell magics
2151 2152 # - user gives %: do both line and cell magics
2152 2153 # - no prefix: do both
2153 2154 # In other words, line magics are skipped if the user gives %% explicitly
2154 2155 #
2155 2156 # We also exclude magics that match any currently visible names:
2156 2157 # https://github.com/ipython/ipython/issues/4877, unless the user has
2157 2158 # typed a %:
2158 2159 # https://github.com/ipython/ipython/issues/10754
2159 2160 bare_text = text.lstrip(pre)
2160 2161 global_matches = self.global_matches(bare_text)
2161 2162 if not explicit_magic:
2162 2163 def matches(magic):
2163 2164 """
2164 2165 Filter magics, in particular remove magics that match
2165 2166 a name present in global namespace.
2166 2167 """
2167 2168 return ( magic.startswith(bare_text) and
2168 2169 magic not in global_matches )
2169 2170 else:
2170 2171 def matches(magic):
2171 2172 return magic.startswith(bare_text)
2172 2173
2173 2174 comp = [ pre2+m for m in cell_magics if matches(m)]
2174 2175 if not text.startswith(pre2):
2175 2176 comp += [ pre+m for m in line_magics if matches(m)]
2176 2177
2177 2178 return comp
2178 2179
2179 2180 @context_matcher()
2180 2181 def magic_config_matcher(self, context: CompletionContext) -> SimpleMatcherResult:
2181 2182 """Match class names and attributes for %config magic."""
2182 2183 # NOTE: uses `line_buffer` equivalent for compatibility
2183 2184 matches = self.magic_config_matches(context.line_with_cursor)
2184 2185 return _convert_matcher_v1_result_to_v2(matches, type="param")
2185 2186
2186 2187 def magic_config_matches(self, text: str) -> List[str]:
2187 2188 """Match class names and attributes for %config magic.
2188 2189
2189 2190 .. deprecated:: 8.6
2190 2191 You can use :meth:`magic_config_matcher` instead.
2191 2192 """
2192 2193 texts = text.strip().split()
2193 2194
2194 2195 if len(texts) > 0 and (texts[0] == 'config' or texts[0] == '%config'):
2195 2196 # get all configuration classes
2196 2197 classes = sorted(set([ c for c in self.shell.configurables
2197 2198 if c.__class__.class_traits(config=True)
2198 2199 ]), key=lambda x: x.__class__.__name__)
2199 2200 classnames = [ c.__class__.__name__ for c in classes ]
2200 2201
2201 2202 # return all classnames if config or %config is given
2202 2203 if len(texts) == 1:
2203 2204 return classnames
2204 2205
2205 2206 # match classname
2206 2207 classname_texts = texts[1].split('.')
2207 2208 classname = classname_texts[0]
2208 2209 classname_matches = [ c for c in classnames
2209 2210 if c.startswith(classname) ]
2210 2211
2211 2212 # return matched classes or the matched class with attributes
2212 2213 if texts[1].find('.') < 0:
2213 2214 return classname_matches
2214 2215 elif len(classname_matches) == 1 and \
2215 2216 classname_matches[0] == classname:
2216 2217 cls = classes[classnames.index(classname)].__class__
2217 2218 help = cls.class_get_help()
2218 2219 # strip leading '--' from cl-args:
2219 2220 help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
2220 2221 return [ attr.split('=')[0]
2221 2222 for attr in help.strip().splitlines()
2222 2223 if attr.startswith(texts[1]) ]
2223 2224 return []
2224 2225
2225 2226 @context_matcher()
2226 2227 def magic_color_matcher(self, context: CompletionContext) -> SimpleMatcherResult:
2227 2228 """Match color schemes for %colors magic."""
2228 2229 # NOTE: uses `line_buffer` equivalent for compatibility
2229 2230 matches = self.magic_color_matches(context.line_with_cursor)
2230 2231 return _convert_matcher_v1_result_to_v2(matches, type="param")
2231 2232
2232 2233 def magic_color_matches(self, text: str) -> List[str]:
2233 2234 """Match color schemes for %colors magic.
2234 2235
2235 2236 .. deprecated:: 8.6
2236 2237 You can use :meth:`magic_color_matcher` instead.
2237 2238 """
2238 2239 texts = text.split()
2239 2240 if text.endswith(' '):
2240 2241 # .split() strips off the trailing whitespace. Add '' back
2241 2242 # so that: '%colors ' -> ['%colors', '']
2242 2243 texts.append('')
2243 2244
2244 2245 if len(texts) == 2 and (texts[0] == 'colors' or texts[0] == '%colors'):
2245 2246 prefix = texts[1]
2246 2247 return [ color for color in InspectColors.keys()
2247 2248 if color.startswith(prefix) ]
2248 2249 return []
2249 2250
2250 2251 @context_matcher(identifier="IPCompleter.jedi_matcher")
2251 2252 def _jedi_matcher(self, context: CompletionContext) -> _JediMatcherResult:
2252 2253 matches = self._jedi_matches(
2253 2254 cursor_column=context.cursor_position,
2254 2255 cursor_line=context.cursor_line,
2255 2256 text=context.full_text,
2256 2257 )
2257 2258 return {
2258 2259 "completions": matches,
2259 2260 # static analysis should not suppress other matchers
2260 2261 "suppress": False,
2261 2262 }
2262 2263
2263 2264 def _jedi_matches(
2264 2265 self, cursor_column: int, cursor_line: int, text: str
2265 2266 ) -> Iterator[_JediCompletionLike]:
2266 2267 """
2267 2268 Return a list of :any:`jedi.api.Completion`\\s object from a ``text`` and
2268 2269 cursor position.
2269 2270
2270 2271 Parameters
2271 2272 ----------
2272 2273 cursor_column : int
2273 2274 column position of the cursor in ``text``, 0-indexed.
2274 2275 cursor_line : int
2275 2276 line position of the cursor in ``text``, 0-indexed
2276 2277 text : str
2277 2278 text to complete
2278 2279
2279 2280 Notes
2280 2281 -----
2281 2282 If ``IPCompleter.debug`` is ``True`` may return a :any:`_FakeJediCompletion`
2282 2283 object containing a string with the Jedi debug information attached.
2283 2284
2284 2285 .. deprecated:: 8.6
2285 2286 You can use :meth:`_jedi_matcher` instead.
2286 2287 """
2287 2288 namespaces = [self.namespace]
2288 2289 if self.global_namespace is not None:
2289 2290 namespaces.append(self.global_namespace)
2290 2291
2291 2292 completion_filter = lambda x:x
2292 2293 offset = cursor_to_position(text, cursor_line, cursor_column)
2293 2294 # filter output if we are completing for object members
2294 2295 if offset:
2295 2296 pre = text[offset-1]
2296 2297 if pre == '.':
2297 2298 if self.omit__names == 2:
2298 2299 completion_filter = lambda c:not c.name.startswith('_')
2299 2300 elif self.omit__names == 1:
2300 2301 completion_filter = lambda c:not (c.name.startswith('__') and c.name.endswith('__'))
2301 2302 elif self.omit__names == 0:
2302 2303 completion_filter = lambda x:x
2303 2304 else:
2304 2305 raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names))
2305 2306
2306 2307 interpreter = jedi.Interpreter(text[:offset], namespaces)
2307 2308 try_jedi = True
2308 2309
2309 2310 try:
2310 2311 # find the first token in the current tree -- if it is a ' or " then we are in a string
2311 2312 completing_string = False
2312 2313 try:
2313 2314 first_child = next(c for c in interpreter._get_module().tree_node.children if hasattr(c, 'value'))
2314 2315 except StopIteration:
2315 2316 pass
2316 2317 else:
2317 2318 # note the value may be ', ", or it may also be ''' or """, or
2318 2319 # in some cases, """what/you/typed..., but all of these are
2319 2320 # strings.
2320 2321 completing_string = len(first_child.value) > 0 and first_child.value[0] in {"'", '"'}
2321 2322
2322 2323 # if we are in a string jedi is likely not the right candidate for
2323 2324 # now. Skip it.
2324 2325 try_jedi = not completing_string
2325 2326 except Exception as e:
2326 2327 # many of things can go wrong, we are using private API just don't crash.
2327 2328 if self.debug:
2328 2329 print("Error detecting if completing a non-finished string :", e, '|')
2329 2330
2330 2331 if not try_jedi:
2331 2332 return iter([])
2332 2333 try:
2333 2334 return filter(completion_filter, interpreter.complete(column=cursor_column, line=cursor_line + 1))
2334 2335 except Exception as e:
2335 2336 if self.debug:
2336 2337 return iter(
2337 2338 [
2338 2339 _FakeJediCompletion(
2339 2340 'Oops Jedi has crashed, please report a bug with the following:\n"""\n%s\ns"""'
2340 2341 % (e)
2341 2342 )
2342 2343 ]
2343 2344 )
2344 2345 else:
2345 2346 return iter([])
2346 2347
2347 2348 @context_matcher()
2348 2349 def python_matcher(self, context: CompletionContext) -> SimpleMatcherResult:
2349 2350 """Match attributes or global python names"""
2350 2351 text = context.line_with_cursor
2351 2352 if "." in text:
2352 2353 try:
2353 2354 matches, fragment = self._attr_matches(text, include_prefix=False)
2354 2355 if text.endswith(".") and self.omit__names:
2355 2356 if self.omit__names == 1:
2356 2357 # true if txt is _not_ a __ name, false otherwise:
2357 2358 no__name = lambda txt: re.match(r".*\.__.*?__", txt) is None
2358 2359 else:
2359 2360 # true if txt is _not_ a _ name, false otherwise:
2360 2361 no__name = (
2361 2362 lambda txt: re.match(r"\._.*?", txt[txt.rindex(".") :])
2362 2363 is None
2363 2364 )
2364 2365 matches = filter(no__name, matches)
2365 2366 return _convert_matcher_v1_result_to_v2(
2366 2367 matches, type="attribute", fragment=fragment
2367 2368 )
2368 2369 except NameError:
2369 2370 # catches <undefined attributes>.<tab>
2370 2371 matches = []
2371 2372 return _convert_matcher_v1_result_to_v2(matches, type="attribute")
2372 2373 else:
2373 2374 matches = self.global_matches(context.token)
2374 2375 # TODO: maybe distinguish between functions, modules and just "variables"
2375 2376 return _convert_matcher_v1_result_to_v2(matches, type="variable")
2376 2377
2377 2378 @completion_matcher(api_version=1)
2378 2379 def python_matches(self, text: str) -> Iterable[str]:
2379 2380 """Match attributes or global python names.
2380 2381
2381 2382 .. deprecated:: 8.27
2382 2383 You can use :meth:`python_matcher` instead."""
2383 2384 if "." in text:
2384 2385 try:
2385 2386 matches = self.attr_matches(text)
2386 2387 if text.endswith('.') and self.omit__names:
2387 2388 if self.omit__names == 1:
2388 2389 # true if txt is _not_ a __ name, false otherwise:
2389 2390 no__name = (lambda txt:
2390 2391 re.match(r'.*\.__.*?__',txt) is None)
2391 2392 else:
2392 2393 # true if txt is _not_ a _ name, false otherwise:
2393 2394 no__name = (lambda txt:
2394 2395 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
2395 2396 matches = filter(no__name, matches)
2396 2397 except NameError:
2397 2398 # catches <undefined attributes>.<tab>
2398 2399 matches = []
2399 2400 else:
2400 2401 matches = self.global_matches(text)
2401 2402 return matches
2402 2403
2403 2404 def _default_arguments_from_docstring(self, doc):
2404 2405 """Parse the first line of docstring for call signature.
2405 2406
2406 2407 Docstring should be of the form 'min(iterable[, key=func])\n'.
2407 2408 It can also parse cython docstring of the form
2408 2409 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
2409 2410 """
2410 2411 if doc is None:
2411 2412 return []
2412 2413
2413 2414 #care only the firstline
2414 2415 line = doc.lstrip().splitlines()[0]
2415 2416
2416 2417 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
2417 2418 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
2418 2419 sig = self.docstring_sig_re.search(line)
2419 2420 if sig is None:
2420 2421 return []
2421 2422 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
2422 2423 sig = sig.groups()[0].split(',')
2423 2424 ret = []
2424 2425 for s in sig:
2425 2426 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
2426 2427 ret += self.docstring_kwd_re.findall(s)
2427 2428 return ret
2428 2429
2429 2430 def _default_arguments(self, obj):
2430 2431 """Return the list of default arguments of obj if it is callable,
2431 2432 or empty list otherwise."""
2432 2433 call_obj = obj
2433 2434 ret = []
2434 2435 if inspect.isbuiltin(obj):
2435 2436 pass
2436 2437 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
2437 2438 if inspect.isclass(obj):
2438 2439 #for cython embedsignature=True the constructor docstring
2439 2440 #belongs to the object itself not __init__
2440 2441 ret += self._default_arguments_from_docstring(
2441 2442 getattr(obj, '__doc__', ''))
2442 2443 # for classes, check for __init__,__new__
2443 2444 call_obj = (getattr(obj, '__init__', None) or
2444 2445 getattr(obj, '__new__', None))
2445 2446 # for all others, check if they are __call__able
2446 2447 elif hasattr(obj, '__call__'):
2447 2448 call_obj = obj.__call__
2448 2449 ret += self._default_arguments_from_docstring(
2449 2450 getattr(call_obj, '__doc__', ''))
2450 2451
2451 2452 _keeps = (inspect.Parameter.KEYWORD_ONLY,
2452 2453 inspect.Parameter.POSITIONAL_OR_KEYWORD)
2453 2454
2454 2455 try:
2455 2456 sig = inspect.signature(obj)
2456 2457 ret.extend(k for k, v in sig.parameters.items() if
2457 2458 v.kind in _keeps)
2458 2459 except ValueError:
2459 2460 pass
2460 2461
2461 2462 return list(set(ret))
2462 2463
2463 2464 @context_matcher()
2464 2465 def python_func_kw_matcher(self, context: CompletionContext) -> SimpleMatcherResult:
2465 2466 """Match named parameters (kwargs) of the last open function."""
2466 2467 matches = self.python_func_kw_matches(context.token)
2467 2468 return _convert_matcher_v1_result_to_v2(matches, type="param")
2468 2469
2469 2470 def python_func_kw_matches(self, text):
2470 2471 """Match named parameters (kwargs) of the last open function.
2471 2472
2472 2473 .. deprecated:: 8.6
2473 2474 You can use :meth:`python_func_kw_matcher` instead.
2474 2475 """
2475 2476
2476 2477 if "." in text: # a parameter cannot be dotted
2477 2478 return []
2478 2479 try: regexp = self.__funcParamsRegex
2479 2480 except AttributeError:
2480 2481 regexp = self.__funcParamsRegex = re.compile(r'''
2481 2482 '.*?(?<!\\)' | # single quoted strings or
2482 2483 ".*?(?<!\\)" | # double quoted strings or
2483 2484 \w+ | # identifier
2484 2485 \S # other characters
2485 2486 ''', re.VERBOSE | re.DOTALL)
2486 2487 # 1. find the nearest identifier that comes before an unclosed
2487 2488 # parenthesis before the cursor
2488 2489 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
2489 2490 tokens = regexp.findall(self.text_until_cursor)
2490 2491 iterTokens = reversed(tokens)
2491 2492 openPar = 0
2492 2493
2493 2494 for token in iterTokens:
2494 2495 if token == ')':
2495 2496 openPar -= 1
2496 2497 elif token == '(':
2497 2498 openPar += 1
2498 2499 if openPar > 0:
2499 2500 # found the last unclosed parenthesis
2500 2501 break
2501 2502 else:
2502 2503 return []
2503 2504 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
2504 2505 ids = []
2505 2506 isId = re.compile(r'\w+$').match
2506 2507
2507 2508 while True:
2508 2509 try:
2509 2510 ids.append(next(iterTokens))
2510 2511 if not isId(ids[-1]):
2511 2512 ids.pop()
2512 2513 break
2513 2514 if not next(iterTokens) == '.':
2514 2515 break
2515 2516 except StopIteration:
2516 2517 break
2517 2518
2518 2519 # Find all named arguments already assigned to, as to avoid suggesting
2519 2520 # them again
2520 2521 usedNamedArgs = set()
2521 2522 par_level = -1
2522 2523 for token, next_token in zip(tokens, tokens[1:]):
2523 2524 if token == '(':
2524 2525 par_level += 1
2525 2526 elif token == ')':
2526 2527 par_level -= 1
2527 2528
2528 2529 if par_level != 0:
2529 2530 continue
2530 2531
2531 2532 if next_token != '=':
2532 2533 continue
2533 2534
2534 2535 usedNamedArgs.add(token)
2535 2536
2536 2537 argMatches = []
2537 2538 try:
2538 2539 callableObj = '.'.join(ids[::-1])
2539 2540 namedArgs = self._default_arguments(eval(callableObj,
2540 2541 self.namespace))
2541 2542
2542 2543 # Remove used named arguments from the list, no need to show twice
2543 2544 for namedArg in set(namedArgs) - usedNamedArgs:
2544 2545 if namedArg.startswith(text):
2545 2546 argMatches.append("%s=" %namedArg)
2546 2547 except:
2547 2548 pass
2548 2549
2549 2550 return argMatches
2550 2551
2551 2552 @staticmethod
2552 2553 def _get_keys(obj: Any) -> List[Any]:
2553 2554 # Objects can define their own completions by defining an
2554 2555 # _ipy_key_completions_() method.
2555 2556 method = get_real_method(obj, '_ipython_key_completions_')
2556 2557 if method is not None:
2557 2558 return method()
2558 2559
2559 2560 # Special case some common in-memory dict-like types
2560 2561 if isinstance(obj, dict) or _safe_isinstance(obj, "pandas", "DataFrame"):
2561 2562 try:
2562 2563 return list(obj.keys())
2563 2564 except Exception:
2564 2565 return []
2565 2566 elif _safe_isinstance(obj, "pandas", "core", "indexing", "_LocIndexer"):
2566 2567 try:
2567 2568 return list(obj.obj.keys())
2568 2569 except Exception:
2569 2570 return []
2570 2571 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
2571 2572 _safe_isinstance(obj, 'numpy', 'void'):
2572 2573 return obj.dtype.names or []
2573 2574 return []
2574 2575
2575 2576 @context_matcher()
2576 2577 def dict_key_matcher(self, context: CompletionContext) -> SimpleMatcherResult:
2577 2578 """Match string keys in a dictionary, after e.g. ``foo[``."""
2578 2579 matches = self.dict_key_matches(context.token)
2579 2580 return _convert_matcher_v1_result_to_v2(
2580 2581 matches, type="dict key", suppress_if_matches=True
2581 2582 )
2582 2583
2583 2584 def dict_key_matches(self, text: str) -> List[str]:
2584 2585 """Match string keys in a dictionary, after e.g. ``foo[``.
2585 2586
2586 2587 .. deprecated:: 8.6
2587 2588 You can use :meth:`dict_key_matcher` instead.
2588 2589 """
2589 2590
2590 2591 # Short-circuit on closed dictionary (regular expression would
2591 2592 # not match anyway, but would take quite a while).
2592 2593 if self.text_until_cursor.strip().endswith("]"):
2593 2594 return []
2594 2595
2595 2596 match = DICT_MATCHER_REGEX.search(self.text_until_cursor)
2596 2597
2597 2598 if match is None:
2598 2599 return []
2599 2600
2600 2601 expr, prior_tuple_keys, key_prefix = match.groups()
2601 2602
2602 2603 obj = self._evaluate_expr(expr)
2603 2604
2604 2605 if obj is not_found:
2605 2606 return []
2606 2607
2607 2608 keys = self._get_keys(obj)
2608 2609 if not keys:
2609 2610 return keys
2610 2611
2611 2612 tuple_prefix = guarded_eval(
2612 2613 prior_tuple_keys,
2613 2614 EvaluationContext(
2614 2615 globals=self.global_namespace,
2615 2616 locals=self.namespace,
2616 2617 evaluation=self.evaluation, # type: ignore
2617 2618 in_subscript=True,
2618 2619 ),
2619 2620 )
2620 2621
2621 2622 closing_quote, token_offset, matches = match_dict_keys(
2622 2623 keys, key_prefix, self.splitter.delims, extra_prefix=tuple_prefix
2623 2624 )
2624 2625 if not matches:
2625 2626 return []
2626 2627
2627 2628 # get the cursor position of
2628 2629 # - the text being completed
2629 2630 # - the start of the key text
2630 2631 # - the start of the completion
2631 2632 text_start = len(self.text_until_cursor) - len(text)
2632 2633 if key_prefix:
2633 2634 key_start = match.start(3)
2634 2635 completion_start = key_start + token_offset
2635 2636 else:
2636 2637 key_start = completion_start = match.end()
2637 2638
2638 2639 # grab the leading prefix, to make sure all completions start with `text`
2639 2640 if text_start > key_start:
2640 2641 leading = ''
2641 2642 else:
2642 2643 leading = text[text_start:completion_start]
2643 2644
2644 2645 # append closing quote and bracket as appropriate
2645 2646 # this is *not* appropriate if the opening quote or bracket is outside
2646 2647 # the text given to this method, e.g. `d["""a\nt
2647 2648 can_close_quote = False
2648 2649 can_close_bracket = False
2649 2650
2650 2651 continuation = self.line_buffer[len(self.text_until_cursor) :].strip()
2651 2652
2652 2653 if continuation.startswith(closing_quote):
2653 2654 # do not close if already closed, e.g. `d['a<tab>'`
2654 2655 continuation = continuation[len(closing_quote) :]
2655 2656 else:
2656 2657 can_close_quote = True
2657 2658
2658 2659 continuation = continuation.strip()
2659 2660
2660 2661 # e.g. `pandas.DataFrame` has different tuple indexer behaviour,
2661 2662 # handling it is out of scope, so let's avoid appending suffixes.
2662 2663 has_known_tuple_handling = isinstance(obj, dict)
2663 2664
2664 2665 can_close_bracket = (
2665 2666 not continuation.startswith("]") and self.auto_close_dict_keys
2666 2667 )
2667 2668 can_close_tuple_item = (
2668 2669 not continuation.startswith(",")
2669 2670 and has_known_tuple_handling
2670 2671 and self.auto_close_dict_keys
2671 2672 )
2672 2673 can_close_quote = can_close_quote and self.auto_close_dict_keys
2673 2674
2674 2675 # fast path if closing quote should be appended but not suffix is allowed
2675 2676 if not can_close_quote and not can_close_bracket and closing_quote:
2676 2677 return [leading + k for k in matches]
2677 2678
2678 2679 results = []
2679 2680
2680 2681 end_of_tuple_or_item = _DictKeyState.END_OF_TUPLE | _DictKeyState.END_OF_ITEM
2681 2682
2682 2683 for k, state_flag in matches.items():
2683 2684 result = leading + k
2684 2685 if can_close_quote and closing_quote:
2685 2686 result += closing_quote
2686 2687
2687 2688 if state_flag == end_of_tuple_or_item:
2688 2689 # We do not know which suffix to add,
2689 2690 # e.g. both tuple item and string
2690 2691 # match this item.
2691 2692 pass
2692 2693
2693 2694 if state_flag in end_of_tuple_or_item and can_close_bracket:
2694 2695 result += "]"
2695 2696 if state_flag == _DictKeyState.IN_TUPLE and can_close_tuple_item:
2696 2697 result += ", "
2697 2698 results.append(result)
2698 2699 return results
2699 2700
2700 2701 @context_matcher()
2701 2702 def unicode_name_matcher(self, context: CompletionContext):
2702 2703 """Same as :any:`unicode_name_matches`, but adopted to new Matcher API."""
2703 2704 fragment, matches = self.unicode_name_matches(context.text_until_cursor)
2704 2705 return _convert_matcher_v1_result_to_v2(
2705 2706 matches, type="unicode", fragment=fragment, suppress_if_matches=True
2706 2707 )
2707 2708
2708 2709 @staticmethod
2709 2710 def unicode_name_matches(text: str) -> Tuple[str, List[str]]:
2710 2711 """Match Latex-like syntax for unicode characters base
2711 2712 on the name of the character.
2712 2713
2713 2714 This does ``\\GREEK SMALL LETTER ETA`` -> ``η``
2714 2715
2715 2716 Works only on valid python 3 identifier, or on combining characters that
2716 2717 will combine to form a valid identifier.
2717 2718 """
2718 2719 slashpos = text.rfind('\\')
2719 2720 if slashpos > -1:
2720 2721 s = text[slashpos+1:]
2721 2722 try :
2722 2723 unic = unicodedata.lookup(s)
2723 2724 # allow combining chars
2724 2725 if ('a'+unic).isidentifier():
2725 2726 return '\\'+s,[unic]
2726 2727 except KeyError:
2727 2728 pass
2728 2729 return '', []
2729 2730
2730 2731 @context_matcher()
2731 2732 def latex_name_matcher(self, context: CompletionContext):
2732 2733 """Match Latex syntax for unicode characters.
2733 2734
2734 2735 This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``α``
2735 2736 """
2736 2737 fragment, matches = self.latex_matches(context.text_until_cursor)
2737 2738 return _convert_matcher_v1_result_to_v2(
2738 2739 matches, type="latex", fragment=fragment, suppress_if_matches=True
2739 2740 )
2740 2741
2741 2742 def latex_matches(self, text: str) -> Tuple[str, Sequence[str]]:
2742 2743 """Match Latex syntax for unicode characters.
2743 2744
2744 2745 This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``α``
2745 2746
2746 2747 .. deprecated:: 8.6
2747 2748 You can use :meth:`latex_name_matcher` instead.
2748 2749 """
2749 2750 slashpos = text.rfind('\\')
2750 2751 if slashpos > -1:
2751 2752 s = text[slashpos:]
2752 2753 if s in latex_symbols:
2753 2754 # Try to complete a full latex symbol to unicode
2754 2755 # \\alpha -> α
2755 2756 return s, [latex_symbols[s]]
2756 2757 else:
2757 2758 # If a user has partially typed a latex symbol, give them
2758 2759 # a full list of options \al -> [\aleph, \alpha]
2759 2760 matches = [k for k in latex_symbols if k.startswith(s)]
2760 2761 if matches:
2761 2762 return s, matches
2762 2763 return '', ()
2763 2764
2764 2765 @context_matcher()
2765 2766 def custom_completer_matcher(self, context):
2766 2767 """Dispatch custom completer.
2767 2768
2768 2769 If a match is found, suppresses all other matchers except for Jedi.
2769 2770 """
2770 2771 matches = self.dispatch_custom_completer(context.token) or []
2771 2772 result = _convert_matcher_v1_result_to_v2(
2772 2773 matches, type=_UNKNOWN_TYPE, suppress_if_matches=True
2773 2774 )
2774 2775 result["ordered"] = True
2775 2776 result["do_not_suppress"] = {_get_matcher_id(self._jedi_matcher)}
2776 2777 return result
2777 2778
2778 2779 def dispatch_custom_completer(self, text):
2779 2780 """
2780 2781 .. deprecated:: 8.6
2781 2782 You can use :meth:`custom_completer_matcher` instead.
2782 2783 """
2783 2784 if not self.custom_completers:
2784 2785 return
2785 2786
2786 2787 line = self.line_buffer
2787 2788 if not line.strip():
2788 2789 return None
2789 2790
2790 2791 # Create a little structure to pass all the relevant information about
2791 2792 # the current completion to any custom completer.
2792 2793 event = SimpleNamespace()
2793 2794 event.line = line
2794 2795 event.symbol = text
2795 2796 cmd = line.split(None,1)[0]
2796 2797 event.command = cmd
2797 2798 event.text_until_cursor = self.text_until_cursor
2798 2799
2799 2800 # for foo etc, try also to find completer for %foo
2800 2801 if not cmd.startswith(self.magic_escape):
2801 2802 try_magic = self.custom_completers.s_matches(
2802 2803 self.magic_escape + cmd)
2803 2804 else:
2804 2805 try_magic = []
2805 2806
2806 2807 for c in itertools.chain(self.custom_completers.s_matches(cmd),
2807 2808 try_magic,
2808 2809 self.custom_completers.flat_matches(self.text_until_cursor)):
2809 2810 try:
2810 2811 res = c(event)
2811 2812 if res:
2812 2813 # first, try case sensitive match
2813 2814 withcase = [r for r in res if r.startswith(text)]
2814 2815 if withcase:
2815 2816 return withcase
2816 2817 # if none, then case insensitive ones are ok too
2817 2818 text_low = text.lower()
2818 2819 return [r for r in res if r.lower().startswith(text_low)]
2819 2820 except TryNext:
2820 2821 pass
2821 2822 except KeyboardInterrupt:
2822 2823 """
2823 2824 If custom completer take too long,
2824 2825 let keyboard interrupt abort and return nothing.
2825 2826 """
2826 2827 break
2827 2828
2828 2829 return None
2829 2830
2830 2831 def completions(self, text: str, offset: int)->Iterator[Completion]:
2831 2832 """
2832 2833 Returns an iterator over the possible completions
2833 2834
2834 2835 .. warning::
2835 2836
2836 2837 Unstable
2837 2838
2838 2839 This function is unstable, API may change without warning.
2839 2840 It will also raise unless use in proper context manager.
2840 2841
2841 2842 Parameters
2842 2843 ----------
2843 2844 text : str
2844 2845 Full text of the current input, multi line string.
2845 2846 offset : int
2846 2847 Integer representing the position of the cursor in ``text``. Offset
2847 2848 is 0-based indexed.
2848 2849
2849 2850 Yields
2850 2851 ------
2851 2852 Completion
2852 2853
2853 2854 Notes
2854 2855 -----
2855 2856 The cursor on a text can either be seen as being "in between"
2856 2857 characters or "On" a character depending on the interface visible to
2857 2858 the user. For consistency the cursor being on "in between" characters X
2858 2859 and Y is equivalent to the cursor being "on" character Y, that is to say
2859 2860 the character the cursor is on is considered as being after the cursor.
2860 2861
2861 2862 Combining characters may span more that one position in the
2862 2863 text.
2863 2864
2864 2865 .. note::
2865 2866
2866 2867 If ``IPCompleter.debug`` is :any:`True` will yield a ``--jedi/ipython--``
2867 2868 fake Completion token to distinguish completion returned by Jedi
2868 2869 and usual IPython completion.
2869 2870
2870 2871 .. note::
2871 2872
2872 2873 Completions are not completely deduplicated yet. If identical
2873 2874 completions are coming from different sources this function does not
2874 2875 ensure that each completion object will only be present once.
2875 2876 """
2876 2877 warnings.warn("_complete is a provisional API (as of IPython 6.0). "
2877 2878 "It may change without warnings. "
2878 2879 "Use in corresponding context manager.",
2879 2880 category=ProvisionalCompleterWarning, stacklevel=2)
2880 2881
2881 2882 seen = set()
2882 2883 profiler:Optional[cProfile.Profile]
2883 2884 try:
2884 2885 if self.profile_completions:
2885 2886 import cProfile
2886 2887 profiler = cProfile.Profile()
2887 2888 profiler.enable()
2888 2889 else:
2889 2890 profiler = None
2890 2891
2891 2892 for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000):
2892 2893 if c and (c in seen):
2893 2894 continue
2894 2895 yield c
2895 2896 seen.add(c)
2896 2897 except KeyboardInterrupt:
2897 2898 """if completions take too long and users send keyboard interrupt,
2898 2899 do not crash and return ASAP. """
2899 2900 pass
2900 2901 finally:
2901 2902 if profiler is not None:
2902 2903 profiler.disable()
2903 2904 ensure_dir_exists(self.profiler_output_dir)
2904 2905 output_path = os.path.join(self.profiler_output_dir, str(uuid.uuid4()))
2905 2906 print("Writing profiler output to", output_path)
2906 2907 profiler.dump_stats(output_path)
2907 2908
2908 2909 def _completions(self, full_text: str, offset: int, *, _timeout) -> Iterator[Completion]:
2909 2910 """
2910 2911 Core completion module.Same signature as :any:`completions`, with the
2911 2912 extra `timeout` parameter (in seconds).
2912 2913
2913 2914 Computing jedi's completion ``.type`` can be quite expensive (it is a
2914 2915 lazy property) and can require some warm-up, more warm up than just
2915 2916 computing the ``name`` of a completion. The warm-up can be :
2916 2917
2917 2918 - Long warm-up the first time a module is encountered after
2918 2919 install/update: actually build parse/inference tree.
2919 2920
2920 2921 - first time the module is encountered in a session: load tree from
2921 2922 disk.
2922 2923
2923 2924 We don't want to block completions for tens of seconds so we give the
2924 2925 completer a "budget" of ``_timeout`` seconds per invocation to compute
2925 2926 completions types, the completions that have not yet been computed will
2926 2927 be marked as "unknown" an will have a chance to be computed next round
2927 2928 are things get cached.
2928 2929
2929 2930 Keep in mind that Jedi is not the only thing treating the completion so
2930 2931 keep the timeout short-ish as if we take more than 0.3 second we still
2931 2932 have lots of processing to do.
2932 2933
2933 2934 """
2934 2935 deadline = time.monotonic() + _timeout
2935 2936
2936 2937 before = full_text[:offset]
2937 2938 cursor_line, cursor_column = position_to_cursor(full_text, offset)
2938 2939
2939 2940 jedi_matcher_id = _get_matcher_id(self._jedi_matcher)
2940 2941
2941 2942 def is_non_jedi_result(
2942 2943 result: MatcherResult, identifier: str
2943 2944 ) -> TypeGuard[SimpleMatcherResult]:
2944 2945 return identifier != jedi_matcher_id
2945 2946
2946 2947 results = self._complete(
2947 2948 full_text=full_text, cursor_line=cursor_line, cursor_pos=cursor_column
2948 2949 )
2949 2950
2950 2951 non_jedi_results: Dict[str, SimpleMatcherResult] = {
2951 2952 identifier: result
2952 2953 for identifier, result in results.items()
2953 2954 if is_non_jedi_result(result, identifier)
2954 2955 }
2955 2956
2956 2957 jedi_matches = (
2957 2958 cast(_JediMatcherResult, results[jedi_matcher_id])["completions"]
2958 2959 if jedi_matcher_id in results
2959 2960 else ()
2960 2961 )
2961 2962
2962 2963 iter_jm = iter(jedi_matches)
2963 2964 if _timeout:
2964 2965 for jm in iter_jm:
2965 2966 try:
2966 2967 type_ = jm.type
2967 2968 except Exception:
2968 2969 if self.debug:
2969 2970 print("Error in Jedi getting type of ", jm)
2970 2971 type_ = None
2971 2972 delta = len(jm.name_with_symbols) - len(jm.complete)
2972 2973 if type_ == 'function':
2973 2974 signature = _make_signature(jm)
2974 2975 else:
2975 2976 signature = ''
2976 2977 yield Completion(start=offset - delta,
2977 2978 end=offset,
2978 2979 text=jm.name_with_symbols,
2979 2980 type=type_,
2980 2981 signature=signature,
2981 2982 _origin='jedi')
2982 2983
2983 2984 if time.monotonic() > deadline:
2984 2985 break
2985 2986
2986 2987 for jm in iter_jm:
2987 2988 delta = len(jm.name_with_symbols) - len(jm.complete)
2988 2989 yield Completion(
2989 2990 start=offset - delta,
2990 2991 end=offset,
2991 2992 text=jm.name_with_symbols,
2992 2993 type=_UNKNOWN_TYPE, # don't compute type for speed
2993 2994 _origin="jedi",
2994 2995 signature="",
2995 2996 )
2996 2997
2997 2998 # TODO:
2998 2999 # Suppress this, right now just for debug.
2999 3000 if jedi_matches and non_jedi_results and self.debug:
3000 3001 some_start_offset = before.rfind(
3001 3002 next(iter(non_jedi_results.values()))["matched_fragment"]
3002 3003 )
3003 3004 yield Completion(
3004 3005 start=some_start_offset,
3005 3006 end=offset,
3006 3007 text="--jedi/ipython--",
3007 3008 _origin="debug",
3008 3009 type="none",
3009 3010 signature="",
3010 3011 )
3011 3012
3012 3013 ordered: List[Completion] = []
3013 3014 sortable: List[Completion] = []
3014 3015
3015 3016 for origin, result in non_jedi_results.items():
3016 3017 matched_text = result["matched_fragment"]
3017 3018 start_offset = before.rfind(matched_text)
3018 3019 is_ordered = result.get("ordered", False)
3019 3020 container = ordered if is_ordered else sortable
3020 3021
3021 3022 # I'm unsure if this is always true, so let's assert and see if it
3022 3023 # crash
3023 3024 assert before.endswith(matched_text)
3024 3025
3025 3026 for simple_completion in result["completions"]:
3026 3027 completion = Completion(
3027 3028 start=start_offset,
3028 3029 end=offset,
3029 3030 text=simple_completion.text,
3030 3031 _origin=origin,
3031 3032 signature="",
3032 3033 type=simple_completion.type or _UNKNOWN_TYPE,
3033 3034 )
3034 3035 container.append(completion)
3035 3036
3036 3037 yield from list(self._deduplicate(ordered + self._sort(sortable)))[
3037 3038 :MATCHES_LIMIT
3038 3039 ]
3039 3040
3040 3041 def complete(self, text=None, line_buffer=None, cursor_pos=None) -> Tuple[str, Sequence[str]]:
3041 3042 """Find completions for the given text and line context.
3042 3043
3043 3044 Note that both the text and the line_buffer are optional, but at least
3044 3045 one of them must be given.
3045 3046
3046 3047 Parameters
3047 3048 ----------
3048 3049 text : string, optional
3049 3050 Text to perform the completion on. If not given, the line buffer
3050 3051 is split using the instance's CompletionSplitter object.
3051 3052 line_buffer : string, optional
3052 3053 If not given, the completer attempts to obtain the current line
3053 3054 buffer via readline. This keyword allows clients which are
3054 3055 requesting for text completions in non-readline contexts to inform
3055 3056 the completer of the entire text.
3056 3057 cursor_pos : int, optional
3057 3058 Index of the cursor in the full line buffer. Should be provided by
3058 3059 remote frontends where kernel has no access to frontend state.
3059 3060
3060 3061 Returns
3061 3062 -------
3062 3063 Tuple of two items:
3063 3064 text : str
3064 3065 Text that was actually used in the completion.
3065 3066 matches : list
3066 3067 A list of completion matches.
3067 3068
3068 3069 Notes
3069 3070 -----
3070 3071 This API is likely to be deprecated and replaced by
3071 3072 :any:`IPCompleter.completions` in the future.
3072 3073
3073 3074 """
3074 3075 warnings.warn('`Completer.complete` is pending deprecation since '
3075 3076 'IPython 6.0 and will be replaced by `Completer.completions`.',
3076 3077 PendingDeprecationWarning)
3077 3078 # potential todo, FOLD the 3rd throw away argument of _complete
3078 3079 # into the first 2 one.
3079 3080 # TODO: Q: does the above refer to jedi completions (i.e. 0-indexed?)
3080 3081 # TODO: should we deprecate now, or does it stay?
3081 3082
3082 3083 results = self._complete(
3083 3084 line_buffer=line_buffer, cursor_pos=cursor_pos, text=text, cursor_line=0
3084 3085 )
3085 3086
3086 3087 jedi_matcher_id = _get_matcher_id(self._jedi_matcher)
3087 3088
3088 3089 return self._arrange_and_extract(
3089 3090 results,
3090 3091 # TODO: can we confirm that excluding Jedi here was a deliberate choice in previous version?
3091 3092 skip_matchers={jedi_matcher_id},
3092 3093 # this API does not support different start/end positions (fragments of token).
3093 3094 abort_if_offset_changes=True,
3094 3095 )
3095 3096
3096 3097 def _arrange_and_extract(
3097 3098 self,
3098 3099 results: Dict[str, MatcherResult],
3099 3100 skip_matchers: Set[str],
3100 3101 abort_if_offset_changes: bool,
3101 3102 ):
3102 3103 sortable: List[AnyMatcherCompletion] = []
3103 3104 ordered: List[AnyMatcherCompletion] = []
3104 3105 most_recent_fragment = None
3105 3106 for identifier, result in results.items():
3106 3107 if identifier in skip_matchers:
3107 3108 continue
3108 3109 if not result["completions"]:
3109 3110 continue
3110 3111 if not most_recent_fragment:
3111 3112 most_recent_fragment = result["matched_fragment"]
3112 3113 if (
3113 3114 abort_if_offset_changes
3114 3115 and result["matched_fragment"] != most_recent_fragment
3115 3116 ):
3116 3117 break
3117 3118 if result.get("ordered", False):
3118 3119 ordered.extend(result["completions"])
3119 3120 else:
3120 3121 sortable.extend(result["completions"])
3121 3122
3122 3123 if not most_recent_fragment:
3123 3124 most_recent_fragment = "" # to satisfy typechecker (and just in case)
3124 3125
3125 3126 return most_recent_fragment, [
3126 3127 m.text for m in self._deduplicate(ordered + self._sort(sortable))
3127 3128 ]
3128 3129
3129 3130 def _complete(self, *, cursor_line, cursor_pos, line_buffer=None, text=None,
3130 3131 full_text=None) -> _CompleteResult:
3131 3132 """
3132 3133 Like complete but can also returns raw jedi completions as well as the
3133 3134 origin of the completion text. This could (and should) be made much
3134 3135 cleaner but that will be simpler once we drop the old (and stateful)
3135 3136 :any:`complete` API.
3136 3137
3137 3138 With current provisional API, cursor_pos act both (depending on the
3138 3139 caller) as the offset in the ``text`` or ``line_buffer``, or as the
3139 3140 ``column`` when passing multiline strings this could/should be renamed
3140 3141 but would add extra noise.
3141 3142
3142 3143 Parameters
3143 3144 ----------
3144 3145 cursor_line
3145 3146 Index of the line the cursor is on. 0 indexed.
3146 3147 cursor_pos
3147 3148 Position of the cursor in the current line/line_buffer/text. 0
3148 3149 indexed.
3149 3150 line_buffer : optional, str
3150 3151 The current line the cursor is in, this is mostly due to legacy
3151 3152 reason that readline could only give a us the single current line.
3152 3153 Prefer `full_text`.
3153 3154 text : str
3154 3155 The current "token" the cursor is in, mostly also for historical
3155 3156 reasons. as the completer would trigger only after the current line
3156 3157 was parsed.
3157 3158 full_text : str
3158 3159 Full text of the current cell.
3159 3160
3160 3161 Returns
3161 3162 -------
3162 3163 An ordered dictionary where keys are identifiers of completion
3163 3164 matchers and values are ``MatcherResult``s.
3164 3165 """
3165 3166
3166 3167 # if the cursor position isn't given, the only sane assumption we can
3167 3168 # make is that it's at the end of the line (the common case)
3168 3169 if cursor_pos is None:
3169 3170 cursor_pos = len(line_buffer) if text is None else len(text)
3170 3171
3171 3172 if self.use_main_ns:
3172 3173 self.namespace = __main__.__dict__
3173 3174
3174 3175 # if text is either None or an empty string, rely on the line buffer
3175 3176 if (not line_buffer) and full_text:
3176 3177 line_buffer = full_text.split('\n')[cursor_line]
3177 3178 if not text: # issue #11508: check line_buffer before calling split_line
3178 3179 text = (
3179 3180 self.splitter.split_line(line_buffer, cursor_pos) if line_buffer else ""
3180 3181 )
3181 3182
3182 3183 # If no line buffer is given, assume the input text is all there was
3183 3184 if line_buffer is None:
3184 3185 line_buffer = text
3185 3186
3186 3187 # deprecated - do not use `line_buffer` in new code.
3187 3188 self.line_buffer = line_buffer
3188 3189 self.text_until_cursor = self.line_buffer[:cursor_pos]
3189 3190
3190 3191 if not full_text:
3191 3192 full_text = line_buffer
3192 3193
3193 3194 context = CompletionContext(
3194 3195 full_text=full_text,
3195 3196 cursor_position=cursor_pos,
3196 3197 cursor_line=cursor_line,
3197 3198 token=text,
3198 3199 limit=MATCHES_LIMIT,
3199 3200 )
3200 3201
3201 3202 # Start with a clean slate of completions
3202 3203 results: Dict[str, MatcherResult] = {}
3203 3204
3204 3205 jedi_matcher_id = _get_matcher_id(self._jedi_matcher)
3205 3206
3206 3207 suppressed_matchers: Set[str] = set()
3207 3208
3208 3209 matchers = {
3209 3210 _get_matcher_id(matcher): matcher
3210 3211 for matcher in sorted(
3211 3212 self.matchers, key=_get_matcher_priority, reverse=True
3212 3213 )
3213 3214 }
3214 3215
3215 3216 for matcher_id, matcher in matchers.items():
3216 3217 matcher_id = _get_matcher_id(matcher)
3217 3218
3218 3219 if matcher_id in self.disable_matchers:
3219 3220 continue
3220 3221
3221 3222 if matcher_id in results:
3222 3223 warnings.warn(f"Duplicate matcher ID: {matcher_id}.")
3223 3224
3224 3225 if matcher_id in suppressed_matchers:
3225 3226 continue
3226 3227
3227 3228 result: MatcherResult
3228 3229 try:
3229 3230 if _is_matcher_v1(matcher):
3230 3231 result = _convert_matcher_v1_result_to_v2(
3231 3232 matcher(text), type=_UNKNOWN_TYPE
3232 3233 )
3233 3234 elif _is_matcher_v2(matcher):
3234 3235 result = matcher(context)
3235 3236 else:
3236 3237 api_version = _get_matcher_api_version(matcher)
3237 3238 raise ValueError(f"Unsupported API version {api_version}")
3238 3239 except BaseException:
3239 3240 # Show the ugly traceback if the matcher causes an
3240 3241 # exception, but do NOT crash the kernel!
3241 3242 sys.excepthook(*sys.exc_info())
3242 3243 continue
3243 3244
3244 3245 # set default value for matched fragment if suffix was not selected.
3245 3246 result["matched_fragment"] = result.get("matched_fragment", context.token)
3246 3247
3247 3248 if not suppressed_matchers:
3248 3249 suppression_recommended: Union[bool, Set[str]] = result.get(
3249 3250 "suppress", False
3250 3251 )
3251 3252
3252 3253 suppression_config = (
3253 3254 self.suppress_competing_matchers.get(matcher_id, None)
3254 3255 if isinstance(self.suppress_competing_matchers, dict)
3255 3256 else self.suppress_competing_matchers
3256 3257 )
3257 3258 should_suppress = (
3258 3259 (suppression_config is True)
3259 3260 or (suppression_recommended and (suppression_config is not False))
3260 3261 ) and has_any_completions(result)
3261 3262
3262 3263 if should_suppress:
3263 3264 suppression_exceptions: Set[str] = result.get(
3264 3265 "do_not_suppress", set()
3265 3266 )
3266 3267 if isinstance(suppression_recommended, Iterable):
3267 3268 to_suppress = set(suppression_recommended)
3268 3269 else:
3269 3270 to_suppress = set(matchers)
3270 3271 suppressed_matchers = to_suppress - suppression_exceptions
3271 3272
3272 3273 new_results = {}
3273 3274 for previous_matcher_id, previous_result in results.items():
3274 3275 if previous_matcher_id not in suppressed_matchers:
3275 3276 new_results[previous_matcher_id] = previous_result
3276 3277 results = new_results
3277 3278
3278 3279 results[matcher_id] = result
3279 3280
3280 3281 _, matches = self._arrange_and_extract(
3281 3282 results,
3282 3283 # TODO Jedi completions non included in legacy stateful API; was this deliberate or omission?
3283 3284 # if it was omission, we can remove the filtering step, otherwise remove this comment.
3284 3285 skip_matchers={jedi_matcher_id},
3285 3286 abort_if_offset_changes=False,
3286 3287 )
3287 3288
3288 3289 # populate legacy stateful API
3289 3290 self.matches = matches
3290 3291
3291 3292 return results
3292 3293
3293 3294 @staticmethod
3294 3295 def _deduplicate(
3295 3296 matches: Sequence[AnyCompletion],
3296 3297 ) -> Iterable[AnyCompletion]:
3297 3298 filtered_matches: Dict[str, AnyCompletion] = {}
3298 3299 for match in matches:
3299 3300 text = match.text
3300 3301 if (
3301 3302 text not in filtered_matches
3302 3303 or filtered_matches[text].type == _UNKNOWN_TYPE
3303 3304 ):
3304 3305 filtered_matches[text] = match
3305 3306
3306 3307 return filtered_matches.values()
3307 3308
3308 3309 @staticmethod
3309 3310 def _sort(matches: Sequence[AnyCompletion]):
3310 3311 return sorted(matches, key=lambda x: completions_sorting_key(x.text))
3311 3312
3312 3313 @context_matcher()
3313 3314 def fwd_unicode_matcher(self, context: CompletionContext):
3314 3315 """Same as :any:`fwd_unicode_match`, but adopted to new Matcher API."""
3315 3316 # TODO: use `context.limit` to terminate early once we matched the maximum
3316 3317 # number that will be used downstream; can be added as an optional to
3317 3318 # `fwd_unicode_match(text: str, limit: int = None)` or we could re-implement here.
3318 3319 fragment, matches = self.fwd_unicode_match(context.text_until_cursor)
3319 3320 return _convert_matcher_v1_result_to_v2(
3320 3321 matches, type="unicode", fragment=fragment, suppress_if_matches=True
3321 3322 )
3322 3323
3323 3324 def fwd_unicode_match(self, text: str) -> Tuple[str, Sequence[str]]:
3324 3325 """
3325 3326 Forward match a string starting with a backslash with a list of
3326 3327 potential Unicode completions.
3327 3328
3328 3329 Will compute list of Unicode character names on first call and cache it.
3329 3330
3330 3331 .. deprecated:: 8.6
3331 3332 You can use :meth:`fwd_unicode_matcher` instead.
3332 3333
3333 3334 Returns
3334 3335 -------
3335 3336 At tuple with:
3336 3337 - matched text (empty if no matches)
3337 3338 - list of potential completions, empty tuple otherwise)
3338 3339 """
3339 3340 # TODO: self.unicode_names is here a list we traverse each time with ~100k elements.
3340 3341 # We could do a faster match using a Trie.
3341 3342
3342 3343 # Using pygtrie the following seem to work:
3343 3344
3344 3345 # s = PrefixSet()
3345 3346
3346 3347 # for c in range(0,0x10FFFF + 1):
3347 3348 # try:
3348 3349 # s.add(unicodedata.name(chr(c)))
3349 3350 # except ValueError:
3350 3351 # pass
3351 3352 # [''.join(k) for k in s.iter(prefix)]
3352 3353
3353 3354 # But need to be timed and adds an extra dependency.
3354 3355
3355 3356 slashpos = text.rfind('\\')
3356 3357 # if text starts with slash
3357 3358 if slashpos > -1:
3358 3359 # PERF: It's important that we don't access self._unicode_names
3359 3360 # until we're inside this if-block. _unicode_names is lazily
3360 3361 # initialized, and it takes a user-noticeable amount of time to
3361 3362 # initialize it, so we don't want to initialize it unless we're
3362 3363 # actually going to use it.
3363 3364 s = text[slashpos + 1 :]
3364 3365 sup = s.upper()
3365 3366 candidates = [x for x in self.unicode_names if x.startswith(sup)]
3366 3367 if candidates:
3367 3368 return s, candidates
3368 3369 candidates = [x for x in self.unicode_names if sup in x]
3369 3370 if candidates:
3370 3371 return s, candidates
3371 3372 splitsup = sup.split(" ")
3372 3373 candidates = [
3373 3374 x for x in self.unicode_names if all(u in x for u in splitsup)
3374 3375 ]
3375 3376 if candidates:
3376 3377 return s, candidates
3377 3378
3378 3379 return "", ()
3379 3380
3380 3381 # if text does not start with slash
3381 3382 else:
3382 3383 return '', ()
3383 3384
3384 3385 @property
3385 3386 def unicode_names(self) -> List[str]:
3386 3387 """List of names of unicode code points that can be completed.
3387 3388
3388 3389 The list is lazily initialized on first access.
3389 3390 """
3390 3391 if self._unicode_names is None:
3391 3392 names = []
3392 3393 for c in range(0,0x10FFFF + 1):
3393 3394 try:
3394 3395 names.append(unicodedata.name(chr(c)))
3395 3396 except ValueError:
3396 3397 pass
3397 3398 self._unicode_names = _unicode_name_compute(_UNICODE_RANGES)
3398 3399
3399 3400 return self._unicode_names
3400 3401
3401 3402 def _unicode_name_compute(ranges:List[Tuple[int,int]]) -> List[str]:
3402 3403 names = []
3403 3404 for start,stop in ranges:
3404 3405 for c in range(start, stop) :
3405 3406 try:
3406 3407 names.append(unicodedata.name(chr(c)))
3407 3408 except ValueError:
3408 3409 pass
3409 3410 return names
@@ -1,1131 +1,1136
1 1 """
2 2 Pdb debugger class.
3 3
4 4
5 5 This is an extension to PDB which adds a number of new features.
6 6 Note that there is also the `IPython.terminal.debugger` class which provides UI
7 7 improvements.
8 8
9 9 We also strongly recommend to use this via the `ipdb` package, which provides
10 10 extra configuration options.
11 11
12 12 Among other things, this subclass of PDB:
13 13 - supports many IPython magics like pdef/psource
14 14 - hide frames in tracebacks based on `__tracebackhide__`
15 15 - allows to skip frames based on `__debuggerskip__`
16 16
17 17
18 18 Global Configuration
19 19 --------------------
20 20
21 21 The IPython debugger will by read the global ``~/.pdbrc`` file.
22 22 That is to say you can list all commands supported by ipdb in your `~/.pdbrc`
23 23 configuration file, to globally configure pdb.
24 24
25 25 Example::
26 26
27 27 # ~/.pdbrc
28 28 skip_predicates debuggerskip false
29 29 skip_hidden false
30 30 context 25
31 31
32 32 Features
33 33 --------
34 34
35 35 The IPython debugger can hide and skip frames when printing or moving through
36 36 the stack. This can have a performance impact, so can be configures.
37 37
38 38 The skipping and hiding frames are configurable via the `skip_predicates`
39 39 command.
40 40
41 41 By default, frames from readonly files will be hidden, frames containing
42 42 ``__tracebackhide__ = True`` will be hidden.
43 43
44 44 Frames containing ``__debuggerskip__`` will be stepped over, frames whose parent
45 45 frames value of ``__debuggerskip__`` is ``True`` will also be skipped.
46 46
47 47 >>> def helpers_helper():
48 48 ... pass
49 49 ...
50 50 ... def helper_1():
51 51 ... print("don't step in me")
52 52 ... helpers_helpers() # will be stepped over unless breakpoint set.
53 53 ...
54 54 ...
55 55 ... def helper_2():
56 56 ... print("in me neither")
57 57 ...
58 58
59 59 One can define a decorator that wraps a function between the two helpers:
60 60
61 61 >>> def pdb_skipped_decorator(function):
62 62 ...
63 63 ...
64 64 ... def wrapped_fn(*args, **kwargs):
65 65 ... __debuggerskip__ = True
66 66 ... helper_1()
67 67 ... __debuggerskip__ = False
68 68 ... result = function(*args, **kwargs)
69 69 ... __debuggerskip__ = True
70 70 ... helper_2()
71 71 ... # setting __debuggerskip__ to False again is not necessary
72 72 ... return result
73 73 ...
74 74 ... return wrapped_fn
75 75
76 76 When decorating a function, ipdb will directly step into ``bar()`` by
77 77 default:
78 78
79 79 >>> @foo_decorator
80 80 ... def bar(x, y):
81 81 ... return x * y
82 82
83 83
84 84 You can toggle the behavior with
85 85
86 86 ipdb> skip_predicates debuggerskip false
87 87
88 88 or configure it in your ``.pdbrc``
89 89
90 90
91 91
92 92 License
93 93 -------
94 94
95 95 Modified from the standard pdb.Pdb class to avoid including readline, so that
96 96 the command line completion of other programs which include this isn't
97 97 damaged.
98 98
99 99 In the future, this class will be expanded with improvements over the standard
100 100 pdb.
101 101
102 102 The original code in this file is mainly lifted out of cmd.py in Python 2.2,
103 103 with minor changes. Licensing should therefore be under the standard Python
104 104 terms. For details on the PSF (Python Software Foundation) standard license,
105 105 see:
106 106
107 107 https://docs.python.org/2/license.html
108 108
109 109
110 110 All the changes since then are under the same license as IPython.
111 111
112 112 """
113 113
114 114 #*****************************************************************************
115 115 #
116 116 # This file is licensed under the PSF license.
117 117 #
118 118 # Copyright (C) 2001 Python Software Foundation, www.python.org
119 119 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
120 120 #
121 121 #
122 122 #*****************************************************************************
123 123
124 124 from __future__ import annotations
125 125
126 126 import inspect
127 127 import linecache
128 128 import os
129 129 import re
130 130 import sys
131 131 from contextlib import contextmanager
132 132 from functools import lru_cache
133 133
134 134 from IPython import get_ipython
135 135 from IPython.core.excolors import exception_colors
136 from IPython.utils import PyColorize, py3compat
136 from IPython.utils import PyColorize, coloransi, py3compat
137 137
138 138 from typing import TYPE_CHECKING
139 139
140 140 if TYPE_CHECKING:
141 141 # otherwise circular import
142 142 from IPython.core.interactiveshell import InteractiveShell
143 143
144 144 # skip module docstests
145 145 __skip_doctest__ = True
146 146
147 147 prompt = 'ipdb> '
148 148
149 149 # We have to check this directly from sys.argv, config struct not yet available
150 150 from pdb import Pdb as OldPdb
151 151
152 152 # Allow the set_trace code to operate outside of an ipython instance, even if
153 153 # it does so with some limitations. The rest of this support is implemented in
154 154 # the Tracer constructor.
155 155
156 156 DEBUGGERSKIP = "__debuggerskip__"
157 157
158 158
159 159 # this has been implemented in Pdb in Python 3.13 (https://github.com/python/cpython/pull/106676
160 160 # on lower python versions, we backported the feature.
161 161 CHAIN_EXCEPTIONS = sys.version_info < (3, 13)
162 162
163 163
164 164 def make_arrow(pad):
165 165 """generate the leading arrow in front of traceback or debugger"""
166 166 if pad >= 2:
167 167 return '-'*(pad-2) + '> '
168 168 elif pad == 1:
169 169 return '>'
170 170 return ''
171 171
172 172
173 173 def BdbQuit_excepthook(et, ev, tb, excepthook=None):
174 174 """Exception hook which handles `BdbQuit` exceptions.
175 175
176 176 All other exceptions are processed using the `excepthook`
177 177 parameter.
178 178 """
179 179 raise ValueError(
180 180 "`BdbQuit_excepthook` is deprecated since version 5.1. It is still around only because it is still imported by ipdb.",
181 181 )
182 182
183 183
184 184 RGX_EXTRA_INDENT = re.compile(r'(?<=\n)\s+')
185 185
186 186
187 187 def strip_indentation(multiline_string):
188 188 return RGX_EXTRA_INDENT.sub('', multiline_string)
189 189
190 190
191 191 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
192 192 """Make new_fn have old_fn's doc string. This is particularly useful
193 193 for the ``do_...`` commands that hook into the help system.
194 194 Adapted from from a comp.lang.python posting
195 195 by Duncan Booth."""
196 196 def wrapper(*args, **kw):
197 197 return new_fn(*args, **kw)
198 198 if old_fn.__doc__:
199 199 wrapper.__doc__ = strip_indentation(old_fn.__doc__) + additional_text
200 200 return wrapper
201 201
202 202
203 203 class Pdb(OldPdb):
204 204 """Modified Pdb class, does not load readline.
205 205
206 206 for a standalone version that uses prompt_toolkit, see
207 207 `IPython.terminal.debugger.TerminalPdb` and
208 208 `IPython.terminal.debugger.set_trace()`
209 209
210 210
211 211 This debugger can hide and skip frames that are tagged according to some predicates.
212 212 See the `skip_predicates` commands.
213 213
214 214 """
215 215
216 216 shell: InteractiveShell
217 217
218 218 if CHAIN_EXCEPTIONS:
219 219 MAX_CHAINED_EXCEPTION_DEPTH = 999
220 220
221 221 default_predicates = {
222 222 "tbhide": True,
223 223 "readonly": False,
224 224 "ipython_internal": True,
225 225 "debuggerskip": True,
226 226 }
227 227
228 228 def __init__(self, completekey=None, stdin=None, stdout=None, context=5, **kwargs):
229 229 """Create a new IPython debugger.
230 230
231 231 Parameters
232 232 ----------
233 233 completekey : default None
234 234 Passed to pdb.Pdb.
235 235 stdin : default None
236 236 Passed to pdb.Pdb.
237 237 stdout : default None
238 238 Passed to pdb.Pdb.
239 239 context : int
240 240 Number of lines of source code context to show when
241 241 displaying stacktrace information.
242 242 **kwargs
243 243 Passed to pdb.Pdb.
244 244
245 245 Notes
246 246 -----
247 247 The possibilities are python version dependent, see the python
248 248 docs for more info.
249 249 """
250 250
251 251 # Parent constructor:
252 252 try:
253 253 self.context = int(context)
254 254 if self.context <= 0:
255 255 raise ValueError("Context must be a positive integer")
256 256 except (TypeError, ValueError) as e:
257 257 raise ValueError("Context must be a positive integer") from e
258 258
259 259 # `kwargs` ensures full compatibility with stdlib's `pdb.Pdb`.
260 260 OldPdb.__init__(self, completekey, stdin, stdout, **kwargs)
261 261
262 262 # IPython changes...
263 263 self.shell = get_ipython()
264 264
265 265 if self.shell is None:
266 266 save_main = sys.modules['__main__']
267 267 # No IPython instance running, we must create one
268 268 from IPython.terminal.interactiveshell import \
269 269 TerminalInteractiveShell
270 270 self.shell = TerminalInteractiveShell.instance()
271 271 # needed by any code which calls __import__("__main__") after
272 272 # the debugger was entered. See also #9941.
273 273 sys.modules["__main__"] = save_main
274 274
275 275
276 276 color_scheme = self.shell.colors
277 277
278 278 self.aliases = {}
279 279
280 280 # Create color table: we copy the default one from the traceback
281 281 # module and add a few attributes needed for debugging
282 282 self.color_scheme_table = exception_colors()
283 283
284 # shorthands
285 C = coloransi.TermColors
286 cst = self.color_scheme_table
287
288
284 289 # Add a python parser so we can syntax highlight source while
285 290 # debugging.
286 291 self.parser = PyColorize.Parser(style=color_scheme)
287 292 self.set_colors(color_scheme)
288 293
289 294 # Set the prompt - the default prompt is '(Pdb)'
290 295 self.prompt = prompt
291 296 self.skip_hidden = True
292 297 self.report_skipped = True
293 298
294 299 # list of predicates we use to skip frames
295 300 self._predicates = self.default_predicates
296 301
297 302 if CHAIN_EXCEPTIONS:
298 303 self._chained_exceptions = tuple()
299 304 self._chained_exception_index = 0
300 305
301 306 #
302 307 def set_colors(self, scheme):
303 308 """Shorthand access to the color table scheme selector method."""
304 309 self.color_scheme_table.set_active_scheme(scheme)
305 310 self.parser.style = scheme
306 311
307 312 def set_trace(self, frame=None):
308 313 if frame is None:
309 314 frame = sys._getframe().f_back
310 315 self.initial_frame = frame
311 316 return super().set_trace(frame)
312 317
313 318 def _hidden_predicate(self, frame):
314 319 """
315 320 Given a frame return whether it it should be hidden or not by IPython.
316 321 """
317 322
318 323 if self._predicates["readonly"]:
319 324 fname = frame.f_code.co_filename
320 325 # we need to check for file existence and interactively define
321 326 # function would otherwise appear as RO.
322 327 if os.path.isfile(fname) and not os.access(fname, os.W_OK):
323 328 return True
324 329
325 330 if self._predicates["tbhide"]:
326 331 if frame in (self.curframe, getattr(self, "initial_frame", None)):
327 332 return False
328 333 frame_locals = self._get_frame_locals(frame)
329 334 if "__tracebackhide__" not in frame_locals:
330 335 return False
331 336 return frame_locals["__tracebackhide__"]
332 337 return False
333 338
334 339 def hidden_frames(self, stack):
335 340 """
336 341 Given an index in the stack return whether it should be skipped.
337 342
338 343 This is used in up/down and where to skip frames.
339 344 """
340 345 # The f_locals dictionary is updated from the actual frame
341 346 # locals whenever the .f_locals accessor is called, so we
342 347 # avoid calling it here to preserve self.curframe_locals.
343 348 # Furthermore, there is no good reason to hide the current frame.
344 349 ip_hide = [self._hidden_predicate(s[0]) for s in stack]
345 350 ip_start = [i for i, s in enumerate(ip_hide) if s == "__ipython_bottom__"]
346 351 if ip_start and self._predicates["ipython_internal"]:
347 352 ip_hide = [h if i > ip_start[0] else True for (i, h) in enumerate(ip_hide)]
348 353 return ip_hide
349 354
350 355 if CHAIN_EXCEPTIONS:
351 356
352 357 def _get_tb_and_exceptions(self, tb_or_exc):
353 358 """
354 359 Given a tracecack or an exception, return a tuple of chained exceptions
355 360 and current traceback to inspect.
356 361 This will deal with selecting the right ``__cause__`` or ``__context__``
357 362 as well as handling cycles, and return a flattened list of exceptions we
358 363 can jump to with do_exceptions.
359 364 """
360 365 _exceptions = []
361 366 if isinstance(tb_or_exc, BaseException):
362 367 traceback, current = tb_or_exc.__traceback__, tb_or_exc
363 368
364 369 while current is not None:
365 370 if current in _exceptions:
366 371 break
367 372 _exceptions.append(current)
368 373 if current.__cause__ is not None:
369 374 current = current.__cause__
370 375 elif (
371 376 current.__context__ is not None
372 377 and not current.__suppress_context__
373 378 ):
374 379 current = current.__context__
375 380
376 381 if len(_exceptions) >= self.MAX_CHAINED_EXCEPTION_DEPTH:
377 382 self.message(
378 383 f"More than {self.MAX_CHAINED_EXCEPTION_DEPTH}"
379 384 " chained exceptions found, not all exceptions"
380 385 "will be browsable with `exceptions`."
381 386 )
382 387 break
383 388 else:
384 389 traceback = tb_or_exc
385 390 return tuple(reversed(_exceptions)), traceback
386 391
387 392 @contextmanager
388 393 def _hold_exceptions(self, exceptions):
389 394 """
390 395 Context manager to ensure proper cleaning of exceptions references
391 396 When given a chained exception instead of a traceback,
392 397 pdb may hold references to many objects which may leak memory.
393 398 We use this context manager to make sure everything is properly cleaned
394 399 """
395 400 try:
396 401 self._chained_exceptions = exceptions
397 402 self._chained_exception_index = len(exceptions) - 1
398 403 yield
399 404 finally:
400 405 # we can't put those in forget as otherwise they would
401 406 # be cleared on exception change
402 407 self._chained_exceptions = tuple()
403 408 self._chained_exception_index = 0
404 409
405 410 def do_exceptions(self, arg):
406 411 """exceptions [number]
407 412 List or change current exception in an exception chain.
408 413 Without arguments, list all the current exception in the exception
409 414 chain. Exceptions will be numbered, with the current exception indicated
410 415 with an arrow.
411 416 If given an integer as argument, switch to the exception at that index.
412 417 """
413 418 if not self._chained_exceptions:
414 419 self.message(
415 420 "Did not find chained exceptions. To move between"
416 421 " exceptions, pdb/post_mortem must be given an exception"
417 422 " object rather than a traceback."
418 423 )
419 424 return
420 425 if not arg:
421 426 for ix, exc in enumerate(self._chained_exceptions):
422 427 prompt = ">" if ix == self._chained_exception_index else " "
423 428 rep = repr(exc)
424 429 if len(rep) > 80:
425 430 rep = rep[:77] + "..."
426 431 indicator = (
427 432 " -"
428 433 if self._chained_exceptions[ix].__traceback__ is None
429 434 else f"{ix:>3}"
430 435 )
431 436 self.message(f"{prompt} {indicator} {rep}")
432 437 else:
433 438 try:
434 439 number = int(arg)
435 440 except ValueError:
436 441 self.error("Argument must be an integer")
437 442 return
438 443 if 0 <= number < len(self._chained_exceptions):
439 444 if self._chained_exceptions[number].__traceback__ is None:
440 445 self.error(
441 446 "This exception does not have a traceback, cannot jump to it"
442 447 )
443 448 return
444 449
445 450 self._chained_exception_index = number
446 451 self.setup(None, self._chained_exceptions[number].__traceback__)
447 452 self.print_stack_entry(self.stack[self.curindex])
448 453 else:
449 454 self.error("No exception with that number")
450 455
451 456 def interaction(self, frame, tb_or_exc):
452 457 try:
453 458 if CHAIN_EXCEPTIONS:
454 459 # this context manager is part of interaction in 3.13
455 460 _chained_exceptions, tb = self._get_tb_and_exceptions(tb_or_exc)
456 461 if isinstance(tb_or_exc, BaseException):
457 462 assert tb is not None, "main exception must have a traceback"
458 463 with self._hold_exceptions(_chained_exceptions):
459 464 OldPdb.interaction(self, frame, tb)
460 465 else:
461 466 OldPdb.interaction(self, frame, tb_or_exc)
462 467
463 468 except KeyboardInterrupt:
464 469 self.stdout.write("\n" + self.shell.get_exception_only())
465 470
466 471 def precmd(self, line):
467 472 """Perform useful escapes on the command before it is executed."""
468 473
469 474 if line.endswith("??"):
470 475 line = "pinfo2 " + line[:-2]
471 476 elif line.endswith("?"):
472 477 line = "pinfo " + line[:-1]
473 478
474 479 line = super().precmd(line)
475 480
476 481 return line
477 482
478 483 def new_do_quit(self, arg):
479 484 return OldPdb.do_quit(self, arg)
480 485
481 486 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
482 487
483 488 def print_stack_trace(self, context=None):
484 489 Colors = self.color_scheme_table.active_colors
485 490 ColorsNormal = Colors.Normal
486 491 if context is None:
487 492 context = self.context
488 493 try:
489 494 context = int(context)
490 495 if context <= 0:
491 496 raise ValueError("Context must be a positive integer")
492 497 except (TypeError, ValueError) as e:
493 498 raise ValueError("Context must be a positive integer") from e
494 499 try:
495 500 skipped = 0
496 501 for hidden, frame_lineno in zip(self.hidden_frames(self.stack), self.stack):
497 502 if hidden and self.skip_hidden:
498 503 skipped += 1
499 504 continue
500 505 if skipped:
501 506 print(
502 507 f"{Colors.excName} [... skipping {skipped} hidden frame(s)]{ColorsNormal}\n"
503 508 )
504 509 skipped = 0
505 510 self.print_stack_entry(frame_lineno, context=context)
506 511 if skipped:
507 512 print(
508 513 f"{Colors.excName} [... skipping {skipped} hidden frame(s)]{ColorsNormal}\n"
509 514 )
510 515 except KeyboardInterrupt:
511 516 pass
512 517
513 518 def print_stack_entry(self, frame_lineno, prompt_prefix='\n-> ',
514 519 context=None):
515 520 if context is None:
516 521 context = self.context
517 522 try:
518 523 context = int(context)
519 524 if context <= 0:
520 525 raise ValueError("Context must be a positive integer")
521 526 except (TypeError, ValueError) as e:
522 527 raise ValueError("Context must be a positive integer") from e
523 528 print(self.format_stack_entry(frame_lineno, '', context), file=self.stdout)
524 529
525 530 # vds: >>
526 531 frame, lineno = frame_lineno
527 532 filename = frame.f_code.co_filename
528 533 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
529 534 # vds: <<
530 535
531 536 def _get_frame_locals(self, frame):
532 537 """ "
533 538 Accessing f_local of current frame reset the namespace, so we want to avoid
534 539 that or the following can happen
535 540
536 541 ipdb> foo
537 542 "old"
538 543 ipdb> foo = "new"
539 544 ipdb> foo
540 545 "new"
541 546 ipdb> where
542 547 ipdb> foo
543 548 "old"
544 549
545 550 So if frame is self.current_frame we instead return self.curframe_locals
546 551
547 552 """
548 553 if frame is getattr(self, "curframe", None):
549 554 return self.curframe_locals
550 555 else:
551 556 return frame.f_locals
552 557
553 558 def format_stack_entry(self, frame_lineno, lprefix=': ', context=None):
554 559 if context is None:
555 560 context = self.context
556 561 try:
557 562 context = int(context)
558 563 if context <= 0:
559 564 print("Context must be a positive integer", file=self.stdout)
560 565 except (TypeError, ValueError):
561 566 print("Context must be a positive integer", file=self.stdout)
562 567
563 568 import reprlib
564 569
565 570 ret = []
566 571
567 572 Colors = self.color_scheme_table.active_colors
568 573 ColorsNormal = Colors.Normal
569 574 tpl_link = "%s%%s%s" % (Colors.filenameEm, ColorsNormal)
570 575 tpl_call = "%s%%s%s%%s%s" % (Colors.vName, Colors.valEm, ColorsNormal)
571 576 tpl_line = "%%s%s%%s %s%%s" % (Colors.lineno, ColorsNormal)
572 577 tpl_line_em = "%%s%s%%s %s%%s%s" % (Colors.linenoEm, Colors.line, ColorsNormal)
573 578
574 579 frame, lineno = frame_lineno
575 580
576 581 return_value = ''
577 582 loc_frame = self._get_frame_locals(frame)
578 583 if "__return__" in loc_frame:
579 584 rv = loc_frame["__return__"]
580 585 # return_value += '->'
581 586 return_value += reprlib.repr(rv) + "\n"
582 587 ret.append(return_value)
583 588
584 589 #s = filename + '(' + `lineno` + ')'
585 590 filename = self.canonic(frame.f_code.co_filename)
586 591 link = tpl_link % py3compat.cast_unicode(filename)
587 592
588 593 if frame.f_code.co_name:
589 594 func = frame.f_code.co_name
590 595 else:
591 596 func = "<lambda>"
592 597
593 598 call = ""
594 599 if func != "?":
595 600 if "__args__" in loc_frame:
596 601 args = reprlib.repr(loc_frame["__args__"])
597 602 else:
598 603 args = '()'
599 604 call = tpl_call % (func, args)
600 605
601 606 # The level info should be generated in the same format pdb uses, to
602 607 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
603 608 if frame is self.curframe:
604 609 ret.append('> ')
605 610 else:
606 611 ret.append(" ")
607 612 ret.append("%s(%s)%s\n" % (link, lineno, call))
608 613
609 614 start = lineno - 1 - context//2
610 615 lines = linecache.getlines(filename)
611 616 start = min(start, len(lines) - context)
612 617 start = max(start, 0)
613 618 lines = lines[start : start + context]
614 619
615 620 for i, line in enumerate(lines):
616 621 show_arrow = start + 1 + i == lineno
617 622 linetpl = (frame is self.curframe or show_arrow) and tpl_line_em or tpl_line
618 623 ret.append(
619 624 self.__format_line(
620 625 linetpl, filename, start + 1 + i, line, arrow=show_arrow
621 626 )
622 627 )
623 628 return "".join(ret)
624 629
625 630 def __format_line(self, tpl_line, filename, lineno, line, arrow=False):
626 631 bp_mark = ""
627 632 bp_mark_color = ""
628 633
629 634 new_line, err = self.parser.format2(line, 'str')
630 635 if not err:
631 636 line = new_line
632 637
633 638 bp = None
634 639 if lineno in self.get_file_breaks(filename):
635 640 bps = self.get_breaks(filename, lineno)
636 641 bp = bps[-1]
637 642
638 643 if bp:
639 644 Colors = self.color_scheme_table.active_colors
640 645 bp_mark = str(bp.number)
641 646 bp_mark_color = Colors.breakpoint_enabled
642 647 if not bp.enabled:
643 648 bp_mark_color = Colors.breakpoint_disabled
644 649
645 650 numbers_width = 7
646 651 if arrow:
647 652 # This is the line with the error
648 653 pad = numbers_width - len(str(lineno)) - len(bp_mark)
649 654 num = '%s%s' % (make_arrow(pad), str(lineno))
650 655 else:
651 656 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
652 657
653 658 return tpl_line % (bp_mark_color + bp_mark, num, line)
654 659
655 660 def print_list_lines(self, filename, first, last):
656 661 """The printing (as opposed to the parsing part of a 'list'
657 662 command."""
658 663 try:
659 664 Colors = self.color_scheme_table.active_colors
660 665 ColorsNormal = Colors.Normal
661 666 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
662 667 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
663 668 src = []
664 669 if filename == "<string>" and hasattr(self, "_exec_filename"):
665 670 filename = self._exec_filename
666 671
667 672 for lineno in range(first, last+1):
668 673 line = linecache.getline(filename, lineno)
669 674 if not line:
670 675 break
671 676
672 677 if lineno == self.curframe.f_lineno:
673 678 line = self.__format_line(
674 679 tpl_line_em, filename, lineno, line, arrow=True
675 680 )
676 681 else:
677 682 line = self.__format_line(
678 683 tpl_line, filename, lineno, line, arrow=False
679 684 )
680 685
681 686 src.append(line)
682 687 self.lineno = lineno
683 688
684 689 print(''.join(src), file=self.stdout)
685 690
686 691 except KeyboardInterrupt:
687 692 pass
688 693
689 694 def do_skip_predicates(self, args):
690 695 """
691 696 Turn on/off individual predicates as to whether a frame should be hidden/skip.
692 697
693 698 The global option to skip (or not) hidden frames is set with skip_hidden
694 699
695 700 To change the value of a predicate
696 701
697 702 skip_predicates key [true|false]
698 703
699 704 Call without arguments to see the current values.
700 705
701 706 To permanently change the value of an option add the corresponding
702 707 command to your ``~/.pdbrc`` file. If you are programmatically using the
703 708 Pdb instance you can also change the ``default_predicates`` class
704 709 attribute.
705 710 """
706 711 if not args.strip():
707 712 print("current predicates:")
708 713 for p, v in self._predicates.items():
709 714 print(" ", p, ":", v)
710 715 return
711 716 type_value = args.strip().split(" ")
712 717 if len(type_value) != 2:
713 718 print(
714 719 f"Usage: skip_predicates <type> <value>, with <type> one of {set(self._predicates.keys())}"
715 720 )
716 721 return
717 722
718 723 type_, value = type_value
719 724 if type_ not in self._predicates:
720 725 print(f"{type_!r} not in {set(self._predicates.keys())}")
721 726 return
722 727 if value.lower() not in ("true", "yes", "1", "no", "false", "0"):
723 728 print(
724 729 f"{value!r} is invalid - use one of ('true', 'yes', '1', 'no', 'false', '0')"
725 730 )
726 731 return
727 732
728 733 self._predicates[type_] = value.lower() in ("true", "yes", "1")
729 734 if not any(self._predicates.values()):
730 735 print(
731 736 "Warning, all predicates set to False, skip_hidden may not have any effects."
732 737 )
733 738
734 739 def do_skip_hidden(self, arg):
735 740 """
736 741 Change whether or not we should skip frames with the
737 742 __tracebackhide__ attribute.
738 743 """
739 744 if not arg.strip():
740 745 print(
741 746 f"skip_hidden = {self.skip_hidden}, use 'yes','no', 'true', or 'false' to change."
742 747 )
743 748 elif arg.strip().lower() in ("true", "yes"):
744 749 self.skip_hidden = True
745 750 elif arg.strip().lower() in ("false", "no"):
746 751 self.skip_hidden = False
747 752 if not any(self._predicates.values()):
748 753 print(
749 754 "Warning, all predicates set to False, skip_hidden may not have any effects."
750 755 )
751 756
752 757 def do_list(self, arg):
753 758 """Print lines of code from the current stack frame
754 759 """
755 760 self.lastcmd = 'list'
756 761 last = None
757 762 if arg and arg != ".":
758 763 try:
759 764 x = eval(arg, {}, {})
760 765 if type(x) == type(()):
761 766 first, last = x
762 767 first = int(first)
763 768 last = int(last)
764 769 if last < first:
765 770 # Assume it's a count
766 771 last = first + last
767 772 else:
768 773 first = max(1, int(x) - 5)
769 774 except:
770 775 print('*** Error in argument:', repr(arg), file=self.stdout)
771 776 return
772 777 elif self.lineno is None or arg == ".":
773 778 first = max(1, self.curframe.f_lineno - 5)
774 779 else:
775 780 first = self.lineno + 1
776 781 if last is None:
777 782 last = first + 10
778 783 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
779 784
780 785 # vds: >>
781 786 lineno = first
782 787 filename = self.curframe.f_code.co_filename
783 788 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
784 789 # vds: <<
785 790
786 791 do_l = do_list
787 792
788 793 def getsourcelines(self, obj):
789 794 lines, lineno = inspect.findsource(obj)
790 795 if inspect.isframe(obj) and obj.f_globals is self._get_frame_locals(obj):
791 796 # must be a module frame: do not try to cut a block out of it
792 797 return lines, 1
793 798 elif inspect.ismodule(obj):
794 799 return lines, 1
795 800 return inspect.getblock(lines[lineno:]), lineno+1
796 801
797 802 def do_longlist(self, arg):
798 803 """Print lines of code from the current stack frame.
799 804
800 805 Shows more lines than 'list' does.
801 806 """
802 807 self.lastcmd = 'longlist'
803 808 try:
804 809 lines, lineno = self.getsourcelines(self.curframe)
805 810 except OSError as err:
806 811 self.error(err)
807 812 return
808 813 last = lineno + len(lines)
809 814 self.print_list_lines(self.curframe.f_code.co_filename, lineno, last)
810 815 do_ll = do_longlist
811 816
812 817 def do_debug(self, arg):
813 818 """debug code
814 819 Enter a recursive debugger that steps through the code
815 820 argument (which is an arbitrary expression or statement to be
816 821 executed in the current environment).
817 822 """
818 823 trace_function = sys.gettrace()
819 824 sys.settrace(None)
820 825 globals = self.curframe.f_globals
821 826 locals = self.curframe_locals
822 827 p = self.__class__(completekey=self.completekey,
823 828 stdin=self.stdin, stdout=self.stdout)
824 829 p.use_rawinput = self.use_rawinput
825 830 p.prompt = "(%s) " % self.prompt.strip()
826 831 self.message("ENTERING RECURSIVE DEBUGGER")
827 832 sys.call_tracing(p.run, (arg, globals, locals))
828 833 self.message("LEAVING RECURSIVE DEBUGGER")
829 834 sys.settrace(trace_function)
830 835 self.lastcmd = p.lastcmd
831 836
832 837 def do_pdef(self, arg):
833 838 """Print the call signature for any callable object.
834 839
835 840 The debugger interface to %pdef"""
836 841 namespaces = [
837 842 ("Locals", self.curframe_locals),
838 843 ("Globals", self.curframe.f_globals),
839 844 ]
840 845 self.shell.find_line_magic("pdef")(arg, namespaces=namespaces)
841 846
842 847 def do_pdoc(self, arg):
843 848 """Print the docstring for an object.
844 849
845 850 The debugger interface to %pdoc."""
846 851 namespaces = [
847 852 ("Locals", self.curframe_locals),
848 853 ("Globals", self.curframe.f_globals),
849 854 ]
850 855 self.shell.find_line_magic("pdoc")(arg, namespaces=namespaces)
851 856
852 857 def do_pfile(self, arg):
853 858 """Print (or run through pager) the file where an object is defined.
854 859
855 860 The debugger interface to %pfile.
856 861 """
857 862 namespaces = [
858 863 ("Locals", self.curframe_locals),
859 864 ("Globals", self.curframe.f_globals),
860 865 ]
861 866 self.shell.find_line_magic("pfile")(arg, namespaces=namespaces)
862 867
863 868 def do_pinfo(self, arg):
864 869 """Provide detailed information about an object.
865 870
866 871 The debugger interface to %pinfo, i.e., obj?."""
867 872 namespaces = [
868 873 ("Locals", self.curframe_locals),
869 874 ("Globals", self.curframe.f_globals),
870 875 ]
871 876 self.shell.find_line_magic("pinfo")(arg, namespaces=namespaces)
872 877
873 878 def do_pinfo2(self, arg):
874 879 """Provide extra detailed information about an object.
875 880
876 881 The debugger interface to %pinfo2, i.e., obj??."""
877 882 namespaces = [
878 883 ("Locals", self.curframe_locals),
879 884 ("Globals", self.curframe.f_globals),
880 885 ]
881 886 self.shell.find_line_magic("pinfo2")(arg, namespaces=namespaces)
882 887
883 888 def do_psource(self, arg):
884 889 """Print (or run through pager) the source code for an object."""
885 890 namespaces = [
886 891 ("Locals", self.curframe_locals),
887 892 ("Globals", self.curframe.f_globals),
888 893 ]
889 894 self.shell.find_line_magic("psource")(arg, namespaces=namespaces)
890 895
891 896 def do_where(self, arg):
892 897 """w(here)
893 898 Print a stack trace, with the most recent frame at the bottom.
894 899 An arrow indicates the "current frame", which determines the
895 900 context of most commands. 'bt' is an alias for this command.
896 901
897 902 Take a number as argument as an (optional) number of context line to
898 903 print"""
899 904 if arg:
900 905 try:
901 906 context = int(arg)
902 907 except ValueError as err:
903 908 self.error(err)
904 909 return
905 910 self.print_stack_trace(context)
906 911 else:
907 912 self.print_stack_trace()
908 913
909 914 do_w = do_where
910 915
911 916 def break_anywhere(self, frame):
912 917 """
913 918 _stop_in_decorator_internals is overly restrictive, as we may still want
914 919 to trace function calls, so we need to also update break_anywhere so
915 920 that is we don't `stop_here`, because of debugger skip, we may still
916 921 stop at any point inside the function
917 922
918 923 """
919 924
920 925 sup = super().break_anywhere(frame)
921 926 if sup:
922 927 return sup
923 928 if self._predicates["debuggerskip"]:
924 929 if DEBUGGERSKIP in frame.f_code.co_varnames:
925 930 return True
926 931 if frame.f_back and self._get_frame_locals(frame.f_back).get(DEBUGGERSKIP):
927 932 return True
928 933 return False
929 934
930 935 def _is_in_decorator_internal_and_should_skip(self, frame):
931 936 """
932 937 Utility to tell us whether we are in a decorator internal and should stop.
933 938
934 939 """
935 940 # if we are disabled don't skip
936 941 if not self._predicates["debuggerskip"]:
937 942 return False
938 943
939 944 return self._cachable_skip(frame)
940 945
941 946 @lru_cache(1024)
942 947 def _cached_one_parent_frame_debuggerskip(self, frame):
943 948 """
944 949 Cache looking up for DEBUGGERSKIP on parent frame.
945 950
946 951 This should speedup walking through deep frame when one of the highest
947 952 one does have a debugger skip.
948 953
949 954 This is likely to introduce fake positive though.
950 955 """
951 956 while getattr(frame, "f_back", None):
952 957 frame = frame.f_back
953 958 if self._get_frame_locals(frame).get(DEBUGGERSKIP):
954 959 return True
955 960 return None
956 961
957 962 @lru_cache(1024)
958 963 def _cachable_skip(self, frame):
959 964 # if frame is tagged, skip by default.
960 965 if DEBUGGERSKIP in frame.f_code.co_varnames:
961 966 return True
962 967
963 968 # if one of the parent frame value set to True skip as well.
964 969 if self._cached_one_parent_frame_debuggerskip(frame):
965 970 return True
966 971
967 972 return False
968 973
969 974 def stop_here(self, frame):
970 975 if self._is_in_decorator_internal_and_should_skip(frame) is True:
971 976 return False
972 977
973 978 hidden = False
974 979 if self.skip_hidden:
975 980 hidden = self._hidden_predicate(frame)
976 981 if hidden:
977 982 if self.report_skipped:
978 983 Colors = self.color_scheme_table.active_colors
979 984 ColorsNormal = Colors.Normal
980 985 print(
981 986 f"{Colors.excName} [... skipped 1 hidden frame]{ColorsNormal}\n"
982 987 )
983 988 return super().stop_here(frame)
984 989
985 990 def do_up(self, arg):
986 991 """u(p) [count]
987 992 Move the current frame count (default one) levels up in the
988 993 stack trace (to an older frame).
989 994
990 995 Will skip hidden frames.
991 996 """
992 997 # modified version of upstream that skips
993 998 # frames with __tracebackhide__
994 999 if self.curindex == 0:
995 1000 self.error("Oldest frame")
996 1001 return
997 1002 try:
998 1003 count = int(arg or 1)
999 1004 except ValueError:
1000 1005 self.error("Invalid frame count (%s)" % arg)
1001 1006 return
1002 1007 skipped = 0
1003 1008 if count < 0:
1004 1009 _newframe = 0
1005 1010 else:
1006 1011 counter = 0
1007 1012 hidden_frames = self.hidden_frames(self.stack)
1008 1013 for i in range(self.curindex - 1, -1, -1):
1009 1014 if hidden_frames[i] and self.skip_hidden:
1010 1015 skipped += 1
1011 1016 continue
1012 1017 counter += 1
1013 1018 if counter >= count:
1014 1019 break
1015 1020 else:
1016 1021 # if no break occurred.
1017 1022 self.error(
1018 1023 "all frames above hidden, use `skip_hidden False` to get get into those."
1019 1024 )
1020 1025 return
1021 1026
1022 1027 Colors = self.color_scheme_table.active_colors
1023 1028 ColorsNormal = Colors.Normal
1024 1029 _newframe = i
1025 1030 self._select_frame(_newframe)
1026 1031 if skipped:
1027 1032 print(
1028 1033 f"{Colors.excName} [... skipped {skipped} hidden frame(s)]{ColorsNormal}\n"
1029 1034 )
1030 1035
1031 1036 def do_down(self, arg):
1032 1037 """d(own) [count]
1033 1038 Move the current frame count (default one) levels down in the
1034 1039 stack trace (to a newer frame).
1035 1040
1036 1041 Will skip hidden frames.
1037 1042 """
1038 1043 if self.curindex + 1 == len(self.stack):
1039 1044 self.error("Newest frame")
1040 1045 return
1041 1046 try:
1042 1047 count = int(arg or 1)
1043 1048 except ValueError:
1044 1049 self.error("Invalid frame count (%s)" % arg)
1045 1050 return
1046 1051 if count < 0:
1047 1052 _newframe = len(self.stack) - 1
1048 1053 else:
1049 1054 counter = 0
1050 1055 skipped = 0
1051 1056 hidden_frames = self.hidden_frames(self.stack)
1052 1057 for i in range(self.curindex + 1, len(self.stack)):
1053 1058 if hidden_frames[i] and self.skip_hidden:
1054 1059 skipped += 1
1055 1060 continue
1056 1061 counter += 1
1057 1062 if counter >= count:
1058 1063 break
1059 1064 else:
1060 1065 self.error(
1061 1066 "all frames below hidden, use `skip_hidden False` to get get into those."
1062 1067 )
1063 1068 return
1064 1069
1065 1070 Colors = self.color_scheme_table.active_colors
1066 1071 ColorsNormal = Colors.Normal
1067 1072 if skipped:
1068 1073 print(
1069 1074 f"{Colors.excName} [... skipped {skipped} hidden frame(s)]{ColorsNormal}\n"
1070 1075 )
1071 1076 _newframe = i
1072 1077
1073 1078 self._select_frame(_newframe)
1074 1079
1075 1080 do_d = do_down
1076 1081 do_u = do_up
1077 1082
1078 1083 def do_context(self, context):
1079 1084 """context number_of_lines
1080 1085 Set the number of lines of source code to show when displaying
1081 1086 stacktrace information.
1082 1087 """
1083 1088 try:
1084 1089 new_context = int(context)
1085 1090 if new_context <= 0:
1086 1091 raise ValueError()
1087 1092 self.context = new_context
1088 1093 except ValueError:
1089 1094 self.error(
1090 1095 f"The 'context' command requires a positive integer argument (current value {self.context})."
1091 1096 )
1092 1097
1093 1098
1094 1099 class InterruptiblePdb(Pdb):
1095 1100 """Version of debugger where KeyboardInterrupt exits the debugger altogether."""
1096 1101
1097 1102 def cmdloop(self, intro=None):
1098 1103 """Wrap cmdloop() such that KeyboardInterrupt stops the debugger."""
1099 1104 try:
1100 1105 return OldPdb.cmdloop(self, intro=intro)
1101 1106 except KeyboardInterrupt:
1102 1107 self.stop_here = lambda frame: False
1103 1108 self.do_quit("")
1104 1109 sys.settrace(None)
1105 1110 self.quitting = False
1106 1111 raise
1107 1112
1108 1113 def _cmdloop(self):
1109 1114 while True:
1110 1115 try:
1111 1116 # keyboard interrupts allow for an easy way to cancel
1112 1117 # the current command, so allow them during interactive input
1113 1118 self.allow_kbdint = True
1114 1119 self.cmdloop()
1115 1120 self.allow_kbdint = False
1116 1121 break
1117 1122 except KeyboardInterrupt:
1118 1123 self.message('--KeyboardInterrupt--')
1119 1124 raise
1120 1125
1121 1126
1122 1127 def set_trace(frame=None, header=None):
1123 1128 """
1124 1129 Start debugging from `frame`.
1125 1130
1126 1131 If frame is not specified, debugging starts from caller's frame.
1127 1132 """
1128 1133 pdb = Pdb()
1129 1134 if header is not None:
1130 1135 pdb.message(header)
1131 1136 pdb.set_trace(frame or sys._getframe().f_back)
@@ -1,336 +1,336
1 1 # -*- coding: utf-8 -*-
2 2 """Displayhook for IPython.
3 3
4 4 This defines a callable class that IPython uses for `sys.displayhook`.
5 5 """
6 6
7 7 # Copyright (c) IPython Development Team.
8 8 # Distributed under the terms of the Modified BSD License.
9 9
10 10 import builtins as builtin_mod
11 11 import sys
12 12 import io as _io
13 13 import tokenize
14 14
15 15 from traitlets.config.configurable import Configurable
16 16 from traitlets import Instance, Float
17 17 from warnings import warn
18 18
19 19 # TODO: Move the various attributes (cache_size, [others now moved]). Some
20 20 # of these are also attributes of InteractiveShell. They should be on ONE object
21 21 # only and the other objects should ask that one object for their values.
22 22
23 23 class DisplayHook(Configurable):
24 24 """The custom IPython displayhook to replace sys.displayhook.
25 25
26 26 This class does many things, but the basic idea is that it is a callable
27 27 that gets called anytime user code returns a value.
28 28 """
29 29
30 30 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
31 31 allow_none=True)
32 32 exec_result = Instance('IPython.core.interactiveshell.ExecutionResult',
33 33 allow_none=True)
34 34 cull_fraction = Float(0.2)
35 35
36 36 def __init__(self, shell=None, cache_size=1000, **kwargs):
37 37 super(DisplayHook, self).__init__(shell=shell, **kwargs)
38 38 cache_size_min = 3
39 39 if cache_size <= 0:
40 40 self.do_full_cache = 0
41 41 cache_size = 0
42 42 elif cache_size < cache_size_min:
43 43 self.do_full_cache = 0
44 44 cache_size = 0
45 45 warn('caching was disabled (min value for cache size is %s).' %
46 46 cache_size_min,stacklevel=3)
47 47 else:
48 48 self.do_full_cache = 1
49 49
50 50 self.cache_size = cache_size
51 51
52 52 # we need a reference to the user-level namespace
53 53 self.shell = shell
54 54
55 55 self._,self.__,self.___ = '','',''
56 56
57 57 # these are deliberately global:
58 58 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
59 59 self.shell.user_ns.update(to_user_ns)
60 60
61 61 @property
62 62 def prompt_count(self):
63 63 return self.shell.execution_count
64 64
65 65 #-------------------------------------------------------------------------
66 66 # Methods used in __call__. Override these methods to modify the behavior
67 67 # of the displayhook.
68 68 #-------------------------------------------------------------------------
69 69
70 70 def check_for_underscore(self):
71 71 """Check if the user has set the '_' variable by hand."""
72 72 # If something injected a '_' variable in __builtin__, delete
73 73 # ipython's automatic one so we don't clobber that. gettext() in
74 74 # particular uses _, so we need to stay away from it.
75 75 if '_' in builtin_mod.__dict__:
76 76 try:
77 77 user_value = self.shell.user_ns['_']
78 78 if user_value is not self._:
79 79 return
80 80 del self.shell.user_ns['_']
81 81 except KeyError:
82 82 pass
83 83
84 84 def quiet(self):
85 85 """Should we silence the display hook because of ';'?"""
86 86 # do not print output if input ends in ';'
87 87
88 88 try:
89 89 cell = self.shell.history_manager.input_hist_parsed[-1]
90 90 except IndexError:
91 91 # some uses of ipshellembed may fail here
92 92 return False
93 93
94 94 return self.semicolon_at_end_of_expression(cell)
95 95
96 96 @staticmethod
97 97 def semicolon_at_end_of_expression(expression):
98 98 """Parse Python expression and detects whether last token is ';'"""
99 99
100 100 sio = _io.StringIO(expression)
101 101 tokens = list(tokenize.generate_tokens(sio.readline))
102 102
103 103 for token in reversed(tokens):
104 104 if token[0] in (tokenize.ENDMARKER, tokenize.NL, tokenize.NEWLINE, tokenize.COMMENT):
105 105 continue
106 106 if (token[0] == tokenize.OP) and (token[1] == ';'):
107 107 return True
108 108 else:
109 109 return False
110 110
111 111 def start_displayhook(self):
112 112 """Start the displayhook, initializing resources."""
113 113 pass
114 114
115 115 def write_output_prompt(self):
116 116 """Write the output prompt.
117 117
118 118 The default implementation simply writes the prompt to
119 119 ``sys.stdout``.
120 120 """
121 121 # Use write, not print which adds an extra space.
122 122 sys.stdout.write(self.shell.separate_out)
123 123 outprompt = 'Out[{}]: '.format(self.shell.execution_count)
124 124 if self.do_full_cache:
125 125 sys.stdout.write(outprompt)
126 126
127 127 def compute_format_data(self, result):
128 128 """Compute format data of the object to be displayed.
129 129
130 130 The format data is a generalization of the :func:`repr` of an object.
131 131 In the default implementation the format data is a :class:`dict` of
132 132 key value pair where the keys are valid MIME types and the values
133 133 are JSON'able data structure containing the raw data for that MIME
134 134 type. It is up to frontends to determine pick a MIME to to use and
135 135 display that data in an appropriate manner.
136 136
137 137 This method only computes the format data for the object and should
138 138 NOT actually print or write that to a stream.
139 139
140 140 Parameters
141 141 ----------
142 142 result : object
143 143 The Python object passed to the display hook, whose format will be
144 144 computed.
145 145
146 146 Returns
147 147 -------
148 148 (format_dict, md_dict) : dict
149 149 format_dict is a :class:`dict` whose keys are valid MIME types and values are
150 150 JSON'able raw data for that MIME type. It is recommended that
151 151 all return values of this should always include the "text/plain"
152 152 MIME type representation of the object.
153 153 md_dict is a :class:`dict` with the same MIME type keys
154 154 of metadata associated with each output.
155 155
156 156 """
157 157 return self.shell.display_formatter.format(result)
158 158
159 159 # This can be set to True by the write_output_prompt method in a subclass
160 160 prompt_end_newline = False
161 161
162 162 def write_format_data(self, format_dict, md_dict=None) -> None:
163 163 """Write the format data dict to the frontend.
164 164
165 165 This default version of this method simply writes the plain text
166 166 representation of the object to ``sys.stdout``. Subclasses should
167 167 override this method to send the entire `format_dict` to the
168 168 frontends.
169 169
170 170 Parameters
171 171 ----------
172 172 format_dict : dict
173 173 The format dict for the object passed to `sys.displayhook`.
174 174 md_dict : dict (optional)
175 175 The metadata dict to be associated with the display data.
176 176 """
177 177 if 'text/plain' not in format_dict:
178 178 # nothing to do
179 179 return
180 180 # We want to print because we want to always make sure we have a
181 181 # newline, even if all the prompt separators are ''. This is the
182 182 # standard IPython behavior.
183 183 result_repr = format_dict['text/plain']
184 184 if '\n' in result_repr:
185 185 # So that multi-line strings line up with the left column of
186 186 # the screen, instead of having the output prompt mess up
187 187 # their first line.
188 188 # We use the prompt template instead of the expanded prompt
189 189 # because the expansion may add ANSI escapes that will interfere
190 190 # with our ability to determine whether or not we should add
191 191 # a newline.
192 192 if not self.prompt_end_newline:
193 193 # But avoid extraneous empty lines.
194 194 result_repr = '\n' + result_repr
195 195
196 196 try:
197 197 print(result_repr)
198 198 except UnicodeEncodeError:
199 199 # If a character is not supported by the terminal encoding replace
200 200 # it with its \u or \x representation
201 201 print(result_repr.encode(sys.stdout.encoding,'backslashreplace').decode(sys.stdout.encoding))
202 202
203 203 def update_user_ns(self, result):
204 204 """Update user_ns with various things like _, __, _1, etc."""
205 205
206 206 # Avoid recursive reference when displaying _oh/Out
207 207 if self.cache_size and result is not self.shell.user_ns['_oh']:
208 208 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
209 209 self.cull_cache()
210 210
211 211 # Don't overwrite '_' and friends if '_' is in __builtin__
212 212 # (otherwise we cause buggy behavior for things like gettext). and
213 213 # do not overwrite _, __ or ___ if one of these has been assigned
214 214 # by the user.
215 215 update_unders = True
216 216 for unders in ['_'*i for i in range(1,4)]:
217 if unders not in self.shell.user_ns:
217 if not unders in self.shell.user_ns:
218 218 continue
219 219 if getattr(self, unders) is not self.shell.user_ns.get(unders):
220 220 update_unders = False
221 221
222 222 self.___ = self.__
223 223 self.__ = self._
224 224 self._ = result
225 225
226 226 if ('_' not in builtin_mod.__dict__) and (update_unders):
227 227 self.shell.push({'_':self._,
228 228 '__':self.__,
229 229 '___':self.___}, interactive=False)
230 230
231 231 # hackish access to top-level namespace to create _1,_2... dynamically
232 232 to_main = {}
233 233 if self.do_full_cache:
234 234 new_result = '_%s' % self.prompt_count
235 235 to_main[new_result] = result
236 236 self.shell.push(to_main, interactive=False)
237 237 self.shell.user_ns['_oh'][self.prompt_count] = result
238 238
239 239 def fill_exec_result(self, result):
240 240 if self.exec_result is not None:
241 241 self.exec_result.result = result
242 242
243 243 def log_output(self, format_dict):
244 244 """Log the output."""
245 245 if 'text/plain' not in format_dict:
246 246 # nothing to do
247 247 return
248 248 if self.shell.logger.log_output:
249 249 self.shell.logger.log_write(format_dict['text/plain'], 'output')
250 250 self.shell.history_manager.output_hist_reprs[self.prompt_count] = \
251 251 format_dict['text/plain']
252 252
253 253 def finish_displayhook(self):
254 254 """Finish up all displayhook activities."""
255 255 sys.stdout.write(self.shell.separate_out2)
256 256 sys.stdout.flush()
257 257
258 258 def __call__(self, result=None):
259 259 """Printing with history cache management.
260 260
261 261 This is invoked every time the interpreter needs to print, and is
262 262 activated by setting the variable sys.displayhook to it.
263 263 """
264 264 self.check_for_underscore()
265 265 if result is not None and not self.quiet():
266 266 self.start_displayhook()
267 267 self.write_output_prompt()
268 268 format_dict, md_dict = self.compute_format_data(result)
269 269 self.update_user_ns(result)
270 270 self.fill_exec_result(result)
271 271 if format_dict:
272 272 self.write_format_data(format_dict, md_dict)
273 273 self.log_output(format_dict)
274 274 self.finish_displayhook()
275 275
276 276 def cull_cache(self):
277 277 """Output cache is full, cull the oldest entries"""
278 278 oh = self.shell.user_ns.get('_oh', {})
279 279 sz = len(oh)
280 280 cull_count = max(int(sz * self.cull_fraction), 2)
281 281 warn('Output cache limit (currently {sz} entries) hit.\n'
282 282 'Flushing oldest {cull_count} entries.'.format(sz=sz, cull_count=cull_count))
283 283
284 284 for i, n in enumerate(sorted(oh)):
285 285 if i >= cull_count:
286 286 break
287 287 self.shell.user_ns.pop('_%i' % n, None)
288 288 oh.pop(n, None)
289 289
290 290
291 291 def flush(self):
292 292 if not self.do_full_cache:
293 293 raise ValueError("You shouldn't have reached the cache flush "
294 294 "if full caching is not enabled!")
295 295 # delete auto-generated vars from global namespace
296 296
297 297 for n in range(1,self.prompt_count + 1):
298 298 key = '_'+repr(n)
299 299 try:
300 300 del self.shell.user_ns_hidden[key]
301 301 except KeyError:
302 302 pass
303 303 try:
304 304 del self.shell.user_ns[key]
305 305 except KeyError:
306 306 pass
307 307 # In some embedded circumstances, the user_ns doesn't have the
308 308 # '_oh' key set up.
309 309 oh = self.shell.user_ns.get('_oh', None)
310 310 if oh is not None:
311 311 oh.clear()
312 312
313 313 # Release our own references to objects:
314 314 self._, self.__, self.___ = '', '', ''
315 315
316 316 if '_' not in builtin_mod.__dict__:
317 317 self.shell.user_ns.update({'_':self._,'__':self.__,'___':self.___})
318 318 import gc
319 319 # TODO: Is this really needed?
320 320 # IronPython blocks here forever
321 321 if sys.platform != "cli":
322 322 gc.collect()
323 323
324 324
325 325 class CapturingDisplayHook(object):
326 326 def __init__(self, shell, outputs=None):
327 327 self.shell = shell
328 328 if outputs is None:
329 329 outputs = []
330 330 self.outputs = outputs
331 331
332 332 def __call__(self, result=None):
333 333 if result is None:
334 334 return
335 335 format_dict, md_dict = self.shell.display_formatter.format(result)
336 336 self.outputs.append({ 'data': format_dict, 'metadata': md_dict })
@@ -1,146 +1,149
1 1 """An interface for publishing rich data to frontends.
2 2
3 3 There are two components of the display system:
4 4
5 5 * Display formatters, which take a Python object and compute the
6 6 representation of the object in various formats (text, HTML, SVG, etc.).
7 7 * The display publisher that is used to send the representation data to the
8 8 various frontends.
9 9
10 10 This module defines the logic display publishing. The display publisher uses
11 11 the ``display_data`` message type that is defined in the IPython messaging
12 12 spec.
13 13 """
14 14
15 15 # Copyright (c) IPython Development Team.
16 16 # Distributed under the terms of the Modified BSD License.
17 17
18 18
19 19 import sys
20 20
21 21 from traitlets.config.configurable import Configurable
22 22 from traitlets import List
23 23
24 # This used to be defined here - it is imported for backwards compatibility
25 from .display_functions import publish_display_data
26
24 27 import typing as t
25 28
26 29 # -----------------------------------------------------------------------------
27 30 # Main payload class
28 31 #-----------------------------------------------------------------------------
29 32
30 33
31 34 class DisplayPublisher(Configurable):
32 35 """A traited class that publishes display data to frontends.
33 36
34 37 Instances of this class are created by the main IPython object and should
35 38 be accessed there.
36 39 """
37 40
38 41 def __init__(self, shell=None, *args, **kwargs):
39 42 self.shell = shell
40 43 super().__init__(*args, **kwargs)
41 44
42 45 def _validate_data(self, data, metadata=None):
43 46 """Validate the display data.
44 47
45 48 Parameters
46 49 ----------
47 50 data : dict
48 51 The formata data dictionary.
49 52 metadata : dict
50 53 Any metadata for the data.
51 54 """
52 55
53 56 if not isinstance(data, dict):
54 57 raise TypeError('data must be a dict, got: %r' % data)
55 58 if metadata is not None:
56 59 if not isinstance(metadata, dict):
57 60 raise TypeError('metadata must be a dict, got: %r' % data)
58 61
59 62 # use * to indicate transient, update are keyword-only
60 63 def publish(self, data, metadata=None, source=None, *, transient=None, update=False, **kwargs) -> None:
61 64 """Publish data and metadata to all frontends.
62 65
63 66 See the ``display_data`` message in the messaging documentation for
64 67 more details about this message type.
65 68
66 69 The following MIME types are currently implemented:
67 70
68 71 * text/plain
69 72 * text/html
70 73 * text/markdown
71 74 * text/latex
72 75 * application/json
73 76 * application/javascript
74 77 * image/png
75 78 * image/jpeg
76 79 * image/svg+xml
77 80
78 81 Parameters
79 82 ----------
80 83 data : dict
81 84 A dictionary having keys that are valid MIME types (like
82 85 'text/plain' or 'image/svg+xml') and values that are the data for
83 86 that MIME type. The data itself must be a JSON'able data
84 87 structure. Minimally all data should have the 'text/plain' data,
85 88 which can be displayed by all frontends. If more than the plain
86 89 text is given, it is up to the frontend to decide which
87 90 representation to use.
88 91 metadata : dict
89 92 A dictionary for metadata related to the data. This can contain
90 93 arbitrary key, value pairs that frontends can use to interpret
91 94 the data. Metadata specific to each mime-type can be specified
92 95 in the metadata dict with the same mime-type keys as
93 96 the data itself.
94 97 source : str, deprecated
95 98 Unused.
96 99 transient : dict, keyword-only
97 100 A dictionary for transient data.
98 101 Data in this dictionary should not be persisted as part of saving this output.
99 102 Examples include 'display_id'.
100 103 update : bool, keyword-only, default: False
101 104 If True, only update existing outputs with the same display_id,
102 105 rather than creating a new output.
103 106 """
104 107
105 108 handlers: t.Dict = {}
106 109 if self.shell is not None:
107 110 handlers = getattr(self.shell, "mime_renderers", {})
108 111
109 112 for mime, handler in handlers.items():
110 113 if mime in data:
111 114 handler(data[mime], metadata.get(mime, None))
112 115 return
113 116
114 117 if 'text/plain' in data:
115 118 print(data['text/plain'])
116 119
117 120 def clear_output(self, wait=False):
118 121 """Clear the output of the cell receiving output."""
119 122 print('\033[2K\r', end='')
120 123 sys.stdout.flush()
121 124 print('\033[2K\r', end='')
122 125 sys.stderr.flush()
123 126
124 127
125 128 class CapturingDisplayPublisher(DisplayPublisher):
126 129 """A DisplayPublisher that stores"""
127 130
128 131 outputs: List = List()
129 132
130 133 def publish(
131 134 self, data, metadata=None, source=None, *, transient=None, update=False
132 135 ):
133 136 self.outputs.append(
134 137 {
135 138 "data": data,
136 139 "metadata": metadata,
137 140 "transient": transient,
138 141 "update": update,
139 142 }
140 143 )
141 144
142 145 def clear_output(self, wait=False):
143 146 super(CapturingDisplayPublisher, self).clear_output(wait)
144 147
145 148 # empty the list, *do not* reassign a new list
146 149 self.outputs.clear()
@@ -1,132 +1,135
1 1 # encoding: utf-8
2 2 """A class for managing IPython extensions."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 import os
8 import os.path
7 9 import sys
8 10 from importlib import import_module, reload
9 11
10 12 from traitlets.config.configurable import Configurable
13 from IPython.utils.path import ensure_dir_exists
11 14 from traitlets import Instance
12 15
13 16
14 17 #-----------------------------------------------------------------------------
15 18 # Main class
16 19 #-----------------------------------------------------------------------------
17 20
18 21 BUILTINS_EXTS = {"storemagic": False, "autoreload": False}
19 22
20 23
21 24 class ExtensionManager(Configurable):
22 25 """A class to manage IPython extensions.
23 26
24 27 An IPython extension is an importable Python module that has
25 28 a function with the signature::
26 29
27 30 def load_ipython_extension(ipython):
28 31 # Do things with ipython
29 32
30 33 This function is called after your extension is imported and the
31 34 currently active :class:`InteractiveShell` instance is passed as
32 35 the only argument. You can do anything you want with IPython at
33 36 that point, including defining new magic and aliases, adding new
34 37 components, etc.
35 38
36 39 You can also optionally define an :func:`unload_ipython_extension(ipython)`
37 40 function, which will be called if the user unloads or reloads the extension.
38 41 The extension manager will only call :func:`load_ipython_extension` again
39 42 if the extension is reloaded.
40 43
41 44 You can put your extension modules anywhere you want, as long as
42 45 they can be imported by Python's standard import mechanism.
43 46 """
44 47
45 48 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
46 49
47 50 def __init__(self, shell=None, **kwargs):
48 51 super(ExtensionManager, self).__init__(shell=shell, **kwargs)
49 52 self.loaded = set()
50 53
51 54 def load_extension(self, module_str: str):
52 55 """Load an IPython extension by its module name.
53 56
54 57 Returns the string "already loaded" if the extension is already loaded,
55 58 "no load function" if the module doesn't have a load_ipython_extension
56 59 function, or None if it succeeded.
57 60 """
58 61 try:
59 62 return self._load_extension(module_str)
60 63 except ModuleNotFoundError:
61 64 if module_str in BUILTINS_EXTS:
62 65 BUILTINS_EXTS[module_str] = True
63 66 return self._load_extension("IPython.extensions." + module_str)
64 67 raise
65 68
66 69 def _load_extension(self, module_str: str):
67 70 if module_str in self.loaded:
68 71 return "already loaded"
69 72
70 73 assert self.shell is not None
71 74
72 75 with self.shell.builtin_trap:
73 76 if module_str not in sys.modules:
74 77 mod = import_module(module_str)
75 78 mod = sys.modules[module_str]
76 79 if self._call_load_ipython_extension(mod):
77 80 self.loaded.add(module_str)
78 81 else:
79 82 return "no load function"
80 83
81 84 def unload_extension(self, module_str: str):
82 85 """Unload an IPython extension by its module name.
83 86
84 87 This function looks up the extension's name in ``sys.modules`` and
85 88 simply calls ``mod.unload_ipython_extension(self)``.
86 89
87 90 Returns the string "no unload function" if the extension doesn't define
88 91 a function to unload itself, "not loaded" if the extension isn't loaded,
89 92 otherwise None.
90 93 """
91 94 if BUILTINS_EXTS.get(module_str, False) is True:
92 95 module_str = "IPython.extensions." + module_str
93 96 if module_str not in self.loaded:
94 97 return "not loaded"
95 98
96 99 if module_str in sys.modules:
97 100 mod = sys.modules[module_str]
98 101 if self._call_unload_ipython_extension(mod):
99 102 self.loaded.discard(module_str)
100 103 else:
101 104 return "no unload function"
102 105
103 106 def reload_extension(self, module_str: str):
104 107 """Reload an IPython extension by calling reload.
105 108
106 109 If the module has not been loaded before,
107 110 :meth:`InteractiveShell.load_extension` is called. Otherwise
108 111 :func:`reload` is called and then the :func:`load_ipython_extension`
109 112 function of the module, if it exists is called.
110 113 """
111 114
112 115 if BUILTINS_EXTS.get(module_str, False) is True:
113 116 module_str = "IPython.extensions." + module_str
114 117
115 118 if (module_str in self.loaded) and (module_str in sys.modules):
116 119 self.unload_extension(module_str)
117 120 mod = sys.modules[module_str]
118 121 reload(mod)
119 122 if self._call_load_ipython_extension(mod):
120 123 self.loaded.add(module_str)
121 124 else:
122 125 self.load_extension(module_str)
123 126
124 127 def _call_load_ipython_extension(self, mod):
125 128 if hasattr(mod, 'load_ipython_extension'):
126 129 mod.load_ipython_extension(self.shell)
127 130 return True
128 131
129 132 def _call_unload_ipython_extension(self, mod):
130 133 if hasattr(mod, 'unload_ipython_extension'):
131 134 mod.unload_ipython_extension(self.shell)
132 135 return True
@@ -1,1140 +1,1141
1 1 """History related magics and functionality"""
2 2
3 3 from __future__ import annotations
4 4
5 5 # Copyright (c) IPython Development Team.
6 6 # Distributed under the terms of the Modified BSD License.
7 7
8 8
9 9 import atexit
10 10 import datetime
11 11 import re
12 12
13 13
14 14 import threading
15 15 from pathlib import Path
16 16
17 17 from decorator import decorator
18 18 from traitlets import (
19 19 Any,
20 20 Bool,
21 21 Dict,
22 22 Instance,
23 23 Integer,
24 24 List,
25 25 TraitError,
26 26 Unicode,
27 27 Union,
28 28 default,
29 29 observe,
30 30 )
31 31 from traitlets.config.configurable import LoggingConfigurable
32 32
33 33 from IPython.paths import locate_profile
34 34 from IPython.utils.decorators import undoc
35 35 from typing import Iterable, Tuple, Optional, TYPE_CHECKING
36 36 import typing
37 37 from warnings import warn
38 38
39 39 if TYPE_CHECKING:
40 40 from IPython.core.interactiveshell import InteractiveShell
41 41 from IPython.config.Configuration import Configuration
42 42
43 43 try:
44 44 from sqlite3 import DatabaseError, OperationalError
45 45 import sqlite3
46 46
47 47 sqlite3_found = True
48 48 except ModuleNotFoundError:
49 49 sqlite3_found = False
50 50
51 51 class DatabaseError(Exception): # type: ignore [no-redef]
52 52 pass
53 53
54 54 class OperationalError(Exception): # type: ignore [no-redef]
55 55 pass
56 56
57 57
58 58 InOrInOut = typing.Union[str, Tuple[str, Optional[str]]]
59 59
60 60 # -----------------------------------------------------------------------------
61 61 # Classes and functions
62 62 # -----------------------------------------------------------------------------
63 63
64 64
65 65 @undoc
66 66 class DummyDB:
67 67 """Dummy DB that will act as a black hole for history.
68 68
69 69 Only used in the absence of sqlite"""
70 70
71 71 def execute(*args: typing.Any, **kwargs: typing.Any) -> typing.List:
72 72 return []
73 73
74 74 def commit(self, *args, **kwargs): # type: ignore [no-untyped-def]
75 75 pass
76 76
77 77 def __enter__(self, *args, **kwargs): # type: ignore [no-untyped-def]
78 78 pass
79 79
80 80 def __exit__(self, *args, **kwargs): # type: ignore [no-untyped-def]
81 81 pass
82 82
83 83
84 84 @decorator
85 85 def only_when_enabled(f, self, *a, **kw): # type: ignore [no-untyped-def]
86 86 """Decorator: return an empty list in the absence of sqlite."""
87 87 if not self.enabled:
88 88 return []
89 89 else:
90 90 return f(self, *a, **kw)
91 91
92 92
93 93 # use 16kB as threshold for whether a corrupt history db should be saved
94 94 # that should be at least 100 entries or so
95 95 _SAVE_DB_SIZE = 16384
96 96
97 97
98 98 @decorator
99 99 def catch_corrupt_db(f, self, *a, **kw): # type: ignore [no-untyped-def]
100 100 """A decorator which wraps HistoryAccessor method calls to catch errors from
101 101 a corrupt SQLite database, move the old database out of the way, and create
102 102 a new one.
103 103
104 104 We avoid clobbering larger databases because this may be triggered due to filesystem issues,
105 105 not just a corrupt file.
106 106 """
107 107 try:
108 108 return f(self, *a, **kw)
109 109 except (DatabaseError, OperationalError) as e:
110 110 self._corrupt_db_counter += 1
111 111 self.log.error("Failed to open SQLite history %s (%s).", self.hist_file, e)
112 112 if self.hist_file != ":memory:":
113 113 if self._corrupt_db_counter > self._corrupt_db_limit:
114 114 self.hist_file = ":memory:"
115 115 self.log.error(
116 116 "Failed to load history too many times, history will not be saved."
117 117 )
118 118 elif self.hist_file.is_file():
119 119 # move the file out of the way
120 120 base = str(self.hist_file.parent / self.hist_file.stem)
121 121 ext = self.hist_file.suffix
122 122 size = self.hist_file.stat().st_size
123 123 if size >= _SAVE_DB_SIZE:
124 124 # if there's significant content, avoid clobbering
125 125 now = datetime.datetime.now().isoformat().replace(":", ".")
126 126 newpath = base + "-corrupt-" + now + ext
127 127 # don't clobber previous corrupt backups
128 128 for i in range(100):
129 129 if not Path(newpath).exists():
130 130 break
131 131 else:
132 132 newpath = base + "-corrupt-" + now + ("-%i" % i) + ext
133 133 else:
134 134 # not much content, possibly empty; don't worry about clobbering
135 135 # maybe we should just delete it?
136 136 newpath = base + "-corrupt" + ext
137 137 self.hist_file.rename(newpath)
138 138 self.log.error(
139 139 "History file was moved to %s and a new file created.", newpath
140 140 )
141 141 self.init_db()
142 142 return []
143 143 else:
144 144 # Failed with :memory:, something serious is wrong
145 145 raise
146 146
147 147
148 148 class HistoryAccessorBase(LoggingConfigurable):
149 149 """An abstract class for History Accessors"""
150 150
151 151 def get_tail(
152 152 self,
153 153 n: int = 10,
154 154 raw: bool = True,
155 155 output: bool = False,
156 156 include_latest: bool = False,
157 157 ) -> Iterable[Tuple[int, int, InOrInOut]]:
158 158 raise NotImplementedError
159 159
160 160 def search(
161 161 self,
162 162 pattern: str = "*",
163 163 raw: bool = True,
164 164 search_raw: bool = True,
165 165 output: bool = False,
166 166 n: Optional[int] = None,
167 167 unique: bool = False,
168 168 ) -> Iterable[Tuple[int, int, InOrInOut]]:
169 169 raise NotImplementedError
170 170
171 171 def get_range(
172 172 self,
173 173 session: int,
174 174 start: int = 1,
175 175 stop: Optional[int] = None,
176 176 raw: bool = True,
177 177 output: bool = False,
178 178 ) -> Iterable[Tuple[int, int, InOrInOut]]:
179 179 raise NotImplementedError
180 180
181 181 def get_range_by_str(
182 182 self, rangestr: str, raw: bool = True, output: bool = False
183 183 ) -> Iterable[Tuple[int, int, InOrInOut]]:
184 184 raise NotImplementedError
185 185
186 186
187 187 class HistoryAccessor(HistoryAccessorBase):
188 188 """Access the history database without adding to it.
189 189
190 190 This is intended for use by standalone history tools. IPython shells use
191 191 HistoryManager, below, which is a subclass of this."""
192 192
193 193 # counter for init_db retries, so we don't keep trying over and over
194 194 _corrupt_db_counter = 0
195 195 # after two failures, fallback on :memory:
196 196 _corrupt_db_limit = 2
197 197
198 198 # String holding the path to the history file
199 199 hist_file = Union(
200 200 [Instance(Path), Unicode()],
201 201 help="""Path to file to use for SQLite history database.
202 202
203 203 By default, IPython will put the history database in the IPython
204 204 profile directory. If you would rather share one history among
205 205 profiles, you can set this value in each, so that they are consistent.
206 206
207 207 Due to an issue with fcntl, SQLite is known to misbehave on some NFS
208 208 mounts. If you see IPython hanging, try setting this to something on a
209 209 local disk, e.g::
210 210
211 211 ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite
212 212
213 213 you can also use the specific value `:memory:` (including the colon
214 214 at both end but not the back ticks), to avoid creating an history file.
215 215
216 216 """,
217 217 ).tag(config=True)
218 218
219 219 enabled = Bool(
220 220 sqlite3_found,
221 221 help="""enable the SQLite history
222 222
223 223 set enabled=False to disable the SQLite history,
224 224 in which case there will be no stored history, no SQLite connection,
225 225 and no background saving thread. This may be necessary in some
226 226 threaded environments where IPython is embedded.
227 227 """,
228 228 ).tag(config=True)
229 229
230 230 connection_options = Dict(
231 231 help="""Options for configuring the SQLite connection
232 232
233 233 These options are passed as keyword args to sqlite3.connect
234 234 when establishing database connections.
235 235 """
236 236 ).tag(config=True)
237 237
238 238 @default("connection_options")
239 239 def _default_connection_options(self) -> typing.Dict[str, bool]:
240 240 return dict(check_same_thread=False)
241 241
242 242 # The SQLite database
243 243 db = Any()
244 244
245 245 @observe("db")
246 246 @only_when_enabled
247 247 def _db_changed(self, change): # type: ignore [no-untyped-def]
248 248 """validate the db, since it can be an Instance of two different types"""
249 249 new = change["new"]
250 250 connection_types = (DummyDB, sqlite3.Connection)
251 251 if not isinstance(new, connection_types):
252 252 msg = "%s.db must be sqlite3 Connection or DummyDB, not %r" % (
253 253 self.__class__.__name__,
254 254 new,
255 255 )
256 256 raise TraitError(msg)
257 257
258 258 def __init__(
259 259 self, profile: str = "default", hist_file: str = "", **traits: typing.Any
260 260 ) -> None:
261 261 """Create a new history accessor.
262 262
263 263 Parameters
264 264 ----------
265 265 profile : str
266 266 The name of the profile from which to open history.
267 267 hist_file : str
268 268 Path to an SQLite history database stored by IPython. If specified,
269 269 hist_file overrides profile.
270 270 config : :class:`~traitlets.config.loader.Config`
271 271 Config object. hist_file can also be set through this.
272 272 """
273 273 super(HistoryAccessor, self).__init__(**traits)
274 274 # defer setting hist_file from kwarg until after init,
275 275 # otherwise the default kwarg value would clobber any value
276 276 # set by config
277 277 if hist_file:
278 278 self.hist_file = hist_file
279 279
280 280 try:
281 281 self.hist_file
282 282 except TraitError:
283 283 # No one has set the hist_file, yet.
284 284 self.hist_file = self._get_hist_file_name(profile)
285 285
286 286 self.init_db()
287 287
288 288 def _get_hist_file_name(self, profile: str = "default") -> Path:
289 289 """Find the history file for the given profile name.
290 290
291 291 This is overridden by the HistoryManager subclass, to use the shell's
292 292 active profile.
293 293
294 294 Parameters
295 295 ----------
296 296 profile : str
297 297 The name of a profile which has a history file.
298 298 """
299 299 return Path(locate_profile(profile)) / "history.sqlite"
300 300
301 301 @catch_corrupt_db
302 302 def init_db(self) -> None:
303 303 """Connect to the database, and create tables if necessary."""
304 304 if not self.enabled:
305 305 self.db = DummyDB()
306 306 return
307 307
308 308 # use detect_types so that timestamps return datetime objects
309 309 kwargs = dict(detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES)
310 310 kwargs.update(self.connection_options)
311 311 self.db = sqlite3.connect(str(self.hist_file), **kwargs) # type: ignore [call-overload]
312 312 with self.db:
313 313 self.db.execute(
314 314 """CREATE TABLE IF NOT EXISTS sessions (session integer
315 315 primary key autoincrement, start timestamp,
316 316 end timestamp, num_cmds integer, remark text)"""
317 317 )
318 318 self.db.execute(
319 319 """CREATE TABLE IF NOT EXISTS history
320 320 (session integer, line integer, source text, source_raw text,
321 321 PRIMARY KEY (session, line))"""
322 322 )
323 323 # Output history is optional, but ensure the table's there so it can be
324 324 # enabled later.
325 325 self.db.execute(
326 326 """CREATE TABLE IF NOT EXISTS output_history
327 327 (session integer, line integer, output text,
328 328 PRIMARY KEY (session, line))"""
329 329 )
330 330 # success! reset corrupt db count
331 331 self._corrupt_db_counter = 0
332 332
333 333 def writeout_cache(self) -> None:
334 334 """Overridden by HistoryManager to dump the cache before certain
335 335 database lookups."""
336 336 pass
337 337
338 338 ## -------------------------------
339 339 ## Methods for retrieving history:
340 340 ## -------------------------------
341 341 def _run_sql(
342 342 self,
343 343 sql: str,
344 344 params: typing.Tuple,
345 345 raw: bool = True,
346 346 output: bool = False,
347 347 latest: bool = False,
348 348 ) -> Iterable[Tuple[int, int, InOrInOut]]:
349 349 """Prepares and runs an SQL query for the history database.
350 350
351 351 Parameters
352 352 ----------
353 353 sql : str
354 354 Any filtering expressions to go after SELECT ... FROM ...
355 355 params : tuple
356 356 Parameters passed to the SQL query (to replace "?")
357 357 raw, output : bool
358 358 See :meth:`get_range`
359 359 latest : bool
360 360 Select rows with max (session, line)
361 361
362 362 Returns
363 363 -------
364 364 Tuples as :meth:`get_range`
365 365 """
366 366 toget = "source_raw" if raw else "source"
367 367 sqlfrom = "history"
368 368 if output:
369 369 sqlfrom = "history LEFT JOIN output_history USING (session, line)"
370 370 toget = "history.%s, output_history.output" % toget
371 371 if latest:
372 372 toget += ", MAX(session * 128 * 1024 + line)"
373 373 this_querry = "SELECT session, line, %s FROM %s " % (toget, sqlfrom) + sql
374 374 cur = self.db.execute(this_querry, params)
375 375 if latest:
376 376 cur = (row[:-1] for row in cur)
377 377 if output: # Regroup into 3-tuples, and parse JSON
378 378 return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur)
379 379 return cur
380 380
381 381 @only_when_enabled
382 382 @catch_corrupt_db
383 383 def get_session_info(
384 384 self, session: int
385 385 ) -> Tuple[int, datetime.datetime, Optional[datetime.datetime], Optional[int], str]:
386 386 """Get info about a session.
387 387
388 388 Parameters
389 389 ----------
390 390 session : int
391 391 Session number to retrieve.
392 392
393 393 Returns
394 394 -------
395 395 session_id : int
396 396 Session ID number
397 397 start : datetime
398 398 Timestamp for the start of the session.
399 399 end : datetime
400 400 Timestamp for the end of the session, or None if IPython crashed.
401 401 num_cmds : int
402 402 Number of commands run, or None if IPython crashed.
403 403 remark : str
404 404 A manually set description.
405 405 """
406 406 query = "SELECT * from sessions where session == ?"
407 407 return self.db.execute(query, (session,)).fetchone()
408 408
409 409 @catch_corrupt_db
410 410 def get_last_session_id(self) -> Optional[int]:
411 411 """Get the last session ID currently in the database.
412 412
413 413 Within IPython, this should be the same as the value stored in
414 414 :attr:`HistoryManager.session_number`.
415 415 """
416 416 for record in self.get_tail(n=1, include_latest=True):
417 417 return record[0]
418 418 return None
419 419
420 420 @catch_corrupt_db
421 421 def get_tail(
422 422 self,
423 423 n: int = 10,
424 424 raw: bool = True,
425 425 output: bool = False,
426 426 include_latest: bool = False,
427 427 ) -> Iterable[Tuple[int, int, InOrInOut]]:
428 428 """Get the last n lines from the history database.
429 429
430 430 Parameters
431 431 ----------
432 432 n : int
433 433 The number of lines to get
434 434 raw, output : bool
435 435 See :meth:`get_range`
436 436 include_latest : bool
437 437 If False (default), n+1 lines are fetched, and the latest one
438 438 is discarded. This is intended to be used where the function
439 439 is called by a user command, which it should not return.
440 440
441 441 Returns
442 442 -------
443 443 Tuples as :meth:`get_range`
444 444 """
445 445 self.writeout_cache()
446 446 if not include_latest:
447 447 n += 1
448 448 cur = self._run_sql(
449 449 "ORDER BY session DESC, line DESC LIMIT ?", (n,), raw=raw, output=output
450 450 )
451 451 if not include_latest:
452 452 return reversed(list(cur)[1:])
453 453 return reversed(list(cur))
454 454
455 455 @catch_corrupt_db
456 456 def search(
457 457 self,
458 458 pattern: str = "*",
459 459 raw: bool = True,
460 460 search_raw: bool = True,
461 461 output: bool = False,
462 462 n: Optional[int] = None,
463 463 unique: bool = False,
464 464 ) -> Iterable[Tuple[int, int, InOrInOut]]:
465 465 """Search the database using unix glob-style matching (wildcards
466 466 * and ?).
467 467
468 468 Parameters
469 469 ----------
470 470 pattern : str
471 471 The wildcarded pattern to match when searching
472 472 search_raw : bool
473 473 If True, search the raw input, otherwise, the parsed input
474 474 raw, output : bool
475 475 See :meth:`get_range`
476 476 n : None or int
477 477 If an integer is given, it defines the limit of
478 478 returned entries.
479 479 unique : bool
480 480 When it is true, return only unique entries.
481 481
482 482 Returns
483 483 -------
484 484 Tuples as :meth:`get_range`
485 485 """
486 486 tosearch = "source_raw" if search_raw else "source"
487 487 if output:
488 488 tosearch = "history." + tosearch
489 489 self.writeout_cache()
490 490 sqlform = "WHERE %s GLOB ?" % tosearch
491 491 params: typing.Tuple[typing.Any, ...] = (pattern,)
492 492 if unique:
493 493 sqlform += " GROUP BY {0}".format(tosearch)
494 494 if n is not None:
495 495 sqlform += " ORDER BY session DESC, line DESC LIMIT ?"
496 496 params += (n,)
497 497 elif unique:
498 498 sqlform += " ORDER BY session, line"
499 499 cur = self._run_sql(sqlform, params, raw=raw, output=output, latest=unique)
500 500 if n is not None:
501 501 return reversed(list(cur))
502 502 return cur
503 503
504 504 @catch_corrupt_db
505 505 def get_range(
506 506 self,
507 507 session: int,
508 508 start: int = 1,
509 509 stop: Optional[int] = None,
510 510 raw: bool = True,
511 511 output: bool = False,
512 512 ) -> Iterable[Tuple[int, int, InOrInOut]]:
513 513 """Retrieve input by session.
514 514
515 515 Parameters
516 516 ----------
517 517 session : int
518 518 Session number to retrieve.
519 519 start : int
520 520 First line to retrieve.
521 521 stop : int
522 522 End of line range (excluded from output itself). If None, retrieve
523 523 to the end of the session.
524 524 raw : bool
525 525 If True, return untranslated input
526 526 output : bool
527 527 If True, attempt to include output. This will be 'real' Python
528 528 objects for the current session, or text reprs from previous
529 529 sessions if db_log_output was enabled at the time. Where no output
530 530 is found, None is used.
531 531
532 532 Returns
533 533 -------
534 534 entries
535 535 An iterator over the desired lines. Each line is a 3-tuple, either
536 536 (session, line, input) if output is False, or
537 537 (session, line, (input, output)) if output is True.
538 538 """
539 539 params: typing.Tuple[typing.Any, ...]
540 540 if stop:
541 541 lineclause = "line >= ? AND line < ?"
542 542 params = (session, start, stop)
543 543 else:
544 544 lineclause = "line>=?"
545 545 params = (session, start)
546 546
547 547 return self._run_sql(
548 548 "WHERE session==? AND %s" % lineclause, params, raw=raw, output=output
549 549 )
550 550
551 551 def get_range_by_str(
552 552 self, rangestr: str, raw: bool = True, output: bool = False
553 553 ) -> Iterable[Tuple[int, int, InOrInOut]]:
554 554 """Get lines of history from a string of ranges, as used by magic
555 555 commands %hist, %save, %macro, etc.
556 556
557 557 Parameters
558 558 ----------
559 559 rangestr : str
560 560 A string specifying ranges, e.g. "5 ~2/1-4". If empty string is used,
561 561 this will return everything from current session's history.
562 562
563 563 See the documentation of :func:`%history` for the full details.
564 564
565 565 raw, output : bool
566 566 As :meth:`get_range`
567 567
568 568 Returns
569 569 -------
570 570 Tuples as :meth:`get_range`
571 571 """
572 572 for sess, s, e in extract_hist_ranges(rangestr):
573 573 for line in self.get_range(sess, s, e, raw=raw, output=output):
574 574 yield line
575 575
576 576
577 577 class HistoryManager(HistoryAccessor):
578 578 """A class to organize all history-related functionality in one place."""
579 579
580 580 # Public interface
581 581
582 582 # An instance of the IPython shell we are attached to
583 583 shell = Instance(
584 584 "IPython.core.interactiveshell.InteractiveShellABC", allow_none=False
585 585 )
586 586 # Lists to hold processed and raw history. These start with a blank entry
587 587 # so that we can index them starting from 1
588 588 input_hist_parsed = List([""])
589 589 input_hist_raw = List([""])
590 590 # A list of directories visited during session
591 591 dir_hist: List = List()
592 592
593 593 @default("dir_hist")
594 594 def _dir_hist_default(self) -> typing.List[Path]:
595 595 try:
596 596 return [Path.cwd()]
597 597 except OSError:
598 598 return []
599 599
600 600 # A dict of output history, keyed with ints from the shell's
601 601 # execution count.
602 602 output_hist = Dict()
603 603 # The text/plain repr of outputs.
604 604 output_hist_reprs: typing.Dict[int, str] = Dict() # type: ignore [assignment]
605 605
606 606 # The number of the current session in the history database
607 607 session_number: int = Integer() # type: ignore [assignment]
608 608
609 609 db_log_output = Bool(
610 610 False, help="Should the history database include output? (default: no)"
611 611 ).tag(config=True)
612 612 db_cache_size = Integer(
613 613 0,
614 614 help="Write to database every x commands (higher values save disk access & power).\n"
615 615 "Values of 1 or less effectively disable caching.",
616 616 ).tag(config=True)
617 617 # The input and output caches
618 618 db_input_cache: List[Tuple[int, str, str]] = List()
619 619 db_output_cache: List[Tuple[int, str]] = List()
620 620
621 621 # History saving in separate thread
622 622 save_thread = Instance("IPython.core.history.HistorySavingThread", allow_none=True)
623 623 save_flag = Instance(threading.Event, allow_none=False)
624 624
625 625 # Private interface
626 626 # Variables used to store the three last inputs from the user. On each new
627 627 # history update, we populate the user's namespace with these, shifted as
628 628 # necessary.
629 629 _i00 = Unicode("")
630 630 _i = Unicode("")
631 631 _ii = Unicode("")
632 632 _iii = Unicode("")
633 633
634 634 # A regex matching all forms of the exit command, so that we don't store
635 635 # them in the history (it's annoying to rewind the first entry and land on
636 636 # an exit call).
637 637 _exit_re = re.compile(r"(exit|quit)(\s*\(.*\))?$")
638 638
639 639 def __init__(
640 640 self,
641 641 shell: InteractiveShell,
642 642 config: Optional[Configuration] = None,
643 643 **traits: typing.Any,
644 644 ):
645 645 """Create a new history manager associated with a shell instance."""
646 646 super().__init__(shell=shell, config=config, **traits)
647 647 self.save_flag = threading.Event()
648 648 self.db_input_cache_lock = threading.Lock()
649 649 self.db_output_cache_lock = threading.Lock()
650 650
651 651 try:
652 652 self.new_session()
653 653 except OperationalError:
654 654 self.log.error(
655 655 "Failed to create history session in %s. History will not be saved.",
656 656 self.hist_file,
657 657 exc_info=True,
658 658 )
659 659 self.hist_file = ":memory:"
660 660
661 661 if self.enabled and self.hist_file != ":memory:":
662 662 self.save_thread = HistorySavingThread(self)
663 663 try:
664 664 self.save_thread.start()
665 665 except RuntimeError:
666 666 self.log.error(
667 667 "Failed to start history saving thread. History will not be saved.",
668 668 exc_info=True,
669 669 )
670 670 self.hist_file = ":memory:"
671 671
672 672 def _get_hist_file_name(self, profile: Optional[str] = None) -> Path:
673 673 """Get default history file name based on the Shell's profile.
674 674
675 675 The profile parameter is ignored, but must exist for compatibility with
676 676 the parent class."""
677 677 profile_dir = self.shell.profile_dir.location
678 678 return Path(profile_dir) / "history.sqlite"
679 679
680 680 @only_when_enabled
681 681 def new_session(self, conn: Optional[sqlite3.Connection] = None) -> None:
682 682 """Get a new session number."""
683 683 if conn is None:
684 684 conn = self.db
685 685
686 686 with conn:
687 687 cur = conn.execute(
688 688 """INSERT INTO sessions VALUES (NULL, ?, NULL,
689 689 NULL, '') """,
690 690 (datetime.datetime.now().isoformat(" "),),
691 691 )
692 692 assert isinstance(cur.lastrowid, int)
693 693 self.session_number = cur.lastrowid
694 694
695 695 def end_session(self) -> None:
696 696 """Close the database session, filling in the end time and line count."""
697 697 self.writeout_cache()
698 698 with self.db:
699 699 self.db.execute(
700 700 """UPDATE sessions SET end=?, num_cmds=? WHERE
701 701 session==?""",
702 702 (
703 703 datetime.datetime.now().isoformat(" "),
704 704 len(self.input_hist_parsed) - 1,
705 705 self.session_number,
706 706 ),
707 707 )
708 708 self.session_number = 0
709 709
710 710 def name_session(self, name: str) -> None:
711 711 """Give the current session a name in the history database."""
712 712 warn(
713 713 "name_session is deprecated in IPython 9.0 and will be removed in future versions",
714 714 DeprecationWarning,
715 715 stacklevel=2,
716 716 )
717 717 with self.db:
718 718 self.db.execute(
719 719 "UPDATE sessions SET remark=? WHERE session==?",
720 720 (name, self.session_number),
721 721 )
722 722
723 723 def reset(self, new_session: bool = True) -> None:
724 724 """Clear the session history, releasing all object references, and
725 725 optionally open a new session."""
726 726 self.output_hist.clear()
727 727 # The directory history can't be completely empty
728 728 self.dir_hist[:] = [Path.cwd()]
729 729
730 730 if new_session:
731 731 if self.session_number:
732 732 self.end_session()
733 733 self.input_hist_parsed[:] = [""]
734 734 self.input_hist_raw[:] = [""]
735 735 self.new_session()
736 736
737 737 # ------------------------------
738 738 # Methods for retrieving history
739 739 # ------------------------------
740 740 def get_session_info(
741 741 self, session: int = 0
742 742 ) -> Tuple[int, datetime.datetime, Optional[datetime.datetime], Optional[int], str]:
743 743 """Get info about a session.
744 744
745 745 Parameters
746 746 ----------
747 747 session : int
748 748 Session number to retrieve. The current session is 0, and negative
749 749 numbers count back from current session, so -1 is the previous session.
750 750
751 751 Returns
752 752 -------
753 753 session_id : int
754 754 Session ID number
755 755 start : datetime
756 756 Timestamp for the start of the session.
757 757 end : datetime
758 758 Timestamp for the end of the session, or None if IPython crashed.
759 759 num_cmds : int
760 760 Number of commands run, or None if IPython crashed.
761 761 remark : str
762 762 A manually set description.
763 763 """
764 764 if session <= 0:
765 765 session += self.session_number
766 766
767 767 return super(HistoryManager, self).get_session_info(session=session)
768 768
769 769 @catch_corrupt_db
770 770 def get_tail(
771 771 self,
772 772 n: int = 10,
773 773 raw: bool = True,
774 774 output: bool = False,
775 775 include_latest: bool = False,
776 776 ) -> Iterable[Tuple[int, int, InOrInOut]]:
777 777 """Get the last n lines from the history database.
778 778
779 779 Most recent entry last.
780 780
781 781 Completion will be reordered so that that the last ones are when
782 782 possible from current session.
783 783
784 784 Parameters
785 785 ----------
786 786 n : int
787 787 The number of lines to get
788 788 raw, output : bool
789 789 See :meth:`get_range`
790 790 include_latest : bool
791 791 If False (default), n+1 lines are fetched, and the latest one
792 792 is discarded. This is intended to be used where the function
793 793 is called by a user command, which it should not return.
794 794
795 795 Returns
796 796 -------
797 797 Tuples as :meth:`get_range`
798 798 """
799 799 self.writeout_cache()
800 800 if not include_latest:
801 801 n += 1
802 802 # cursor/line/entry
803 803 this_cur = list(
804 804 self._run_sql(
805 805 "WHERE session == ? ORDER BY line DESC LIMIT ? ",
806 806 (self.session_number, n),
807 807 raw=raw,
808 808 output=output,
809 809 )
810 810 )
811 811 other_cur = list(
812 812 self._run_sql(
813 813 "WHERE session != ? ORDER BY session DESC, line DESC LIMIT ?",
814 814 (self.session_number, n),
815 815 raw=raw,
816 816 output=output,
817 817 )
818 818 )
819 819
820 820 everything: typing.List[Tuple[int, int, InOrInOut]] = this_cur + other_cur
821 821
822 822 everything = everything[:n]
823 823
824 824 if not include_latest:
825 825 return list(everything)[:0:-1]
826 826 return list(everything)[::-1]
827 827
828 828 def _get_range_session(
829 829 self,
830 830 start: int = 1,
831 831 stop: Optional[int] = None,
832 832 raw: bool = True,
833 833 output: bool = False,
834 834 ) -> Iterable[Tuple[int, int, InOrInOut]]:
835 835 """Get input and output history from the current session. Called by
836 836 get_range, and takes similar parameters."""
837 837 input_hist = self.input_hist_raw if raw else self.input_hist_parsed
838 838
839 839 n = len(input_hist)
840 840 if start < 0:
841 841 start += n
842 842 if not stop or (stop > n):
843 843 stop = n
844 844 elif stop < 0:
845 845 stop += n
846 846 line: InOrInOut
847 847 for i in range(start, stop):
848 848 if output:
849 849 line = (input_hist[i], self.output_hist_reprs.get(i))
850 850 else:
851 851 line = input_hist[i]
852 852 yield (0, i, line)
853 853
854 854 def get_range(
855 855 self,
856 856 session: int = 0,
857 857 start: int = 1,
858 858 stop: Optional[int] = None,
859 859 raw: bool = True,
860 860 output: bool = False,
861 861 ) -> Iterable[Tuple[int, int, InOrInOut]]:
862 862 """Retrieve input by session.
863 863
864 864 Parameters
865 865 ----------
866 866 session : int
867 867 Session number to retrieve. The current session is 0, and negative
868 868 numbers count back from current session, so -1 is previous session.
869 869 start : int
870 870 First line to retrieve.
871 871 stop : int
872 872 End of line range (excluded from output itself). If None, retrieve
873 873 to the end of the session.
874 874 raw : bool
875 875 If True, return untranslated input
876 876 output : bool
877 877 If True, attempt to include output. This will be 'real' Python
878 878 objects for the current session, or text reprs from previous
879 879 sessions if db_log_output was enabled at the time. Where no output
880 880 is found, None is used.
881 881
882 882 Returns
883 883 -------
884 884 entries
885 885 An iterator over the desired lines. Each line is a 3-tuple, either
886 886 (session, line, input) if output is False, or
887 887 (session, line, (input, output)) if output is True.
888 888 """
889 889 if session <= 0:
890 890 session += self.session_number
891 891 if session == self.session_number: # Current session
892 892 return self._get_range_session(start, stop, raw, output)
893 893 return super(HistoryManager, self).get_range(session, start, stop, raw, output)
894 894
895 895 ## ----------------------------
896 896 ## Methods for storing history:
897 897 ## ----------------------------
898 898 def store_inputs(
899 899 self, line_num: int, source: str, source_raw: Optional[str] = None
900 900 ) -> None:
901 901 """Store source and raw input in history and create input cache
902 902 variables ``_i*``.
903 903
904 904 Parameters
905 905 ----------
906 906 line_num : int
907 907 The prompt number of this input.
908 908 source : str
909 909 Python input.
910 910 source_raw : str, optional
911 911 If given, this is the raw input without any IPython transformations
912 912 applied to it. If not given, ``source`` is used.
913 913 """
914 914 if source_raw is None:
915 915 source_raw = source
916 916 source = source.rstrip("\n")
917 917 source_raw = source_raw.rstrip("\n")
918 918
919 919 # do not store exit/quit commands
920 920 if self._exit_re.match(source_raw.strip()):
921 921 return
922 922
923 923 self.input_hist_parsed.append(source)
924 924 self.input_hist_raw.append(source_raw)
925 925
926 926 with self.db_input_cache_lock:
927 927 self.db_input_cache.append((line_num, source, source_raw))
928 928 # Trigger to flush cache and write to DB.
929 929 if len(self.db_input_cache) >= self.db_cache_size:
930 930 self.save_flag.set()
931 931
932 932 # update the auto _i variables
933 933 self._iii = self._ii
934 934 self._ii = self._i
935 935 self._i = self._i00
936 936 self._i00 = source_raw
937 937
938 938 # hackish access to user namespace to create _i1,_i2... dynamically
939 939 new_i = "_i%s" % line_num
940 940 to_main = {"_i": self._i, "_ii": self._ii, "_iii": self._iii, new_i: self._i00}
941 941
942 942 if self.shell is not None:
943 943 self.shell.push(to_main, interactive=False)
944 944
945 945 def store_output(self, line_num: int) -> None:
946 946 """If database output logging is enabled, this saves all the
947 947 outputs from the indicated prompt number to the database. It's
948 948 called by run_cell after code has been executed.
949 949
950 950 Parameters
951 951 ----------
952 952 line_num : int
953 953 The line number from which to save outputs
954 954 """
955 955 if (not self.db_log_output) or (line_num not in self.output_hist_reprs):
956 956 return
957 lnum: int = line_num
957 958 output = self.output_hist_reprs[line_num]
958 959
959 960 with self.db_output_cache_lock:
960 961 self.db_output_cache.append((line_num, output))
961 962 if self.db_cache_size <= 1:
962 963 self.save_flag.set()
963 964
964 965 def _writeout_input_cache(self, conn: sqlite3.Connection) -> None:
965 966 with conn:
966 967 for line in self.db_input_cache:
967 968 conn.execute(
968 969 "INSERT INTO history VALUES (?, ?, ?, ?)",
969 970 (self.session_number,) + line,
970 971 )
971 972
972 973 def _writeout_output_cache(self, conn: sqlite3.Connection) -> None:
973 974 with conn:
974 975 for line in self.db_output_cache:
975 976 conn.execute(
976 977 "INSERT INTO output_history VALUES (?, ?, ?)",
977 978 (self.session_number,) + line,
978 979 )
979 980
980 981 @only_when_enabled
981 982 def writeout_cache(self, conn: Optional[sqlite3.Connection] = None) -> None:
982 983 """Write any entries in the cache to the database."""
983 984 if conn is None:
984 985 conn = self.db
985 986
986 987 with self.db_input_cache_lock:
987 988 try:
988 989 self._writeout_input_cache(conn)
989 990 except sqlite3.IntegrityError:
990 991 self.new_session(conn)
991 992 print(
992 993 "ERROR! Session/line number was not unique in",
993 994 "database. History logging moved to new session",
994 995 self.session_number,
995 996 )
996 997 try:
997 998 # Try writing to the new session. If this fails, don't
998 999 # recurse
999 1000 self._writeout_input_cache(conn)
1000 1001 except sqlite3.IntegrityError:
1001 1002 pass
1002 1003 finally:
1003 1004 self.db_input_cache = []
1004 1005
1005 1006 with self.db_output_cache_lock:
1006 1007 try:
1007 1008 self._writeout_output_cache(conn)
1008 1009 except sqlite3.IntegrityError:
1009 1010 print(
1010 1011 "!! Session/line number for output was not unique",
1011 1012 "in database. Output will not be stored.",
1012 1013 )
1013 1014 finally:
1014 1015 self.db_output_cache = []
1015 1016
1016 1017
1017 1018 class HistorySavingThread(threading.Thread):
1018 1019 """This thread takes care of writing history to the database, so that
1019 1020 the UI isn't held up while that happens.
1020 1021
1021 1022 It waits for the HistoryManager's save_flag to be set, then writes out
1022 1023 the history cache. The main thread is responsible for setting the flag when
1023 1024 the cache size reaches a defined threshold."""
1024 1025
1025 1026 daemon = True
1026 1027 stop_now = False
1027 1028 enabled = True
1028 1029 history_manager: HistoryManager
1029 1030
1030 1031 def __init__(self, history_manager: HistoryManager) -> None:
1031 1032 super(HistorySavingThread, self).__init__(name="IPythonHistorySavingThread")
1032 1033 self.history_manager = history_manager
1033 1034 self.enabled = history_manager.enabled
1034 1035
1035 1036 @only_when_enabled
1036 1037 def run(self) -> None:
1037 1038 atexit.register(self.stop)
1038 1039 # We need a separate db connection per thread:
1039 1040 try:
1040 1041 self.db = sqlite3.connect(
1041 1042 str(self.history_manager.hist_file),
1042 1043 **self.history_manager.connection_options,
1043 1044 )
1044 1045 while True:
1045 1046 self.history_manager.save_flag.wait()
1046 1047 if self.stop_now:
1047 1048 self.db.close()
1048 1049 return
1049 1050 self.history_manager.save_flag.clear()
1050 1051 self.history_manager.writeout_cache(self.db)
1051 1052 except Exception as e:
1052 1053 print(
1053 1054 (
1054 1055 "The history saving thread hit an unexpected error (%s)."
1055 1056 "History will not be written to the database."
1056 1057 )
1057 1058 % repr(e)
1058 1059 )
1059 1060 finally:
1060 1061 atexit.unregister(self.stop)
1061 1062
1062 1063 def stop(self) -> None:
1063 1064 """This can be called from the main thread to safely stop this thread.
1064 1065
1065 1066 Note that it does not attempt to write out remaining history before
1066 1067 exiting. That should be done by calling the HistoryManager's
1067 1068 end_session method."""
1068 1069 self.stop_now = True
1069 1070 self.history_manager.save_flag.set()
1070 1071 self.join()
1071 1072
1072 1073
1073 1074 # To match, e.g. ~5/8-~2/3
1074 1075 range_re = re.compile(
1075 1076 r"""
1076 1077 ((?P<startsess>~?\d+)/)?
1077 1078 (?P<start>\d+)?
1078 1079 ((?P<sep>[\-:])
1079 1080 ((?P<endsess>~?\d+)/)?
1080 1081 (?P<end>\d+))?
1081 1082 $""",
1082 1083 re.VERBOSE,
1083 1084 )
1084 1085
1085 1086
1086 1087 def extract_hist_ranges(ranges_str: str) -> Iterable[Tuple[int, int, Optional[int]]]:
1087 1088 """Turn a string of history ranges into 3-tuples of (session, start, stop).
1088 1089
1089 1090 Empty string results in a `[(0, 1, None)]`, i.e. "everything from current
1090 1091 session".
1091 1092
1092 1093 Examples
1093 1094 --------
1094 1095 >>> list(extract_hist_ranges("~8/5-~7/4 2"))
1095 1096 [(-8, 5, None), (-7, 1, 5), (0, 2, 3)]
1096 1097 """
1097 1098 if ranges_str == "":
1098 1099 yield (0, 1, None) # Everything from current session
1099 1100 return
1100 1101
1101 1102 for range_str in ranges_str.split():
1102 1103 rmatch = range_re.match(range_str)
1103 1104 if not rmatch:
1104 1105 continue
1105 1106 start = rmatch.group("start")
1106 1107 if start:
1107 1108 start = int(start)
1108 1109 end = rmatch.group("end")
1109 1110 # If no end specified, get (a, a + 1)
1110 1111 end = int(end) if end else start + 1
1111 1112 else: # start not specified
1112 1113 if not rmatch.group("startsess"): # no startsess
1113 1114 continue
1114 1115 start = 1
1115 1116 end = None # provide the entire session hist
1116 1117
1117 1118 if rmatch.group("sep") == "-": # 1-3 == 1:4 --> [1, 2, 3]
1118 1119 assert end is not None
1119 1120 end += 1
1120 1121 startsess = rmatch.group("startsess") or "0"
1121 1122 endsess = rmatch.group("endsess") or startsess
1122 1123 startsess = int(startsess.replace("~", "-"))
1123 1124 endsess = int(endsess.replace("~", "-"))
1124 1125 assert endsess >= startsess, "start session must be earlier than end session"
1125 1126
1126 1127 if endsess == startsess:
1127 1128 yield (startsess, start, end)
1128 1129 continue
1129 1130 # Multiple sessions in one range:
1130 1131 yield (startsess, start, None)
1131 1132 for sess in range(startsess + 1, endsess):
1132 1133 yield (sess, 1, None)
1133 1134 yield (endsess, 1, end)
1134 1135
1135 1136
1136 1137 def _format_lineno(session: int, line: int) -> str:
1137 1138 """Helper function to format line numbers properly."""
1138 1139 if session == 0:
1139 1140 return str(line)
1140 1141 return "%s#%s" % (session, line)
@@ -1,3984 +1,3985
1 1 # -*- coding: utf-8 -*-
2 2 """Main IPython class."""
3 3
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
6 6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 7 # Copyright (C) 2008-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13
14 14 import abc
15 15 import ast
16 16 import atexit
17 17 import bdb
18 18 import builtins as builtin_mod
19 19 import functools
20 20 import inspect
21 21 import os
22 22 import re
23 23 import runpy
24 24 import shutil
25 25 import subprocess
26 26 import sys
27 27 import tempfile
28 28 import traceback
29 29 import types
30 30 import warnings
31 31 from ast import stmt
32 32 from io import open as io_open
33 33 from logging import error
34 34 from pathlib import Path
35 35 from typing import Callable
36 from typing import List as ListType, Any as AnyType
36 from typing import List as ListType, Dict as DictType, Any as AnyType
37 37 from typing import Optional, Sequence, Tuple
38 38 from warnings import warn
39 39
40 40 try:
41 41 from pickleshare import PickleShareDB
42 42 except ModuleNotFoundError:
43 43
44 44 class PickleShareDB: # type: ignore [no-redef]
45 45 _mock = True
46 46
47 47 def __init__(self, path):
48 48 pass
49 49
50 50 def get(self, key, default=None):
51 51 warn(
52 52 f"This is now an optional IPython functionality, using {key} requires you to install the `pickleshare` library.",
53 53 stacklevel=2,
54 54 )
55 55 return default
56 56
57 57 def __getitem__(self, key):
58 58 warn(
59 59 f"This is now an optional IPython functionality, using {key} requires you to install the `pickleshare` library.",
60 60 stacklevel=2,
61 61 )
62 62 return None
63 63
64 64 def __setitem__(self, key, value):
65 65 warn(
66 66 f"This is now an optional IPython functionality, setting {key} requires you to install the `pickleshare` library.",
67 67 stacklevel=2,
68 68 )
69 69
70 70 def __delitem__(self, key):
71 71 warn(
72 72 f"This is now an optional IPython functionality, deleting {key} requires you to install the `pickleshare` library.",
73 73 stacklevel=2,
74 74 )
75 75
76 76
77 77 from tempfile import TemporaryDirectory
78 78 from traitlets import (
79 79 Any,
80 80 Bool,
81 81 CaselessStrEnum,
82 82 Dict,
83 83 Enum,
84 84 Instance,
85 85 Integer,
86 86 List,
87 87 Type,
88 88 Unicode,
89 89 default,
90 90 observe,
91 91 validate,
92 92 )
93 93 from traitlets.config.configurable import SingletonConfigurable
94 94 from traitlets.utils.importstring import import_item
95 95
96 96 import IPython.core.hooks
97 97 from IPython.core import magic, oinspect, page, prefilter, ultratb
98 98 from IPython.core.alias import Alias, AliasManager
99 99 from IPython.core.autocall import ExitAutocall
100 100 from IPython.core.builtin_trap import BuiltinTrap
101 101 from IPython.core.compilerop import CachingCompiler
102 102 from IPython.core.debugger import InterruptiblePdb
103 103 from IPython.core.display_trap import DisplayTrap
104 104 from IPython.core.displayhook import DisplayHook
105 105 from IPython.core.displaypub import DisplayPublisher
106 106 from IPython.core.error import InputRejected, UsageError
107 107 from IPython.core.events import EventManager, available_events
108 108 from IPython.core.extensions import ExtensionManager
109 109 from IPython.core.formatters import DisplayFormatter
110 110 from IPython.core.history import HistoryManager
111 111 from IPython.core.inputtransformer2 import ESC_MAGIC, ESC_MAGIC2
112 112 from IPython.core.logger import Logger
113 113 from IPython.core.macro import Macro
114 114 from IPython.core.payload import PayloadManager
115 115 from IPython.core.prefilter import PrefilterManager
116 116 from IPython.core.profiledir import ProfileDir
117 117 from IPython.core.usage import default_banner
118 118 from IPython.display import display
119 119 from IPython.paths import get_ipython_dir
120 120 from IPython.testing.skipdoctest import skip_doctest
121 from IPython.utils import PyColorize, openpy, py3compat
121 from IPython.utils import PyColorize, io, openpy, py3compat
122 122 from IPython.utils.decorators import undoc
123 123 from IPython.utils.io import ask_yes_no
124 124 from IPython.utils.ipstruct import Struct
125 125 from IPython.utils.path import ensure_dir_exists, get_home_dir, get_py_filename
126 126 from IPython.utils.process import getoutput, system
127 127 from IPython.utils.strdispatch import StrDispatch
128 128 from IPython.utils.syspathcontext import prepended_to_syspath
129 129 from IPython.utils.text import DollarFormatter, LSString, SList, format_screen
130 130 from IPython.core.oinspect import OInfo
131 131
132 from ast import Module
133
134 # we still need to run things using the asyncio eventloop, but there is no
135 # async integration
136
137 from .async_helpers import (
138 _asyncio_runner,
139 _curio_runner,
140 _pseudo_sync_runner,
141 _should_be_async,
142 _trio_runner,
143 )
144 132
145 133 sphinxify: Optional[Callable]
146 134
147 135 try:
148 136 import docrepr.sphinxify as sphx
149 137
150 138 def sphinxify(oinfo):
151 139 wrapped_docstring = sphx.wrap_main_docstring(oinfo)
152 140
153 141 def sphinxify_docstring(docstring):
154 142 with TemporaryDirectory() as dirname:
155 143 return {
156 144 "text/html": sphx.sphinxify(wrapped_docstring, dirname),
157 145 "text/plain": docstring,
158 146 }
159 147
160 148 return sphinxify_docstring
161 149 except ImportError:
162 150 sphinxify = None
163 151
164 152
165 153 class ProvisionalWarning(DeprecationWarning):
166 154 """
167 155 Warning class for unstable features
168 156 """
169 157 pass
170 158
159 from ast import Module
171 160
172 161 _assign_nodes = (ast.AugAssign, ast.AnnAssign, ast.Assign)
173 162 _single_targets_nodes = (ast.AugAssign, ast.AnnAssign)
174 163
175 164 #-----------------------------------------------------------------------------
165 # Await Helpers
166 #-----------------------------------------------------------------------------
167
168 # we still need to run things using the asyncio eventloop, but there is no
169 # async integration
170 from .async_helpers import (
171 _asyncio_runner,
172 _curio_runner,
173 _pseudo_sync_runner,
174 _should_be_async,
175 _trio_runner,
176 )
177
178 #-----------------------------------------------------------------------------
176 179 # Globals
177 180 #-----------------------------------------------------------------------------
178 181
179 182 # compiled regexps for autoindent management
180 183 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
181 184
182 185 #-----------------------------------------------------------------------------
183 186 # Utilities
184 187 #-----------------------------------------------------------------------------
185 188
186 189
187 190 def is_integer_string(s: str):
188 191 """
189 192 Variant of "str.isnumeric()" that allow negative values and other ints.
190 193 """
191 194 try:
192 195 int(s)
193 196 return True
194 197 except ValueError:
195 198 return False
196 199 raise ValueError("Unexpected error")
197 200
198 201
199 202 @undoc
200 203 def softspace(file, newvalue):
201 204 """Copied from code.py, to remove the dependency"""
202 205
203 206 oldvalue = 0
204 207 try:
205 208 oldvalue = file.softspace
206 209 except AttributeError:
207 210 pass
208 211 try:
209 212 file.softspace = newvalue
210 213 except (AttributeError, TypeError):
211 214 # "attribute-less object" or "read-only attributes"
212 215 pass
213 216 return oldvalue
214 217
215 218 @undoc
216 219 def no_op(*a, **kw):
217 220 pass
218 221
219 222
220 class SpaceInInput(Exception):
221 pass
223 class SpaceInInput(Exception): pass
222 224
223 225
224 226 class SeparateUnicode(Unicode):
225 227 r"""A Unicode subclass to validate separate_in, separate_out, etc.
226 228
227 229 This is a Unicode based trait that converts '0'->'' and ``'\\n'->'\n'``.
228 230 """
229 231
230 232 def validate(self, obj, value):
231 if value == "0":
232 value = ""
233 value = value.replace("\\n", "\n")
233 if value == '0': value = ''
234 value = value.replace('\\n','\n')
234 235 return super(SeparateUnicode, self).validate(obj, value)
235 236
236 237
237 238 @undoc
238 239 class DummyMod(object):
239 240 """A dummy module used for IPython's interactive module when
240 241 a namespace must be assigned to the module's __dict__."""
241 242 __spec__ = None
242 243
243 244
244 245 class ExecutionInfo(object):
245 246 """The arguments used for a call to :meth:`InteractiveShell.run_cell`
246 247
247 248 Stores information about what is going to happen.
248 249 """
249 250 raw_cell = None
250 251 store_history = False
251 252 silent = False
252 253 shell_futures = True
253 254 cell_id = None
254 255
255 256 def __init__(self, raw_cell, store_history, silent, shell_futures, cell_id):
256 257 self.raw_cell = raw_cell
257 258 self.store_history = store_history
258 259 self.silent = silent
259 260 self.shell_futures = shell_futures
260 261 self.cell_id = cell_id
261 262
262 263 def __repr__(self):
263 264 name = self.__class__.__qualname__
264 265 raw_cell = (
265 266 (self.raw_cell[:50] + "..") if len(self.raw_cell) > 50 else self.raw_cell
266 267 )
267 268 return (
268 269 '<%s object at %x, raw_cell="%s" store_history=%s silent=%s shell_futures=%s cell_id=%s>'
269 270 % (
270 271 name,
271 272 id(self),
272 273 raw_cell,
273 274 self.store_history,
274 275 self.silent,
275 276 self.shell_futures,
276 277 self.cell_id,
277 278 )
278 279 )
279 280
280 281
281 282 class ExecutionResult:
282 283 """The result of a call to :meth:`InteractiveShell.run_cell`
283 284
284 285 Stores information about what took place.
285 286 """
286 287
287 288 execution_count: Optional[int] = None
288 289 error_before_exec: Optional[bool] = None
289 290 error_in_exec: Optional[BaseException] = None
290 291 info = None
291 292 result = None
292 293
293 294 def __init__(self, info):
294 295 self.info = info
295 296
296 297 @property
297 298 def success(self):
298 299 return (self.error_before_exec is None) and (self.error_in_exec is None)
299 300
300 301 def raise_error(self):
301 302 """Reraises error if `success` is `False`, otherwise does nothing"""
302 303 if self.error_before_exec is not None:
303 304 raise self.error_before_exec
304 305 if self.error_in_exec is not None:
305 306 raise self.error_in_exec
306 307
307 308 def __repr__(self):
308 309 name = self.__class__.__qualname__
309 310 return '<%s object at %x, execution_count=%s error_before_exec=%s error_in_exec=%s info=%s result=%s>' %\
310 311 (name, id(self), self.execution_count, self.error_before_exec, self.error_in_exec, repr(self.info), repr(self.result))
311 312
312 313 @functools.wraps(io_open)
313 314 def _modified_open(file, *args, **kwargs):
314 315 if file in {0, 1, 2}:
315 316 raise ValueError(
316 317 f"IPython won't let you open fd={file} by default "
317 318 "as it is likely to crash IPython. If you know what you are doing, "
318 319 "you can use builtins' open."
319 320 )
320 321
321 322 return io_open(file, *args, **kwargs)
322 323
323 324 class InteractiveShell(SingletonConfigurable):
324 325 """An enhanced, interactive shell for Python."""
325 326
326 327 _instance = None
327 328
328 329 ast_transformers: List[ast.NodeTransformer] = List(
329 330 [],
330 331 help="""
331 332 A list of ast.NodeTransformer subclass instances, which will be applied
332 333 to user input before code is run.
333 334 """,
334 335 ).tag(config=True)
335 336
336 337 autocall = Enum((0,1,2), default_value=0, help=
337 338 """
338 339 Make IPython automatically call any callable object even if you didn't
339 340 type explicit parentheses. For example, 'str 43' becomes 'str(43)'
340 341 automatically. The value can be '0' to disable the feature, '1' for
341 342 'smart' autocall, where it is not applied if there are no more
342 343 arguments on the line, and '2' for 'full' autocall, where all callable
343 344 objects are automatically called (even if no arguments are present).
344 345 """
345 346 ).tag(config=True)
346 347
347 348 autoindent = Bool(True, help=
348 349 """
349 350 Autoindent IPython code entered interactively.
350 351 """
351 352 ).tag(config=True)
352 353
353 354 autoawait = Bool(True, help=
354 355 """
355 356 Automatically run await statement in the top level repl.
356 357 """
357 358 ).tag(config=True)
358 359
359 360 loop_runner_map ={
360 361 'asyncio':(_asyncio_runner, True),
361 362 'curio':(_curio_runner, True),
362 363 'trio':(_trio_runner, True),
363 364 'sync': (_pseudo_sync_runner, False)
364 365 }
365 366
366 367 loop_runner = Any(default_value="IPython.core.interactiveshell._asyncio_runner",
367 368 allow_none=True,
368 369 help="""Select the loop runner that will be used to execute top-level asynchronous code"""
369 370 ).tag(config=True)
370 371
371 372 @default('loop_runner')
372 373 def _default_loop_runner(self):
373 374 return import_item("IPython.core.interactiveshell._asyncio_runner")
374 375
375 376 @validate('loop_runner')
376 377 def _import_runner(self, proposal):
377 378 if isinstance(proposal.value, str):
378 379 if proposal.value in self.loop_runner_map:
379 380 runner, autoawait = self.loop_runner_map[proposal.value]
380 381 self.autoawait = autoawait
381 382 return runner
382 383 runner = import_item(proposal.value)
383 384 if not callable(runner):
384 385 raise ValueError('loop_runner must be callable')
385 386 return runner
386 387 if not callable(proposal.value):
387 388 raise ValueError('loop_runner must be callable')
388 389 return proposal.value
389 390
390 391 automagic = Bool(True, help=
391 392 """
392 393 Enable magic commands to be called without the leading %.
393 394 """
394 395 ).tag(config=True)
395 396
396 397 banner1 = Unicode(default_banner,
397 398 help="""The part of the banner to be printed before the profile"""
398 399 ).tag(config=True)
399 400 banner2 = Unicode('',
400 401 help="""The part of the banner to be printed after the profile"""
401 402 ).tag(config=True)
402 403
403 404 cache_size = Integer(1000, help=
404 405 """
405 406 Set the size of the output cache. The default is 1000, you can
406 407 change it permanently in your config file. Setting it to 0 completely
407 408 disables the caching system, and the minimum value accepted is 3 (if
408 409 you provide a value less than 3, it is reset to 0 and a warning is
409 410 issued). This limit is defined because otherwise you'll spend more
410 411 time re-flushing a too small cache than working
411 412 """
412 413 ).tag(config=True)
413 414 color_info = Bool(True, help=
414 415 """
415 416 Use colors for displaying information about objects. Because this
416 417 information is passed through a pager (like 'less'), and some pagers
417 418 get confused with color codes, this capability can be turned off.
418 419 """
419 420 ).tag(config=True)
420 421 colors = CaselessStrEnum(('Neutral', 'NoColor','LightBG','Linux'),
421 422 default_value='Neutral',
422 423 help="Set the color scheme (NoColor, Neutral, Linux, or LightBG)."
423 424 ).tag(config=True)
424 425 debug = Bool(False).tag(config=True)
425 426 disable_failing_post_execute = Bool(False,
426 427 help="Don't call post-execute functions that have failed in the past."
427 428 ).tag(config=True)
428 429 display_formatter = Instance(DisplayFormatter, allow_none=True)
429 430 displayhook_class = Type(DisplayHook)
430 431 display_pub_class = Type(DisplayPublisher)
431 432 compiler_class = Type(CachingCompiler)
432 433 inspector_class = Type(
433 434 oinspect.Inspector, help="Class to use to instantiate the shell inspector"
434 435 ).tag(config=True)
435 436
436 437 sphinxify_docstring = Bool(False, help=
437 438 """
438 439 Enables rich html representation of docstrings. (This requires the
439 440 docrepr module).
440 441 """).tag(config=True)
441 442
442 443 @observe("sphinxify_docstring")
443 444 def _sphinxify_docstring_changed(self, change):
444 445 if change['new']:
445 446 warn("`sphinxify_docstring` is provisional since IPython 5.0 and might change in future versions." , ProvisionalWarning)
446 447
447 448 enable_html_pager = Bool(False, help=
448 449 """
449 450 (Provisional API) enables html representation in mime bundles sent
450 451 to pagers.
451 452 """).tag(config=True)
452 453
453 454 @observe("enable_html_pager")
454 455 def _enable_html_pager_changed(self, change):
455 456 if change['new']:
456 457 warn("`enable_html_pager` is provisional since IPython 5.0 and might change in future versions.", ProvisionalWarning)
457 458
458 459 data_pub_class = None
459 460
460 461 exit_now = Bool(False)
461 462 exiter = Instance(ExitAutocall)
462 463 @default('exiter')
463 464 def _exiter_default(self):
464 465 return ExitAutocall(self)
465 466 # Monotonically increasing execution counter
466 467 execution_count = Integer(1)
467 468 filename = Unicode("<ipython console>")
468 469 ipython_dir= Unicode('').tag(config=True) # Set to get_ipython_dir() in __init__
469 470
470 471 # Used to transform cells before running them, and check whether code is complete
471 472 input_transformer_manager = Instance('IPython.core.inputtransformer2.TransformerManager',
472 473 ())
473 474
474 475 @property
475 476 def input_transformers_cleanup(self):
476 477 return self.input_transformer_manager.cleanup_transforms
477 478
478 479 input_transformers_post: List = List(
479 480 [],
480 481 help="A list of string input transformers, to be applied after IPython's "
481 482 "own input transformations."
482 483 )
483 484
484 485 @property
485 486 def input_splitter(self):
486 487 """Make this available for backward compatibility (pre-7.0 release) with existing code.
487 488
488 489 For example, ipykernel ipykernel currently uses
489 490 `shell.input_splitter.check_complete`
490 491 """
491 492 from warnings import warn
492 493 warn("`input_splitter` is deprecated since IPython 7.0, prefer `input_transformer_manager`.",
493 494 DeprecationWarning, stacklevel=2
494 495 )
495 496 return self.input_transformer_manager
496 497
497 498 logstart = Bool(False, help=
498 499 """
499 500 Start logging to the default log file in overwrite mode.
500 501 Use `logappend` to specify a log file to **append** logs to.
501 502 """
502 503 ).tag(config=True)
503 504 logfile = Unicode('', help=
504 505 """
505 506 The name of the logfile to use.
506 507 """
507 508 ).tag(config=True)
508 509 logappend = Unicode('', help=
509 510 """
510 511 Start logging to the given file in append mode.
511 512 Use `logfile` to specify a log file to **overwrite** logs to.
512 513 """
513 514 ).tag(config=True)
514 515 object_info_string_level = Enum((0,1,2), default_value=0,
515 516 ).tag(config=True)
516 517 pdb = Bool(False, help=
517 518 """
518 519 Automatically call the pdb debugger after every exception.
519 520 """
520 521 ).tag(config=True)
521 522 display_page = Bool(False,
522 523 help="""If True, anything that would be passed to the pager
523 524 will be displayed as regular output instead."""
524 525 ).tag(config=True)
525 526
526 527
527 528 show_rewritten_input = Bool(True,
528 529 help="Show rewritten input, e.g. for autocall."
529 530 ).tag(config=True)
530 531
531 532 quiet = Bool(False).tag(config=True)
532 533
533 534 history_length = Integer(10000,
534 535 help='Total length of command history'
535 536 ).tag(config=True)
536 537
537 538 history_load_length = Integer(1000, help=
538 539 """
539 540 The number of saved history entries to be loaded
540 541 into the history buffer at startup.
541 542 """
542 543 ).tag(config=True)
543 544
544 545 ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none', 'last_expr_or_assign'],
545 546 default_value='last_expr',
546 547 help="""
547 548 'all', 'last', 'last_expr' or 'none', 'last_expr_or_assign' specifying
548 549 which nodes should be run interactively (displaying output from expressions).
549 550 """
550 551 ).tag(config=True)
551 552
552 553 warn_venv = Bool(
553 554 True,
554 555 help="Warn if running in a virtual environment with no IPython installed (so IPython from the global environment is used).",
555 556 ).tag(config=True)
556 557
557 558 # TODO: this part of prompt management should be moved to the frontends.
558 559 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
559 560 separate_in = SeparateUnicode('\n').tag(config=True)
560 561 separate_out = SeparateUnicode('').tag(config=True)
561 562 separate_out2 = SeparateUnicode('').tag(config=True)
562 563 wildcards_case_sensitive = Bool(True).tag(config=True)
563 564 xmode = CaselessStrEnum(('Context', 'Plain', 'Verbose', 'Minimal'),
564 565 default_value='Context',
565 566 help="Switch modes for the IPython exception handlers."
566 567 ).tag(config=True)
567 568
568 569 # Subcomponents of InteractiveShell
569 570 alias_manager = Instance("IPython.core.alias.AliasManager", allow_none=True)
570 571 prefilter_manager = Instance(
571 572 "IPython.core.prefilter.PrefilterManager", allow_none=True
572 573 )
573 574 builtin_trap = Instance("IPython.core.builtin_trap.BuiltinTrap")
574 575 display_trap = Instance("IPython.core.display_trap.DisplayTrap")
575 576 extension_manager = Instance(
576 577 "IPython.core.extensions.ExtensionManager", allow_none=True
577 578 )
578 579 payload_manager = Instance("IPython.core.payload.PayloadManager", allow_none=True)
579 580 history_manager = Instance(
580 581 "IPython.core.history.HistoryAccessorBase", allow_none=True
581 582 )
582 583 magics_manager = Instance("IPython.core.magic.MagicsManager")
583 584
584 585 profile_dir = Instance('IPython.core.application.ProfileDir', allow_none=True)
585 586 @property
586 587 def profile(self):
587 588 if self.profile_dir is not None:
588 589 name = os.path.basename(self.profile_dir.location)
589 590 return name.replace('profile_','')
590 591
591 592
592 593 # Private interface
593 594 _post_execute = Dict()
594 595
595 596 # Tracks any GUI loop loaded for pylab
596 597 pylab_gui_select = None
597 598
598 599 last_execution_succeeded = Bool(True, help='Did last executed command succeeded')
599 600
600 601 last_execution_result = Instance('IPython.core.interactiveshell.ExecutionResult', help='Result of executing the last command', allow_none=True)
601 602
602 603 def __init__(self, ipython_dir=None, profile_dir=None,
603 604 user_module=None, user_ns=None,
604 605 custom_exceptions=((), None), **kwargs):
605 606 # This is where traits with a config_key argument are updated
606 607 # from the values on config.
607 608 super(InteractiveShell, self).__init__(**kwargs)
608 609 if 'PromptManager' in self.config:
609 610 warn('As of IPython 5.0 `PromptManager` config will have no effect'
610 611 ' and has been replaced by TerminalInteractiveShell.prompts_class')
611 612 self.configurables = [self]
612 613
613 614 # These are relatively independent and stateless
614 615 self.init_ipython_dir(ipython_dir)
615 616 self.init_profile_dir(profile_dir)
616 617 self.init_instance_attrs()
617 618 self.init_environment()
618 619
619 620 # Check if we're in a virtualenv, and set up sys.path.
620 621 self.init_virtualenv()
621 622
622 623 # Create namespaces (user_ns, user_global_ns, etc.)
623 624 self.init_create_namespaces(user_module, user_ns)
624 625 # This has to be done after init_create_namespaces because it uses
625 626 # something in self.user_ns, but before init_sys_modules, which
626 627 # is the first thing to modify sys.
627 628 # TODO: When we override sys.stdout and sys.stderr before this class
628 629 # is created, we are saving the overridden ones here. Not sure if this
629 630 # is what we want to do.
630 631 self.save_sys_module_state()
631 632 self.init_sys_modules()
632 633
633 634 # While we're trying to have each part of the code directly access what
634 635 # it needs without keeping redundant references to objects, we have too
635 636 # much legacy code that expects ip.db to exist.
636 637 self.db = PickleShareDB(os.path.join(self.profile_dir.location, 'db'))
637 638
638 639 self.init_history()
639 640 self.init_encoding()
640 641 self.init_prefilter()
641 642
642 643 self.init_syntax_highlighting()
643 644 self.init_hooks()
644 645 self.init_events()
645 646 self.init_pushd_popd_magic()
646 647 self.init_user_ns()
647 648 self.init_logger()
648 649 self.init_builtins()
649 650
650 651 # The following was in post_config_initialization
651 652 self.init_inspector()
652 653 self.raw_input_original = input
653 654 self.init_completer()
654 655 # TODO: init_io() needs to happen before init_traceback handlers
655 656 # because the traceback handlers hardcode the stdout/stderr streams.
656 657 # This logic in in debugger.Pdb and should eventually be changed.
657 658 self.init_io()
658 659 self.init_traceback_handlers(custom_exceptions)
659 660 self.init_prompts()
660 661 self.init_display_formatter()
661 662 self.init_display_pub()
662 663 self.init_data_pub()
663 664 self.init_displayhook()
664 665 self.init_magics()
665 666 self.init_alias()
666 667 self.init_logstart()
667 668 self.init_pdb()
668 669 self.init_extension_manager()
669 670 self.init_payload()
670 671 self.events.trigger('shell_initialized', self)
671 672 atexit.register(self.atexit_operations)
672 673
673 674 # The trio runner is used for running Trio in the foreground thread. It
674 675 # is different from `_trio_runner(async_fn)` in `async_helpers.py`
675 676 # which calls `trio.run()` for every cell. This runner runs all cells
676 677 # inside a single Trio event loop. If used, it is set from
677 678 # `ipykernel.kernelapp`.
678 679 self.trio_runner = None
679 680
680 681 def get_ipython(self):
681 682 """Return the currently running IPython instance."""
682 683 return self
683 684
684 685 #-------------------------------------------------------------------------
685 686 # Trait changed handlers
686 687 #-------------------------------------------------------------------------
687 688 @observe('ipython_dir')
688 689 def _ipython_dir_changed(self, change):
689 690 ensure_dir_exists(change['new'])
690 691
691 692 def set_autoindent(self,value=None):
692 693 """Set the autoindent flag.
693 694
694 695 If called with no arguments, it acts as a toggle."""
695 696 if value is None:
696 697 self.autoindent = not self.autoindent
697 698 else:
698 699 self.autoindent = value
699 700
700 701 def set_trio_runner(self, tr):
701 702 self.trio_runner = tr
702 703
703 704 #-------------------------------------------------------------------------
704 705 # init_* methods called by __init__
705 706 #-------------------------------------------------------------------------
706 707
707 708 def init_ipython_dir(self, ipython_dir):
708 709 if ipython_dir is not None:
709 710 self.ipython_dir = ipython_dir
710 711 return
711 712
712 713 self.ipython_dir = get_ipython_dir()
713 714
714 715 def init_profile_dir(self, profile_dir):
715 716 if profile_dir is not None:
716 717 self.profile_dir = profile_dir
717 718 return
718 719 self.profile_dir = ProfileDir.create_profile_dir_by_name(
719 720 self.ipython_dir, "default"
720 721 )
721 722
722 723 def init_instance_attrs(self):
723 724 self.more = False
724 725
725 726 # command compiler
726 727 self.compile = self.compiler_class()
727 728
728 729 # Make an empty namespace, which extension writers can rely on both
729 730 # existing and NEVER being used by ipython itself. This gives them a
730 731 # convenient location for storing additional information and state
731 732 # their extensions may require, without fear of collisions with other
732 733 # ipython names that may develop later.
733 734 self.meta = Struct()
734 735
735 736 # Temporary files used for various purposes. Deleted at exit.
736 737 # The files here are stored with Path from Pathlib
737 738 self.tempfiles = []
738 739 self.tempdirs = []
739 740
740 741 # keep track of where we started running (mainly for crash post-mortem)
741 742 # This is not being used anywhere currently.
742 743 self.starting_dir = os.getcwd()
743 744
744 745 # Indentation management
745 746 self.indent_current_nsp = 0
746 747
747 748 # Dict to track post-execution functions that have been registered
748 749 self._post_execute = {}
749 750
750 751 def init_environment(self):
751 752 """Any changes we need to make to the user's environment."""
752 753 pass
753 754
754 755 def init_encoding(self):
755 756 # Get system encoding at startup time. Certain terminals (like Emacs
756 757 # under Win32 have it set to None, and we need to have a known valid
757 758 # encoding to use in the raw_input() method
758 759 try:
759 760 self.stdin_encoding = sys.stdin.encoding or 'ascii'
760 761 except AttributeError:
761 762 self.stdin_encoding = 'ascii'
762 763
763 764
764 765 @observe('colors')
765 766 def init_syntax_highlighting(self, changes=None):
766 767 # Python source parser/formatter for syntax highlighting
767 768 pyformat = PyColorize.Parser(style=self.colors, parent=self).format
768 769 self.pycolorize = lambda src: pyformat(src,'str')
769 770
770 771 def refresh_style(self):
771 772 # No-op here, used in subclass
772 773 pass
773 774
774 775 def init_pushd_popd_magic(self):
775 776 # for pushd/popd management
776 777 self.home_dir = get_home_dir()
777 778
778 779 self.dir_stack = []
779 780
780 781 def init_logger(self):
781 782 self.logger = Logger(self.home_dir, logfname='ipython_log.py',
782 783 logmode='rotate')
783 784
784 785 def init_logstart(self):
785 786 """Initialize logging in case it was requested at the command line.
786 787 """
787 788 if self.logappend:
788 789 self.magic('logstart %s append' % self.logappend)
789 790 elif self.logfile:
790 791 self.magic('logstart %s' % self.logfile)
791 792 elif self.logstart:
792 793 self.magic('logstart')
793 794
794 795
795 796 def init_builtins(self):
796 797 # A single, static flag that we set to True. Its presence indicates
797 798 # that an IPython shell has been created, and we make no attempts at
798 799 # removing on exit or representing the existence of more than one
799 800 # IPython at a time.
800 801 builtin_mod.__dict__['__IPYTHON__'] = True
801 802 builtin_mod.__dict__['display'] = display
802 803
803 804 self.builtin_trap = BuiltinTrap(shell=self)
804 805
805 806 @observe('colors')
806 807 def init_inspector(self, changes=None):
807 808 # Object inspector
808 809 self.inspector = self.inspector_class(
809 810 oinspect.InspectColors,
810 811 PyColorize.ANSICodeColors,
811 812 self.colors,
812 813 self.object_info_string_level,
813 814 )
814 815
815 816 def init_io(self):
816 817 # implemented in subclasses, TerminalInteractiveShell does call
817 818 # colorama.init().
818 819 pass
819 820
820 821 def init_prompts(self):
821 822 # Set system prompts, so that scripts can decide if they are running
822 823 # interactively.
823 824 sys.ps1 = 'In : '
824 825 sys.ps2 = '...: '
825 826 sys.ps3 = 'Out: '
826 827
827 828 def init_display_formatter(self):
828 829 self.display_formatter = DisplayFormatter(parent=self)
829 830 self.configurables.append(self.display_formatter)
830 831
831 832 def init_display_pub(self):
832 833 self.display_pub = self.display_pub_class(parent=self, shell=self)
833 834 self.configurables.append(self.display_pub)
834 835
835 836 def init_data_pub(self):
836 837 if not self.data_pub_class:
837 838 self.data_pub = None
838 839 return
839 840 self.data_pub = self.data_pub_class(parent=self)
840 841 self.configurables.append(self.data_pub)
841 842
842 843 def init_displayhook(self):
843 844 # Initialize displayhook, set in/out prompts and printing system
844 845 self.displayhook = self.displayhook_class(
845 846 parent=self,
846 847 shell=self,
847 848 cache_size=self.cache_size,
848 849 )
849 850 self.configurables.append(self.displayhook)
850 851 # This is a context manager that installs/revmoes the displayhook at
851 852 # the appropriate time.
852 853 self.display_trap = DisplayTrap(hook=self.displayhook)
853 854
854 855 @staticmethod
855 856 def get_path_links(p: Path):
856 857 """Gets path links including all symlinks
857 858
858 859 Examples
859 860 --------
860 861 In [1]: from IPython.core.interactiveshell import InteractiveShell
861 862
862 863 In [2]: import sys, pathlib
863 864
864 865 In [3]: paths = InteractiveShell.get_path_links(pathlib.Path(sys.executable))
865 866
866 867 In [4]: len(paths) == len(set(paths))
867 868 Out[4]: True
868 869
869 870 In [5]: bool(paths)
870 871 Out[5]: True
871 872 """
872 873 paths = [p]
873 874 while p.is_symlink():
874 875 new_path = Path(os.readlink(p))
875 876 if not new_path.is_absolute():
876 877 new_path = p.parent / new_path
877 878 p = new_path
878 879 paths.append(p)
879 880 return paths
880 881
881 882 def init_virtualenv(self):
882 883 """Add the current virtualenv to sys.path so the user can import modules from it.
883 884 This isn't perfect: it doesn't use the Python interpreter with which the
884 885 virtualenv was built, and it ignores the --no-site-packages option. A
885 886 warning will appear suggesting the user installs IPython in the
886 887 virtualenv, but for many cases, it probably works well enough.
887 888
888 889 Adapted from code snippets online.
889 890
890 891 http://blog.ufsoft.org/2009/1/29/ipython-and-virtualenv
891 892 """
892 893 if 'VIRTUAL_ENV' not in os.environ:
893 894 # Not in a virtualenv
894 895 return
895 896 elif os.environ["VIRTUAL_ENV"] == "":
896 897 warn("Virtual env path set to '', please check if this is intended.")
897 898 return
898 899
899 900 p = Path(sys.executable)
900 901 p_venv = Path(os.environ["VIRTUAL_ENV"])
901 902
902 903 # fallback venv detection:
903 904 # stdlib venv may symlink sys.executable, so we can't use realpath.
904 905 # but others can symlink *to* the venv Python, so we can't just use sys.executable.
905 906 # So we just check every item in the symlink tree (generally <= 3)
906 907 paths = self.get_path_links(p)
907 908
908 909 # In Cygwin paths like "c:\..." and '\cygdrive\c\...' are possible
909 910 if len(p_venv.parts) > 2 and p_venv.parts[1] == "cygdrive":
910 911 drive_name = p_venv.parts[2]
911 912 p_venv = (drive_name + ":/") / Path(*p_venv.parts[3:])
912 913
913 914 if any(p_venv == p.parents[1] for p in paths):
914 915 # Our exe is inside or has access to the virtualenv, don't need to do anything.
915 916 return
916 917
917 918 if sys.platform == "win32":
918 919 virtual_env = str(Path(os.environ["VIRTUAL_ENV"], "Lib", "site-packages"))
919 920 else:
920 921 virtual_env_path = Path(
921 922 os.environ["VIRTUAL_ENV"], "lib", "python{}.{}", "site-packages"
922 923 )
923 924 p_ver = sys.version_info[:2]
924 925
925 926 # Predict version from py[thon]-x.x in the $VIRTUAL_ENV
926 927 re_m = re.search(r"\bpy(?:thon)?([23])\.(\d+)\b", os.environ["VIRTUAL_ENV"])
927 928 if re_m:
928 929 predicted_path = Path(str(virtual_env_path).format(*re_m.groups()))
929 930 if predicted_path.exists():
930 931 p_ver = re_m.groups()
931 932
932 933 virtual_env = str(virtual_env_path).format(*p_ver)
933 934 if self.warn_venv:
934 935 warn(
935 936 "Attempting to work in a virtualenv. If you encounter problems, "
936 937 "please install IPython inside the virtualenv."
937 938 )
938 939 import site
939 940 sys.path.insert(0, virtual_env)
940 941 site.addsitedir(virtual_env)
941 942
942 943 #-------------------------------------------------------------------------
943 944 # Things related to injections into the sys module
944 945 #-------------------------------------------------------------------------
945 946
946 947 def save_sys_module_state(self):
947 948 """Save the state of hooks in the sys module.
948 949
949 950 This has to be called after self.user_module is created.
950 951 """
951 952 self._orig_sys_module_state = {'stdin': sys.stdin,
952 953 'stdout': sys.stdout,
953 954 'stderr': sys.stderr,
954 955 'excepthook': sys.excepthook}
955 956 self._orig_sys_modules_main_name = self.user_module.__name__
956 957 self._orig_sys_modules_main_mod = sys.modules.get(self.user_module.__name__)
957 958
958 959 def restore_sys_module_state(self):
959 960 """Restore the state of the sys module."""
960 961 try:
961 962 for k, v in self._orig_sys_module_state.items():
962 963 setattr(sys, k, v)
963 964 except AttributeError:
964 965 pass
965 966 # Reset what what done in self.init_sys_modules
966 967 if self._orig_sys_modules_main_mod is not None:
967 968 sys.modules[self._orig_sys_modules_main_name] = self._orig_sys_modules_main_mod
968 969
969 970 #-------------------------------------------------------------------------
970 971 # Things related to the banner
971 972 #-------------------------------------------------------------------------
972 973
973 974 @property
974 975 def banner(self):
975 976 banner = self.banner1
976 977 if self.profile and self.profile != 'default':
977 978 banner += '\nIPython profile: %s\n' % self.profile
978 979 if self.banner2:
979 980 banner += '\n' + self.banner2
980 981 return banner
981 982
982 983 def show_banner(self, banner=None):
983 984 if banner is None:
984 985 banner = self.banner
985 986 sys.stdout.write(banner)
986 987
987 988 #-------------------------------------------------------------------------
988 989 # Things related to hooks
989 990 #-------------------------------------------------------------------------
990 991
991 992 def init_hooks(self):
992 993 # hooks holds pointers used for user-side customizations
993 994 self.hooks = Struct()
994 995
995 996 self.strdispatchers = {}
996 997
997 998 # Set all default hooks, defined in the IPython.hooks module.
998 999 hooks = IPython.core.hooks
999 1000 for hook_name in hooks.__all__:
1000 1001 # default hooks have priority 100, i.e. low; user hooks should have
1001 1002 # 0-100 priority
1002 1003 self.set_hook(hook_name, getattr(hooks, hook_name), 100)
1003 1004
1004 1005 if self.display_page:
1005 1006 self.set_hook('show_in_pager', page.as_hook(page.display_page), 90)
1006 1007
1007 1008 def set_hook(self, name, hook, priority=50, str_key=None, re_key=None):
1008 1009 """set_hook(name,hook) -> sets an internal IPython hook.
1009 1010
1010 1011 IPython exposes some of its internal API as user-modifiable hooks. By
1011 1012 adding your function to one of these hooks, you can modify IPython's
1012 1013 behavior to call at runtime your own routines."""
1013 1014
1014 1015 # At some point in the future, this should validate the hook before it
1015 1016 # accepts it. Probably at least check that the hook takes the number
1016 1017 # of args it's supposed to.
1017 1018
1018 1019 f = types.MethodType(hook,self)
1019 1020
1020 1021 # check if the hook is for strdispatcher first
1021 1022 if str_key is not None:
1022 1023 sdp = self.strdispatchers.get(name, StrDispatch())
1023 1024 sdp.add_s(str_key, f, priority )
1024 1025 self.strdispatchers[name] = sdp
1025 1026 return
1026 1027 if re_key is not None:
1027 1028 sdp = self.strdispatchers.get(name, StrDispatch())
1028 1029 sdp.add_re(re.compile(re_key), f, priority )
1029 1030 self.strdispatchers[name] = sdp
1030 1031 return
1031 1032
1032 1033 dp = getattr(self.hooks, name, None)
1033 1034 if name not in IPython.core.hooks.__all__:
1034 1035 print("Warning! Hook '%s' is not one of %s" % \
1035 1036 (name, IPython.core.hooks.__all__ ))
1036 1037
1037 1038 if name in IPython.core.hooks.deprecated:
1038 1039 alternative = IPython.core.hooks.deprecated[name]
1039 1040 raise ValueError(
1040 1041 "Hook {} has been deprecated since IPython 5.0. Use {} instead.".format(
1041 1042 name, alternative
1042 1043 )
1043 1044 )
1044 1045
1045 1046 if not dp:
1046 1047 dp = IPython.core.hooks.CommandChainDispatcher()
1047 1048
1048 1049 try:
1049 1050 dp.add(f,priority)
1050 1051 except AttributeError:
1051 1052 # it was not commandchain, plain old func - replace
1052 1053 dp = f
1053 1054
1054 1055 setattr(self.hooks,name, dp)
1055 1056
1056 1057 #-------------------------------------------------------------------------
1057 1058 # Things related to events
1058 1059 #-------------------------------------------------------------------------
1059 1060
1060 1061 def init_events(self):
1061 1062 self.events = EventManager(self, available_events)
1062 1063
1063 1064 self.events.register("pre_execute", self._clear_warning_registry)
1064 1065
1065 1066 def register_post_execute(self, func):
1066 1067 """DEPRECATED: Use ip.events.register('post_run_cell', func)
1067 1068
1068 1069 Register a function for calling after code execution.
1069 1070 """
1070 1071 raise ValueError(
1071 1072 "ip.register_post_execute is deprecated since IPython 1.0, use "
1072 1073 "ip.events.register('post_run_cell', func) instead."
1073 1074 )
1074 1075
1075 1076 def _clear_warning_registry(self):
1076 1077 # clear the warning registry, so that different code blocks with
1077 1078 # overlapping line number ranges don't cause spurious suppression of
1078 1079 # warnings (see gh-6611 for details)
1079 1080 if "__warningregistry__" in self.user_global_ns:
1080 1081 del self.user_global_ns["__warningregistry__"]
1081 1082
1082 1083 #-------------------------------------------------------------------------
1083 1084 # Things related to the "main" module
1084 1085 #-------------------------------------------------------------------------
1085 1086
1086 1087 def new_main_mod(self, filename, modname):
1087 1088 """Return a new 'main' module object for user code execution.
1088 1089
1089 1090 ``filename`` should be the path of the script which will be run in the
1090 1091 module. Requests with the same filename will get the same module, with
1091 1092 its namespace cleared.
1092 1093
1093 1094 ``modname`` should be the module name - normally either '__main__' or
1094 1095 the basename of the file without the extension.
1095 1096
1096 1097 When scripts are executed via %run, we must keep a reference to their
1097 1098 __main__ module around so that Python doesn't
1098 1099 clear it, rendering references to module globals useless.
1099 1100
1100 1101 This method keeps said reference in a private dict, keyed by the
1101 1102 absolute path of the script. This way, for multiple executions of the
1102 1103 same script we only keep one copy of the namespace (the last one),
1103 1104 thus preventing memory leaks from old references while allowing the
1104 1105 objects from the last execution to be accessible.
1105 1106 """
1106 1107 filename = os.path.abspath(filename)
1107 1108 try:
1108 1109 main_mod = self._main_mod_cache[filename]
1109 1110 except KeyError:
1110 1111 main_mod = self._main_mod_cache[filename] = types.ModuleType(
1111 1112 modname,
1112 1113 doc="Module created for script run in IPython")
1113 1114 else:
1114 1115 main_mod.__dict__.clear()
1115 1116 main_mod.__name__ = modname
1116 1117
1117 1118 main_mod.__file__ = filename
1118 1119 # It seems pydoc (and perhaps others) needs any module instance to
1119 1120 # implement a __nonzero__ method
1120 1121 main_mod.__nonzero__ = lambda : True
1121 1122
1122 1123 return main_mod
1123 1124
1124 1125 def clear_main_mod_cache(self):
1125 1126 """Clear the cache of main modules.
1126 1127
1127 1128 Mainly for use by utilities like %reset.
1128 1129
1129 1130 Examples
1130 1131 --------
1131 1132 In [15]: import IPython
1132 1133
1133 1134 In [16]: m = _ip.new_main_mod(IPython.__file__, 'IPython')
1134 1135
1135 1136 In [17]: len(_ip._main_mod_cache) > 0
1136 1137 Out[17]: True
1137 1138
1138 1139 In [18]: _ip.clear_main_mod_cache()
1139 1140
1140 1141 In [19]: len(_ip._main_mod_cache) == 0
1141 1142 Out[19]: True
1142 1143 """
1143 1144 self._main_mod_cache.clear()
1144 1145
1145 1146 #-------------------------------------------------------------------------
1146 1147 # Things related to debugging
1147 1148 #-------------------------------------------------------------------------
1148 1149
1149 1150 def init_pdb(self):
1150 1151 # Set calling of pdb on exceptions
1151 1152 # self.call_pdb is a property
1152 1153 self.call_pdb = self.pdb
1153 1154
1154 1155 def _get_call_pdb(self):
1155 1156 return self._call_pdb
1156 1157
1157 1158 def _set_call_pdb(self,val):
1158 1159
1159 1160 if val not in (0,1,False,True):
1160 1161 raise ValueError('new call_pdb value must be boolean')
1161 1162
1162 1163 # store value in instance
1163 1164 self._call_pdb = val
1164 1165
1165 1166 # notify the actual exception handlers
1166 1167 self.InteractiveTB.call_pdb = val
1167 1168
1168 1169 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
1169 1170 'Control auto-activation of pdb at exceptions')
1170 1171
1171 1172 def debugger(self,force=False):
1172 1173 """Call the pdb debugger.
1173 1174
1174 1175 Keywords:
1175 1176
1176 1177 - force(False): by default, this routine checks the instance call_pdb
1177 1178 flag and does not actually invoke the debugger if the flag is false.
1178 1179 The 'force' option forces the debugger to activate even if the flag
1179 1180 is false.
1180 1181 """
1181 1182
1182 1183 if not (force or self.call_pdb):
1183 1184 return
1184 1185
1185 1186 if not hasattr(sys,'last_traceback'):
1186 1187 error('No traceback has been produced, nothing to debug.')
1187 1188 return
1188 1189
1189 1190 self.InteractiveTB.debugger(force=True)
1190 1191
1191 1192 #-------------------------------------------------------------------------
1192 1193 # Things related to IPython's various namespaces
1193 1194 #-------------------------------------------------------------------------
1194 1195 default_user_namespaces = True
1195 1196
1196 1197 def init_create_namespaces(self, user_module=None, user_ns=None):
1197 1198 # Create the namespace where the user will operate. user_ns is
1198 1199 # normally the only one used, and it is passed to the exec calls as
1199 1200 # the locals argument. But we do carry a user_global_ns namespace
1200 1201 # given as the exec 'globals' argument, This is useful in embedding
1201 1202 # situations where the ipython shell opens in a context where the
1202 1203 # distinction between locals and globals is meaningful. For
1203 1204 # non-embedded contexts, it is just the same object as the user_ns dict.
1204 1205
1205 1206 # FIXME. For some strange reason, __builtins__ is showing up at user
1206 1207 # level as a dict instead of a module. This is a manual fix, but I
1207 1208 # should really track down where the problem is coming from. Alex
1208 1209 # Schmolck reported this problem first.
1209 1210
1210 1211 # A useful post by Alex Martelli on this topic:
1211 1212 # Re: inconsistent value from __builtins__
1212 1213 # Von: Alex Martelli <aleaxit@yahoo.com>
1213 1214 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
1214 1215 # Gruppen: comp.lang.python
1215 1216
1216 1217 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
1217 1218 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
1218 1219 # > <type 'dict'>
1219 1220 # > >>> print type(__builtins__)
1220 1221 # > <type 'module'>
1221 1222 # > Is this difference in return value intentional?
1222 1223
1223 1224 # Well, it's documented that '__builtins__' can be either a dictionary
1224 1225 # or a module, and it's been that way for a long time. Whether it's
1225 1226 # intentional (or sensible), I don't know. In any case, the idea is
1226 1227 # that if you need to access the built-in namespace directly, you
1227 1228 # should start with "import __builtin__" (note, no 's') which will
1228 1229 # definitely give you a module. Yeah, it's somewhat confusing:-(.
1229 1230
1230 1231 # These routines return a properly built module and dict as needed by
1231 1232 # the rest of the code, and can also be used by extension writers to
1232 1233 # generate properly initialized namespaces.
1233 1234 if (user_ns is not None) or (user_module is not None):
1234 1235 self.default_user_namespaces = False
1235 1236 self.user_module, self.user_ns = self.prepare_user_module(user_module, user_ns)
1236 1237
1237 1238 # A record of hidden variables we have added to the user namespace, so
1238 1239 # we can list later only variables defined in actual interactive use.
1239 1240 self.user_ns_hidden = {}
1240 1241
1241 1242 # Now that FakeModule produces a real module, we've run into a nasty
1242 1243 # problem: after script execution (via %run), the module where the user
1243 1244 # code ran is deleted. Now that this object is a true module (needed
1244 1245 # so doctest and other tools work correctly), the Python module
1245 1246 # teardown mechanism runs over it, and sets to None every variable
1246 1247 # present in that module. Top-level references to objects from the
1247 1248 # script survive, because the user_ns is updated with them. However,
1248 1249 # calling functions defined in the script that use other things from
1249 1250 # the script will fail, because the function's closure had references
1250 1251 # to the original objects, which are now all None. So we must protect
1251 1252 # these modules from deletion by keeping a cache.
1252 1253 #
1253 1254 # To avoid keeping stale modules around (we only need the one from the
1254 1255 # last run), we use a dict keyed with the full path to the script, so
1255 1256 # only the last version of the module is held in the cache. Note,
1256 1257 # however, that we must cache the module *namespace contents* (their
1257 1258 # __dict__). Because if we try to cache the actual modules, old ones
1258 1259 # (uncached) could be destroyed while still holding references (such as
1259 1260 # those held by GUI objects that tend to be long-lived)>
1260 1261 #
1261 1262 # The %reset command will flush this cache. See the cache_main_mod()
1262 1263 # and clear_main_mod_cache() methods for details on use.
1263 1264
1264 1265 # This is the cache used for 'main' namespaces
1265 1266 self._main_mod_cache = {}
1266 1267
1267 1268 # A table holding all the namespaces IPython deals with, so that
1268 1269 # introspection facilities can search easily.
1269 1270 self.ns_table = {'user_global':self.user_module.__dict__,
1270 1271 'user_local':self.user_ns,
1271 1272 'builtin':builtin_mod.__dict__
1272 1273 }
1273 1274
1274 1275 @property
1275 1276 def user_global_ns(self):
1276 1277 return self.user_module.__dict__
1277 1278
1278 1279 def prepare_user_module(self, user_module=None, user_ns=None):
1279 1280 """Prepare the module and namespace in which user code will be run.
1280 1281
1281 1282 When IPython is started normally, both parameters are None: a new module
1282 1283 is created automatically, and its __dict__ used as the namespace.
1283 1284
1284 1285 If only user_module is provided, its __dict__ is used as the namespace.
1285 1286 If only user_ns is provided, a dummy module is created, and user_ns
1286 1287 becomes the global namespace. If both are provided (as they may be
1287 1288 when embedding), user_ns is the local namespace, and user_module
1288 1289 provides the global namespace.
1289 1290
1290 1291 Parameters
1291 1292 ----------
1292 1293 user_module : module, optional
1293 1294 The current user module in which IPython is being run. If None,
1294 1295 a clean module will be created.
1295 1296 user_ns : dict, optional
1296 1297 A namespace in which to run interactive commands.
1297 1298
1298 1299 Returns
1299 1300 -------
1300 1301 A tuple of user_module and user_ns, each properly initialised.
1301 1302 """
1302 1303 if user_module is None and user_ns is not None:
1303 1304 user_ns.setdefault("__name__", "__main__")
1304 1305 user_module = DummyMod()
1305 1306 user_module.__dict__ = user_ns
1306 1307
1307 1308 if user_module is None:
1308 1309 user_module = types.ModuleType("__main__",
1309 1310 doc="Automatically created module for IPython interactive environment")
1310 1311
1311 1312 # We must ensure that __builtin__ (without the final 's') is always
1312 1313 # available and pointing to the __builtin__ *module*. For more details:
1313 1314 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1314 1315 user_module.__dict__.setdefault('__builtin__', builtin_mod)
1315 1316 user_module.__dict__.setdefault('__builtins__', builtin_mod)
1316 1317
1317 1318 if user_ns is None:
1318 1319 user_ns = user_module.__dict__
1319 1320
1320 1321 return user_module, user_ns
1321 1322
1322 1323 def init_sys_modules(self):
1323 1324 # We need to insert into sys.modules something that looks like a
1324 1325 # module but which accesses the IPython namespace, for shelve and
1325 1326 # pickle to work interactively. Normally they rely on getting
1326 1327 # everything out of __main__, but for embedding purposes each IPython
1327 1328 # instance has its own private namespace, so we can't go shoving
1328 1329 # everything into __main__.
1329 1330
1330 1331 # note, however, that we should only do this for non-embedded
1331 1332 # ipythons, which really mimic the __main__.__dict__ with their own
1332 1333 # namespace. Embedded instances, on the other hand, should not do
1333 1334 # this because they need to manage the user local/global namespaces
1334 1335 # only, but they live within a 'normal' __main__ (meaning, they
1335 1336 # shouldn't overtake the execution environment of the script they're
1336 1337 # embedded in).
1337 1338
1338 1339 # This is overridden in the InteractiveShellEmbed subclass to a no-op.
1339 1340 main_name = self.user_module.__name__
1340 1341 sys.modules[main_name] = self.user_module
1341 1342
1342 1343 def init_user_ns(self):
1343 1344 """Initialize all user-visible namespaces to their minimum defaults.
1344 1345
1345 1346 Certain history lists are also initialized here, as they effectively
1346 1347 act as user namespaces.
1347 1348
1348 1349 Notes
1349 1350 -----
1350 1351 All data structures here are only filled in, they are NOT reset by this
1351 1352 method. If they were not empty before, data will simply be added to
1352 1353 them.
1353 1354 """
1354 1355 # This function works in two parts: first we put a few things in
1355 1356 # user_ns, and we sync that contents into user_ns_hidden so that these
1356 1357 # initial variables aren't shown by %who. After the sync, we add the
1357 1358 # rest of what we *do* want the user to see with %who even on a new
1358 1359 # session (probably nothing, so they really only see their own stuff)
1359 1360
1360 1361 # The user dict must *always* have a __builtin__ reference to the
1361 1362 # Python standard __builtin__ namespace, which must be imported.
1362 1363 # This is so that certain operations in prompt evaluation can be
1363 1364 # reliably executed with builtins. Note that we can NOT use
1364 1365 # __builtins__ (note the 's'), because that can either be a dict or a
1365 1366 # module, and can even mutate at runtime, depending on the context
1366 1367 # (Python makes no guarantees on it). In contrast, __builtin__ is
1367 1368 # always a module object, though it must be explicitly imported.
1368 1369
1369 1370 # For more details:
1370 1371 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1371 1372 ns = {}
1372 1373
1373 1374 # make global variables for user access to the histories
1374 1375 ns['_ih'] = self.history_manager.input_hist_parsed
1375 1376 ns['_oh'] = self.history_manager.output_hist
1376 1377 ns['_dh'] = self.history_manager.dir_hist
1377 1378
1378 1379 # user aliases to input and output histories. These shouldn't show up
1379 1380 # in %who, as they can have very large reprs.
1380 1381 ns['In'] = self.history_manager.input_hist_parsed
1381 1382 ns['Out'] = self.history_manager.output_hist
1382 1383
1383 1384 # Store myself as the public api!!!
1384 1385 ns['get_ipython'] = self.get_ipython
1385 1386
1386 1387 ns['exit'] = self.exiter
1387 1388 ns['quit'] = self.exiter
1388 1389 ns["open"] = _modified_open
1389 1390
1390 1391 # Sync what we've added so far to user_ns_hidden so these aren't seen
1391 1392 # by %who
1392 1393 self.user_ns_hidden.update(ns)
1393 1394
1394 1395 # Anything put into ns now would show up in %who. Think twice before
1395 1396 # putting anything here, as we really want %who to show the user their
1396 1397 # stuff, not our variables.
1397 1398
1398 1399 # Finally, update the real user's namespace
1399 1400 self.user_ns.update(ns)
1400 1401
1401 1402 @property
1402 1403 def all_ns_refs(self):
1403 1404 """Get a list of references to all the namespace dictionaries in which
1404 1405 IPython might store a user-created object.
1405 1406
1406 1407 Note that this does not include the displayhook, which also caches
1407 1408 objects from the output."""
1408 1409 return [self.user_ns, self.user_global_ns, self.user_ns_hidden] + \
1409 1410 [m.__dict__ for m in self._main_mod_cache.values()]
1410 1411
1411 1412 def reset(self, new_session=True, aggressive=False):
1412 1413 """Clear all internal namespaces, and attempt to release references to
1413 1414 user objects.
1414 1415
1415 1416 If new_session is True, a new history session will be opened.
1416 1417 """
1417 1418 # Clear histories
1418 1419 assert self.history_manager is not None
1419 1420 self.history_manager.reset(new_session)
1420 1421 # Reset counter used to index all histories
1421 1422 if new_session:
1422 1423 self.execution_count = 1
1423 1424
1424 1425 # Reset last execution result
1425 1426 self.last_execution_succeeded = True
1426 1427 self.last_execution_result = None
1427 1428
1428 1429 # Flush cached output items
1429 1430 if self.displayhook.do_full_cache:
1430 1431 self.displayhook.flush()
1431 1432
1432 1433 # The main execution namespaces must be cleared very carefully,
1433 1434 # skipping the deletion of the builtin-related keys, because doing so
1434 1435 # would cause errors in many object's __del__ methods.
1435 1436 if self.user_ns is not self.user_global_ns:
1436 1437 self.user_ns.clear()
1437 1438 ns = self.user_global_ns
1438 1439 drop_keys = set(ns.keys())
1439 1440 drop_keys.discard('__builtin__')
1440 1441 drop_keys.discard('__builtins__')
1441 1442 drop_keys.discard('__name__')
1442 1443 for k in drop_keys:
1443 1444 del ns[k]
1444 1445
1445 1446 self.user_ns_hidden.clear()
1446 1447
1447 1448 # Restore the user namespaces to minimal usability
1448 1449 self.init_user_ns()
1449 1450 if aggressive and not hasattr(self, "_sys_modules_keys"):
1450 1451 print("Cannot restore sys.module, no snapshot")
1451 1452 elif aggressive:
1452 1453 print("culling sys module...")
1453 1454 current_keys = set(sys.modules.keys())
1454 1455 for k in current_keys - self._sys_modules_keys:
1455 1456 if k.startswith("multiprocessing"):
1456 1457 continue
1457 1458 del sys.modules[k]
1458 1459
1459 1460 # Restore the default and user aliases
1460 1461 self.alias_manager.clear_aliases()
1461 1462 self.alias_manager.init_aliases()
1462 1463
1463 1464 # Now define aliases that only make sense on the terminal, because they
1464 1465 # need direct access to the console in a way that we can't emulate in
1465 1466 # GUI or web frontend
1466 1467 if os.name == 'posix':
1467 1468 for cmd in ('clear', 'more', 'less', 'man'):
1468 1469 if cmd not in self.magics_manager.magics['line']:
1469 1470 self.alias_manager.soft_define_alias(cmd, cmd)
1470 1471
1471 1472 # Flush the private list of module references kept for script
1472 1473 # execution protection
1473 1474 self.clear_main_mod_cache()
1474 1475
1475 1476 def del_var(self, varname, by_name=False):
1476 1477 """Delete a variable from the various namespaces, so that, as
1477 1478 far as possible, we're not keeping any hidden references to it.
1478 1479
1479 1480 Parameters
1480 1481 ----------
1481 1482 varname : str
1482 1483 The name of the variable to delete.
1483 1484 by_name : bool
1484 1485 If True, delete variables with the given name in each
1485 1486 namespace. If False (default), find the variable in the user
1486 1487 namespace, and delete references to it.
1487 1488 """
1488 1489 if varname in ('__builtin__', '__builtins__'):
1489 1490 raise ValueError("Refusing to delete %s" % varname)
1490 1491
1491 1492 ns_refs = self.all_ns_refs
1492 1493
1493 1494 if by_name: # Delete by name
1494 1495 for ns in ns_refs:
1495 1496 try:
1496 1497 del ns[varname]
1497 1498 except KeyError:
1498 1499 pass
1499 1500 else: # Delete by object
1500 1501 try:
1501 1502 obj = self.user_ns[varname]
1502 1503 except KeyError as e:
1503 1504 raise NameError("name '%s' is not defined" % varname) from e
1504 1505 # Also check in output history
1505 1506 assert self.history_manager is not None
1506 1507 ns_refs.append(self.history_manager.output_hist)
1507 1508 for ns in ns_refs:
1508 1509 to_delete = [n for n, o in ns.items() if o is obj]
1509 1510 for name in to_delete:
1510 1511 del ns[name]
1511 1512
1512 1513 # Ensure it is removed from the last execution result
1513 1514 if self.last_execution_result.result is obj:
1514 1515 self.last_execution_result = None
1515 1516
1516 1517 # displayhook keeps extra references, but not in a dictionary
1517 1518 for name in ('_', '__', '___'):
1518 1519 if getattr(self.displayhook, name) is obj:
1519 1520 setattr(self.displayhook, name, None)
1520 1521
1521 1522 def reset_selective(self, regex=None):
1522 1523 """Clear selective variables from internal namespaces based on a
1523 1524 specified regular expression.
1524 1525
1525 1526 Parameters
1526 1527 ----------
1527 1528 regex : string or compiled pattern, optional
1528 1529 A regular expression pattern that will be used in searching
1529 1530 variable names in the users namespaces.
1530 1531 """
1531 1532 if regex is not None:
1532 1533 try:
1533 1534 m = re.compile(regex)
1534 1535 except TypeError as e:
1535 1536 raise TypeError('regex must be a string or compiled pattern') from e
1536 1537 # Search for keys in each namespace that match the given regex
1537 1538 # If a match is found, delete the key/value pair.
1538 1539 for ns in self.all_ns_refs:
1539 1540 for var in ns:
1540 1541 if m.search(var):
1541 1542 del ns[var]
1542 1543
1543 1544 def push(self, variables, interactive=True):
1544 1545 """Inject a group of variables into the IPython user namespace.
1545 1546
1546 1547 Parameters
1547 1548 ----------
1548 1549 variables : dict, str or list/tuple of str
1549 1550 The variables to inject into the user's namespace. If a dict, a
1550 1551 simple update is done. If a str, the string is assumed to have
1551 1552 variable names separated by spaces. A list/tuple of str can also
1552 1553 be used to give the variable names. If just the variable names are
1553 1554 give (list/tuple/str) then the variable values looked up in the
1554 1555 callers frame.
1555 1556 interactive : bool
1556 1557 If True (default), the variables will be listed with the ``who``
1557 1558 magic.
1558 1559 """
1559 1560 vdict = None
1560 1561
1561 1562 # We need a dict of name/value pairs to do namespace updates.
1562 1563 if isinstance(variables, dict):
1563 1564 vdict = variables
1564 1565 elif isinstance(variables, (str, list, tuple)):
1565 1566 if isinstance(variables, str):
1566 1567 vlist = variables.split()
1567 1568 else:
1568 1569 vlist = variables
1569 1570 vdict = {}
1570 1571 cf = sys._getframe(1)
1571 1572 for name in vlist:
1572 1573 try:
1573 1574 vdict[name] = eval(name, cf.f_globals, cf.f_locals)
1574 except Exception:
1575 except:
1575 1576 print('Could not get variable %s from %s' %
1576 1577 (name,cf.f_code.co_name))
1577 1578 else:
1578 1579 raise ValueError('variables must be a dict/str/list/tuple')
1579 1580
1580 1581 # Propagate variables to user namespace
1581 1582 self.user_ns.update(vdict)
1582 1583
1583 1584 # And configure interactive visibility
1584 1585 user_ns_hidden = self.user_ns_hidden
1585 1586 if interactive:
1586 1587 for name in vdict:
1587 1588 user_ns_hidden.pop(name, None)
1588 1589 else:
1589 1590 user_ns_hidden.update(vdict)
1590 1591
1591 1592 def drop_by_id(self, variables):
1592 1593 """Remove a dict of variables from the user namespace, if they are the
1593 1594 same as the values in the dictionary.
1594 1595
1595 1596 This is intended for use by extensions: variables that they've added can
1596 1597 be taken back out if they are unloaded, without removing any that the
1597 1598 user has overwritten.
1598 1599
1599 1600 Parameters
1600 1601 ----------
1601 1602 variables : dict
1602 1603 A dictionary mapping object names (as strings) to the objects.
1603 1604 """
1604 1605 for name, obj in variables.items():
1605 1606 if name in self.user_ns and self.user_ns[name] is obj:
1606 1607 del self.user_ns[name]
1607 1608 self.user_ns_hidden.pop(name, None)
1608 1609
1609 1610 #-------------------------------------------------------------------------
1610 1611 # Things related to object introspection
1611 1612 #-------------------------------------------------------------------------
1612 1613 @staticmethod
1613 1614 def _find_parts(oname: str) -> Tuple[bool, ListType[str]]:
1614 1615 """
1615 1616 Given an object name, return a list of parts of this object name.
1616 1617
1617 1618 Basically split on docs when using attribute access,
1618 1619 and extract the value when using square bracket.
1619 1620
1620 1621
1621 1622 For example foo.bar[3].baz[x] -> foo, bar, 3, baz, x
1622 1623
1623 1624
1624 1625 Returns
1625 1626 -------
1626 1627 parts_ok: bool
1627 1628 whether we were properly able to parse parts.
1628 1629 parts: list of str
1629 1630 extracted parts
1630 1631
1631 1632
1632 1633
1633 1634 """
1634 1635 raw_parts = oname.split(".")
1635 1636 parts = []
1636 1637 parts_ok = True
1637 1638 for p in raw_parts:
1638 1639 if p.endswith("]"):
1639 1640 var, *indices = p.split("[")
1640 1641 if not var.isidentifier():
1641 1642 parts_ok = False
1642 1643 break
1643 1644 parts.append(var)
1644 1645 for ind in indices:
1645 1646 if ind[-1] != "]" and not is_integer_string(ind[:-1]):
1646 1647 parts_ok = False
1647 1648 break
1648 1649 parts.append(ind[:-1])
1649 1650 continue
1650 1651
1651 1652 if not p.isidentifier():
1652 1653 parts_ok = False
1653 1654 parts.append(p)
1654 1655
1655 1656 return parts_ok, parts
1656 1657
1657 1658 def _ofind(
1658 1659 self, oname: str, namespaces: Optional[Sequence[Tuple[str, AnyType]]] = None
1659 1660 ) -> OInfo:
1660 1661 """Find an object in the available namespaces.
1661 1662
1662 1663
1663 1664 Returns
1664 1665 -------
1665 1666 OInfo with fields:
1666 1667 - ismagic
1667 1668 - isalias
1668 1669 - found
1669 1670 - obj
1670 1671 - namespac
1671 1672 - parent
1672 1673
1673 1674 Has special code to detect magic functions.
1674 1675 """
1675 1676 oname = oname.strip()
1676 1677 parts_ok, parts = self._find_parts(oname)
1677 1678
1678 1679 if (
1679 1680 not oname.startswith(ESC_MAGIC)
1680 1681 and not oname.startswith(ESC_MAGIC2)
1681 1682 and not parts_ok
1682 1683 ):
1683 1684 return OInfo(
1684 1685 ismagic=False,
1685 1686 isalias=False,
1686 1687 found=False,
1687 1688 obj=None,
1688 1689 namespace=None,
1689 1690 parent=None,
1690 1691 )
1691 1692
1692 1693 if namespaces is None:
1693 1694 # Namespaces to search in:
1694 1695 # Put them in a list. The order is important so that we
1695 1696 # find things in the same order that Python finds them.
1696 1697 namespaces = [ ('Interactive', self.user_ns),
1697 1698 ('Interactive (global)', self.user_global_ns),
1698 1699 ('Python builtin', builtin_mod.__dict__),
1699 1700 ]
1700 1701
1701 1702 ismagic = False
1702 1703 isalias = False
1703 1704 found = False
1704 1705 ospace = None
1705 1706 parent = None
1706 1707 obj = None
1707 1708
1708 1709
1709 1710 # Look for the given name by splitting it in parts. If the head is
1710 1711 # found, then we look for all the remaining parts as members, and only
1711 1712 # declare success if we can find them all.
1712 1713 oname_parts = parts
1713 1714 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
1714 1715 for nsname,ns in namespaces:
1715 1716 try:
1716 1717 obj = ns[oname_head]
1717 1718 except KeyError:
1718 1719 continue
1719 1720 else:
1720 1721 for idx, part in enumerate(oname_rest):
1721 1722 try:
1722 1723 parent = obj
1723 1724 # The last part is looked up in a special way to avoid
1724 1725 # descriptor invocation as it may raise or have side
1725 1726 # effects.
1726 1727 if idx == len(oname_rest) - 1:
1727 1728 obj = self._getattr_property(obj, part)
1728 1729 else:
1729 1730 if is_integer_string(part):
1730 1731 obj = obj[int(part)]
1731 1732 else:
1732 1733 obj = getattr(obj, part)
1733 except Exception:
1734 except:
1734 1735 # Blanket except b/c some badly implemented objects
1735 1736 # allow __getattr__ to raise exceptions other than
1736 1737 # AttributeError, which then crashes IPython.
1737 1738 break
1738 1739 else:
1739 1740 # If we finish the for loop (no break), we got all members
1740 1741 found = True
1741 1742 ospace = nsname
1742 1743 break # namespace loop
1743 1744
1744 1745 # Try to see if it's magic
1745 1746 if not found:
1746 1747 obj = None
1747 1748 if oname.startswith(ESC_MAGIC2):
1748 1749 oname = oname.lstrip(ESC_MAGIC2)
1749 1750 obj = self.find_cell_magic(oname)
1750 1751 elif oname.startswith(ESC_MAGIC):
1751 1752 oname = oname.lstrip(ESC_MAGIC)
1752 1753 obj = self.find_line_magic(oname)
1753 1754 else:
1754 1755 # search without prefix, so run? will find %run?
1755 1756 obj = self.find_line_magic(oname)
1756 1757 if obj is None:
1757 1758 obj = self.find_cell_magic(oname)
1758 1759 if obj is not None:
1759 1760 found = True
1760 1761 ospace = 'IPython internal'
1761 1762 ismagic = True
1762 1763 isalias = isinstance(obj, Alias)
1763 1764
1764 1765 # Last try: special-case some literals like '', [], {}, etc:
1765 1766 if not found and oname_head in ["''",'""','[]','{}','()']:
1766 1767 obj = eval(oname_head)
1767 1768 found = True
1768 1769 ospace = 'Interactive'
1769 1770
1770 1771 return OInfo(
1771 1772 obj=obj,
1772 1773 found=found,
1773 1774 parent=parent,
1774 1775 ismagic=ismagic,
1775 1776 isalias=isalias,
1776 1777 namespace=ospace,
1777 1778 )
1778 1779
1779 1780 @staticmethod
1780 1781 def _getattr_property(obj, attrname):
1781 1782 """Property-aware getattr to use in object finding.
1782 1783
1783 1784 If attrname represents a property, return it unevaluated (in case it has
1784 1785 side effects or raises an error.
1785 1786
1786 1787 """
1787 1788 if not isinstance(obj, type):
1788 1789 try:
1789 1790 # `getattr(type(obj), attrname)` is not guaranteed to return
1790 1791 # `obj`, but does so for property:
1791 1792 #
1792 1793 # property.__get__(self, None, cls) -> self
1793 1794 #
1794 1795 # The universal alternative is to traverse the mro manually
1795 1796 # searching for attrname in class dicts.
1796 1797 if is_integer_string(attrname):
1797 1798 return obj[int(attrname)]
1798 1799 else:
1799 1800 attr = getattr(type(obj), attrname)
1800 1801 except AttributeError:
1801 1802 pass
1802 1803 else:
1803 1804 # This relies on the fact that data descriptors (with both
1804 1805 # __get__ & __set__ magic methods) take precedence over
1805 1806 # instance-level attributes:
1806 1807 #
1807 1808 # class A(object):
1808 1809 # @property
1809 1810 # def foobar(self): return 123
1810 1811 # a = A()
1811 1812 # a.__dict__['foobar'] = 345
1812 1813 # a.foobar # == 123
1813 1814 #
1814 1815 # So, a property may be returned right away.
1815 1816 if isinstance(attr, property):
1816 1817 return attr
1817 1818
1818 1819 # Nothing helped, fall back.
1819 1820 return getattr(obj, attrname)
1820 1821
1821 1822 def _object_find(self, oname, namespaces=None) -> OInfo:
1822 1823 """Find an object and return a struct with info about it."""
1823 1824 return self._ofind(oname, namespaces)
1824 1825
1825 1826 def _inspect(self, meth, oname: str, namespaces=None, **kw):
1826 1827 """Generic interface to the inspector system.
1827 1828
1828 1829 This function is meant to be called by pdef, pdoc & friends.
1829 1830 """
1830 1831 info: OInfo = self._object_find(oname, namespaces)
1831 1832 if self.sphinxify_docstring:
1832 1833 if sphinxify is None:
1833 1834 raise ImportError("Module ``docrepr`` required but missing")
1834 1835 docformat = sphinxify(self.object_inspect(oname))
1835 1836 else:
1836 1837 docformat = None
1837 1838 if info.found or hasattr(info.parent, oinspect.HOOK_NAME):
1838 1839 pmethod = getattr(self.inspector, meth)
1839 1840 # TODO: only apply format_screen to the plain/text repr of the mime
1840 1841 # bundle.
1841 1842 formatter = format_screen if info.ismagic else docformat
1842 1843 if meth == 'pdoc':
1843 1844 pmethod(info.obj, oname, formatter)
1844 1845 elif meth == 'pinfo':
1845 1846 pmethod(
1846 1847 info.obj,
1847 1848 oname,
1848 1849 formatter,
1849 1850 info,
1850 1851 enable_html_pager=self.enable_html_pager,
1851 1852 **kw,
1852 1853 )
1853 1854 else:
1854 1855 pmethod(info.obj, oname)
1855 1856 else:
1856 1857 print('Object `%s` not found.' % oname)
1857 1858 return 'not found' # so callers can take other action
1858 1859
1859 1860 def object_inspect(self, oname, detail_level=0):
1860 1861 """Get object info about oname"""
1861 1862 with self.builtin_trap:
1862 1863 info = self._object_find(oname)
1863 1864 if info.found:
1864 1865 return self.inspector.info(info.obj, oname, info=info,
1865 1866 detail_level=detail_level
1866 1867 )
1867 1868 else:
1868 1869 return oinspect.object_info(name=oname, found=False)
1869 1870
1870 1871 def object_inspect_text(self, oname, detail_level=0):
1871 1872 """Get object info as formatted text"""
1872 1873 return self.object_inspect_mime(oname, detail_level)['text/plain']
1873 1874
1874 1875 def object_inspect_mime(self, oname, detail_level=0, omit_sections=()):
1875 1876 """Get object info as a mimebundle of formatted representations.
1876 1877
1877 1878 A mimebundle is a dictionary, keyed by mime-type.
1878 1879 It must always have the key `'text/plain'`.
1879 1880 """
1880 1881 with self.builtin_trap:
1881 1882 info = self._object_find(oname)
1882 1883 if info.found:
1883 1884 docformat = (
1884 1885 sphinxify(self.object_inspect(oname))
1885 1886 if self.sphinxify_docstring
1886 1887 else None
1887 1888 )
1888 1889 return self.inspector._get_info(
1889 1890 info.obj,
1890 1891 oname,
1891 1892 info=info,
1892 1893 detail_level=detail_level,
1893 1894 formatter=docformat,
1894 1895 omit_sections=omit_sections,
1895 1896 )
1896 1897 else:
1897 1898 raise KeyError(oname)
1898 1899
1899 1900 #-------------------------------------------------------------------------
1900 1901 # Things related to history management
1901 1902 #-------------------------------------------------------------------------
1902 1903
1903 1904 def init_history(self):
1904 1905 """Sets up the command history, and starts regular autosaves."""
1905 1906 self.history_manager = HistoryManager(shell=self, parent=self)
1906 1907 self.configurables.append(self.history_manager)
1907 1908
1908 1909 #-------------------------------------------------------------------------
1909 1910 # Things related to exception handling and tracebacks (not debugging)
1910 1911 #-------------------------------------------------------------------------
1911 1912
1912 1913 debugger_cls = InterruptiblePdb
1913 1914
1914 1915 def init_traceback_handlers(self, custom_exceptions):
1915 1916 # Syntax error handler.
1916 1917 self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor', parent=self)
1917 1918
1918 1919 # The interactive one is initialized with an offset, meaning we always
1919 1920 # want to remove the topmost item in the traceback, which is our own
1920 1921 # internal code. Valid modes: ['Plain','Context','Verbose','Minimal']
1921 1922 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1922 1923 color_scheme='NoColor',
1923 1924 tb_offset = 1,
1924 1925 debugger_cls=self.debugger_cls, parent=self)
1925 1926
1926 1927 # The instance will store a pointer to the system-wide exception hook,
1927 1928 # so that runtime code (such as magics) can access it. This is because
1928 1929 # during the read-eval loop, it may get temporarily overwritten.
1929 1930 self.sys_excepthook = sys.excepthook
1930 1931
1931 1932 # and add any custom exception handlers the user may have specified
1932 1933 self.set_custom_exc(*custom_exceptions)
1933 1934
1934 1935 # Set the exception mode
1935 1936 self.InteractiveTB.set_mode(mode=self.xmode)
1936 1937
1937 1938 def set_custom_exc(self, exc_tuple, handler):
1938 1939 """set_custom_exc(exc_tuple, handler)
1939 1940
1940 1941 Set a custom exception handler, which will be called if any of the
1941 1942 exceptions in exc_tuple occur in the mainloop (specifically, in the
1942 1943 run_code() method).
1943 1944
1944 1945 Parameters
1945 1946 ----------
1946 1947 exc_tuple : tuple of exception classes
1947 1948 A *tuple* of exception classes, for which to call the defined
1948 1949 handler. It is very important that you use a tuple, and NOT A
1949 1950 LIST here, because of the way Python's except statement works. If
1950 1951 you only want to trap a single exception, use a singleton tuple::
1951 1952
1952 1953 exc_tuple == (MyCustomException,)
1953 1954
1954 1955 handler : callable
1955 1956 handler must have the following signature::
1956 1957
1957 1958 def my_handler(self, etype, value, tb, tb_offset=None):
1958 1959 ...
1959 1960 return structured_traceback
1960 1961
1961 1962 Your handler must return a structured traceback (a list of strings),
1962 1963 or None.
1963 1964
1964 1965 This will be made into an instance method (via types.MethodType)
1965 1966 of IPython itself, and it will be called if any of the exceptions
1966 1967 listed in the exc_tuple are caught. If the handler is None, an
1967 1968 internal basic one is used, which just prints basic info.
1968 1969
1969 1970 To protect IPython from crashes, if your handler ever raises an
1970 1971 exception or returns an invalid result, it will be immediately
1971 1972 disabled.
1972 1973
1973 1974 Notes
1974 1975 -----
1975 1976 WARNING: by putting in your own exception handler into IPython's main
1976 1977 execution loop, you run a very good chance of nasty crashes. This
1977 1978 facility should only be used if you really know what you are doing.
1978 1979 """
1979 1980
1980 1981 if not isinstance(exc_tuple, tuple):
1981 1982 raise TypeError("The custom exceptions must be given as a tuple.")
1982 1983
1983 1984 def dummy_handler(self, etype, value, tb, tb_offset=None):
1984 1985 print('*** Simple custom exception handler ***')
1985 1986 print('Exception type :', etype)
1986 1987 print('Exception value:', value)
1987 1988 print('Traceback :', tb)
1988 1989
1989 1990 def validate_stb(stb):
1990 1991 """validate structured traceback return type
1991 1992
1992 1993 return type of CustomTB *should* be a list of strings, but allow
1993 1994 single strings or None, which are harmless.
1994 1995
1995 1996 This function will *always* return a list of strings,
1996 1997 and will raise a TypeError if stb is inappropriate.
1997 1998 """
1998 1999 msg = "CustomTB must return list of strings, not %r" % stb
1999 2000 if stb is None:
2000 2001 return []
2001 2002 elif isinstance(stb, str):
2002 2003 return [stb]
2003 2004 elif not isinstance(stb, list):
2004 2005 raise TypeError(msg)
2005 2006 # it's a list
2006 2007 for line in stb:
2007 2008 # check every element
2008 2009 if not isinstance(line, str):
2009 2010 raise TypeError(msg)
2010 2011 return stb
2011 2012
2012 2013 if handler is None:
2013 2014 wrapped = dummy_handler
2014 2015 else:
2015 2016 def wrapped(self,etype,value,tb,tb_offset=None):
2016 2017 """wrap CustomTB handler, to protect IPython from user code
2017 2018
2018 2019 This makes it harder (but not impossible) for custom exception
2019 2020 handlers to crash IPython.
2020 2021 """
2021 2022 try:
2022 2023 stb = handler(self,etype,value,tb,tb_offset=tb_offset)
2023 2024 return validate_stb(stb)
2024 except Exception:
2025 except:
2025 2026 # clear custom handler immediately
2026 2027 self.set_custom_exc((), None)
2027 2028 print("Custom TB Handler failed, unregistering", file=sys.stderr)
2028 2029 # show the exception in handler first
2029 2030 stb = self.InteractiveTB.structured_traceback(*sys.exc_info())
2030 2031 print(self.InteractiveTB.stb2text(stb))
2031 2032 print("The original exception:")
2032 2033 stb = self.InteractiveTB.structured_traceback(
2033 2034 etype, value, tb, tb_offset=tb_offset
2034 2035 )
2035 2036 return stb
2036 2037
2037 2038 self.CustomTB = types.MethodType(wrapped,self)
2038 2039 self.custom_exceptions = exc_tuple
2039 2040
2040 2041 def excepthook(self, etype, value, tb):
2041 2042 """One more defense for GUI apps that call sys.excepthook.
2042 2043
2043 2044 GUI frameworks like wxPython trap exceptions and call
2044 2045 sys.excepthook themselves. I guess this is a feature that
2045 2046 enables them to keep running after exceptions that would
2046 2047 otherwise kill their mainloop. This is a bother for IPython
2047 2048 which expects to catch all of the program exceptions with a try:
2048 2049 except: statement.
2049 2050
2050 2051 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
2051 2052 any app directly invokes sys.excepthook, it will look to the user like
2052 2053 IPython crashed. In order to work around this, we can disable the
2053 2054 CrashHandler and replace it with this excepthook instead, which prints a
2054 2055 regular traceback using our InteractiveTB. In this fashion, apps which
2055 2056 call sys.excepthook will generate a regular-looking exception from
2056 2057 IPython, and the CrashHandler will only be triggered by real IPython
2057 2058 crashes.
2058 2059
2059 2060 This hook should be used sparingly, only in places which are not likely
2060 2061 to be true IPython errors.
2061 2062 """
2062 2063 self.showtraceback((etype, value, tb), tb_offset=0)
2063 2064
2064 2065 def _get_exc_info(self, exc_tuple=None):
2065 2066 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
2066 2067
2067 2068 Ensures sys.last_type,value,traceback hold the exc_info we found,
2068 2069 from whichever source.
2069 2070
2070 2071 raises ValueError if none of these contain any information
2071 2072 """
2072 2073 if exc_tuple is None:
2073 2074 etype, value, tb = sys.exc_info()
2074 2075 else:
2075 2076 etype, value, tb = exc_tuple
2076 2077
2077 2078 if etype is None:
2078 2079 if hasattr(sys, 'last_type'):
2079 2080 etype, value, tb = sys.last_type, sys.last_value, \
2080 2081 sys.last_traceback
2081 2082
2082 2083 if etype is None:
2083 2084 raise ValueError("No exception to find")
2084 2085
2085 2086 # Now store the exception info in sys.last_type etc.
2086 2087 # WARNING: these variables are somewhat deprecated and not
2087 2088 # necessarily safe to use in a threaded environment, but tools
2088 2089 # like pdb depend on their existence, so let's set them. If we
2089 2090 # find problems in the field, we'll need to revisit their use.
2090 2091 sys.last_type = etype
2091 2092 sys.last_value = value
2092 2093 sys.last_traceback = tb
2093 2094
2094 2095 return etype, value, tb
2095 2096
2096 2097 def show_usage_error(self, exc):
2097 2098 """Show a short message for UsageErrors
2098 2099
2099 2100 These are special exceptions that shouldn't show a traceback.
2100 2101 """
2101 2102 print("UsageError: %s" % exc, file=sys.stderr)
2102 2103
2103 2104 def get_exception_only(self, exc_tuple=None):
2104 2105 """
2105 2106 Return as a string (ending with a newline) the exception that
2106 2107 just occurred, without any traceback.
2107 2108 """
2108 2109 etype, value, tb = self._get_exc_info(exc_tuple)
2109 2110 msg = traceback.format_exception_only(etype, value)
2110 2111 return ''.join(msg)
2111 2112
2112 2113 def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None,
2113 2114 exception_only=False, running_compiled_code=False):
2114 2115 """Display the exception that just occurred.
2115 2116
2116 2117 If nothing is known about the exception, this is the method which
2117 2118 should be used throughout the code for presenting user tracebacks,
2118 2119 rather than directly invoking the InteractiveTB object.
2119 2120
2120 2121 A specific showsyntaxerror() also exists, but this method can take
2121 2122 care of calling it if needed, so unless you are explicitly catching a
2122 2123 SyntaxError exception, don't try to analyze the stack manually and
2123 2124 simply call this method."""
2124 2125
2125 2126 try:
2126 2127 try:
2127 2128 etype, value, tb = self._get_exc_info(exc_tuple)
2128 2129 except ValueError:
2129 2130 print('No traceback available to show.', file=sys.stderr)
2130 2131 return
2131 2132
2132 2133 if issubclass(etype, SyntaxError):
2133 2134 # Though this won't be called by syntax errors in the input
2134 2135 # line, there may be SyntaxError cases with imported code.
2135 2136 self.showsyntaxerror(filename, running_compiled_code)
2136 2137 elif etype is UsageError:
2137 2138 self.show_usage_error(value)
2138 2139 else:
2139 2140 if exception_only:
2140 2141 stb = ['An exception has occurred, use %tb to see '
2141 2142 'the full traceback.\n']
2142 2143 stb.extend(self.InteractiveTB.get_exception_only(etype,
2143 2144 value))
2144 2145 else:
2145 2146
2146 2147 def contains_exceptiongroup(val):
2147 2148 if val is None:
2148 2149 return False
2149 2150 return isinstance(
2150 2151 val, BaseExceptionGroup
2151 2152 ) or contains_exceptiongroup(val.__context__)
2152 2153
2153 2154 if contains_exceptiongroup(value):
2154 2155 # fall back to native exception formatting until ultratb
2155 2156 # supports exception groups
2156 2157 traceback.print_exc()
2157 2158 else:
2158 2159 try:
2159 2160 # Exception classes can customise their traceback - we
2160 2161 # use this in IPython.parallel for exceptions occurring
2161 2162 # in the engines. This should return a list of strings.
2162 2163 if hasattr(value, "_render_traceback_"):
2163 2164 stb = value._render_traceback_()
2164 2165 else:
2165 2166 stb = self.InteractiveTB.structured_traceback(
2166 2167 etype, value, tb, tb_offset=tb_offset
2167 2168 )
2168 2169
2169 2170 except Exception:
2170 2171 print(
2171 2172 "Unexpected exception formatting exception. Falling back to standard exception"
2172 2173 )
2173 2174 traceback.print_exc()
2174 2175 return None
2175 2176
2176 2177 self._showtraceback(etype, value, stb)
2177 2178 if self.call_pdb:
2178 2179 # drop into debugger
2179 2180 self.debugger(force=True)
2180 2181 return
2181 2182
2182 2183 # Actually show the traceback
2183 2184 self._showtraceback(etype, value, stb)
2184 2185
2185 2186 except KeyboardInterrupt:
2186 2187 print('\n' + self.get_exception_only(), file=sys.stderr)
2187 2188
2188 2189 def _showtraceback(self, etype, evalue, stb: str):
2189 2190 """Actually show a traceback.
2190 2191
2191 2192 Subclasses may override this method to put the traceback on a different
2192 2193 place, like a side channel.
2193 2194 """
2194 2195 val = self.InteractiveTB.stb2text(stb)
2195 2196 try:
2196 2197 print(val)
2197 2198 except UnicodeEncodeError:
2198 2199 print(val.encode("utf-8", "backslashreplace").decode())
2199 2200
2200 2201 def showsyntaxerror(self, filename=None, running_compiled_code=False):
2201 2202 """Display the syntax error that just occurred.
2202 2203
2203 2204 This doesn't display a stack trace because there isn't one.
2204 2205
2205 2206 If a filename is given, it is stuffed in the exception instead
2206 2207 of what was there before (because Python's parser always uses
2207 2208 "<string>" when reading from a string).
2208 2209
2209 2210 If the syntax error occurred when running a compiled code (i.e. running_compile_code=True),
2210 2211 longer stack trace will be displayed.
2211 2212 """
2212 2213 etype, value, last_traceback = self._get_exc_info()
2213 2214
2214 2215 if filename and issubclass(etype, SyntaxError):
2215 2216 try:
2216 2217 value.filename = filename
2217 except Exception:
2218 except:
2218 2219 # Not the format we expect; leave it alone
2219 2220 pass
2220 2221
2221 2222 # If the error occurred when executing compiled code, we should provide full stacktrace.
2222 2223 elist = traceback.extract_tb(last_traceback) if running_compiled_code else []
2223 2224 stb = self.SyntaxTB.structured_traceback(etype, value, elist)
2224 2225 self._showtraceback(etype, value, stb)
2225 2226
2226 2227 # This is overridden in TerminalInteractiveShell to show a message about
2227 2228 # the %paste magic.
2228 2229 def showindentationerror(self):
2229 2230 """Called by _run_cell when there's an IndentationError in code entered
2230 2231 at the prompt.
2231 2232
2232 2233 This is overridden in TerminalInteractiveShell to show a message about
2233 2234 the %paste magic."""
2234 2235 self.showsyntaxerror()
2235 2236
2236 2237 @skip_doctest
2237 2238 def set_next_input(self, s, replace=False):
2238 2239 """ Sets the 'default' input string for the next command line.
2239 2240
2240 2241 Example::
2241 2242
2242 2243 In [1]: _ip.set_next_input("Hello Word")
2243 2244 In [2]: Hello Word_ # cursor is here
2244 2245 """
2245 2246 self.rl_next_input = s
2246 2247
2247 2248 def _indent_current_str(self):
2248 2249 """return the current level of indentation as a string"""
2249 2250 return self.input_splitter.get_indent_spaces() * ' '
2250 2251
2251 2252 #-------------------------------------------------------------------------
2252 2253 # Things related to text completion
2253 2254 #-------------------------------------------------------------------------
2254 2255
2255 2256 def init_completer(self):
2256 2257 """Initialize the completion machinery.
2257 2258
2258 2259 This creates completion machinery that can be used by client code,
2259 2260 either interactively in-process (typically triggered by the readline
2260 2261 library), programmatically (such as in test suites) or out-of-process
2261 2262 (typically over the network by remote frontends).
2262 2263 """
2263 2264 from IPython.core.completer import IPCompleter
2264 2265 from IPython.core.completerlib import (
2265 2266 cd_completer,
2266 2267 magic_run_completer,
2267 2268 module_completer,
2268 2269 reset_completer,
2269 2270 )
2270 2271
2271 2272 self.Completer = IPCompleter(shell=self,
2272 2273 namespace=self.user_ns,
2273 2274 global_namespace=self.user_global_ns,
2274 2275 parent=self,
2275 2276 )
2276 2277 self.configurables.append(self.Completer)
2277 2278
2278 2279 # Add custom completers to the basic ones built into IPCompleter
2279 2280 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
2280 2281 self.strdispatchers['complete_command'] = sdisp
2281 2282 self.Completer.custom_completers = sdisp
2282 2283
2283 2284 self.set_hook('complete_command', module_completer, str_key = 'import')
2284 2285 self.set_hook('complete_command', module_completer, str_key = 'from')
2285 2286 self.set_hook('complete_command', module_completer, str_key = '%aimport')
2286 2287 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
2287 2288 self.set_hook('complete_command', cd_completer, str_key = '%cd')
2288 2289 self.set_hook('complete_command', reset_completer, str_key = '%reset')
2289 2290
2290 2291 @skip_doctest
2291 2292 def complete(self, text, line=None, cursor_pos=None):
2292 2293 """Return the completed text and a list of completions.
2293 2294
2294 2295 Parameters
2295 2296 ----------
2296 2297 text : string
2297 2298 A string of text to be completed on. It can be given as empty and
2298 2299 instead a line/position pair are given. In this case, the
2299 2300 completer itself will split the line like readline does.
2300 2301 line : string, optional
2301 2302 The complete line that text is part of.
2302 2303 cursor_pos : int, optional
2303 2304 The position of the cursor on the input line.
2304 2305
2305 2306 Returns
2306 2307 -------
2307 2308 text : string
2308 2309 The actual text that was completed.
2309 2310 matches : list
2310 2311 A sorted list with all possible completions.
2311 2312
2312 2313 Notes
2313 2314 -----
2314 2315 The optional arguments allow the completion to take more context into
2315 2316 account, and are part of the low-level completion API.
2316 2317
2317 2318 This is a wrapper around the completion mechanism, similar to what
2318 2319 readline does at the command line when the TAB key is hit. By
2319 2320 exposing it as a method, it can be used by other non-readline
2320 2321 environments (such as GUIs) for text completion.
2321 2322
2322 2323 Examples
2323 2324 --------
2324 2325 In [1]: x = 'hello'
2325 2326
2326 2327 In [2]: _ip.complete('x.l')
2327 2328 Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
2328 2329 """
2329 2330
2330 2331 # Inject names into __builtin__ so we can complete on the added names.
2331 2332 with self.builtin_trap:
2332 2333 return self.Completer.complete(text, line, cursor_pos)
2333 2334
2334 2335 def set_custom_completer(self, completer, pos=0) -> None:
2335 2336 """Adds a new custom completer function.
2336 2337
2337 2338 The position argument (defaults to 0) is the index in the completers
2338 2339 list where you want the completer to be inserted.
2339 2340
2340 2341 `completer` should have the following signature::
2341 2342
2342 2343 def completion(self: Completer, text: string) -> List[str]:
2343 2344 raise NotImplementedError
2344 2345
2345 2346 It will be bound to the current Completer instance and pass some text
2346 2347 and return a list with current completions to suggest to the user.
2347 2348 """
2348 2349
2349 2350 newcomp = types.MethodType(completer, self.Completer)
2350 2351 self.Completer.custom_matchers.insert(pos,newcomp)
2351 2352
2352 2353 def set_completer_frame(self, frame=None):
2353 2354 """Set the frame of the completer."""
2354 2355 if frame:
2355 2356 self.Completer.namespace = frame.f_locals
2356 2357 self.Completer.global_namespace = frame.f_globals
2357 2358 else:
2358 2359 self.Completer.namespace = self.user_ns
2359 2360 self.Completer.global_namespace = self.user_global_ns
2360 2361
2361 2362 #-------------------------------------------------------------------------
2362 2363 # Things related to magics
2363 2364 #-------------------------------------------------------------------------
2364 2365
2365 2366 def init_magics(self):
2366 2367 from IPython.core import magics as m
2367 2368 self.magics_manager = magic.MagicsManager(shell=self,
2368 2369 parent=self,
2369 2370 user_magics=m.UserMagics(self))
2370 2371 self.configurables.append(self.magics_manager)
2371 2372
2372 2373 # Expose as public API from the magics manager
2373 2374 self.register_magics = self.magics_manager.register
2374 2375
2375 2376 self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics,
2376 2377 m.ConfigMagics, m.DisplayMagics, m.ExecutionMagics,
2377 2378 m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics,
2378 2379 m.NamespaceMagics, m.OSMagics, m.PackagingMagics,
2379 2380 m.PylabMagics, m.ScriptMagics,
2380 2381 )
2381 2382 self.register_magics(m.AsyncMagics)
2382 2383
2383 2384 # Register Magic Aliases
2384 2385 mman = self.magics_manager
2385 2386 # FIXME: magic aliases should be defined by the Magics classes
2386 2387 # or in MagicsManager, not here
2387 2388 mman.register_alias('ed', 'edit')
2388 2389 mman.register_alias('hist', 'history')
2389 2390 mman.register_alias('rep', 'recall')
2390 2391 mman.register_alias('SVG', 'svg', 'cell')
2391 2392 mman.register_alias('HTML', 'html', 'cell')
2392 2393 mman.register_alias('file', 'writefile', 'cell')
2393 2394
2394 2395 # FIXME: Move the color initialization to the DisplayHook, which
2395 2396 # should be split into a prompt manager and displayhook. We probably
2396 2397 # even need a centralize colors management object.
2397 2398 self.run_line_magic('colors', self.colors)
2398 2399
2399 2400 # Defined here so that it's included in the documentation
2400 2401 @functools.wraps(magic.MagicsManager.register_function)
2401 2402 def register_magic_function(self, func, magic_kind='line', magic_name=None):
2402 2403 self.magics_manager.register_function(
2403 2404 func, magic_kind=magic_kind, magic_name=magic_name
2404 2405 )
2405 2406
2406 2407 def _find_with_lazy_load(self, /, type_, magic_name: str):
2407 2408 """
2408 2409 Try to find a magic potentially lazy-loading it.
2409 2410
2410 2411 Parameters
2411 2412 ----------
2412 2413
2413 2414 type_: "line"|"cell"
2414 2415 the type of magics we are trying to find/lazy load.
2415 2416 magic_name: str
2416 2417 The name of the magic we are trying to find/lazy load
2417 2418
2418 2419
2419 2420 Note that this may have any side effects
2420 2421 """
2421 2422 finder = {"line": self.find_line_magic, "cell": self.find_cell_magic}[type_]
2422 2423 fn = finder(magic_name)
2423 2424 if fn is not None:
2424 2425 return fn
2425 2426 lazy = self.magics_manager.lazy_magics.get(magic_name)
2426 2427 if lazy is None:
2427 2428 return None
2428 2429
2429 2430 self.run_line_magic("load_ext", lazy)
2430 2431 res = finder(magic_name)
2431 2432 return res
2432 2433
2433 2434 def run_line_magic(self, magic_name: str, line: str, _stack_depth=1):
2434 2435 """Execute the given line magic.
2435 2436
2436 2437 Parameters
2437 2438 ----------
2438 2439 magic_name : str
2439 2440 Name of the desired magic function, without '%' prefix.
2440 2441 line : str
2441 2442 The rest of the input line as a single string.
2442 2443 _stack_depth : int
2443 2444 If run_line_magic() is called from magic() then _stack_depth=2.
2444 2445 This is added to ensure backward compatibility for use of 'get_ipython().magic()'
2445 2446 """
2446 2447 fn = self._find_with_lazy_load("line", magic_name)
2447 2448 if fn is None:
2448 2449 lazy = self.magics_manager.lazy_magics.get(magic_name)
2449 2450 if lazy:
2450 2451 self.run_line_magic("load_ext", lazy)
2451 2452 fn = self.find_line_magic(magic_name)
2452 2453 if fn is None:
2453 2454 cm = self.find_cell_magic(magic_name)
2454 2455 etpl = "Line magic function `%%%s` not found%s."
2455 2456 extra = '' if cm is None else (' (But cell magic `%%%%%s` exists, '
2456 2457 'did you mean that instead?)' % magic_name )
2457 2458 raise UsageError(etpl % (magic_name, extra))
2458 2459 else:
2459 2460 # Note: this is the distance in the stack to the user's frame.
2460 2461 # This will need to be updated if the internal calling logic gets
2461 2462 # refactored, or else we'll be expanding the wrong variables.
2462 2463
2463 2464 # Determine stack_depth depending on where run_line_magic() has been called
2464 2465 stack_depth = _stack_depth
2465 2466 if getattr(fn, magic.MAGIC_NO_VAR_EXPAND_ATTR, False):
2466 2467 # magic has opted out of var_expand
2467 2468 magic_arg_s = line
2468 2469 else:
2469 2470 magic_arg_s = self.var_expand(line, stack_depth)
2470 2471 # Put magic args in a list so we can call with f(*a) syntax
2471 2472 args = [magic_arg_s]
2472 2473 kwargs = {}
2473 2474 # Grab local namespace if we need it:
2474 2475 if getattr(fn, "needs_local_scope", False):
2475 2476 kwargs['local_ns'] = self.get_local_scope(stack_depth)
2476 2477 with self.builtin_trap:
2477 2478 result = fn(*args, **kwargs)
2478 2479
2479 2480 # The code below prevents the output from being displayed
2480 2481 # when using magics with decorator @output_can_be_silenced
2481 2482 # when the last Python token in the expression is a ';'.
2482 2483 if getattr(fn, magic.MAGIC_OUTPUT_CAN_BE_SILENCED, False):
2483 2484 if DisplayHook.semicolon_at_end_of_expression(magic_arg_s):
2484 2485 return None
2485 2486
2486 2487 return result
2487 2488
2488 2489 def get_local_scope(self, stack_depth):
2489 2490 """Get local scope at given stack depth.
2490 2491
2491 2492 Parameters
2492 2493 ----------
2493 2494 stack_depth : int
2494 2495 Depth relative to calling frame
2495 2496 """
2496 2497 return sys._getframe(stack_depth + 1).f_locals
2497 2498
2498 2499 def run_cell_magic(self, magic_name, line, cell):
2499 2500 """Execute the given cell magic.
2500 2501
2501 2502 Parameters
2502 2503 ----------
2503 2504 magic_name : str
2504 2505 Name of the desired magic function, without '%' prefix.
2505 2506 line : str
2506 2507 The rest of the first input line as a single string.
2507 2508 cell : str
2508 2509 The body of the cell as a (possibly multiline) string.
2509 2510 """
2510 2511 fn = self._find_with_lazy_load("cell", magic_name)
2511 2512 if fn is None:
2512 2513 lm = self.find_line_magic(magic_name)
2513 2514 etpl = "Cell magic `%%{0}` not found{1}."
2514 2515 extra = '' if lm is None else (' (But line magic `%{0}` exists, '
2515 2516 'did you mean that instead?)'.format(magic_name))
2516 2517 raise UsageError(etpl.format(magic_name, extra))
2517 2518 elif cell == '':
2518 2519 message = '%%{0} is a cell magic, but the cell body is empty.'.format(magic_name)
2519 2520 if self.find_line_magic(magic_name) is not None:
2520 2521 message += ' Did you mean the line magic %{0} (single %)?'.format(magic_name)
2521 2522 raise UsageError(message)
2522 2523 else:
2523 2524 # Note: this is the distance in the stack to the user's frame.
2524 2525 # This will need to be updated if the internal calling logic gets
2525 2526 # refactored, or else we'll be expanding the wrong variables.
2526 2527 stack_depth = 2
2527 2528 if getattr(fn, magic.MAGIC_NO_VAR_EXPAND_ATTR, False):
2528 2529 # magic has opted out of var_expand
2529 2530 magic_arg_s = line
2530 2531 else:
2531 2532 magic_arg_s = self.var_expand(line, stack_depth)
2532 2533 kwargs = {}
2533 2534 if getattr(fn, "needs_local_scope", False):
2534 2535 kwargs['local_ns'] = self.user_ns
2535 2536
2536 2537 with self.builtin_trap:
2537 2538 args = (magic_arg_s, cell)
2538 2539 result = fn(*args, **kwargs)
2539 2540
2540 2541 # The code below prevents the output from being displayed
2541 2542 # when using magics with decorator @output_can_be_silenced
2542 2543 # when the last Python token in the expression is a ';'.
2543 2544 if getattr(fn, magic.MAGIC_OUTPUT_CAN_BE_SILENCED, False):
2544 2545 if DisplayHook.semicolon_at_end_of_expression(cell):
2545 2546 return None
2546 2547
2547 2548 return result
2548 2549
2549 2550 def find_line_magic(self, magic_name):
2550 2551 """Find and return a line magic by name.
2551 2552
2552 2553 Returns None if the magic isn't found."""
2553 2554 return self.magics_manager.magics['line'].get(magic_name)
2554 2555
2555 2556 def find_cell_magic(self, magic_name):
2556 2557 """Find and return a cell magic by name.
2557 2558
2558 2559 Returns None if the magic isn't found."""
2559 2560 return self.magics_manager.magics['cell'].get(magic_name)
2560 2561
2561 2562 def find_magic(self, magic_name, magic_kind='line'):
2562 2563 """Find and return a magic of the given type by name.
2563 2564
2564 2565 Returns None if the magic isn't found."""
2565 2566 return self.magics_manager.magics[magic_kind].get(magic_name)
2566 2567
2567 2568 def magic(self, arg_s):
2568 2569 """
2569 2570 DEPRECATED
2570 2571
2571 2572 Deprecated since IPython 0.13 (warning added in
2572 2573 8.1), use run_line_magic(magic_name, parameter_s).
2573 2574
2574 2575 Call a magic function by name.
2575 2576
2576 2577 Input: a string containing the name of the magic function to call and
2577 2578 any additional arguments to be passed to the magic.
2578 2579
2579 2580 magic('name -opt foo bar') is equivalent to typing at the ipython
2580 2581 prompt:
2581 2582
2582 2583 In[1]: %name -opt foo bar
2583 2584
2584 2585 To call a magic without arguments, simply use magic('name').
2585 2586
2586 2587 This provides a proper Python function to call IPython's magics in any
2587 2588 valid Python code you can type at the interpreter, including loops and
2588 2589 compound statements.
2589 2590 """
2590 2591 warnings.warn(
2591 2592 "`magic(...)` is deprecated since IPython 0.13 (warning added in "
2592 2593 "8.1), use run_line_magic(magic_name, parameter_s).",
2593 2594 DeprecationWarning,
2594 2595 stacklevel=2,
2595 2596 )
2596 2597 # TODO: should we issue a loud deprecation warning here?
2597 2598 magic_name, _, magic_arg_s = arg_s.partition(' ')
2598 2599 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
2599 2600 return self.run_line_magic(magic_name, magic_arg_s, _stack_depth=2)
2600 2601
2601 2602 #-------------------------------------------------------------------------
2602 2603 # Things related to macros
2603 2604 #-------------------------------------------------------------------------
2604 2605
2605 2606 def define_macro(self, name, themacro):
2606 2607 """Define a new macro
2607 2608
2608 2609 Parameters
2609 2610 ----------
2610 2611 name : str
2611 2612 The name of the macro.
2612 2613 themacro : str or Macro
2613 2614 The action to do upon invoking the macro. If a string, a new
2614 2615 Macro object is created by passing the string to it.
2615 2616 """
2616 2617
2617 2618 from IPython.core import macro
2618 2619
2619 2620 if isinstance(themacro, str):
2620 2621 themacro = macro.Macro(themacro)
2621 2622 if not isinstance(themacro, macro.Macro):
2622 2623 raise ValueError('A macro must be a string or a Macro instance.')
2623 2624 self.user_ns[name] = themacro
2624 2625
2625 2626 #-------------------------------------------------------------------------
2626 2627 # Things related to the running of system commands
2627 2628 #-------------------------------------------------------------------------
2628 2629
2629 2630 def system_piped(self, cmd):
2630 2631 """Call the given cmd in a subprocess, piping stdout/err
2631 2632
2632 2633 Parameters
2633 2634 ----------
2634 2635 cmd : str
2635 2636 Command to execute (can not end in '&', as background processes are
2636 2637 not supported. Should not be a command that expects input
2637 2638 other than simple text.
2638 2639 """
2639 2640 if cmd.rstrip().endswith('&'):
2640 2641 # this is *far* from a rigorous test
2641 2642 # We do not support backgrounding processes because we either use
2642 2643 # pexpect or pipes to read from. Users can always just call
2643 2644 # os.system() or use ip.system=ip.system_raw
2644 2645 # if they really want a background process.
2645 2646 raise OSError("Background processes not supported.")
2646 2647
2647 2648 # we explicitly do NOT return the subprocess status code, because
2648 2649 # a non-None value would trigger :func:`sys.displayhook` calls.
2649 2650 # Instead, we store the exit_code in user_ns.
2650 2651 self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1))
2651 2652
2652 2653 def system_raw(self, cmd):
2653 2654 """Call the given cmd in a subprocess using os.system on Windows or
2654 2655 subprocess.call using the system shell on other platforms.
2655 2656
2656 2657 Parameters
2657 2658 ----------
2658 2659 cmd : str
2659 2660 Command to execute.
2660 2661 """
2661 2662 cmd = self.var_expand(cmd, depth=1)
2662 2663 # warn if there is an IPython magic alternative.
2663 2664 if cmd == "":
2664 2665 main_cmd = ""
2665 2666 else:
2666 2667 main_cmd = cmd.split()[0]
2667 2668 has_magic_alternatives = ("pip", "conda", "cd")
2668 2669
2669 2670 if main_cmd in has_magic_alternatives:
2670 2671 warnings.warn(
2671 2672 (
2672 2673 "You executed the system command !{0} which may not work "
2673 2674 "as expected. Try the IPython magic %{0} instead."
2674 2675 ).format(main_cmd)
2675 2676 )
2676 2677
2677 2678 # protect os.system from UNC paths on Windows, which it can't handle:
2678 2679 if sys.platform == 'win32':
2679 2680 from IPython.utils._process_win32 import AvoidUNCPath
2680 2681 with AvoidUNCPath() as path:
2681 2682 if path is not None:
2682 2683 cmd = '"pushd %s &&"%s' % (path, cmd)
2683 2684 try:
2684 2685 ec = os.system(cmd)
2685 2686 except KeyboardInterrupt:
2686 2687 print('\n' + self.get_exception_only(), file=sys.stderr)
2687 2688 ec = -2
2688 2689 else:
2689 2690 # For posix the result of the subprocess.call() below is an exit
2690 2691 # code, which by convention is zero for success, positive for
2691 2692 # program failure. Exit codes above 128 are reserved for signals,
2692 2693 # and the formula for converting a signal to an exit code is usually
2693 2694 # signal_number+128. To more easily differentiate between exit
2694 2695 # codes and signals, ipython uses negative numbers. For instance
2695 2696 # since control-c is signal 2 but exit code 130, ipython's
2696 2697 # _exit_code variable will read -2. Note that some shells like
2697 2698 # csh and fish don't follow sh/bash conventions for exit codes.
2698 2699 executable = os.environ.get('SHELL', None)
2699 2700 try:
2700 2701 # Use env shell instead of default /bin/sh
2701 2702 ec = subprocess.call(cmd, shell=True, executable=executable)
2702 2703 except KeyboardInterrupt:
2703 2704 # intercept control-C; a long traceback is not useful here
2704 2705 print('\n' + self.get_exception_only(), file=sys.stderr)
2705 2706 ec = 130
2706 2707 if ec > 128:
2707 2708 ec = -(ec - 128)
2708 2709
2709 2710 # We explicitly do NOT return the subprocess status code, because
2710 2711 # a non-None value would trigger :func:`sys.displayhook` calls.
2711 2712 # Instead, we store the exit_code in user_ns. Note the semantics
2712 2713 # of _exit_code: for control-c, _exit_code == -signal.SIGNIT,
2713 2714 # but raising SystemExit(_exit_code) will give status 254!
2714 2715 self.user_ns['_exit_code'] = ec
2715 2716
2716 2717 # use piped system by default, because it is better behaved
2717 2718 system = system_piped
2718 2719
2719 2720 def getoutput(self, cmd, split=True, depth=0):
2720 2721 """Get output (possibly including stderr) from a subprocess.
2721 2722
2722 2723 Parameters
2723 2724 ----------
2724 2725 cmd : str
2725 2726 Command to execute (can not end in '&', as background processes are
2726 2727 not supported.
2727 2728 split : bool, optional
2728 2729 If True, split the output into an IPython SList. Otherwise, an
2729 2730 IPython LSString is returned. These are objects similar to normal
2730 2731 lists and strings, with a few convenience attributes for easier
2731 2732 manipulation of line-based output. You can use '?' on them for
2732 2733 details.
2733 2734 depth : int, optional
2734 2735 How many frames above the caller are the local variables which should
2735 2736 be expanded in the command string? The default (0) assumes that the
2736 2737 expansion variables are in the stack frame calling this function.
2737 2738 """
2738 2739 if cmd.rstrip().endswith('&'):
2739 2740 # this is *far* from a rigorous test
2740 2741 raise OSError("Background processes not supported.")
2741 2742 out = getoutput(self.var_expand(cmd, depth=depth+1))
2742 2743 if split:
2743 2744 out = SList(out.splitlines())
2744 2745 else:
2745 2746 out = LSString(out)
2746 2747 return out
2747 2748
2748 2749 #-------------------------------------------------------------------------
2749 2750 # Things related to aliases
2750 2751 #-------------------------------------------------------------------------
2751 2752
2752 2753 def init_alias(self):
2753 2754 self.alias_manager = AliasManager(shell=self, parent=self)
2754 2755 self.configurables.append(self.alias_manager)
2755 2756
2756 2757 #-------------------------------------------------------------------------
2757 2758 # Things related to extensions
2758 2759 #-------------------------------------------------------------------------
2759 2760
2760 2761 def init_extension_manager(self):
2761 2762 self.extension_manager = ExtensionManager(shell=self, parent=self)
2762 2763 self.configurables.append(self.extension_manager)
2763 2764
2764 2765 #-------------------------------------------------------------------------
2765 2766 # Things related to payloads
2766 2767 #-------------------------------------------------------------------------
2767 2768
2768 2769 def init_payload(self):
2769 2770 self.payload_manager = PayloadManager(parent=self)
2770 2771 self.configurables.append(self.payload_manager)
2771 2772
2772 2773 #-------------------------------------------------------------------------
2773 2774 # Things related to the prefilter
2774 2775 #-------------------------------------------------------------------------
2775 2776
2776 2777 def init_prefilter(self):
2777 2778 self.prefilter_manager = PrefilterManager(shell=self, parent=self)
2778 2779 self.configurables.append(self.prefilter_manager)
2779 2780 # Ultimately this will be refactored in the new interpreter code, but
2780 2781 # for now, we should expose the main prefilter method (there's legacy
2781 2782 # code out there that may rely on this).
2782 2783 self.prefilter = self.prefilter_manager.prefilter_lines
2783 2784
2784 2785 def auto_rewrite_input(self, cmd):
2785 2786 """Print to the screen the rewritten form of the user's command.
2786 2787
2787 2788 This shows visual feedback by rewriting input lines that cause
2788 2789 automatic calling to kick in, like::
2789 2790
2790 2791 /f x
2791 2792
2792 2793 into::
2793 2794
2794 2795 ------> f(x)
2795 2796
2796 2797 after the user's input prompt. This helps the user understand that the
2797 2798 input line was transformed automatically by IPython.
2798 2799 """
2799 2800 if not self.show_rewritten_input:
2800 2801 return
2801 2802
2802 2803 # This is overridden in TerminalInteractiveShell to use fancy prompts
2803 2804 print("------> " + cmd)
2804 2805
2805 2806 #-------------------------------------------------------------------------
2806 2807 # Things related to extracting values/expressions from kernel and user_ns
2807 2808 #-------------------------------------------------------------------------
2808 2809
2809 2810 def _user_obj_error(self):
2810 2811 """return simple exception dict
2811 2812
2812 2813 for use in user_expressions
2813 2814 """
2814 2815
2815 2816 etype, evalue, tb = self._get_exc_info()
2816 2817 stb = self.InteractiveTB.get_exception_only(etype, evalue)
2817 2818
2818 2819 exc_info = {
2819 2820 "status": "error",
2820 2821 "traceback": stb,
2821 2822 "ename": etype.__name__,
2822 2823 "evalue": py3compat.safe_unicode(evalue),
2823 2824 }
2824 2825
2825 2826 return exc_info
2826 2827
2827 2828 def _format_user_obj(self, obj):
2828 2829 """format a user object to display dict
2829 2830
2830 2831 for use in user_expressions
2831 2832 """
2832 2833
2833 2834 data, md = self.display_formatter.format(obj)
2834 2835 value = {
2835 2836 'status' : 'ok',
2836 2837 'data' : data,
2837 2838 'metadata' : md,
2838 2839 }
2839 2840 return value
2840 2841
2841 2842 def user_expressions(self, expressions):
2842 2843 """Evaluate a dict of expressions in the user's namespace.
2843 2844
2844 2845 Parameters
2845 2846 ----------
2846 2847 expressions : dict
2847 2848 A dict with string keys and string values. The expression values
2848 2849 should be valid Python expressions, each of which will be evaluated
2849 2850 in the user namespace.
2850 2851
2851 2852 Returns
2852 2853 -------
2853 2854 A dict, keyed like the input expressions dict, with the rich mime-typed
2854 2855 display_data of each value.
2855 2856 """
2856 2857 out = {}
2857 2858 user_ns = self.user_ns
2858 2859 global_ns = self.user_global_ns
2859 2860
2860 2861 for key, expr in expressions.items():
2861 2862 try:
2862 2863 value = self._format_user_obj(eval(expr, global_ns, user_ns))
2863 except Exception:
2864 except:
2864 2865 value = self._user_obj_error()
2865 2866 out[key] = value
2866 2867 return out
2867 2868
2868 2869 #-------------------------------------------------------------------------
2869 2870 # Things related to the running of code
2870 2871 #-------------------------------------------------------------------------
2871 2872
2872 2873 def ex(self, cmd):
2873 2874 """Execute a normal python statement in user namespace."""
2874 2875 with self.builtin_trap:
2875 2876 exec(cmd, self.user_global_ns, self.user_ns)
2876 2877
2877 2878 def ev(self, expr):
2878 2879 """Evaluate python expression expr in user namespace.
2879 2880
2880 2881 Returns the result of evaluation
2881 2882 """
2882 2883 with self.builtin_trap:
2883 2884 return eval(expr, self.user_global_ns, self.user_ns)
2884 2885
2885 2886 def safe_execfile(self, fname, *where, exit_ignore=False, raise_exceptions=False, shell_futures=False):
2886 2887 """A safe version of the builtin execfile().
2887 2888
2888 2889 This version will never throw an exception, but instead print
2889 2890 helpful error messages to the screen. This only works on pure
2890 2891 Python files with the .py extension.
2891 2892
2892 2893 Parameters
2893 2894 ----------
2894 2895 fname : string
2895 2896 The name of the file to be executed.
2896 2897 *where : tuple
2897 2898 One or two namespaces, passed to execfile() as (globals,locals).
2898 2899 If only one is given, it is passed as both.
2899 2900 exit_ignore : bool (False)
2900 2901 If True, then silence SystemExit for non-zero status (it is always
2901 2902 silenced for zero status, as it is so common).
2902 2903 raise_exceptions : bool (False)
2903 2904 If True raise exceptions everywhere. Meant for testing.
2904 2905 shell_futures : bool (False)
2905 2906 If True, the code will share future statements with the interactive
2906 2907 shell. It will both be affected by previous __future__ imports, and
2907 2908 any __future__ imports in the code will affect the shell. If False,
2908 2909 __future__ imports are not shared in either direction.
2909 2910
2910 2911 """
2911 2912 fname = Path(fname).expanduser().resolve()
2912 2913
2913 2914 # Make sure we can open the file
2914 2915 try:
2915 2916 with fname.open("rb"):
2916 2917 pass
2917 except Exception:
2918 except:
2918 2919 warn('Could not open file <%s> for safe execution.' % fname)
2919 2920 return
2920 2921
2921 2922 # Find things also in current directory. This is needed to mimic the
2922 2923 # behavior of running a script from the system command line, where
2923 2924 # Python inserts the script's directory into sys.path
2924 2925 dname = str(fname.parent)
2925 2926
2926 2927 with prepended_to_syspath(dname), self.builtin_trap:
2927 2928 try:
2928 2929 glob, loc = (where + (None, ))[:2]
2929 2930 py3compat.execfile(
2930 2931 fname, glob, loc,
2931 2932 self.compile if shell_futures else None)
2932 2933 except SystemExit as status:
2933 2934 # If the call was made with 0 or None exit status (sys.exit(0)
2934 2935 # or sys.exit() ), don't bother showing a traceback, as both of
2935 2936 # these are considered normal by the OS:
2936 2937 # > python -c'import sys;sys.exit(0)'; echo $?
2937 2938 # 0
2938 2939 # > python -c'import sys;sys.exit()'; echo $?
2939 2940 # 0
2940 2941 # For other exit status, we show the exception unless
2941 2942 # explicitly silenced, but only in short form.
2942 2943 if status.code:
2943 2944 if raise_exceptions:
2944 2945 raise
2945 2946 if not exit_ignore:
2946 2947 self.showtraceback(exception_only=True)
2947 except Exception:
2948 except:
2948 2949 if raise_exceptions:
2949 2950 raise
2950 2951 # tb offset is 2 because we wrap execfile
2951 2952 self.showtraceback(tb_offset=2)
2952 2953
2953 2954 def safe_execfile_ipy(self, fname, shell_futures=False, raise_exceptions=False):
2954 2955 """Like safe_execfile, but for .ipy or .ipynb files with IPython syntax.
2955 2956
2956 2957 Parameters
2957 2958 ----------
2958 2959 fname : str
2959 2960 The name of the file to execute. The filename must have a
2960 2961 .ipy or .ipynb extension.
2961 2962 shell_futures : bool (False)
2962 2963 If True, the code will share future statements with the interactive
2963 2964 shell. It will both be affected by previous __future__ imports, and
2964 2965 any __future__ imports in the code will affect the shell. If False,
2965 2966 __future__ imports are not shared in either direction.
2966 2967 raise_exceptions : bool (False)
2967 2968 If True raise exceptions everywhere. Meant for testing.
2968 2969 """
2969 2970 fname = Path(fname).expanduser().resolve()
2970 2971
2971 2972 # Make sure we can open the file
2972 2973 try:
2973 2974 with fname.open("rb"):
2974 2975 pass
2975 except Exception:
2976 except:
2976 2977 warn('Could not open file <%s> for safe execution.' % fname)
2977 2978 return
2978 2979
2979 2980 # Find things also in current directory. This is needed to mimic the
2980 2981 # behavior of running a script from the system command line, where
2981 2982 # Python inserts the script's directory into sys.path
2982 2983 dname = str(fname.parent)
2983 2984
2984 2985 def get_cells():
2985 2986 """generator for sequence of code blocks to run"""
2986 2987 if fname.suffix == ".ipynb":
2987 2988 from nbformat import read
2988 2989 nb = read(fname, as_version=4)
2989 2990 if not nb.cells:
2990 2991 return
2991 2992 for cell in nb.cells:
2992 2993 if cell.cell_type == 'code':
2993 2994 yield cell.source
2994 2995 else:
2995 2996 yield fname.read_text(encoding="utf-8")
2996 2997
2997 2998 with prepended_to_syspath(dname):
2998 2999 try:
2999 3000 for cell in get_cells():
3000 3001 result = self.run_cell(cell, silent=True, shell_futures=shell_futures)
3001 3002 if raise_exceptions:
3002 3003 result.raise_error()
3003 3004 elif not result.success:
3004 3005 break
3005 except Exception:
3006 except:
3006 3007 if raise_exceptions:
3007 3008 raise
3008 3009 self.showtraceback()
3009 3010 warn('Unknown failure executing file: <%s>' % fname)
3010 3011
3011 3012 def safe_run_module(self, mod_name, where):
3012 3013 """A safe version of runpy.run_module().
3013 3014
3014 3015 This version will never throw an exception, but instead print
3015 3016 helpful error messages to the screen.
3016 3017
3017 3018 `SystemExit` exceptions with status code 0 or None are ignored.
3018 3019
3019 3020 Parameters
3020 3021 ----------
3021 3022 mod_name : string
3022 3023 The name of the module to be executed.
3023 3024 where : dict
3024 3025 The globals namespace.
3025 3026 """
3026 3027 try:
3027 3028 try:
3028 3029 where.update(
3029 3030 runpy.run_module(str(mod_name), run_name="__main__",
3030 3031 alter_sys=True)
3031 3032 )
3032 3033 except SystemExit as status:
3033 3034 if status.code:
3034 3035 raise
3035 except Exception:
3036 except:
3036 3037 self.showtraceback()
3037 3038 warn('Unknown failure executing module: <%s>' % mod_name)
3038 3039
3039 3040 def run_cell(
3040 3041 self,
3041 3042 raw_cell,
3042 3043 store_history=False,
3043 3044 silent=False,
3044 3045 shell_futures=True,
3045 3046 cell_id=None,
3046 3047 ):
3047 3048 """Run a complete IPython cell.
3048 3049
3049 3050 Parameters
3050 3051 ----------
3051 3052 raw_cell : str
3052 3053 The code (including IPython code such as %magic functions) to run.
3053 3054 store_history : bool
3054 3055 If True, the raw and translated cell will be stored in IPython's
3055 3056 history. For user code calling back into IPython's machinery, this
3056 3057 should be set to False.
3057 3058 silent : bool
3058 3059 If True, avoid side-effects, such as implicit displayhooks and
3059 3060 and logging. silent=True forces store_history=False.
3060 3061 shell_futures : bool
3061 3062 If True, the code will share future statements with the interactive
3062 3063 shell. It will both be affected by previous __future__ imports, and
3063 3064 any __future__ imports in the code will affect the shell. If False,
3064 3065 __future__ imports are not shared in either direction.
3065 3066
3066 3067 Returns
3067 3068 -------
3068 3069 result : :class:`ExecutionResult`
3069 3070 """
3070 3071 result = None
3071 3072 try:
3072 3073 result = self._run_cell(
3073 3074 raw_cell, store_history, silent, shell_futures, cell_id
3074 3075 )
3075 3076 finally:
3076 3077 self.events.trigger('post_execute')
3077 3078 if not silent:
3078 3079 self.events.trigger('post_run_cell', result)
3079 3080 return result
3080 3081
3081 3082 def _run_cell(
3082 3083 self,
3083 3084 raw_cell: str,
3084 3085 store_history: bool,
3085 3086 silent: bool,
3086 3087 shell_futures: bool,
3087 3088 cell_id: str,
3088 3089 ) -> ExecutionResult:
3089 3090 """Internal method to run a complete IPython cell."""
3090 3091
3091 3092 # we need to avoid calling self.transform_cell multiple time on the same thing
3092 3093 # so we need to store some results:
3093 3094 preprocessing_exc_tuple = None
3094 3095 try:
3095 3096 transformed_cell = self.transform_cell(raw_cell)
3096 3097 except Exception:
3097 3098 transformed_cell = raw_cell
3098 3099 preprocessing_exc_tuple = sys.exc_info()
3099 3100
3100 3101 assert transformed_cell is not None
3101 3102 coro = self.run_cell_async(
3102 3103 raw_cell,
3103 3104 store_history=store_history,
3104 3105 silent=silent,
3105 3106 shell_futures=shell_futures,
3106 3107 transformed_cell=transformed_cell,
3107 3108 preprocessing_exc_tuple=preprocessing_exc_tuple,
3108 3109 cell_id=cell_id,
3109 3110 )
3110 3111
3111 3112 # run_cell_async is async, but may not actually need an eventloop.
3112 3113 # when this is the case, we want to run it using the pseudo_sync_runner
3113 3114 # so that code can invoke eventloops (for example via the %run , and
3114 3115 # `%paste` magic.
3115 3116 if self.trio_runner:
3116 3117 runner = self.trio_runner
3117 3118 elif self.should_run_async(
3118 3119 raw_cell,
3119 3120 transformed_cell=transformed_cell,
3120 3121 preprocessing_exc_tuple=preprocessing_exc_tuple,
3121 3122 ):
3122 3123 runner = self.loop_runner
3123 3124 else:
3124 3125 runner = _pseudo_sync_runner
3125 3126
3126 3127 try:
3127 3128 result = runner(coro)
3128 3129 except BaseException as e:
3129 3130 info = ExecutionInfo(
3130 3131 raw_cell, store_history, silent, shell_futures, cell_id
3131 3132 )
3132 3133 result = ExecutionResult(info)
3133 3134 result.error_in_exec = e
3134 3135 self.showtraceback(running_compiled_code=True)
3135 3136 finally:
3136 3137 return result
3137 3138
3138 3139 def should_run_async(
3139 3140 self, raw_cell: str, *, transformed_cell=None, preprocessing_exc_tuple=None
3140 3141 ) -> bool:
3141 3142 """Return whether a cell should be run asynchronously via a coroutine runner
3142 3143
3143 3144 Parameters
3144 3145 ----------
3145 3146 raw_cell : str
3146 3147 The code to be executed
3147 3148
3148 3149 Returns
3149 3150 -------
3150 3151 result: bool
3151 3152 Whether the code needs to be run with a coroutine runner or not
3152 3153 .. versionadded:: 7.0
3153 3154 """
3154 3155 if not self.autoawait:
3155 3156 return False
3156 3157 if preprocessing_exc_tuple is not None:
3157 3158 return False
3158 3159 assert preprocessing_exc_tuple is None
3159 3160 if transformed_cell is None:
3160 3161 warnings.warn(
3161 3162 "`should_run_async` will not call `transform_cell`"
3162 3163 " automatically in the future. Please pass the result to"
3163 3164 " `transformed_cell` argument and any exception that happen"
3164 3165 " during the"
3165 3166 "transform in `preprocessing_exc_tuple` in"
3166 3167 " IPython 7.17 and above.",
3167 3168 DeprecationWarning,
3168 3169 stacklevel=2,
3169 3170 )
3170 3171 try:
3171 3172 cell = self.transform_cell(raw_cell)
3172 3173 except Exception:
3173 3174 # any exception during transform will be raised
3174 3175 # prior to execution
3175 3176 return False
3176 3177 else:
3177 3178 cell = transformed_cell
3178 3179 return _should_be_async(cell)
3179 3180
3180 3181 async def run_cell_async(
3181 3182 self,
3182 3183 raw_cell: str,
3183 3184 store_history=False,
3184 3185 silent=False,
3185 3186 shell_futures=True,
3186 3187 *,
3187 3188 transformed_cell: Optional[str] = None,
3188 3189 preprocessing_exc_tuple: Optional[AnyType] = None,
3189 3190 cell_id=None,
3190 3191 ) -> ExecutionResult:
3191 3192 """Run a complete IPython cell asynchronously.
3192 3193
3193 3194 Parameters
3194 3195 ----------
3195 3196 raw_cell : str
3196 3197 The code (including IPython code such as %magic functions) to run.
3197 3198 store_history : bool
3198 3199 If True, the raw and translated cell will be stored in IPython's
3199 3200 history. For user code calling back into IPython's machinery, this
3200 3201 should be set to False.
3201 3202 silent : bool
3202 3203 If True, avoid side-effects, such as implicit displayhooks and
3203 3204 and logging. silent=True forces store_history=False.
3204 3205 shell_futures : bool
3205 3206 If True, the code will share future statements with the interactive
3206 3207 shell. It will both be affected by previous __future__ imports, and
3207 3208 any __future__ imports in the code will affect the shell. If False,
3208 3209 __future__ imports are not shared in either direction.
3209 3210 transformed_cell: str
3210 3211 cell that was passed through transformers
3211 3212 preprocessing_exc_tuple:
3212 3213 trace if the transformation failed.
3213 3214
3214 3215 Returns
3215 3216 -------
3216 3217 result : :class:`ExecutionResult`
3217 3218
3218 3219 .. versionadded:: 7.0
3219 3220 """
3220 3221 info = ExecutionInfo(raw_cell, store_history, silent, shell_futures, cell_id)
3221 3222 result = ExecutionResult(info)
3222 3223
3223 3224 if (not raw_cell) or raw_cell.isspace():
3224 3225 self.last_execution_succeeded = True
3225 3226 self.last_execution_result = result
3226 3227 return result
3227 3228
3228 3229 if silent:
3229 3230 store_history = False
3230 3231
3231 3232 if store_history:
3232 3233 result.execution_count = self.execution_count
3233 3234
3234 3235 def error_before_exec(value):
3235 3236 if store_history:
3236 3237 self.execution_count += 1
3237 3238 result.error_before_exec = value
3238 3239 self.last_execution_succeeded = False
3239 3240 self.last_execution_result = result
3240 3241 return result
3241 3242
3242 3243 self.events.trigger('pre_execute')
3243 3244 if not silent:
3244 3245 self.events.trigger('pre_run_cell', info)
3245 3246
3246 3247 if transformed_cell is None:
3247 3248 warnings.warn(
3248 3249 "`run_cell_async` will not call `transform_cell`"
3249 3250 " automatically in the future. Please pass the result to"
3250 3251 " `transformed_cell` argument and any exception that happen"
3251 3252 " during the"
3252 3253 "transform in `preprocessing_exc_tuple` in"
3253 3254 " IPython 7.17 and above.",
3254 3255 DeprecationWarning,
3255 3256 stacklevel=2,
3256 3257 )
3257 3258 # If any of our input transformation (input_transformer_manager or
3258 3259 # prefilter_manager) raises an exception, we store it in this variable
3259 3260 # so that we can display the error after logging the input and storing
3260 3261 # it in the history.
3261 3262 try:
3262 3263 cell = self.transform_cell(raw_cell)
3263 3264 except Exception:
3264 3265 preprocessing_exc_tuple = sys.exc_info()
3265 3266 cell = raw_cell # cell has to exist so it can be stored/logged
3266 3267 else:
3267 3268 preprocessing_exc_tuple = None
3268 3269 else:
3269 3270 if preprocessing_exc_tuple is None:
3270 3271 cell = transformed_cell
3271 3272 else:
3272 3273 cell = raw_cell
3273 3274
3274 3275 # Do NOT store paste/cpaste magic history
3275 3276 if "get_ipython().run_line_magic(" in cell and "paste" in cell:
3276 3277 store_history = False
3277 3278
3278 3279 # Store raw and processed history
3279 3280 if store_history:
3280 3281 assert self.history_manager is not None
3281 3282 self.history_manager.store_inputs(self.execution_count, cell, raw_cell)
3282 3283 if not silent:
3283 3284 self.logger.log(cell, raw_cell)
3284 3285
3285 3286 # Display the exception if input processing failed.
3286 3287 if preprocessing_exc_tuple is not None:
3287 3288 self.showtraceback(preprocessing_exc_tuple)
3288 3289 if store_history:
3289 3290 self.execution_count += 1
3290 3291 return error_before_exec(preprocessing_exc_tuple[1])
3291 3292
3292 3293 # Our own compiler remembers the __future__ environment. If we want to
3293 3294 # run code with a separate __future__ environment, use the default
3294 3295 # compiler
3295 3296 compiler = self.compile if shell_futures else self.compiler_class()
3296 3297
3297 3298 with self.builtin_trap:
3298 3299 cell_name = compiler.cache(cell, self.execution_count, raw_code=raw_cell)
3299 3300
3300 3301 with self.display_trap:
3301 3302 # Compile to bytecode
3302 3303 try:
3303 3304 code_ast = compiler.ast_parse(cell, filename=cell_name)
3304 3305 except self.custom_exceptions as e:
3305 3306 etype, value, tb = sys.exc_info()
3306 3307 self.CustomTB(etype, value, tb)
3307 3308 return error_before_exec(e)
3308 3309 except IndentationError as e:
3309 3310 self.showindentationerror()
3310 3311 return error_before_exec(e)
3311 3312 except (OverflowError, SyntaxError, ValueError, TypeError,
3312 3313 MemoryError) as e:
3313 3314 self.showsyntaxerror()
3314 3315 return error_before_exec(e)
3315 3316
3316 3317 # Apply AST transformations
3317 3318 try:
3318 3319 code_ast = self.transform_ast(code_ast)
3319 3320 except InputRejected as e:
3320 3321 self.showtraceback()
3321 3322 return error_before_exec(e)
3322 3323
3323 3324 # Give the displayhook a reference to our ExecutionResult so it
3324 3325 # can fill in the output value.
3325 3326 self.displayhook.exec_result = result
3326 3327
3327 3328 # Execute the user code
3328 3329 interactivity = "none" if silent else self.ast_node_interactivity
3329 3330
3330 3331
3331 3332 has_raised = await self.run_ast_nodes(code_ast.body, cell_name,
3332 3333 interactivity=interactivity, compiler=compiler, result=result)
3333 3334
3334 3335 self.last_execution_succeeded = not has_raised
3335 3336 self.last_execution_result = result
3336 3337
3337 3338 # Reset this so later displayed values do not modify the
3338 3339 # ExecutionResult
3339 3340 self.displayhook.exec_result = None
3340 3341
3341 3342 if store_history:
3342 3343 assert self.history_manager is not None
3343 3344 # Write output to the database. Does nothing unless
3344 3345 # history output logging is enabled.
3345 3346 self.history_manager.store_output(self.execution_count)
3346 3347 # Each cell is a *single* input, regardless of how many lines it has
3347 3348 self.execution_count += 1
3348 3349
3349 3350 return result
3350 3351
3351 3352 def transform_cell(self, raw_cell):
3352 3353 """Transform an input cell before parsing it.
3353 3354
3354 3355 Static transformations, implemented in IPython.core.inputtransformer2,
3355 3356 deal with things like ``%magic`` and ``!system`` commands.
3356 3357 These run on all input.
3357 3358 Dynamic transformations, for things like unescaped magics and the exit
3358 3359 autocall, depend on the state of the interpreter.
3359 3360 These only apply to single line inputs.
3360 3361
3361 3362 These string-based transformations are followed by AST transformations;
3362 3363 see :meth:`transform_ast`.
3363 3364 """
3364 3365 # Static input transformations
3365 3366 cell = self.input_transformer_manager.transform_cell(raw_cell)
3366 3367
3367 3368 if len(cell.splitlines()) == 1:
3368 3369 # Dynamic transformations - only applied for single line commands
3369 3370 with self.builtin_trap:
3370 3371 # use prefilter_lines to handle trailing newlines
3371 3372 # restore trailing newline for ast.parse
3372 3373 cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
3373 3374
3374 3375 lines = cell.splitlines(keepends=True)
3375 3376 for transform in self.input_transformers_post:
3376 3377 lines = transform(lines)
3377 3378 cell = ''.join(lines)
3378 3379
3379 3380 return cell
3380 3381
3381 3382 def transform_ast(self, node):
3382 3383 """Apply the AST transformations from self.ast_transformers
3383 3384
3384 3385 Parameters
3385 3386 ----------
3386 3387 node : ast.Node
3387 3388 The root node to be transformed. Typically called with the ast.Module
3388 3389 produced by parsing user input.
3389 3390
3390 3391 Returns
3391 3392 -------
3392 3393 An ast.Node corresponding to the node it was called with. Note that it
3393 3394 may also modify the passed object, so don't rely on references to the
3394 3395 original AST.
3395 3396 """
3396 3397 for transformer in self.ast_transformers:
3397 3398 try:
3398 3399 node = transformer.visit(node)
3399 3400 except InputRejected:
3400 3401 # User-supplied AST transformers can reject an input by raising
3401 3402 # an InputRejected. Short-circuit in this case so that we
3402 3403 # don't unregister the transform.
3403 3404 raise
3404 3405 except Exception as e:
3405 3406 warn(
3406 3407 "AST transformer %r threw an error. It will be unregistered. %s"
3407 3408 % (transformer, e)
3408 3409 )
3409 3410 self.ast_transformers.remove(transformer)
3410 3411
3411 3412 if self.ast_transformers:
3412 3413 ast.fix_missing_locations(node)
3413 3414 return node
3414 3415
3415 3416 async def run_ast_nodes(
3416 3417 self,
3417 3418 nodelist: ListType[stmt],
3418 3419 cell_name: str,
3419 3420 interactivity="last_expr",
3420 3421 compiler=compile,
3421 3422 result=None,
3422 3423 ):
3423 3424 """Run a sequence of AST nodes. The execution mode depends on the
3424 3425 interactivity parameter.
3425 3426
3426 3427 Parameters
3427 3428 ----------
3428 3429 nodelist : list
3429 3430 A sequence of AST nodes to run.
3430 3431 cell_name : str
3431 3432 Will be passed to the compiler as the filename of the cell. Typically
3432 3433 the value returned by ip.compile.cache(cell).
3433 3434 interactivity : str
3434 3435 'all', 'last', 'last_expr' , 'last_expr_or_assign' or 'none',
3435 3436 specifying which nodes should be run interactively (displaying output
3436 3437 from expressions). 'last_expr' will run the last node interactively
3437 3438 only if it is an expression (i.e. expressions in loops or other blocks
3438 3439 are not displayed) 'last_expr_or_assign' will run the last expression
3439 3440 or the last assignment. Other values for this parameter will raise a
3440 3441 ValueError.
3441 3442
3442 3443 compiler : callable
3443 3444 A function with the same interface as the built-in compile(), to turn
3444 3445 the AST nodes into code objects. Default is the built-in compile().
3445 3446 result : ExecutionResult, optional
3446 3447 An object to store exceptions that occur during execution.
3447 3448
3448 3449 Returns
3449 3450 -------
3450 3451 True if an exception occurred while running code, False if it finished
3451 3452 running.
3452 3453 """
3453 3454 if not nodelist:
3454 3455 return
3455 3456
3456 3457
3457 3458 if interactivity == 'last_expr_or_assign':
3458 3459 if isinstance(nodelist[-1], _assign_nodes):
3459 3460 asg = nodelist[-1]
3460 3461 if isinstance(asg, ast.Assign) and len(asg.targets) == 1:
3461 3462 target = asg.targets[0]
3462 3463 elif isinstance(asg, _single_targets_nodes):
3463 3464 target = asg.target
3464 3465 else:
3465 3466 target = None
3466 3467 if isinstance(target, ast.Name):
3467 3468 nnode = ast.Expr(ast.Name(target.id, ast.Load()))
3468 3469 ast.fix_missing_locations(nnode)
3469 3470 nodelist.append(nnode)
3470 3471 interactivity = 'last_expr'
3471 3472
3472 3473 _async = False
3473 3474 if interactivity == 'last_expr':
3474 3475 if isinstance(nodelist[-1], ast.Expr):
3475 3476 interactivity = "last"
3476 3477 else:
3477 3478 interactivity = "none"
3478 3479
3479 3480 if interactivity == 'none':
3480 3481 to_run_exec, to_run_interactive = nodelist, []
3481 3482 elif interactivity == 'last':
3482 3483 to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:]
3483 3484 elif interactivity == 'all':
3484 3485 to_run_exec, to_run_interactive = [], nodelist
3485 3486 else:
3486 3487 raise ValueError("Interactivity was %r" % interactivity)
3487 3488
3488 3489 try:
3489 3490
3490 3491 def compare(code):
3491 3492 is_async = inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE
3492 3493 return is_async
3493 3494
3494 3495 # refactor that to just change the mod constructor.
3495 3496 to_run = []
3496 3497 for node in to_run_exec:
3497 3498 to_run.append((node, "exec"))
3498 3499
3499 3500 for node in to_run_interactive:
3500 3501 to_run.append((node, "single"))
3501 3502
3502 3503 for node, mode in to_run:
3503 3504 if mode == "exec":
3504 3505 mod = Module([node], [])
3505 3506 elif mode == "single":
3506 3507 mod = ast.Interactive([node]) # type: ignore
3507 3508 with compiler.extra_flags(
3508 3509 getattr(ast, "PyCF_ALLOW_TOP_LEVEL_AWAIT", 0x0)
3509 3510 if self.autoawait
3510 3511 else 0x0
3511 3512 ):
3512 3513 code = compiler(mod, cell_name, mode)
3513 3514 asy = compare(code)
3514 3515 if await self.run_code(code, result, async_=asy):
3515 3516 return True
3516 3517
3517 3518 # Flush softspace
3518 3519 if softspace(sys.stdout, 0):
3519 3520 print()
3520 3521
3521 except Exception:
3522 except:
3522 3523 # It's possible to have exceptions raised here, typically by
3523 3524 # compilation of odd code (such as a naked 'return' outside a
3524 3525 # function) that did parse but isn't valid. Typically the exception
3525 3526 # is a SyntaxError, but it's safest just to catch anything and show
3526 3527 # the user a traceback.
3527 3528
3528 3529 # We do only one try/except outside the loop to minimize the impact
3529 3530 # on runtime, and also because if any node in the node list is
3530 3531 # broken, we should stop execution completely.
3531 3532 if result:
3532 3533 result.error_before_exec = sys.exc_info()[1]
3533 3534 self.showtraceback()
3534 3535 return True
3535 3536
3536 3537 return False
3537 3538
3538 3539 async def run_code(self, code_obj, result=None, *, async_=False):
3539 3540 """Execute a code object.
3540 3541
3541 3542 When an exception occurs, self.showtraceback() is called to display a
3542 3543 traceback.
3543 3544
3544 3545 Parameters
3545 3546 ----------
3546 3547 code_obj : code object
3547 3548 A compiled code object, to be executed
3548 3549 result : ExecutionResult, optional
3549 3550 An object to store exceptions that occur during execution.
3550 3551 async_ : Bool (Experimental)
3551 3552 Attempt to run top-level asynchronous code in a default loop.
3552 3553
3553 3554 Returns
3554 3555 -------
3555 3556 False : successful execution.
3556 3557 True : an error occurred.
3557 3558 """
3558 3559 # special value to say that anything above is IPython and should be
3559 3560 # hidden.
3560 3561 __tracebackhide__ = "__ipython_bottom__"
3561 3562 # Set our own excepthook in case the user code tries to call it
3562 3563 # directly, so that the IPython crash handler doesn't get triggered
3563 3564 old_excepthook, sys.excepthook = sys.excepthook, self.excepthook
3564 3565
3565 3566 # we save the original sys.excepthook in the instance, in case config
3566 3567 # code (such as magics) needs access to it.
3567 3568 self.sys_excepthook = old_excepthook
3568 3569 outflag = True # happens in more places, so it's easier as default
3569 3570 try:
3570 3571 try:
3571 3572 if async_:
3572 3573 await eval(code_obj, self.user_global_ns, self.user_ns)
3573 3574 else:
3574 3575 exec(code_obj, self.user_global_ns, self.user_ns)
3575 3576 finally:
3576 3577 # Reset our crash handler in place
3577 3578 sys.excepthook = old_excepthook
3578 3579 except SystemExit as e:
3579 3580 if result is not None:
3580 3581 result.error_in_exec = e
3581 3582 self.showtraceback(exception_only=True)
3582 3583 warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
3583 3584 except bdb.BdbQuit:
3584 3585 etype, value, tb = sys.exc_info()
3585 3586 if result is not None:
3586 3587 result.error_in_exec = value
3587 3588 # the BdbQuit stops here
3588 3589 except self.custom_exceptions:
3589 3590 etype, value, tb = sys.exc_info()
3590 3591 if result is not None:
3591 3592 result.error_in_exec = value
3592 3593 self.CustomTB(etype, value, tb)
3593 except Exception:
3594 except:
3594 3595 if result is not None:
3595 3596 result.error_in_exec = sys.exc_info()[1]
3596 3597 self.showtraceback(running_compiled_code=True)
3597 3598 else:
3598 3599 outflag = False
3599 3600 return outflag
3600 3601
3601 3602 # For backwards compatibility
3602 3603 runcode = run_code
3603 3604
3604 3605 def check_complete(self, code: str) -> Tuple[str, str]:
3605 3606 """Return whether a block of code is ready to execute, or should be continued
3606 3607
3607 3608 Parameters
3608 3609 ----------
3609 3610 code : string
3610 3611 Python input code, which can be multiline.
3611 3612
3612 3613 Returns
3613 3614 -------
3614 3615 status : str
3615 3616 One of 'complete', 'incomplete', or 'invalid' if source is not a
3616 3617 prefix of valid code.
3617 3618 indent : str
3618 3619 When status is 'incomplete', this is some whitespace to insert on
3619 3620 the next line of the prompt.
3620 3621 """
3621 3622 status, nspaces = self.input_transformer_manager.check_complete(code)
3622 3623 return status, ' ' * (nspaces or 0)
3623 3624
3624 3625 #-------------------------------------------------------------------------
3625 3626 # Things related to GUI support and pylab
3626 3627 #-------------------------------------------------------------------------
3627 3628
3628 3629 active_eventloop: Optional[str] = None
3629 3630
3630 3631 def enable_gui(self, gui=None):
3631 3632 raise NotImplementedError('Implement enable_gui in a subclass')
3632 3633
3633 3634 def enable_matplotlib(self, gui=None):
3634 3635 """Enable interactive matplotlib and inline figure support.
3635 3636
3636 3637 This takes the following steps:
3637 3638
3638 3639 1. select the appropriate eventloop and matplotlib backend
3639 3640 2. set up matplotlib for interactive use with that backend
3640 3641 3. configure formatters for inline figure display
3641 3642 4. enable the selected gui eventloop
3642 3643
3643 3644 Parameters
3644 3645 ----------
3645 3646 gui : optional, string
3646 3647 If given, dictates the choice of matplotlib GUI backend to use
3647 3648 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3648 3649 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3649 3650 matplotlib (as dictated by the matplotlib build-time options plus the
3650 3651 user's matplotlibrc configuration file). Note that not all backends
3651 3652 make sense in all contexts, for example a terminal ipython can't
3652 3653 display figures inline.
3653 3654 """
3654 3655 from .pylabtools import _matplotlib_manages_backends
3655 3656
3656 3657 if not _matplotlib_manages_backends() and gui in (None, "auto"):
3657 3658 # Early import of backend_inline required for its side effect of
3658 3659 # calling _enable_matplotlib_integration()
3659 import matplotlib_inline.backend_inline # noqa : F401
3660 import matplotlib_inline.backend_inline
3660 3661
3661 3662 from IPython.core import pylabtools as pt
3662 3663 gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select)
3663 3664
3664 if gui is not None:
3665 if gui != None:
3665 3666 # If we have our first gui selection, store it
3666 3667 if self.pylab_gui_select is None:
3667 3668 self.pylab_gui_select = gui
3668 3669 # Otherwise if they are different
3669 3670 elif gui != self.pylab_gui_select:
3670 3671 print('Warning: Cannot change to a different GUI toolkit: %s.'
3671 3672 ' Using %s instead.' % (gui, self.pylab_gui_select))
3672 3673 gui, backend = pt.find_gui_and_backend(self.pylab_gui_select)
3673 3674
3674 3675 pt.activate_matplotlib(backend)
3675 3676
3676 3677 from matplotlib_inline.backend_inline import configure_inline_support
3677 3678
3678 3679 configure_inline_support(self, backend)
3679 3680
3680 3681 # Now we must activate the gui pylab wants to use, and fix %run to take
3681 3682 # plot updates into account
3682 3683 self.enable_gui(gui)
3683 3684 self.magics_manager.registry['ExecutionMagics'].default_runner = \
3684 3685 pt.mpl_runner(self.safe_execfile)
3685 3686
3686 3687 return gui, backend
3687 3688
3688 3689 def enable_pylab(self, gui=None, import_all=True, welcome_message=False):
3689 3690 """Activate pylab support at runtime.
3690 3691
3691 3692 This turns on support for matplotlib, preloads into the interactive
3692 3693 namespace all of numpy and pylab, and configures IPython to correctly
3693 3694 interact with the GUI event loop. The GUI backend to be used can be
3694 3695 optionally selected with the optional ``gui`` argument.
3695 3696
3696 3697 This method only adds preloading the namespace to InteractiveShell.enable_matplotlib.
3697 3698
3698 3699 Parameters
3699 3700 ----------
3700 3701 gui : optional, string
3701 3702 If given, dictates the choice of matplotlib GUI backend to use
3702 3703 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3703 3704 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3704 3705 matplotlib (as dictated by the matplotlib build-time options plus the
3705 3706 user's matplotlibrc configuration file). Note that not all backends
3706 3707 make sense in all contexts, for example a terminal ipython can't
3707 3708 display figures inline.
3708 3709 import_all : optional, bool, default: True
3709 3710 Whether to do `from numpy import *` and `from pylab import *`
3710 3711 in addition to module imports.
3711 3712 welcome_message : deprecated
3712 3713 This argument is ignored, no welcome message will be displayed.
3713 3714 """
3714 3715 from IPython.core.pylabtools import import_pylab
3715 3716
3716 3717 gui, backend = self.enable_matplotlib(gui)
3717 3718
3718 3719 # We want to prevent the loading of pylab to pollute the user's
3719 3720 # namespace as shown by the %who* magics, so we execute the activation
3720 3721 # code in an empty namespace, and we update *both* user_ns and
3721 3722 # user_ns_hidden with this information.
3722 3723 ns = {}
3723 3724 import_pylab(ns, import_all)
3724 3725 # warn about clobbered names
3725 3726 ignored = {"__builtins__"}
3726 3727 both = set(ns).intersection(self.user_ns).difference(ignored)
3727 3728 clobbered = [ name for name in both if self.user_ns[name] is not ns[name] ]
3728 3729 self.user_ns.update(ns)
3729 3730 self.user_ns_hidden.update(ns)
3730 3731 return gui, backend, clobbered
3731 3732
3732 3733 #-------------------------------------------------------------------------
3733 3734 # Utilities
3734 3735 #-------------------------------------------------------------------------
3735 3736
3736 3737 def var_expand(self, cmd, depth=0, formatter=DollarFormatter()):
3737 3738 """Expand python variables in a string.
3738 3739
3739 3740 The depth argument indicates how many frames above the caller should
3740 3741 be walked to look for the local namespace where to expand variables.
3741 3742
3742 3743 The global namespace for expansion is always the user's interactive
3743 3744 namespace.
3744 3745 """
3745 3746 ns = self.user_ns.copy()
3746 3747 try:
3747 3748 frame = sys._getframe(depth+1)
3748 3749 except ValueError:
3749 3750 # This is thrown if there aren't that many frames on the stack,
3750 3751 # e.g. if a script called run_line_magic() directly.
3751 3752 pass
3752 3753 else:
3753 3754 ns.update(frame.f_locals)
3754 3755
3755 3756 try:
3756 3757 # We have to use .vformat() here, because 'self' is a valid and common
3757 3758 # name, and expanding **ns for .format() would make it collide with
3758 3759 # the 'self' argument of the method.
3759 3760 cmd = formatter.vformat(cmd, args=[], kwargs=ns)
3760 3761 except Exception:
3761 3762 # if formatter couldn't format, just let it go untransformed
3762 3763 pass
3763 3764 return cmd
3764 3765
3765 3766 def mktempfile(self, data=None, prefix='ipython_edit_'):
3766 3767 """Make a new tempfile and return its filename.
3767 3768
3768 3769 This makes a call to tempfile.mkstemp (created in a tempfile.mkdtemp),
3769 3770 but it registers the created filename internally so ipython cleans it up
3770 3771 at exit time.
3771 3772
3772 3773 Optional inputs:
3773 3774
3774 3775 - data(None): if data is given, it gets written out to the temp file
3775 3776 immediately, and the file is closed again."""
3776 3777
3777 3778 dir_path = Path(tempfile.mkdtemp(prefix=prefix))
3778 3779 self.tempdirs.append(dir_path)
3779 3780
3780 3781 handle, filename = tempfile.mkstemp(".py", prefix, dir=str(dir_path))
3781 3782 os.close(handle) # On Windows, there can only be one open handle on a file
3782 3783
3783 3784 file_path = Path(filename)
3784 3785 self.tempfiles.append(file_path)
3785 3786
3786 3787 if data:
3787 3788 file_path.write_text(data, encoding="utf-8")
3788 3789 return filename
3789 3790
3790 3791 def ask_yes_no(self, prompt, default=None, interrupt=None):
3791 3792 if self.quiet:
3792 3793 return True
3793 3794 return ask_yes_no(prompt,default,interrupt)
3794 3795
3795 3796 def show_usage(self):
3796 3797 """Show a usage message"""
3797 3798 page.page(IPython.core.usage.interactive_usage)
3798 3799
3799 3800 def extract_input_lines(self, range_str, raw=False):
3800 3801 """Return as a string a set of input history slices.
3801 3802
3802 3803 Parameters
3803 3804 ----------
3804 3805 range_str : str
3805 3806 The set of slices is given as a string, like "~5/6-~4/2 4:8 9",
3806 3807 since this function is for use by magic functions which get their
3807 3808 arguments as strings. The number before the / is the session
3808 3809 number: ~n goes n back from the current session.
3809 3810
3810 3811 If empty string is given, returns history of current session
3811 3812 without the last input.
3812 3813
3813 3814 raw : bool, optional
3814 3815 By default, the processed input is used. If this is true, the raw
3815 3816 input history is used instead.
3816 3817
3817 3818 Notes
3818 3819 -----
3819 3820 Slices can be described with two notations:
3820 3821
3821 3822 * ``N:M`` -> standard python form, means including items N...(M-1).
3822 3823 * ``N-M`` -> include items N..M (closed endpoint).
3823 3824 """
3824 3825 lines = self.history_manager.get_range_by_str(range_str, raw=raw)
3825 3826 text = "\n".join(x for _, _, x in lines)
3826 3827
3827 3828 # Skip the last line, as it's probably the magic that called this
3828 3829 if not range_str:
3829 3830 if "\n" not in text:
3830 3831 text = ""
3831 3832 else:
3832 3833 text = text[: text.rfind("\n")]
3833 3834
3834 3835 return text
3835 3836
3836 3837 def find_user_code(self, target, raw=True, py_only=False, skip_encoding_cookie=True, search_ns=False):
3837 3838 """Get a code string from history, file, url, or a string or macro.
3838 3839
3839 3840 This is mainly used by magic functions.
3840 3841
3841 3842 Parameters
3842 3843 ----------
3843 3844 target : str
3844 3845 A string specifying code to retrieve. This will be tried respectively
3845 3846 as: ranges of input history (see %history for syntax), url,
3846 3847 corresponding .py file, filename, or an expression evaluating to a
3847 3848 string or Macro in the user namespace.
3848 3849
3849 3850 If empty string is given, returns complete history of current
3850 3851 session, without the last line.
3851 3852
3852 3853 raw : bool
3853 3854 If true (default), retrieve raw history. Has no effect on the other
3854 3855 retrieval mechanisms.
3855 3856
3856 3857 py_only : bool (default False)
3857 3858 Only try to fetch python code, do not try alternative methods to decode file
3858 3859 if unicode fails.
3859 3860
3860 3861 Returns
3861 3862 -------
3862 3863 A string of code.
3863 3864 ValueError is raised if nothing is found, and TypeError if it evaluates
3864 3865 to an object of another type. In each case, .args[0] is a printable
3865 3866 message.
3866 3867 """
3867 3868 code = self.extract_input_lines(target, raw=raw) # Grab history
3868 3869 if code:
3869 3870 return code
3870 3871 try:
3871 3872 if target.startswith(('http://', 'https://')):
3872 3873 return openpy.read_py_url(target, skip_encoding_cookie=skip_encoding_cookie)
3873 3874 except UnicodeDecodeError as e:
3874 3875 if not py_only :
3875 3876 # Deferred import
3876 3877 from urllib.request import urlopen
3877 3878 response = urlopen(target)
3878 3879 return response.read().decode('latin1')
3879 3880 raise ValueError(("'%s' seem to be unreadable.") % target) from e
3880 3881
3881 3882 potential_target = [target]
3882 3883 try :
3883 3884 potential_target.insert(0,get_py_filename(target))
3884 3885 except IOError:
3885 3886 pass
3886 3887
3887 3888 for tgt in potential_target :
3888 3889 if os.path.isfile(tgt): # Read file
3889 3890 try :
3890 3891 return openpy.read_py_file(tgt, skip_encoding_cookie=skip_encoding_cookie)
3891 3892 except UnicodeDecodeError as e:
3892 3893 if not py_only :
3893 3894 with io_open(tgt,'r', encoding='latin1') as f :
3894 3895 return f.read()
3895 3896 raise ValueError(("'%s' seem to be unreadable.") % target) from e
3896 3897 elif os.path.isdir(os.path.expanduser(tgt)):
3897 3898 raise ValueError("'%s' is a directory, not a regular file." % target)
3898 3899
3899 3900 if search_ns:
3900 3901 # Inspect namespace to load object source
3901 3902 object_info = self.object_inspect(target, detail_level=1)
3902 3903 if object_info['found'] and object_info['source']:
3903 3904 return object_info['source']
3904 3905
3905 3906 try: # User namespace
3906 3907 codeobj = eval(target, self.user_ns)
3907 3908 except Exception as e:
3908 3909 raise ValueError(("'%s' was not found in history, as a file, url, "
3909 3910 "nor in the user namespace.") % target) from e
3910 3911
3911 3912 if isinstance(codeobj, str):
3912 3913 return codeobj
3913 3914 elif isinstance(codeobj, Macro):
3914 3915 return codeobj.value
3915 3916
3916 3917 raise TypeError("%s is neither a string nor a macro." % target,
3917 3918 codeobj)
3918 3919
3919 3920 def _atexit_once(self):
3920 3921 """
3921 3922 At exist operation that need to be called at most once.
3922 3923 Second call to this function per instance will do nothing.
3923 3924 """
3924 3925
3925 3926 if not getattr(self, "_atexit_once_called", False):
3926 3927 self._atexit_once_called = True
3927 3928 # Clear all user namespaces to release all references cleanly.
3928 3929 self.reset(new_session=False)
3929 3930 # Close the history session (this stores the end time and line count)
3930 3931 # this must be *before* the tempfile cleanup, in case of temporary
3931 3932 # history db
3932 3933 self.history_manager.end_session()
3933 3934 self.history_manager = None
3934 3935
3935 3936 #-------------------------------------------------------------------------
3936 3937 # Things related to IPython exiting
3937 3938 #-------------------------------------------------------------------------
3938 3939 def atexit_operations(self):
3939 3940 """This will be executed at the time of exit.
3940 3941
3941 3942 Cleanup operations and saving of persistent data that is done
3942 3943 unconditionally by IPython should be performed here.
3943 3944
3944 3945 For things that may depend on startup flags or platform specifics (such
3945 3946 as having readline or not), register a separate atexit function in the
3946 3947 code that has the appropriate information, rather than trying to
3947 3948 clutter
3948 3949 """
3949 3950 self._atexit_once()
3950 3951
3951 3952 # Cleanup all tempfiles and folders left around
3952 3953 for tfile in self.tempfiles:
3953 3954 try:
3954 3955 tfile.unlink()
3955 3956 self.tempfiles.remove(tfile)
3956 3957 except FileNotFoundError:
3957 3958 pass
3958 3959 del self.tempfiles
3959 3960 for tdir in self.tempdirs:
3960 3961 try:
3961 3962 shutil.rmtree(tdir)
3962 3963 self.tempdirs.remove(tdir)
3963 3964 except FileNotFoundError:
3964 3965 pass
3965 3966 del self.tempdirs
3966 3967
3967 3968 # Restore user's cursor
3968 3969 if hasattr(self, "editing_mode") and self.editing_mode == "vi":
3969 3970 sys.stdout.write("\x1b[0 q")
3970 3971 sys.stdout.flush()
3971 3972
3972 3973 def cleanup(self):
3973 3974 self.restore_sys_module_state()
3974 3975
3975 3976
3976 3977 # Overridden in terminal subclass to change prompts
3977 3978 def switch_doctest_mode(self, mode):
3978 3979 pass
3979 3980
3980 3981
3981 3982 class InteractiveShellABC(metaclass=abc.ABCMeta):
3982 3983 """An abstract base class for InteractiveShell."""
3983 3984
3984 3985 InteractiveShellABC.register(InteractiveShell)
@@ -1,45 +1,42
1 1 """Implementation of all the magic functions built into IPython.
2 2 """
3
4 # -----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
5 4 # Copyright (c) 2012 The IPython Development Team.
6 5 #
7 6 # Distributed under the terms of the Modified BSD License.
8 7 #
9 8 # The full license is in the file COPYING.txt, distributed with this software.
10 # -----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
11 10
12 # -----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
13 12 # Imports
14 # -----------------------------------------------------------------------------
15
16 from ..magic import Magics as Magics, magics_class as magics_class
17 from .auto import AutoMagics as AutoMagics
18 from .basic import BasicMagics as BasicMagics, AsyncMagics as AsyncMagics
19 from .code import CodeMagics as CodeMagics, MacroToEdit as MacroToEdit
20 from .config import ConfigMagics as ConfigMagics
21 from .display import DisplayMagics as DisplayMagics
22 from .execution import ExecutionMagics as ExecutionMagics
23 from .extension import ExtensionMagics as ExtensionMagics
24 from .history import HistoryMagics as HistoryMagics
25 from .logging import LoggingMagics as LoggingMagics
26 from .namespace import NamespaceMagics as NamespaceMagics
27 from .osm import OSMagics as OSMagics
28 from .packaging import PackagingMagics as PackagingMagics
29 from .pylab import PylabMagics as PylabMagics
30 from .script import ScriptMagics as ScriptMagics
31
32
33 # -----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
15 from ..magic import Magics, magics_class
16 from .auto import AutoMagics
17 from .basic import BasicMagics, AsyncMagics
18 from .code import CodeMagics, MacroToEdit
19 from .config import ConfigMagics
20 from .display import DisplayMagics
21 from .execution import ExecutionMagics
22 from .extension import ExtensionMagics
23 from .history import HistoryMagics
24 from .logging import LoggingMagics
25 from .namespace import NamespaceMagics
26 from .osm import OSMagics
27 from .packaging import PackagingMagics
28 from .pylab import PylabMagics
29 from .script import ScriptMagics
30
31 #-----------------------------------------------------------------------------
34 32 # Magic implementation classes
35 # -----------------------------------------------------------------------------
36
33 #-----------------------------------------------------------------------------
37 34
38 35 @magics_class
39 36 class UserMagics(Magics):
40 37 """Placeholder for user-defined magics to be added at runtime.
41 38
42 39 All magics are eventually merged into a single namespace at runtime, but we
43 40 use this class to isolate the magics defined dynamically by the user into
44 41 their own class.
45 42 """
@@ -1,144 +1,144
1 1 """Implementation of magic functions that control various automatic behaviors.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (c) 2012 The IPython Development Team.
5 5 #
6 6 # Distributed under the terms of the Modified BSD License.
7 7 #
8 8 # The full license is in the file COPYING.txt, distributed with this software.
9 9 #-----------------------------------------------------------------------------
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14
15 15 # Our own packages
16 16 from IPython.core.magic import Bunch, Magics, magics_class, line_magic
17 17 from IPython.testing.skipdoctest import skip_doctest
18 18 from logging import error
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Magic implementation classes
22 22 #-----------------------------------------------------------------------------
23 23
24 24 @magics_class
25 25 class AutoMagics(Magics):
26 26 """Magics that control various autoX behaviors."""
27 27
28 28 def __init__(self, shell):
29 29 super(AutoMagics, self).__init__(shell)
30 30 # namespace for holding state we may need
31 31 self._magic_state = Bunch()
32 32
33 33 @line_magic
34 34 def automagic(self, parameter_s=''):
35 35 """Make magic functions callable without having to type the initial %.
36 36
37 37 Without arguments toggles on/off (when off, you must call it as
38 38 %automagic, of course). With arguments it sets the value, and you can
39 39 use any of (case insensitive):
40 40
41 41 - on, 1, True: to activate
42 42
43 43 - off, 0, False: to deactivate.
44 44
45 45 Note that magic functions have lowest priority, so if there's a
46 46 variable whose name collides with that of a magic fn, automagic won't
47 47 work for that function (you get the variable instead). However, if you
48 48 delete the variable (del var), the previously shadowed magic function
49 49 becomes visible to automagic again."""
50 50
51 51 arg = parameter_s.lower()
52 52 mman = self.shell.magics_manager
53 53 if arg in ('on', '1', 'true'):
54 54 val = True
55 55 elif arg in ('off', '0', 'false'):
56 56 val = False
57 57 else:
58 58 val = not mman.auto_magic
59 59 mman.auto_magic = val
60 60 print('\n' + self.shell.magics_manager.auto_status())
61 61
62 62 @skip_doctest
63 63 @line_magic
64 64 def autocall(self, parameter_s=''):
65 65 """Make functions callable without having to type parentheses.
66 66
67 67 Usage:
68 68
69 69 %autocall [mode]
70 70
71 71 The mode can be one of: 0->Off, 1->Smart, 2->Full. If not given, the
72 72 value is toggled on and off (remembering the previous state).
73 73
74 74 In more detail, these values mean:
75 75
76 76 0 -> fully disabled
77 77
78 78 1 -> active, but do not apply if there are no arguments on the line.
79 79
80 80 In this mode, you get::
81 81
82 82 In [1]: callable
83 83 Out[1]: <built-in function callable>
84 84
85 85 In [2]: callable 'hello'
86 86 ------> callable('hello')
87 87 Out[2]: False
88 88
89 89 2 -> Active always. Even if no arguments are present, the callable
90 90 object is called::
91 91
92 92 In [2]: float
93 93 ------> float()
94 94 Out[2]: 0.0
95 95
96 96 Note that even with autocall off, you can still use '/' at the start of
97 97 a line to treat the first argument on the command line as a function
98 98 and add parentheses to it::
99 99
100 100 In [8]: /str 43
101 101 ------> str(43)
102 102 Out[8]: '43'
103 103
104 104 # all-random (note for auto-testing)
105 105 """
106 106
107 107 valid_modes = {
108 108 0: "Off",
109 109 1: "Smart",
110 110 2: "Full",
111 111 }
112 112
113 113 def errorMessage() -> str:
114 114 error = "Valid modes: "
115 115 for k, v in valid_modes.items():
116 116 error += str(k) + "->" + v + ", "
117 117 error = error[:-2] # remove tailing `, ` after last element
118 118 return error
119 119
120 120 if parameter_s:
121 if parameter_s not in map(str, valid_modes.keys()):
121 if not parameter_s in map(str, valid_modes.keys()):
122 122 error(errorMessage())
123 123 return
124 124 arg = int(parameter_s)
125 125 else:
126 126 arg = 'toggle'
127 127
128 if arg not in (*list(valid_modes.keys()), "toggle"):
128 if not arg in (*list(valid_modes.keys()), "toggle"):
129 129 error(errorMessage())
130 130 return
131 131
132 132 if arg in (valid_modes.keys()):
133 133 self.shell.autocall = arg
134 134 else: # toggle
135 135 if self.shell.autocall:
136 136 self._magic_state.autocall_save = self.shell.autocall
137 137 self.shell.autocall = 0
138 138 else:
139 139 try:
140 140 self.shell.autocall = self._magic_state.autocall_save
141 141 except AttributeError:
142 142 self.shell.autocall = self._magic_state.autocall_save = 1
143 143
144 144 print("Automatic calling is:", list(valid_modes.values())[self.shell.autocall])
@@ -1,1616 +1,1624
1 1 # -*- coding: utf-8 -*-
2 2 """Implementation of execution-related magic functions."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7
8 8 import ast
9 9 import bdb
10 10 import builtins as builtin_mod
11 import copy
11 12 import cProfile as profile
12 13 import gc
13 14 import itertools
14 15 import math
15 16 import os
16 17 import pstats
17 18 import re
18 19 import shlex
19 20 import sys
20 21 import time
21 22 import timeit
22 23 from typing import Dict, Any
23 24 from ast import (
25 Assign,
26 Call,
27 Expr,
28 Load,
24 29 Module,
30 Name,
31 NodeTransformer,
32 Store,
33 parse,
34 unparse,
25 35 )
26 36 from io import StringIO
27 37 from logging import error
28 38 from pathlib import Path
29 39 from pdb import Restart
30 from textwrap import indent
40 from textwrap import dedent, indent
31 41 from warnings import warn
32 42
33 from IPython.core import magic_arguments, page
43 from IPython.core import magic_arguments, oinspect, page
34 44 from IPython.core.displayhook import DisplayHook
35 45 from IPython.core.error import UsageError
36 46 from IPython.core.macro import Macro
37 47 from IPython.core.magic import (
38 48 Magics,
39 49 cell_magic,
40 50 line_cell_magic,
41 51 line_magic,
42 52 magics_class,
43 53 needs_local_scope,
44 54 no_var_expand,
45 55 on_off,
46 56 output_can_be_silenced,
47 57 )
48 58 from IPython.testing.skipdoctest import skip_doctest
49 59 from IPython.utils.capture import capture_output
50 60 from IPython.utils.contexts import preserve_keys
51 61 from IPython.utils.ipstruct import Struct
52 62 from IPython.utils.module_paths import find_mod
53 63 from IPython.utils.path import get_py_filename, shellglob
54 64 from IPython.utils.timing import clock, clock2
55 65 from IPython.core.magics.ast_mod import ReplaceCodeTransformer
56 66
57 67 #-----------------------------------------------------------------------------
58 68 # Magic implementation classes
59 69 #-----------------------------------------------------------------------------
60 70
61 71
62 72 class TimeitResult(object):
63 73 """
64 74 Object returned by the timeit magic with info about the run.
65 75
66 76 Contains the following attributes :
67 77
68 78 loops: (int) number of loops done per measurement
69 79 repeat: (int) number of times the measurement has been repeated
70 80 best: (float) best execution time / number
71 81 all_runs: (list of float) execution time of each run (in s)
72 82 compile_time: (float) time of statement compilation (s)
73 83
74 84 """
75 85 def __init__(self, loops, repeat, best, worst, all_runs, compile_time, precision):
76 86 self.loops = loops
77 87 self.repeat = repeat
78 88 self.best = best
79 89 self.worst = worst
80 90 self.all_runs = all_runs
81 91 self.compile_time = compile_time
82 92 self._precision = precision
83 93 self.timings = [ dt / self.loops for dt in all_runs]
84 94
85 95 @property
86 96 def average(self):
87 97 return math.fsum(self.timings) / len(self.timings)
88 98
89 99 @property
90 100 def stdev(self):
91 101 mean = self.average
92 102 return (math.fsum([(x - mean) ** 2 for x in self.timings]) / len(self.timings)) ** 0.5
93 103
94 104 def __str__(self):
95 105 pm = '+-'
96 106 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
97 107 try:
98 108 u'\xb1'.encode(sys.stdout.encoding)
99 109 pm = u'\xb1'
100 110 except:
101 111 pass
102 112 return "{mean} {pm} {std} per loop (mean {pm} std. dev. of {runs} run{run_plural}, {loops:,} loop{loop_plural} each)".format(
103 113 pm=pm,
104 114 runs=self.repeat,
105 115 loops=self.loops,
106 116 loop_plural="" if self.loops == 1 else "s",
107 117 run_plural="" if self.repeat == 1 else "s",
108 118 mean=_format_time(self.average, self._precision),
109 119 std=_format_time(self.stdev, self._precision),
110 120 )
111 121
112 122 def _repr_pretty_(self, p , cycle):
113 123 unic = self.__str__()
114 124 p.text(u'<TimeitResult : '+unic+u'>')
115 125
116 126
117 127 class TimeitTemplateFiller(ast.NodeTransformer):
118 128 """Fill in the AST template for timing execution.
119 129
120 130 This is quite closely tied to the template definition, which is in
121 131 :meth:`ExecutionMagics.timeit`.
122 132 """
123 133 def __init__(self, ast_setup, ast_stmt):
124 134 self.ast_setup = ast_setup
125 135 self.ast_stmt = ast_stmt
126 136
127 137 def visit_FunctionDef(self, node):
128 138 "Fill in the setup statement"
129 139 self.generic_visit(node)
130 140 if node.name == "inner":
131 141 node.body[:1] = self.ast_setup.body
132 142
133 143 return node
134 144
135 145 def visit_For(self, node):
136 146 "Fill in the statement to be timed"
137 147 if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt':
138 148 node.body = self.ast_stmt.body
139 149 return node
140 150
141 151
142 152 class Timer(timeit.Timer):
143 153 """Timer class that explicitly uses self.inner
144 154
145 155 which is an undocumented implementation detail of CPython,
146 156 not shared by PyPy.
147 157 """
148 158 # Timer.timeit copied from CPython 3.4.2
149 159 def timeit(self, number=timeit.default_number):
150 160 """Time 'number' executions of the main statement.
151 161
152 162 To be precise, this executes the setup statement once, and
153 163 then returns the time it takes to execute the main statement
154 164 a number of times, as a float measured in seconds. The
155 165 argument is the number of times through the loop, defaulting
156 166 to one million. The main statement, the setup statement and
157 167 the timer function to be used are passed to the constructor.
158 168 """
159 169 it = itertools.repeat(None, number)
160 170 gcold = gc.isenabled()
161 171 gc.disable()
162 172 try:
163 173 timing = self.inner(it, self.timer)
164 174 finally:
165 175 if gcold:
166 176 gc.enable()
167 177 return timing
168 178
169 179
170 180 @magics_class
171 181 class ExecutionMagics(Magics):
172 182 """Magics related to code execution, debugging, profiling, etc."""
173 183
174 184 _transformers: Dict[str, Any] = {}
175 185
176 186 def __init__(self, shell):
177 187 super(ExecutionMagics, self).__init__(shell)
178 188 # Default execution function used to actually run user code.
179 189 self.default_runner = None
180 190
181 191 @skip_doctest
182 192 @no_var_expand
183 193 @line_cell_magic
184 194 def prun(self, parameter_s='', cell=None):
185 195
186 196 """Run a statement through the python code profiler.
187 197
188 198 **Usage, in line mode:**
189 199
190 200 %prun [options] statement
191 201
192 202 **Usage, in cell mode:**
193 203
194 204 %%prun [options] [statement]
195 205
196 206 code...
197 207
198 208 code...
199 209
200 210 In cell mode, the additional code lines are appended to the (possibly
201 211 empty) statement in the first line. Cell mode allows you to easily
202 212 profile multiline blocks without having to put them in a separate
203 213 function.
204 214
205 215 The given statement (which doesn't require quote marks) is run via the
206 216 python profiler in a manner similar to the profile.run() function.
207 217 Namespaces are internally managed to work correctly; profile.run
208 218 cannot be used in IPython because it makes certain assumptions about
209 219 namespaces which do not hold under IPython.
210 220
211 221 Options:
212 222
213 223 -l <limit>
214 224 you can place restrictions on what or how much of the
215 225 profile gets printed. The limit value can be:
216 226
217 227 * A string: only information for function names containing this string
218 228 is printed.
219 229
220 230 * An integer: only these many lines are printed.
221 231
222 232 * A float (between 0 and 1): this fraction of the report is printed
223 233 (for example, use a limit of 0.4 to see the topmost 40% only).
224 234
225 235 You can combine several limits with repeated use of the option. For
226 236 example, ``-l __init__ -l 5`` will print only the topmost 5 lines of
227 237 information about class constructors.
228 238
229 239 -r
230 240 return the pstats.Stats object generated by the profiling. This
231 241 object has all the information about the profile in it, and you can
232 242 later use it for further analysis or in other functions.
233 243
234 244 -s <key>
235 245 sort profile by given key. You can provide more than one key
236 246 by using the option several times: '-s key1 -s key2 -s key3...'. The
237 247 default sorting key is 'time'.
238 248
239 249 The following is copied verbatim from the profile documentation
240 250 referenced below:
241 251
242 252 When more than one key is provided, additional keys are used as
243 253 secondary criteria when the there is equality in all keys selected
244 254 before them.
245 255
246 256 Abbreviations can be used for any key names, as long as the
247 257 abbreviation is unambiguous. The following are the keys currently
248 258 defined:
249 259
250 260 ============ =====================
251 261 Valid Arg Meaning
252 262 ============ =====================
253 263 "calls" call count
254 264 "cumulative" cumulative time
255 265 "file" file name
256 266 "module" file name
257 267 "pcalls" primitive call count
258 268 "line" line number
259 269 "name" function name
260 270 "nfl" name/file/line
261 271 "stdname" standard name
262 272 "time" internal time
263 273 ============ =====================
264 274
265 275 Note that all sorts on statistics are in descending order (placing
266 276 most time consuming items first), where as name, file, and line number
267 277 searches are in ascending order (i.e., alphabetical). The subtle
268 278 distinction between "nfl" and "stdname" is that the standard name is a
269 279 sort of the name as printed, which means that the embedded line
270 280 numbers get compared in an odd way. For example, lines 3, 20, and 40
271 281 would (if the file names were the same) appear in the string order
272 282 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
273 283 line numbers. In fact, sort_stats("nfl") is the same as
274 284 sort_stats("name", "file", "line").
275 285
276 286 -T <filename>
277 287 save profile results as shown on screen to a text
278 288 file. The profile is still shown on screen.
279 289
280 290 -D <filename>
281 291 save (via dump_stats) profile statistics to given
282 292 filename. This data is in a format understood by the pstats module, and
283 293 is generated by a call to the dump_stats() method of profile
284 294 objects. The profile is still shown on screen.
285 295
286 296 -q
287 297 suppress output to the pager. Best used with -T and/or -D above.
288 298
289 299 If you want to run complete programs under the profiler's control, use
290 300 ``%run -p [prof_opts] filename.py [args to program]`` where prof_opts
291 301 contains profiler specific options as described here.
292 302
293 303 You can read the complete documentation for the profile module with::
294 304
295 305 In [1]: import profile; profile.help()
296 306
297 307 .. versionchanged:: 7.3
298 308 User variables are no longer expanded,
299 309 the magic line is always left unmodified.
300 310
301 311 """
302 312 opts, arg_str = self.parse_options(parameter_s, 'D:l:rs:T:q',
303 313 list_all=True, posix=False)
304 314 if cell is not None:
305 315 arg_str += '\n' + cell
306 316 arg_str = self.shell.transform_cell(arg_str)
307 317 return self._run_with_profiler(arg_str, opts, self.shell.user_ns)
308 318
309 319 def _run_with_profiler(self, code, opts, namespace):
310 320 """
311 321 Run `code` with profiler. Used by ``%prun`` and ``%run -p``.
312 322
313 323 Parameters
314 324 ----------
315 325 code : str
316 326 Code to be executed.
317 327 opts : Struct
318 328 Options parsed by `self.parse_options`.
319 329 namespace : dict
320 330 A dictionary for Python namespace (e.g., `self.shell.user_ns`).
321 331
322 332 """
323 333
324 334 # Fill default values for unspecified options:
325 335 opts.merge(Struct(D=[''], l=[], s=['time'], T=['']))
326 336
327 337 prof = profile.Profile()
328 338 try:
329 339 prof = prof.runctx(code, namespace, namespace)
330 340 sys_exit = ''
331 341 except SystemExit:
332 342 sys_exit = """*** SystemExit exception caught in code being profiled."""
333 343
334 344 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
335 345
336 346 lims = opts.l
337 347 if lims:
338 348 lims = [] # rebuild lims with ints/floats/strings
339 349 for lim in opts.l:
340 350 try:
341 351 lims.append(int(lim))
342 352 except ValueError:
343 353 try:
344 354 lims.append(float(lim))
345 355 except ValueError:
346 356 lims.append(lim)
347 357
348 358 # Trap output.
349 359 stdout_trap = StringIO()
350 360 stats_stream = stats.stream
351 361 try:
352 362 stats.stream = stdout_trap
353 363 stats.print_stats(*lims)
354 364 finally:
355 365 stats.stream = stats_stream
356 366
357 367 output = stdout_trap.getvalue()
358 368 output = output.rstrip()
359 369
360 370 if 'q' not in opts:
361 371 page.page(output)
362 372 print(sys_exit, end=' ')
363 373
364 374 dump_file = opts.D[0]
365 375 text_file = opts.T[0]
366 376 if dump_file:
367 377 prof.dump_stats(dump_file)
368 378 print(
369 379 f"\n*** Profile stats marshalled to file {repr(dump_file)}.{sys_exit}"
370 380 )
371 381 if text_file:
372 382 pfile = Path(text_file)
373 383 pfile.touch(exist_ok=True)
374 384 pfile.write_text(output, encoding="utf-8")
375 385
376 386 print(
377 387 f"\n*** Profile printout saved to text file {repr(text_file)}.{sys_exit}"
378 388 )
379 389
380 390 if 'r' in opts:
381 391 return stats
382 392
383 393 return None
384 394
385 395 @line_magic
386 396 def pdb(self, parameter_s=''):
387 397 """Control the automatic calling of the pdb interactive debugger.
388 398
389 399 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
390 400 argument it works as a toggle.
391 401
392 402 When an exception is triggered, IPython can optionally call the
393 403 interactive pdb debugger after the traceback printout. %pdb toggles
394 404 this feature on and off.
395 405
396 406 The initial state of this feature is set in your configuration
397 407 file (the option is ``InteractiveShell.pdb``).
398 408
399 409 If you want to just activate the debugger AFTER an exception has fired,
400 410 without having to type '%pdb on' and rerunning your code, you can use
401 411 the %debug magic."""
402 412
403 413 par = parameter_s.strip().lower()
404 414
405 415 if par:
406 416 try:
407 417 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
408 418 except KeyError:
409 419 print ('Incorrect argument. Use on/1, off/0, '
410 420 'or nothing for a toggle.')
411 421 return
412 422 else:
413 423 # toggle
414 424 new_pdb = not self.shell.call_pdb
415 425
416 426 # set on the shell
417 427 self.shell.call_pdb = new_pdb
418 428 print('Automatic pdb calling has been turned',on_off(new_pdb))
419 429
420 430 @magic_arguments.magic_arguments()
421 431 @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE',
422 432 help="""
423 433 Set break point at LINE in FILE.
424 434 """
425 435 )
426 436 @magic_arguments.argument('statement', nargs='*',
427 437 help="""
428 438 Code to run in debugger.
429 439 You can omit this in cell magic mode.
430 440 """
431 441 )
432 442 @no_var_expand
433 443 @line_cell_magic
434 444 @needs_local_scope
435 445 def debug(self, line="", cell=None, local_ns=None):
436 446 """Activate the interactive debugger.
437 447
438 448 This magic command support two ways of activating debugger.
439 449 One is to activate debugger before executing code. This way, you
440 450 can set a break point, to step through the code from the point.
441 451 You can use this mode by giving statements to execute and optionally
442 452 a breakpoint.
443 453
444 454 The other one is to activate debugger in post-mortem mode. You can
445 455 activate this mode simply running %debug without any argument.
446 456 If an exception has just occurred, this lets you inspect its stack
447 457 frames interactively. Note that this will always work only on the last
448 458 traceback that occurred, so you must call this quickly after an
449 459 exception that you wish to inspect has fired, because if another one
450 460 occurs, it clobbers the previous one.
451 461
452 462 If you want IPython to automatically do this on every exception, see
453 463 the %pdb magic for more details.
454 464
455 465 .. versionchanged:: 7.3
456 466 When running code, user variables are no longer expanded,
457 467 the magic line is always left unmodified.
458 468
459 469 """
460 470 args = magic_arguments.parse_argstring(self.debug, line)
461 471
462 472 if not (args.breakpoint or args.statement or cell):
463 473 self._debug_post_mortem()
464 474 elif not (args.breakpoint or cell):
465 475 # If there is no breakpoints, the line is just code to execute
466 476 self._debug_exec(line, None, local_ns)
467 477 else:
468 478 # Here we try to reconstruct the code from the output of
469 479 # parse_argstring. This might not work if the code has spaces
470 480 # For example this fails for `print("a b")`
471 481 code = "\n".join(args.statement)
472 482 if cell:
473 483 code += "\n" + cell
474 484 self._debug_exec(code, args.breakpoint, local_ns)
475 485
476 486 def _debug_post_mortem(self):
477 487 self.shell.debugger(force=True)
478 488
479 489 def _debug_exec(self, code, breakpoint, local_ns=None):
480 490 if breakpoint:
481 491 (filename, bp_line) = breakpoint.rsplit(':', 1)
482 492 bp_line = int(bp_line)
483 493 else:
484 494 (filename, bp_line) = (None, None)
485 495 self._run_with_debugger(
486 496 code, self.shell.user_ns, filename, bp_line, local_ns=local_ns
487 497 )
488 498
489 499 @line_magic
490 500 def tb(self, s):
491 501 """Print the last traceback.
492 502
493 503 Optionally, specify an exception reporting mode, tuning the
494 504 verbosity of the traceback. By default the currently-active exception
495 505 mode is used. See %xmode for changing exception reporting modes.
496 506
497 507 Valid modes: Plain, Context, Verbose, and Minimal.
498 508 """
499 509 interactive_tb = self.shell.InteractiveTB
500 510 if s:
501 511 # Switch exception reporting mode for this one call.
502 512 # Ensure it is switched back.
503 513 def xmode_switch_err(name):
504 514 warn('Error changing %s exception modes.\n%s' %
505 515 (name,sys.exc_info()[1]))
506 516
507 517 new_mode = s.strip().capitalize()
508 518 original_mode = interactive_tb.mode
509 519 try:
510 520 try:
511 521 interactive_tb.set_mode(mode=new_mode)
512 522 except Exception:
513 523 xmode_switch_err('user')
514 524 else:
515 525 self.shell.showtraceback()
516 526 finally:
517 527 interactive_tb.set_mode(mode=original_mode)
518 528 else:
519 529 self.shell.showtraceback()
520 530
521 531 @skip_doctest
522 532 @line_magic
523 533 def run(self, parameter_s='', runner=None,
524 534 file_finder=get_py_filename):
525 535 """Run the named file inside IPython as a program.
526 536
527 537 Usage::
528 538
529 539 %run [-n -i -e -G]
530 540 [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )]
531 541 ( -m mod | filename ) [args]
532 542
533 543 The filename argument should be either a pure Python script (with
534 544 extension ``.py``), or a file with custom IPython syntax (such as
535 545 magics). If the latter, the file can be either a script with ``.ipy``
536 546 extension, or a Jupyter notebook with ``.ipynb`` extension. When running
537 547 a Jupyter notebook, the output from print statements and other
538 548 displayed objects will appear in the terminal (even matplotlib figures
539 549 will open, if a terminal-compliant backend is being used). Note that,
540 550 at the system command line, the ``jupyter run`` command offers similar
541 551 functionality for executing notebooks (albeit currently with some
542 552 differences in supported options).
543 553
544 554 Parameters after the filename are passed as command-line arguments to
545 555 the program (put in sys.argv). Then, control returns to IPython's
546 556 prompt.
547 557
548 558 This is similar to running at a system prompt ``python file args``,
549 559 but with the advantage of giving you IPython's tracebacks, and of
550 560 loading all variables into your interactive namespace for further use
551 561 (unless -p is used, see below).
552 562
553 563 The file is executed in a namespace initially consisting only of
554 564 ``__name__=='__main__'`` and sys.argv constructed as indicated. It thus
555 565 sees its environment as if it were being run as a stand-alone program
556 566 (except for sharing global objects such as previously imported
557 567 modules). But after execution, the IPython interactive namespace gets
558 568 updated with all variables defined in the program (except for __name__
559 569 and sys.argv). This allows for very convenient loading of code for
560 570 interactive work, while giving each program a 'clean sheet' to run in.
561 571
562 572 Arguments are expanded using shell-like glob match. Patterns
563 573 '*', '?', '[seq]' and '[!seq]' can be used. Additionally,
564 574 tilde '~' will be expanded into user's home directory. Unlike
565 575 real shells, quotation does not suppress expansions. Use
566 576 *two* back slashes (e.g. ``\\\\*``) to suppress expansions.
567 577 To completely disable these expansions, you can use -G flag.
568 578
569 579 On Windows systems, the use of single quotes `'` when specifying
570 580 a file is not supported. Use double quotes `"`.
571 581
572 582 Options:
573 583
574 584 -n
575 585 __name__ is NOT set to '__main__', but to the running file's name
576 586 without extension (as python does under import). This allows running
577 587 scripts and reloading the definitions in them without calling code
578 588 protected by an ``if __name__ == "__main__"`` clause.
579 589
580 590 -i
581 591 run the file in IPython's namespace instead of an empty one. This
582 592 is useful if you are experimenting with code written in a text editor
583 593 which depends on variables defined interactively.
584 594
585 595 -e
586 596 ignore sys.exit() calls or SystemExit exceptions in the script
587 597 being run. This is particularly useful if IPython is being used to
588 598 run unittests, which always exit with a sys.exit() call. In such
589 599 cases you are interested in the output of the test results, not in
590 600 seeing a traceback of the unittest module.
591 601
592 602 -t
593 603 print timing information at the end of the run. IPython will give
594 604 you an estimated CPU time consumption for your script, which under
595 605 Unix uses the resource module to avoid the wraparound problems of
596 606 time.clock(). Under Unix, an estimate of time spent on system tasks
597 607 is also given (for Windows platforms this is reported as 0.0).
598 608
599 609 If -t is given, an additional ``-N<N>`` option can be given, where <N>
600 610 must be an integer indicating how many times you want the script to
601 611 run. The final timing report will include total and per run results.
602 612
603 613 For example (testing the script uniq_stable.py)::
604 614
605 615 In [1]: run -t uniq_stable
606 616
607 617 IPython CPU timings (estimated):
608 618 User : 0.19597 s.
609 619 System: 0.0 s.
610 620
611 621 In [2]: run -t -N5 uniq_stable
612 622
613 623 IPython CPU timings (estimated):
614 624 Total runs performed: 5
615 625 Times : Total Per run
616 626 User : 0.910862 s, 0.1821724 s.
617 627 System: 0.0 s, 0.0 s.
618 628
619 629 -d
620 630 run your program under the control of pdb, the Python debugger.
621 631 This allows you to execute your program step by step, watch variables,
622 632 etc. Internally, what IPython does is similar to calling::
623 633
624 634 pdb.run('execfile("YOURFILENAME")')
625 635
626 636 with a breakpoint set on line 1 of your file. You can change the line
627 637 number for this automatic breakpoint to be <N> by using the -bN option
628 638 (where N must be an integer). For example::
629 639
630 640 %run -d -b40 myscript
631 641
632 642 will set the first breakpoint at line 40 in myscript.py. Note that
633 643 the first breakpoint must be set on a line which actually does
634 644 something (not a comment or docstring) for it to stop execution.
635 645
636 646 Or you can specify a breakpoint in a different file::
637 647
638 648 %run -d -b myotherfile.py:20 myscript
639 649
640 650 When the pdb debugger starts, you will see a (Pdb) prompt. You must
641 651 first enter 'c' (without quotes) to start execution up to the first
642 652 breakpoint.
643 653
644 654 Entering 'help' gives information about the use of the debugger. You
645 655 can easily see pdb's full documentation with "import pdb;pdb.help()"
646 656 at a prompt.
647 657
648 658 -p
649 659 run program under the control of the Python profiler module (which
650 660 prints a detailed report of execution times, function calls, etc).
651 661
652 662 You can pass other options after -p which affect the behavior of the
653 663 profiler itself. See the docs for %prun for details.
654 664
655 665 In this mode, the program's variables do NOT propagate back to the
656 666 IPython interactive namespace (because they remain in the namespace
657 667 where the profiler executes them).
658 668
659 669 Internally this triggers a call to %prun, see its documentation for
660 670 details on the options available specifically for profiling.
661 671
662 672 There is one special usage for which the text above doesn't apply:
663 673 if the filename ends with .ipy[nb], the file is run as ipython script,
664 674 just as if the commands were written on IPython prompt.
665 675
666 676 -m
667 677 specify module name to load instead of script path. Similar to
668 678 the -m option for the python interpreter. Use this option last if you
669 679 want to combine with other %run options. Unlike the python interpreter
670 680 only source modules are allowed no .pyc or .pyo files.
671 681 For example::
672 682
673 683 %run -m example
674 684
675 685 will run the example module.
676 686
677 687 -G
678 688 disable shell-like glob expansion of arguments.
679 689
680 690 """
681 691
682 692 # Logic to handle issue #3664
683 693 # Add '--' after '-m <module_name>' to ignore additional args passed to a module.
684 694 if '-m' in parameter_s and '--' not in parameter_s:
685 695 argv = shlex.split(parameter_s, posix=(os.name == 'posix'))
686 696 for idx, arg in enumerate(argv):
687 697 if arg and arg.startswith('-') and arg != '-':
688 698 if arg == '-m':
689 699 argv.insert(idx + 2, '--')
690 700 break
691 701 else:
692 702 # Positional arg, break
693 703 break
694 704 parameter_s = ' '.join(shlex.quote(arg) for arg in argv)
695 705
696 706 # get arguments and set sys.argv for program to be run.
697 707 opts, arg_lst = self.parse_options(parameter_s,
698 708 'nidtN:b:pD:l:rs:T:em:G',
699 709 mode='list', list_all=1)
700 710 if "m" in opts:
701 711 modulename = opts["m"][0]
702 712 modpath = find_mod(modulename)
703 713 if modpath is None:
704 714 msg = '%r is not a valid modulename on sys.path'%modulename
705 715 raise Exception(msg)
706 716 arg_lst = [modpath] + arg_lst
707 717 try:
708 718 fpath = None # initialize to make sure fpath is in scope later
709 719 fpath = arg_lst[0]
710 720 filename = file_finder(fpath)
711 721 except IndexError as e:
712 722 msg = 'you must provide at least a filename.'
713 723 raise Exception(msg) from e
714 724 except IOError as e:
715 725 try:
716 726 msg = str(e)
717 727 except UnicodeError:
718 728 msg = e.message
719 729 if os.name == 'nt' and re.match(r"^'.*'$",fpath):
720 730 warn('For Windows, use double quotes to wrap a filename: %run "mypath\\myfile.py"')
721 731 raise Exception(msg) from e
722 732 except TypeError:
723 733 if fpath in sys.meta_path:
724 734 filename = ""
725 735 else:
726 736 raise
727 737
728 738 if filename.lower().endswith(('.ipy', '.ipynb')):
729 739 with preserve_keys(self.shell.user_ns, '__file__'):
730 740 self.shell.user_ns['__file__'] = filename
731 741 self.shell.safe_execfile_ipy(filename, raise_exceptions=True)
732 742 return
733 743
734 744 # Control the response to exit() calls made by the script being run
735 745 exit_ignore = 'e' in opts
736 746
737 747 # Make sure that the running script gets a proper sys.argv as if it
738 748 # were run from a system shell.
739 749 save_argv = sys.argv # save it for later restoring
740 750
741 751 if 'G' in opts:
742 752 args = arg_lst[1:]
743 753 else:
744 754 # tilde and glob expansion
745 755 args = shellglob(map(os.path.expanduser, arg_lst[1:]))
746 756
747 757 sys.argv = [filename] + args # put in the proper filename
748 758
749 759 if 'n' in opts:
750 760 name = Path(filename).stem
751 761 else:
752 762 name = '__main__'
753 763
754 764 if 'i' in opts:
755 765 # Run in user's interactive namespace
756 766 prog_ns = self.shell.user_ns
757 767 __name__save = self.shell.user_ns['__name__']
758 768 prog_ns['__name__'] = name
759 769 main_mod = self.shell.user_module
760 770
761 771 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
762 772 # set the __file__ global in the script's namespace
763 773 # TK: Is this necessary in interactive mode?
764 774 prog_ns['__file__'] = filename
765 775 else:
766 776 # Run in a fresh, empty namespace
767 777
768 778 # The shell MUST hold a reference to prog_ns so after %run
769 779 # exits, the python deletion mechanism doesn't zero it out
770 780 # (leaving dangling references). See interactiveshell for details
771 781 main_mod = self.shell.new_main_mod(filename, name)
772 782 prog_ns = main_mod.__dict__
773 783
774 784 # pickle fix. See interactiveshell for an explanation. But we need to
775 785 # make sure that, if we overwrite __main__, we replace it at the end
776 786 main_mod_name = prog_ns['__name__']
777 787
778 788 if main_mod_name == '__main__':
779 789 restore_main = sys.modules['__main__']
780 790 else:
781 791 restore_main = False
782 792
783 793 # This needs to be undone at the end to prevent holding references to
784 794 # every single object ever created.
785 795 sys.modules[main_mod_name] = main_mod
786 796
787 797 if 'p' in opts or 'd' in opts:
788 798 if 'm' in opts:
789 799 code = 'run_module(modulename, prog_ns)'
790 800 code_ns = {
791 801 'run_module': self.shell.safe_run_module,
792 802 'prog_ns': prog_ns,
793 803 'modulename': modulename,
794 804 }
795 805 else:
796 806 if 'd' in opts:
797 807 # allow exceptions to raise in debug mode
798 808 code = 'execfile(filename, prog_ns, raise_exceptions=True)'
799 809 else:
800 810 code = 'execfile(filename, prog_ns)'
801 811 code_ns = {
802 812 'execfile': self.shell.safe_execfile,
803 813 'prog_ns': prog_ns,
804 814 'filename': get_py_filename(filename),
805 815 }
806 816
807 817 try:
808 818 stats = None
809 819 if 'p' in opts:
810 820 stats = self._run_with_profiler(code, opts, code_ns)
811 821 else:
812 822 if 'd' in opts:
813 823 bp_file, bp_line = parse_breakpoint(
814 824 opts.get('b', ['1'])[0], filename)
815 825 self._run_with_debugger(
816 826 code, code_ns, filename, bp_line, bp_file)
817 827 else:
818 828 if 'm' in opts:
819 829 def run():
820 830 self.shell.safe_run_module(modulename, prog_ns)
821 831 else:
822 832 if runner is None:
823 833 runner = self.default_runner
824 834 if runner is None:
825 835 runner = self.shell.safe_execfile
826 836
827 837 def run():
828 838 runner(filename, prog_ns, prog_ns,
829 839 exit_ignore=exit_ignore)
830 840
831 841 if 't' in opts:
832 842 # timed execution
833 843 try:
834 844 nruns = int(opts['N'][0])
835 845 if nruns < 1:
836 846 error('Number of runs must be >=1')
837 847 return
838 848 except (KeyError):
839 849 nruns = 1
840 850 self._run_with_timing(run, nruns)
841 851 else:
842 852 # regular execution
843 853 run()
844 854
845 855 if 'i' in opts:
846 856 self.shell.user_ns['__name__'] = __name__save
847 857 else:
848 858 # update IPython interactive namespace
849 859
850 860 # Some forms of read errors on the file may mean the
851 861 # __name__ key was never set; using pop we don't have to
852 862 # worry about a possible KeyError.
853 863 prog_ns.pop('__name__', None)
854 864
855 865 with preserve_keys(self.shell.user_ns, '__file__'):
856 866 self.shell.user_ns.update(prog_ns)
857 867 finally:
858 868 # It's a bit of a mystery why, but __builtins__ can change from
859 869 # being a module to becoming a dict missing some key data after
860 870 # %run. As best I can see, this is NOT something IPython is doing
861 871 # at all, and similar problems have been reported before:
862 872 # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
863 873 # Since this seems to be done by the interpreter itself, the best
864 874 # we can do is to at least restore __builtins__ for the user on
865 875 # exit.
866 876 self.shell.user_ns['__builtins__'] = builtin_mod
867 877
868 878 # Ensure key global structures are restored
869 879 sys.argv = save_argv
870 880 if restore_main:
871 881 sys.modules['__main__'] = restore_main
872 882 if '__mp_main__' in sys.modules:
873 883 sys.modules['__mp_main__'] = restore_main
874 884 else:
875 885 # Remove from sys.modules the reference to main_mod we'd
876 886 # added. Otherwise it will trap references to objects
877 887 # contained therein.
878 888 del sys.modules[main_mod_name]
879 889
880 890 return stats
881 891
882 892 def _run_with_debugger(
883 893 self, code, code_ns, filename=None, bp_line=None, bp_file=None, local_ns=None
884 894 ):
885 895 """
886 896 Run `code` in debugger with a break point.
887 897
888 898 Parameters
889 899 ----------
890 900 code : str
891 901 Code to execute.
892 902 code_ns : dict
893 903 A namespace in which `code` is executed.
894 904 filename : str
895 905 `code` is ran as if it is in `filename`.
896 906 bp_line : int, optional
897 907 Line number of the break point.
898 908 bp_file : str, optional
899 909 Path to the file in which break point is specified.
900 910 `filename` is used if not given.
901 911 local_ns : dict, optional
902 912 A local namespace in which `code` is executed.
903 913
904 914 Raises
905 915 ------
906 916 UsageError
907 917 If the break point given by `bp_line` is not valid.
908 918
909 919 """
910 920 deb = self.shell.InteractiveTB.pdb
911 921 if not deb:
912 922 self.shell.InteractiveTB.pdb = self.shell.InteractiveTB.debugger_cls()
913 923 deb = self.shell.InteractiveTB.pdb
914 924
915 925 # deb.checkline() fails if deb.curframe exists but is None; it can
916 926 # handle it not existing. https://github.com/ipython/ipython/issues/10028
917 927 if hasattr(deb, 'curframe'):
918 928 del deb.curframe
919 929
920 930 # reset Breakpoint state, which is moronically kept
921 931 # in a class
922 932 bdb.Breakpoint.next = 1
923 933 bdb.Breakpoint.bplist = {}
924 934 bdb.Breakpoint.bpbynumber = [None]
925 935 deb.clear_all_breaks()
926 936 if bp_line is not None:
927 937 # Set an initial breakpoint to stop execution
928 938 maxtries = 10
929 939 bp_file = bp_file or filename
930 940 checkline = deb.checkline(bp_file, bp_line)
931 941 if not checkline:
932 942 for bp in range(bp_line + 1, bp_line + maxtries + 1):
933 943 if deb.checkline(bp_file, bp):
934 944 break
935 945 else:
936 946 msg = ("\nI failed to find a valid line to set "
937 947 "a breakpoint\n"
938 948 "after trying up to line: %s.\n"
939 949 "Please set a valid breakpoint manually "
940 950 "with the -b option." % bp)
941 951 raise UsageError(msg)
942 952 # if we find a good linenumber, set the breakpoint
943 953 deb.do_break('%s:%s' % (bp_file, bp_line))
944 954
945 955 if filename:
946 956 # Mimic Pdb._runscript(...)
947 957 deb._wait_for_mainpyfile = True
948 958 deb.mainpyfile = deb.canonic(filename)
949 959
950 960 # Start file run
951 961 print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt)
952 962 try:
953 963 if filename:
954 964 # save filename so it can be used by methods on the deb object
955 965 deb._exec_filename = filename
956 966 while True:
957 967 try:
958 968 trace = sys.gettrace()
959 969 deb.run(code, code_ns, local_ns)
960 970 except Restart:
961 971 print("Restarting")
962 972 if filename:
963 973 deb._wait_for_mainpyfile = True
964 974 deb.mainpyfile = deb.canonic(filename)
965 975 continue
966 976 else:
967 977 break
968 978 finally:
969 979 sys.settrace(trace)
970 980
971 981
972 982 except:
973 983 etype, value, tb = sys.exc_info()
974 984 # Skip three frames in the traceback: the %run one,
975 985 # one inside bdb.py, and the command-line typed by the
976 986 # user (run by exec in pdb itself).
977 987 self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
978 988
979 989 @staticmethod
980 990 def _run_with_timing(run, nruns):
981 991 """
982 992 Run function `run` and print timing information.
983 993
984 994 Parameters
985 995 ----------
986 996 run : callable
987 997 Any callable object which takes no argument.
988 998 nruns : int
989 999 Number of times to execute `run`.
990 1000
991 1001 """
992 1002 twall0 = time.perf_counter()
993 1003 if nruns == 1:
994 1004 t0 = clock2()
995 1005 run()
996 1006 t1 = clock2()
997 1007 t_usr = t1[0] - t0[0]
998 1008 t_sys = t1[1] - t0[1]
999 1009 print("\nIPython CPU timings (estimated):")
1000 1010 print(" User : %10.2f s." % t_usr)
1001 1011 print(" System : %10.2f s." % t_sys)
1002 1012 else:
1003 1013 runs = range(nruns)
1004 1014 t0 = clock2()
1005 1015 for nr in runs:
1006 1016 run()
1007 1017 t1 = clock2()
1008 1018 t_usr = t1[0] - t0[0]
1009 1019 t_sys = t1[1] - t0[1]
1010 1020 print("\nIPython CPU timings (estimated):")
1011 1021 print("Total runs performed:", nruns)
1012 1022 print(" Times : %10s %10s" % ('Total', 'Per run'))
1013 1023 print(" User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns))
1014 1024 print(" System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns))
1015 1025 twall1 = time.perf_counter()
1016 1026 print("Wall time: %10.2f s." % (twall1 - twall0))
1017 1027
1018 1028 @skip_doctest
1019 1029 @no_var_expand
1020 1030 @line_cell_magic
1021 1031 @needs_local_scope
1022 1032 def timeit(self, line='', cell=None, local_ns=None):
1023 1033 """Time execution of a Python statement or expression
1024 1034
1025 1035 **Usage, in line mode:**
1026 1036
1027 1037 %timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] statement
1028 1038
1029 1039 **or in cell mode:**
1030 1040
1031 1041 %%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] setup_code
1032 1042
1033 1043 code
1034 1044
1035 1045 code...
1036 1046
1037 1047 Time execution of a Python statement or expression using the timeit
1038 1048 module. This function can be used both as a line and cell magic:
1039 1049
1040 1050 - In line mode you can time a single-line statement (though multiple
1041 1051 ones can be chained with using semicolons).
1042 1052
1043 1053 - In cell mode, the statement in the first line is used as setup code
1044 1054 (executed but not timed) and the body of the cell is timed. The cell
1045 1055 body has access to any variables created in the setup code.
1046 1056
1047 1057 Options:
1048 1058
1049 1059 -n<N>: execute the given statement <N> times in a loop. If <N> is not
1050 1060 provided, <N> is determined so as to get sufficient accuracy.
1051 1061
1052 1062 -r<R>: number of repeats <R>, each consisting of <N> loops, and take the
1053 1063 average result.
1054 1064 Default: 7
1055 1065
1056 1066 -t: use time.time to measure the time, which is the default on Unix.
1057 1067 This function measures wall time.
1058 1068
1059 1069 -c: use time.clock to measure the time, which is the default on
1060 1070 Windows and measures wall time. On Unix, resource.getrusage is used
1061 1071 instead and returns the CPU user time.
1062 1072
1063 1073 -p<P>: use a precision of <P> digits to display the timing result.
1064 1074 Default: 3
1065 1075
1066 1076 -q: Quiet, do not print result.
1067 1077
1068 1078 -o: return a TimeitResult that can be stored in a variable to inspect
1069 1079 the result in more details.
1070 1080
1071 1081 .. versionchanged:: 7.3
1072 1082 User variables are no longer expanded,
1073 1083 the magic line is always left unmodified.
1074 1084
1075 1085 Examples
1076 1086 --------
1077 1087 ::
1078 1088
1079 1089 In [1]: %timeit pass
1080 1090 8.26 ns ± 0.12 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
1081 1091
1082 1092 In [2]: u = None
1083 1093
1084 1094 In [3]: %timeit u is None
1085 1095 29.9 ns ± 0.643 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
1086 1096
1087 1097 In [4]: %timeit -r 4 u == None
1088 1098
1089 1099 In [5]: import time
1090 1100
1091 1101 In [6]: %timeit -n1 time.sleep(2)
1092 1102
1093 1103 The times reported by %timeit will be slightly higher than those
1094 1104 reported by the timeit.py script when variables are accessed. This is
1095 1105 due to the fact that %timeit executes the statement in the namespace
1096 1106 of the shell, compared with timeit.py, which uses a single setup
1097 1107 statement to import function or create variables. Generally, the bias
1098 1108 does not matter as long as results from timeit.py are not mixed with
1099 1109 those from %timeit."""
1100 1110
1101 1111 opts, stmt = self.parse_options(
1102 1112 line, "n:r:tcp:qo", posix=False, strict=False, preserve_non_opts=True
1103 1113 )
1104 1114 if stmt == "" and cell is None:
1105 1115 return
1106 1116
1107 1117 timefunc = timeit.default_timer
1108 1118 number = int(getattr(opts, "n", 0))
1109 1119 default_repeat = 7 if timeit.default_repeat < 7 else timeit.default_repeat
1110 1120 repeat = int(getattr(opts, "r", default_repeat))
1111 1121 precision = int(getattr(opts, "p", 3))
1112 1122 quiet = 'q' in opts
1113 1123 return_result = 'o' in opts
1114 1124 if hasattr(opts, "t"):
1115 1125 timefunc = time.time
1116 1126 if hasattr(opts, "c"):
1117 1127 timefunc = clock
1118 1128
1119 1129 timer = Timer(timer=timefunc)
1120 1130 # this code has tight coupling to the inner workings of timeit.Timer,
1121 1131 # but is there a better way to achieve that the code stmt has access
1122 1132 # to the shell namespace?
1123 1133 transform = self.shell.transform_cell
1124 1134
1125 1135 if cell is None:
1126 1136 # called as line magic
1127 1137 ast_setup = self.shell.compile.ast_parse("pass")
1128 1138 ast_stmt = self.shell.compile.ast_parse(transform(stmt))
1129 1139 else:
1130 1140 ast_setup = self.shell.compile.ast_parse(transform(stmt))
1131 1141 ast_stmt = self.shell.compile.ast_parse(transform(cell))
1132 1142
1133 1143 ast_setup = self.shell.transform_ast(ast_setup)
1134 1144 ast_stmt = self.shell.transform_ast(ast_stmt)
1135 1145
1136 1146 # Check that these compile to valid Python code *outside* the timer func
1137 1147 # Invalid code may become valid when put inside the function & loop,
1138 1148 # which messes up error messages.
1139 1149 # https://github.com/ipython/ipython/issues/10636
1140 1150 self.shell.compile(ast_setup, "<magic-timeit-setup>", "exec")
1141 1151 self.shell.compile(ast_stmt, "<magic-timeit-stmt>", "exec")
1142 1152
1143 1153 # This codestring is taken from timeit.template - we fill it in as an
1144 1154 # AST, so that we can apply our AST transformations to the user code
1145 1155 # without affecting the timing code.
1146 1156 timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
1147 1157 ' setup\n'
1148 1158 ' _t0 = _timer()\n'
1149 1159 ' for _i in _it:\n'
1150 1160 ' stmt\n'
1151 1161 ' _t1 = _timer()\n'
1152 1162 ' return _t1 - _t0\n')
1153 1163
1154 1164 timeit_ast = TimeitTemplateFiller(ast_setup, ast_stmt).visit(timeit_ast_template)
1155 1165 timeit_ast = ast.fix_missing_locations(timeit_ast)
1156 1166
1157 1167 # Track compilation time so it can be reported if too long
1158 1168 # Minimum time above which compilation time will be reported
1159 1169 tc_min = 0.1
1160 1170
1161 1171 t0 = clock()
1162 1172 code = self.shell.compile(timeit_ast, "<magic-timeit>", "exec")
1163 1173 tc = clock()-t0
1164 1174
1165 1175 ns = {}
1166 1176 glob = self.shell.user_ns
1167 1177 # handles global vars with same name as local vars. We store them in conflict_globs.
1168 1178 conflict_globs = {}
1169 1179 if local_ns and cell is None:
1170 1180 for var_name, var_val in glob.items():
1171 1181 if var_name in local_ns:
1172 1182 conflict_globs[var_name] = var_val
1173 1183 glob.update(local_ns)
1174 1184
1175 1185 exec(code, glob, ns)
1176 1186 timer.inner = ns["inner"]
1177 1187
1178 1188 # This is used to check if there is a huge difference between the
1179 1189 # best and worst timings.
1180 1190 # Issue: https://github.com/ipython/ipython/issues/6471
1181 1191 if number == 0:
1182 1192 # determine number so that 0.2 <= total time < 2.0
1183 1193 for index in range(0, 10):
1184 1194 number = 10 ** index
1185 1195 time_number = timer.timeit(number)
1186 1196 if time_number >= 0.2:
1187 1197 break
1188 1198
1189 1199 all_runs = timer.repeat(repeat, number)
1190 1200 best = min(all_runs) / number
1191 1201 worst = max(all_runs) / number
1192 1202 timeit_result = TimeitResult(number, repeat, best, worst, all_runs, tc, precision)
1193 1203
1194 1204 # Restore global vars from conflict_globs
1195 1205 if conflict_globs:
1196 1206 glob.update(conflict_globs)
1197 1207
1198 1208 if not quiet :
1199 1209 # Check best timing is greater than zero to avoid a
1200 1210 # ZeroDivisionError.
1201 1211 # In cases where the slowest timing is lesser than a microsecond
1202 1212 # we assume that it does not really matter if the fastest
1203 1213 # timing is 4 times faster than the slowest timing or not.
1204 1214 if worst > 4 * best and best > 0 and worst > 1e-6:
1205 1215 print("The slowest run took %0.2f times longer than the "
1206 1216 "fastest. This could mean that an intermediate result "
1207 1217 "is being cached." % (worst / best))
1208 1218
1209 1219 print( timeit_result )
1210 1220
1211 1221 if tc > tc_min:
1212 1222 print("Compiler time: %.2f s" % tc)
1213 1223 if return_result:
1214 1224 return timeit_result
1215 1225
1216 1226 @skip_doctest
1217 1227 @no_var_expand
1218 1228 @needs_local_scope
1219 1229 @line_cell_magic
1220 1230 @output_can_be_silenced
1221 1231 def time(self,line='', cell=None, local_ns=None):
1222 1232 """Time execution of a Python statement or expression.
1223 1233
1224 1234 The CPU and wall clock times are printed, and the value of the
1225 1235 expression (if any) is returned. Note that under Win32, system time
1226 1236 is always reported as 0, since it can not be measured.
1227 1237
1228 1238 This function can be used both as a line and cell magic:
1229 1239
1230 1240 - In line mode you can time a single-line statement (though multiple
1231 1241 ones can be chained with using semicolons).
1232 1242
1233 1243 - In cell mode, you can time the cell body (a directly
1234 1244 following statement raises an error).
1235 1245
1236 1246 This function provides very basic timing functionality. Use the timeit
1237 1247 magic for more control over the measurement.
1238 1248
1239 1249 .. versionchanged:: 7.3
1240 1250 User variables are no longer expanded,
1241 1251 the magic line is always left unmodified.
1242 1252
1243 1253 Examples
1244 1254 --------
1245 1255 ::
1246 1256
1247 1257 In [1]: %time 2**128
1248 1258 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1249 1259 Wall time: 0.00
1250 1260 Out[1]: 340282366920938463463374607431768211456L
1251 1261
1252 1262 In [2]: n = 1000000
1253 1263
1254 1264 In [3]: %time sum(range(n))
1255 1265 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1256 1266 Wall time: 1.37
1257 1267 Out[3]: 499999500000L
1258 1268
1259 1269 In [4]: %time print('hello world')
1260 1270 hello world
1261 1271 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1262 1272 Wall time: 0.00
1263 1273
1264 1274 .. note::
1265 1275 The time needed by Python to compile the given expression will be
1266 1276 reported if it is more than 0.1s.
1267 1277
1268 1278 In the example below, the actual exponentiation is done by Python
1269 1279 at compilation time, so while the expression can take a noticeable
1270 1280 amount of time to compute, that time is purely due to the
1271 1281 compilation::
1272 1282
1273 1283 In [5]: %time 3**9999;
1274 1284 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1275 1285 Wall time: 0.00 s
1276 1286
1277 1287 In [6]: %time 3**999999;
1278 1288 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1279 1289 Wall time: 0.00 s
1280 1290 Compiler : 0.78 s
1281 1291 """
1282 1292 # fail immediately if the given expression can't be compiled
1283 1293
1284 1294 if line and cell:
1285 1295 raise UsageError("Can't use statement directly after '%%time'!")
1286 1296
1287 1297 if cell:
1288 1298 expr = self.shell.transform_cell(cell)
1289 1299 else:
1290 1300 expr = self.shell.transform_cell(line)
1291 1301
1292 1302 # Minimum time above which parse time will be reported
1293 1303 tp_min = 0.1
1294 1304
1295 1305 t0 = clock()
1296 1306 expr_ast = self.shell.compile.ast_parse(expr)
1297 1307 tp = clock()-t0
1298 1308
1299 1309 # Apply AST transformations
1300 1310 expr_ast = self.shell.transform_ast(expr_ast)
1301 1311
1302 1312 # Minimum time above which compilation time will be reported
1303 1313 tc_min = 0.1
1304 1314
1305 1315 expr_val=None
1306 1316 if len(expr_ast.body)==1 and isinstance(expr_ast.body[0], ast.Expr):
1307 1317 mode = 'eval'
1308 1318 source = '<timed eval>'
1309 1319 expr_ast = ast.Expression(expr_ast.body[0].value)
1310 1320 else:
1311 1321 mode = 'exec'
1312 1322 source = '<timed exec>'
1313 1323 # multi-line %%time case
1314 1324 if len(expr_ast.body) > 1 and isinstance(expr_ast.body[-1], ast.Expr):
1315 1325 expr_val= expr_ast.body[-1]
1316 1326 expr_ast = expr_ast.body[:-1]
1317 1327 expr_ast = Module(expr_ast, [])
1318 1328 expr_val = ast.Expression(expr_val.value)
1319 1329
1320 1330 t0 = clock()
1321 1331 code = self.shell.compile(expr_ast, source, mode)
1322 1332 tc = clock()-t0
1323 1333
1324 1334 # skew measurement as little as possible
1325 1335 glob = self.shell.user_ns
1326 1336 wtime = time.time
1327 1337 # time execution
1328 1338 wall_st = wtime()
1329 1339 if mode=='eval':
1330 1340 st = clock2()
1331 1341 try:
1332 1342 out = eval(code, glob, local_ns)
1333 1343 except:
1334 1344 self.shell.showtraceback()
1335 1345 return
1336 1346 end = clock2()
1337 1347 else:
1338 1348 st = clock2()
1339 1349 try:
1340 1350 exec(code, glob, local_ns)
1341 1351 out=None
1342 1352 # multi-line %%time case
1343 1353 if expr_val is not None:
1344 1354 code_2 = self.shell.compile(expr_val, source, 'eval')
1345 1355 out = eval(code_2, glob, local_ns)
1346 1356 except:
1347 1357 self.shell.showtraceback()
1348 1358 return
1349 1359 end = clock2()
1350 1360
1351 1361 wall_end = wtime()
1352 1362 # Compute actual times and report
1353 1363 wall_time = wall_end - wall_st
1354 1364 cpu_user = end[0] - st[0]
1355 1365 cpu_sys = end[1] - st[1]
1356 1366 cpu_tot = cpu_user + cpu_sys
1357 1367 # On windows cpu_sys is always zero, so only total is displayed
1358 1368 if sys.platform != "win32":
1359 1369 print(
1360 1370 f"CPU times: user {_format_time(cpu_user)}, sys: {_format_time(cpu_sys)}, total: {_format_time(cpu_tot)}"
1361 1371 )
1362 1372 else:
1363 1373 print(f"CPU times: total: {_format_time(cpu_tot)}")
1364 1374 print(f"Wall time: {_format_time(wall_time)}")
1365 1375 if tc > tc_min:
1366 1376 print(f"Compiler : {_format_time(tc)}")
1367 1377 if tp > tp_min:
1368 1378 print(f"Parser : {_format_time(tp)}")
1369 1379 return out
1370 1380
1371 1381 @skip_doctest
1372 1382 @line_magic
1373 1383 def macro(self, parameter_s=''):
1374 1384 """Define a macro for future re-execution. It accepts ranges of history,
1375 1385 filenames or string objects.
1376 1386
1377 1387 Usage:\\
1378 1388 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1379 1389
1380 1390 Options:
1381 1391
1382 1392 -r: use 'raw' input. By default, the 'processed' history is used,
1383 1393 so that magics are loaded in their transformed version to valid
1384 1394 Python. If this option is given, the raw input as typed at the
1385 1395 command line is used instead.
1386 1396
1387 1397 -q: quiet macro definition. By default, a tag line is printed
1388 1398 to indicate the macro has been created, and then the contents of
1389 1399 the macro are printed. If this option is given, then no printout
1390 1400 is produced once the macro is created.
1391 1401
1392 1402 This will define a global variable called `name` which is a string
1393 1403 made of joining the slices and lines you specify (n1,n2,... numbers
1394 1404 above) from your input history into a single string. This variable
1395 1405 acts like an automatic function which re-executes those lines as if
1396 1406 you had typed them. You just type 'name' at the prompt and the code
1397 1407 executes.
1398 1408
1399 1409 The syntax for indicating input ranges is described in %history.
1400 1410
1401 1411 Note: as a 'hidden' feature, you can also use traditional python slice
1402 1412 notation, where N:M means numbers N through M-1.
1403 1413
1404 1414 For example, if your history contains (print using %hist -n )::
1405 1415
1406 1416 44: x=1
1407 1417 45: y=3
1408 1418 46: z=x+y
1409 1419 47: print(x)
1410 1420 48: a=5
1411 1421 49: print('x',x,'y',y)
1412 1422
1413 1423 you can create a macro with lines 44 through 47 (included) and line 49
1414 1424 called my_macro with::
1415 1425
1416 1426 In [55]: %macro my_macro 44-47 49
1417 1427
1418 1428 Now, typing `my_macro` (without quotes) will re-execute all this code
1419 1429 in one pass.
1420 1430
1421 1431 You don't need to give the line-numbers in order, and any given line
1422 1432 number can appear multiple times. You can assemble macros with any
1423 1433 lines from your input history in any order.
1424 1434
1425 1435 The macro is a simple object which holds its value in an attribute,
1426 1436 but IPython's display system checks for macros and executes them as
1427 1437 code instead of printing them when you type their name.
1428 1438
1429 1439 You can view a macro's contents by explicitly printing it with::
1430 1440
1431 1441 print(macro_name)
1432 1442
1433 1443 """
1434 1444 opts,args = self.parse_options(parameter_s,'rq',mode='list')
1435 1445 if not args: # List existing macros
1436 1446 return sorted(k for k,v in self.shell.user_ns.items() if isinstance(v, Macro))
1437 1447 if len(args) == 1:
1438 1448 raise UsageError(
1439 1449 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
1440 1450 name, codefrom = args[0], " ".join(args[1:])
1441 1451
1442 1452 # print('rng',ranges) # dbg
1443 1453 try:
1444 1454 lines = self.shell.find_user_code(codefrom, 'r' in opts)
1445 1455 except (ValueError, TypeError) as e:
1446 1456 print(e.args[0])
1447 1457 return
1448 1458 macro = Macro(lines)
1449 1459 self.shell.define_macro(name, macro)
1450 if "q" not in opts:
1451 print(
1452 "Macro `%s` created. To execute, type its name (without quotes)." % name
1453 )
1454 print("=== Macro contents: ===")
1455 print(macro, end=" ")
1460 if not ( 'q' in opts) :
1461 print('Macro `%s` created. To execute, type its name (without quotes).' % name)
1462 print('=== Macro contents: ===')
1463 print(macro, end=' ')
1456 1464
1457 1465 @magic_arguments.magic_arguments()
1458 1466 @magic_arguments.argument('output', type=str, default='', nargs='?',
1459 1467 help="""The name of the variable in which to store output.
1460 1468 This is a utils.io.CapturedIO object with stdout/err attributes
1461 1469 for the text of the captured output.
1462 1470
1463 1471 CapturedOutput also has a show() method for displaying the output,
1464 1472 and __call__ as well, so you can use that to quickly display the
1465 1473 output.
1466 1474
1467 1475 If unspecified, captured output is discarded.
1468 1476 """
1469 1477 )
1470 1478 @magic_arguments.argument('--no-stderr', action="store_true",
1471 1479 help="""Don't capture stderr."""
1472 1480 )
1473 1481 @magic_arguments.argument('--no-stdout', action="store_true",
1474 1482 help="""Don't capture stdout."""
1475 1483 )
1476 1484 @magic_arguments.argument('--no-display', action="store_true",
1477 1485 help="""Don't capture IPython's rich display."""
1478 1486 )
1479 1487 @cell_magic
1480 1488 def capture(self, line, cell):
1481 1489 """run the cell, capturing stdout, stderr, and IPython's rich display() calls."""
1482 1490 args = magic_arguments.parse_argstring(self.capture, line)
1483 1491 out = not args.no_stdout
1484 1492 err = not args.no_stderr
1485 1493 disp = not args.no_display
1486 1494 with capture_output(out, err, disp) as io:
1487 1495 self.shell.run_cell(cell)
1488 1496 if DisplayHook.semicolon_at_end_of_expression(cell):
1489 1497 if args.output in self.shell.user_ns:
1490 1498 del self.shell.user_ns[args.output]
1491 1499 elif args.output:
1492 1500 self.shell.user_ns[args.output] = io
1493 1501
1494 1502 @skip_doctest
1495 1503 @magic_arguments.magic_arguments()
1496 1504 @magic_arguments.argument("name", type=str, default="default", nargs="?")
1497 1505 @magic_arguments.argument(
1498 1506 "--remove", action="store_true", help="remove the current transformer"
1499 1507 )
1500 1508 @magic_arguments.argument(
1501 1509 "--list", action="store_true", help="list existing transformers name"
1502 1510 )
1503 1511 @magic_arguments.argument(
1504 1512 "--list-all",
1505 1513 action="store_true",
1506 1514 help="list existing transformers name and code template",
1507 1515 )
1508 1516 @line_cell_magic
1509 1517 def code_wrap(self, line, cell=None):
1510 1518 """
1511 1519 Simple magic to quickly define a code transformer for all IPython's future input.
1512 1520
1513 1521 ``__code__`` and ``__ret__`` are special variable that represent the code to run
1514 1522 and the value of the last expression of ``__code__`` respectively.
1515 1523
1516 1524 Examples
1517 1525 --------
1518 1526
1519 1527 .. ipython::
1520 1528
1521 1529 In [1]: %%code_wrap before_after
1522 1530 ...: print('before')
1523 1531 ...: __code__
1524 1532 ...: print('after')
1525 1533 ...: __ret__
1526 1534
1527 1535
1528 1536 In [2]: 1
1529 1537 before
1530 1538 after
1531 1539 Out[2]: 1
1532 1540
1533 1541 In [3]: %code_wrap --list
1534 1542 before_after
1535 1543
1536 1544 In [4]: %code_wrap --list-all
1537 1545 before_after :
1538 1546 print('before')
1539 1547 __code__
1540 1548 print('after')
1541 1549 __ret__
1542 1550
1543 1551 In [5]: %code_wrap --remove before_after
1544 1552
1545 1553 """
1546 1554 args = magic_arguments.parse_argstring(self.code_wrap, line)
1547 1555
1548 1556 if args.list:
1549 1557 for name in self._transformers.keys():
1550 1558 print(name)
1551 1559 return
1552 1560 if args.list_all:
1553 1561 for name, _t in self._transformers.items():
1554 1562 print(name, ":")
1555 1563 print(indent(ast.unparse(_t.template), " "))
1556 1564 print()
1557 1565 return
1558 1566
1559 1567 to_remove = self._transformers.pop(args.name, None)
1560 1568 if to_remove in self.shell.ast_transformers:
1561 1569 self.shell.ast_transformers.remove(to_remove)
1562 1570 if cell is None or args.remove:
1563 1571 return
1564 1572
1565 1573 _trs = ReplaceCodeTransformer(ast.parse(cell))
1566 1574
1567 1575 self._transformers[args.name] = _trs
1568 1576 self.shell.ast_transformers.append(_trs)
1569 1577
1570 1578
1571 1579 def parse_breakpoint(text, current_file):
1572 1580 '''Returns (file, line) for file:line and (current_file, line) for line'''
1573 1581 colon = text.find(':')
1574 1582 if colon == -1:
1575 1583 return current_file, int(text)
1576 1584 else:
1577 1585 return text[:colon], int(text[colon+1:])
1578 1586
1579 1587 def _format_time(timespan, precision=3):
1580 1588 """Formats the timespan in a human readable form"""
1581 1589
1582 1590 if timespan >= 60.0:
1583 1591 # we have more than a minute, format that in a human readable form
1584 1592 # Idea from http://snipplr.com/view/5713/
1585 1593 parts = [("d", 60*60*24),("h", 60*60),("min", 60), ("s", 1)]
1586 1594 time = []
1587 1595 leftover = timespan
1588 1596 for suffix, length in parts:
1589 1597 value = int(leftover / length)
1590 1598 if value > 0:
1591 1599 leftover = leftover % length
1592 1600 time.append(u'%s%s' % (str(value), suffix))
1593 1601 if leftover < 1:
1594 1602 break
1595 1603 return " ".join(time)
1596 1604
1597 1605
1598 1606 # Unfortunately characters outside of range(128) can cause problems in
1599 1607 # certain terminals.
1600 1608 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
1601 1609 # Try to prevent crashes by being more secure than it needs to
1602 1610 # E.g. eclipse is able to print a µ, but has no sys.stdout.encoding set.
1603 1611 units = ["s", "ms", "us", "ns"] # the safe value
1604 1612 if hasattr(sys.stdout, "encoding") and sys.stdout.encoding:
1605 1613 try:
1606 1614 "μ".encode(sys.stdout.encoding)
1607 1615 units = ["s", "ms", "μs", "ns"]
1608 1616 except:
1609 1617 pass
1610 1618 scaling = [1, 1e3, 1e6, 1e9]
1611 1619
1612 1620 if timespan > 0.0:
1613 1621 order = min(-int(math.floor(math.log10(timespan)) // 3), 3)
1614 1622 else:
1615 1623 order = 3
1616 1624 return "%.*g %s" % (precision, timespan * scaling[order], units[order])
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now