m7n commited on
Commit
d3f4baf
·
1 Parent(s): 318cea6

Fixed font issues.

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. openalex_env_map/lib/python3.10/site-packages/IPython/__init__.py +0 -163
  2. openalex_env_map/lib/python3.10/site-packages/IPython/__main__.py +0 -15
  3. openalex_env_map/lib/python3.10/site-packages/IPython/conftest.py +0 -87
  4. openalex_env_map/lib/python3.10/site-packages/IPython/consoleapp.py +0 -12
  5. openalex_env_map/lib/python3.10/site-packages/IPython/core/__init__.py +0 -0
  6. openalex_env_map/lib/python3.10/site-packages/IPython/core/alias.py +0 -267
  7. openalex_env_map/lib/python3.10/site-packages/IPython/core/application.py +0 -492
  8. openalex_env_map/lib/python3.10/site-packages/IPython/core/async_helpers.py +0 -155
  9. openalex_env_map/lib/python3.10/site-packages/IPython/core/autocall.py +0 -70
  10. openalex_env_map/lib/python3.10/site-packages/IPython/core/builtin_trap.py +0 -86
  11. openalex_env_map/lib/python3.10/site-packages/IPython/core/compilerop.py +0 -214
  12. openalex_env_map/lib/python3.10/site-packages/IPython/core/completer.py +0 -0
  13. openalex_env_map/lib/python3.10/site-packages/IPython/core/completerlib.py +0 -382
  14. openalex_env_map/lib/python3.10/site-packages/IPython/core/crashhandler.py +0 -248
  15. openalex_env_map/lib/python3.10/site-packages/IPython/core/debugger.py +0 -1136
  16. openalex_env_map/lib/python3.10/site-packages/IPython/core/display.py +0 -1373
  17. openalex_env_map/lib/python3.10/site-packages/IPython/core/display_functions.py +0 -391
  18. openalex_env_map/lib/python3.10/site-packages/IPython/core/display_trap.py +0 -70
  19. openalex_env_map/lib/python3.10/site-packages/IPython/core/displayhook.py +0 -336
  20. openalex_env_map/lib/python3.10/site-packages/IPython/core/displaypub.py +0 -149
  21. openalex_env_map/lib/python3.10/site-packages/IPython/core/error.py +0 -60
  22. openalex_env_map/lib/python3.10/site-packages/IPython/core/events.py +0 -158
  23. openalex_env_map/lib/python3.10/site-packages/IPython/core/excolors.py +0 -192
  24. openalex_env_map/lib/python3.10/site-packages/IPython/core/extensions.py +0 -135
  25. openalex_env_map/lib/python3.10/site-packages/IPython/core/formatters.py +0 -1090
  26. openalex_env_map/lib/python3.10/site-packages/IPython/core/getipython.py +0 -24
  27. openalex_env_map/lib/python3.10/site-packages/IPython/core/guarded_eval.py +0 -895
  28. openalex_env_map/lib/python3.10/site-packages/IPython/core/history.py +0 -989
  29. openalex_env_map/lib/python3.10/site-packages/IPython/core/historyapp.py +0 -158
  30. openalex_env_map/lib/python3.10/site-packages/IPython/core/hooks.py +0 -173
  31. openalex_env_map/lib/python3.10/site-packages/IPython/core/inputsplitter.py +0 -799
  32. openalex_env_map/lib/python3.10/site-packages/IPython/core/inputtransformer.py +0 -577
  33. openalex_env_map/lib/python3.10/site-packages/IPython/core/inputtransformer2.py +0 -830
  34. openalex_env_map/lib/python3.10/site-packages/IPython/core/interactiveshell.py +0 -0
  35. openalex_env_map/lib/python3.10/site-packages/IPython/core/latex_symbols.py +0 -1301
  36. openalex_env_map/lib/python3.10/site-packages/IPython/core/logger.py +0 -231
  37. openalex_env_map/lib/python3.10/site-packages/IPython/core/macro.py +0 -53
  38. openalex_env_map/lib/python3.10/site-packages/IPython/core/magic.py +0 -759
  39. openalex_env_map/lib/python3.10/site-packages/IPython/core/magic_arguments.py +0 -310
  40. openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/__init__.py +0 -42
  41. openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/ast_mod.py +0 -330
  42. openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/auto.py +0 -144
  43. openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/basic.py +0 -666
  44. openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/code.py +0 -757
  45. openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/config.py +0 -140
  46. openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/display.py +0 -93
  47. openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/execution.py +0 -1624
  48. openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/extension.py +0 -63
  49. openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/history.py +0 -338
  50. openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/logging.py +0 -195
openalex_env_map/lib/python3.10/site-packages/IPython/__init__.py DELETED
@@ -1,163 +0,0 @@
1
- # PYTHON_ARGCOMPLETE_OK
2
- """
3
- IPython: tools for interactive and parallel computing in Python.
4
-
5
- https://ipython.org
6
- """
7
- #-----------------------------------------------------------------------------
8
- # Copyright (c) 2008-2011, IPython Development Team.
9
- # Copyright (c) 2001-2007, Fernando Perez <[email protected]>
10
- # Copyright (c) 2001, Janko Hauser <[email protected]>
11
- # Copyright (c) 2001, Nathaniel Gray <[email protected]>
12
- #
13
- # Distributed under the terms of the Modified BSD License.
14
- #
15
- # The full license is in the file COPYING.txt, distributed with this software.
16
- #-----------------------------------------------------------------------------
17
-
18
- #-----------------------------------------------------------------------------
19
- # Imports
20
- #-----------------------------------------------------------------------------
21
-
22
- import sys
23
-
24
- #-----------------------------------------------------------------------------
25
- # Setup everything
26
- #-----------------------------------------------------------------------------
27
-
28
- # Don't forget to also update setup.py when this changes!
29
- if sys.version_info < (3, 10):
30
- raise ImportError(
31
- """
32
- IPython 8.19+ supports Python 3.10 and above, following SPEC0.
33
- IPython 8.13+ supports Python 3.9 and above, following NEP 29.
34
- IPython 8.0-8.12 supports Python 3.8 and above, following NEP 29.
35
- When using Python 2.7, please install IPython 5.x LTS Long Term Support version.
36
- Python 3.3 and 3.4 were supported up to IPython 6.x.
37
- Python 3.5 was supported with IPython 7.0 to 7.9.
38
- Python 3.6 was supported with IPython up to 7.16.
39
- Python 3.7 was still supported with the 7.x branch.
40
-
41
- See IPython `README.rst` file for more information:
42
-
43
- https://github.com/ipython/ipython/blob/main/README.rst
44
-
45
- """
46
- )
47
-
48
- #-----------------------------------------------------------------------------
49
- # Setup the top level names
50
- #-----------------------------------------------------------------------------
51
-
52
- from .core.getipython import get_ipython
53
- from .core import release
54
- from .core.application import Application
55
- from .terminal.embed import embed
56
-
57
- from .core.interactiveshell import InteractiveShell
58
- from .utils.sysinfo import sys_info
59
- from .utils.frame import extract_module_locals
60
-
61
- __all__ = ["start_ipython", "embed", "start_kernel", "embed_kernel"]
62
-
63
- # Release data
64
- __author__ = '%s <%s>' % (release.author, release.author_email)
65
- __license__ = release.license
66
- __version__ = release.version
67
- version_info = release.version_info
68
- # list of CVEs that should have been patched in this release.
69
- # this is informational and should not be relied upon.
70
- __patched_cves__ = {"CVE-2022-21699", "CVE-2023-24816"}
71
-
72
-
73
- def embed_kernel(module=None, local_ns=None, **kwargs):
74
- """Embed and start an IPython kernel in a given scope.
75
-
76
- If you don't want the kernel to initialize the namespace
77
- from the scope of the surrounding function,
78
- and/or you want to load full IPython configuration,
79
- you probably want `IPython.start_kernel()` instead.
80
-
81
- Parameters
82
- ----------
83
- module : types.ModuleType, optional
84
- The module to load into IPython globals (default: caller)
85
- local_ns : dict, optional
86
- The namespace to load into IPython user namespace (default: caller)
87
- **kwargs : various, optional
88
- Further keyword args are relayed to the IPKernelApp constructor,
89
- such as `config`, a traitlets :class:`Config` object (see :ref:`configure_start_ipython`),
90
- allowing configuration of the kernel (see :ref:`kernel_options`). Will only have an effect
91
- on the first embed_kernel call for a given process.
92
- """
93
-
94
- (caller_module, caller_locals) = extract_module_locals(1)
95
- if module is None:
96
- module = caller_module
97
- if local_ns is None:
98
- local_ns = caller_locals
99
-
100
- # Only import .zmq when we really need it
101
- from ipykernel.embed import embed_kernel as real_embed_kernel
102
- real_embed_kernel(module=module, local_ns=local_ns, **kwargs)
103
-
104
- def start_ipython(argv=None, **kwargs):
105
- """Launch a normal IPython instance (as opposed to embedded)
106
-
107
- `IPython.embed()` puts a shell in a particular calling scope,
108
- such as a function or method for debugging purposes,
109
- which is often not desirable.
110
-
111
- `start_ipython()` does full, regular IPython initialization,
112
- including loading startup files, configuration, etc.
113
- much of which is skipped by `embed()`.
114
-
115
- This is a public API method, and will survive implementation changes.
116
-
117
- Parameters
118
- ----------
119
- argv : list or None, optional
120
- If unspecified or None, IPython will parse command-line options from sys.argv.
121
- To prevent any command-line parsing, pass an empty list: `argv=[]`.
122
- user_ns : dict, optional
123
- specify this dictionary to initialize the IPython user namespace with particular values.
124
- **kwargs : various, optional
125
- Any other kwargs will be passed to the Application constructor,
126
- such as `config`, a traitlets :class:`Config` object (see :ref:`configure_start_ipython`),
127
- allowing configuration of the instance (see :ref:`terminal_options`).
128
- """
129
- from IPython.terminal.ipapp import launch_new_instance
130
- return launch_new_instance(argv=argv, **kwargs)
131
-
132
- def start_kernel(argv=None, **kwargs):
133
- """Launch a normal IPython kernel instance (as opposed to embedded)
134
-
135
- `IPython.embed_kernel()` puts a shell in a particular calling scope,
136
- such as a function or method for debugging purposes,
137
- which is often not desirable.
138
-
139
- `start_kernel()` does full, regular IPython initialization,
140
- including loading startup files, configuration, etc.
141
- much of which is skipped by `embed_kernel()`.
142
-
143
- Parameters
144
- ----------
145
- argv : list or None, optional
146
- If unspecified or None, IPython will parse command-line options from sys.argv.
147
- To prevent any command-line parsing, pass an empty list: `argv=[]`.
148
- user_ns : dict, optional
149
- specify this dictionary to initialize the IPython user namespace with particular values.
150
- **kwargs : various, optional
151
- Any other kwargs will be passed to the Application constructor,
152
- such as `config`, a traitlets :class:`Config` object (see :ref:`configure_start_ipython`),
153
- allowing configuration of the kernel (see :ref:`kernel_options`).
154
- """
155
- import warnings
156
-
157
- warnings.warn(
158
- "start_kernel is deprecated since IPython 8.0, use from `ipykernel.kernelapp.launch_new_instance`",
159
- DeprecationWarning,
160
- stacklevel=2,
161
- )
162
- from ipykernel.kernelapp import launch_new_instance
163
- return launch_new_instance(argv=argv, **kwargs)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/__main__.py DELETED
@@ -1,15 +0,0 @@
1
- # PYTHON_ARGCOMPLETE_OK
2
- # encoding: utf-8
3
- """Terminal-based IPython entry point.
4
- """
5
- # -----------------------------------------------------------------------------
6
- # Copyright (c) 2012, IPython Development Team.
7
- #
8
- # Distributed under the terms of the Modified BSD License.
9
- #
10
- # The full license is in the file COPYING.txt, distributed with this software.
11
- # -----------------------------------------------------------------------------
12
-
13
- from IPython import start_ipython
14
-
15
- start_ipython()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/conftest.py DELETED
@@ -1,87 +0,0 @@
1
- import builtins
2
- import inspect
3
- import os
4
- import pathlib
5
- import shutil
6
- import sys
7
- import types
8
-
9
- import pytest
10
-
11
- # Must register before it gets imported
12
- pytest.register_assert_rewrite("IPython.testing.tools")
13
-
14
- from .testing import tools
15
-
16
-
17
- def pytest_collection_modifyitems(items):
18
- """This function is automatically run by pytest passing all collected test
19
- functions.
20
-
21
- We use it to add asyncio marker to all async tests and assert we don't use
22
- test functions that are async generators which wouldn't make sense.
23
- """
24
- for item in items:
25
- if inspect.iscoroutinefunction(item.obj):
26
- item.add_marker("asyncio")
27
- assert not inspect.isasyncgenfunction(item.obj)
28
-
29
-
30
- def get_ipython():
31
- from .terminal.interactiveshell import TerminalInteractiveShell
32
- if TerminalInteractiveShell._instance:
33
- return TerminalInteractiveShell.instance()
34
-
35
- config = tools.default_config()
36
- config.TerminalInteractiveShell.simple_prompt = True
37
-
38
- # Create and initialize our test-friendly IPython instance.
39
- shell = TerminalInteractiveShell.instance(config=config)
40
- return shell
41
-
42
-
43
- @pytest.fixture(scope='session', autouse=True)
44
- def work_path():
45
- path = pathlib.Path("./tmp-ipython-pytest-profiledir")
46
- os.environ["IPYTHONDIR"] = str(path.absolute())
47
- if path.exists():
48
- raise ValueError('IPython dir temporary path already exists ! Did previous test run exit successfully ?')
49
- path.mkdir()
50
- yield
51
- shutil.rmtree(str(path.resolve()))
52
-
53
-
54
- def nopage(strng, start=0, screen_lines=0, pager_cmd=None):
55
- if isinstance(strng, dict):
56
- strng = strng.get("text/plain", "")
57
- print(strng)
58
-
59
-
60
- def xsys(self, cmd):
61
- """Replace the default system call with a capturing one for doctest.
62
- """
63
- # We use getoutput, but we need to strip it because pexpect captures
64
- # the trailing newline differently from commands.getoutput
65
- print(self.getoutput(cmd, split=False, depth=1).rstrip(), end="", file=sys.stdout)
66
- sys.stdout.flush()
67
-
68
-
69
- # for things to work correctly we would need this as a session fixture;
70
- # unfortunately this will fail on some test that get executed as _collection_
71
- # time (before the fixture run), in particular parametrized test that contain
72
- # yields. so for now execute at import time.
73
- #@pytest.fixture(autouse=True, scope='session')
74
- def inject():
75
-
76
- builtins.get_ipython = get_ipython
77
- builtins._ip = get_ipython()
78
- builtins.ip = get_ipython()
79
- builtins.ip.system = types.MethodType(xsys, ip)
80
- builtins.ip.builtin_trap.activate()
81
- from .core import page
82
-
83
- page.pager_page = nopage
84
- # yield
85
-
86
-
87
- inject()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/consoleapp.py DELETED
@@ -1,12 +0,0 @@
1
- """
2
- Shim to maintain backwards compatibility with old IPython.consoleapp imports.
3
- """
4
- # Copyright (c) IPython Development Team.
5
- # Distributed under the terms of the Modified BSD License.
6
-
7
- from warnings import warn
8
-
9
- warn("The `IPython.consoleapp` package has been deprecated since IPython 4.0."
10
- "You should import from jupyter_client.consoleapp instead.", stacklevel=2)
11
-
12
- from jupyter_client.consoleapp import *
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/__init__.py DELETED
File without changes
openalex_env_map/lib/python3.10/site-packages/IPython/core/alias.py DELETED
@@ -1,267 +0,0 @@
1
- # encoding: utf-8
2
- """
3
- System command aliases.
4
-
5
- Authors:
6
-
7
- * Fernando Perez
8
- * Brian Granger
9
- """
10
-
11
- #-----------------------------------------------------------------------------
12
- # Copyright (C) 2008-2011 The IPython Development Team
13
- #
14
- # Distributed under the terms of the BSD License.
15
- #
16
- # The full license is in the file COPYING.txt, distributed with this software.
17
- #-----------------------------------------------------------------------------
18
-
19
- #-----------------------------------------------------------------------------
20
- # Imports
21
- #-----------------------------------------------------------------------------
22
-
23
- import os
24
- import re
25
- import sys
26
-
27
- from traitlets.config.configurable import Configurable
28
- from .error import UsageError
29
-
30
- from traitlets import List, Instance
31
- from logging import error
32
-
33
- import typing as t
34
-
35
-
36
- #-----------------------------------------------------------------------------
37
- # Utilities
38
- #-----------------------------------------------------------------------------
39
-
40
- # This is used as the pattern for calls to split_user_input.
41
- shell_line_split = re.compile(r'^(\s*)()(\S+)(.*$)')
42
-
43
- def default_aliases() -> t.List[t.Tuple[str, str]]:
44
- """Return list of shell aliases to auto-define.
45
- """
46
- # Note: the aliases defined here should be safe to use on a kernel
47
- # regardless of what frontend it is attached to. Frontends that use a
48
- # kernel in-process can define additional aliases that will only work in
49
- # their case. For example, things like 'less' or 'clear' that manipulate
50
- # the terminal should NOT be declared here, as they will only work if the
51
- # kernel is running inside a true terminal, and not over the network.
52
-
53
- if os.name == 'posix':
54
- default_aliases = [('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
55
- ('mv', 'mv'), ('rm', 'rm'), ('cp', 'cp'),
56
- ('cat', 'cat'),
57
- ]
58
- # Useful set of ls aliases. The GNU and BSD options are a little
59
- # different, so we make aliases that provide as similar as possible
60
- # behavior in ipython, by passing the right flags for each platform
61
- if sys.platform.startswith('linux'):
62
- ls_aliases = [('ls', 'ls -F --color'),
63
- # long ls
64
- ('ll', 'ls -F -o --color'),
65
- # ls normal files only
66
- ('lf', 'ls -F -o --color %l | grep ^-'),
67
- # ls symbolic links
68
- ('lk', 'ls -F -o --color %l | grep ^l'),
69
- # directories or links to directories,
70
- ('ldir', 'ls -F -o --color %l | grep /$'),
71
- # things which are executable
72
- ('lx', 'ls -F -o --color %l | grep ^-..x'),
73
- ]
74
- elif sys.platform.startswith('openbsd') or sys.platform.startswith('netbsd'):
75
- # OpenBSD, NetBSD. The ls implementation on these platforms do not support
76
- # the -G switch and lack the ability to use colorized output.
77
- ls_aliases = [('ls', 'ls -F'),
78
- # long ls
79
- ('ll', 'ls -F -l'),
80
- # ls normal files only
81
- ('lf', 'ls -F -l %l | grep ^-'),
82
- # ls symbolic links
83
- ('lk', 'ls -F -l %l | grep ^l'),
84
- # directories or links to directories,
85
- ('ldir', 'ls -F -l %l | grep /$'),
86
- # things which are executable
87
- ('lx', 'ls -F -l %l | grep ^-..x'),
88
- ]
89
- else:
90
- # BSD, OSX, etc.
91
- ls_aliases = [('ls', 'ls -F -G'),
92
- # long ls
93
- ('ll', 'ls -F -l -G'),
94
- # ls normal files only
95
- ('lf', 'ls -F -l -G %l | grep ^-'),
96
- # ls symbolic links
97
- ('lk', 'ls -F -l -G %l | grep ^l'),
98
- # directories or links to directories,
99
- ('ldir', 'ls -F -G -l %l | grep /$'),
100
- # things which are executable
101
- ('lx', 'ls -F -l -G %l | grep ^-..x'),
102
- ]
103
- default_aliases = default_aliases + ls_aliases
104
- elif os.name in ['nt', 'dos']:
105
- default_aliases = [('ls', 'dir /on'),
106
- ('ddir', 'dir /ad /on'), ('ldir', 'dir /ad /on'),
107
- ('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
108
- ('echo', 'echo'), ('ren', 'ren'), ('copy', 'copy'),
109
- ]
110
- else:
111
- default_aliases = []
112
-
113
- return default_aliases
114
-
115
-
116
- class AliasError(Exception):
117
- pass
118
-
119
-
120
- class InvalidAliasError(AliasError):
121
- pass
122
-
123
- class Alias(object):
124
- """Callable object storing the details of one alias.
125
-
126
- Instances are registered as magic functions to allow use of aliases.
127
- """
128
-
129
- # Prepare blacklist
130
- blacklist = {'cd','popd','pushd','dhist','alias','unalias'}
131
-
132
- def __init__(self, shell, name, cmd):
133
- self.shell = shell
134
- self.name = name
135
- self.cmd = cmd
136
- self.__doc__ = "Alias for `!{}`".format(cmd)
137
- self.nargs = self.validate()
138
-
139
- def validate(self):
140
- """Validate the alias, and return the number of arguments."""
141
- if self.name in self.blacklist:
142
- raise InvalidAliasError("The name %s can't be aliased "
143
- "because it is a keyword or builtin." % self.name)
144
- try:
145
- caller = self.shell.magics_manager.magics['line'][self.name]
146
- except KeyError:
147
- pass
148
- else:
149
- if not isinstance(caller, Alias):
150
- raise InvalidAliasError("The name %s can't be aliased "
151
- "because it is another magic command." % self.name)
152
-
153
- if not (isinstance(self.cmd, str)):
154
- raise InvalidAliasError("An alias command must be a string, "
155
- "got: %r" % self.cmd)
156
-
157
- nargs = self.cmd.count('%s') - self.cmd.count('%%s')
158
-
159
- if (nargs > 0) and (self.cmd.find('%l') >= 0):
160
- raise InvalidAliasError('The %s and %l specifiers are mutually '
161
- 'exclusive in alias definitions.')
162
-
163
- return nargs
164
-
165
- def __repr__(self):
166
- return "<alias {} for {!r}>".format(self.name, self.cmd)
167
-
168
- def __call__(self, rest=''):
169
- cmd = self.cmd
170
- nargs = self.nargs
171
- # Expand the %l special to be the user's input line
172
- if cmd.find('%l') >= 0:
173
- cmd = cmd.replace('%l', rest)
174
- rest = ''
175
-
176
- if nargs==0:
177
- if cmd.find('%%s') >= 1:
178
- cmd = cmd.replace('%%s', '%s')
179
- # Simple, argument-less aliases
180
- cmd = '%s %s' % (cmd, rest)
181
- else:
182
- # Handle aliases with positional arguments
183
- args = rest.split(None, nargs)
184
- if len(args) < nargs:
185
- raise UsageError('Alias <%s> requires %s arguments, %s given.' %
186
- (self.name, nargs, len(args)))
187
- cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
188
-
189
- self.shell.system(cmd)
190
-
191
- #-----------------------------------------------------------------------------
192
- # Main AliasManager class
193
- #-----------------------------------------------------------------------------
194
-
195
- class AliasManager(Configurable):
196
- default_aliases: List = List(default_aliases()).tag(config=True)
197
- user_aliases: List = List(default_value=[]).tag(config=True)
198
- shell = Instance(
199
- "IPython.core.interactiveshell.InteractiveShellABC", allow_none=True
200
- )
201
-
202
- def __init__(self, shell=None, **kwargs):
203
- super(AliasManager, self).__init__(shell=shell, **kwargs)
204
- # For convenient access
205
- if self.shell is not None:
206
- self.linemagics = self.shell.magics_manager.magics["line"]
207
- self.init_aliases()
208
-
209
- def init_aliases(self):
210
- # Load default & user aliases
211
- for name, cmd in self.default_aliases + self.user_aliases:
212
- if (
213
- cmd.startswith("ls ")
214
- and self.shell is not None
215
- and self.shell.colors == "NoColor"
216
- ):
217
- cmd = cmd.replace(" --color", "")
218
- self.soft_define_alias(name, cmd)
219
-
220
- @property
221
- def aliases(self):
222
- return [(n, func.cmd) for (n, func) in self.linemagics.items()
223
- if isinstance(func, Alias)]
224
-
225
- def soft_define_alias(self, name, cmd):
226
- """Define an alias, but don't raise on an AliasError."""
227
- try:
228
- self.define_alias(name, cmd)
229
- except AliasError as e:
230
- error("Invalid alias: %s" % e)
231
-
232
- def define_alias(self, name, cmd):
233
- """Define a new alias after validating it.
234
-
235
- This will raise an :exc:`AliasError` if there are validation
236
- problems.
237
- """
238
- caller = Alias(shell=self.shell, name=name, cmd=cmd)
239
- self.shell.magics_manager.register_function(caller, magic_kind='line',
240
- magic_name=name)
241
-
242
- def get_alias(self, name):
243
- """Return an alias, or None if no alias by that name exists."""
244
- aname = self.linemagics.get(name, None)
245
- return aname if isinstance(aname, Alias) else None
246
-
247
- def is_alias(self, name):
248
- """Return whether or not a given name has been defined as an alias"""
249
- return self.get_alias(name) is not None
250
-
251
- def undefine_alias(self, name):
252
- if self.is_alias(name):
253
- del self.linemagics[name]
254
- else:
255
- raise ValueError('%s is not an alias' % name)
256
-
257
- def clear_aliases(self):
258
- for name, _ in self.aliases:
259
- self.undefine_alias(name)
260
-
261
- def retrieve_alias(self, name):
262
- """Retrieve the command to which an alias expands."""
263
- caller = self.get_alias(name)
264
- if caller:
265
- return caller.cmd
266
- else:
267
- raise ValueError('%s is not an alias' % name)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/application.py DELETED
@@ -1,492 +0,0 @@
1
- # encoding: utf-8
2
- """
3
- An application for IPython.
4
-
5
- All top-level applications should use the classes in this module for
6
- handling configuration and creating configurables.
7
-
8
- The job of an :class:`Application` is to create the master configuration
9
- object and then create the configurable objects, passing the config to them.
10
- """
11
-
12
- # Copyright (c) IPython Development Team.
13
- # Distributed under the terms of the Modified BSD License.
14
-
15
- import atexit
16
- from copy import deepcopy
17
- import logging
18
- import os
19
- import shutil
20
- import sys
21
-
22
- from pathlib import Path
23
-
24
- from traitlets.config.application import Application, catch_config_error
25
- from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader
26
- from IPython.core import release, crashhandler
27
- from IPython.core.profiledir import ProfileDir, ProfileDirError
28
- from IPython.paths import get_ipython_dir, get_ipython_package_dir
29
- from IPython.utils.path import ensure_dir_exists
30
- from traitlets import (
31
- List, Unicode, Type, Bool, Set, Instance, Undefined,
32
- default, observe,
33
- )
34
-
35
- if os.name == "nt":
36
- programdata = os.environ.get("PROGRAMDATA", None)
37
- if programdata is not None:
38
- SYSTEM_CONFIG_DIRS = [str(Path(programdata) / "ipython")]
39
- else: # PROGRAMDATA is not defined by default on XP.
40
- SYSTEM_CONFIG_DIRS = []
41
- else:
42
- SYSTEM_CONFIG_DIRS = [
43
- "/usr/local/etc/ipython",
44
- "/etc/ipython",
45
- ]
46
-
47
-
48
- ENV_CONFIG_DIRS = []
49
- _env_config_dir = os.path.join(sys.prefix, 'etc', 'ipython')
50
- if _env_config_dir not in SYSTEM_CONFIG_DIRS:
51
- # only add ENV_CONFIG if sys.prefix is not already included
52
- ENV_CONFIG_DIRS.append(_env_config_dir)
53
-
54
-
55
- _envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS')
56
- if _envvar in {None, ''}:
57
- IPYTHON_SUPPRESS_CONFIG_ERRORS = None
58
- else:
59
- if _envvar.lower() in {'1','true'}:
60
- IPYTHON_SUPPRESS_CONFIG_ERRORS = True
61
- elif _envvar.lower() in {'0','false'} :
62
- IPYTHON_SUPPRESS_CONFIG_ERRORS = False
63
- else:
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
-
66
- # aliases and flags
67
-
68
- base_aliases = {}
69
- if isinstance(Application.aliases, dict):
70
- # traitlets 5
71
- base_aliases.update(Application.aliases)
72
- base_aliases.update(
73
- {
74
- "profile-dir": "ProfileDir.location",
75
- "profile": "BaseIPythonApplication.profile",
76
- "ipython-dir": "BaseIPythonApplication.ipython_dir",
77
- "log-level": "Application.log_level",
78
- "config": "BaseIPythonApplication.extra_config_file",
79
- }
80
- )
81
-
82
- base_flags = dict()
83
- if isinstance(Application.flags, dict):
84
- # traitlets 5
85
- base_flags.update(Application.flags)
86
- base_flags.update(
87
- dict(
88
- debug=(
89
- {"Application": {"log_level": logging.DEBUG}},
90
- "set log level to logging.DEBUG (maximize logging output)",
91
- ),
92
- quiet=(
93
- {"Application": {"log_level": logging.CRITICAL}},
94
- "set log level to logging.CRITICAL (minimize logging output)",
95
- ),
96
- init=(
97
- {
98
- "BaseIPythonApplication": {
99
- "copy_config_files": True,
100
- "auto_create": True,
101
- }
102
- },
103
- """Initialize profile with default config files. This is equivalent
104
- to running `ipython profile create <profile>` prior to startup.
105
- """,
106
- ),
107
- )
108
- )
109
-
110
-
111
- class ProfileAwareConfigLoader(PyFileConfigLoader):
112
- """A Python file config loader that is aware of IPython profiles."""
113
- def load_subconfig(self, fname, path=None, profile=None):
114
- if profile is not None:
115
- try:
116
- profile_dir = ProfileDir.find_profile_dir_by_name(
117
- get_ipython_dir(),
118
- profile,
119
- )
120
- except ProfileDirError:
121
- return
122
- path = profile_dir.location
123
- return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
124
-
125
- class BaseIPythonApplication(Application):
126
- name = "ipython"
127
- description = "IPython: an enhanced interactive Python shell."
128
- version = Unicode(release.version)
129
-
130
- aliases = base_aliases
131
- flags = base_flags
132
- classes = List([ProfileDir])
133
-
134
- # enable `load_subconfig('cfg.py', profile='name')`
135
- python_config_loader_class = ProfileAwareConfigLoader
136
-
137
- # Track whether the config_file has changed,
138
- # because some logic happens only if we aren't using the default.
139
- config_file_specified = Set()
140
-
141
- config_file_name = Unicode()
142
- @default('config_file_name')
143
- def _config_file_name_default(self):
144
- return self.name.replace('-','_') + u'_config.py'
145
- @observe('config_file_name')
146
- def _config_file_name_changed(self, change):
147
- if change['new'] != change['old']:
148
- self.config_file_specified.add(change['new'])
149
-
150
- # The directory that contains IPython's builtin profiles.
151
- builtin_profile_dir = Unicode(
152
- os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
153
- )
154
-
155
- config_file_paths = List(Unicode())
156
- @default('config_file_paths')
157
- def _config_file_paths_default(self):
158
- return []
159
-
160
- extra_config_file = Unicode(
161
- help="""Path to an extra config file to load.
162
-
163
- If specified, load this config file in addition to any other IPython config.
164
- """).tag(config=True)
165
- @observe('extra_config_file')
166
- def _extra_config_file_changed(self, change):
167
- old = change['old']
168
- new = change['new']
169
- try:
170
- self.config_files.remove(old)
171
- except ValueError:
172
- pass
173
- self.config_file_specified.add(new)
174
- self.config_files.append(new)
175
-
176
- profile = Unicode(u'default',
177
- help="""The IPython profile to use."""
178
- ).tag(config=True)
179
-
180
- @observe('profile')
181
- def _profile_changed(self, change):
182
- self.builtin_profile_dir = os.path.join(
183
- get_ipython_package_dir(), u'config', u'profile', change['new']
184
- )
185
-
186
- add_ipython_dir_to_sys_path = Bool(
187
- False,
188
- """Should the IPython profile directory be added to sys path ?
189
-
190
- This option was non-existing before IPython 8.0, and ipython_dir was added to
191
- sys path to allow import of extensions present there. This was historical
192
- baggage from when pip did not exist. This now default to false,
193
- but can be set to true for legacy reasons.
194
- """,
195
- ).tag(config=True)
196
-
197
- ipython_dir = Unicode(
198
- help="""
199
- The name of the IPython directory. This directory is used for logging
200
- configuration (through profiles), history storage, etc. The default
201
- is usually $HOME/.ipython. This option can also be specified through
202
- the environment variable IPYTHONDIR.
203
- """
204
- ).tag(config=True)
205
- @default('ipython_dir')
206
- def _ipython_dir_default(self):
207
- d = get_ipython_dir()
208
- self._ipython_dir_changed({
209
- 'name': 'ipython_dir',
210
- 'old': d,
211
- 'new': d,
212
- })
213
- return d
214
-
215
- _in_init_profile_dir = False
216
-
217
- profile_dir = Instance(ProfileDir, allow_none=True)
218
-
219
- @default('profile_dir')
220
- def _profile_dir_default(self):
221
- # avoid recursion
222
- if self._in_init_profile_dir:
223
- return
224
- # profile_dir requested early, force initialization
225
- self.init_profile_dir()
226
- return self.profile_dir
227
-
228
- overwrite = Bool(False,
229
- help="""Whether to overwrite existing config files when copying"""
230
- ).tag(config=True)
231
-
232
- auto_create = Bool(False,
233
- help="""Whether to create profile dir if it doesn't exist"""
234
- ).tag(config=True)
235
-
236
- config_files = List(Unicode())
237
-
238
- @default('config_files')
239
- def _config_files_default(self):
240
- return [self.config_file_name]
241
-
242
- copy_config_files = Bool(False,
243
- help="""Whether to install the default config files into the profile dir.
244
- If a new profile is being created, and IPython contains config files for that
245
- profile, then they will be staged into the new directory. Otherwise,
246
- default config files will be automatically generated.
247
- """).tag(config=True)
248
-
249
- verbose_crash = Bool(False,
250
- help="""Create a massive crash report when IPython encounters what may be an
251
- internal error. The default is to append a short message to the
252
- usual traceback""").tag(config=True)
253
-
254
- # The class to use as the crash handler.
255
- crash_handler_class = Type(crashhandler.CrashHandler)
256
-
257
- @catch_config_error
258
- def __init__(self, **kwargs):
259
- super(BaseIPythonApplication, self).__init__(**kwargs)
260
- # ensure current working directory exists
261
- try:
262
- os.getcwd()
263
- except:
264
- # exit if cwd doesn't exist
265
- self.log.error("Current working directory doesn't exist.")
266
- self.exit(1)
267
-
268
- #-------------------------------------------------------------------------
269
- # Various stages of Application creation
270
- #-------------------------------------------------------------------------
271
-
272
- def init_crash_handler(self):
273
- """Create a crash handler, typically setting sys.excepthook to it."""
274
- self.crash_handler = self.crash_handler_class(self)
275
- sys.excepthook = self.excepthook
276
- def unset_crashhandler():
277
- sys.excepthook = sys.__excepthook__
278
- atexit.register(unset_crashhandler)
279
-
280
- def excepthook(self, etype, evalue, tb):
281
- """this is sys.excepthook after init_crashhandler
282
-
283
- set self.verbose_crash=True to use our full crashhandler, instead of
284
- a regular traceback with a short message (crash_handler_lite)
285
- """
286
-
287
- if self.verbose_crash:
288
- return self.crash_handler(etype, evalue, tb)
289
- else:
290
- return crashhandler.crash_handler_lite(etype, evalue, tb)
291
-
292
- @observe('ipython_dir')
293
- def _ipython_dir_changed(self, change):
294
- old = change['old']
295
- new = change['new']
296
- if old is not Undefined:
297
- str_old = os.path.abspath(old)
298
- if str_old in sys.path:
299
- sys.path.remove(str_old)
300
- if self.add_ipython_dir_to_sys_path:
301
- str_path = os.path.abspath(new)
302
- sys.path.append(str_path)
303
- ensure_dir_exists(new)
304
- readme = os.path.join(new, "README")
305
- readme_src = os.path.join(
306
- get_ipython_package_dir(), "config", "profile", "README"
307
- )
308
- if not os.path.exists(readme) and os.path.exists(readme_src):
309
- shutil.copy(readme_src, readme)
310
- for d in ("extensions", "nbextensions"):
311
- path = os.path.join(new, d)
312
- try:
313
- ensure_dir_exists(path)
314
- except OSError as e:
315
- # this will not be EEXIST
316
- self.log.error("couldn't create path %s: %s", path, e)
317
- self.log.debug("IPYTHONDIR set to: %s", new)
318
-
319
- def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
320
- """Load the config file.
321
-
322
- By default, errors in loading config are handled, and a warning
323
- printed on screen. For testing, the suppress_errors option is set
324
- to False, so errors will make tests fail.
325
-
326
- `suppress_errors` default value is to be `None` in which case the
327
- behavior default to the one of `traitlets.Application`.
328
-
329
- The default value can be set :
330
- - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive).
331
- - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive).
332
- - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset.
333
-
334
- Any other value are invalid, and will make IPython exit with a non-zero return code.
335
- """
336
-
337
-
338
- self.log.debug("Searching path %s for config files", self.config_file_paths)
339
- base_config = 'ipython_config.py'
340
- self.log.debug("Attempting to load config file: %s" %
341
- base_config)
342
- try:
343
- if suppress_errors is not None:
344
- old_value = Application.raise_config_file_errors
345
- Application.raise_config_file_errors = not suppress_errors;
346
- Application.load_config_file(
347
- self,
348
- base_config,
349
- path=self.config_file_paths
350
- )
351
- except ConfigFileNotFound:
352
- # ignore errors loading parent
353
- self.log.debug("Config file %s not found", base_config)
354
- pass
355
- if suppress_errors is not None:
356
- Application.raise_config_file_errors = old_value
357
-
358
- for config_file_name in self.config_files:
359
- if not config_file_name or config_file_name == base_config:
360
- continue
361
- self.log.debug("Attempting to load config file: %s" %
362
- self.config_file_name)
363
- try:
364
- Application.load_config_file(
365
- self,
366
- config_file_name,
367
- path=self.config_file_paths
368
- )
369
- except ConfigFileNotFound:
370
- # Only warn if the default config file was NOT being used.
371
- if config_file_name in self.config_file_specified:
372
- msg = self.log.warning
373
- else:
374
- msg = self.log.debug
375
- msg("Config file not found, skipping: %s", config_file_name)
376
- except Exception:
377
- # For testing purposes.
378
- if not suppress_errors:
379
- raise
380
- self.log.warning("Error loading config file: %s" %
381
- self.config_file_name, exc_info=True)
382
-
383
- def init_profile_dir(self):
384
- """initialize the profile dir"""
385
- self._in_init_profile_dir = True
386
- if self.profile_dir is not None:
387
- # already ran
388
- return
389
- if 'ProfileDir.location' not in self.config:
390
- # location not specified, find by profile name
391
- try:
392
- p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
393
- except ProfileDirError:
394
- # not found, maybe create it (always create default profile)
395
- if self.auto_create or self.profile == 'default':
396
- try:
397
- p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
398
- except ProfileDirError:
399
- self.log.fatal("Could not create profile: %r"%self.profile)
400
- self.exit(1)
401
- else:
402
- self.log.info("Created profile dir: %r"%p.location)
403
- else:
404
- self.log.fatal("Profile %r not found."%self.profile)
405
- self.exit(1)
406
- else:
407
- self.log.debug("Using existing profile dir: %r", p.location)
408
- else:
409
- location = self.config.ProfileDir.location
410
- # location is fully specified
411
- try:
412
- p = ProfileDir.find_profile_dir(location, self.config)
413
- except ProfileDirError:
414
- # not found, maybe create it
415
- if self.auto_create:
416
- try:
417
- p = ProfileDir.create_profile_dir(location, self.config)
418
- except ProfileDirError:
419
- self.log.fatal("Could not create profile directory: %r"%location)
420
- self.exit(1)
421
- else:
422
- self.log.debug("Creating new profile dir: %r"%location)
423
- else:
424
- self.log.fatal("Profile directory %r not found."%location)
425
- self.exit(1)
426
- else:
427
- self.log.debug("Using existing profile dir: %r", p.location)
428
- # if profile_dir is specified explicitly, set profile name
429
- dir_name = os.path.basename(p.location)
430
- if dir_name.startswith('profile_'):
431
- self.profile = dir_name[8:]
432
-
433
- self.profile_dir = p
434
- self.config_file_paths.append(p.location)
435
- self._in_init_profile_dir = False
436
-
437
- def init_config_files(self):
438
- """[optionally] copy default config files into profile dir."""
439
- self.config_file_paths.extend(ENV_CONFIG_DIRS)
440
- self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
441
- # copy config files
442
- path = Path(self.builtin_profile_dir)
443
- if self.copy_config_files:
444
- src = self.profile
445
-
446
- cfg = self.config_file_name
447
- if path and (path / cfg).exists():
448
- self.log.warning(
449
- "Staging %r from %s into %r [overwrite=%s]"
450
- % (cfg, src, self.profile_dir.location, self.overwrite)
451
- )
452
- self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
453
- else:
454
- self.stage_default_config_file()
455
- else:
456
- # Still stage *bundled* config files, but not generated ones
457
- # This is necessary for `ipython profile=sympy` to load the profile
458
- # on the first go
459
- files = path.glob("*.py")
460
- for fullpath in files:
461
- cfg = fullpath.name
462
- if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
463
- # file was copied
464
- self.log.warning("Staging bundled %s from %s into %r"%(
465
- cfg, self.profile, self.profile_dir.location)
466
- )
467
-
468
-
469
- def stage_default_config_file(self):
470
- """auto generate default config file, and stage it into the profile."""
471
- s = self.generate_config_file()
472
- config_file = Path(self.profile_dir.location) / self.config_file_name
473
- if self.overwrite or not config_file.exists():
474
- self.log.warning("Generating default config file: %r", (config_file))
475
- config_file.write_text(s, encoding="utf-8")
476
-
477
- @catch_config_error
478
- def initialize(self, argv=None):
479
- # don't hook up crash handler before parsing command-line
480
- self.parse_command_line(argv)
481
- self.init_crash_handler()
482
- if self.subapp is not None:
483
- # stop here if subapp is taking over
484
- return
485
- # save a copy of CLI config to re-load after config files
486
- # so that it has highest priority
487
- cl_config = deepcopy(self.config)
488
- self.init_profile_dir()
489
- self.init_config_files()
490
- self.load_config_file()
491
- # enforce cl-opts override configfile opts:
492
- self.update_config(cl_config)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/async_helpers.py DELETED
@@ -1,155 +0,0 @@
1
- """
2
- Async helper function that are invalid syntax on Python 3.5 and below.
3
-
4
- This code is best effort, and may have edge cases not behaving as expected. In
5
- particular it contain a number of heuristics to detect whether code is
6
- effectively async and need to run in an event loop or not.
7
-
8
- Some constructs (like top-level `return`, or `yield`) are taken care of
9
- explicitly to actually raise a SyntaxError and stay as close as possible to
10
- Python semantics.
11
- """
12
-
13
- import ast
14
- import asyncio
15
- import inspect
16
- from functools import wraps
17
-
18
- _asyncio_event_loop = None
19
-
20
-
21
- def get_asyncio_loop():
22
- """asyncio has deprecated get_event_loop
23
-
24
- Replicate it here, with our desired semantics:
25
-
26
- - always returns a valid, not-closed loop
27
- - not thread-local like asyncio's,
28
- because we only want one loop for IPython
29
- - if called from inside a coroutine (e.g. in ipykernel),
30
- return the running loop
31
-
32
- .. versionadded:: 8.0
33
- """
34
- try:
35
- return asyncio.get_running_loop()
36
- except RuntimeError:
37
- # not inside a coroutine,
38
- # track our own global
39
- pass
40
-
41
- # not thread-local like asyncio's,
42
- # because we only track one event loop to run for IPython itself,
43
- # always in the main thread.
44
- global _asyncio_event_loop
45
- if _asyncio_event_loop is None or _asyncio_event_loop.is_closed():
46
- _asyncio_event_loop = asyncio.new_event_loop()
47
- return _asyncio_event_loop
48
-
49
-
50
- class _AsyncIORunner:
51
- def __call__(self, coro):
52
- """
53
- Handler for asyncio autoawait
54
- """
55
- return get_asyncio_loop().run_until_complete(coro)
56
-
57
- def __str__(self):
58
- return "asyncio"
59
-
60
-
61
- _asyncio_runner = _AsyncIORunner()
62
-
63
-
64
- class _AsyncIOProxy:
65
- """Proxy-object for an asyncio
66
-
67
- Any coroutine methods will be wrapped in event_loop.run_
68
- """
69
-
70
- def __init__(self, obj, event_loop):
71
- self._obj = obj
72
- self._event_loop = event_loop
73
-
74
- def __repr__(self):
75
- return f"<_AsyncIOProxy({self._obj!r})>"
76
-
77
- def __getattr__(self, key):
78
- attr = getattr(self._obj, key)
79
- if inspect.iscoroutinefunction(attr):
80
- # if it's a coroutine method,
81
- # return a threadsafe wrapper onto the _current_ asyncio loop
82
- @wraps(attr)
83
- def _wrapped(*args, **kwargs):
84
- concurrent_future = asyncio.run_coroutine_threadsafe(
85
- attr(*args, **kwargs), self._event_loop
86
- )
87
- return asyncio.wrap_future(concurrent_future)
88
-
89
- return _wrapped
90
- else:
91
- return attr
92
-
93
- def __dir__(self):
94
- return dir(self._obj)
95
-
96
-
97
- def _curio_runner(coroutine):
98
- """
99
- handler for curio autoawait
100
- """
101
- import curio
102
-
103
- return curio.run(coroutine)
104
-
105
-
106
- def _trio_runner(async_fn):
107
- import trio
108
-
109
- async def loc(coro):
110
- """
111
- We need the dummy no-op async def to protect from
112
- trio's internal. See https://github.com/python-trio/trio/issues/89
113
- """
114
- return await coro
115
-
116
- return trio.run(loc, async_fn)
117
-
118
-
119
- def _pseudo_sync_runner(coro):
120
- """
121
- A runner that does not really allow async execution, and just advance the coroutine.
122
-
123
- See discussion in https://github.com/python-trio/trio/issues/608,
124
-
125
- Credit to Nathaniel Smith
126
- """
127
- try:
128
- coro.send(None)
129
- except StopIteration as exc:
130
- return exc.value
131
- else:
132
- # TODO: do not raise but return an execution result with the right info.
133
- raise RuntimeError(
134
- "{coro_name!r} needs a real async loop".format(coro_name=coro.__name__)
135
- )
136
-
137
-
138
- def _should_be_async(cell: str) -> bool:
139
- """Detect if a block of code need to be wrapped in an `async def`
140
-
141
- Attempt to parse the block of code, it it compile we're fine.
142
- Otherwise we wrap if and try to compile.
143
-
144
- If it works, assume it should be async. Otherwise Return False.
145
-
146
- Not handled yet: If the block of code has a return statement as the top
147
- level, it will be seen as async. This is a know limitation.
148
- """
149
- try:
150
- code = compile(
151
- cell, "<>", "exec", flags=getattr(ast, "PyCF_ALLOW_TOP_LEVEL_AWAIT", 0x0)
152
- )
153
- return inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE
154
- except (SyntaxError, MemoryError):
155
- return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/autocall.py DELETED
@@ -1,70 +0,0 @@
1
- # encoding: utf-8
2
- """
3
- Autocall capabilities for IPython.core.
4
-
5
- Authors:
6
-
7
- * Brian Granger
8
- * Fernando Perez
9
- * Thomas Kluyver
10
-
11
- Notes
12
- -----
13
- """
14
-
15
- #-----------------------------------------------------------------------------
16
- # Copyright (C) 2008-2011 The IPython Development Team
17
- #
18
- # Distributed under the terms of the BSD License. The full license is in
19
- # the file COPYING, distributed as part of this software.
20
- #-----------------------------------------------------------------------------
21
-
22
- #-----------------------------------------------------------------------------
23
- # Imports
24
- #-----------------------------------------------------------------------------
25
-
26
-
27
- #-----------------------------------------------------------------------------
28
- # Code
29
- #-----------------------------------------------------------------------------
30
-
31
- class IPyAutocall(object):
32
- """ Instances of this class are always autocalled
33
-
34
- This happens regardless of 'autocall' variable state. Use this to
35
- develop macro-like mechanisms.
36
- """
37
- _ip = None
38
- rewrite = True
39
- def __init__(self, ip=None):
40
- self._ip = ip
41
-
42
- def set_ip(self, ip):
43
- """Will be used to set _ip point to current ipython instance b/f call
44
-
45
- Override this method if you don't want this to happen.
46
-
47
- """
48
- self._ip = ip
49
-
50
-
51
- class ExitAutocall(IPyAutocall):
52
- """An autocallable object which will be added to the user namespace so that
53
- exit, exit(), quit or quit() are all valid ways to close the shell."""
54
- rewrite = False
55
-
56
- def __call__(self):
57
- self._ip.ask_exit()
58
-
59
- class ZMQExitAutocall(ExitAutocall):
60
- """Exit IPython. Autocallable, so it needn't be explicitly called.
61
-
62
- Parameters
63
- ----------
64
- keep_kernel : bool
65
- If True, leave the kernel alive. Otherwise, tell the kernel to exit too
66
- (default).
67
- """
68
- def __call__(self, keep_kernel=False):
69
- self._ip.keepkernel_on_exit = keep_kernel
70
- self._ip.ask_exit()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/builtin_trap.py DELETED
@@ -1,86 +0,0 @@
1
- """
2
- A context manager for managing things injected into :mod:`builtins`.
3
- """
4
- # Copyright (c) IPython Development Team.
5
- # Distributed under the terms of the Modified BSD License.
6
- import builtins as builtin_mod
7
-
8
- from traitlets.config.configurable import Configurable
9
-
10
- from traitlets import Instance
11
-
12
-
13
- class __BuiltinUndefined(object): pass
14
- BuiltinUndefined = __BuiltinUndefined()
15
-
16
- class __HideBuiltin(object): pass
17
- HideBuiltin = __HideBuiltin()
18
-
19
-
20
- class BuiltinTrap(Configurable):
21
-
22
- shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
23
- allow_none=True)
24
-
25
- def __init__(self, shell=None):
26
- super(BuiltinTrap, self).__init__(shell=shell, config=None)
27
- self._orig_builtins = {}
28
- # We define this to track if a single BuiltinTrap is nested.
29
- # Only turn off the trap when the outermost call to __exit__ is made.
30
- self._nested_level = 0
31
- self.shell = shell
32
- # builtins we always add - if set to HideBuiltin, they will just
33
- # be removed instead of being replaced by something else
34
- self.auto_builtins = {'exit': HideBuiltin,
35
- 'quit': HideBuiltin,
36
- 'get_ipython': self.shell.get_ipython,
37
- }
38
-
39
- def __enter__(self):
40
- if self._nested_level == 0:
41
- self.activate()
42
- self._nested_level += 1
43
- # I return self, so callers can use add_builtin in a with clause.
44
- return self
45
-
46
- def __exit__(self, type, value, traceback):
47
- if self._nested_level == 1:
48
- self.deactivate()
49
- self._nested_level -= 1
50
- # Returning False will cause exceptions to propagate
51
- return False
52
-
53
- def add_builtin(self, key, value):
54
- """Add a builtin and save the original."""
55
- bdict = builtin_mod.__dict__
56
- orig = bdict.get(key, BuiltinUndefined)
57
- if value is HideBuiltin:
58
- if orig is not BuiltinUndefined: #same as 'key in bdict'
59
- self._orig_builtins[key] = orig
60
- del bdict[key]
61
- else:
62
- self._orig_builtins[key] = orig
63
- bdict[key] = value
64
-
65
- def remove_builtin(self, key, orig):
66
- """Remove an added builtin and re-set the original."""
67
- if orig is BuiltinUndefined:
68
- del builtin_mod.__dict__[key]
69
- else:
70
- builtin_mod.__dict__[key] = orig
71
-
72
- def activate(self):
73
- """Store ipython references in the __builtin__ namespace."""
74
-
75
- add_builtin = self.add_builtin
76
- for name, func in self.auto_builtins.items():
77
- add_builtin(name, func)
78
-
79
- def deactivate(self):
80
- """Remove any builtins which might have been added by add_builtins, or
81
- restore overwritten ones to their previous values."""
82
- remove_builtin = self.remove_builtin
83
- for key, val in self._orig_builtins.items():
84
- remove_builtin(key, val)
85
- self._orig_builtins.clear()
86
- self._builtins_added = False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/compilerop.py DELETED
@@ -1,214 +0,0 @@
1
- """Compiler tools with improved interactive support.
2
-
3
- Provides compilation machinery similar to codeop, but with caching support so
4
- we can provide interactive tracebacks.
5
-
6
- Authors
7
- -------
8
- * Robert Kern
9
- * Fernando Perez
10
- * Thomas Kluyver
11
- """
12
-
13
- # Note: though it might be more natural to name this module 'compiler', that
14
- # name is in the stdlib and name collisions with the stdlib tend to produce
15
- # weird problems (often with third-party tools).
16
-
17
- #-----------------------------------------------------------------------------
18
- # Copyright (C) 2010-2011 The IPython Development Team.
19
- #
20
- # Distributed under the terms of the BSD License.
21
- #
22
- # The full license is in the file COPYING.txt, distributed with this software.
23
- #-----------------------------------------------------------------------------
24
-
25
- #-----------------------------------------------------------------------------
26
- # Imports
27
- #-----------------------------------------------------------------------------
28
-
29
- # Stdlib imports
30
- import __future__
31
- from ast import PyCF_ONLY_AST
32
- import codeop
33
- import functools
34
- import hashlib
35
- import linecache
36
- import operator
37
- import time
38
- from contextlib import contextmanager
39
-
40
- #-----------------------------------------------------------------------------
41
- # Constants
42
- #-----------------------------------------------------------------------------
43
-
44
- # Roughly equal to PyCF_MASK | PyCF_MASK_OBSOLETE as defined in pythonrun.h,
45
- # this is used as a bitmask to extract future-related code flags.
46
- PyCF_MASK = functools.reduce(operator.or_,
47
- (getattr(__future__, fname).compiler_flag
48
- for fname in __future__.all_feature_names))
49
-
50
- #-----------------------------------------------------------------------------
51
- # Local utilities
52
- #-----------------------------------------------------------------------------
53
-
54
- def code_name(code, number=0):
55
- """ Compute a (probably) unique name for code for caching.
56
-
57
- This now expects code to be unicode.
58
- """
59
- hash_digest = hashlib.sha1(code.encode("utf-8")).hexdigest()
60
- # Include the number and 12 characters of the hash in the name. It's
61
- # pretty much impossible that in a single session we'll have collisions
62
- # even with truncated hashes, and the full one makes tracebacks too long
63
- return '<ipython-input-{0}-{1}>'.format(number, hash_digest[:12])
64
-
65
- #-----------------------------------------------------------------------------
66
- # Classes and functions
67
- #-----------------------------------------------------------------------------
68
-
69
- class CachingCompiler(codeop.Compile):
70
- """A compiler that caches code compiled from interactive statements.
71
- """
72
-
73
- def __init__(self):
74
- codeop.Compile.__init__(self)
75
-
76
- # Caching a dictionary { filename: execution_count } for nicely
77
- # rendered tracebacks. The filename corresponds to the filename
78
- # argument used for the builtins.compile function.
79
- self._filename_map = {}
80
-
81
- def ast_parse(self, source, filename='<unknown>', symbol='exec'):
82
- """Parse code to an AST with the current compiler flags active.
83
-
84
- Arguments are exactly the same as ast.parse (in the standard library),
85
- and are passed to the built-in compile function."""
86
- return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1)
87
-
88
- def reset_compiler_flags(self):
89
- """Reset compiler flags to default state."""
90
- # This value is copied from codeop.Compile.__init__, so if that ever
91
- # changes, it will need to be updated.
92
- self.flags = codeop.PyCF_DONT_IMPLY_DEDENT
93
-
94
- @property
95
- def compiler_flags(self):
96
- """Flags currently active in the compilation process.
97
- """
98
- return self.flags
99
-
100
- def get_code_name(self, raw_code, transformed_code, number):
101
- """Compute filename given the code, and the cell number.
102
-
103
- Parameters
104
- ----------
105
- raw_code : str
106
- The raw cell code.
107
- transformed_code : str
108
- The executable Python source code to cache and compile.
109
- number : int
110
- A number which forms part of the code's name. Used for the execution
111
- counter.
112
-
113
- Returns
114
- -------
115
- The computed filename.
116
- """
117
- return code_name(transformed_code, number)
118
-
119
- def format_code_name(self, name):
120
- """Return a user-friendly label and name for a code block.
121
-
122
- Parameters
123
- ----------
124
- name : str
125
- The name for the code block returned from get_code_name
126
-
127
- Returns
128
- -------
129
- A (label, name) pair that can be used in tracebacks, or None if the default formatting should be used.
130
- """
131
- if name in self._filename_map:
132
- return "Cell", "In[%s]" % self._filename_map[name]
133
-
134
- def cache(self, transformed_code, number=0, raw_code=None):
135
- """Make a name for a block of code, and cache the code.
136
-
137
- Parameters
138
- ----------
139
- transformed_code : str
140
- The executable Python source code to cache and compile.
141
- number : int
142
- A number which forms part of the code's name. Used for the execution
143
- counter.
144
- raw_code : str
145
- The raw code before transformation, if None, set to `transformed_code`.
146
-
147
- Returns
148
- -------
149
- The name of the cached code (as a string). Pass this as the filename
150
- argument to compilation, so that tracebacks are correctly hooked up.
151
- """
152
- if raw_code is None:
153
- raw_code = transformed_code
154
-
155
- name = self.get_code_name(raw_code, transformed_code, number)
156
-
157
- # Save the execution count
158
- self._filename_map[name] = number
159
-
160
- # Since Python 2.5, setting mtime to `None` means the lines will
161
- # never be removed by `linecache.checkcache`. This means all the
162
- # monkeypatching has *never* been necessary, since this code was
163
- # only added in 2010, at which point IPython had already stopped
164
- # supporting Python 2.4.
165
- #
166
- # Note that `linecache.clearcache` and `linecache.updatecache` may
167
- # still remove our code from the cache, but those show explicit
168
- # intent, and we should not try to interfere. Normally the former
169
- # is never called except when out of memory, and the latter is only
170
- # called for lines *not* in the cache.
171
- entry = (
172
- len(transformed_code),
173
- None,
174
- [line + "\n" for line in transformed_code.splitlines()],
175
- name,
176
- )
177
- linecache.cache[name] = entry
178
- return name
179
-
180
- @contextmanager
181
- def extra_flags(self, flags):
182
- ## bits that we'll set to 1
183
- turn_on_bits = ~self.flags & flags
184
-
185
-
186
- self.flags = self.flags | flags
187
- try:
188
- yield
189
- finally:
190
- # turn off only the bits we turned on so that something like
191
- # __future__ that set flags stays.
192
- self.flags &= ~turn_on_bits
193
-
194
-
195
- def check_linecache_ipython(*args):
196
- """Deprecated since IPython 8.6. Call linecache.checkcache() directly.
197
-
198
- It was already not necessary to call this function directly. If no
199
- CachingCompiler had been created, this function would fail badly. If
200
- an instance had been created, this function would've been monkeypatched
201
- into place.
202
-
203
- As of IPython 8.6, the monkeypatching has gone away entirely. But there
204
- were still internal callers of this function, so maybe external callers
205
- also existed?
206
- """
207
- import warnings
208
-
209
- warnings.warn(
210
- "Deprecated Since IPython 8.6, Just call linecache.checkcache() directly.",
211
- DeprecationWarning,
212
- stacklevel=2,
213
- )
214
- linecache.checkcache()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/completer.py DELETED
The diff for this file is too large to render. See raw diff
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/completerlib.py DELETED
@@ -1,382 +0,0 @@
1
- # encoding: utf-8
2
- """Implementations for various useful completers.
3
-
4
- These are all loaded by default by IPython.
5
- """
6
- #-----------------------------------------------------------------------------
7
- # Copyright (C) 2010-2011 The IPython Development Team.
8
- #
9
- # Distributed under the terms of the BSD License.
10
- #
11
- # The full license is in the file COPYING.txt, distributed with this software.
12
- #-----------------------------------------------------------------------------
13
-
14
- #-----------------------------------------------------------------------------
15
- # Imports
16
- #-----------------------------------------------------------------------------
17
-
18
- # Stdlib imports
19
- import glob
20
- import inspect
21
- import os
22
- import re
23
- import sys
24
- from importlib import import_module
25
- from importlib.machinery import all_suffixes
26
-
27
-
28
- # Third-party imports
29
- from time import time
30
- from zipimport import zipimporter
31
-
32
- # Our own imports
33
- from .completer import expand_user, compress_user
34
- from .error import TryNext
35
- from ..utils._process_common import arg_split
36
-
37
- # FIXME: this should be pulled in with the right call via the component system
38
- from IPython import get_ipython
39
-
40
- from typing import List
41
-
42
- #-----------------------------------------------------------------------------
43
- # Globals and constants
44
- #-----------------------------------------------------------------------------
45
- _suffixes = all_suffixes()
46
-
47
- # Time in seconds after which the rootmodules will be stored permanently in the
48
- # ipython ip.db database (kept in the user's .ipython dir).
49
- TIMEOUT_STORAGE = 2
50
-
51
- # Time in seconds after which we give up
52
- TIMEOUT_GIVEUP = 20
53
-
54
- # Regular expression for the python import statement
55
- import_re = re.compile(r'(?P<name>[^\W\d]\w*?)'
56
- r'(?P<package>[/\\]__init__)?'
57
- r'(?P<suffix>%s)$' %
58
- r'|'.join(re.escape(s) for s in _suffixes))
59
-
60
- # RE for the ipython %run command (python + ipython scripts)
61
- magic_run_re = re.compile(r'.*(\.ipy|\.ipynb|\.py[w]?)$')
62
-
63
- #-----------------------------------------------------------------------------
64
- # Local utilities
65
- #-----------------------------------------------------------------------------
66
-
67
-
68
- def module_list(path: str) -> List[str]:
69
- """
70
- Return the list containing the names of the modules available in the given
71
- folder.
72
- """
73
- # sys.path has the cwd as an empty string, but isdir/listdir need it as '.'
74
- if path == '':
75
- path = '.'
76
-
77
- # A few local constants to be used in loops below
78
- pjoin = os.path.join
79
-
80
- if os.path.isdir(path):
81
- # Build a list of all files in the directory and all files
82
- # in its subdirectories. For performance reasons, do not
83
- # recurse more than one level into subdirectories.
84
- files: List[str] = []
85
- for root, dirs, nondirs in os.walk(path, followlinks=True):
86
- subdir = root[len(path)+1:]
87
- if subdir:
88
- files.extend(pjoin(subdir, f) for f in nondirs)
89
- dirs[:] = [] # Do not recurse into additional subdirectories.
90
- else:
91
- files.extend(nondirs)
92
-
93
- else:
94
- try:
95
- files = list(zipimporter(path)._files.keys()) # type: ignore
96
- except Exception:
97
- files = []
98
-
99
- # Build a list of modules which match the import_re regex.
100
- modules = []
101
- for f in files:
102
- m = import_re.match(f)
103
- if m:
104
- modules.append(m.group('name'))
105
- return list(set(modules))
106
-
107
-
108
- def get_root_modules():
109
- """
110
- Returns a list containing the names of all the modules available in the
111
- folders of the pythonpath.
112
-
113
- ip.db['rootmodules_cache'] maps sys.path entries to list of modules.
114
- """
115
- ip = get_ipython()
116
- if ip is None:
117
- # No global shell instance to store cached list of modules.
118
- # Don't try to scan for modules every time.
119
- return list(sys.builtin_module_names)
120
-
121
- if getattr(ip.db, "_mock", False):
122
- rootmodules_cache = {}
123
- else:
124
- rootmodules_cache = ip.db.get("rootmodules_cache", {})
125
- rootmodules = list(sys.builtin_module_names)
126
- start_time = time()
127
- store = False
128
- for path in sys.path:
129
- try:
130
- modules = rootmodules_cache[path]
131
- except KeyError:
132
- modules = module_list(path)
133
- try:
134
- modules.remove('__init__')
135
- except ValueError:
136
- pass
137
- if path not in ('', '.'): # cwd modules should not be cached
138
- rootmodules_cache[path] = modules
139
- if time() - start_time > TIMEOUT_STORAGE and not store:
140
- store = True
141
- print("\nCaching the list of root modules, please wait!")
142
- print("(This will only be done once - type '%rehashx' to "
143
- "reset cache!)\n")
144
- sys.stdout.flush()
145
- if time() - start_time > TIMEOUT_GIVEUP:
146
- print("This is taking too long, we give up.\n")
147
- return []
148
- rootmodules.extend(modules)
149
- if store:
150
- ip.db['rootmodules_cache'] = rootmodules_cache
151
- rootmodules = list(set(rootmodules))
152
- return rootmodules
153
-
154
-
155
- def is_importable(module, attr: str, only_modules) -> bool:
156
- if only_modules:
157
- try:
158
- mod = getattr(module, attr)
159
- except ModuleNotFoundError:
160
- # See gh-14434
161
- return False
162
- return inspect.ismodule(mod)
163
- else:
164
- return not(attr[:2] == '__' and attr[-2:] == '__')
165
-
166
- def is_possible_submodule(module, attr):
167
- try:
168
- obj = getattr(module, attr)
169
- except AttributeError:
170
- # Is possibly an unimported submodule
171
- return True
172
- except TypeError:
173
- # https://github.com/ipython/ipython/issues/9678
174
- return False
175
- return inspect.ismodule(obj)
176
-
177
-
178
- def try_import(mod: str, only_modules=False) -> List[str]:
179
- """
180
- Try to import given module and return list of potential completions.
181
- """
182
- mod = mod.rstrip('.')
183
- try:
184
- m = import_module(mod)
185
- except:
186
- return []
187
-
188
- m_is_init = '__init__' in (getattr(m, '__file__', '') or '')
189
-
190
- completions = []
191
- if (not hasattr(m, '__file__')) or (not only_modules) or m_is_init:
192
- completions.extend( [attr for attr in dir(m) if
193
- is_importable(m, attr, only_modules)])
194
-
195
- m_all = getattr(m, "__all__", [])
196
- if only_modules:
197
- completions.extend(attr for attr in m_all if is_possible_submodule(m, attr))
198
- else:
199
- completions.extend(m_all)
200
-
201
- if m_is_init:
202
- file_ = m.__file__
203
- file_path = os.path.dirname(file_) # type: ignore
204
- if file_path is not None:
205
- completions.extend(module_list(file_path))
206
- completions_set = {c for c in completions if isinstance(c, str)}
207
- completions_set.discard('__init__')
208
- return list(completions_set)
209
-
210
-
211
- #-----------------------------------------------------------------------------
212
- # Completion-related functions.
213
- #-----------------------------------------------------------------------------
214
-
215
- def quick_completer(cmd, completions):
216
- r""" Easily create a trivial completer for a command.
217
-
218
- Takes either a list of completions, or all completions in string (that will
219
- be split on whitespace).
220
-
221
- Example::
222
-
223
- [d:\ipython]|1> import ipy_completers
224
- [d:\ipython]|2> ipy_completers.quick_completer('foo', ['bar','baz'])
225
- [d:\ipython]|3> foo b<TAB>
226
- bar baz
227
- [d:\ipython]|3> foo ba
228
- """
229
-
230
- if isinstance(completions, str):
231
- completions = completions.split()
232
-
233
- def do_complete(self, event):
234
- return completions
235
-
236
- get_ipython().set_hook('complete_command',do_complete, str_key = cmd)
237
-
238
- def module_completion(line):
239
- """
240
- Returns a list containing the completion possibilities for an import line.
241
-
242
- The line looks like this :
243
- 'import xml.d'
244
- 'from xml.dom import'
245
- """
246
-
247
- words = line.split(' ')
248
- nwords = len(words)
249
-
250
- # from whatever <tab> -> 'import '
251
- if nwords == 3 and words[0] == 'from':
252
- return ['import ']
253
-
254
- # 'from xy<tab>' or 'import xy<tab>'
255
- if nwords < 3 and (words[0] in {'%aimport', 'import', 'from'}) :
256
- if nwords == 1:
257
- return get_root_modules()
258
- mod = words[1].split('.')
259
- if len(mod) < 2:
260
- return get_root_modules()
261
- completion_list = try_import('.'.join(mod[:-1]), True)
262
- return ['.'.join(mod[:-1] + [el]) for el in completion_list]
263
-
264
- # 'from xyz import abc<tab>'
265
- if nwords >= 3 and words[0] == 'from':
266
- mod = words[1]
267
- return try_import(mod)
268
-
269
- #-----------------------------------------------------------------------------
270
- # Completers
271
- #-----------------------------------------------------------------------------
272
- # These all have the func(self, event) signature to be used as custom
273
- # completers
274
-
275
- def module_completer(self,event):
276
- """Give completions after user has typed 'import ...' or 'from ...'"""
277
-
278
- # This works in all versions of python. While 2.5 has
279
- # pkgutil.walk_packages(), that particular routine is fairly dangerous,
280
- # since it imports *EVERYTHING* on sys.path. That is: a) very slow b) full
281
- # of possibly problematic side effects.
282
- # This search the folders in the sys.path for available modules.
283
-
284
- return module_completion(event.line)
285
-
286
- # FIXME: there's a lot of logic common to the run, cd and builtin file
287
- # completers, that is currently reimplemented in each.
288
-
289
- def magic_run_completer(self, event):
290
- """Complete files that end in .py or .ipy or .ipynb for the %run command.
291
- """
292
- comps = arg_split(event.line, strict=False)
293
- # relpath should be the current token that we need to complete.
294
- if (len(comps) > 1) and (not event.line.endswith(' ')):
295
- relpath = comps[-1].strip("'\"")
296
- else:
297
- relpath = ''
298
-
299
- #print("\nev=", event) # dbg
300
- #print("rp=", relpath) # dbg
301
- #print('comps=', comps) # dbg
302
-
303
- lglob = glob.glob
304
- isdir = os.path.isdir
305
- relpath, tilde_expand, tilde_val = expand_user(relpath)
306
-
307
- # Find if the user has already typed the first filename, after which we
308
- # should complete on all files, since after the first one other files may
309
- # be arguments to the input script.
310
-
311
- if any(magic_run_re.match(c) for c in comps):
312
- matches = [f.replace('\\','/') + ('/' if isdir(f) else '')
313
- for f in lglob(relpath+'*')]
314
- else:
315
- dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*') if isdir(f)]
316
- pys = [f.replace('\\','/')
317
- for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') +
318
- lglob(relpath+'*.ipynb') + lglob(relpath + '*.pyw')]
319
-
320
- matches = dirs + pys
321
-
322
- #print('run comp:', dirs+pys) # dbg
323
- return [compress_user(p, tilde_expand, tilde_val) for p in matches]
324
-
325
-
326
- def cd_completer(self, event):
327
- """Completer function for cd, which only returns directories."""
328
- ip = get_ipython()
329
- relpath = event.symbol
330
-
331
- #print(event) # dbg
332
- if event.line.endswith('-b') or ' -b ' in event.line:
333
- # return only bookmark completions
334
- bkms = self.db.get('bookmarks', None)
335
- if bkms:
336
- return bkms.keys()
337
- else:
338
- return []
339
-
340
- if event.symbol == '-':
341
- width_dh = str(len(str(len(ip.user_ns['_dh']) + 1)))
342
- # jump in directory history by number
343
- fmt = '-%0' + width_dh +'d [%s]'
344
- ents = [ fmt % (i,s) for i,s in enumerate(ip.user_ns['_dh'])]
345
- if len(ents) > 1:
346
- return ents
347
- return []
348
-
349
- if event.symbol.startswith('--'):
350
- return ["--" + os.path.basename(d) for d in ip.user_ns['_dh']]
351
-
352
- # Expand ~ in path and normalize directory separators.
353
- relpath, tilde_expand, tilde_val = expand_user(relpath)
354
- relpath = relpath.replace('\\','/')
355
-
356
- found = []
357
- for d in [f.replace('\\','/') + '/' for f in glob.glob(relpath+'*')
358
- if os.path.isdir(f)]:
359
- if ' ' in d:
360
- # we don't want to deal with any of that, complex code
361
- # for this is elsewhere
362
- raise TryNext
363
-
364
- found.append(d)
365
-
366
- if not found:
367
- if os.path.isdir(relpath):
368
- return [compress_user(relpath, tilde_expand, tilde_val)]
369
-
370
- # if no completions so far, try bookmarks
371
- bks = self.db.get('bookmarks',{})
372
- bkmatches = [s for s in bks if s.startswith(event.symbol)]
373
- if bkmatches:
374
- return bkmatches
375
-
376
- raise TryNext
377
-
378
- return [compress_user(p, tilde_expand, tilde_val) for p in found]
379
-
380
- def reset_completer(self, event):
381
- "A completer for %reset magic"
382
- return '-f -s in out array dhist'.split()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/crashhandler.py DELETED
@@ -1,248 +0,0 @@
1
- # encoding: utf-8
2
- """sys.excepthook for IPython itself, leaves a detailed report on disk.
3
-
4
- Authors:
5
-
6
- * Fernando Perez
7
- * Brian E. Granger
8
- """
9
-
10
- #-----------------------------------------------------------------------------
11
- # Copyright (C) 2001-2007 Fernando Perez. <[email protected]>
12
- # Copyright (C) 2008-2011 The IPython Development Team
13
- #
14
- # Distributed under the terms of the BSD License. The full license is in
15
- # the file COPYING, distributed as part of this software.
16
- #-----------------------------------------------------------------------------
17
-
18
- #-----------------------------------------------------------------------------
19
- # Imports
20
- #-----------------------------------------------------------------------------
21
-
22
- import sys
23
- import traceback
24
- from pprint import pformat
25
- from pathlib import Path
26
-
27
- import builtins as builtin_mod
28
-
29
- from IPython.core import ultratb
30
- from IPython.core.application import Application
31
- from IPython.core.release import author_email
32
- from IPython.utils.sysinfo import sys_info
33
-
34
- from IPython.core.release import __version__ as version
35
-
36
- from typing import Optional, Dict
37
- import types
38
-
39
- #-----------------------------------------------------------------------------
40
- # Code
41
- #-----------------------------------------------------------------------------
42
-
43
- # Template for the user message.
44
- _default_message_template = """\
45
- Oops, {app_name} crashed. We do our best to make it stable, but...
46
-
47
- A crash report was automatically generated with the following information:
48
- - A verbatim copy of the crash traceback.
49
- - A copy of your input history during this session.
50
- - Data on your current {app_name} configuration.
51
-
52
- It was left in the file named:
53
- \t'{crash_report_fname}'
54
- If you can email this file to the developers, the information in it will help
55
- them in understanding and correcting the problem.
56
-
57
- You can mail it to: {contact_name} at {contact_email}
58
- with the subject '{app_name} Crash Report'.
59
-
60
- If you want to do it now, the following command will work (under Unix):
61
- mail -s '{app_name} Crash Report' {contact_email} < {crash_report_fname}
62
-
63
- In your email, please also include information about:
64
- - The operating system under which the crash happened: Linux, macOS, Windows,
65
- other, and which exact version (for example: Ubuntu 16.04.3, macOS 10.13.2,
66
- Windows 10 Pro), and whether it is 32-bit or 64-bit;
67
- - How {app_name} was installed: using pip or conda, from GitHub, as part of
68
- a Docker container, or other, providing more detail if possible;
69
- - How to reproduce the crash: what exact sequence of instructions can one
70
- input to get the same crash? Ideally, find a minimal yet complete sequence
71
- of instructions that yields the crash.
72
-
73
- To ensure accurate tracking of this issue, please file a report about it at:
74
- {bug_tracker}
75
- """
76
-
77
- _lite_message_template = """
78
- If you suspect this is an IPython {version} bug, please report it at:
79
- https://github.com/ipython/ipython/issues
80
- or send an email to the mailing list at {email}
81
-
82
- You can print a more detailed traceback right now with "%tb", or use "%debug"
83
- to interactively debug it.
84
-
85
- Extra-detailed tracebacks for bug-reporting purposes can be enabled via:
86
- {config}Application.verbose_crash=True
87
- """
88
-
89
-
90
- class CrashHandler:
91
- """Customizable crash handlers for IPython applications.
92
-
93
- Instances of this class provide a :meth:`__call__` method which can be
94
- used as a ``sys.excepthook``. The :meth:`__call__` signature is::
95
-
96
- def __call__(self, etype, evalue, etb)
97
- """
98
-
99
- message_template = _default_message_template
100
- section_sep = '\n\n'+'*'*75+'\n\n'
101
- info: Dict[str, Optional[str]]
102
-
103
- def __init__(
104
- self,
105
- app: Application,
106
- contact_name: Optional[str] = None,
107
- contact_email: Optional[str] = None,
108
- bug_tracker: Optional[str] = None,
109
- show_crash_traceback: bool = True,
110
- call_pdb: bool = False,
111
- ):
112
- """Create a new crash handler
113
-
114
- Parameters
115
- ----------
116
- app : Application
117
- A running :class:`Application` instance, which will be queried at
118
- crash time for internal information.
119
- contact_name : str
120
- A string with the name of the person to contact.
121
- contact_email : str
122
- A string with the email address of the contact.
123
- bug_tracker : str
124
- A string with the URL for your project's bug tracker.
125
- show_crash_traceback : bool
126
- If false, don't print the crash traceback on stderr, only generate
127
- the on-disk report
128
- call_pdb
129
- Whether to call pdb on crash
130
-
131
- Attributes
132
- ----------
133
- These instances contain some non-argument attributes which allow for
134
- further customization of the crash handler's behavior. Please see the
135
- source for further details.
136
-
137
- """
138
- self.crash_report_fname = "Crash_report_%s.txt" % app.name
139
- self.app = app
140
- self.call_pdb = call_pdb
141
- #self.call_pdb = True # dbg
142
- self.show_crash_traceback = show_crash_traceback
143
- self.info = dict(app_name = app.name,
144
- contact_name = contact_name,
145
- contact_email = contact_email,
146
- bug_tracker = bug_tracker,
147
- crash_report_fname = self.crash_report_fname)
148
-
149
- def __call__(
150
- self,
151
- etype: type[BaseException],
152
- evalue: BaseException,
153
- etb: types.TracebackType,
154
- ) -> None:
155
- """Handle an exception, call for compatible with sys.excepthook"""
156
-
157
- # do not allow the crash handler to be called twice without reinstalling it
158
- # this prevents unlikely errors in the crash handling from entering an
159
- # infinite loop.
160
- sys.excepthook = sys.__excepthook__
161
-
162
- # Report tracebacks shouldn't use color in general (safer for users)
163
- color_scheme = 'NoColor'
164
-
165
- # Use this ONLY for developer debugging (keep commented out for release)
166
- # color_scheme = 'Linux' # dbg
167
- ipython_dir = getattr(self.app, "ipython_dir", None)
168
- if ipython_dir is not None:
169
- assert isinstance(ipython_dir, str)
170
- rptdir = Path(ipython_dir)
171
- else:
172
- rptdir = Path.cwd()
173
- if not rptdir.is_dir():
174
- rptdir = Path.cwd()
175
- report_name = rptdir / self.crash_report_fname
176
- # write the report filename into the instance dict so it can get
177
- # properly expanded out in the user message template
178
- self.crash_report_fname = str(report_name)
179
- self.info["crash_report_fname"] = str(report_name)
180
- TBhandler = ultratb.VerboseTB(
181
- color_scheme=color_scheme,
182
- long_header=True,
183
- call_pdb=self.call_pdb,
184
- )
185
- if self.call_pdb:
186
- TBhandler(etype,evalue,etb)
187
- return
188
- else:
189
- traceback = TBhandler.text(etype,evalue,etb,context=31)
190
-
191
- # print traceback to screen
192
- if self.show_crash_traceback:
193
- print(traceback, file=sys.stderr)
194
-
195
- # and generate a complete report on disk
196
- try:
197
- report = open(report_name, "w", encoding="utf-8")
198
- except:
199
- print('Could not create crash report on disk.', file=sys.stderr)
200
- return
201
-
202
- with report:
203
- # Inform user on stderr of what happened
204
- print('\n'+'*'*70+'\n', file=sys.stderr)
205
- print(self.message_template.format(**self.info), file=sys.stderr)
206
-
207
- # Construct report on disk
208
- report.write(self.make_report(str(traceback)))
209
-
210
- builtin_mod.input("Hit <Enter> to quit (your terminal may close):")
211
-
212
- def make_report(self, traceback: str) -> str:
213
- """Return a string containing a crash report."""
214
-
215
- sec_sep = self.section_sep
216
-
217
- report = ['*'*75+'\n\n'+'IPython post-mortem report\n\n']
218
- rpt_add = report.append
219
- rpt_add(sys_info())
220
-
221
- try:
222
- config = pformat(self.app.config)
223
- rpt_add(sec_sep)
224
- rpt_add("Application name: %s\n\n" % self.app.name)
225
- rpt_add("Current user configuration structure:\n\n")
226
- rpt_add(config)
227
- except:
228
- pass
229
- rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
230
-
231
- return ''.join(report)
232
-
233
-
234
- def crash_handler_lite(
235
- etype: type[BaseException], evalue: BaseException, tb: types.TracebackType
236
- ) -> None:
237
- """a light excepthook, adding a small message to the usual traceback"""
238
- traceback.print_exception(etype, evalue, tb)
239
-
240
- from IPython.core.interactiveshell import InteractiveShell
241
- if InteractiveShell.initialized():
242
- # we are in a Shell environment, give %magic example
243
- config = "%config "
244
- else:
245
- # we are not in a shell, show generic config
246
- config = "c."
247
- print(_lite_message_template.format(email=author_email, config=config, version=version), file=sys.stderr)
248
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/debugger.py DELETED
@@ -1,1136 +0,0 @@
1
- """
2
- Pdb debugger class.
3
-
4
-
5
- This is an extension to PDB which adds a number of new features.
6
- Note that there is also the `IPython.terminal.debugger` class which provides UI
7
- improvements.
8
-
9
- We also strongly recommend to use this via the `ipdb` package, which provides
10
- extra configuration options.
11
-
12
- Among other things, this subclass of PDB:
13
- - supports many IPython magics like pdef/psource
14
- - hide frames in tracebacks based on `__tracebackhide__`
15
- - allows to skip frames based on `__debuggerskip__`
16
-
17
-
18
- Global Configuration
19
- --------------------
20
-
21
- The IPython debugger will by read the global ``~/.pdbrc`` file.
22
- That is to say you can list all commands supported by ipdb in your `~/.pdbrc`
23
- configuration file, to globally configure pdb.
24
-
25
- Example::
26
-
27
- # ~/.pdbrc
28
- skip_predicates debuggerskip false
29
- skip_hidden false
30
- context 25
31
-
32
- Features
33
- --------
34
-
35
- The IPython debugger can hide and skip frames when printing or moving through
36
- the stack. This can have a performance impact, so can be configures.
37
-
38
- The skipping and hiding frames are configurable via the `skip_predicates`
39
- command.
40
-
41
- By default, frames from readonly files will be hidden, frames containing
42
- ``__tracebackhide__ = True`` will be hidden.
43
-
44
- Frames containing ``__debuggerskip__`` will be stepped over, frames whose parent
45
- frames value of ``__debuggerskip__`` is ``True`` will also be skipped.
46
-
47
- >>> def helpers_helper():
48
- ... pass
49
- ...
50
- ... def helper_1():
51
- ... print("don't step in me")
52
- ... helpers_helpers() # will be stepped over unless breakpoint set.
53
- ...
54
- ...
55
- ... def helper_2():
56
- ... print("in me neither")
57
- ...
58
-
59
- One can define a decorator that wraps a function between the two helpers:
60
-
61
- >>> def pdb_skipped_decorator(function):
62
- ...
63
- ...
64
- ... def wrapped_fn(*args, **kwargs):
65
- ... __debuggerskip__ = True
66
- ... helper_1()
67
- ... __debuggerskip__ = False
68
- ... result = function(*args, **kwargs)
69
- ... __debuggerskip__ = True
70
- ... helper_2()
71
- ... # setting __debuggerskip__ to False again is not necessary
72
- ... return result
73
- ...
74
- ... return wrapped_fn
75
-
76
- When decorating a function, ipdb will directly step into ``bar()`` by
77
- default:
78
-
79
- >>> @foo_decorator
80
- ... def bar(x, y):
81
- ... return x * y
82
-
83
-
84
- You can toggle the behavior with
85
-
86
- ipdb> skip_predicates debuggerskip false
87
-
88
- or configure it in your ``.pdbrc``
89
-
90
-
91
-
92
- License
93
- -------
94
-
95
- Modified from the standard pdb.Pdb class to avoid including readline, so that
96
- the command line completion of other programs which include this isn't
97
- damaged.
98
-
99
- In the future, this class will be expanded with improvements over the standard
100
- pdb.
101
-
102
- The original code in this file is mainly lifted out of cmd.py in Python 2.2,
103
- with minor changes. Licensing should therefore be under the standard Python
104
- terms. For details on the PSF (Python Software Foundation) standard license,
105
- see:
106
-
107
- https://docs.python.org/2/license.html
108
-
109
-
110
- All the changes since then are under the same license as IPython.
111
-
112
- """
113
-
114
- #*****************************************************************************
115
- #
116
- # This file is licensed under the PSF license.
117
- #
118
- # Copyright (C) 2001 Python Software Foundation, www.python.org
119
- # Copyright (C) 2005-2006 Fernando Perez. <[email protected]>
120
- #
121
- #
122
- #*****************************************************************************
123
-
124
- from __future__ import annotations
125
-
126
- import inspect
127
- import linecache
128
- import os
129
- import re
130
- import sys
131
- from contextlib import contextmanager
132
- from functools import lru_cache
133
-
134
- from IPython import get_ipython
135
- from IPython.core.excolors import exception_colors
136
- from IPython.utils import PyColorize, coloransi, py3compat
137
-
138
- from typing import TYPE_CHECKING
139
-
140
- if TYPE_CHECKING:
141
- # otherwise circular import
142
- from IPython.core.interactiveshell import InteractiveShell
143
-
144
- # skip module docstests
145
- __skip_doctest__ = True
146
-
147
- prompt = 'ipdb> '
148
-
149
- # We have to check this directly from sys.argv, config struct not yet available
150
- from pdb import Pdb as OldPdb
151
-
152
- # Allow the set_trace code to operate outside of an ipython instance, even if
153
- # it does so with some limitations. The rest of this support is implemented in
154
- # the Tracer constructor.
155
-
156
- DEBUGGERSKIP = "__debuggerskip__"
157
-
158
-
159
- # this has been implemented in Pdb in Python 3.13 (https://github.com/python/cpython/pull/106676
160
- # on lower python versions, we backported the feature.
161
- CHAIN_EXCEPTIONS = sys.version_info < (3, 13)
162
-
163
-
164
- def make_arrow(pad):
165
- """generate the leading arrow in front of traceback or debugger"""
166
- if pad >= 2:
167
- return '-'*(pad-2) + '> '
168
- elif pad == 1:
169
- return '>'
170
- return ''
171
-
172
-
173
- def BdbQuit_excepthook(et, ev, tb, excepthook=None):
174
- """Exception hook which handles `BdbQuit` exceptions.
175
-
176
- All other exceptions are processed using the `excepthook`
177
- parameter.
178
- """
179
- raise ValueError(
180
- "`BdbQuit_excepthook` is deprecated since version 5.1. It is still around only because it is still imported by ipdb.",
181
- )
182
-
183
-
184
- RGX_EXTRA_INDENT = re.compile(r'(?<=\n)\s+')
185
-
186
-
187
- def strip_indentation(multiline_string):
188
- return RGX_EXTRA_INDENT.sub('', multiline_string)
189
-
190
-
191
- def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
192
- """Make new_fn have old_fn's doc string. This is particularly useful
193
- for the ``do_...`` commands that hook into the help system.
194
- Adapted from from a comp.lang.python posting
195
- by Duncan Booth."""
196
- def wrapper(*args, **kw):
197
- return new_fn(*args, **kw)
198
- if old_fn.__doc__:
199
- wrapper.__doc__ = strip_indentation(old_fn.__doc__) + additional_text
200
- return wrapper
201
-
202
-
203
- class Pdb(OldPdb):
204
- """Modified Pdb class, does not load readline.
205
-
206
- for a standalone version that uses prompt_toolkit, see
207
- `IPython.terminal.debugger.TerminalPdb` and
208
- `IPython.terminal.debugger.set_trace()`
209
-
210
-
211
- This debugger can hide and skip frames that are tagged according to some predicates.
212
- See the `skip_predicates` commands.
213
-
214
- """
215
-
216
- shell: InteractiveShell
217
-
218
- if CHAIN_EXCEPTIONS:
219
- MAX_CHAINED_EXCEPTION_DEPTH = 999
220
-
221
- default_predicates = {
222
- "tbhide": True,
223
- "readonly": False,
224
- "ipython_internal": True,
225
- "debuggerskip": True,
226
- }
227
-
228
- def __init__(self, completekey=None, stdin=None, stdout=None, context=5, **kwargs):
229
- """Create a new IPython debugger.
230
-
231
- Parameters
232
- ----------
233
- completekey : default None
234
- Passed to pdb.Pdb.
235
- stdin : default None
236
- Passed to pdb.Pdb.
237
- stdout : default None
238
- Passed to pdb.Pdb.
239
- context : int
240
- Number of lines of source code context to show when
241
- displaying stacktrace information.
242
- **kwargs
243
- Passed to pdb.Pdb.
244
-
245
- Notes
246
- -----
247
- The possibilities are python version dependent, see the python
248
- docs for more info.
249
- """
250
-
251
- # Parent constructor:
252
- try:
253
- self.context = int(context)
254
- if self.context <= 0:
255
- raise ValueError("Context must be a positive integer")
256
- except (TypeError, ValueError) as e:
257
- raise ValueError("Context must be a positive integer") from e
258
-
259
- # `kwargs` ensures full compatibility with stdlib's `pdb.Pdb`.
260
- OldPdb.__init__(self, completekey, stdin, stdout, **kwargs)
261
-
262
- # IPython changes...
263
- self.shell = get_ipython()
264
-
265
- if self.shell is None:
266
- save_main = sys.modules['__main__']
267
- # No IPython instance running, we must create one
268
- from IPython.terminal.interactiveshell import \
269
- TerminalInteractiveShell
270
- self.shell = TerminalInteractiveShell.instance()
271
- # needed by any code which calls __import__("__main__") after
272
- # the debugger was entered. See also #9941.
273
- sys.modules["__main__"] = save_main
274
-
275
-
276
- color_scheme = self.shell.colors
277
-
278
- self.aliases = {}
279
-
280
- # Create color table: we copy the default one from the traceback
281
- # module and add a few attributes needed for debugging
282
- self.color_scheme_table = exception_colors()
283
-
284
- # shorthands
285
- C = coloransi.TermColors
286
- cst = self.color_scheme_table
287
-
288
-
289
- # Add a python parser so we can syntax highlight source while
290
- # debugging.
291
- self.parser = PyColorize.Parser(style=color_scheme)
292
- self.set_colors(color_scheme)
293
-
294
- # Set the prompt - the default prompt is '(Pdb)'
295
- self.prompt = prompt
296
- self.skip_hidden = True
297
- self.report_skipped = True
298
-
299
- # list of predicates we use to skip frames
300
- self._predicates = self.default_predicates
301
-
302
- if CHAIN_EXCEPTIONS:
303
- self._chained_exceptions = tuple()
304
- self._chained_exception_index = 0
305
-
306
- #
307
- def set_colors(self, scheme):
308
- """Shorthand access to the color table scheme selector method."""
309
- self.color_scheme_table.set_active_scheme(scheme)
310
- self.parser.style = scheme
311
-
312
- def set_trace(self, frame=None):
313
- if frame is None:
314
- frame = sys._getframe().f_back
315
- self.initial_frame = frame
316
- return super().set_trace(frame)
317
-
318
- def _hidden_predicate(self, frame):
319
- """
320
- Given a frame return whether it it should be hidden or not by IPython.
321
- """
322
-
323
- if self._predicates["readonly"]:
324
- fname = frame.f_code.co_filename
325
- # we need to check for file existence and interactively define
326
- # function would otherwise appear as RO.
327
- if os.path.isfile(fname) and not os.access(fname, os.W_OK):
328
- return True
329
-
330
- if self._predicates["tbhide"]:
331
- if frame in (self.curframe, getattr(self, "initial_frame", None)):
332
- return False
333
- frame_locals = self._get_frame_locals(frame)
334
- if "__tracebackhide__" not in frame_locals:
335
- return False
336
- return frame_locals["__tracebackhide__"]
337
- return False
338
-
339
- def hidden_frames(self, stack):
340
- """
341
- Given an index in the stack return whether it should be skipped.
342
-
343
- This is used in up/down and where to skip frames.
344
- """
345
- # The f_locals dictionary is updated from the actual frame
346
- # locals whenever the .f_locals accessor is called, so we
347
- # avoid calling it here to preserve self.curframe_locals.
348
- # Furthermore, there is no good reason to hide the current frame.
349
- ip_hide = [self._hidden_predicate(s[0]) for s in stack]
350
- ip_start = [i for i, s in enumerate(ip_hide) if s == "__ipython_bottom__"]
351
- if ip_start and self._predicates["ipython_internal"]:
352
- ip_hide = [h if i > ip_start[0] else True for (i, h) in enumerate(ip_hide)]
353
- return ip_hide
354
-
355
- if CHAIN_EXCEPTIONS:
356
-
357
- def _get_tb_and_exceptions(self, tb_or_exc):
358
- """
359
- Given a tracecack or an exception, return a tuple of chained exceptions
360
- and current traceback to inspect.
361
- This will deal with selecting the right ``__cause__`` or ``__context__``
362
- as well as handling cycles, and return a flattened list of exceptions we
363
- can jump to with do_exceptions.
364
- """
365
- _exceptions = []
366
- if isinstance(tb_or_exc, BaseException):
367
- traceback, current = tb_or_exc.__traceback__, tb_or_exc
368
-
369
- while current is not None:
370
- if current in _exceptions:
371
- break
372
- _exceptions.append(current)
373
- if current.__cause__ is not None:
374
- current = current.__cause__
375
- elif (
376
- current.__context__ is not None
377
- and not current.__suppress_context__
378
- ):
379
- current = current.__context__
380
-
381
- if len(_exceptions) >= self.MAX_CHAINED_EXCEPTION_DEPTH:
382
- self.message(
383
- f"More than {self.MAX_CHAINED_EXCEPTION_DEPTH}"
384
- " chained exceptions found, not all exceptions"
385
- "will be browsable with `exceptions`."
386
- )
387
- break
388
- else:
389
- traceback = tb_or_exc
390
- return tuple(reversed(_exceptions)), traceback
391
-
392
- @contextmanager
393
- def _hold_exceptions(self, exceptions):
394
- """
395
- Context manager to ensure proper cleaning of exceptions references
396
- When given a chained exception instead of a traceback,
397
- pdb may hold references to many objects which may leak memory.
398
- We use this context manager to make sure everything is properly cleaned
399
- """
400
- try:
401
- self._chained_exceptions = exceptions
402
- self._chained_exception_index = len(exceptions) - 1
403
- yield
404
- finally:
405
- # we can't put those in forget as otherwise they would
406
- # be cleared on exception change
407
- self._chained_exceptions = tuple()
408
- self._chained_exception_index = 0
409
-
410
- def do_exceptions(self, arg):
411
- """exceptions [number]
412
- List or change current exception in an exception chain.
413
- Without arguments, list all the current exception in the exception
414
- chain. Exceptions will be numbered, with the current exception indicated
415
- with an arrow.
416
- If given an integer as argument, switch to the exception at that index.
417
- """
418
- if not self._chained_exceptions:
419
- self.message(
420
- "Did not find chained exceptions. To move between"
421
- " exceptions, pdb/post_mortem must be given an exception"
422
- " object rather than a traceback."
423
- )
424
- return
425
- if not arg:
426
- for ix, exc in enumerate(self._chained_exceptions):
427
- prompt = ">" if ix == self._chained_exception_index else " "
428
- rep = repr(exc)
429
- if len(rep) > 80:
430
- rep = rep[:77] + "..."
431
- indicator = (
432
- " -"
433
- if self._chained_exceptions[ix].__traceback__ is None
434
- else f"{ix:>3}"
435
- )
436
- self.message(f"{prompt} {indicator} {rep}")
437
- else:
438
- try:
439
- number = int(arg)
440
- except ValueError:
441
- self.error("Argument must be an integer")
442
- return
443
- if 0 <= number < len(self._chained_exceptions):
444
- if self._chained_exceptions[number].__traceback__ is None:
445
- self.error(
446
- "This exception does not have a traceback, cannot jump to it"
447
- )
448
- return
449
-
450
- self._chained_exception_index = number
451
- self.setup(None, self._chained_exceptions[number].__traceback__)
452
- self.print_stack_entry(self.stack[self.curindex])
453
- else:
454
- self.error("No exception with that number")
455
-
456
- def interaction(self, frame, tb_or_exc):
457
- try:
458
- if CHAIN_EXCEPTIONS:
459
- # this context manager is part of interaction in 3.13
460
- _chained_exceptions, tb = self._get_tb_and_exceptions(tb_or_exc)
461
- if isinstance(tb_or_exc, BaseException):
462
- assert tb is not None, "main exception must have a traceback"
463
- with self._hold_exceptions(_chained_exceptions):
464
- OldPdb.interaction(self, frame, tb)
465
- else:
466
- OldPdb.interaction(self, frame, tb_or_exc)
467
-
468
- except KeyboardInterrupt:
469
- self.stdout.write("\n" + self.shell.get_exception_only())
470
-
471
- def precmd(self, line):
472
- """Perform useful escapes on the command before it is executed."""
473
-
474
- if line.endswith("??"):
475
- line = "pinfo2 " + line[:-2]
476
- elif line.endswith("?"):
477
- line = "pinfo " + line[:-1]
478
-
479
- line = super().precmd(line)
480
-
481
- return line
482
-
483
- def new_do_quit(self, arg):
484
- return OldPdb.do_quit(self, arg)
485
-
486
- do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
487
-
488
- def print_stack_trace(self, context=None):
489
- Colors = self.color_scheme_table.active_colors
490
- ColorsNormal = Colors.Normal
491
- if context is None:
492
- context = self.context
493
- try:
494
- context = int(context)
495
- if context <= 0:
496
- raise ValueError("Context must be a positive integer")
497
- except (TypeError, ValueError) as e:
498
- raise ValueError("Context must be a positive integer") from e
499
- try:
500
- skipped = 0
501
- for hidden, frame_lineno in zip(self.hidden_frames(self.stack), self.stack):
502
- if hidden and self.skip_hidden:
503
- skipped += 1
504
- continue
505
- if skipped:
506
- print(
507
- f"{Colors.excName} [... skipping {skipped} hidden frame(s)]{ColorsNormal}\n"
508
- )
509
- skipped = 0
510
- self.print_stack_entry(frame_lineno, context=context)
511
- if skipped:
512
- print(
513
- f"{Colors.excName} [... skipping {skipped} hidden frame(s)]{ColorsNormal}\n"
514
- )
515
- except KeyboardInterrupt:
516
- pass
517
-
518
- def print_stack_entry(self, frame_lineno, prompt_prefix='\n-> ',
519
- context=None):
520
- if context is None:
521
- context = self.context
522
- try:
523
- context = int(context)
524
- if context <= 0:
525
- raise ValueError("Context must be a positive integer")
526
- except (TypeError, ValueError) as e:
527
- raise ValueError("Context must be a positive integer") from e
528
- print(self.format_stack_entry(frame_lineno, '', context), file=self.stdout)
529
-
530
- # vds: >>
531
- frame, lineno = frame_lineno
532
- filename = frame.f_code.co_filename
533
- self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
534
- # vds: <<
535
-
536
- def _get_frame_locals(self, frame):
537
- """ "
538
- Accessing f_local of current frame reset the namespace, so we want to avoid
539
- that or the following can happen
540
-
541
- ipdb> foo
542
- "old"
543
- ipdb> foo = "new"
544
- ipdb> foo
545
- "new"
546
- ipdb> where
547
- ipdb> foo
548
- "old"
549
-
550
- So if frame is self.current_frame we instead return self.curframe_locals
551
-
552
- """
553
- if frame is getattr(self, "curframe", None):
554
- return self.curframe_locals
555
- else:
556
- return frame.f_locals
557
-
558
- def format_stack_entry(self, frame_lineno, lprefix=': ', context=None):
559
- if context is None:
560
- context = self.context
561
- try:
562
- context = int(context)
563
- if context <= 0:
564
- print("Context must be a positive integer", file=self.stdout)
565
- except (TypeError, ValueError):
566
- print("Context must be a positive integer", file=self.stdout)
567
-
568
- import reprlib
569
-
570
- ret = []
571
-
572
- Colors = self.color_scheme_table.active_colors
573
- ColorsNormal = Colors.Normal
574
- tpl_link = "%s%%s%s" % (Colors.filenameEm, ColorsNormal)
575
- tpl_call = "%s%%s%s%%s%s" % (Colors.vName, Colors.valEm, ColorsNormal)
576
- tpl_line = "%%s%s%%s %s%%s" % (Colors.lineno, ColorsNormal)
577
- tpl_line_em = "%%s%s%%s %s%%s%s" % (Colors.linenoEm, Colors.line, ColorsNormal)
578
-
579
- frame, lineno = frame_lineno
580
-
581
- return_value = ''
582
- loc_frame = self._get_frame_locals(frame)
583
- if "__return__" in loc_frame:
584
- rv = loc_frame["__return__"]
585
- # return_value += '->'
586
- return_value += reprlib.repr(rv) + "\n"
587
- ret.append(return_value)
588
-
589
- #s = filename + '(' + `lineno` + ')'
590
- filename = self.canonic(frame.f_code.co_filename)
591
- link = tpl_link % py3compat.cast_unicode(filename)
592
-
593
- if frame.f_code.co_name:
594
- func = frame.f_code.co_name
595
- else:
596
- func = "<lambda>"
597
-
598
- call = ""
599
- if func != "?":
600
- if "__args__" in loc_frame:
601
- args = reprlib.repr(loc_frame["__args__"])
602
- else:
603
- args = '()'
604
- call = tpl_call % (func, args)
605
-
606
- # The level info should be generated in the same format pdb uses, to
607
- # avoid breaking the pdbtrack functionality of python-mode in *emacs.
608
- if frame is self.curframe:
609
- ret.append('> ')
610
- else:
611
- ret.append(" ")
612
- ret.append("%s(%s)%s\n" % (link, lineno, call))
613
-
614
- start = lineno - 1 - context//2
615
- lines = linecache.getlines(filename)
616
- start = min(start, len(lines) - context)
617
- start = max(start, 0)
618
- lines = lines[start : start + context]
619
-
620
- for i, line in enumerate(lines):
621
- show_arrow = start + 1 + i == lineno
622
- linetpl = (frame is self.curframe or show_arrow) and tpl_line_em or tpl_line
623
- ret.append(
624
- self.__format_line(
625
- linetpl, filename, start + 1 + i, line, arrow=show_arrow
626
- )
627
- )
628
- return "".join(ret)
629
-
630
- def __format_line(self, tpl_line, filename, lineno, line, arrow=False):
631
- bp_mark = ""
632
- bp_mark_color = ""
633
-
634
- new_line, err = self.parser.format2(line, 'str')
635
- if not err:
636
- line = new_line
637
-
638
- bp = None
639
- if lineno in self.get_file_breaks(filename):
640
- bps = self.get_breaks(filename, lineno)
641
- bp = bps[-1]
642
-
643
- if bp:
644
- Colors = self.color_scheme_table.active_colors
645
- bp_mark = str(bp.number)
646
- bp_mark_color = Colors.breakpoint_enabled
647
- if not bp.enabled:
648
- bp_mark_color = Colors.breakpoint_disabled
649
-
650
- numbers_width = 7
651
- if arrow:
652
- # This is the line with the error
653
- pad = numbers_width - len(str(lineno)) - len(bp_mark)
654
- num = '%s%s' % (make_arrow(pad), str(lineno))
655
- else:
656
- num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
657
-
658
- return tpl_line % (bp_mark_color + bp_mark, num, line)
659
-
660
- def print_list_lines(self, filename, first, last):
661
- """The printing (as opposed to the parsing part of a 'list'
662
- command."""
663
- try:
664
- Colors = self.color_scheme_table.active_colors
665
- ColorsNormal = Colors.Normal
666
- tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
667
- tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
668
- src = []
669
- if filename == "<string>" and hasattr(self, "_exec_filename"):
670
- filename = self._exec_filename
671
-
672
- for lineno in range(first, last+1):
673
- line = linecache.getline(filename, lineno)
674
- if not line:
675
- break
676
-
677
- if lineno == self.curframe.f_lineno:
678
- line = self.__format_line(
679
- tpl_line_em, filename, lineno, line, arrow=True
680
- )
681
- else:
682
- line = self.__format_line(
683
- tpl_line, filename, lineno, line, arrow=False
684
- )
685
-
686
- src.append(line)
687
- self.lineno = lineno
688
-
689
- print(''.join(src), file=self.stdout)
690
-
691
- except KeyboardInterrupt:
692
- pass
693
-
694
- def do_skip_predicates(self, args):
695
- """
696
- Turn on/off individual predicates as to whether a frame should be hidden/skip.
697
-
698
- The global option to skip (or not) hidden frames is set with skip_hidden
699
-
700
- To change the value of a predicate
701
-
702
- skip_predicates key [true|false]
703
-
704
- Call without arguments to see the current values.
705
-
706
- To permanently change the value of an option add the corresponding
707
- command to your ``~/.pdbrc`` file. If you are programmatically using the
708
- Pdb instance you can also change the ``default_predicates`` class
709
- attribute.
710
- """
711
- if not args.strip():
712
- print("current predicates:")
713
- for p, v in self._predicates.items():
714
- print(" ", p, ":", v)
715
- return
716
- type_value = args.strip().split(" ")
717
- if len(type_value) != 2:
718
- print(
719
- f"Usage: skip_predicates <type> <value>, with <type> one of {set(self._predicates.keys())}"
720
- )
721
- return
722
-
723
- type_, value = type_value
724
- if type_ not in self._predicates:
725
- print(f"{type_!r} not in {set(self._predicates.keys())}")
726
- return
727
- if value.lower() not in ("true", "yes", "1", "no", "false", "0"):
728
- print(
729
- f"{value!r} is invalid - use one of ('true', 'yes', '1', 'no', 'false', '0')"
730
- )
731
- return
732
-
733
- self._predicates[type_] = value.lower() in ("true", "yes", "1")
734
- if not any(self._predicates.values()):
735
- print(
736
- "Warning, all predicates set to False, skip_hidden may not have any effects."
737
- )
738
-
739
- def do_skip_hidden(self, arg):
740
- """
741
- Change whether or not we should skip frames with the
742
- __tracebackhide__ attribute.
743
- """
744
- if not arg.strip():
745
- print(
746
- f"skip_hidden = {self.skip_hidden}, use 'yes','no', 'true', or 'false' to change."
747
- )
748
- elif arg.strip().lower() in ("true", "yes"):
749
- self.skip_hidden = True
750
- elif arg.strip().lower() in ("false", "no"):
751
- self.skip_hidden = False
752
- if not any(self._predicates.values()):
753
- print(
754
- "Warning, all predicates set to False, skip_hidden may not have any effects."
755
- )
756
-
757
- def do_list(self, arg):
758
- """Print lines of code from the current stack frame
759
- """
760
- self.lastcmd = 'list'
761
- last = None
762
- if arg and arg != ".":
763
- try:
764
- x = eval(arg, {}, {})
765
- if type(x) == type(()):
766
- first, last = x
767
- first = int(first)
768
- last = int(last)
769
- if last < first:
770
- # Assume it's a count
771
- last = first + last
772
- else:
773
- first = max(1, int(x) - 5)
774
- except:
775
- print('*** Error in argument:', repr(arg), file=self.stdout)
776
- return
777
- elif self.lineno is None or arg == ".":
778
- first = max(1, self.curframe.f_lineno - 5)
779
- else:
780
- first = self.lineno + 1
781
- if last is None:
782
- last = first + 10
783
- self.print_list_lines(self.curframe.f_code.co_filename, first, last)
784
-
785
- # vds: >>
786
- lineno = first
787
- filename = self.curframe.f_code.co_filename
788
- self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
789
- # vds: <<
790
-
791
- do_l = do_list
792
-
793
- def getsourcelines(self, obj):
794
- lines, lineno = inspect.findsource(obj)
795
- if inspect.isframe(obj) and obj.f_globals is self._get_frame_locals(obj):
796
- # must be a module frame: do not try to cut a block out of it
797
- return lines, 1
798
- elif inspect.ismodule(obj):
799
- return lines, 1
800
- return inspect.getblock(lines[lineno:]), lineno+1
801
-
802
- def do_longlist(self, arg):
803
- """Print lines of code from the current stack frame.
804
-
805
- Shows more lines than 'list' does.
806
- """
807
- self.lastcmd = 'longlist'
808
- try:
809
- lines, lineno = self.getsourcelines(self.curframe)
810
- except OSError as err:
811
- self.error(err)
812
- return
813
- last = lineno + len(lines)
814
- self.print_list_lines(self.curframe.f_code.co_filename, lineno, last)
815
- do_ll = do_longlist
816
-
817
- def do_debug(self, arg):
818
- """debug code
819
- Enter a recursive debugger that steps through the code
820
- argument (which is an arbitrary expression or statement to be
821
- executed in the current environment).
822
- """
823
- trace_function = sys.gettrace()
824
- sys.settrace(None)
825
- globals = self.curframe.f_globals
826
- locals = self.curframe_locals
827
- p = self.__class__(completekey=self.completekey,
828
- stdin=self.stdin, stdout=self.stdout)
829
- p.use_rawinput = self.use_rawinput
830
- p.prompt = "(%s) " % self.prompt.strip()
831
- self.message("ENTERING RECURSIVE DEBUGGER")
832
- sys.call_tracing(p.run, (arg, globals, locals))
833
- self.message("LEAVING RECURSIVE DEBUGGER")
834
- sys.settrace(trace_function)
835
- self.lastcmd = p.lastcmd
836
-
837
- def do_pdef(self, arg):
838
- """Print the call signature for any callable object.
839
-
840
- The debugger interface to %pdef"""
841
- namespaces = [
842
- ("Locals", self.curframe_locals),
843
- ("Globals", self.curframe.f_globals),
844
- ]
845
- self.shell.find_line_magic("pdef")(arg, namespaces=namespaces)
846
-
847
- def do_pdoc(self, arg):
848
- """Print the docstring for an object.
849
-
850
- The debugger interface to %pdoc."""
851
- namespaces = [
852
- ("Locals", self.curframe_locals),
853
- ("Globals", self.curframe.f_globals),
854
- ]
855
- self.shell.find_line_magic("pdoc")(arg, namespaces=namespaces)
856
-
857
- def do_pfile(self, arg):
858
- """Print (or run through pager) the file where an object is defined.
859
-
860
- The debugger interface to %pfile.
861
- """
862
- namespaces = [
863
- ("Locals", self.curframe_locals),
864
- ("Globals", self.curframe.f_globals),
865
- ]
866
- self.shell.find_line_magic("pfile")(arg, namespaces=namespaces)
867
-
868
- def do_pinfo(self, arg):
869
- """Provide detailed information about an object.
870
-
871
- The debugger interface to %pinfo, i.e., obj?."""
872
- namespaces = [
873
- ("Locals", self.curframe_locals),
874
- ("Globals", self.curframe.f_globals),
875
- ]
876
- self.shell.find_line_magic("pinfo")(arg, namespaces=namespaces)
877
-
878
- def do_pinfo2(self, arg):
879
- """Provide extra detailed information about an object.
880
-
881
- The debugger interface to %pinfo2, i.e., obj??."""
882
- namespaces = [
883
- ("Locals", self.curframe_locals),
884
- ("Globals", self.curframe.f_globals),
885
- ]
886
- self.shell.find_line_magic("pinfo2")(arg, namespaces=namespaces)
887
-
888
- def do_psource(self, arg):
889
- """Print (or run through pager) the source code for an object."""
890
- namespaces = [
891
- ("Locals", self.curframe_locals),
892
- ("Globals", self.curframe.f_globals),
893
- ]
894
- self.shell.find_line_magic("psource")(arg, namespaces=namespaces)
895
-
896
- def do_where(self, arg):
897
- """w(here)
898
- Print a stack trace, with the most recent frame at the bottom.
899
- An arrow indicates the "current frame", which determines the
900
- context of most commands. 'bt' is an alias for this command.
901
-
902
- Take a number as argument as an (optional) number of context line to
903
- print"""
904
- if arg:
905
- try:
906
- context = int(arg)
907
- except ValueError as err:
908
- self.error(err)
909
- return
910
- self.print_stack_trace(context)
911
- else:
912
- self.print_stack_trace()
913
-
914
- do_w = do_where
915
-
916
- def break_anywhere(self, frame):
917
- """
918
- _stop_in_decorator_internals is overly restrictive, as we may still want
919
- to trace function calls, so we need to also update break_anywhere so
920
- that is we don't `stop_here`, because of debugger skip, we may still
921
- stop at any point inside the function
922
-
923
- """
924
-
925
- sup = super().break_anywhere(frame)
926
- if sup:
927
- return sup
928
- if self._predicates["debuggerskip"]:
929
- if DEBUGGERSKIP in frame.f_code.co_varnames:
930
- return True
931
- if frame.f_back and self._get_frame_locals(frame.f_back).get(DEBUGGERSKIP):
932
- return True
933
- return False
934
-
935
- def _is_in_decorator_internal_and_should_skip(self, frame):
936
- """
937
- Utility to tell us whether we are in a decorator internal and should stop.
938
-
939
- """
940
- # if we are disabled don't skip
941
- if not self._predicates["debuggerskip"]:
942
- return False
943
-
944
- return self._cachable_skip(frame)
945
-
946
- @lru_cache(1024)
947
- def _cached_one_parent_frame_debuggerskip(self, frame):
948
- """
949
- Cache looking up for DEBUGGERSKIP on parent frame.
950
-
951
- This should speedup walking through deep frame when one of the highest
952
- one does have a debugger skip.
953
-
954
- This is likely to introduce fake positive though.
955
- """
956
- while getattr(frame, "f_back", None):
957
- frame = frame.f_back
958
- if self._get_frame_locals(frame).get(DEBUGGERSKIP):
959
- return True
960
- return None
961
-
962
- @lru_cache(1024)
963
- def _cachable_skip(self, frame):
964
- # if frame is tagged, skip by default.
965
- if DEBUGGERSKIP in frame.f_code.co_varnames:
966
- return True
967
-
968
- # if one of the parent frame value set to True skip as well.
969
- if self._cached_one_parent_frame_debuggerskip(frame):
970
- return True
971
-
972
- return False
973
-
974
- def stop_here(self, frame):
975
- if self._is_in_decorator_internal_and_should_skip(frame) is True:
976
- return False
977
-
978
- hidden = False
979
- if self.skip_hidden:
980
- hidden = self._hidden_predicate(frame)
981
- if hidden:
982
- if self.report_skipped:
983
- Colors = self.color_scheme_table.active_colors
984
- ColorsNormal = Colors.Normal
985
- print(
986
- f"{Colors.excName} [... skipped 1 hidden frame]{ColorsNormal}\n"
987
- )
988
- return super().stop_here(frame)
989
-
990
- def do_up(self, arg):
991
- """u(p) [count]
992
- Move the current frame count (default one) levels up in the
993
- stack trace (to an older frame).
994
-
995
- Will skip hidden frames.
996
- """
997
- # modified version of upstream that skips
998
- # frames with __tracebackhide__
999
- if self.curindex == 0:
1000
- self.error("Oldest frame")
1001
- return
1002
- try:
1003
- count = int(arg or 1)
1004
- except ValueError:
1005
- self.error("Invalid frame count (%s)" % arg)
1006
- return
1007
- skipped = 0
1008
- if count < 0:
1009
- _newframe = 0
1010
- else:
1011
- counter = 0
1012
- hidden_frames = self.hidden_frames(self.stack)
1013
- for i in range(self.curindex - 1, -1, -1):
1014
- if hidden_frames[i] and self.skip_hidden:
1015
- skipped += 1
1016
- continue
1017
- counter += 1
1018
- if counter >= count:
1019
- break
1020
- else:
1021
- # if no break occurred.
1022
- self.error(
1023
- "all frames above hidden, use `skip_hidden False` to get get into those."
1024
- )
1025
- return
1026
-
1027
- Colors = self.color_scheme_table.active_colors
1028
- ColorsNormal = Colors.Normal
1029
- _newframe = i
1030
- self._select_frame(_newframe)
1031
- if skipped:
1032
- print(
1033
- f"{Colors.excName} [... skipped {skipped} hidden frame(s)]{ColorsNormal}\n"
1034
- )
1035
-
1036
- def do_down(self, arg):
1037
- """d(own) [count]
1038
- Move the current frame count (default one) levels down in the
1039
- stack trace (to a newer frame).
1040
-
1041
- Will skip hidden frames.
1042
- """
1043
- if self.curindex + 1 == len(self.stack):
1044
- self.error("Newest frame")
1045
- return
1046
- try:
1047
- count = int(arg or 1)
1048
- except ValueError:
1049
- self.error("Invalid frame count (%s)" % arg)
1050
- return
1051
- if count < 0:
1052
- _newframe = len(self.stack) - 1
1053
- else:
1054
- counter = 0
1055
- skipped = 0
1056
- hidden_frames = self.hidden_frames(self.stack)
1057
- for i in range(self.curindex + 1, len(self.stack)):
1058
- if hidden_frames[i] and self.skip_hidden:
1059
- skipped += 1
1060
- continue
1061
- counter += 1
1062
- if counter >= count:
1063
- break
1064
- else:
1065
- self.error(
1066
- "all frames below hidden, use `skip_hidden False` to get get into those."
1067
- )
1068
- return
1069
-
1070
- Colors = self.color_scheme_table.active_colors
1071
- ColorsNormal = Colors.Normal
1072
- if skipped:
1073
- print(
1074
- f"{Colors.excName} [... skipped {skipped} hidden frame(s)]{ColorsNormal}\n"
1075
- )
1076
- _newframe = i
1077
-
1078
- self._select_frame(_newframe)
1079
-
1080
- do_d = do_down
1081
- do_u = do_up
1082
-
1083
- def do_context(self, context):
1084
- """context number_of_lines
1085
- Set the number of lines of source code to show when displaying
1086
- stacktrace information.
1087
- """
1088
- try:
1089
- new_context = int(context)
1090
- if new_context <= 0:
1091
- raise ValueError()
1092
- self.context = new_context
1093
- except ValueError:
1094
- self.error(
1095
- f"The 'context' command requires a positive integer argument (current value {self.context})."
1096
- )
1097
-
1098
-
1099
- class InterruptiblePdb(Pdb):
1100
- """Version of debugger where KeyboardInterrupt exits the debugger altogether."""
1101
-
1102
- def cmdloop(self, intro=None):
1103
- """Wrap cmdloop() such that KeyboardInterrupt stops the debugger."""
1104
- try:
1105
- return OldPdb.cmdloop(self, intro=intro)
1106
- except KeyboardInterrupt:
1107
- self.stop_here = lambda frame: False
1108
- self.do_quit("")
1109
- sys.settrace(None)
1110
- self.quitting = False
1111
- raise
1112
-
1113
- def _cmdloop(self):
1114
- while True:
1115
- try:
1116
- # keyboard interrupts allow for an easy way to cancel
1117
- # the current command, so allow them during interactive input
1118
- self.allow_kbdint = True
1119
- self.cmdloop()
1120
- self.allow_kbdint = False
1121
- break
1122
- except KeyboardInterrupt:
1123
- self.message('--KeyboardInterrupt--')
1124
- raise
1125
-
1126
-
1127
- def set_trace(frame=None, header=None):
1128
- """
1129
- Start debugging from `frame`.
1130
-
1131
- If frame is not specified, debugging starts from caller's frame.
1132
- """
1133
- pdb = Pdb()
1134
- if header is not None:
1135
- pdb.message(header)
1136
- pdb.set_trace(frame or sys._getframe().f_back)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/display.py DELETED
@@ -1,1373 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """Top-level display functions for displaying object in different formats."""
3
-
4
- # Copyright (c) IPython Development Team.
5
- # Distributed under the terms of the Modified BSD License.
6
-
7
-
8
- from binascii import b2a_base64, hexlify
9
- import html
10
- import json
11
- import mimetypes
12
- import os
13
- import struct
14
- import warnings
15
- from copy import deepcopy
16
- from os.path import splitext
17
- from pathlib import Path, PurePath
18
-
19
- from typing import Optional
20
-
21
- from IPython.testing.skipdoctest import skip_doctest
22
- from . import display_functions
23
-
24
-
25
- __all__ = [
26
- "display_pretty",
27
- "display_html",
28
- "display_markdown",
29
- "display_svg",
30
- "display_png",
31
- "display_jpeg",
32
- "display_webp",
33
- "display_latex",
34
- "display_json",
35
- "display_javascript",
36
- "display_pdf",
37
- "DisplayObject",
38
- "TextDisplayObject",
39
- "Pretty",
40
- "HTML",
41
- "Markdown",
42
- "Math",
43
- "Latex",
44
- "SVG",
45
- "ProgressBar",
46
- "JSON",
47
- "GeoJSON",
48
- "Javascript",
49
- "Image",
50
- "set_matplotlib_formats",
51
- "set_matplotlib_close",
52
- "Video",
53
- ]
54
-
55
- _deprecated_names = ["display", "clear_output", "publish_display_data", "update_display", "DisplayHandle"]
56
-
57
- __all__ = __all__ + _deprecated_names
58
-
59
-
60
- # ----- warn to import from IPython.display -----
61
-
62
- from warnings import warn
63
-
64
-
65
- def __getattr__(name):
66
- if name in _deprecated_names:
67
- warn(
68
- f"Importing {name} from IPython.core.display is deprecated since IPython 7.14, please import from IPython.display",
69
- DeprecationWarning,
70
- stacklevel=2,
71
- )
72
- return getattr(display_functions, name)
73
-
74
- if name in globals().keys():
75
- return globals()[name]
76
- else:
77
- raise AttributeError(f"module {__name__} has no attribute {name}")
78
-
79
-
80
- #-----------------------------------------------------------------------------
81
- # utility functions
82
- #-----------------------------------------------------------------------------
83
-
84
- def _safe_exists(path):
85
- """Check path, but don't let exceptions raise"""
86
- try:
87
- return os.path.exists(path)
88
- except Exception:
89
- return False
90
-
91
-
92
- def _display_mimetype(mimetype, objs, raw=False, metadata=None):
93
- """internal implementation of all display_foo methods
94
-
95
- Parameters
96
- ----------
97
- mimetype : str
98
- The mimetype to be published (e.g. 'image/png')
99
- *objs : object
100
- The Python objects to display, or if raw=True raw text data to
101
- display.
102
- raw : bool
103
- Are the data objects raw data or Python objects that need to be
104
- formatted before display? [default: False]
105
- metadata : dict (optional)
106
- Metadata to be associated with the specific mimetype output.
107
- """
108
- if metadata:
109
- metadata = {mimetype: metadata}
110
- if raw:
111
- # turn list of pngdata into list of { 'image/png': pngdata }
112
- objs = [ {mimetype: obj} for obj in objs ]
113
- display_functions.display(*objs, raw=raw, metadata=metadata, include=[mimetype])
114
-
115
- #-----------------------------------------------------------------------------
116
- # Main functions
117
- #-----------------------------------------------------------------------------
118
-
119
-
120
- def display_pretty(*objs, **kwargs):
121
- """Display the pretty (default) representation of an object.
122
-
123
- Parameters
124
- ----------
125
- *objs : object
126
- The Python objects to display, or if raw=True raw text data to
127
- display.
128
- raw : bool
129
- Are the data objects raw data or Python objects that need to be
130
- formatted before display? [default: False]
131
- metadata : dict (optional)
132
- Metadata to be associated with the specific mimetype output.
133
- """
134
- _display_mimetype('text/plain', objs, **kwargs)
135
-
136
-
137
- def display_html(*objs, **kwargs):
138
- """Display the HTML representation of an object.
139
-
140
- Note: If raw=False and the object does not have a HTML
141
- representation, no HTML will be shown.
142
-
143
- Parameters
144
- ----------
145
- *objs : object
146
- The Python objects to display, or if raw=True raw HTML data to
147
- display.
148
- raw : bool
149
- Are the data objects raw data or Python objects that need to be
150
- formatted before display? [default: False]
151
- metadata : dict (optional)
152
- Metadata to be associated with the specific mimetype output.
153
- """
154
- _display_mimetype('text/html', objs, **kwargs)
155
-
156
-
157
- def display_markdown(*objs, **kwargs):
158
- """Displays the Markdown representation of an object.
159
-
160
- Parameters
161
- ----------
162
- *objs : object
163
- The Python objects to display, or if raw=True raw markdown data to
164
- display.
165
- raw : bool
166
- Are the data objects raw data or Python objects that need to be
167
- formatted before display? [default: False]
168
- metadata : dict (optional)
169
- Metadata to be associated with the specific mimetype output.
170
- """
171
-
172
- _display_mimetype('text/markdown', objs, **kwargs)
173
-
174
-
175
- def display_svg(*objs, **kwargs):
176
- """Display the SVG representation of an object.
177
-
178
- Parameters
179
- ----------
180
- *objs : object
181
- The Python objects to display, or if raw=True raw svg data to
182
- display.
183
- raw : bool
184
- Are the data objects raw data or Python objects that need to be
185
- formatted before display? [default: False]
186
- metadata : dict (optional)
187
- Metadata to be associated with the specific mimetype output.
188
- """
189
- _display_mimetype('image/svg+xml', objs, **kwargs)
190
-
191
-
192
- def display_png(*objs, **kwargs):
193
- """Display the PNG representation of an object.
194
-
195
- Parameters
196
- ----------
197
- *objs : object
198
- The Python objects to display, or if raw=True raw png data to
199
- display.
200
- raw : bool
201
- Are the data objects raw data or Python objects that need to be
202
- formatted before display? [default: False]
203
- metadata : dict (optional)
204
- Metadata to be associated with the specific mimetype output.
205
- """
206
- _display_mimetype('image/png', objs, **kwargs)
207
-
208
-
209
- def display_jpeg(*objs, **kwargs):
210
- """Display the JPEG representation of an object.
211
-
212
- Parameters
213
- ----------
214
- *objs : object
215
- The Python objects to display, or if raw=True raw JPEG data to
216
- display.
217
- raw : bool
218
- Are the data objects raw data or Python objects that need to be
219
- formatted before display? [default: False]
220
- metadata : dict (optional)
221
- Metadata to be associated with the specific mimetype output.
222
- """
223
- _display_mimetype('image/jpeg', objs, **kwargs)
224
-
225
-
226
- def display_webp(*objs, **kwargs):
227
- """Display the WEBP representation of an object.
228
-
229
- Parameters
230
- ----------
231
- *objs : object
232
- The Python objects to display, or if raw=True raw JPEG data to
233
- display.
234
- raw : bool
235
- Are the data objects raw data or Python objects that need to be
236
- formatted before display? [default: False]
237
- metadata : dict (optional)
238
- Metadata to be associated with the specific mimetype output.
239
- """
240
- _display_mimetype("image/webp", objs, **kwargs)
241
-
242
-
243
- def display_latex(*objs, **kwargs):
244
- """Display the LaTeX representation of an object.
245
-
246
- Parameters
247
- ----------
248
- *objs : object
249
- The Python objects to display, or if raw=True raw latex data to
250
- display.
251
- raw : bool
252
- Are the data objects raw data or Python objects that need to be
253
- formatted before display? [default: False]
254
- metadata : dict (optional)
255
- Metadata to be associated with the specific mimetype output.
256
- """
257
- _display_mimetype('text/latex', objs, **kwargs)
258
-
259
-
260
- def display_json(*objs, **kwargs):
261
- """Display the JSON representation of an object.
262
-
263
- Note that not many frontends support displaying JSON.
264
-
265
- Parameters
266
- ----------
267
- *objs : object
268
- The Python objects to display, or if raw=True raw json data to
269
- display.
270
- raw : bool
271
- Are the data objects raw data or Python objects that need to be
272
- formatted before display? [default: False]
273
- metadata : dict (optional)
274
- Metadata to be associated with the specific mimetype output.
275
- """
276
- _display_mimetype('application/json', objs, **kwargs)
277
-
278
-
279
- def display_javascript(*objs, **kwargs):
280
- """Display the Javascript representation of an object.
281
-
282
- Parameters
283
- ----------
284
- *objs : object
285
- The Python objects to display, or if raw=True raw javascript data to
286
- display.
287
- raw : bool
288
- Are the data objects raw data or Python objects that need to be
289
- formatted before display? [default: False]
290
- metadata : dict (optional)
291
- Metadata to be associated with the specific mimetype output.
292
- """
293
- _display_mimetype('application/javascript', objs, **kwargs)
294
-
295
-
296
- def display_pdf(*objs, **kwargs):
297
- """Display the PDF representation of an object.
298
-
299
- Parameters
300
- ----------
301
- *objs : object
302
- The Python objects to display, or if raw=True raw javascript data to
303
- display.
304
- raw : bool
305
- Are the data objects raw data or Python objects that need to be
306
- formatted before display? [default: False]
307
- metadata : dict (optional)
308
- Metadata to be associated with the specific mimetype output.
309
- """
310
- _display_mimetype('application/pdf', objs, **kwargs)
311
-
312
-
313
- #-----------------------------------------------------------------------------
314
- # Smart classes
315
- #-----------------------------------------------------------------------------
316
-
317
-
318
- class DisplayObject(object):
319
- """An object that wraps data to be displayed."""
320
-
321
- _read_flags = 'r'
322
- _show_mem_addr = False
323
- metadata = None
324
-
325
- def __init__(self, data=None, url=None, filename=None, metadata=None):
326
- """Create a display object given raw data.
327
-
328
- When this object is returned by an expression or passed to the
329
- display function, it will result in the data being displayed
330
- in the frontend. The MIME type of the data should match the
331
- subclasses used, so the Png subclass should be used for 'image/png'
332
- data. If the data is a URL, the data will first be downloaded
333
- and then displayed.
334
-
335
- Parameters
336
- ----------
337
- data : unicode, str or bytes
338
- The raw data or a URL or file to load the data from
339
- url : unicode
340
- A URL to download the data from.
341
- filename : unicode
342
- Path to a local file to load the data from.
343
- metadata : dict
344
- Dict of metadata associated to be the object when displayed
345
- """
346
- if isinstance(data, (Path, PurePath)):
347
- data = str(data)
348
-
349
- if data is not None and isinstance(data, str):
350
- if data.startswith('http') and url is None:
351
- url = data
352
- filename = None
353
- data = None
354
- elif _safe_exists(data) and filename is None:
355
- url = None
356
- filename = data
357
- data = None
358
-
359
- self.url = url
360
- self.filename = filename
361
- # because of @data.setter methods in
362
- # subclasses ensure url and filename are set
363
- # before assigning to self.data
364
- self.data = data
365
-
366
- if metadata is not None:
367
- self.metadata = metadata
368
- elif self.metadata is None:
369
- self.metadata = {}
370
-
371
- self.reload()
372
- self._check_data()
373
-
374
- def __repr__(self):
375
- if not self._show_mem_addr:
376
- cls = self.__class__
377
- r = "<%s.%s object>" % (cls.__module__, cls.__name__)
378
- else:
379
- r = super(DisplayObject, self).__repr__()
380
- return r
381
-
382
- def _check_data(self):
383
- """Override in subclasses if there's something to check."""
384
- pass
385
-
386
- def _data_and_metadata(self):
387
- """shortcut for returning metadata with shape information, if defined"""
388
- if self.metadata:
389
- return self.data, deepcopy(self.metadata)
390
- else:
391
- return self.data
392
-
393
- def reload(self):
394
- """Reload the raw data from file or URL."""
395
- if self.filename is not None:
396
- encoding = None if "b" in self._read_flags else "utf-8"
397
- with open(self.filename, self._read_flags, encoding=encoding) as f:
398
- self.data = f.read()
399
- elif self.url is not None:
400
- # Deferred import
401
- from urllib.request import urlopen
402
- response = urlopen(self.url)
403
- data = response.read()
404
- # extract encoding from header, if there is one:
405
- encoding = None
406
- if 'content-type' in response.headers:
407
- for sub in response.headers['content-type'].split(';'):
408
- sub = sub.strip()
409
- if sub.startswith('charset'):
410
- encoding = sub.split('=')[-1].strip()
411
- break
412
- if 'content-encoding' in response.headers:
413
- # TODO: do deflate?
414
- if 'gzip' in response.headers['content-encoding']:
415
- import gzip
416
- from io import BytesIO
417
-
418
- # assume utf-8 if encoding is not specified
419
- with gzip.open(
420
- BytesIO(data), "rt", encoding=encoding or "utf-8"
421
- ) as fp:
422
- encoding = None
423
- data = fp.read()
424
-
425
- # decode data, if an encoding was specified
426
- # We only touch self.data once since
427
- # subclasses such as SVG have @data.setter methods
428
- # that transform self.data into ... well svg.
429
- if encoding:
430
- self.data = data.decode(encoding, 'replace')
431
- else:
432
- self.data = data
433
-
434
-
435
- class TextDisplayObject(DisplayObject):
436
- """Create a text display object given raw data.
437
-
438
- Parameters
439
- ----------
440
- data : str or unicode
441
- The raw data or a URL or file to load the data from.
442
- url : unicode
443
- A URL to download the data from.
444
- filename : unicode
445
- Path to a local file to load the data from.
446
- metadata : dict
447
- Dict of metadata associated to be the object when displayed
448
- """
449
- def _check_data(self):
450
- if self.data is not None and not isinstance(self.data, str):
451
- raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
452
-
453
- class Pretty(TextDisplayObject):
454
-
455
- def _repr_pretty_(self, pp, cycle):
456
- return pp.text(self.data)
457
-
458
-
459
- class HTML(TextDisplayObject):
460
-
461
- def __init__(self, data=None, url=None, filename=None, metadata=None):
462
- def warn():
463
- if not data:
464
- return False
465
-
466
- #
467
- # Avoid calling lower() on the entire data, because it could be a
468
- # long string and we're only interested in its beginning and end.
469
- #
470
- prefix = data[:10].lower()
471
- suffix = data[-10:].lower()
472
- return prefix.startswith("<iframe ") and suffix.endswith("</iframe>")
473
-
474
- if warn():
475
- warnings.warn("Consider using IPython.display.IFrame instead")
476
- super(HTML, self).__init__(data=data, url=url, filename=filename, metadata=metadata)
477
-
478
- def _repr_html_(self):
479
- return self._data_and_metadata()
480
-
481
- def __html__(self):
482
- """
483
- This method exists to inform other HTML-using modules (e.g. Markupsafe,
484
- htmltag, etc) that this object is HTML and does not need things like
485
- special characters (<>&) escaped.
486
- """
487
- return self._repr_html_()
488
-
489
-
490
- class Markdown(TextDisplayObject):
491
-
492
- def _repr_markdown_(self):
493
- return self._data_and_metadata()
494
-
495
-
496
- class Math(TextDisplayObject):
497
-
498
- def _repr_latex_(self):
499
- s = r"$\displaystyle %s$" % self.data.strip('$')
500
- if self.metadata:
501
- return s, deepcopy(self.metadata)
502
- else:
503
- return s
504
-
505
-
506
- class Latex(TextDisplayObject):
507
-
508
- def _repr_latex_(self):
509
- return self._data_and_metadata()
510
-
511
-
512
- class SVG(DisplayObject):
513
- """Embed an SVG into the display.
514
-
515
- Note if you just want to view a svg image via a URL use `:class:Image` with
516
- a url=URL keyword argument.
517
- """
518
-
519
- _read_flags = 'rb'
520
- # wrap data in a property, which extracts the <svg> tag, discarding
521
- # document headers
522
- _data: Optional[str] = None
523
-
524
- @property
525
- def data(self):
526
- return self._data
527
-
528
- @data.setter
529
- def data(self, svg):
530
- if svg is None:
531
- self._data = None
532
- return
533
- # parse into dom object
534
- from xml.dom import minidom
535
- x = minidom.parseString(svg)
536
- # get svg tag (should be 1)
537
- found_svg = x.getElementsByTagName('svg')
538
- if found_svg:
539
- svg = found_svg[0].toxml()
540
- else:
541
- # fallback on the input, trust the user
542
- # but this is probably an error.
543
- pass
544
- if isinstance(svg, bytes):
545
- self._data = svg.decode(errors="replace")
546
- else:
547
- self._data = svg
548
-
549
- def _repr_svg_(self):
550
- return self._data_and_metadata()
551
-
552
- class ProgressBar(DisplayObject):
553
- """Progressbar supports displaying a progressbar like element
554
- """
555
- def __init__(self, total):
556
- """Creates a new progressbar
557
-
558
- Parameters
559
- ----------
560
- total : int
561
- maximum size of the progressbar
562
- """
563
- self.total = total
564
- self._progress = 0
565
- self.html_width = '60ex'
566
- self.text_width = 60
567
- self._display_id = hexlify(os.urandom(8)).decode('ascii')
568
-
569
- def __repr__(self):
570
- fraction = self.progress / self.total
571
- filled = '=' * int(fraction * self.text_width)
572
- rest = ' ' * (self.text_width - len(filled))
573
- return '[{}{}] {}/{}'.format(
574
- filled, rest,
575
- self.progress, self.total,
576
- )
577
-
578
- def _repr_html_(self):
579
- return "<progress style='width:{}' max='{}' value='{}'></progress>".format(
580
- self.html_width, self.total, self.progress)
581
-
582
- def display(self):
583
- display_functions.display(self, display_id=self._display_id)
584
-
585
- def update(self):
586
- display_functions.display(self, display_id=self._display_id, update=True)
587
-
588
- @property
589
- def progress(self):
590
- return self._progress
591
-
592
- @progress.setter
593
- def progress(self, value):
594
- self._progress = value
595
- self.update()
596
-
597
- def __iter__(self):
598
- self.display()
599
- self._progress = -1 # First iteration is 0
600
- return self
601
-
602
- def __next__(self):
603
- """Returns current value and increments display by one."""
604
- self.progress += 1
605
- if self.progress < self.total:
606
- return self.progress
607
- else:
608
- raise StopIteration()
609
-
610
- class JSON(DisplayObject):
611
- """JSON expects a JSON-able dict or list
612
-
613
- not an already-serialized JSON string.
614
-
615
- Scalar types (None, number, string) are not allowed, only dict or list containers.
616
- """
617
- # wrap data in a property, which warns about passing already-serialized JSON
618
- _data = None
619
- def __init__(self, data=None, url=None, filename=None, expanded=False, metadata=None, root='root', **kwargs):
620
- """Create a JSON display object given raw data.
621
-
622
- Parameters
623
- ----------
624
- data : dict or list
625
- JSON data to display. Not an already-serialized JSON string.
626
- Scalar types (None, number, string) are not allowed, only dict
627
- or list containers.
628
- url : unicode
629
- A URL to download the data from.
630
- filename : unicode
631
- Path to a local file to load the data from.
632
- expanded : boolean
633
- Metadata to control whether a JSON display component is expanded.
634
- metadata : dict
635
- Specify extra metadata to attach to the json display object.
636
- root : str
637
- The name of the root element of the JSON tree
638
- """
639
- self.metadata = {
640
- 'expanded': expanded,
641
- 'root': root,
642
- }
643
- if metadata:
644
- self.metadata.update(metadata)
645
- if kwargs:
646
- self.metadata.update(kwargs)
647
- super(JSON, self).__init__(data=data, url=url, filename=filename)
648
-
649
- def _check_data(self):
650
- if self.data is not None and not isinstance(self.data, (dict, list)):
651
- raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
652
-
653
- @property
654
- def data(self):
655
- return self._data
656
-
657
- @data.setter
658
- def data(self, data):
659
- if isinstance(data, (Path, PurePath)):
660
- data = str(data)
661
-
662
- if isinstance(data, str):
663
- if self.filename is None and self.url is None:
664
- warnings.warn("JSON expects JSONable dict or list, not JSON strings")
665
- data = json.loads(data)
666
- self._data = data
667
-
668
- def _data_and_metadata(self):
669
- return self.data, self.metadata
670
-
671
- def _repr_json_(self):
672
- return self._data_and_metadata()
673
-
674
-
675
- _css_t = """var link = document.createElement("link");
676
- link.rel = "stylesheet";
677
- link.type = "text/css";
678
- link.href = "%s";
679
- document.head.appendChild(link);
680
- """
681
-
682
- _lib_t1 = """new Promise(function(resolve, reject) {
683
- var script = document.createElement("script");
684
- script.onload = resolve;
685
- script.onerror = reject;
686
- script.src = "%s";
687
- document.head.appendChild(script);
688
- }).then(() => {
689
- """
690
-
691
- _lib_t2 = """
692
- });"""
693
-
694
- class GeoJSON(JSON):
695
- """GeoJSON expects JSON-able dict
696
-
697
- not an already-serialized JSON string.
698
-
699
- Scalar types (None, number, string) are not allowed, only dict containers.
700
- """
701
-
702
- def __init__(self, *args, **kwargs):
703
- """Create a GeoJSON display object given raw data.
704
-
705
- Parameters
706
- ----------
707
- data : dict or list
708
- VegaLite data. Not an already-serialized JSON string.
709
- Scalar types (None, number, string) are not allowed, only dict
710
- or list containers.
711
- url_template : string
712
- Leaflet TileLayer URL template: http://leafletjs.com/reference.html#url-template
713
- layer_options : dict
714
- Leaflet TileLayer options: http://leafletjs.com/reference.html#tilelayer-options
715
- url : unicode
716
- A URL to download the data from.
717
- filename : unicode
718
- Path to a local file to load the data from.
719
- metadata : dict
720
- Specify extra metadata to attach to the json display object.
721
-
722
- Examples
723
- --------
724
- The following will display an interactive map of Mars with a point of
725
- interest on frontend that do support GeoJSON display.
726
-
727
- >>> from IPython.display import GeoJSON
728
-
729
- >>> GeoJSON(data={
730
- ... "type": "Feature",
731
- ... "geometry": {
732
- ... "type": "Point",
733
- ... "coordinates": [-81.327, 296.038]
734
- ... }
735
- ... },
736
- ... url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png",
737
- ... layer_options={
738
- ... "basemap_id": "celestia_mars-shaded-16k_global",
739
- ... "attribution" : "Celestia/praesepe",
740
- ... "minZoom" : 0,
741
- ... "maxZoom" : 18,
742
- ... })
743
- <IPython.core.display.GeoJSON object>
744
-
745
- In the terminal IPython, you will only see the text representation of
746
- the GeoJSON object.
747
-
748
- """
749
-
750
- super(GeoJSON, self).__init__(*args, **kwargs)
751
-
752
-
753
- def _ipython_display_(self):
754
- bundle = {
755
- 'application/geo+json': self.data,
756
- 'text/plain': '<IPython.display.GeoJSON object>'
757
- }
758
- metadata = {
759
- 'application/geo+json': self.metadata
760
- }
761
- display_functions.display(bundle, metadata=metadata, raw=True)
762
-
763
- class Javascript(TextDisplayObject):
764
-
765
- def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
766
- """Create a Javascript display object given raw data.
767
-
768
- When this object is returned by an expression or passed to the
769
- display function, it will result in the data being displayed
770
- in the frontend. If the data is a URL, the data will first be
771
- downloaded and then displayed.
772
-
773
- In the Notebook, the containing element will be available as `element`,
774
- and jQuery will be available. Content appended to `element` will be
775
- visible in the output area.
776
-
777
- Parameters
778
- ----------
779
- data : unicode, str or bytes
780
- The Javascript source code or a URL to download it from.
781
- url : unicode
782
- A URL to download the data from.
783
- filename : unicode
784
- Path to a local file to load the data from.
785
- lib : list or str
786
- A sequence of Javascript library URLs to load asynchronously before
787
- running the source code. The full URLs of the libraries should
788
- be given. A single Javascript library URL can also be given as a
789
- string.
790
- css : list or str
791
- A sequence of css files to load before running the source code.
792
- The full URLs of the css files should be given. A single css URL
793
- can also be given as a string.
794
- """
795
- if isinstance(lib, str):
796
- lib = [lib]
797
- elif lib is None:
798
- lib = []
799
- if isinstance(css, str):
800
- css = [css]
801
- elif css is None:
802
- css = []
803
- if not isinstance(lib, (list,tuple)):
804
- raise TypeError('expected sequence, got: %r' % lib)
805
- if not isinstance(css, (list,tuple)):
806
- raise TypeError('expected sequence, got: %r' % css)
807
- self.lib = lib
808
- self.css = css
809
- super(Javascript, self).__init__(data=data, url=url, filename=filename)
810
-
811
- def _repr_javascript_(self):
812
- r = ''
813
- for c in self.css:
814
- r += _css_t % c
815
- for l in self.lib:
816
- r += _lib_t1 % l
817
- r += self.data
818
- r += _lib_t2*len(self.lib)
819
- return r
820
-
821
-
822
- # constants for identifying png/jpeg/gif/webp data
823
- _PNG = b"\x89PNG\r\n\x1a\n"
824
- _JPEG = b"\xff\xd8"
825
- _GIF1 = b"GIF87a"
826
- _GIF2 = b"GIF89a"
827
- _WEBP = b"WEBP"
828
-
829
-
830
- def _pngxy(data):
831
- """read the (width, height) from a PNG header"""
832
- ihdr = data.index(b'IHDR')
833
- # next 8 bytes are width/height
834
- return struct.unpack('>ii', data[ihdr+4:ihdr+12])
835
-
836
-
837
- def _jpegxy(data):
838
- """read the (width, height) from a JPEG header"""
839
- # adapted from http://www.64lines.com/jpeg-width-height
840
-
841
- idx = 4
842
- while True:
843
- block_size = struct.unpack('>H', data[idx:idx+2])[0]
844
- idx = idx + block_size
845
- if data[idx:idx+2] == b'\xFF\xC0':
846
- # found Start of Frame
847
- iSOF = idx
848
- break
849
- else:
850
- # read another block
851
- idx += 2
852
-
853
- h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
854
- return w, h
855
-
856
-
857
- def _gifxy(data):
858
- """read the (width, height) from a GIF header"""
859
- return struct.unpack('<HH', data[6:10])
860
-
861
-
862
- def _webpxy(data):
863
- """read the (width, height) from a WEBP header"""
864
- if data[12:16] == b"VP8 ":
865
- width, height = struct.unpack("<HH", data[24:30])
866
- width = width & 0x3FFF
867
- height = height & 0x3FFF
868
- return (width, height)
869
- elif data[12:16] == b"VP8L":
870
- size_info = struct.unpack("<I", data[21:25])[0]
871
- width = 1 + ((size_info & 0x3F) << 8) | (size_info >> 24)
872
- height = 1 + (
873
- (((size_info >> 8) & 0xF) << 10)
874
- | (((size_info >> 14) & 0x3FC) << 2)
875
- | ((size_info >> 22) & 0x3)
876
- )
877
- return (width, height)
878
- else:
879
- raise ValueError("Not a valid WEBP header")
880
-
881
-
882
- class Image(DisplayObject):
883
-
884
- _read_flags = "rb"
885
- _FMT_JPEG = "jpeg"
886
- _FMT_PNG = "png"
887
- _FMT_GIF = "gif"
888
- _FMT_WEBP = "webp"
889
- _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG, _FMT_GIF, _FMT_WEBP]
890
- _MIMETYPES = {
891
- _FMT_PNG: "image/png",
892
- _FMT_JPEG: "image/jpeg",
893
- _FMT_GIF: "image/gif",
894
- _FMT_WEBP: "image/webp",
895
- }
896
-
897
- def __init__(
898
- self,
899
- data=None,
900
- url=None,
901
- filename=None,
902
- format=None,
903
- embed=None,
904
- width=None,
905
- height=None,
906
- retina=False,
907
- unconfined=False,
908
- metadata=None,
909
- alt=None,
910
- ):
911
- """Create a PNG/JPEG/GIF/WEBP image object given raw data.
912
-
913
- When this object is returned by an input cell or passed to the
914
- display function, it will result in the image being displayed
915
- in the frontend.
916
-
917
- Parameters
918
- ----------
919
- data : unicode, str or bytes
920
- The raw image data or a URL or filename to load the data from.
921
- This always results in embedded image data.
922
-
923
- url : unicode
924
- A URL to download the data from. If you specify `url=`,
925
- the image data will not be embedded unless you also specify `embed=True`.
926
-
927
- filename : unicode
928
- Path to a local file to load the data from.
929
- Images from a file are always embedded.
930
-
931
- format : unicode
932
- The format of the image data (png/jpeg/jpg/gif/webp). If a filename or URL is given
933
- for format will be inferred from the filename extension.
934
-
935
- embed : bool
936
- Should the image data be embedded using a data URI (True) or be
937
- loaded using an <img> tag. Set this to True if you want the image
938
- to be viewable later with no internet connection in the notebook.
939
-
940
- Default is `True`, unless the keyword argument `url` is set, then
941
- default value is `False`.
942
-
943
- Note that QtConsole is not able to display images if `embed` is set to `False`
944
-
945
- width : int
946
- Width in pixels to which to constrain the image in html
947
-
948
- height : int
949
- Height in pixels to which to constrain the image in html
950
-
951
- retina : bool
952
- Automatically set the width and height to half of the measured
953
- width and height.
954
- This only works for embedded images because it reads the width/height
955
- from image data.
956
- For non-embedded images, you can just set the desired display width
957
- and height directly.
958
-
959
- unconfined : bool
960
- Set unconfined=True to disable max-width confinement of the image.
961
-
962
- metadata : dict
963
- Specify extra metadata to attach to the image.
964
-
965
- alt : unicode
966
- Alternative text for the image, for use by screen readers.
967
-
968
- Examples
969
- --------
970
- embedded image data, works in qtconsole and notebook
971
- when passed positionally, the first arg can be any of raw image data,
972
- a URL, or a filename from which to load image data.
973
- The result is always embedding image data for inline images.
974
-
975
- >>> Image('https://www.google.fr/images/srpr/logo3w.png') # doctest: +SKIP
976
- <IPython.core.display.Image object>
977
-
978
- >>> Image('/path/to/image.jpg')
979
- <IPython.core.display.Image object>
980
-
981
- >>> Image(b'RAW_PNG_DATA...')
982
- <IPython.core.display.Image object>
983
-
984
- Specifying Image(url=...) does not embed the image data,
985
- it only generates ``<img>`` tag with a link to the source.
986
- This will not work in the qtconsole or offline.
987
-
988
- >>> Image(url='https://www.google.fr/images/srpr/logo3w.png')
989
- <IPython.core.display.Image object>
990
-
991
- """
992
- if isinstance(data, (Path, PurePath)):
993
- data = str(data)
994
-
995
- if filename is not None:
996
- ext = self._find_ext(filename)
997
- elif url is not None:
998
- ext = self._find_ext(url)
999
- elif data is None:
1000
- raise ValueError("No image data found. Expecting filename, url, or data.")
1001
- elif isinstance(data, str) and (
1002
- data.startswith('http') or _safe_exists(data)
1003
- ):
1004
- ext = self._find_ext(data)
1005
- else:
1006
- ext = None
1007
-
1008
- if format is None:
1009
- if ext is not None:
1010
- if ext == u'jpg' or ext == u'jpeg':
1011
- format = self._FMT_JPEG
1012
- elif ext == u'png':
1013
- format = self._FMT_PNG
1014
- elif ext == u'gif':
1015
- format = self._FMT_GIF
1016
- elif ext == "webp":
1017
- format = self._FMT_WEBP
1018
- else:
1019
- format = ext.lower()
1020
- elif isinstance(data, bytes):
1021
- # infer image type from image data header,
1022
- # only if format has not been specified.
1023
- if data[:2] == _JPEG:
1024
- format = self._FMT_JPEG
1025
- elif data[:8] == _PNG:
1026
- format = self._FMT_PNG
1027
- elif data[8:12] == _WEBP:
1028
- format = self._FMT_WEBP
1029
- elif data[:6] == _GIF1 or data[:6] == _GIF2:
1030
- format = self._FMT_GIF
1031
-
1032
- # failed to detect format, default png
1033
- if format is None:
1034
- format = self._FMT_PNG
1035
-
1036
- if format.lower() == 'jpg':
1037
- # jpg->jpeg
1038
- format = self._FMT_JPEG
1039
-
1040
- self.format = format.lower()
1041
- self.embed = embed if embed is not None else (url is None)
1042
-
1043
- if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
1044
- raise ValueError("Cannot embed the '%s' image format" % (self.format))
1045
- if self.embed:
1046
- self._mimetype = self._MIMETYPES.get(self.format)
1047
-
1048
- self.width = width
1049
- self.height = height
1050
- self.retina = retina
1051
- self.unconfined = unconfined
1052
- self.alt = alt
1053
- super(Image, self).__init__(data=data, url=url, filename=filename,
1054
- metadata=metadata)
1055
-
1056
- if self.width is None and self.metadata.get('width', {}):
1057
- self.width = metadata['width']
1058
-
1059
- if self.height is None and self.metadata.get('height', {}):
1060
- self.height = metadata['height']
1061
-
1062
- if self.alt is None and self.metadata.get("alt", {}):
1063
- self.alt = metadata["alt"]
1064
-
1065
- if retina:
1066
- self._retina_shape()
1067
-
1068
-
1069
- def _retina_shape(self):
1070
- """load pixel-doubled width and height from image data"""
1071
- if not self.embed:
1072
- return
1073
- if self.format == self._FMT_PNG:
1074
- w, h = _pngxy(self.data)
1075
- elif self.format == self._FMT_JPEG:
1076
- w, h = _jpegxy(self.data)
1077
- elif self.format == self._FMT_GIF:
1078
- w, h = _gifxy(self.data)
1079
- else:
1080
- # retina only supports png
1081
- return
1082
- self.width = w // 2
1083
- self.height = h // 2
1084
-
1085
- def reload(self):
1086
- """Reload the raw data from file or URL."""
1087
- if self.embed:
1088
- super(Image,self).reload()
1089
- if self.retina:
1090
- self._retina_shape()
1091
-
1092
- def _repr_html_(self):
1093
- if not self.embed:
1094
- width = height = klass = alt = ""
1095
- if self.width:
1096
- width = ' width="%d"' % self.width
1097
- if self.height:
1098
- height = ' height="%d"' % self.height
1099
- if self.unconfined:
1100
- klass = ' class="unconfined"'
1101
- if self.alt:
1102
- alt = ' alt="%s"' % html.escape(self.alt)
1103
- return '<img src="{url}"{width}{height}{klass}{alt}/>'.format(
1104
- url=self.url,
1105
- width=width,
1106
- height=height,
1107
- klass=klass,
1108
- alt=alt,
1109
- )
1110
-
1111
- def _repr_mimebundle_(self, include=None, exclude=None):
1112
- """Return the image as a mimebundle
1113
-
1114
- Any new mimetype support should be implemented here.
1115
- """
1116
- if self.embed:
1117
- mimetype = self._mimetype
1118
- data, metadata = self._data_and_metadata(always_both=True)
1119
- if metadata:
1120
- metadata = {mimetype: metadata}
1121
- return {mimetype: data}, metadata
1122
- else:
1123
- return {'text/html': self._repr_html_()}
1124
-
1125
- def _data_and_metadata(self, always_both=False):
1126
- """shortcut for returning metadata with shape information, if defined"""
1127
- try:
1128
- b64_data = b2a_base64(self.data, newline=False).decode("ascii")
1129
- except TypeError as e:
1130
- raise FileNotFoundError(
1131
- "No such file or directory: '%s'" % (self.data)) from e
1132
- md = {}
1133
- if self.metadata:
1134
- md.update(self.metadata)
1135
- if self.width:
1136
- md['width'] = self.width
1137
- if self.height:
1138
- md['height'] = self.height
1139
- if self.unconfined:
1140
- md['unconfined'] = self.unconfined
1141
- if self.alt:
1142
- md["alt"] = self.alt
1143
- if md or always_both:
1144
- return b64_data, md
1145
- else:
1146
- return b64_data
1147
-
1148
- def _repr_png_(self):
1149
- if self.embed and self.format == self._FMT_PNG:
1150
- return self._data_and_metadata()
1151
-
1152
- def _repr_jpeg_(self):
1153
- if self.embed and self.format == self._FMT_JPEG:
1154
- return self._data_and_metadata()
1155
-
1156
- def _find_ext(self, s):
1157
- base, ext = splitext(s)
1158
-
1159
- if not ext:
1160
- return base
1161
-
1162
- # `splitext` includes leading period, so we skip it
1163
- return ext[1:].lower()
1164
-
1165
-
1166
- class Video(DisplayObject):
1167
-
1168
- def __init__(self, data=None, url=None, filename=None, embed=False,
1169
- mimetype=None, width=None, height=None, html_attributes="controls"):
1170
- """Create a video object given raw data or an URL.
1171
-
1172
- When this object is returned by an input cell or passed to the
1173
- display function, it will result in the video being displayed
1174
- in the frontend.
1175
-
1176
- Parameters
1177
- ----------
1178
- data : unicode, str or bytes
1179
- The raw video data or a URL or filename to load the data from.
1180
- Raw data will require passing ``embed=True``.
1181
-
1182
- url : unicode
1183
- A URL for the video. If you specify ``url=``,
1184
- the image data will not be embedded.
1185
-
1186
- filename : unicode
1187
- Path to a local file containing the video.
1188
- Will be interpreted as a local URL unless ``embed=True``.
1189
-
1190
- embed : bool
1191
- Should the video be embedded using a data URI (True) or be
1192
- loaded using a <video> tag (False).
1193
-
1194
- Since videos are large, embedding them should be avoided, if possible.
1195
- You must confirm embedding as your intention by passing ``embed=True``.
1196
-
1197
- Local files can be displayed with URLs without embedding the content, via::
1198
-
1199
- Video('./video.mp4')
1200
-
1201
- mimetype : unicode
1202
- Specify the mimetype for embedded videos.
1203
- Default will be guessed from file extension, if available.
1204
-
1205
- width : int
1206
- Width in pixels to which to constrain the video in HTML.
1207
- If not supplied, defaults to the width of the video.
1208
-
1209
- height : int
1210
- Height in pixels to which to constrain the video in html.
1211
- If not supplied, defaults to the height of the video.
1212
-
1213
- html_attributes : str
1214
- Attributes for the HTML ``<video>`` block.
1215
- Default: ``"controls"`` to get video controls.
1216
- Other examples: ``"controls muted"`` for muted video with controls,
1217
- ``"loop autoplay"`` for looping autoplaying video without controls.
1218
-
1219
- Examples
1220
- --------
1221
- ::
1222
-
1223
- Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
1224
- Video('path/to/video.mp4')
1225
- Video('path/to/video.mp4', embed=True)
1226
- Video('path/to/video.mp4', embed=True, html_attributes="controls muted autoplay")
1227
- Video(b'raw-videodata', embed=True)
1228
- """
1229
- if isinstance(data, (Path, PurePath)):
1230
- data = str(data)
1231
-
1232
- if url is None and isinstance(data, str) and data.startswith(('http:', 'https:')):
1233
- url = data
1234
- data = None
1235
- elif data is not None and os.path.exists(data):
1236
- filename = data
1237
- data = None
1238
-
1239
- if data and not embed:
1240
- msg = ''.join([
1241
- "To embed videos, you must pass embed=True ",
1242
- "(this may make your notebook files huge)\n",
1243
- "Consider passing Video(url='...')",
1244
- ])
1245
- raise ValueError(msg)
1246
-
1247
- self.mimetype = mimetype
1248
- self.embed = embed
1249
- self.width = width
1250
- self.height = height
1251
- self.html_attributes = html_attributes
1252
- super(Video, self).__init__(data=data, url=url, filename=filename)
1253
-
1254
- def _repr_html_(self):
1255
- width = height = ''
1256
- if self.width:
1257
- width = ' width="%d"' % self.width
1258
- if self.height:
1259
- height = ' height="%d"' % self.height
1260
-
1261
- # External URLs and potentially local files are not embedded into the
1262
- # notebook output.
1263
- if not self.embed:
1264
- url = self.url if self.url is not None else self.filename
1265
- output = """<video src="{0}" {1} {2} {3}>
1266
- Your browser does not support the <code>video</code> element.
1267
- </video>""".format(url, self.html_attributes, width, height)
1268
- return output
1269
-
1270
- # Embedded videos are base64-encoded.
1271
- mimetype = self.mimetype
1272
- if self.filename is not None:
1273
- if not mimetype:
1274
- mimetype, _ = mimetypes.guess_type(self.filename)
1275
-
1276
- with open(self.filename, 'rb') as f:
1277
- video = f.read()
1278
- else:
1279
- video = self.data
1280
- if isinstance(video, str):
1281
- # unicode input is already b64-encoded
1282
- b64_video = video
1283
- else:
1284
- b64_video = b2a_base64(video, newline=False).decode("ascii").rstrip()
1285
-
1286
- output = """<video {0} {1} {2}>
1287
- <source src="data:{3};base64,{4}" type="{3}">
1288
- Your browser does not support the video tag.
1289
- </video>""".format(self.html_attributes, width, height, mimetype, b64_video)
1290
- return output
1291
-
1292
- def reload(self):
1293
- # TODO
1294
- pass
1295
-
1296
-
1297
- @skip_doctest
1298
- def set_matplotlib_formats(*formats, **kwargs):
1299
- """
1300
- .. deprecated:: 7.23
1301
-
1302
- use `matplotlib_inline.backend_inline.set_matplotlib_formats()`
1303
-
1304
- Select figure formats for the inline backend. Optionally pass quality for JPEG.
1305
-
1306
- For example, this enables PNG and JPEG output with a JPEG quality of 90%::
1307
-
1308
- In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
1309
-
1310
- To set this in your config files use the following::
1311
-
1312
- c.InlineBackend.figure_formats = {'png', 'jpeg'}
1313
- c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
1314
-
1315
- Parameters
1316
- ----------
1317
- *formats : strs
1318
- One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
1319
- **kwargs
1320
- Keyword args will be relayed to ``figure.canvas.print_figure``.
1321
- """
1322
- warnings.warn(
1323
- "`set_matplotlib_formats` is deprecated since IPython 7.23, directly "
1324
- "use `matplotlib_inline.backend_inline.set_matplotlib_formats()`",
1325
- DeprecationWarning,
1326
- stacklevel=2,
1327
- )
1328
-
1329
- from matplotlib_inline.backend_inline import (
1330
- set_matplotlib_formats as set_matplotlib_formats_orig,
1331
- )
1332
-
1333
- set_matplotlib_formats_orig(*formats, **kwargs)
1334
-
1335
- @skip_doctest
1336
- def set_matplotlib_close(close=True):
1337
- """
1338
- .. deprecated:: 7.23
1339
-
1340
- use `matplotlib_inline.backend_inline.set_matplotlib_close()`
1341
-
1342
- Set whether the inline backend closes all figures automatically or not.
1343
-
1344
- By default, the inline backend used in the IPython Notebook will close all
1345
- matplotlib figures automatically after each cell is run. This means that
1346
- plots in different cells won't interfere. Sometimes, you may want to make
1347
- a plot in one cell and then refine it in later cells. This can be accomplished
1348
- by::
1349
-
1350
- In [1]: set_matplotlib_close(False)
1351
-
1352
- To set this in your config files use the following::
1353
-
1354
- c.InlineBackend.close_figures = False
1355
-
1356
- Parameters
1357
- ----------
1358
- close : bool
1359
- Should all matplotlib figures be automatically closed after each cell is
1360
- run?
1361
- """
1362
- warnings.warn(
1363
- "`set_matplotlib_close` is deprecated since IPython 7.23, directly "
1364
- "use `matplotlib_inline.backend_inline.set_matplotlib_close()`",
1365
- DeprecationWarning,
1366
- stacklevel=2,
1367
- )
1368
-
1369
- from matplotlib_inline.backend_inline import (
1370
- set_matplotlib_close as set_matplotlib_close_orig,
1371
- )
1372
-
1373
- set_matplotlib_close_orig(close)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/display_functions.py DELETED
@@ -1,391 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """Top-level display functions for displaying object in different formats."""
3
-
4
- # Copyright (c) IPython Development Team.
5
- # Distributed under the terms of the Modified BSD License.
6
-
7
-
8
- from binascii import b2a_hex
9
- import os
10
- import sys
11
- import warnings
12
-
13
- __all__ = ['display', 'clear_output', 'publish_display_data', 'update_display', 'DisplayHandle']
14
-
15
- #-----------------------------------------------------------------------------
16
- # utility functions
17
- #-----------------------------------------------------------------------------
18
-
19
-
20
- def _merge(d1, d2):
21
- """Like update, but merges sub-dicts instead of clobbering at the top level.
22
-
23
- Updates d1 in-place
24
- """
25
-
26
- if not isinstance(d2, dict) or not isinstance(d1, dict):
27
- return d2
28
- for key, value in d2.items():
29
- d1[key] = _merge(d1.get(key), value)
30
- return d1
31
-
32
-
33
- #-----------------------------------------------------------------------------
34
- # Main functions
35
- #-----------------------------------------------------------------------------
36
-
37
- class _Sentinel:
38
- def __repr__(self):
39
- return "<deprecated>"
40
-
41
-
42
- _sentinel = _Sentinel()
43
-
44
- # use * to indicate transient is keyword-only
45
- def publish_display_data(
46
- data, metadata=None, source=_sentinel, *, transient=None, **kwargs
47
- ):
48
- """Publish data and metadata to all frontends.
49
-
50
- See the ``display_data`` message in the messaging documentation for
51
- more details about this message type.
52
-
53
- Keys of data and metadata can be any mime-type.
54
-
55
- Parameters
56
- ----------
57
- data : dict
58
- A dictionary having keys that are valid MIME types (like
59
- 'text/plain' or 'image/svg+xml') and values that are the data for
60
- that MIME type. The data itself must be a JSON'able data
61
- structure. Minimally all data should have the 'text/plain' data,
62
- which can be displayed by all frontends. If more than the plain
63
- text is given, it is up to the frontend to decide which
64
- representation to use.
65
- metadata : dict
66
- A dictionary for metadata related to the data. This can contain
67
- arbitrary key, value pairs that frontends can use to interpret
68
- the data. mime-type keys matching those in data can be used
69
- to specify metadata about particular representations.
70
- source : str, deprecated
71
- Unused.
72
- transient : dict, keyword-only
73
- A dictionary of transient data, such as display_id.
74
- """
75
- from IPython.core.interactiveshell import InteractiveShell
76
-
77
- if source is not _sentinel:
78
- warnings.warn(
79
- "The `source` parameter emit a deprecation warning since"
80
- " IPython 8.0, it had no effects for a long time and will "
81
- " be removed in future versions.",
82
- DeprecationWarning,
83
- stacklevel=2,
84
- )
85
- display_pub = InteractiveShell.instance().display_pub
86
-
87
- # only pass transient if supplied,
88
- # to avoid errors with older ipykernel.
89
- # TODO: We could check for ipykernel version and provide a detailed upgrade message.
90
- if transient:
91
- kwargs['transient'] = transient
92
-
93
- display_pub.publish(
94
- data=data,
95
- metadata=metadata,
96
- **kwargs
97
- )
98
-
99
-
100
- def _new_id():
101
- """Generate a new random text id with urandom"""
102
- return b2a_hex(os.urandom(16)).decode('ascii')
103
-
104
-
105
- def display(
106
- *objs,
107
- include=None,
108
- exclude=None,
109
- metadata=None,
110
- transient=None,
111
- display_id=None,
112
- raw=False,
113
- clear=False,
114
- **kwargs,
115
- ):
116
- """Display a Python object in all frontends.
117
-
118
- By default all representations will be computed and sent to the frontends.
119
- Frontends can decide which representation is used and how.
120
-
121
- In terminal IPython this will be similar to using :func:`print`, for use in richer
122
- frontends see Jupyter notebook examples with rich display logic.
123
-
124
- Parameters
125
- ----------
126
- *objs : object
127
- The Python objects to display.
128
- raw : bool, optional
129
- Are the objects to be displayed already mimetype-keyed dicts of raw display data,
130
- or Python objects that need to be formatted before display? [default: False]
131
- include : list, tuple or set, optional
132
- A list of format type strings (MIME types) to include in the
133
- format data dict. If this is set *only* the format types included
134
- in this list will be computed.
135
- exclude : list, tuple or set, optional
136
- A list of format type strings (MIME types) to exclude in the format
137
- data dict. If this is set all format types will be computed,
138
- except for those included in this argument.
139
- metadata : dict, optional
140
- A dictionary of metadata to associate with the output.
141
- mime-type keys in this dictionary will be associated with the individual
142
- representation formats, if they exist.
143
- transient : dict, optional
144
- A dictionary of transient data to associate with the output.
145
- Data in this dict should not be persisted to files (e.g. notebooks).
146
- display_id : str, bool optional
147
- Set an id for the display.
148
- This id can be used for updating this display area later via update_display.
149
- If given as `True`, generate a new `display_id`
150
- clear : bool, optional
151
- Should the output area be cleared before displaying anything? If True,
152
- this will wait for additional output before clearing. [default: False]
153
- **kwargs : additional keyword-args, optional
154
- Additional keyword-arguments are passed through to the display publisher.
155
-
156
- Returns
157
- -------
158
- handle: DisplayHandle
159
- Returns a handle on updatable displays for use with :func:`update_display`,
160
- if `display_id` is given. Returns :any:`None` if no `display_id` is given
161
- (default).
162
-
163
- Examples
164
- --------
165
- >>> class Json(object):
166
- ... def __init__(self, json):
167
- ... self.json = json
168
- ... def _repr_pretty_(self, pp, cycle):
169
- ... import json
170
- ... pp.text(json.dumps(self.json, indent=2))
171
- ... def __repr__(self):
172
- ... return str(self.json)
173
- ...
174
-
175
- >>> d = Json({1:2, 3: {4:5}})
176
-
177
- >>> print(d)
178
- {1: 2, 3: {4: 5}}
179
-
180
- >>> display(d)
181
- {
182
- "1": 2,
183
- "3": {
184
- "4": 5
185
- }
186
- }
187
-
188
- >>> def int_formatter(integer, pp, cycle):
189
- ... pp.text('I'*integer)
190
-
191
- >>> plain = get_ipython().display_formatter.formatters['text/plain']
192
- >>> plain.for_type(int, int_formatter)
193
- <function _repr_pprint at 0x...>
194
- >>> display(7-5)
195
- II
196
-
197
- >>> del plain.type_printers[int]
198
- >>> display(7-5)
199
- 2
200
-
201
- See Also
202
- --------
203
- :func:`update_display`
204
-
205
- Notes
206
- -----
207
- In Python, objects can declare their textual representation using the
208
- `__repr__` method. IPython expands on this idea and allows objects to declare
209
- other, rich representations including:
210
-
211
- - HTML
212
- - JSON
213
- - PNG
214
- - JPEG
215
- - SVG
216
- - LaTeX
217
-
218
- A single object can declare some or all of these representations; all are
219
- handled by IPython's display system.
220
-
221
- The main idea of the first approach is that you have to implement special
222
- display methods when you define your class, one for each representation you
223
- want to use. Here is a list of the names of the special methods and the
224
- values they must return:
225
-
226
- - `_repr_html_`: return raw HTML as a string, or a tuple (see below).
227
- - `_repr_json_`: return a JSONable dict, or a tuple (see below).
228
- - `_repr_jpeg_`: return raw JPEG data, or a tuple (see below).
229
- - `_repr_png_`: return raw PNG data, or a tuple (see below).
230
- - `_repr_svg_`: return raw SVG data as a string, or a tuple (see below).
231
- - `_repr_latex_`: return LaTeX commands in a string surrounded by "$",
232
- or a tuple (see below).
233
- - `_repr_mimebundle_`: return a full mimebundle containing the mapping
234
- from all mimetypes to data.
235
- Use this for any mime-type not listed above.
236
-
237
- The above functions may also return the object's metadata alonside the
238
- data. If the metadata is available, the functions will return a tuple
239
- containing the data and metadata, in that order. If there is no metadata
240
- available, then the functions will return the data only.
241
-
242
- When you are directly writing your own classes, you can adapt them for
243
- display in IPython by following the above approach. But in practice, you
244
- often need to work with existing classes that you can't easily modify.
245
-
246
- You can refer to the documentation on integrating with the display system in
247
- order to register custom formatters for already existing types
248
- (:ref:`integrating_rich_display`).
249
-
250
- .. versionadded:: 5.4 display available without import
251
- .. versionadded:: 6.1 display available without import
252
-
253
- Since IPython 5.4 and 6.1 :func:`display` is automatically made available to
254
- the user without import. If you are using display in a document that might
255
- be used in a pure python context or with older version of IPython, use the
256
- following import at the top of your file::
257
-
258
- from IPython.display import display
259
-
260
- """
261
- from IPython.core.interactiveshell import InteractiveShell
262
-
263
- if not InteractiveShell.initialized():
264
- # Directly print objects.
265
- print(*objs)
266
- return
267
-
268
- if transient is None:
269
- transient = {}
270
- if metadata is None:
271
- metadata={}
272
- if display_id:
273
- if display_id is True:
274
- display_id = _new_id()
275
- transient['display_id'] = display_id
276
- if kwargs.get('update') and 'display_id' not in transient:
277
- raise TypeError('display_id required for update_display')
278
- if transient:
279
- kwargs['transient'] = transient
280
-
281
- if not objs and display_id:
282
- # if given no objects, but still a request for a display_id,
283
- # we assume the user wants to insert an empty output that
284
- # can be updated later
285
- objs = [{}]
286
- raw = True
287
-
288
- if not raw:
289
- format = InteractiveShell.instance().display_formatter.format
290
-
291
- if clear:
292
- clear_output(wait=True)
293
-
294
- for obj in objs:
295
- if raw:
296
- publish_display_data(data=obj, metadata=metadata, **kwargs)
297
- else:
298
- format_dict, md_dict = format(obj, include=include, exclude=exclude)
299
- if not format_dict:
300
- # nothing to display (e.g. _ipython_display_ took over)
301
- continue
302
- if metadata:
303
- # kwarg-specified metadata gets precedence
304
- _merge(md_dict, metadata)
305
- publish_display_data(data=format_dict, metadata=md_dict, **kwargs)
306
- if display_id:
307
- return DisplayHandle(display_id)
308
-
309
-
310
- # use * for keyword-only display_id arg
311
- def update_display(obj, *, display_id, **kwargs):
312
- """Update an existing display by id
313
-
314
- Parameters
315
- ----------
316
- obj
317
- The object with which to update the display
318
- display_id : keyword-only
319
- The id of the display to update
320
-
321
- See Also
322
- --------
323
- :func:`display`
324
- """
325
- kwargs['update'] = True
326
- display(obj, display_id=display_id, **kwargs)
327
-
328
-
329
- class DisplayHandle(object):
330
- """A handle on an updatable display
331
-
332
- Call `.update(obj)` to display a new object.
333
-
334
- Call `.display(obj`) to add a new instance of this display,
335
- and update existing instances.
336
-
337
- See Also
338
- --------
339
-
340
- :func:`display`, :func:`update_display`
341
-
342
- """
343
-
344
- def __init__(self, display_id=None):
345
- if display_id is None:
346
- display_id = _new_id()
347
- self.display_id = display_id
348
-
349
- def __repr__(self):
350
- return "<%s display_id=%s>" % (self.__class__.__name__, self.display_id)
351
-
352
- def display(self, obj, **kwargs):
353
- """Make a new display with my id, updating existing instances.
354
-
355
- Parameters
356
- ----------
357
- obj
358
- object to display
359
- **kwargs
360
- additional keyword arguments passed to display
361
- """
362
- display(obj, display_id=self.display_id, **kwargs)
363
-
364
- def update(self, obj, **kwargs):
365
- """Update existing displays with my id
366
-
367
- Parameters
368
- ----------
369
- obj
370
- object to display
371
- **kwargs
372
- additional keyword arguments passed to update_display
373
- """
374
- update_display(obj, display_id=self.display_id, **kwargs)
375
-
376
-
377
- def clear_output(wait=False):
378
- """Clear the output of the current cell receiving output.
379
-
380
- Parameters
381
- ----------
382
- wait : bool [default: false]
383
- Wait to clear the output until new output is available to replace it."""
384
- from IPython.core.interactiveshell import InteractiveShell
385
- if InteractiveShell.initialized():
386
- InteractiveShell.instance().display_pub.clear_output(wait)
387
- else:
388
- print('\033[2K\r', end='')
389
- sys.stdout.flush()
390
- print('\033[2K\r', end='')
391
- sys.stderr.flush()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/display_trap.py DELETED
@@ -1,70 +0,0 @@
1
- # encoding: utf-8
2
- """
3
- A context manager for handling sys.displayhook.
4
-
5
- Authors:
6
-
7
- * Robert Kern
8
- * Brian Granger
9
- """
10
-
11
- #-----------------------------------------------------------------------------
12
- # Copyright (C) 2008-2011 The IPython Development Team
13
- #
14
- # Distributed under the terms of the BSD License. The full license is in
15
- # the file COPYING, distributed as part of this software.
16
- #-----------------------------------------------------------------------------
17
-
18
- #-----------------------------------------------------------------------------
19
- # Imports
20
- #-----------------------------------------------------------------------------
21
-
22
- import sys
23
-
24
- from traitlets.config.configurable import Configurable
25
- from traitlets import Any
26
-
27
- #-----------------------------------------------------------------------------
28
- # Classes and functions
29
- #-----------------------------------------------------------------------------
30
-
31
-
32
- class DisplayTrap(Configurable):
33
- """Object to manage sys.displayhook.
34
-
35
- This came from IPython.core.kernel.display_hook, but is simplified
36
- (no callbacks or formatters) until more of the core is refactored.
37
- """
38
-
39
- hook = Any()
40
-
41
- def __init__(self, hook=None):
42
- super(DisplayTrap, self).__init__(hook=hook, config=None)
43
- self.old_hook = None
44
- # We define this to track if a single BuiltinTrap is nested.
45
- # Only turn off the trap when the outermost call to __exit__ is made.
46
- self._nested_level = 0
47
-
48
- def __enter__(self):
49
- if self._nested_level == 0:
50
- self.set()
51
- self._nested_level += 1
52
- return self
53
-
54
- def __exit__(self, type, value, traceback):
55
- if self._nested_level == 1:
56
- self.unset()
57
- self._nested_level -= 1
58
- # Returning False will cause exceptions to propagate
59
- return False
60
-
61
- def set(self):
62
- """Set the hook."""
63
- if sys.displayhook is not self.hook:
64
- self.old_hook = sys.displayhook
65
- sys.displayhook = self.hook
66
-
67
- def unset(self):
68
- """Unset the hook."""
69
- sys.displayhook = self.old_hook
70
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/displayhook.py DELETED
@@ -1,336 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """Displayhook for IPython.
3
-
4
- This defines a callable class that IPython uses for `sys.displayhook`.
5
- """
6
-
7
- # Copyright (c) IPython Development Team.
8
- # Distributed under the terms of the Modified BSD License.
9
-
10
- import builtins as builtin_mod
11
- import sys
12
- import io as _io
13
- import tokenize
14
-
15
- from traitlets.config.configurable import Configurable
16
- from traitlets import Instance, Float
17
- from warnings import warn
18
-
19
- # TODO: Move the various attributes (cache_size, [others now moved]). Some
20
- # of these are also attributes of InteractiveShell. They should be on ONE object
21
- # only and the other objects should ask that one object for their values.
22
-
23
- class DisplayHook(Configurable):
24
- """The custom IPython displayhook to replace sys.displayhook.
25
-
26
- This class does many things, but the basic idea is that it is a callable
27
- that gets called anytime user code returns a value.
28
- """
29
-
30
- shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
31
- allow_none=True)
32
- exec_result = Instance('IPython.core.interactiveshell.ExecutionResult',
33
- allow_none=True)
34
- cull_fraction = Float(0.2)
35
-
36
- def __init__(self, shell=None, cache_size=1000, **kwargs):
37
- super(DisplayHook, self).__init__(shell=shell, **kwargs)
38
- cache_size_min = 3
39
- if cache_size <= 0:
40
- self.do_full_cache = 0
41
- cache_size = 0
42
- elif cache_size < cache_size_min:
43
- self.do_full_cache = 0
44
- cache_size = 0
45
- warn('caching was disabled (min value for cache size is %s).' %
46
- cache_size_min,stacklevel=3)
47
- else:
48
- self.do_full_cache = 1
49
-
50
- self.cache_size = cache_size
51
-
52
- # we need a reference to the user-level namespace
53
- self.shell = shell
54
-
55
- self._,self.__,self.___ = '','',''
56
-
57
- # these are deliberately global:
58
- to_user_ns = {'_':self._,'__':self.__,'___':self.___}
59
- self.shell.user_ns.update(to_user_ns)
60
-
61
- @property
62
- def prompt_count(self):
63
- return self.shell.execution_count
64
-
65
- #-------------------------------------------------------------------------
66
- # Methods used in __call__. Override these methods to modify the behavior
67
- # of the displayhook.
68
- #-------------------------------------------------------------------------
69
-
70
- def check_for_underscore(self):
71
- """Check if the user has set the '_' variable by hand."""
72
- # If something injected a '_' variable in __builtin__, delete
73
- # ipython's automatic one so we don't clobber that. gettext() in
74
- # particular uses _, so we need to stay away from it.
75
- if '_' in builtin_mod.__dict__:
76
- try:
77
- user_value = self.shell.user_ns['_']
78
- if user_value is not self._:
79
- return
80
- del self.shell.user_ns['_']
81
- except KeyError:
82
- pass
83
-
84
- def quiet(self):
85
- """Should we silence the display hook because of ';'?"""
86
- # do not print output if input ends in ';'
87
-
88
- try:
89
- cell = self.shell.history_manager.input_hist_parsed[-1]
90
- except IndexError:
91
- # some uses of ipshellembed may fail here
92
- return False
93
-
94
- return self.semicolon_at_end_of_expression(cell)
95
-
96
- @staticmethod
97
- def semicolon_at_end_of_expression(expression):
98
- """Parse Python expression and detects whether last token is ';'"""
99
-
100
- sio = _io.StringIO(expression)
101
- tokens = list(tokenize.generate_tokens(sio.readline))
102
-
103
- for token in reversed(tokens):
104
- if token[0] in (tokenize.ENDMARKER, tokenize.NL, tokenize.NEWLINE, tokenize.COMMENT):
105
- continue
106
- if (token[0] == tokenize.OP) and (token[1] == ';'):
107
- return True
108
- else:
109
- return False
110
-
111
- def start_displayhook(self):
112
- """Start the displayhook, initializing resources."""
113
- pass
114
-
115
- def write_output_prompt(self):
116
- """Write the output prompt.
117
-
118
- The default implementation simply writes the prompt to
119
- ``sys.stdout``.
120
- """
121
- # Use write, not print which adds an extra space.
122
- sys.stdout.write(self.shell.separate_out)
123
- outprompt = 'Out[{}]: '.format(self.shell.execution_count)
124
- if self.do_full_cache:
125
- sys.stdout.write(outprompt)
126
-
127
- def compute_format_data(self, result):
128
- """Compute format data of the object to be displayed.
129
-
130
- The format data is a generalization of the :func:`repr` of an object.
131
- In the default implementation the format data is a :class:`dict` of
132
- key value pair where the keys are valid MIME types and the values
133
- are JSON'able data structure containing the raw data for that MIME
134
- type. It is up to frontends to determine pick a MIME to to use and
135
- display that data in an appropriate manner.
136
-
137
- This method only computes the format data for the object and should
138
- NOT actually print or write that to a stream.
139
-
140
- Parameters
141
- ----------
142
- result : object
143
- The Python object passed to the display hook, whose format will be
144
- computed.
145
-
146
- Returns
147
- -------
148
- (format_dict, md_dict) : dict
149
- format_dict is a :class:`dict` whose keys are valid MIME types and values are
150
- JSON'able raw data for that MIME type. It is recommended that
151
- all return values of this should always include the "text/plain"
152
- MIME type representation of the object.
153
- md_dict is a :class:`dict` with the same MIME type keys
154
- of metadata associated with each output.
155
-
156
- """
157
- return self.shell.display_formatter.format(result)
158
-
159
- # This can be set to True by the write_output_prompt method in a subclass
160
- prompt_end_newline = False
161
-
162
- def write_format_data(self, format_dict, md_dict=None) -> None:
163
- """Write the format data dict to the frontend.
164
-
165
- This default version of this method simply writes the plain text
166
- representation of the object to ``sys.stdout``. Subclasses should
167
- override this method to send the entire `format_dict` to the
168
- frontends.
169
-
170
- Parameters
171
- ----------
172
- format_dict : dict
173
- The format dict for the object passed to `sys.displayhook`.
174
- md_dict : dict (optional)
175
- The metadata dict to be associated with the display data.
176
- """
177
- if 'text/plain' not in format_dict:
178
- # nothing to do
179
- return
180
- # We want to print because we want to always make sure we have a
181
- # newline, even if all the prompt separators are ''. This is the
182
- # standard IPython behavior.
183
- result_repr = format_dict['text/plain']
184
- if '\n' in result_repr:
185
- # So that multi-line strings line up with the left column of
186
- # the screen, instead of having the output prompt mess up
187
- # their first line.
188
- # We use the prompt template instead of the expanded prompt
189
- # because the expansion may add ANSI escapes that will interfere
190
- # with our ability to determine whether or not we should add
191
- # a newline.
192
- if not self.prompt_end_newline:
193
- # But avoid extraneous empty lines.
194
- result_repr = '\n' + result_repr
195
-
196
- try:
197
- print(result_repr)
198
- except UnicodeEncodeError:
199
- # If a character is not supported by the terminal encoding replace
200
- # it with its \u or \x representation
201
- print(result_repr.encode(sys.stdout.encoding,'backslashreplace').decode(sys.stdout.encoding))
202
-
203
- def update_user_ns(self, result):
204
- """Update user_ns with various things like _, __, _1, etc."""
205
-
206
- # Avoid recursive reference when displaying _oh/Out
207
- if self.cache_size and result is not self.shell.user_ns['_oh']:
208
- if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
209
- self.cull_cache()
210
-
211
- # Don't overwrite '_' and friends if '_' is in __builtin__
212
- # (otherwise we cause buggy behavior for things like gettext). and
213
- # do not overwrite _, __ or ___ if one of these has been assigned
214
- # by the user.
215
- update_unders = True
216
- for unders in ['_'*i for i in range(1,4)]:
217
- if not unders in self.shell.user_ns:
218
- continue
219
- if getattr(self, unders) is not self.shell.user_ns.get(unders):
220
- update_unders = False
221
-
222
- self.___ = self.__
223
- self.__ = self._
224
- self._ = result
225
-
226
- if ('_' not in builtin_mod.__dict__) and (update_unders):
227
- self.shell.push({'_':self._,
228
- '__':self.__,
229
- '___':self.___}, interactive=False)
230
-
231
- # hackish access to top-level namespace to create _1,_2... dynamically
232
- to_main = {}
233
- if self.do_full_cache:
234
- new_result = '_%s' % self.prompt_count
235
- to_main[new_result] = result
236
- self.shell.push(to_main, interactive=False)
237
- self.shell.user_ns['_oh'][self.prompt_count] = result
238
-
239
- def fill_exec_result(self, result):
240
- if self.exec_result is not None:
241
- self.exec_result.result = result
242
-
243
- def log_output(self, format_dict):
244
- """Log the output."""
245
- if 'text/plain' not in format_dict:
246
- # nothing to do
247
- return
248
- if self.shell.logger.log_output:
249
- self.shell.logger.log_write(format_dict['text/plain'], 'output')
250
- self.shell.history_manager.output_hist_reprs[self.prompt_count] = \
251
- format_dict['text/plain']
252
-
253
- def finish_displayhook(self):
254
- """Finish up all displayhook activities."""
255
- sys.stdout.write(self.shell.separate_out2)
256
- sys.stdout.flush()
257
-
258
- def __call__(self, result=None):
259
- """Printing with history cache management.
260
-
261
- This is invoked every time the interpreter needs to print, and is
262
- activated by setting the variable sys.displayhook to it.
263
- """
264
- self.check_for_underscore()
265
- if result is not None and not self.quiet():
266
- self.start_displayhook()
267
- self.write_output_prompt()
268
- format_dict, md_dict = self.compute_format_data(result)
269
- self.update_user_ns(result)
270
- self.fill_exec_result(result)
271
- if format_dict:
272
- self.write_format_data(format_dict, md_dict)
273
- self.log_output(format_dict)
274
- self.finish_displayhook()
275
-
276
- def cull_cache(self):
277
- """Output cache is full, cull the oldest entries"""
278
- oh = self.shell.user_ns.get('_oh', {})
279
- sz = len(oh)
280
- cull_count = max(int(sz * self.cull_fraction), 2)
281
- warn('Output cache limit (currently {sz} entries) hit.\n'
282
- 'Flushing oldest {cull_count} entries.'.format(sz=sz, cull_count=cull_count))
283
-
284
- for i, n in enumerate(sorted(oh)):
285
- if i >= cull_count:
286
- break
287
- self.shell.user_ns.pop('_%i' % n, None)
288
- oh.pop(n, None)
289
-
290
-
291
- def flush(self):
292
- if not self.do_full_cache:
293
- raise ValueError("You shouldn't have reached the cache flush "
294
- "if full caching is not enabled!")
295
- # delete auto-generated vars from global namespace
296
-
297
- for n in range(1,self.prompt_count + 1):
298
- key = '_'+repr(n)
299
- try:
300
- del self.shell.user_ns_hidden[key]
301
- except KeyError:
302
- pass
303
- try:
304
- del self.shell.user_ns[key]
305
- except KeyError:
306
- pass
307
- # In some embedded circumstances, the user_ns doesn't have the
308
- # '_oh' key set up.
309
- oh = self.shell.user_ns.get('_oh', None)
310
- if oh is not None:
311
- oh.clear()
312
-
313
- # Release our own references to objects:
314
- self._, self.__, self.___ = '', '', ''
315
-
316
- if '_' not in builtin_mod.__dict__:
317
- self.shell.user_ns.update({'_':self._,'__':self.__,'___':self.___})
318
- import gc
319
- # TODO: Is this really needed?
320
- # IronPython blocks here forever
321
- if sys.platform != "cli":
322
- gc.collect()
323
-
324
-
325
- class CapturingDisplayHook(object):
326
- def __init__(self, shell, outputs=None):
327
- self.shell = shell
328
- if outputs is None:
329
- outputs = []
330
- self.outputs = outputs
331
-
332
- def __call__(self, result=None):
333
- if result is None:
334
- return
335
- format_dict, md_dict = self.shell.display_formatter.format(result)
336
- self.outputs.append({ 'data': format_dict, 'metadata': md_dict })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/displaypub.py DELETED
@@ -1,149 +0,0 @@
1
- """An interface for publishing rich data to frontends.
2
-
3
- There are two components of the display system:
4
-
5
- * Display formatters, which take a Python object and compute the
6
- representation of the object in various formats (text, HTML, SVG, etc.).
7
- * The display publisher that is used to send the representation data to the
8
- various frontends.
9
-
10
- This module defines the logic display publishing. The display publisher uses
11
- the ``display_data`` message type that is defined in the IPython messaging
12
- spec.
13
- """
14
-
15
- # Copyright (c) IPython Development Team.
16
- # Distributed under the terms of the Modified BSD License.
17
-
18
-
19
- import sys
20
-
21
- from traitlets.config.configurable import Configurable
22
- from traitlets import List
23
-
24
- # This used to be defined here - it is imported for backwards compatibility
25
- from .display_functions import publish_display_data
26
-
27
- import typing as t
28
-
29
- # -----------------------------------------------------------------------------
30
- # Main payload class
31
- #-----------------------------------------------------------------------------
32
-
33
-
34
- class DisplayPublisher(Configurable):
35
- """A traited class that publishes display data to frontends.
36
-
37
- Instances of this class are created by the main IPython object and should
38
- be accessed there.
39
- """
40
-
41
- def __init__(self, shell=None, *args, **kwargs):
42
- self.shell = shell
43
- super().__init__(*args, **kwargs)
44
-
45
- def _validate_data(self, data, metadata=None):
46
- """Validate the display data.
47
-
48
- Parameters
49
- ----------
50
- data : dict
51
- The formata data dictionary.
52
- metadata : dict
53
- Any metadata for the data.
54
- """
55
-
56
- if not isinstance(data, dict):
57
- raise TypeError('data must be a dict, got: %r' % data)
58
- if metadata is not None:
59
- if not isinstance(metadata, dict):
60
- raise TypeError('metadata must be a dict, got: %r' % data)
61
-
62
- # use * to indicate transient, update are keyword-only
63
- def publish(self, data, metadata=None, source=None, *, transient=None, update=False, **kwargs) -> None:
64
- """Publish data and metadata to all frontends.
65
-
66
- See the ``display_data`` message in the messaging documentation for
67
- more details about this message type.
68
-
69
- The following MIME types are currently implemented:
70
-
71
- * text/plain
72
- * text/html
73
- * text/markdown
74
- * text/latex
75
- * application/json
76
- * application/javascript
77
- * image/png
78
- * image/jpeg
79
- * image/svg+xml
80
-
81
- Parameters
82
- ----------
83
- data : dict
84
- A dictionary having keys that are valid MIME types (like
85
- 'text/plain' or 'image/svg+xml') and values that are the data for
86
- that MIME type. The data itself must be a JSON'able data
87
- structure. Minimally all data should have the 'text/plain' data,
88
- which can be displayed by all frontends. If more than the plain
89
- text is given, it is up to the frontend to decide which
90
- representation to use.
91
- metadata : dict
92
- A dictionary for metadata related to the data. This can contain
93
- arbitrary key, value pairs that frontends can use to interpret
94
- the data. Metadata specific to each mime-type can be specified
95
- in the metadata dict with the same mime-type keys as
96
- the data itself.
97
- source : str, deprecated
98
- Unused.
99
- transient : dict, keyword-only
100
- A dictionary for transient data.
101
- Data in this dictionary should not be persisted as part of saving this output.
102
- Examples include 'display_id'.
103
- update : bool, keyword-only, default: False
104
- If True, only update existing outputs with the same display_id,
105
- rather than creating a new output.
106
- """
107
-
108
- handlers: t.Dict = {}
109
- if self.shell is not None:
110
- handlers = getattr(self.shell, "mime_renderers", {})
111
-
112
- for mime, handler in handlers.items():
113
- if mime in data:
114
- handler(data[mime], metadata.get(mime, None))
115
- return
116
-
117
- if 'text/plain' in data:
118
- print(data['text/plain'])
119
-
120
- def clear_output(self, wait=False):
121
- """Clear the output of the cell receiving output."""
122
- print('\033[2K\r', end='')
123
- sys.stdout.flush()
124
- print('\033[2K\r', end='')
125
- sys.stderr.flush()
126
-
127
-
128
- class CapturingDisplayPublisher(DisplayPublisher):
129
- """A DisplayPublisher that stores"""
130
-
131
- outputs: List = List()
132
-
133
- def publish(
134
- self, data, metadata=None, source=None, *, transient=None, update=False
135
- ):
136
- self.outputs.append(
137
- {
138
- "data": data,
139
- "metadata": metadata,
140
- "transient": transient,
141
- "update": update,
142
- }
143
- )
144
-
145
- def clear_output(self, wait=False):
146
- super(CapturingDisplayPublisher, self).clear_output(wait)
147
-
148
- # empty the list, *do not* reassign a new list
149
- self.outputs.clear()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/error.py DELETED
@@ -1,60 +0,0 @@
1
- # encoding: utf-8
2
- """
3
- Global exception classes for IPython.core.
4
-
5
- Authors:
6
-
7
- * Brian Granger
8
- * Fernando Perez
9
- * Min Ragan-Kelley
10
-
11
- Notes
12
- -----
13
- """
14
-
15
- #-----------------------------------------------------------------------------
16
- # Copyright (C) 2008 The IPython Development Team
17
- #
18
- # Distributed under the terms of the BSD License. The full license is in
19
- # the file COPYING, distributed as part of this software.
20
- #-----------------------------------------------------------------------------
21
-
22
- #-----------------------------------------------------------------------------
23
- # Imports
24
- #-----------------------------------------------------------------------------
25
-
26
- #-----------------------------------------------------------------------------
27
- # Exception classes
28
- #-----------------------------------------------------------------------------
29
-
30
- class IPythonCoreError(Exception):
31
- pass
32
-
33
-
34
- class TryNext(IPythonCoreError):
35
- """Try next hook exception.
36
-
37
- Raise this in your hook function to indicate that the next hook handler
38
- should be used to handle the operation.
39
- """
40
-
41
- class UsageError(IPythonCoreError):
42
- """Error in magic function arguments, etc.
43
-
44
- Something that probably won't warrant a full traceback, but should
45
- nevertheless interrupt a macro / batch file.
46
- """
47
-
48
- class StdinNotImplementedError(IPythonCoreError, NotImplementedError):
49
- """raw_input was requested in a context where it is not supported
50
-
51
- For use in IPython kernels, where only some frontends may support
52
- stdin requests.
53
- """
54
-
55
- class InputRejected(Exception):
56
- """Input rejected by ast transformer.
57
-
58
- Raise this in your NodeTransformer to indicate that InteractiveShell should
59
- not execute the supplied input.
60
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/events.py DELETED
@@ -1,158 +0,0 @@
1
- """Infrastructure for registering and firing callbacks on application events.
2
-
3
- Unlike :mod:`IPython.core.hooks`, which lets end users set single functions to
4
- be called at specific times, or a collection of alternative methods to try,
5
- callbacks are designed to be used by extension authors. A number of callbacks
6
- can be registered for the same event without needing to be aware of one another.
7
-
8
- The functions defined in this module are no-ops indicating the names of available
9
- events and the arguments which will be passed to them.
10
-
11
- .. note::
12
-
13
- This API is experimental in IPython 2.0, and may be revised in future versions.
14
- """
15
-
16
-
17
- class EventManager(object):
18
- """Manage a collection of events and a sequence of callbacks for each.
19
-
20
- This is attached to :class:`~IPython.core.interactiveshell.InteractiveShell`
21
- instances as an ``events`` attribute.
22
-
23
- .. note::
24
-
25
- This API is experimental in IPython 2.0, and may be revised in future versions.
26
- """
27
-
28
- def __init__(self, shell, available_events, print_on_error=True):
29
- """Initialise the :class:`CallbackManager`.
30
-
31
- Parameters
32
- ----------
33
- shell
34
- The :class:`~IPython.core.interactiveshell.InteractiveShell` instance
35
- available_events
36
- An iterable of names for callback events.
37
- print_on_error:
38
- A boolean flag to set whether the EventManager will print a warning which a event errors.
39
- """
40
- self.shell = shell
41
- self.callbacks = {n:[] for n in available_events}
42
- self.print_on_error = print_on_error
43
-
44
- def register(self, event, function):
45
- """Register a new event callback.
46
-
47
- Parameters
48
- ----------
49
- event : str
50
- The event for which to register this callback.
51
- function : callable
52
- A function to be called on the given event. It should take the same
53
- parameters as the appropriate callback prototype.
54
-
55
- Raises
56
- ------
57
- TypeError
58
- If ``function`` is not callable.
59
- KeyError
60
- If ``event`` is not one of the known events.
61
- """
62
- if not callable(function):
63
- raise TypeError('Need a callable, got %r' % function)
64
- if function not in self.callbacks[event]:
65
- self.callbacks[event].append(function)
66
-
67
- def unregister(self, event, function):
68
- """Remove a callback from the given event."""
69
- if function in self.callbacks[event]:
70
- return self.callbacks[event].remove(function)
71
-
72
- raise ValueError('Function {!r} is not registered as a {} callback'.format(function, event))
73
-
74
- def trigger(self, event, *args, **kwargs):
75
- """Call callbacks for ``event``.
76
-
77
- Any additional arguments are passed to all callbacks registered for this
78
- event. Exceptions raised by callbacks are caught, and a message printed.
79
- """
80
- for func in self.callbacks[event][:]:
81
- try:
82
- func(*args, **kwargs)
83
- except (Exception, KeyboardInterrupt):
84
- if self.print_on_error:
85
- print(
86
- "Error in callback {} (for {}), with arguments args {},kwargs {}:".format(
87
- func, event, args, kwargs
88
- )
89
- )
90
- self.shell.showtraceback()
91
-
92
- # event_name -> prototype mapping
93
- available_events = {}
94
-
95
- def _define_event(callback_function):
96
- available_events[callback_function.__name__] = callback_function
97
- return callback_function
98
-
99
- # ------------------------------------------------------------------------------
100
- # Callback prototypes
101
- #
102
- # No-op functions which describe the names of available events and the
103
- # signatures of callbacks for those events.
104
- # ------------------------------------------------------------------------------
105
-
106
- @_define_event
107
- def pre_execute():
108
- """Fires before code is executed in response to user/frontend action.
109
-
110
- This includes comm and widget messages and silent execution, as well as user
111
- code cells.
112
- """
113
- pass
114
-
115
- @_define_event
116
- def pre_run_cell(info):
117
- """Fires before user-entered code runs.
118
-
119
- Parameters
120
- ----------
121
- info : :class:`~IPython.core.interactiveshell.ExecutionInfo`
122
- An object containing information used for the code execution.
123
- """
124
- pass
125
-
126
- @_define_event
127
- def post_execute():
128
- """Fires after code is executed in response to user/frontend action.
129
-
130
- This includes comm and widget messages and silent execution, as well as user
131
- code cells.
132
- """
133
- pass
134
-
135
- @_define_event
136
- def post_run_cell(result):
137
- """Fires after user-entered code runs.
138
-
139
- Parameters
140
- ----------
141
- result : :class:`~IPython.core.interactiveshell.ExecutionResult`
142
- The object which will be returned as the execution result.
143
- """
144
- pass
145
-
146
- @_define_event
147
- def shell_initialized(ip):
148
- """Fires after initialisation of :class:`~IPython.core.interactiveshell.InteractiveShell`.
149
-
150
- This is before extensions and startup scripts are loaded, so it can only be
151
- set by subclassing.
152
-
153
- Parameters
154
- ----------
155
- ip : :class:`~IPython.core.interactiveshell.InteractiveShell`
156
- The newly initialised shell.
157
- """
158
- pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/excolors.py DELETED
@@ -1,192 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """
3
- Color schemes for exception handling code in IPython.
4
- """
5
-
6
- import os
7
-
8
- #*****************************************************************************
9
- # Copyright (C) 2005-2006 Fernando Perez <[email protected]>
10
- #
11
- # Distributed under the terms of the BSD License. The full license is in
12
- # the file COPYING, distributed as part of this software.
13
- #*****************************************************************************
14
-
15
- from IPython.utils.coloransi import ColorSchemeTable, TermColors, ColorScheme
16
-
17
- def exception_colors():
18
- """Return a color table with fields for exception reporting.
19
-
20
- The table is an instance of ColorSchemeTable with schemes added for
21
- 'Neutral', 'Linux', 'LightBG' and 'NoColor' and fields for exception handling filled
22
- in.
23
-
24
- Examples:
25
-
26
- >>> ec = exception_colors()
27
- >>> ec.active_scheme_name
28
- ''
29
- >>> print(ec.active_colors)
30
- None
31
-
32
- Now we activate a color scheme:
33
- >>> ec.set_active_scheme('NoColor')
34
- >>> ec.active_scheme_name
35
- 'NoColor'
36
- >>> sorted(ec.active_colors.keys())
37
- ['Normal', 'breakpoint_disabled', 'breakpoint_enabled', 'caret', 'em',
38
- 'excName', 'filename', 'filenameEm', 'line', 'lineno', 'linenoEm', 'name',
39
- 'nameEm', 'normalEm', 'prompt', 'topline', 'vName', 'val', 'valEm']
40
-
41
- """
42
-
43
- ex_colors = ColorSchemeTable()
44
-
45
- # Populate it with color schemes
46
- C = TermColors # shorthand and local lookup
47
- ex_colors.add_scheme(
48
- ColorScheme(
49
- "NoColor",
50
- {
51
- # The color to be used for the top line
52
- "topline": C.NoColor,
53
-
54
- # The colors to be used in the traceback
55
- "filename": C.NoColor,
56
- "lineno": C.NoColor,
57
- "name": C.NoColor,
58
- "vName": C.NoColor,
59
- "val": C.NoColor,
60
- "em": C.NoColor,
61
-
62
- # Emphasized colors for the last frame of the traceback
63
- "normalEm": C.NoColor,
64
- "filenameEm": C.NoColor,
65
- "linenoEm": C.NoColor,
66
- "nameEm": C.NoColor,
67
- "valEm": C.NoColor,
68
-
69
- # Colors for printing the exception
70
- "excName": C.NoColor,
71
- "line": C.NoColor,
72
- "caret": C.NoColor,
73
- "Normal": C.NoColor,
74
- # debugger
75
- "prompt": C.NoColor,
76
- "breakpoint_enabled": C.NoColor,
77
- "breakpoint_disabled": C.NoColor,
78
- },
79
- )
80
- )
81
-
82
- # make some schemes as instances so we can copy them for modification easily
83
- ex_colors.add_scheme(
84
- ColorScheme(
85
- "Linux",
86
- {
87
- # The color to be used for the top line
88
- "topline": C.LightRed,
89
- # The colors to be used in the traceback
90
- "filename": C.Green,
91
- "lineno": C.Green,
92
- "name": C.Purple,
93
- "vName": C.Cyan,
94
- "val": C.Green,
95
- "em": C.LightCyan,
96
- # Emphasized colors for the last frame of the traceback
97
- "normalEm": C.LightCyan,
98
- "filenameEm": C.LightGreen,
99
- "linenoEm": C.LightGreen,
100
- "nameEm": C.LightPurple,
101
- "valEm": C.LightBlue,
102
- # Colors for printing the exception
103
- "excName": C.LightRed,
104
- "line": C.Yellow,
105
- "caret": C.White,
106
- "Normal": C.Normal,
107
- # debugger
108
- "prompt": C.Green,
109
- "breakpoint_enabled": C.LightRed,
110
- "breakpoint_disabled": C.Red,
111
- },
112
- )
113
- )
114
-
115
- # For light backgrounds, swap dark/light colors
116
- ex_colors.add_scheme(
117
- ColorScheme(
118
- "LightBG",
119
- {
120
- # The color to be used for the top line
121
- "topline": C.Red,
122
-
123
- # The colors to be used in the traceback
124
- "filename": C.LightGreen,
125
- "lineno": C.LightGreen,
126
- "name": C.LightPurple,
127
- "vName": C.Cyan,
128
- "val": C.LightGreen,
129
- "em": C.Cyan,
130
-
131
- # Emphasized colors for the last frame of the traceback
132
- "normalEm": C.Cyan,
133
- "filenameEm": C.Green,
134
- "linenoEm": C.Green,
135
- "nameEm": C.Purple,
136
- "valEm": C.Blue,
137
-
138
- # Colors for printing the exception
139
- "excName": C.Red,
140
- # "line": C.Brown, # brown often is displayed as yellow
141
- "line": C.Red,
142
- "caret": C.Normal,
143
- "Normal": C.Normal,
144
- # debugger
145
- "prompt": C.Blue,
146
- "breakpoint_enabled": C.LightRed,
147
- "breakpoint_disabled": C.Red,
148
- },
149
- )
150
- )
151
-
152
- ex_colors.add_scheme(
153
- ColorScheme(
154
- "Neutral",
155
- {
156
- # The color to be used for the top line
157
- "topline": C.Red,
158
- # The colors to be used in the traceback
159
- "filename": C.LightGreen,
160
- "lineno": C.LightGreen,
161
- "name": C.LightPurple,
162
- "vName": C.Cyan,
163
- "val": C.LightGreen,
164
- "em": C.Cyan,
165
- # Emphasized colors for the last frame of the traceback
166
- "normalEm": C.Cyan,
167
- "filenameEm": C.Green,
168
- "linenoEm": C.Green,
169
- "nameEm": C.Purple,
170
- "valEm": C.Blue,
171
- # Colors for printing the exception
172
- "excName": C.Red,
173
- # line = C.Brown, # brown often is displayed as yellow
174
- "line": C.Red,
175
- "caret": C.Normal,
176
- "Normal": C.Normal,
177
- # debugger
178
- "prompt": C.Blue,
179
- "breakpoint_enabled": C.LightRed,
180
- "breakpoint_disabled": C.Red,
181
- },
182
- )
183
- )
184
-
185
- # Hack: the 'neutral' colours are not very visible on a dark background on
186
- # Windows. Since Windows command prompts have a dark background by default, and
187
- # relatively few users are likely to alter that, we will use the 'Linux' colours,
188
- # designed for a dark background, as the default on Windows.
189
- if os.name == "nt":
190
- ex_colors.add_scheme(ex_colors['Linux'].copy('Neutral'))
191
-
192
- return ex_colors
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/extensions.py DELETED
@@ -1,135 +0,0 @@
1
- # encoding: utf-8
2
- """A class for managing IPython extensions."""
3
-
4
- # Copyright (c) IPython Development Team.
5
- # Distributed under the terms of the Modified BSD License.
6
-
7
- import os
8
- import os.path
9
- import sys
10
- from importlib import import_module, reload
11
-
12
- from traitlets.config.configurable import Configurable
13
- from IPython.utils.path import ensure_dir_exists
14
- from traitlets import Instance
15
-
16
-
17
- #-----------------------------------------------------------------------------
18
- # Main class
19
- #-----------------------------------------------------------------------------
20
-
21
- BUILTINS_EXTS = {"storemagic": False, "autoreload": False}
22
-
23
-
24
- class ExtensionManager(Configurable):
25
- """A class to manage IPython extensions.
26
-
27
- An IPython extension is an importable Python module that has
28
- a function with the signature::
29
-
30
- def load_ipython_extension(ipython):
31
- # Do things with ipython
32
-
33
- This function is called after your extension is imported and the
34
- currently active :class:`InteractiveShell` instance is passed as
35
- the only argument. You can do anything you want with IPython at
36
- that point, including defining new magic and aliases, adding new
37
- components, etc.
38
-
39
- You can also optionally define an :func:`unload_ipython_extension(ipython)`
40
- function, which will be called if the user unloads or reloads the extension.
41
- The extension manager will only call :func:`load_ipython_extension` again
42
- if the extension is reloaded.
43
-
44
- You can put your extension modules anywhere you want, as long as
45
- they can be imported by Python's standard import mechanism.
46
- """
47
-
48
- shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
49
-
50
- def __init__(self, shell=None, **kwargs):
51
- super(ExtensionManager, self).__init__(shell=shell, **kwargs)
52
- self.loaded = set()
53
-
54
- def load_extension(self, module_str: str):
55
- """Load an IPython extension by its module name.
56
-
57
- Returns the string "already loaded" if the extension is already loaded,
58
- "no load function" if the module doesn't have a load_ipython_extension
59
- function, or None if it succeeded.
60
- """
61
- try:
62
- return self._load_extension(module_str)
63
- except ModuleNotFoundError:
64
- if module_str in BUILTINS_EXTS:
65
- BUILTINS_EXTS[module_str] = True
66
- return self._load_extension("IPython.extensions." + module_str)
67
- raise
68
-
69
- def _load_extension(self, module_str: str):
70
- if module_str in self.loaded:
71
- return "already loaded"
72
-
73
- assert self.shell is not None
74
-
75
- with self.shell.builtin_trap:
76
- if module_str not in sys.modules:
77
- mod = import_module(module_str)
78
- mod = sys.modules[module_str]
79
- if self._call_load_ipython_extension(mod):
80
- self.loaded.add(module_str)
81
- else:
82
- return "no load function"
83
-
84
- def unload_extension(self, module_str: str):
85
- """Unload an IPython extension by its module name.
86
-
87
- This function looks up the extension's name in ``sys.modules`` and
88
- simply calls ``mod.unload_ipython_extension(self)``.
89
-
90
- Returns the string "no unload function" if the extension doesn't define
91
- a function to unload itself, "not loaded" if the extension isn't loaded,
92
- otherwise None.
93
- """
94
- if BUILTINS_EXTS.get(module_str, False) is True:
95
- module_str = "IPython.extensions." + module_str
96
- if module_str not in self.loaded:
97
- return "not loaded"
98
-
99
- if module_str in sys.modules:
100
- mod = sys.modules[module_str]
101
- if self._call_unload_ipython_extension(mod):
102
- self.loaded.discard(module_str)
103
- else:
104
- return "no unload function"
105
-
106
- def reload_extension(self, module_str: str):
107
- """Reload an IPython extension by calling reload.
108
-
109
- If the module has not been loaded before,
110
- :meth:`InteractiveShell.load_extension` is called. Otherwise
111
- :func:`reload` is called and then the :func:`load_ipython_extension`
112
- function of the module, if it exists is called.
113
- """
114
-
115
- if BUILTINS_EXTS.get(module_str, False) is True:
116
- module_str = "IPython.extensions." + module_str
117
-
118
- if (module_str in self.loaded) and (module_str in sys.modules):
119
- self.unload_extension(module_str)
120
- mod = sys.modules[module_str]
121
- reload(mod)
122
- if self._call_load_ipython_extension(mod):
123
- self.loaded.add(module_str)
124
- else:
125
- self.load_extension(module_str)
126
-
127
- def _call_load_ipython_extension(self, mod):
128
- if hasattr(mod, 'load_ipython_extension'):
129
- mod.load_ipython_extension(self.shell)
130
- return True
131
-
132
- def _call_unload_ipython_extension(self, mod):
133
- if hasattr(mod, 'unload_ipython_extension'):
134
- mod.unload_ipython_extension(self.shell)
135
- return True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/formatters.py DELETED
@@ -1,1090 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """Display formatters.
3
-
4
- This module defines the base instances in order to implement custom
5
- formatters/mimetypes
6
- got objects:
7
-
8
- As we want to see internal IPython working we are going to use the following
9
- function to diaply objects instead of the normal print or display method:
10
-
11
- >>> ip = get_ipython()
12
- >>> ip.display_formatter.format(...)
13
- ({'text/plain': 'Ellipsis'}, {})
14
-
15
- This return a tuple with the mimebumdle for the current object, and the
16
- associated metadata.
17
-
18
-
19
- We can now define our own formatter and register it:
20
-
21
-
22
- >>> from IPython.core.formatters import BaseFormatter, FormatterABC
23
-
24
-
25
- >>> class LLMFormatter(BaseFormatter):
26
- ...
27
- ... format_type = 'x-vendor/llm'
28
- ... print_method = '_repr_llm_'
29
- ... _return_type = (dict, str)
30
-
31
- >>> llm_formatter = LLMFormatter(parent=ip.display_formatter)
32
-
33
- >>> ip.display_formatter.formatters[LLMFormatter.format_type] = llm_formatter
34
-
35
- Now any class that define `_repr_llm_` will return a x-vendor/llm as part of
36
- it's display data:
37
-
38
- >>> class A:
39
- ...
40
- ... def _repr_llm_(self, *kwargs):
41
- ... return 'This a A'
42
- ...
43
-
44
- >>> ip.display_formatter.format(A())
45
- ({'text/plain': '<IPython.core.formatters.A at ...>', 'x-vendor/llm': 'This a A'}, {})
46
-
47
- As usual, you can register methods for third party types (see
48
- :ref:`third_party_formatting`)
49
-
50
- >>> def llm_int(obj):
51
- ... return 'This is the integer %s, in between %s and %s'%(obj, obj-1, obj+1)
52
-
53
- >>> llm_formatter.for_type(int, llm_int)
54
-
55
- >>> ip.display_formatter.format(42)
56
- ({'text/plain': '42', 'x-vendor/llm': 'This is the integer 42, in between 41 and 43'}, {})
57
-
58
-
59
- Inheritance diagram:
60
-
61
- .. inheritance-diagram:: IPython.core.formatters
62
- :parts: 3
63
- """
64
-
65
- # Copyright (c) IPython Development Team.
66
- # Distributed under the terms of the Modified BSD License.
67
-
68
- import abc
69
- import sys
70
- import traceback
71
- import warnings
72
- from io import StringIO
73
-
74
- from decorator import decorator
75
-
76
- from traitlets.config.configurable import Configurable
77
- from .getipython import get_ipython
78
- from ..utils.sentinel import Sentinel
79
- from ..utils.dir2 import get_real_method
80
- from ..lib import pretty
81
- from traitlets import (
82
- Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
83
- ForwardDeclaredInstance,
84
- default, observe,
85
- )
86
-
87
- from typing import Any
88
-
89
-
90
- class DisplayFormatter(Configurable):
91
-
92
- active_types = List(Unicode(),
93
- help="""List of currently active mime-types to display.
94
- You can use this to set a white-list for formats to display.
95
-
96
- Most users will not need to change this value.
97
- """,
98
- ).tag(config=True)
99
-
100
- @default('active_types')
101
- def _active_types_default(self):
102
- return self.format_types
103
-
104
- @observe('active_types')
105
- def _active_types_changed(self, change):
106
- for key, formatter in self.formatters.items():
107
- if key in change['new']:
108
- formatter.enabled = True
109
- else:
110
- formatter.enabled = False
111
-
112
- ipython_display_formatter = ForwardDeclaredInstance("FormatterABC") # type: ignore
113
-
114
- @default("ipython_display_formatter")
115
- def _default_formatter(self):
116
- return IPythonDisplayFormatter(parent=self)
117
-
118
- mimebundle_formatter = ForwardDeclaredInstance("FormatterABC") # type: ignore
119
-
120
- @default("mimebundle_formatter")
121
- def _default_mime_formatter(self):
122
- return MimeBundleFormatter(parent=self)
123
-
124
- # A dict of formatter whose keys are format types (MIME types) and whose
125
- # values are subclasses of BaseFormatter.
126
- formatters = Dict()
127
-
128
- @default("formatters")
129
- def _formatters_default(self):
130
- """Activate the default formatters."""
131
- formatter_classes = [
132
- PlainTextFormatter,
133
- HTMLFormatter,
134
- MarkdownFormatter,
135
- SVGFormatter,
136
- PNGFormatter,
137
- PDFFormatter,
138
- JPEGFormatter,
139
- LatexFormatter,
140
- JSONFormatter,
141
- JavascriptFormatter
142
- ]
143
- d = {}
144
- for cls in formatter_classes:
145
- f = cls(parent=self)
146
- d[f.format_type] = f
147
- return d
148
-
149
- def format(self, obj, include=None, exclude=None):
150
- """Return a format data dict for an object.
151
-
152
- By default all format types will be computed.
153
-
154
- The following MIME types are usually implemented:
155
-
156
- * text/plain
157
- * text/html
158
- * text/markdown
159
- * text/latex
160
- * application/json
161
- * application/javascript
162
- * application/pdf
163
- * image/png
164
- * image/jpeg
165
- * image/svg+xml
166
-
167
- Parameters
168
- ----------
169
- obj : object
170
- The Python object whose format data will be computed.
171
- include : list, tuple or set; optional
172
- A list of format type strings (MIME types) to include in the
173
- format data dict. If this is set *only* the format types included
174
- in this list will be computed.
175
- exclude : list, tuple or set; optional
176
- A list of format type string (MIME types) to exclude in the format
177
- data dict. If this is set all format types will be computed,
178
- except for those included in this argument.
179
- Mimetypes present in exclude will take precedence over the ones in include
180
-
181
- Returns
182
- -------
183
- (format_dict, metadata_dict) : tuple of two dicts
184
- format_dict is a dictionary of key/value pairs, one of each format that was
185
- generated for the object. The keys are the format types, which
186
- will usually be MIME type strings and the values and JSON'able
187
- data structure containing the raw data for the representation in
188
- that format.
189
-
190
- metadata_dict is a dictionary of metadata about each mime-type output.
191
- Its keys will be a strict subset of the keys in format_dict.
192
-
193
- Notes
194
- -----
195
- If an object implement `_repr_mimebundle_` as well as various
196
- `_repr_*_`, the data returned by `_repr_mimebundle_` will take
197
- precedence and the corresponding `_repr_*_` for this mimetype will
198
- not be called.
199
-
200
- """
201
- format_dict = {}
202
- md_dict = {}
203
-
204
- if self.ipython_display_formatter(obj):
205
- # object handled itself, don't proceed
206
- return {}, {}
207
-
208
- format_dict, md_dict = self.mimebundle_formatter(obj, include=include, exclude=exclude)
209
-
210
- if format_dict or md_dict:
211
- if include:
212
- format_dict = {k:v for k,v in format_dict.items() if k in include}
213
- md_dict = {k:v for k,v in md_dict.items() if k in include}
214
- if exclude:
215
- format_dict = {k:v for k,v in format_dict.items() if k not in exclude}
216
- md_dict = {k:v for k,v in md_dict.items() if k not in exclude}
217
-
218
- for format_type, formatter in self.formatters.items():
219
- if format_type in format_dict:
220
- # already got it from mimebundle, maybe don't render again.
221
- # exception: manually registered per-mime renderer
222
- # check priority:
223
- # 1. user-registered per-mime formatter
224
- # 2. mime-bundle (user-registered or repr method)
225
- # 3. default per-mime formatter (e.g. repr method)
226
- try:
227
- formatter.lookup(obj)
228
- except KeyError:
229
- # no special formatter, use mime-bundle-provided value
230
- continue
231
- if include and format_type not in include:
232
- continue
233
- if exclude and format_type in exclude:
234
- continue
235
-
236
- md = None
237
- try:
238
- data = formatter(obj)
239
- except:
240
- # FIXME: log the exception
241
- raise
242
-
243
- # formatters can return raw data or (data, metadata)
244
- if isinstance(data, tuple) and len(data) == 2:
245
- data, md = data
246
-
247
- if data is not None:
248
- format_dict[format_type] = data
249
- if md is not None:
250
- md_dict[format_type] = md
251
- return format_dict, md_dict
252
-
253
- @property
254
- def format_types(self):
255
- """Return the format types (MIME types) of the active formatters."""
256
- return list(self.formatters.keys())
257
-
258
-
259
- #-----------------------------------------------------------------------------
260
- # Formatters for specific format types (text, html, svg, etc.)
261
- #-----------------------------------------------------------------------------
262
-
263
-
264
- def _safe_repr(obj):
265
- """Try to return a repr of an object
266
-
267
- always returns a string, at least.
268
- """
269
- try:
270
- return repr(obj)
271
- except Exception as e:
272
- return "un-repr-able object (%r)" % e
273
-
274
-
275
- class FormatterWarning(UserWarning):
276
- """Warning class for errors in formatters"""
277
-
278
- @decorator
279
- def catch_format_error(method, self, *args, **kwargs):
280
- """show traceback on failed format call"""
281
- try:
282
- r = method(self, *args, **kwargs)
283
- except NotImplementedError:
284
- # don't warn on NotImplementedErrors
285
- return self._check_return(None, args[0])
286
- except Exception:
287
- exc_info = sys.exc_info()
288
- ip = get_ipython()
289
- if ip is not None:
290
- ip.showtraceback(exc_info)
291
- else:
292
- traceback.print_exception(*exc_info)
293
- return self._check_return(None, args[0])
294
- return self._check_return(r, args[0])
295
-
296
-
297
- class FormatterABC(metaclass=abc.ABCMeta):
298
- """ Abstract base class for Formatters.
299
-
300
- A formatter is a callable class that is responsible for computing the
301
- raw format data for a particular format type (MIME type). For example,
302
- an HTML formatter would have a format type of `text/html` and would return
303
- the HTML representation of the object when called.
304
- """
305
-
306
- # The format type of the data returned, usually a MIME type.
307
- format_type = 'text/plain'
308
-
309
- # Is the formatter enabled...
310
- enabled = True
311
-
312
- @abc.abstractmethod
313
- def __call__(self, obj):
314
- """Return a JSON'able representation of the object.
315
-
316
- If the object cannot be formatted by this formatter,
317
- warn and return None.
318
- """
319
- return repr(obj)
320
-
321
-
322
- def _mod_name_key(typ):
323
- """Return a (__module__, __name__) tuple for a type.
324
-
325
- Used as key in Formatter.deferred_printers.
326
- """
327
- module = getattr(typ, '__module__', None)
328
- name = getattr(typ, '__name__', None)
329
- return (module, name)
330
-
331
-
332
- def _get_type(obj):
333
- """Return the type of an instance (old and new-style)"""
334
- return getattr(obj, '__class__', None) or type(obj)
335
-
336
-
337
- _raise_key_error = Sentinel(
338
- "_raise_key_error",
339
- __name__,
340
- """
341
- Special value to raise a KeyError
342
-
343
- Raise KeyError in `BaseFormatter.pop` if passed as the default value to `pop`
344
- """,
345
- )
346
-
347
-
348
- class BaseFormatter(Configurable):
349
- """A base formatter class that is configurable.
350
-
351
- This formatter should usually be used as the base class of all formatters.
352
- It is a traited :class:`Configurable` class and includes an extensible
353
- API for users to determine how their objects are formatted. The following
354
- logic is used to find a function to format an given object.
355
-
356
- 1. The object is introspected to see if it has a method with the name
357
- :attr:`print_method`. If is does, that object is passed to that method
358
- for formatting.
359
- 2. If no print method is found, three internal dictionaries are consulted
360
- to find print method: :attr:`singleton_printers`, :attr:`type_printers`
361
- and :attr:`deferred_printers`.
362
-
363
- Users should use these dictionaries to register functions that will be
364
- used to compute the format data for their objects (if those objects don't
365
- have the special print methods). The easiest way of using these
366
- dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
367
- methods.
368
-
369
- If no function/callable is found to compute the format data, ``None`` is
370
- returned and this format type is not used.
371
- """
372
-
373
- format_type = Unicode("text/plain")
374
- _return_type: Any = str
375
-
376
- enabled = Bool(True).tag(config=True)
377
-
378
- print_method = ObjectName('__repr__')
379
-
380
- # The singleton printers.
381
- # Maps the IDs of the builtin singleton objects to the format functions.
382
- singleton_printers = Dict().tag(config=True)
383
-
384
- # The type-specific printers.
385
- # Map type objects to the format functions.
386
- type_printers = Dict().tag(config=True)
387
-
388
- # The deferred-import type-specific printers.
389
- # Map (modulename, classname) pairs to the format functions.
390
- deferred_printers = Dict().tag(config=True)
391
-
392
- @catch_format_error
393
- def __call__(self, obj):
394
- """Compute the format for an object."""
395
- if self.enabled:
396
- # lookup registered printer
397
- try:
398
- printer = self.lookup(obj)
399
- except KeyError:
400
- pass
401
- else:
402
- return printer(obj)
403
- # Finally look for special method names
404
- method = get_real_method(obj, self.print_method)
405
- if method is not None:
406
- return method()
407
- return None
408
- else:
409
- return None
410
-
411
- def __contains__(self, typ):
412
- """map in to lookup_by_type"""
413
- try:
414
- self.lookup_by_type(typ)
415
- except KeyError:
416
- return False
417
- else:
418
- return True
419
-
420
- def _check_return(self, r, obj):
421
- """Check that a return value is appropriate
422
-
423
- Return the value if so, None otherwise, warning if invalid.
424
- """
425
- if r is None or isinstance(r, self._return_type) or \
426
- (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
427
- return r
428
- else:
429
- warnings.warn(
430
- "%s formatter returned invalid type %s (expected %s) for object: %s" % \
431
- (self.format_type, type(r), self._return_type, _safe_repr(obj)),
432
- FormatterWarning
433
- )
434
-
435
- def lookup(self, obj):
436
- """Look up the formatter for a given instance.
437
-
438
- Parameters
439
- ----------
440
- obj : object instance
441
-
442
- Returns
443
- -------
444
- f : callable
445
- The registered formatting callable for the type.
446
-
447
- Raises
448
- ------
449
- KeyError if the type has not been registered.
450
- """
451
- # look for singleton first
452
- obj_id = id(obj)
453
- if obj_id in self.singleton_printers:
454
- return self.singleton_printers[obj_id]
455
- # then lookup by type
456
- return self.lookup_by_type(_get_type(obj))
457
-
458
- def lookup_by_type(self, typ):
459
- """Look up the registered formatter for a type.
460
-
461
- Parameters
462
- ----------
463
- typ : type or '__module__.__name__' string for a type
464
-
465
- Returns
466
- -------
467
- f : callable
468
- The registered formatting callable for the type.
469
-
470
- Raises
471
- ------
472
- KeyError if the type has not been registered.
473
- """
474
- if isinstance(typ, str):
475
- typ_key = tuple(typ.rsplit('.',1))
476
- if typ_key not in self.deferred_printers:
477
- # We may have it cached in the type map. We will have to
478
- # iterate over all of the types to check.
479
- for cls in self.type_printers:
480
- if _mod_name_key(cls) == typ_key:
481
- return self.type_printers[cls]
482
- else:
483
- return self.deferred_printers[typ_key]
484
- else:
485
- for cls in pretty._get_mro(typ):
486
- if cls in self.type_printers or self._in_deferred_types(cls):
487
- return self.type_printers[cls]
488
-
489
- # If we have reached here, the lookup failed.
490
- raise KeyError("No registered printer for {0!r}".format(typ))
491
-
492
- def for_type(self, typ, func=None):
493
- """Add a format function for a given type.
494
-
495
- Parameters
496
- ----------
497
- typ : type or '__module__.__name__' string for a type
498
- The class of the object that will be formatted using `func`.
499
-
500
- func : callable
501
- A callable for computing the format data.
502
- `func` will be called with the object to be formatted,
503
- and will return the raw data in this formatter's format.
504
- Subclasses may use a different call signature for the
505
- `func` argument.
506
-
507
- If `func` is None or not specified, there will be no change,
508
- only returning the current value.
509
-
510
- Returns
511
- -------
512
- oldfunc : callable
513
- The currently registered callable.
514
- If you are registering a new formatter,
515
- this will be the previous value (to enable restoring later).
516
- """
517
- # if string given, interpret as 'pkg.module.class_name'
518
- if isinstance(typ, str):
519
- type_module, type_name = typ.rsplit('.', 1)
520
- return self.for_type_by_name(type_module, type_name, func)
521
-
522
- try:
523
- oldfunc = self.lookup_by_type(typ)
524
- except KeyError:
525
- oldfunc = None
526
-
527
- if func is not None:
528
- self.type_printers[typ] = func
529
-
530
- return oldfunc
531
-
532
- def for_type_by_name(self, type_module, type_name, func=None):
533
- """Add a format function for a type specified by the full dotted
534
- module and name of the type, rather than the type of the object.
535
-
536
- Parameters
537
- ----------
538
- type_module : str
539
- The full dotted name of the module the type is defined in, like
540
- ``numpy``.
541
-
542
- type_name : str
543
- The name of the type (the class name), like ``dtype``
544
-
545
- func : callable
546
- A callable for computing the format data.
547
- `func` will be called with the object to be formatted,
548
- and will return the raw data in this formatter's format.
549
- Subclasses may use a different call signature for the
550
- `func` argument.
551
-
552
- If `func` is None or unspecified, there will be no change,
553
- only returning the current value.
554
-
555
- Returns
556
- -------
557
- oldfunc : callable
558
- The currently registered callable.
559
- If you are registering a new formatter,
560
- this will be the previous value (to enable restoring later).
561
- """
562
- key = (type_module, type_name)
563
-
564
- try:
565
- oldfunc = self.lookup_by_type("%s.%s" % key)
566
- except KeyError:
567
- oldfunc = None
568
-
569
- if func is not None:
570
- self.deferred_printers[key] = func
571
- return oldfunc
572
-
573
- def pop(self, typ, default=_raise_key_error):
574
- """Pop a formatter for the given type.
575
-
576
- Parameters
577
- ----------
578
- typ : type or '__module__.__name__' string for a type
579
- default : object
580
- value to be returned if no formatter is registered for typ.
581
-
582
- Returns
583
- -------
584
- obj : object
585
- The last registered object for the type.
586
-
587
- Raises
588
- ------
589
- KeyError if the type is not registered and default is not specified.
590
- """
591
-
592
- if isinstance(typ, str):
593
- typ_key = tuple(typ.rsplit('.',1))
594
- if typ_key not in self.deferred_printers:
595
- # We may have it cached in the type map. We will have to
596
- # iterate over all of the types to check.
597
- for cls in self.type_printers:
598
- if _mod_name_key(cls) == typ_key:
599
- old = self.type_printers.pop(cls)
600
- break
601
- else:
602
- old = default
603
- else:
604
- old = self.deferred_printers.pop(typ_key)
605
- else:
606
- if typ in self.type_printers:
607
- old = self.type_printers.pop(typ)
608
- else:
609
- old = self.deferred_printers.pop(_mod_name_key(typ), default)
610
- if old is _raise_key_error:
611
- raise KeyError("No registered value for {0!r}".format(typ))
612
- return old
613
-
614
- def _in_deferred_types(self, cls):
615
- """
616
- Check if the given class is specified in the deferred type registry.
617
-
618
- Successful matches will be moved to the regular type registry for future use.
619
- """
620
- mod = getattr(cls, '__module__', None)
621
- name = getattr(cls, '__name__', None)
622
- key = (mod, name)
623
- if key in self.deferred_printers:
624
- # Move the printer over to the regular registry.
625
- printer = self.deferred_printers.pop(key)
626
- self.type_printers[cls] = printer
627
- return True
628
- return False
629
-
630
-
631
- class PlainTextFormatter(BaseFormatter):
632
- """The default pretty-printer.
633
-
634
- This uses :mod:`IPython.lib.pretty` to compute the format data of
635
- the object. If the object cannot be pretty printed, :func:`repr` is used.
636
- See the documentation of :mod:`IPython.lib.pretty` for details on
637
- how to write pretty printers. Here is a simple example::
638
-
639
- def dtype_pprinter(obj, p, cycle):
640
- if cycle:
641
- return p.text('dtype(...)')
642
- if hasattr(obj, 'fields'):
643
- if obj.fields is None:
644
- p.text(repr(obj))
645
- else:
646
- p.begin_group(7, 'dtype([')
647
- for i, field in enumerate(obj.descr):
648
- if i > 0:
649
- p.text(',')
650
- p.breakable()
651
- p.pretty(field)
652
- p.end_group(7, '])')
653
- """
654
-
655
- # The format type of data returned.
656
- format_type = Unicode('text/plain')
657
-
658
- # This subclass ignores this attribute as it always need to return
659
- # something.
660
- enabled = Bool(True).tag(config=False)
661
-
662
- max_seq_length = Integer(pretty.MAX_SEQ_LENGTH,
663
- help="""Truncate large collections (lists, dicts, tuples, sets) to this size.
664
-
665
- Set to 0 to disable truncation.
666
- """,
667
- ).tag(config=True)
668
-
669
- # Look for a _repr_pretty_ methods to use for pretty printing.
670
- print_method = ObjectName('_repr_pretty_')
671
-
672
- # Whether to pretty-print or not.
673
- pprint = Bool(True).tag(config=True)
674
-
675
- # Whether to be verbose or not.
676
- verbose = Bool(False).tag(config=True)
677
-
678
- # The maximum width.
679
- max_width = Integer(79).tag(config=True)
680
-
681
- # The newline character.
682
- newline = Unicode('\n').tag(config=True)
683
-
684
- # format-string for pprinting floats
685
- float_format = Unicode('%r')
686
- # setter for float precision, either int or direct format-string
687
- float_precision = CUnicode('').tag(config=True)
688
-
689
- @observe('float_precision')
690
- def _float_precision_changed(self, change):
691
- """float_precision changed, set float_format accordingly.
692
-
693
- float_precision can be set by int or str.
694
- This will set float_format, after interpreting input.
695
- If numpy has been imported, numpy print precision will also be set.
696
-
697
- integer `n` sets format to '%.nf', otherwise, format set directly.
698
-
699
- An empty string returns to defaults (repr for float, 8 for numpy).
700
-
701
- This parameter can be set via the '%precision' magic.
702
- """
703
- new = change['new']
704
- if '%' in new:
705
- # got explicit format string
706
- fmt = new
707
- try:
708
- fmt%3.14159
709
- except Exception as e:
710
- raise ValueError("Precision must be int or format string, not %r"%new) from e
711
- elif new:
712
- # otherwise, should be an int
713
- try:
714
- i = int(new)
715
- assert i >= 0
716
- except ValueError as e:
717
- raise ValueError("Precision must be int or format string, not %r"%new) from e
718
- except AssertionError as e:
719
- raise ValueError("int precision must be non-negative, not %r"%i) from e
720
-
721
- fmt = '%%.%if'%i
722
- if 'numpy' in sys.modules:
723
- # set numpy precision if it has been imported
724
- import numpy
725
- numpy.set_printoptions(precision=i)
726
- else:
727
- # default back to repr
728
- fmt = '%r'
729
- if 'numpy' in sys.modules:
730
- import numpy
731
- # numpy default is 8
732
- numpy.set_printoptions(precision=8)
733
- self.float_format = fmt
734
-
735
- # Use the default pretty printers from IPython.lib.pretty.
736
- @default('singleton_printers')
737
- def _singleton_printers_default(self):
738
- return pretty._singleton_pprinters.copy()
739
-
740
- @default('type_printers')
741
- def _type_printers_default(self):
742
- d = pretty._type_pprinters.copy()
743
- d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
744
- # if NumPy is used, set precision for its float64 type
745
- if "numpy" in sys.modules:
746
- import numpy
747
-
748
- d[numpy.float64] = lambda obj, p, cycle: p.text(self.float_format % obj)
749
- return d
750
-
751
- @default('deferred_printers')
752
- def _deferred_printers_default(self):
753
- return pretty._deferred_type_pprinters.copy()
754
-
755
- #### FormatterABC interface ####
756
-
757
- @catch_format_error
758
- def __call__(self, obj):
759
- """Compute the pretty representation of the object."""
760
- if not self.pprint:
761
- return repr(obj)
762
- else:
763
- stream = StringIO()
764
- printer = pretty.RepresentationPrinter(stream, self.verbose,
765
- self.max_width, self.newline,
766
- max_seq_length=self.max_seq_length,
767
- singleton_pprinters=self.singleton_printers,
768
- type_pprinters=self.type_printers,
769
- deferred_pprinters=self.deferred_printers)
770
- printer.pretty(obj)
771
- printer.flush()
772
- return stream.getvalue()
773
-
774
-
775
- class HTMLFormatter(BaseFormatter):
776
- """An HTML formatter.
777
-
778
- To define the callables that compute the HTML representation of your
779
- objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
780
- or :meth:`for_type_by_name` methods to register functions that handle
781
- this.
782
-
783
- The return value of this formatter should be a valid HTML snippet that
784
- could be injected into an existing DOM. It should *not* include the
785
- ```<html>`` or ```<body>`` tags.
786
- """
787
- format_type = Unicode('text/html')
788
-
789
- print_method = ObjectName('_repr_html_')
790
-
791
-
792
- class MarkdownFormatter(BaseFormatter):
793
- """A Markdown formatter.
794
-
795
- To define the callables that compute the Markdown representation of your
796
- objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type`
797
- or :meth:`for_type_by_name` methods to register functions that handle
798
- this.
799
-
800
- The return value of this formatter should be a valid Markdown.
801
- """
802
- format_type = Unicode('text/markdown')
803
-
804
- print_method = ObjectName('_repr_markdown_')
805
-
806
- class SVGFormatter(BaseFormatter):
807
- """An SVG formatter.
808
-
809
- To define the callables that compute the SVG representation of your
810
- objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
811
- or :meth:`for_type_by_name` methods to register functions that handle
812
- this.
813
-
814
- The return value of this formatter should be valid SVG enclosed in
815
- ```<svg>``` tags, that could be injected into an existing DOM. It should
816
- *not* include the ```<html>`` or ```<body>`` tags.
817
- """
818
- format_type = Unicode('image/svg+xml')
819
-
820
- print_method = ObjectName('_repr_svg_')
821
-
822
-
823
- class PNGFormatter(BaseFormatter):
824
- """A PNG formatter.
825
-
826
- To define the callables that compute the PNG representation of your
827
- objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
828
- or :meth:`for_type_by_name` methods to register functions that handle
829
- this.
830
-
831
- The return value of this formatter should be raw PNG data, *not*
832
- base64 encoded.
833
- """
834
- format_type = Unicode('image/png')
835
-
836
- print_method = ObjectName('_repr_png_')
837
-
838
- _return_type = (bytes, str)
839
-
840
-
841
- class JPEGFormatter(BaseFormatter):
842
- """A JPEG formatter.
843
-
844
- To define the callables that compute the JPEG representation of your
845
- objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
846
- or :meth:`for_type_by_name` methods to register functions that handle
847
- this.
848
-
849
- The return value of this formatter should be raw JPEG data, *not*
850
- base64 encoded.
851
- """
852
- format_type = Unicode('image/jpeg')
853
-
854
- print_method = ObjectName('_repr_jpeg_')
855
-
856
- _return_type = (bytes, str)
857
-
858
-
859
- class LatexFormatter(BaseFormatter):
860
- """A LaTeX formatter.
861
-
862
- To define the callables that compute the LaTeX representation of your
863
- objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
864
- or :meth:`for_type_by_name` methods to register functions that handle
865
- this.
866
-
867
- The return value of this formatter should be a valid LaTeX equation,
868
- enclosed in either ```$```, ```$$``` or another LaTeX equation
869
- environment.
870
- """
871
- format_type = Unicode('text/latex')
872
-
873
- print_method = ObjectName('_repr_latex_')
874
-
875
-
876
- class JSONFormatter(BaseFormatter):
877
- """A JSON string formatter.
878
-
879
- To define the callables that compute the JSONable representation of
880
- your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
881
- or :meth:`for_type_by_name` methods to register functions that handle
882
- this.
883
-
884
- The return value of this formatter should be a JSONable list or dict.
885
- JSON scalars (None, number, string) are not allowed, only dict or list containers.
886
- """
887
- format_type = Unicode('application/json')
888
- _return_type = (list, dict)
889
-
890
- print_method = ObjectName('_repr_json_')
891
-
892
- def _check_return(self, r, obj):
893
- """Check that a return value is appropriate
894
-
895
- Return the value if so, None otherwise, warning if invalid.
896
- """
897
- if r is None:
898
- return
899
- md = None
900
- if isinstance(r, tuple):
901
- # unpack data, metadata tuple for type checking on first element
902
- r, md = r
903
-
904
- assert not isinstance(
905
- r, str
906
- ), "JSON-as-string has been deprecated since IPython < 3"
907
-
908
- if md is not None:
909
- # put the tuple back together
910
- r = (r, md)
911
- return super(JSONFormatter, self)._check_return(r, obj)
912
-
913
-
914
- class JavascriptFormatter(BaseFormatter):
915
- """A Javascript formatter.
916
-
917
- To define the callables that compute the Javascript representation of
918
- your objects, define a :meth:`_repr_javascript_` method or use the
919
- :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
920
- that handle this.
921
-
922
- The return value of this formatter should be valid Javascript code and
923
- should *not* be enclosed in ```<script>``` tags.
924
- """
925
- format_type = Unicode('application/javascript')
926
-
927
- print_method = ObjectName('_repr_javascript_')
928
-
929
-
930
- class PDFFormatter(BaseFormatter):
931
- """A PDF formatter.
932
-
933
- To define the callables that compute the PDF representation of your
934
- objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type`
935
- or :meth:`for_type_by_name` methods to register functions that handle
936
- this.
937
-
938
- The return value of this formatter should be raw PDF data, *not*
939
- base64 encoded.
940
- """
941
- format_type = Unicode('application/pdf')
942
-
943
- print_method = ObjectName('_repr_pdf_')
944
-
945
- _return_type = (bytes, str)
946
-
947
- class IPythonDisplayFormatter(BaseFormatter):
948
- """An escape-hatch Formatter for objects that know how to display themselves.
949
-
950
- To define the callables that compute the representation of your
951
- objects, define a :meth:`_ipython_display_` method or use the :meth:`for_type`
952
- or :meth:`for_type_by_name` methods to register functions that handle
953
- this. Unlike mime-type displays, this method should not return anything,
954
- instead calling any appropriate display methods itself.
955
-
956
- This display formatter has highest priority.
957
- If it fires, no other display formatter will be called.
958
-
959
- Prior to IPython 6.1, `_ipython_display_` was the only way to display custom mime-types
960
- without registering a new Formatter.
961
-
962
- IPython 6.1 introduces `_repr_mimebundle_` for displaying custom mime-types,
963
- so `_ipython_display_` should only be used for objects that require unusual
964
- display patterns, such as multiple display calls.
965
- """
966
- print_method = ObjectName('_ipython_display_')
967
- _return_type = (type(None), bool)
968
-
969
- @catch_format_error
970
- def __call__(self, obj):
971
- """Compute the format for an object."""
972
- if self.enabled:
973
- # lookup registered printer
974
- try:
975
- printer = self.lookup(obj)
976
- except KeyError:
977
- pass
978
- else:
979
- printer(obj)
980
- return True
981
- # Finally look for special method names
982
- method = get_real_method(obj, self.print_method)
983
- if method is not None:
984
- method()
985
- return True
986
-
987
-
988
- class MimeBundleFormatter(BaseFormatter):
989
- """A Formatter for arbitrary mime-types.
990
-
991
- Unlike other `_repr_<mimetype>_` methods,
992
- `_repr_mimebundle_` should return mime-bundle data,
993
- either the mime-keyed `data` dictionary or the tuple `(data, metadata)`.
994
- Any mime-type is valid.
995
-
996
- To define the callables that compute the mime-bundle representation of your
997
- objects, define a :meth:`_repr_mimebundle_` method or use the :meth:`for_type`
998
- or :meth:`for_type_by_name` methods to register functions that handle
999
- this.
1000
-
1001
- .. versionadded:: 6.1
1002
- """
1003
- print_method = ObjectName('_repr_mimebundle_')
1004
- _return_type = dict
1005
-
1006
- def _check_return(self, r, obj):
1007
- r = super(MimeBundleFormatter, self)._check_return(r, obj)
1008
- # always return (data, metadata):
1009
- if r is None:
1010
- return {}, {}
1011
- if not isinstance(r, tuple):
1012
- return r, {}
1013
- return r
1014
-
1015
- @catch_format_error
1016
- def __call__(self, obj, include=None, exclude=None):
1017
- """Compute the format for an object.
1018
-
1019
- Identical to parent's method but we pass extra parameters to the method.
1020
-
1021
- Unlike other _repr_*_ `_repr_mimebundle_` should allow extra kwargs, in
1022
- particular `include` and `exclude`.
1023
- """
1024
- if self.enabled:
1025
- # lookup registered printer
1026
- try:
1027
- printer = self.lookup(obj)
1028
- except KeyError:
1029
- pass
1030
- else:
1031
- return printer(obj)
1032
- # Finally look for special method names
1033
- method = get_real_method(obj, self.print_method)
1034
-
1035
- if method is not None:
1036
- return method(include=include, exclude=exclude)
1037
- return None
1038
- else:
1039
- return None
1040
-
1041
-
1042
- FormatterABC.register(BaseFormatter)
1043
- FormatterABC.register(PlainTextFormatter)
1044
- FormatterABC.register(HTMLFormatter)
1045
- FormatterABC.register(MarkdownFormatter)
1046
- FormatterABC.register(SVGFormatter)
1047
- FormatterABC.register(PNGFormatter)
1048
- FormatterABC.register(PDFFormatter)
1049
- FormatterABC.register(JPEGFormatter)
1050
- FormatterABC.register(LatexFormatter)
1051
- FormatterABC.register(JSONFormatter)
1052
- FormatterABC.register(JavascriptFormatter)
1053
- FormatterABC.register(IPythonDisplayFormatter)
1054
- FormatterABC.register(MimeBundleFormatter)
1055
-
1056
-
1057
- def format_display_data(obj, include=None, exclude=None):
1058
- """Return a format data dict for an object.
1059
-
1060
- By default all format types will be computed.
1061
-
1062
- Parameters
1063
- ----------
1064
- obj : object
1065
- The Python object whose format data will be computed.
1066
-
1067
- Returns
1068
- -------
1069
- format_dict : dict
1070
- A dictionary of key/value pairs, one or each format that was
1071
- generated for the object. The keys are the format types, which
1072
- will usually be MIME type strings and the values and JSON'able
1073
- data structure containing the raw data for the representation in
1074
- that format.
1075
- include : list or tuple, optional
1076
- A list of format type strings (MIME types) to include in the
1077
- format data dict. If this is set *only* the format types included
1078
- in this list will be computed.
1079
- exclude : list or tuple, optional
1080
- A list of format type string (MIME types) to exclude in the format
1081
- data dict. If this is set all format types will be computed,
1082
- except for those included in this argument.
1083
- """
1084
- from .interactiveshell import InteractiveShell
1085
-
1086
- return InteractiveShell.instance().display_formatter.format(
1087
- obj,
1088
- include,
1089
- exclude
1090
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/getipython.py DELETED
@@ -1,24 +0,0 @@
1
- # encoding: utf-8
2
- """Simple function to call to get the current InteractiveShell instance
3
- """
4
-
5
- #-----------------------------------------------------------------------------
6
- # Copyright (C) 2013 The IPython Development Team
7
- #
8
- # Distributed under the terms of the BSD License. The full license is in
9
- # the file COPYING, distributed as part of this software.
10
- #-----------------------------------------------------------------------------
11
-
12
- #-----------------------------------------------------------------------------
13
- # Classes and functions
14
- #-----------------------------------------------------------------------------
15
-
16
-
17
- def get_ipython():
18
- """Get the global InteractiveShell instance.
19
-
20
- Returns None if no InteractiveShell instance is registered.
21
- """
22
- from IPython.core.interactiveshell import InteractiveShell
23
- if InteractiveShell.initialized():
24
- return InteractiveShell.instance()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/guarded_eval.py DELETED
@@ -1,895 +0,0 @@
1
- from inspect import isclass, signature, Signature
2
- from typing import (
3
- Annotated,
4
- AnyStr,
5
- Callable,
6
- Dict,
7
- Literal,
8
- NamedTuple,
9
- NewType,
10
- Optional,
11
- Protocol,
12
- Set,
13
- Sequence,
14
- Tuple,
15
- Type,
16
- TypeGuard,
17
- Union,
18
- get_args,
19
- get_origin,
20
- is_typeddict,
21
- )
22
- import ast
23
- import builtins
24
- import collections
25
- import operator
26
- import sys
27
- from functools import cached_property
28
- from dataclasses import dataclass, field
29
- from types import MethodDescriptorType, ModuleType
30
-
31
- from IPython.utils.decorators import undoc
32
-
33
-
34
- if sys.version_info < (3, 11):
35
- from typing_extensions import Self, LiteralString
36
- else:
37
- from typing import Self, LiteralString
38
-
39
- if sys.version_info < (3, 12):
40
- from typing_extensions import TypeAliasType
41
- else:
42
- from typing import TypeAliasType
43
-
44
-
45
- @undoc
46
- class HasGetItem(Protocol):
47
- def __getitem__(self, key) -> None: ...
48
-
49
-
50
- @undoc
51
- class InstancesHaveGetItem(Protocol):
52
- def __call__(self, *args, **kwargs) -> HasGetItem: ...
53
-
54
-
55
- @undoc
56
- class HasGetAttr(Protocol):
57
- def __getattr__(self, key) -> None: ...
58
-
59
-
60
- @undoc
61
- class DoesNotHaveGetAttr(Protocol):
62
- pass
63
-
64
-
65
- # By default `__getattr__` is not explicitly implemented on most objects
66
- MayHaveGetattr = Union[HasGetAttr, DoesNotHaveGetAttr]
67
-
68
-
69
- def _unbind_method(func: Callable) -> Union[Callable, None]:
70
- """Get unbound method for given bound method.
71
-
72
- Returns None if cannot get unbound method, or method is already unbound.
73
- """
74
- owner = getattr(func, "__self__", None)
75
- owner_class = type(owner)
76
- name = getattr(func, "__name__", None)
77
- instance_dict_overrides = getattr(owner, "__dict__", None)
78
- if (
79
- owner is not None
80
- and name
81
- and (
82
- not instance_dict_overrides
83
- or (instance_dict_overrides and name not in instance_dict_overrides)
84
- )
85
- ):
86
- return getattr(owner_class, name)
87
- return None
88
-
89
-
90
- @undoc
91
- @dataclass
92
- class EvaluationPolicy:
93
- """Definition of evaluation policy."""
94
-
95
- allow_locals_access: bool = False
96
- allow_globals_access: bool = False
97
- allow_item_access: bool = False
98
- allow_attr_access: bool = False
99
- allow_builtins_access: bool = False
100
- allow_all_operations: bool = False
101
- allow_any_calls: bool = False
102
- allowed_calls: Set[Callable] = field(default_factory=set)
103
-
104
- def can_get_item(self, value, item):
105
- return self.allow_item_access
106
-
107
- def can_get_attr(self, value, attr):
108
- return self.allow_attr_access
109
-
110
- def can_operate(self, dunders: Tuple[str, ...], a, b=None):
111
- if self.allow_all_operations:
112
- return True
113
-
114
- def can_call(self, func):
115
- if self.allow_any_calls:
116
- return True
117
-
118
- if func in self.allowed_calls:
119
- return True
120
-
121
- owner_method = _unbind_method(func)
122
-
123
- if owner_method and owner_method in self.allowed_calls:
124
- return True
125
-
126
-
127
- def _get_external(module_name: str, access_path: Sequence[str]):
128
- """Get value from external module given a dotted access path.
129
-
130
- Raises:
131
- * `KeyError` if module is removed not found, and
132
- * `AttributeError` if access path does not match an exported object
133
- """
134
- member_type = sys.modules[module_name]
135
- for attr in access_path:
136
- member_type = getattr(member_type, attr)
137
- return member_type
138
-
139
-
140
- def _has_original_dunder_external(
141
- value,
142
- module_name: str,
143
- access_path: Sequence[str],
144
- method_name: str,
145
- ):
146
- if module_name not in sys.modules:
147
- # LBYLB as it is faster
148
- return False
149
- try:
150
- member_type = _get_external(module_name, access_path)
151
- value_type = type(value)
152
- if type(value) == member_type:
153
- return True
154
- if method_name == "__getattribute__":
155
- # we have to short-circuit here due to an unresolved issue in
156
- # `isinstance` implementation: https://bugs.python.org/issue32683
157
- return False
158
- if isinstance(value, member_type):
159
- method = getattr(value_type, method_name, None)
160
- member_method = getattr(member_type, method_name, None)
161
- if member_method == method:
162
- return True
163
- except (AttributeError, KeyError):
164
- return False
165
-
166
-
167
- def _has_original_dunder(
168
- value, allowed_types, allowed_methods, allowed_external, method_name
169
- ):
170
- # note: Python ignores `__getattr__`/`__getitem__` on instances,
171
- # we only need to check at class level
172
- value_type = type(value)
173
-
174
- # strict type check passes → no need to check method
175
- if value_type in allowed_types:
176
- return True
177
-
178
- method = getattr(value_type, method_name, None)
179
-
180
- if method is None:
181
- return None
182
-
183
- if method in allowed_methods:
184
- return True
185
-
186
- for module_name, *access_path in allowed_external:
187
- if _has_original_dunder_external(value, module_name, access_path, method_name):
188
- return True
189
-
190
- return False
191
-
192
-
193
- @undoc
194
- @dataclass
195
- class SelectivePolicy(EvaluationPolicy):
196
- allowed_getitem: Set[InstancesHaveGetItem] = field(default_factory=set)
197
- allowed_getitem_external: Set[Tuple[str, ...]] = field(default_factory=set)
198
-
199
- allowed_getattr: Set[MayHaveGetattr] = field(default_factory=set)
200
- allowed_getattr_external: Set[Tuple[str, ...]] = field(default_factory=set)
201
-
202
- allowed_operations: Set = field(default_factory=set)
203
- allowed_operations_external: Set[Tuple[str, ...]] = field(default_factory=set)
204
-
205
- _operation_methods_cache: Dict[str, Set[Callable]] = field(
206
- default_factory=dict, init=False
207
- )
208
-
209
- def can_get_attr(self, value, attr):
210
- has_original_attribute = _has_original_dunder(
211
- value,
212
- allowed_types=self.allowed_getattr,
213
- allowed_methods=self._getattribute_methods,
214
- allowed_external=self.allowed_getattr_external,
215
- method_name="__getattribute__",
216
- )
217
- has_original_attr = _has_original_dunder(
218
- value,
219
- allowed_types=self.allowed_getattr,
220
- allowed_methods=self._getattr_methods,
221
- allowed_external=self.allowed_getattr_external,
222
- method_name="__getattr__",
223
- )
224
-
225
- accept = False
226
-
227
- # Many objects do not have `__getattr__`, this is fine.
228
- if has_original_attr is None and has_original_attribute:
229
- accept = True
230
- else:
231
- # Accept objects without modifications to `__getattr__` and `__getattribute__`
232
- accept = has_original_attr and has_original_attribute
233
-
234
- if accept:
235
- # We still need to check for overridden properties.
236
-
237
- value_class = type(value)
238
- if not hasattr(value_class, attr):
239
- return True
240
-
241
- class_attr_val = getattr(value_class, attr)
242
- is_property = isinstance(class_attr_val, property)
243
-
244
- if not is_property:
245
- return True
246
-
247
- # Properties in allowed types are ok (although we do not include any
248
- # properties in our default allow list currently).
249
- if type(value) in self.allowed_getattr:
250
- return True # pragma: no cover
251
-
252
- # Properties in subclasses of allowed types may be ok if not changed
253
- for module_name, *access_path in self.allowed_getattr_external:
254
- try:
255
- external_class = _get_external(module_name, access_path)
256
- external_class_attr_val = getattr(external_class, attr)
257
- except (KeyError, AttributeError):
258
- return False # pragma: no cover
259
- return class_attr_val == external_class_attr_val
260
-
261
- return False
262
-
263
- def can_get_item(self, value, item):
264
- """Allow accessing `__getiitem__` of allow-listed instances unless it was not modified."""
265
- return _has_original_dunder(
266
- value,
267
- allowed_types=self.allowed_getitem,
268
- allowed_methods=self._getitem_methods,
269
- allowed_external=self.allowed_getitem_external,
270
- method_name="__getitem__",
271
- )
272
-
273
- def can_operate(self, dunders: Tuple[str, ...], a, b=None):
274
- objects = [a]
275
- if b is not None:
276
- objects.append(b)
277
- return all(
278
- [
279
- _has_original_dunder(
280
- obj,
281
- allowed_types=self.allowed_operations,
282
- allowed_methods=self._operator_dunder_methods(dunder),
283
- allowed_external=self.allowed_operations_external,
284
- method_name=dunder,
285
- )
286
- for dunder in dunders
287
- for obj in objects
288
- ]
289
- )
290
-
291
- def _operator_dunder_methods(self, dunder: str) -> Set[Callable]:
292
- if dunder not in self._operation_methods_cache:
293
- self._operation_methods_cache[dunder] = self._safe_get_methods(
294
- self.allowed_operations, dunder
295
- )
296
- return self._operation_methods_cache[dunder]
297
-
298
- @cached_property
299
- def _getitem_methods(self) -> Set[Callable]:
300
- return self._safe_get_methods(self.allowed_getitem, "__getitem__")
301
-
302
- @cached_property
303
- def _getattr_methods(self) -> Set[Callable]:
304
- return self._safe_get_methods(self.allowed_getattr, "__getattr__")
305
-
306
- @cached_property
307
- def _getattribute_methods(self) -> Set[Callable]:
308
- return self._safe_get_methods(self.allowed_getattr, "__getattribute__")
309
-
310
- def _safe_get_methods(self, classes, name) -> Set[Callable]:
311
- return {
312
- method
313
- for class_ in classes
314
- for method in [getattr(class_, name, None)]
315
- if method
316
- }
317
-
318
-
319
- class _DummyNamedTuple(NamedTuple):
320
- """Used internally to retrieve methods of named tuple instance."""
321
-
322
-
323
- class EvaluationContext(NamedTuple):
324
- #: Local namespace
325
- locals: dict
326
- #: Global namespace
327
- globals: dict
328
- #: Evaluation policy identifier
329
- evaluation: Literal["forbidden", "minimal", "limited", "unsafe", "dangerous"] = (
330
- "forbidden"
331
- )
332
- #: Whether the evaluation of code takes place inside of a subscript.
333
- #: Useful for evaluating ``:-1, 'col'`` in ``df[:-1, 'col']``.
334
- in_subscript: bool = False
335
-
336
-
337
- class _IdentitySubscript:
338
- """Returns the key itself when item is requested via subscript."""
339
-
340
- def __getitem__(self, key):
341
- return key
342
-
343
-
344
- IDENTITY_SUBSCRIPT = _IdentitySubscript()
345
- SUBSCRIPT_MARKER = "__SUBSCRIPT_SENTINEL__"
346
- UNKNOWN_SIGNATURE = Signature()
347
- NOT_EVALUATED = object()
348
-
349
-
350
- class GuardRejection(Exception):
351
- """Exception raised when guard rejects evaluation attempt."""
352
-
353
- pass
354
-
355
-
356
- def guarded_eval(code: str, context: EvaluationContext):
357
- """Evaluate provided code in the evaluation context.
358
-
359
- If evaluation policy given by context is set to ``forbidden``
360
- no evaluation will be performed; if it is set to ``dangerous``
361
- standard :func:`eval` will be used; finally, for any other,
362
- policy :func:`eval_node` will be called on parsed AST.
363
- """
364
- locals_ = context.locals
365
-
366
- if context.evaluation == "forbidden":
367
- raise GuardRejection("Forbidden mode")
368
-
369
- # note: not using `ast.literal_eval` as it does not implement
370
- # getitem at all, for example it fails on simple `[0][1]`
371
-
372
- if context.in_subscript:
373
- # syntactic sugar for ellipsis (:) is only available in subscripts
374
- # so we need to trick the ast parser into thinking that we have
375
- # a subscript, but we need to be able to later recognise that we did
376
- # it so we can ignore the actual __getitem__ operation
377
- if not code:
378
- return tuple()
379
- locals_ = locals_.copy()
380
- locals_[SUBSCRIPT_MARKER] = IDENTITY_SUBSCRIPT
381
- code = SUBSCRIPT_MARKER + "[" + code + "]"
382
- context = EvaluationContext(**{**context._asdict(), **{"locals": locals_}})
383
-
384
- if context.evaluation == "dangerous":
385
- return eval(code, context.globals, context.locals)
386
-
387
- expression = ast.parse(code, mode="eval")
388
-
389
- return eval_node(expression, context)
390
-
391
-
392
- BINARY_OP_DUNDERS: Dict[Type[ast.operator], Tuple[str]] = {
393
- ast.Add: ("__add__",),
394
- ast.Sub: ("__sub__",),
395
- ast.Mult: ("__mul__",),
396
- ast.Div: ("__truediv__",),
397
- ast.FloorDiv: ("__floordiv__",),
398
- ast.Mod: ("__mod__",),
399
- ast.Pow: ("__pow__",),
400
- ast.LShift: ("__lshift__",),
401
- ast.RShift: ("__rshift__",),
402
- ast.BitOr: ("__or__",),
403
- ast.BitXor: ("__xor__",),
404
- ast.BitAnd: ("__and__",),
405
- ast.MatMult: ("__matmul__",),
406
- }
407
-
408
- COMP_OP_DUNDERS: Dict[Type[ast.cmpop], Tuple[str, ...]] = {
409
- ast.Eq: ("__eq__",),
410
- ast.NotEq: ("__ne__", "__eq__"),
411
- ast.Lt: ("__lt__", "__gt__"),
412
- ast.LtE: ("__le__", "__ge__"),
413
- ast.Gt: ("__gt__", "__lt__"),
414
- ast.GtE: ("__ge__", "__le__"),
415
- ast.In: ("__contains__",),
416
- # Note: ast.Is, ast.IsNot, ast.NotIn are handled specially
417
- }
418
-
419
- UNARY_OP_DUNDERS: Dict[Type[ast.unaryop], Tuple[str, ...]] = {
420
- ast.USub: ("__neg__",),
421
- ast.UAdd: ("__pos__",),
422
- # we have to check both __inv__ and __invert__!
423
- ast.Invert: ("__invert__", "__inv__"),
424
- ast.Not: ("__not__",),
425
- }
426
-
427
-
428
- class ImpersonatingDuck:
429
- """A dummy class used to create objects of other classes without calling their ``__init__``"""
430
-
431
- # no-op: override __class__ to impersonate
432
-
433
-
434
- class _Duck:
435
- """A dummy class used to create objects pretending to have given attributes"""
436
-
437
- def __init__(self, attributes: Optional[dict] = None, items: Optional[dict] = None):
438
- self.attributes = attributes or {}
439
- self.items = items or {}
440
-
441
- def __getattr__(self, attr: str):
442
- return self.attributes[attr]
443
-
444
- def __hasattr__(self, attr: str):
445
- return attr in self.attributes
446
-
447
- def __dir__(self):
448
- return [*dir(super), *self.attributes]
449
-
450
- def __getitem__(self, key: str):
451
- return self.items[key]
452
-
453
- def __hasitem__(self, key: str):
454
- return self.items[key]
455
-
456
- def _ipython_key_completions_(self):
457
- return self.items.keys()
458
-
459
-
460
- def _find_dunder(node_op, dunders) -> Union[Tuple[str, ...], None]:
461
- dunder = None
462
- for op, candidate_dunder in dunders.items():
463
- if isinstance(node_op, op):
464
- dunder = candidate_dunder
465
- return dunder
466
-
467
-
468
- def eval_node(node: Union[ast.AST, None], context: EvaluationContext):
469
- """Evaluate AST node in provided context.
470
-
471
- Applies evaluation restrictions defined in the context. Currently does not support evaluation of functions with keyword arguments.
472
-
473
- Does not evaluate actions that always have side effects:
474
-
475
- - class definitions (``class sth: ...``)
476
- - function definitions (``def sth: ...``)
477
- - variable assignments (``x = 1``)
478
- - augmented assignments (``x += 1``)
479
- - deletions (``del x``)
480
-
481
- Does not evaluate operations which do not return values:
482
-
483
- - assertions (``assert x``)
484
- - pass (``pass``)
485
- - imports (``import x``)
486
- - control flow:
487
-
488
- - conditionals (``if x:``) except for ternary IfExp (``a if x else b``)
489
- - loops (``for`` and ``while``)
490
- - exception handling
491
-
492
- The purpose of this function is to guard against unwanted side-effects;
493
- it does not give guarantees on protection from malicious code execution.
494
- """
495
- policy = EVALUATION_POLICIES[context.evaluation]
496
- if node is None:
497
- return None
498
- if isinstance(node, ast.Expression):
499
- return eval_node(node.body, context)
500
- if isinstance(node, ast.BinOp):
501
- left = eval_node(node.left, context)
502
- right = eval_node(node.right, context)
503
- dunders = _find_dunder(node.op, BINARY_OP_DUNDERS)
504
- if dunders:
505
- if policy.can_operate(dunders, left, right):
506
- return getattr(left, dunders[0])(right)
507
- else:
508
- raise GuardRejection(
509
- f"Operation (`{dunders}`) for",
510
- type(left),
511
- f"not allowed in {context.evaluation} mode",
512
- )
513
- if isinstance(node, ast.Compare):
514
- left = eval_node(node.left, context)
515
- all_true = True
516
- negate = False
517
- for op, right in zip(node.ops, node.comparators):
518
- right = eval_node(right, context)
519
- dunder = None
520
- dunders = _find_dunder(op, COMP_OP_DUNDERS)
521
- if not dunders:
522
- if isinstance(op, ast.NotIn):
523
- dunders = COMP_OP_DUNDERS[ast.In]
524
- negate = True
525
- if isinstance(op, ast.Is):
526
- dunder = "is_"
527
- if isinstance(op, ast.IsNot):
528
- dunder = "is_"
529
- negate = True
530
- if not dunder and dunders:
531
- dunder = dunders[0]
532
- if dunder:
533
- a, b = (right, left) if dunder == "__contains__" else (left, right)
534
- if dunder == "is_" or dunders and policy.can_operate(dunders, a, b):
535
- result = getattr(operator, dunder)(a, b)
536
- if negate:
537
- result = not result
538
- if not result:
539
- all_true = False
540
- left = right
541
- else:
542
- raise GuardRejection(
543
- f"Comparison (`{dunder}`) for",
544
- type(left),
545
- f"not allowed in {context.evaluation} mode",
546
- )
547
- else:
548
- raise ValueError(
549
- f"Comparison `{dunder}` not supported"
550
- ) # pragma: no cover
551
- return all_true
552
- if isinstance(node, ast.Constant):
553
- return node.value
554
- if isinstance(node, ast.Tuple):
555
- return tuple(eval_node(e, context) for e in node.elts)
556
- if isinstance(node, ast.List):
557
- return [eval_node(e, context) for e in node.elts]
558
- if isinstance(node, ast.Set):
559
- return {eval_node(e, context) for e in node.elts}
560
- if isinstance(node, ast.Dict):
561
- return dict(
562
- zip(
563
- [eval_node(k, context) for k in node.keys],
564
- [eval_node(v, context) for v in node.values],
565
- )
566
- )
567
- if isinstance(node, ast.Slice):
568
- return slice(
569
- eval_node(node.lower, context),
570
- eval_node(node.upper, context),
571
- eval_node(node.step, context),
572
- )
573
- if isinstance(node, ast.UnaryOp):
574
- value = eval_node(node.operand, context)
575
- dunders = _find_dunder(node.op, UNARY_OP_DUNDERS)
576
- if dunders:
577
- if policy.can_operate(dunders, value):
578
- return getattr(value, dunders[0])()
579
- else:
580
- raise GuardRejection(
581
- f"Operation (`{dunders}`) for",
582
- type(value),
583
- f"not allowed in {context.evaluation} mode",
584
- )
585
- if isinstance(node, ast.Subscript):
586
- value = eval_node(node.value, context)
587
- slice_ = eval_node(node.slice, context)
588
- if policy.can_get_item(value, slice_):
589
- return value[slice_]
590
- raise GuardRejection(
591
- "Subscript access (`__getitem__`) for",
592
- type(value), # not joined to avoid calling `repr`
593
- f" not allowed in {context.evaluation} mode",
594
- )
595
- if isinstance(node, ast.Name):
596
- return _eval_node_name(node.id, context)
597
- if isinstance(node, ast.Attribute):
598
- value = eval_node(node.value, context)
599
- if policy.can_get_attr(value, node.attr):
600
- return getattr(value, node.attr)
601
- raise GuardRejection(
602
- "Attribute access (`__getattr__`) for",
603
- type(value), # not joined to avoid calling `repr`
604
- f"not allowed in {context.evaluation} mode",
605
- )
606
- if isinstance(node, ast.IfExp):
607
- test = eval_node(node.test, context)
608
- if test:
609
- return eval_node(node.body, context)
610
- else:
611
- return eval_node(node.orelse, context)
612
- if isinstance(node, ast.Call):
613
- func = eval_node(node.func, context)
614
- if policy.can_call(func) and not node.keywords:
615
- args = [eval_node(arg, context) for arg in node.args]
616
- return func(*args)
617
- if isclass(func):
618
- # this code path gets entered when calling class e.g. `MyClass()`
619
- # or `my_instance.__class__()` - in both cases `func` is `MyClass`.
620
- # Should return `MyClass` if `__new__` is not overridden,
621
- # otherwise whatever `__new__` return type is.
622
- overridden_return_type = _eval_return_type(func.__new__, node, context)
623
- if overridden_return_type is not NOT_EVALUATED:
624
- return overridden_return_type
625
- return _create_duck_for_heap_type(func)
626
- else:
627
- return_type = _eval_return_type(func, node, context)
628
- if return_type is not NOT_EVALUATED:
629
- return return_type
630
- raise GuardRejection(
631
- "Call for",
632
- func, # not joined to avoid calling `repr`
633
- f"not allowed in {context.evaluation} mode",
634
- )
635
- raise ValueError("Unhandled node", ast.dump(node))
636
-
637
-
638
- def _eval_return_type(func: Callable, node: ast.Call, context: EvaluationContext):
639
- """Evaluate return type of a given callable function.
640
-
641
- Returns the built-in type, a duck or NOT_EVALUATED sentinel.
642
- """
643
- try:
644
- sig = signature(func)
645
- except ValueError:
646
- sig = UNKNOWN_SIGNATURE
647
- # if annotation was not stringized, or it was stringized
648
- # but resolved by signature call we know the return type
649
- not_empty = sig.return_annotation is not Signature.empty
650
- if not_empty:
651
- return _resolve_annotation(sig.return_annotation, sig, func, node, context)
652
- return NOT_EVALUATED
653
-
654
-
655
- def _resolve_annotation(
656
- annotation,
657
- sig: Signature,
658
- func: Callable,
659
- node: ast.Call,
660
- context: EvaluationContext,
661
- ):
662
- """Resolve annotation created by user with `typing` module and custom objects."""
663
- annotation = (
664
- _eval_node_name(annotation, context)
665
- if isinstance(annotation, str)
666
- else annotation
667
- )
668
- origin = get_origin(annotation)
669
- if annotation is Self and hasattr(func, "__self__"):
670
- return func.__self__
671
- elif origin is Literal:
672
- type_args = get_args(annotation)
673
- if len(type_args) == 1:
674
- return type_args[0]
675
- elif annotation is LiteralString:
676
- return ""
677
- elif annotation is AnyStr:
678
- index = None
679
- for i, (key, value) in enumerate(sig.parameters.items()):
680
- if value.annotation is AnyStr:
681
- index = i
682
- break
683
- if index is not None and index < len(node.args):
684
- return eval_node(node.args[index], context)
685
- elif origin is TypeGuard:
686
- return bool()
687
- elif origin is Union:
688
- attributes = [
689
- attr
690
- for type_arg in get_args(annotation)
691
- for attr in dir(_resolve_annotation(type_arg, sig, func, node, context))
692
- ]
693
- return _Duck(attributes=dict.fromkeys(attributes))
694
- elif is_typeddict(annotation):
695
- return _Duck(
696
- attributes=dict.fromkeys(dir(dict())),
697
- items={
698
- k: _resolve_annotation(v, sig, func, node, context)
699
- for k, v in annotation.__annotations__.items()
700
- },
701
- )
702
- elif hasattr(annotation, "_is_protocol"):
703
- return _Duck(attributes=dict.fromkeys(dir(annotation)))
704
- elif origin is Annotated:
705
- type_arg = get_args(annotation)[0]
706
- return _resolve_annotation(type_arg, sig, func, node, context)
707
- elif isinstance(annotation, NewType):
708
- return _eval_or_create_duck(annotation.__supertype__, node, context)
709
- elif isinstance(annotation, TypeAliasType):
710
- return _eval_or_create_duck(annotation.__value__, node, context)
711
- else:
712
- return _eval_or_create_duck(annotation, node, context)
713
-
714
-
715
- def _eval_node_name(node_id: str, context: EvaluationContext):
716
- policy = EVALUATION_POLICIES[context.evaluation]
717
- if policy.allow_locals_access and node_id in context.locals:
718
- return context.locals[node_id]
719
- if policy.allow_globals_access and node_id in context.globals:
720
- return context.globals[node_id]
721
- if policy.allow_builtins_access and hasattr(builtins, node_id):
722
- # note: do not use __builtins__, it is implementation detail of cPython
723
- return getattr(builtins, node_id)
724
- if not policy.allow_globals_access and not policy.allow_locals_access:
725
- raise GuardRejection(
726
- f"Namespace access not allowed in {context.evaluation} mode"
727
- )
728
- else:
729
- raise NameError(f"{node_id} not found in locals, globals, nor builtins")
730
-
731
-
732
- def _eval_or_create_duck(duck_type, node: ast.Call, context: EvaluationContext):
733
- policy = EVALUATION_POLICIES[context.evaluation]
734
- # if allow-listed builtin is on type annotation, instantiate it
735
- if policy.can_call(duck_type) and not node.keywords:
736
- args = [eval_node(arg, context) for arg in node.args]
737
- return duck_type(*args)
738
- # if custom class is in type annotation, mock it
739
- return _create_duck_for_heap_type(duck_type)
740
-
741
-
742
- def _create_duck_for_heap_type(duck_type):
743
- """Create an imitation of an object of a given type (a duck).
744
-
745
- Returns the duck or NOT_EVALUATED sentinel if duck could not be created.
746
- """
747
- duck = ImpersonatingDuck()
748
- try:
749
- # this only works for heap types, not builtins
750
- duck.__class__ = duck_type
751
- return duck
752
- except TypeError:
753
- pass
754
- return NOT_EVALUATED
755
-
756
-
757
- SUPPORTED_EXTERNAL_GETITEM = {
758
- ("pandas", "core", "indexing", "_iLocIndexer"),
759
- ("pandas", "core", "indexing", "_LocIndexer"),
760
- ("pandas", "DataFrame"),
761
- ("pandas", "Series"),
762
- ("numpy", "ndarray"),
763
- ("numpy", "void"),
764
- }
765
-
766
-
767
- BUILTIN_GETITEM: Set[InstancesHaveGetItem] = {
768
- dict,
769
- str, # type: ignore[arg-type]
770
- bytes, # type: ignore[arg-type]
771
- list,
772
- tuple,
773
- collections.defaultdict,
774
- collections.deque,
775
- collections.OrderedDict,
776
- collections.ChainMap,
777
- collections.UserDict,
778
- collections.UserList,
779
- collections.UserString, # type: ignore[arg-type]
780
- _DummyNamedTuple,
781
- _IdentitySubscript,
782
- }
783
-
784
-
785
- def _list_methods(cls, source=None):
786
- """For use on immutable objects or with methods returning a copy"""
787
- return [getattr(cls, k) for k in (source if source else dir(cls))]
788
-
789
-
790
- dict_non_mutating_methods = ("copy", "keys", "values", "items")
791
- list_non_mutating_methods = ("copy", "index", "count")
792
- set_non_mutating_methods = set(dir(set)) & set(dir(frozenset))
793
-
794
-
795
- dict_keys: Type[collections.abc.KeysView] = type({}.keys())
796
-
797
- NUMERICS = {int, float, complex}
798
-
799
- ALLOWED_CALLS = {
800
- bytes,
801
- *_list_methods(bytes),
802
- dict,
803
- *_list_methods(dict, dict_non_mutating_methods),
804
- dict_keys.isdisjoint,
805
- list,
806
- *_list_methods(list, list_non_mutating_methods),
807
- set,
808
- *_list_methods(set, set_non_mutating_methods),
809
- frozenset,
810
- *_list_methods(frozenset),
811
- range,
812
- str,
813
- *_list_methods(str),
814
- tuple,
815
- *_list_methods(tuple),
816
- *NUMERICS,
817
- *[method for numeric_cls in NUMERICS for method in _list_methods(numeric_cls)],
818
- collections.deque,
819
- *_list_methods(collections.deque, list_non_mutating_methods),
820
- collections.defaultdict,
821
- *_list_methods(collections.defaultdict, dict_non_mutating_methods),
822
- collections.OrderedDict,
823
- *_list_methods(collections.OrderedDict, dict_non_mutating_methods),
824
- collections.UserDict,
825
- *_list_methods(collections.UserDict, dict_non_mutating_methods),
826
- collections.UserList,
827
- *_list_methods(collections.UserList, list_non_mutating_methods),
828
- collections.UserString,
829
- *_list_methods(collections.UserString, dir(str)),
830
- collections.Counter,
831
- *_list_methods(collections.Counter, dict_non_mutating_methods),
832
- collections.Counter.elements,
833
- collections.Counter.most_common,
834
- }
835
-
836
- BUILTIN_GETATTR: Set[MayHaveGetattr] = {
837
- *BUILTIN_GETITEM,
838
- set,
839
- frozenset,
840
- object,
841
- type, # `type` handles a lot of generic cases, e.g. numbers as in `int.real`.
842
- *NUMERICS,
843
- dict_keys,
844
- MethodDescriptorType,
845
- ModuleType,
846
- }
847
-
848
-
849
- BUILTIN_OPERATIONS = {*BUILTIN_GETATTR}
850
-
851
- EVALUATION_POLICIES = {
852
- "minimal": EvaluationPolicy(
853
- allow_builtins_access=True,
854
- allow_locals_access=False,
855
- allow_globals_access=False,
856
- allow_item_access=False,
857
- allow_attr_access=False,
858
- allowed_calls=set(),
859
- allow_any_calls=False,
860
- allow_all_operations=False,
861
- ),
862
- "limited": SelectivePolicy(
863
- allowed_getitem=BUILTIN_GETITEM,
864
- allowed_getitem_external=SUPPORTED_EXTERNAL_GETITEM,
865
- allowed_getattr=BUILTIN_GETATTR,
866
- allowed_getattr_external={
867
- # pandas Series/Frame implements custom `__getattr__`
868
- ("pandas", "DataFrame"),
869
- ("pandas", "Series"),
870
- },
871
- allowed_operations=BUILTIN_OPERATIONS,
872
- allow_builtins_access=True,
873
- allow_locals_access=True,
874
- allow_globals_access=True,
875
- allowed_calls=ALLOWED_CALLS,
876
- ),
877
- "unsafe": EvaluationPolicy(
878
- allow_builtins_access=True,
879
- allow_locals_access=True,
880
- allow_globals_access=True,
881
- allow_attr_access=True,
882
- allow_item_access=True,
883
- allow_any_calls=True,
884
- allow_all_operations=True,
885
- ),
886
- }
887
-
888
-
889
- __all__ = [
890
- "guarded_eval",
891
- "eval_node",
892
- "GuardRejection",
893
- "EvaluationContext",
894
- "_unbind_method",
895
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/history.py DELETED
@@ -1,989 +0,0 @@
1
- """ History related magics and functionality """
2
-
3
- # Copyright (c) IPython Development Team.
4
- # Distributed under the terms of the Modified BSD License.
5
-
6
-
7
- import atexit
8
- import datetime
9
- import re
10
- import sqlite3
11
- import threading
12
- from pathlib import Path
13
-
14
- from decorator import decorator
15
- from traitlets import (
16
- Any,
17
- Bool,
18
- Dict,
19
- Instance,
20
- Integer,
21
- List,
22
- TraitError,
23
- Unicode,
24
- Union,
25
- default,
26
- observe,
27
- )
28
- from traitlets.config.configurable import LoggingConfigurable
29
-
30
- from IPython.paths import locate_profile
31
- from IPython.utils.decorators import undoc
32
-
33
- #-----------------------------------------------------------------------------
34
- # Classes and functions
35
- #-----------------------------------------------------------------------------
36
-
37
- @undoc
38
- class DummyDB(object):
39
- """Dummy DB that will act as a black hole for history.
40
-
41
- Only used in the absence of sqlite"""
42
- def execute(*args, **kwargs):
43
- return []
44
-
45
- def commit(self, *args, **kwargs):
46
- pass
47
-
48
- def __enter__(self, *args, **kwargs):
49
- pass
50
-
51
- def __exit__(self, *args, **kwargs):
52
- pass
53
-
54
-
55
- @decorator
56
- def only_when_enabled(f, self, *a, **kw):
57
- """Decorator: return an empty list in the absence of sqlite."""
58
- if not self.enabled:
59
- return []
60
- else:
61
- return f(self, *a, **kw)
62
-
63
-
64
- # use 16kB as threshold for whether a corrupt history db should be saved
65
- # that should be at least 100 entries or so
66
- _SAVE_DB_SIZE = 16384
67
-
68
- @decorator
69
- def catch_corrupt_db(f, self, *a, **kw):
70
- """A decorator which wraps HistoryAccessor method calls to catch errors from
71
- a corrupt SQLite database, move the old database out of the way, and create
72
- a new one.
73
-
74
- We avoid clobbering larger databases because this may be triggered due to filesystem issues,
75
- not just a corrupt file.
76
- """
77
- try:
78
- return f(self, *a, **kw)
79
- except (sqlite3.DatabaseError, sqlite3.OperationalError) as e:
80
- self._corrupt_db_counter += 1
81
- self.log.error("Failed to open SQLite history %s (%s).", self.hist_file, e)
82
- if self.hist_file != ':memory:':
83
- if self._corrupt_db_counter > self._corrupt_db_limit:
84
- self.hist_file = ':memory:'
85
- self.log.error("Failed to load history too many times, history will not be saved.")
86
- elif self.hist_file.is_file():
87
- # move the file out of the way
88
- base = str(self.hist_file.parent / self.hist_file.stem)
89
- ext = self.hist_file.suffix
90
- size = self.hist_file.stat().st_size
91
- if size >= _SAVE_DB_SIZE:
92
- # if there's significant content, avoid clobbering
93
- now = datetime.datetime.now().isoformat().replace(':', '.')
94
- newpath = base + '-corrupt-' + now + ext
95
- # don't clobber previous corrupt backups
96
- for i in range(100):
97
- if not Path(newpath).exists():
98
- break
99
- else:
100
- newpath = base + '-corrupt-' + now + (u'-%i' % i) + ext
101
- else:
102
- # not much content, possibly empty; don't worry about clobbering
103
- # maybe we should just delete it?
104
- newpath = base + '-corrupt' + ext
105
- self.hist_file.rename(newpath)
106
- self.log.error("History file was moved to %s and a new file created.", newpath)
107
- self.init_db()
108
- return []
109
- else:
110
- # Failed with :memory:, something serious is wrong
111
- raise
112
-
113
-
114
- class HistoryAccessorBase(LoggingConfigurable):
115
- """An abstract class for History Accessors """
116
-
117
- def get_tail(self, n=10, raw=True, output=False, include_latest=False):
118
- raise NotImplementedError
119
-
120
- def search(self, pattern="*", raw=True, search_raw=True,
121
- output=False, n=None, unique=False):
122
- raise NotImplementedError
123
-
124
- def get_range(self, session, start=1, stop=None, raw=True,output=False):
125
- raise NotImplementedError
126
-
127
- def get_range_by_str(self, rangestr, raw=True, output=False):
128
- raise NotImplementedError
129
-
130
-
131
- class HistoryAccessor(HistoryAccessorBase):
132
- """Access the history database without adding to it.
133
-
134
- This is intended for use by standalone history tools. IPython shells use
135
- HistoryManager, below, which is a subclass of this."""
136
-
137
- # counter for init_db retries, so we don't keep trying over and over
138
- _corrupt_db_counter = 0
139
- # after two failures, fallback on :memory:
140
- _corrupt_db_limit = 2
141
-
142
- # String holding the path to the history file
143
- hist_file = Union(
144
- [Instance(Path), Unicode()],
145
- help="""Path to file to use for SQLite history database.
146
-
147
- By default, IPython will put the history database in the IPython
148
- profile directory. If you would rather share one history among
149
- profiles, you can set this value in each, so that they are consistent.
150
-
151
- Due to an issue with fcntl, SQLite is known to misbehave on some NFS
152
- mounts. If you see IPython hanging, try setting this to something on a
153
- local disk, e.g::
154
-
155
- ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite
156
-
157
- you can also use the specific value `:memory:` (including the colon
158
- at both end but not the back ticks), to avoid creating an history file.
159
-
160
- """,
161
- ).tag(config=True)
162
-
163
- enabled = Bool(True,
164
- help="""enable the SQLite history
165
-
166
- set enabled=False to disable the SQLite history,
167
- in which case there will be no stored history, no SQLite connection,
168
- and no background saving thread. This may be necessary in some
169
- threaded environments where IPython is embedded.
170
- """,
171
- ).tag(config=True)
172
-
173
- connection_options = Dict(
174
- help="""Options for configuring the SQLite connection
175
-
176
- These options are passed as keyword args to sqlite3.connect
177
- when establishing database connections.
178
- """
179
- ).tag(config=True)
180
-
181
- @default("connection_options")
182
- def _default_connection_options(self):
183
- return dict(check_same_thread=False)
184
-
185
- # The SQLite database
186
- db = Any()
187
- @observe('db')
188
- def _db_changed(self, change):
189
- """validate the db, since it can be an Instance of two different types"""
190
- new = change['new']
191
- connection_types = (DummyDB, sqlite3.Connection)
192
- if not isinstance(new, connection_types):
193
- msg = "%s.db must be sqlite3 Connection or DummyDB, not %r" % \
194
- (self.__class__.__name__, new)
195
- raise TraitError(msg)
196
-
197
- def __init__(self, profile="default", hist_file="", **traits):
198
- """Create a new history accessor.
199
-
200
- Parameters
201
- ----------
202
- profile : str
203
- The name of the profile from which to open history.
204
- hist_file : str
205
- Path to an SQLite history database stored by IPython. If specified,
206
- hist_file overrides profile.
207
- config : :class:`~traitlets.config.loader.Config`
208
- Config object. hist_file can also be set through this.
209
- """
210
- super(HistoryAccessor, self).__init__(**traits)
211
- # defer setting hist_file from kwarg until after init,
212
- # otherwise the default kwarg value would clobber any value
213
- # set by config
214
- if hist_file:
215
- self.hist_file = hist_file
216
-
217
- try:
218
- self.hist_file
219
- except TraitError:
220
- # No one has set the hist_file, yet.
221
- self.hist_file = self._get_hist_file_name(profile)
222
-
223
- self.init_db()
224
-
225
- def _get_hist_file_name(self, profile='default'):
226
- """Find the history file for the given profile name.
227
-
228
- This is overridden by the HistoryManager subclass, to use the shell's
229
- active profile.
230
-
231
- Parameters
232
- ----------
233
- profile : str
234
- The name of a profile which has a history file.
235
- """
236
- return Path(locate_profile(profile)) / "history.sqlite"
237
-
238
- @catch_corrupt_db
239
- def init_db(self):
240
- """Connect to the database, and create tables if necessary."""
241
- if not self.enabled:
242
- self.db = DummyDB()
243
- return
244
-
245
- # use detect_types so that timestamps return datetime objects
246
- kwargs = dict(detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
247
- kwargs.update(self.connection_options)
248
- self.db = sqlite3.connect(str(self.hist_file), **kwargs)
249
- with self.db:
250
- self.db.execute(
251
- """CREATE TABLE IF NOT EXISTS sessions (session integer
252
- primary key autoincrement, start timestamp,
253
- end timestamp, num_cmds integer, remark text)"""
254
- )
255
- self.db.execute(
256
- """CREATE TABLE IF NOT EXISTS history
257
- (session integer, line integer, source text, source_raw text,
258
- PRIMARY KEY (session, line))"""
259
- )
260
- # Output history is optional, but ensure the table's there so it can be
261
- # enabled later.
262
- self.db.execute(
263
- """CREATE TABLE IF NOT EXISTS output_history
264
- (session integer, line integer, output text,
265
- PRIMARY KEY (session, line))"""
266
- )
267
- # success! reset corrupt db count
268
- self._corrupt_db_counter = 0
269
-
270
- def writeout_cache(self):
271
- """Overridden by HistoryManager to dump the cache before certain
272
- database lookups."""
273
- pass
274
-
275
- ## -------------------------------
276
- ## Methods for retrieving history:
277
- ## -------------------------------
278
- def _run_sql(self, sql, params, raw=True, output=False, latest=False):
279
- """Prepares and runs an SQL query for the history database.
280
-
281
- Parameters
282
- ----------
283
- sql : str
284
- Any filtering expressions to go after SELECT ... FROM ...
285
- params : tuple
286
- Parameters passed to the SQL query (to replace "?")
287
- raw, output : bool
288
- See :meth:`get_range`
289
- latest : bool
290
- Select rows with max (session, line)
291
-
292
- Returns
293
- -------
294
- Tuples as :meth:`get_range`
295
- """
296
- toget = 'source_raw' if raw else 'source'
297
- sqlfrom = "history"
298
- if output:
299
- sqlfrom = "history LEFT JOIN output_history USING (session, line)"
300
- toget = "history.%s, output_history.output" % toget
301
- if latest:
302
- toget += ", MAX(session * 128 * 1024 + line)"
303
- this_querry = "SELECT session, line, %s FROM %s " % (toget, sqlfrom) + sql
304
- cur = self.db.execute(this_querry, params)
305
- if latest:
306
- cur = (row[:-1] for row in cur)
307
- if output: # Regroup into 3-tuples, and parse JSON
308
- return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur)
309
- return cur
310
-
311
- @only_when_enabled
312
- @catch_corrupt_db
313
- def get_session_info(self, session):
314
- """Get info about a session.
315
-
316
- Parameters
317
- ----------
318
- session : int
319
- Session number to retrieve.
320
-
321
- Returns
322
- -------
323
- session_id : int
324
- Session ID number
325
- start : datetime
326
- Timestamp for the start of the session.
327
- end : datetime
328
- Timestamp for the end of the session, or None if IPython crashed.
329
- num_cmds : int
330
- Number of commands run, or None if IPython crashed.
331
- remark : unicode
332
- A manually set description.
333
- """
334
- query = "SELECT * from sessions where session == ?"
335
- return self.db.execute(query, (session,)).fetchone()
336
-
337
- @catch_corrupt_db
338
- def get_last_session_id(self):
339
- """Get the last session ID currently in the database.
340
-
341
- Within IPython, this should be the same as the value stored in
342
- :attr:`HistoryManager.session_number`.
343
- """
344
- for record in self.get_tail(n=1, include_latest=True):
345
- return record[0]
346
-
347
- @catch_corrupt_db
348
- def get_tail(self, n=10, raw=True, output=False, include_latest=False):
349
- """Get the last n lines from the history database.
350
-
351
- Parameters
352
- ----------
353
- n : int
354
- The number of lines to get
355
- raw, output : bool
356
- See :meth:`get_range`
357
- include_latest : bool
358
- If False (default), n+1 lines are fetched, and the latest one
359
- is discarded. This is intended to be used where the function
360
- is called by a user command, which it should not return.
361
-
362
- Returns
363
- -------
364
- Tuples as :meth:`get_range`
365
- """
366
- self.writeout_cache()
367
- if not include_latest:
368
- n += 1
369
- cur = self._run_sql(
370
- "ORDER BY session DESC, line DESC LIMIT ?", (n,), raw=raw, output=output
371
- )
372
- if not include_latest:
373
- return reversed(list(cur)[1:])
374
- return reversed(list(cur))
375
-
376
- @catch_corrupt_db
377
- def search(self, pattern="*", raw=True, search_raw=True,
378
- output=False, n=None, unique=False):
379
- """Search the database using unix glob-style matching (wildcards
380
- * and ?).
381
-
382
- Parameters
383
- ----------
384
- pattern : str
385
- The wildcarded pattern to match when searching
386
- search_raw : bool
387
- If True, search the raw input, otherwise, the parsed input
388
- raw, output : bool
389
- See :meth:`get_range`
390
- n : None or int
391
- If an integer is given, it defines the limit of
392
- returned entries.
393
- unique : bool
394
- When it is true, return only unique entries.
395
-
396
- Returns
397
- -------
398
- Tuples as :meth:`get_range`
399
- """
400
- tosearch = "source_raw" if search_raw else "source"
401
- if output:
402
- tosearch = "history." + tosearch
403
- self.writeout_cache()
404
- sqlform = "WHERE %s GLOB ?" % tosearch
405
- params = (pattern,)
406
- if unique:
407
- sqlform += ' GROUP BY {0}'.format(tosearch)
408
- if n is not None:
409
- sqlform += " ORDER BY session DESC, line DESC LIMIT ?"
410
- params += (n,)
411
- elif unique:
412
- sqlform += " ORDER BY session, line"
413
- cur = self._run_sql(sqlform, params, raw=raw, output=output, latest=unique)
414
- if n is not None:
415
- return reversed(list(cur))
416
- return cur
417
-
418
- @catch_corrupt_db
419
- def get_range(self, session, start=1, stop=None, raw=True,output=False):
420
- """Retrieve input by session.
421
-
422
- Parameters
423
- ----------
424
- session : int
425
- Session number to retrieve.
426
- start : int
427
- First line to retrieve.
428
- stop : int
429
- End of line range (excluded from output itself). If None, retrieve
430
- to the end of the session.
431
- raw : bool
432
- If True, return untranslated input
433
- output : bool
434
- If True, attempt to include output. This will be 'real' Python
435
- objects for the current session, or text reprs from previous
436
- sessions if db_log_output was enabled at the time. Where no output
437
- is found, None is used.
438
-
439
- Returns
440
- -------
441
- entries
442
- An iterator over the desired lines. Each line is a 3-tuple, either
443
- (session, line, input) if output is False, or
444
- (session, line, (input, output)) if output is True.
445
- """
446
- if stop:
447
- lineclause = "line >= ? AND line < ?"
448
- params = (session, start, stop)
449
- else:
450
- lineclause = "line>=?"
451
- params = (session, start)
452
-
453
- return self._run_sql("WHERE session==? AND %s" % lineclause,
454
- params, raw=raw, output=output)
455
-
456
- def get_range_by_str(self, rangestr, raw=True, output=False):
457
- """Get lines of history from a string of ranges, as used by magic
458
- commands %hist, %save, %macro, etc.
459
-
460
- Parameters
461
- ----------
462
- rangestr : str
463
- A string specifying ranges, e.g. "5 ~2/1-4". If empty string is used,
464
- this will return everything from current session's history.
465
-
466
- See the documentation of :func:`%history` for the full details.
467
-
468
- raw, output : bool
469
- As :meth:`get_range`
470
-
471
- Returns
472
- -------
473
- Tuples as :meth:`get_range`
474
- """
475
- for sess, s, e in extract_hist_ranges(rangestr):
476
- for line in self.get_range(sess, s, e, raw=raw, output=output):
477
- yield line
478
-
479
-
480
- class HistoryManager(HistoryAccessor):
481
- """A class to organize all history-related functionality in one place.
482
- """
483
- # Public interface
484
-
485
- # An instance of the IPython shell we are attached to
486
- shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
487
- allow_none=True)
488
- # Lists to hold processed and raw history. These start with a blank entry
489
- # so that we can index them starting from 1
490
- input_hist_parsed = List([""])
491
- input_hist_raw = List([""])
492
- # A list of directories visited during session
493
- dir_hist: List = List()
494
-
495
- @default("dir_hist")
496
- def _dir_hist_default(self):
497
- try:
498
- return [Path.cwd()]
499
- except OSError:
500
- return []
501
-
502
- # A dict of output history, keyed with ints from the shell's
503
- # execution count.
504
- output_hist = Dict()
505
- # The text/plain repr of outputs.
506
- output_hist_reprs = Dict()
507
-
508
- # The number of the current session in the history database
509
- session_number = Integer()
510
-
511
- db_log_output = Bool(False,
512
- help="Should the history database include output? (default: no)"
513
- ).tag(config=True)
514
- db_cache_size = Integer(0,
515
- help="Write to database every x commands (higher values save disk access & power).\n"
516
- "Values of 1 or less effectively disable caching."
517
- ).tag(config=True)
518
- # The input and output caches
519
- db_input_cache: List = List()
520
- db_output_cache: List = List()
521
-
522
- # History saving in separate thread
523
- save_thread = Instance('IPython.core.history.HistorySavingThread',
524
- allow_none=True)
525
- save_flag = Instance(threading.Event, allow_none=True)
526
-
527
- # Private interface
528
- # Variables used to store the three last inputs from the user. On each new
529
- # history update, we populate the user's namespace with these, shifted as
530
- # necessary.
531
- _i00 = Unicode("")
532
- _i = Unicode("")
533
- _ii = Unicode("")
534
- _iii = Unicode("")
535
-
536
- # A regex matching all forms of the exit command, so that we don't store
537
- # them in the history (it's annoying to rewind the first entry and land on
538
- # an exit call).
539
- _exit_re = re.compile(r"(exit|quit)(\s*\(.*\))?$")
540
-
541
- def __init__(self, shell=None, config=None, **traits):
542
- """Create a new history manager associated with a shell instance.
543
- """
544
- super(HistoryManager, self).__init__(shell=shell, config=config,
545
- **traits)
546
- self.save_flag = threading.Event()
547
- self.db_input_cache_lock = threading.Lock()
548
- self.db_output_cache_lock = threading.Lock()
549
-
550
- try:
551
- self.new_session()
552
- except sqlite3.OperationalError:
553
- self.log.error("Failed to create history session in %s. History will not be saved.",
554
- self.hist_file, exc_info=True)
555
- self.hist_file = ':memory:'
556
-
557
- if self.enabled and self.hist_file != ':memory:':
558
- self.save_thread = HistorySavingThread(self)
559
- try:
560
- self.save_thread.start()
561
- except RuntimeError:
562
- self.log.error(
563
- "Failed to start history saving thread. History will not be saved.",
564
- exc_info=True,
565
- )
566
- self.hist_file = ":memory:"
567
-
568
- def _get_hist_file_name(self, profile=None):
569
- """Get default history file name based on the Shell's profile.
570
-
571
- The profile parameter is ignored, but must exist for compatibility with
572
- the parent class."""
573
- profile_dir = self.shell.profile_dir.location
574
- return Path(profile_dir) / "history.sqlite"
575
-
576
- @only_when_enabled
577
- def new_session(self, conn=None):
578
- """Get a new session number."""
579
- if conn is None:
580
- conn = self.db
581
-
582
- with conn:
583
- cur = conn.execute(
584
- """INSERT INTO sessions VALUES (NULL, ?, NULL,
585
- NULL, '') """,
586
- (datetime.datetime.now().isoformat(" "),),
587
- )
588
- self.session_number = cur.lastrowid
589
-
590
- def end_session(self):
591
- """Close the database session, filling in the end time and line count."""
592
- self.writeout_cache()
593
- with self.db:
594
- self.db.execute(
595
- """UPDATE sessions SET end=?, num_cmds=? WHERE
596
- session==?""",
597
- (
598
- datetime.datetime.now().isoformat(" "),
599
- len(self.input_hist_parsed) - 1,
600
- self.session_number,
601
- ),
602
- )
603
- self.session_number = 0
604
-
605
- def name_session(self, name):
606
- """Give the current session a name in the history database."""
607
- with self.db:
608
- self.db.execute("UPDATE sessions SET remark=? WHERE session==?",
609
- (name, self.session_number))
610
-
611
- def reset(self, new_session=True):
612
- """Clear the session history, releasing all object references, and
613
- optionally open a new session."""
614
- self.output_hist.clear()
615
- # The directory history can't be completely empty
616
- self.dir_hist[:] = [Path.cwd()]
617
-
618
- if new_session:
619
- if self.session_number:
620
- self.end_session()
621
- self.input_hist_parsed[:] = [""]
622
- self.input_hist_raw[:] = [""]
623
- self.new_session()
624
-
625
- # ------------------------------
626
- # Methods for retrieving history
627
- # ------------------------------
628
- def get_session_info(self, session=0):
629
- """Get info about a session.
630
-
631
- Parameters
632
- ----------
633
- session : int
634
- Session number to retrieve. The current session is 0, and negative
635
- numbers count back from current session, so -1 is the previous session.
636
-
637
- Returns
638
- -------
639
- session_id : int
640
- Session ID number
641
- start : datetime
642
- Timestamp for the start of the session.
643
- end : datetime
644
- Timestamp for the end of the session, or None if IPython crashed.
645
- num_cmds : int
646
- Number of commands run, or None if IPython crashed.
647
- remark : unicode
648
- A manually set description.
649
- """
650
- if session <= 0:
651
- session += self.session_number
652
-
653
- return super(HistoryManager, self).get_session_info(session=session)
654
-
655
- @catch_corrupt_db
656
- def get_tail(self, n=10, raw=True, output=False, include_latest=False):
657
- """Get the last n lines from the history database.
658
-
659
- Most recent entry last.
660
-
661
- Completion will be reordered so that that the last ones are when
662
- possible from current session.
663
-
664
- Parameters
665
- ----------
666
- n : int
667
- The number of lines to get
668
- raw, output : bool
669
- See :meth:`get_range`
670
- include_latest : bool
671
- If False (default), n+1 lines are fetched, and the latest one
672
- is discarded. This is intended to be used where the function
673
- is called by a user command, which it should not return.
674
-
675
- Returns
676
- -------
677
- Tuples as :meth:`get_range`
678
- """
679
- self.writeout_cache()
680
- if not include_latest:
681
- n += 1
682
- # cursor/line/entry
683
- this_cur = list(
684
- self._run_sql(
685
- "WHERE session == ? ORDER BY line DESC LIMIT ? ",
686
- (self.session_number, n),
687
- raw=raw,
688
- output=output,
689
- )
690
- )
691
- other_cur = list(
692
- self._run_sql(
693
- "WHERE session != ? ORDER BY session DESC, line DESC LIMIT ?",
694
- (self.session_number, n),
695
- raw=raw,
696
- output=output,
697
- )
698
- )
699
-
700
- everything = this_cur + other_cur
701
-
702
- everything = everything[:n]
703
-
704
- if not include_latest:
705
- return list(everything)[:0:-1]
706
- return list(everything)[::-1]
707
-
708
- def _get_range_session(self, start=1, stop=None, raw=True, output=False):
709
- """Get input and output history from the current session. Called by
710
- get_range, and takes similar parameters."""
711
- input_hist = self.input_hist_raw if raw else self.input_hist_parsed
712
-
713
- n = len(input_hist)
714
- if start < 0:
715
- start += n
716
- if not stop or (stop > n):
717
- stop = n
718
- elif stop < 0:
719
- stop += n
720
-
721
- for i in range(start, stop):
722
- if output:
723
- line = (input_hist[i], self.output_hist_reprs.get(i))
724
- else:
725
- line = input_hist[i]
726
- yield (0, i, line)
727
-
728
- def get_range(self, session=0, start=1, stop=None, raw=True,output=False):
729
- """Retrieve input by session.
730
-
731
- Parameters
732
- ----------
733
- session : int
734
- Session number to retrieve. The current session is 0, and negative
735
- numbers count back from current session, so -1 is previous session.
736
- start : int
737
- First line to retrieve.
738
- stop : int
739
- End of line range (excluded from output itself). If None, retrieve
740
- to the end of the session.
741
- raw : bool
742
- If True, return untranslated input
743
- output : bool
744
- If True, attempt to include output. This will be 'real' Python
745
- objects for the current session, or text reprs from previous
746
- sessions if db_log_output was enabled at the time. Where no output
747
- is found, None is used.
748
-
749
- Returns
750
- -------
751
- entries
752
- An iterator over the desired lines. Each line is a 3-tuple, either
753
- (session, line, input) if output is False, or
754
- (session, line, (input, output)) if output is True.
755
- """
756
- if session <= 0:
757
- session += self.session_number
758
- if session==self.session_number: # Current session
759
- return self._get_range_session(start, stop, raw, output)
760
- return super(HistoryManager, self).get_range(session, start, stop, raw,
761
- output)
762
-
763
- ## ----------------------------
764
- ## Methods for storing history:
765
- ## ----------------------------
766
- def store_inputs(self, line_num, source, source_raw=None):
767
- """Store source and raw input in history and create input cache
768
- variables ``_i*``.
769
-
770
- Parameters
771
- ----------
772
- line_num : int
773
- The prompt number of this input.
774
- source : str
775
- Python input.
776
- source_raw : str, optional
777
- If given, this is the raw input without any IPython transformations
778
- applied to it. If not given, ``source`` is used.
779
- """
780
- if source_raw is None:
781
- source_raw = source
782
- source = source.rstrip('\n')
783
- source_raw = source_raw.rstrip('\n')
784
-
785
- # do not store exit/quit commands
786
- if self._exit_re.match(source_raw.strip()):
787
- return
788
-
789
- self.input_hist_parsed.append(source)
790
- self.input_hist_raw.append(source_raw)
791
-
792
- with self.db_input_cache_lock:
793
- self.db_input_cache.append((line_num, source, source_raw))
794
- # Trigger to flush cache and write to DB.
795
- if len(self.db_input_cache) >= self.db_cache_size:
796
- self.save_flag.set()
797
-
798
- # update the auto _i variables
799
- self._iii = self._ii
800
- self._ii = self._i
801
- self._i = self._i00
802
- self._i00 = source_raw
803
-
804
- # hackish access to user namespace to create _i1,_i2... dynamically
805
- new_i = '_i%s' % line_num
806
- to_main = {'_i': self._i,
807
- '_ii': self._ii,
808
- '_iii': self._iii,
809
- new_i : self._i00 }
810
-
811
- if self.shell is not None:
812
- self.shell.push(to_main, interactive=False)
813
-
814
- def store_output(self, line_num):
815
- """If database output logging is enabled, this saves all the
816
- outputs from the indicated prompt number to the database. It's
817
- called by run_cell after code has been executed.
818
-
819
- Parameters
820
- ----------
821
- line_num : int
822
- The line number from which to save outputs
823
- """
824
- if (not self.db_log_output) or (line_num not in self.output_hist_reprs):
825
- return
826
- output = self.output_hist_reprs[line_num]
827
-
828
- with self.db_output_cache_lock:
829
- self.db_output_cache.append((line_num, output))
830
- if self.db_cache_size <= 1:
831
- self.save_flag.set()
832
-
833
- def _writeout_input_cache(self, conn):
834
- with conn:
835
- for line in self.db_input_cache:
836
- conn.execute("INSERT INTO history VALUES (?, ?, ?, ?)",
837
- (self.session_number,)+line)
838
-
839
- def _writeout_output_cache(self, conn):
840
- with conn:
841
- for line in self.db_output_cache:
842
- conn.execute("INSERT INTO output_history VALUES (?, ?, ?)",
843
- (self.session_number,)+line)
844
-
845
- @only_when_enabled
846
- def writeout_cache(self, conn=None):
847
- """Write any entries in the cache to the database."""
848
- if conn is None:
849
- conn = self.db
850
-
851
- with self.db_input_cache_lock:
852
- try:
853
- self._writeout_input_cache(conn)
854
- except sqlite3.IntegrityError:
855
- self.new_session(conn)
856
- print("ERROR! Session/line number was not unique in",
857
- "database. History logging moved to new session",
858
- self.session_number)
859
- try:
860
- # Try writing to the new session. If this fails, don't
861
- # recurse
862
- self._writeout_input_cache(conn)
863
- except sqlite3.IntegrityError:
864
- pass
865
- finally:
866
- self.db_input_cache = []
867
-
868
- with self.db_output_cache_lock:
869
- try:
870
- self._writeout_output_cache(conn)
871
- except sqlite3.IntegrityError:
872
- print("!! Session/line number for output was not unique",
873
- "in database. Output will not be stored.")
874
- finally:
875
- self.db_output_cache = []
876
-
877
-
878
- class HistorySavingThread(threading.Thread):
879
- """This thread takes care of writing history to the database, so that
880
- the UI isn't held up while that happens.
881
-
882
- It waits for the HistoryManager's save_flag to be set, then writes out
883
- the history cache. The main thread is responsible for setting the flag when
884
- the cache size reaches a defined threshold."""
885
- daemon = True
886
- stop_now = False
887
- enabled = True
888
- def __init__(self, history_manager):
889
- super(HistorySavingThread, self).__init__(name="IPythonHistorySavingThread")
890
- self.history_manager = history_manager
891
- self.enabled = history_manager.enabled
892
-
893
- @only_when_enabled
894
- def run(self):
895
- atexit.register(self.stop)
896
- # We need a separate db connection per thread:
897
- try:
898
- self.db = sqlite3.connect(
899
- str(self.history_manager.hist_file),
900
- **self.history_manager.connection_options,
901
- )
902
- while True:
903
- self.history_manager.save_flag.wait()
904
- if self.stop_now:
905
- self.db.close()
906
- return
907
- self.history_manager.save_flag.clear()
908
- self.history_manager.writeout_cache(self.db)
909
- except Exception as e:
910
- print(("The history saving thread hit an unexpected error (%s)."
911
- "History will not be written to the database.") % repr(e))
912
- finally:
913
- atexit.unregister(self.stop)
914
-
915
- def stop(self):
916
- """This can be called from the main thread to safely stop this thread.
917
-
918
- Note that it does not attempt to write out remaining history before
919
- exiting. That should be done by calling the HistoryManager's
920
- end_session method."""
921
- self.stop_now = True
922
- self.history_manager.save_flag.set()
923
- self.join()
924
-
925
-
926
- # To match, e.g. ~5/8-~2/3
927
- range_re = re.compile(r"""
928
- ((?P<startsess>~?\d+)/)?
929
- (?P<start>\d+)?
930
- ((?P<sep>[\-:])
931
- ((?P<endsess>~?\d+)/)?
932
- (?P<end>\d+))?
933
- $""", re.VERBOSE)
934
-
935
-
936
- def extract_hist_ranges(ranges_str):
937
- """Turn a string of history ranges into 3-tuples of (session, start, stop).
938
-
939
- Empty string results in a `[(0, 1, None)]`, i.e. "everything from current
940
- session".
941
-
942
- Examples
943
- --------
944
- >>> list(extract_hist_ranges("~8/5-~7/4 2"))
945
- [(-8, 5, None), (-7, 1, 5), (0, 2, 3)]
946
- """
947
- if ranges_str == "":
948
- yield (0, 1, None) # Everything from current session
949
- return
950
-
951
- for range_str in ranges_str.split():
952
- rmatch = range_re.match(range_str)
953
- if not rmatch:
954
- continue
955
- start = rmatch.group("start")
956
- if start:
957
- start = int(start)
958
- end = rmatch.group("end")
959
- # If no end specified, get (a, a + 1)
960
- end = int(end) if end else start + 1
961
- else: # start not specified
962
- if not rmatch.group('startsess'): # no startsess
963
- continue
964
- start = 1
965
- end = None # provide the entire session hist
966
-
967
- if rmatch.group("sep") == "-": # 1-3 == 1:4 --> [1, 2, 3]
968
- end += 1
969
- startsess = rmatch.group("startsess") or "0"
970
- endsess = rmatch.group("endsess") or startsess
971
- startsess = int(startsess.replace("~","-"))
972
- endsess = int(endsess.replace("~","-"))
973
- assert endsess >= startsess, "start session must be earlier than end session"
974
-
975
- if endsess == startsess:
976
- yield (startsess, start, end)
977
- continue
978
- # Multiple sessions in one range:
979
- yield (startsess, start, None)
980
- for sess in range(startsess+1, endsess):
981
- yield (sess, 1, None)
982
- yield (endsess, 1, end)
983
-
984
-
985
- def _format_lineno(session, line):
986
- """Helper function to format line numbers properly."""
987
- if session == 0:
988
- return str(line)
989
- return "%s#%s" % (session, line)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/historyapp.py DELETED
@@ -1,158 +0,0 @@
1
- # encoding: utf-8
2
- """
3
- An application for managing IPython history.
4
-
5
- To be invoked as the `ipython history` subcommand.
6
- """
7
-
8
- import sqlite3
9
- from pathlib import Path
10
-
11
- from traitlets.config.application import Application
12
- from .application import BaseIPythonApplication
13
- from traitlets import Bool, Int, Dict
14
- from ..utils.io import ask_yes_no
15
-
16
- trim_hist_help = """Trim the IPython history database to the last 1000 entries.
17
-
18
- This actually copies the last 1000 entries to a new database, and then replaces
19
- the old file with the new. Use the `--keep=` argument to specify a number
20
- other than 1000.
21
- """
22
-
23
- clear_hist_help = """Clear the IPython history database, deleting all entries.
24
-
25
- Because this is a destructive operation, IPython will prompt the user if they
26
- really want to do this. Passing a `-f` flag will force clearing without a
27
- prompt.
28
-
29
- This is an handy alias to `ipython history trim --keep=0`
30
- """
31
-
32
-
33
- class HistoryTrim(BaseIPythonApplication):
34
- description = trim_hist_help
35
-
36
- backup = Bool(False, help="Keep the old history file as history.sqlite.<N>").tag(
37
- config=True
38
- )
39
-
40
- keep = Int(1000, help="Number of recent lines to keep in the database.").tag(
41
- config=True
42
- )
43
-
44
- flags = Dict( # type: ignore
45
- dict(backup=({"HistoryTrim": {"backup": True}}, backup.help))
46
- )
47
-
48
- aliases = Dict(dict(keep="HistoryTrim.keep")) # type: ignore
49
-
50
- def start(self):
51
- profile_dir = Path(self.profile_dir.location)
52
- hist_file = profile_dir / "history.sqlite"
53
- con = sqlite3.connect(hist_file)
54
-
55
- # Grab the recent history from the current database.
56
- inputs = list(con.execute('SELECT session, line, source, source_raw FROM '
57
- 'history ORDER BY session DESC, line DESC LIMIT ?', (self.keep+1,)))
58
- if len(inputs) <= self.keep:
59
- print("There are already at most %d entries in the history database." % self.keep)
60
- print("Not doing anything. Use --keep= argument to keep fewer entries")
61
- return
62
-
63
- print("Trimming history to the most recent %d entries." % self.keep)
64
-
65
- inputs.pop() # Remove the extra element we got to check the length.
66
- inputs.reverse()
67
- if inputs:
68
- first_session = inputs[0][0]
69
- outputs = list(con.execute('SELECT session, line, output FROM '
70
- 'output_history WHERE session >= ?', (first_session,)))
71
- sessions = list(con.execute('SELECT session, start, end, num_cmds, remark FROM '
72
- 'sessions WHERE session >= ?', (first_session,)))
73
- con.close()
74
-
75
- # Create the new history database.
76
- new_hist_file = profile_dir / "history.sqlite.new"
77
- i = 0
78
- while new_hist_file.exists():
79
- # Make sure we don't interfere with an existing file.
80
- i += 1
81
- new_hist_file = profile_dir / ("history.sqlite.new" + str(i))
82
- new_db = sqlite3.connect(new_hist_file)
83
- new_db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
84
- primary key autoincrement, start timestamp,
85
- end timestamp, num_cmds integer, remark text)""")
86
- new_db.execute("""CREATE TABLE IF NOT EXISTS history
87
- (session integer, line integer, source text, source_raw text,
88
- PRIMARY KEY (session, line))""")
89
- new_db.execute("""CREATE TABLE IF NOT EXISTS output_history
90
- (session integer, line integer, output text,
91
- PRIMARY KEY (session, line))""")
92
- new_db.commit()
93
-
94
-
95
- if inputs:
96
- with new_db:
97
- # Add the recent history into the new database.
98
- new_db.executemany('insert into sessions values (?,?,?,?,?)', sessions)
99
- new_db.executemany('insert into history values (?,?,?,?)', inputs)
100
- new_db.executemany('insert into output_history values (?,?,?)', outputs)
101
- new_db.close()
102
-
103
- if self.backup:
104
- i = 1
105
- backup_hist_file = profile_dir / ("history.sqlite.old.%d" % i)
106
- while backup_hist_file.exists():
107
- i += 1
108
- backup_hist_file = profile_dir / ("history.sqlite.old.%d" % i)
109
- hist_file.rename(backup_hist_file)
110
- print("Backed up longer history file to", backup_hist_file)
111
- else:
112
- hist_file.unlink()
113
-
114
- new_hist_file.rename(hist_file)
115
-
116
-
117
- class HistoryClear(HistoryTrim):
118
- description = clear_hist_help
119
- keep = Int(0, help="Number of recent lines to keep in the database.")
120
-
121
- force = Bool(False, help="Don't prompt user for confirmation").tag(config=True)
122
-
123
- flags = Dict( # type: ignore
124
- dict(
125
- force=({"HistoryClear": {"force": True}}, force.help),
126
- f=({"HistoryTrim": {"force": True}}, force.help),
127
- )
128
- )
129
- aliases = Dict() # type: ignore
130
-
131
- def start(self):
132
- if self.force or ask_yes_no(
133
- "Really delete all ipython history? ", default="no", interrupt="no"
134
- ):
135
- HistoryTrim.start(self)
136
-
137
-
138
- class HistoryApp(Application):
139
- name = "ipython-history"
140
- description = "Manage the IPython history database."
141
-
142
- subcommands = Dict(dict(
143
- trim = (HistoryTrim, HistoryTrim.description.splitlines()[0]),
144
- clear = (HistoryClear, HistoryClear.description.splitlines()[0]),
145
- ))
146
-
147
- def start(self):
148
- if self.subapp is None:
149
- print(
150
- "No subcommand specified. Must specify one of: "
151
- + ", ".join(map(repr, self.subcommands))
152
- + ".\n"
153
- )
154
- self.print_description()
155
- self.print_subcommands()
156
- self.exit(1)
157
- else:
158
- return self.subapp.start()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/hooks.py DELETED
@@ -1,173 +0,0 @@
1
- """Hooks for IPython.
2
-
3
- In Python, it is possible to overwrite any method of any object if you really
4
- want to. But IPython exposes a few 'hooks', methods which are *designed* to
5
- be overwritten by users for customization purposes. This module defines the
6
- default versions of all such hooks, which get used by IPython if not
7
- overridden by the user.
8
-
9
- Hooks are simple functions, but they should be declared with ``self`` as their
10
- first argument, because when activated they are registered into IPython as
11
- instance methods. The self argument will be the IPython running instance
12
- itself, so hooks have full access to the entire IPython object.
13
-
14
- If you wish to define a new hook and activate it, you can make an :doc:`extension
15
- </config/extensions/index>` or a :ref:`startup script <startup_files>`. For
16
- example, you could use a startup file like this::
17
-
18
- import os
19
-
20
- def calljed(self,filename, linenum):
21
- "My editor hook calls the jed editor directly."
22
- print("Calling my own editor, jed ...")
23
- if os.system('jed +%d %s' % (linenum,filename)) != 0:
24
- raise TryNext()
25
-
26
- def load_ipython_extension(ip):
27
- ip.set_hook('editor', calljed)
28
-
29
- """
30
-
31
- #*****************************************************************************
32
- # Copyright (C) 2005 Fernando Perez. <[email protected]>
33
- #
34
- # Distributed under the terms of the BSD License. The full license is in
35
- # the file COPYING, distributed as part of this software.
36
- #*****************************************************************************
37
-
38
- import os
39
- import subprocess
40
- import sys
41
-
42
- from .error import TryNext
43
-
44
- # List here all the default hooks. For now it's just the editor functions
45
- # but over time we'll move here all the public API for user-accessible things.
46
-
47
- __all__ = [
48
- "editor",
49
- "synchronize_with_editor",
50
- "show_in_pager",
51
- "pre_prompt_hook",
52
- "clipboard_get",
53
- ]
54
-
55
- deprecated = {'pre_run_code_hook': "a callback for the 'pre_execute' or 'pre_run_cell' event",
56
- 'late_startup_hook': "a callback for the 'shell_initialized' event",
57
- 'shutdown_hook': "the atexit module",
58
- }
59
-
60
- def editor(self, filename, linenum=None, wait=True):
61
- """Open the default editor at the given filename and linenumber.
62
-
63
- This is IPython's default editor hook, you can use it as an example to
64
- write your own modified one. To set your own editor function as the
65
- new editor hook, call ip.set_hook('editor',yourfunc)."""
66
-
67
- # IPython configures a default editor at startup by reading $EDITOR from
68
- # the environment, and falling back on vi (unix) or notepad (win32).
69
- editor = self.editor
70
-
71
- # marker for at which line to open the file (for existing objects)
72
- if linenum is None or editor=='notepad':
73
- linemark = ''
74
- else:
75
- linemark = '+%d' % int(linenum)
76
-
77
- # Enclose in quotes if necessary and legal
78
- if ' ' in editor and os.path.isfile(editor) and editor[0] != '"':
79
- editor = '"%s"' % editor
80
-
81
- # Call the actual editor
82
- proc = subprocess.Popen('%s %s %s' % (editor, linemark, filename),
83
- shell=True)
84
- if wait and proc.wait() != 0:
85
- raise TryNext()
86
-
87
-
88
- def synchronize_with_editor(self, filename, linenum, column):
89
- pass
90
-
91
-
92
- class CommandChainDispatcher:
93
- """ Dispatch calls to a chain of commands until some func can handle it
94
-
95
- Usage: instantiate, execute "add" to add commands (with optional
96
- priority), execute normally via f() calling mechanism.
97
-
98
- """
99
- def __init__(self,commands=None):
100
- if commands is None:
101
- self.chain = []
102
- else:
103
- self.chain = commands
104
-
105
-
106
- def __call__(self,*args, **kw):
107
- """ Command chain is called just like normal func.
108
-
109
- This will call all funcs in chain with the same args as were given to
110
- this function, and return the result of first func that didn't raise
111
- TryNext"""
112
- last_exc = TryNext()
113
- for prio,cmd in self.chain:
114
- # print("prio",prio,"cmd",cmd) # dbg
115
- try:
116
- return cmd(*args, **kw)
117
- except TryNext as exc:
118
- last_exc = exc
119
- # if no function will accept it, raise TryNext up to the caller
120
- raise last_exc
121
-
122
- def __str__(self):
123
- return str(self.chain)
124
-
125
- def add(self, func, priority=0):
126
- """ Add a func to the cmd chain with given priority """
127
- self.chain.append((priority, func))
128
- self.chain.sort(key=lambda x: x[0])
129
-
130
- def __iter__(self):
131
- """ Return all objects in chain.
132
-
133
- Handy if the objects are not callable.
134
- """
135
- return iter(self.chain)
136
-
137
-
138
- def show_in_pager(self, data, start, screen_lines):
139
- """ Run a string through pager """
140
- # raising TryNext here will use the default paging functionality
141
- raise TryNext
142
-
143
-
144
- def pre_prompt_hook(self):
145
- """ Run before displaying the next prompt
146
-
147
- Use this e.g. to display output from asynchronous operations (in order
148
- to not mess up text entry)
149
- """
150
-
151
- return None
152
-
153
-
154
- def clipboard_get(self):
155
- """ Get text from the clipboard.
156
- """
157
- from ..lib.clipboard import (
158
- osx_clipboard_get,
159
- tkinter_clipboard_get,
160
- win32_clipboard_get,
161
- wayland_clipboard_get,
162
- )
163
- if sys.platform == 'win32':
164
- chain = [win32_clipboard_get, tkinter_clipboard_get]
165
- elif sys.platform == 'darwin':
166
- chain = [osx_clipboard_get, tkinter_clipboard_get]
167
- else:
168
- chain = [wayland_clipboard_get, tkinter_clipboard_get]
169
- dispatcher = CommandChainDispatcher()
170
- for func in chain:
171
- dispatcher.add(func)
172
- text = dispatcher()
173
- return text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/inputsplitter.py DELETED
@@ -1,799 +0,0 @@
1
- """DEPRECATED: Input handling and transformation machinery.
2
-
3
- This module was deprecated in IPython 7.0, in favour of inputtransformer2.
4
-
5
- The first class in this module, :class:`InputSplitter`, is designed to tell when
6
- input from a line-oriented frontend is complete and should be executed, and when
7
- the user should be prompted for another line of code instead. The name 'input
8
- splitter' is largely for historical reasons.
9
-
10
- A companion, :class:`IPythonInputSplitter`, provides the same functionality but
11
- with full support for the extended IPython syntax (magics, system calls, etc).
12
- The code to actually do these transformations is in :mod:`IPython.core.inputtransformer`.
13
- :class:`IPythonInputSplitter` feeds the raw code to the transformers in order
14
- and stores the results.
15
-
16
- For more details, see the class docstrings below.
17
- """
18
-
19
- from __future__ import annotations
20
-
21
- from warnings import warn
22
-
23
- warn('IPython.core.inputsplitter is deprecated since IPython 7 in favor of `IPython.core.inputtransformer2`',
24
- DeprecationWarning)
25
-
26
- # Copyright (c) IPython Development Team.
27
- # Distributed under the terms of the Modified BSD License.
28
- import ast
29
- import codeop
30
- import io
31
- import re
32
- import sys
33
- import tokenize
34
- import warnings
35
-
36
- from typing import List, Tuple, Union, Optional, TYPE_CHECKING
37
- from types import CodeType
38
-
39
- from IPython.core.inputtransformer import (leading_indent,
40
- classic_prompt,
41
- ipy_prompt,
42
- cellmagic,
43
- assemble_logical_lines,
44
- help_end,
45
- escaped_commands,
46
- assign_from_magic,
47
- assign_from_system,
48
- assemble_python_lines,
49
- )
50
- from IPython.utils import tokenutil
51
-
52
- # These are available in this module for backwards compatibility.
53
- from IPython.core.inputtransformer import (ESC_SHELL, ESC_SH_CAP, ESC_HELP,
54
- ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,
55
- ESC_QUOTE, ESC_QUOTE2, ESC_PAREN, ESC_SEQUENCES)
56
-
57
- if TYPE_CHECKING:
58
- from typing_extensions import Self
59
- #-----------------------------------------------------------------------------
60
- # Utilities
61
- #-----------------------------------------------------------------------------
62
-
63
- # FIXME: These are general-purpose utilities that later can be moved to the
64
- # general ward. Kept here for now because we're being very strict about test
65
- # coverage with this code, and this lets us ensure that we keep 100% coverage
66
- # while developing.
67
-
68
- # compiled regexps for autoindent management
69
- dedent_re = re.compile('|'.join([
70
- r'^\s+raise(\s.*)?$', # raise statement (+ space + other stuff, maybe)
71
- r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
72
- r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
73
- r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
74
- r'^\s+pass\s*$', # pass (optionally followed by trailing spaces)
75
- r'^\s+break\s*$', # break (optionally followed by trailing spaces)
76
- r'^\s+continue\s*$', # continue (optionally followed by trailing spaces)
77
- ]))
78
- ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
79
-
80
- # regexp to match pure comment lines so we don't accidentally insert 'if 1:'
81
- # before pure comments
82
- comment_line_re = re.compile(r'^\s*\#')
83
-
84
-
85
- def num_ini_spaces(s):
86
- """Return the number of initial spaces in a string.
87
-
88
- Note that tabs are counted as a single space. For now, we do *not* support
89
- mixing of tabs and spaces in the user's input.
90
-
91
- Parameters
92
- ----------
93
- s : string
94
-
95
- Returns
96
- -------
97
- n : int
98
- """
99
- warnings.warn(
100
- "`num_ini_spaces` is Pending Deprecation since IPython 8.17."
101
- "It is considered for removal in in future version. "
102
- "Please open an issue if you believe it should be kept.",
103
- stacklevel=2,
104
- category=PendingDeprecationWarning,
105
- )
106
- ini_spaces = ini_spaces_re.match(s)
107
- if ini_spaces:
108
- return ini_spaces.end()
109
- else:
110
- return 0
111
-
112
- # Fake token types for partial_tokenize:
113
- INCOMPLETE_STRING = tokenize.N_TOKENS
114
- IN_MULTILINE_STATEMENT = tokenize.N_TOKENS + 1
115
-
116
- # The 2 classes below have the same API as TokenInfo, but don't try to look up
117
- # a token type name that they won't find.
118
- class IncompleteString:
119
- type = exact_type = INCOMPLETE_STRING
120
- def __init__(self, s, start, end, line):
121
- self.s = s
122
- self.start = start
123
- self.end = end
124
- self.line = line
125
-
126
- class InMultilineStatement:
127
- type = exact_type = IN_MULTILINE_STATEMENT
128
- def __init__(self, pos, line):
129
- self.s = ''
130
- self.start = self.end = pos
131
- self.line = line
132
-
133
- def partial_tokens(s):
134
- """Iterate over tokens from a possibly-incomplete string of code.
135
-
136
- This adds two special token types: INCOMPLETE_STRING and
137
- IN_MULTILINE_STATEMENT. These can only occur as the last token yielded, and
138
- represent the two main ways for code to be incomplete.
139
- """
140
- readline = io.StringIO(s).readline
141
- token = tokenize.TokenInfo(tokenize.NEWLINE, '', (1, 0), (1, 0), '')
142
- try:
143
- for token in tokenutil.generate_tokens_catch_errors(readline):
144
- yield token
145
- except tokenize.TokenError as e:
146
- # catch EOF error
147
- lines = s.splitlines(keepends=True)
148
- end = len(lines), len(lines[-1])
149
- if 'multi-line string' in e.args[0]:
150
- l, c = start = token.end
151
- s = lines[l-1][c:] + ''.join(lines[l:])
152
- yield IncompleteString(s, start, end, lines[-1])
153
- elif 'multi-line statement' in e.args[0]:
154
- yield InMultilineStatement(end, lines[-1])
155
- else:
156
- raise
157
-
158
- def find_next_indent(code) -> int:
159
- """Find the number of spaces for the next line of indentation"""
160
- tokens = list(partial_tokens(code))
161
- if tokens[-1].type == tokenize.ENDMARKER:
162
- tokens.pop()
163
- if not tokens:
164
- return 0
165
-
166
- while tokens[-1].type in {
167
- tokenize.DEDENT,
168
- tokenize.NEWLINE,
169
- tokenize.COMMENT,
170
- tokenize.ERRORTOKEN,
171
- }:
172
- tokens.pop()
173
-
174
- # Starting in Python 3.12, the tokenize module adds implicit newlines at the end
175
- # of input. We need to remove those if we're in a multiline statement
176
- if tokens[-1].type == IN_MULTILINE_STATEMENT:
177
- while tokens[-2].type in {tokenize.NL}:
178
- tokens.pop(-2)
179
-
180
-
181
- if tokens[-1].type == INCOMPLETE_STRING:
182
- # Inside a multiline string
183
- return 0
184
-
185
- # Find the indents used before
186
- prev_indents = [0]
187
- def _add_indent(n):
188
- if n != prev_indents[-1]:
189
- prev_indents.append(n)
190
-
191
- tokiter = iter(tokens)
192
- for tok in tokiter:
193
- if tok.type in {tokenize.INDENT, tokenize.DEDENT}:
194
- _add_indent(tok.end[1])
195
- elif (tok.type == tokenize.NL):
196
- try:
197
- _add_indent(next(tokiter).start[1])
198
- except StopIteration:
199
- break
200
-
201
- last_indent = prev_indents.pop()
202
-
203
- # If we've just opened a multiline statement (e.g. 'a = ['), indent more
204
- if tokens[-1].type == IN_MULTILINE_STATEMENT:
205
- if tokens[-2].exact_type in {tokenize.LPAR, tokenize.LSQB, tokenize.LBRACE}:
206
- return last_indent + 4
207
- return last_indent
208
-
209
- if tokens[-1].exact_type == tokenize.COLON:
210
- # Line ends with colon - indent
211
- return last_indent + 4
212
-
213
- if last_indent:
214
- # Examine the last line for dedent cues - statements like return or
215
- # raise which normally end a block of code.
216
- last_line_starts = 0
217
- for i, tok in enumerate(tokens):
218
- if tok.type == tokenize.NEWLINE:
219
- last_line_starts = i + 1
220
-
221
- last_line_tokens = tokens[last_line_starts:]
222
- names = [t.string for t in last_line_tokens if t.type == tokenize.NAME]
223
- if names and names[0] in {'raise', 'return', 'pass', 'break', 'continue'}:
224
- # Find the most recent indentation less than the current level
225
- for indent in reversed(prev_indents):
226
- if indent < last_indent:
227
- return indent
228
-
229
- return last_indent
230
-
231
-
232
- def last_blank(src):
233
- """Determine if the input source ends in a blank.
234
-
235
- A blank is either a newline or a line consisting of whitespace.
236
-
237
- Parameters
238
- ----------
239
- src : string
240
- A single or multiline string.
241
- """
242
- if not src: return False
243
- ll = src.splitlines()[-1]
244
- return (ll == '') or ll.isspace()
245
-
246
-
247
- last_two_blanks_re = re.compile(r'\n\s*\n\s*$', re.MULTILINE)
248
- last_two_blanks_re2 = re.compile(r'.+\n\s*\n\s+$', re.MULTILINE)
249
-
250
- def last_two_blanks(src):
251
- """Determine if the input source ends in two blanks.
252
-
253
- A blank is either a newline or a line consisting of whitespace.
254
-
255
- Parameters
256
- ----------
257
- src : string
258
- A single or multiline string.
259
- """
260
- if not src: return False
261
- # The logic here is tricky: I couldn't get a regexp to work and pass all
262
- # the tests, so I took a different approach: split the source by lines,
263
- # grab the last two and prepend '###\n' as a stand-in for whatever was in
264
- # the body before the last two lines. Then, with that structure, it's
265
- # possible to analyze with two regexps. Not the most elegant solution, but
266
- # it works. If anyone tries to change this logic, make sure to validate
267
- # the whole test suite first!
268
- new_src = '\n'.join(['###\n'] + src.splitlines()[-2:])
269
- return (bool(last_two_blanks_re.match(new_src)) or
270
- bool(last_two_blanks_re2.match(new_src)) )
271
-
272
-
273
- def remove_comments(src):
274
- """Remove all comments from input source.
275
-
276
- Note: comments are NOT recognized inside of strings!
277
-
278
- Parameters
279
- ----------
280
- src : string
281
- A single or multiline input string.
282
-
283
- Returns
284
- -------
285
- String with all Python comments removed.
286
- """
287
-
288
- return re.sub('#.*', '', src)
289
-
290
-
291
- def get_input_encoding():
292
- """Return the default standard input encoding.
293
-
294
- If sys.stdin has no encoding, 'ascii' is returned."""
295
- # There are strange environments for which sys.stdin.encoding is None. We
296
- # ensure that a valid encoding is returned.
297
- encoding = getattr(sys.stdin, 'encoding', None)
298
- if encoding is None:
299
- encoding = 'ascii'
300
- return encoding
301
-
302
- #-----------------------------------------------------------------------------
303
- # Classes and functions for normal Python syntax handling
304
- #-----------------------------------------------------------------------------
305
-
306
- class InputSplitter(object):
307
- r"""An object that can accumulate lines of Python source before execution.
308
-
309
- This object is designed to be fed python source line-by-line, using
310
- :meth:`push`. It will return on each push whether the currently pushed
311
- code could be executed already. In addition, it provides a method called
312
- :meth:`push_accepts_more` that can be used to query whether more input
313
- can be pushed into a single interactive block.
314
-
315
- This is a simple example of how an interactive terminal-based client can use
316
- this tool::
317
-
318
- isp = InputSplitter()
319
- while isp.push_accepts_more():
320
- indent = ' '*isp.indent_spaces
321
- prompt = '>>> ' + indent
322
- line = indent + raw_input(prompt)
323
- isp.push(line)
324
- print('Input source was:\n', isp.source_reset())
325
- """
326
- # A cache for storing the current indentation
327
- # The first value stores the most recently processed source input
328
- # The second value is the number of spaces for the current indentation
329
- # If self.source matches the first value, the second value is a valid
330
- # current indentation. Otherwise, the cache is invalid and the indentation
331
- # must be recalculated.
332
- _indent_spaces_cache: Union[Tuple[None, None], Tuple[str, int]] = None, None
333
- # String, indicating the default input encoding. It is computed by default
334
- # at initialization time via get_input_encoding(), but it can be reset by a
335
- # client with specific knowledge of the encoding.
336
- encoding = ''
337
- # String where the current full source input is stored, properly encoded.
338
- # Reading this attribute is the normal way of querying the currently pushed
339
- # source code, that has been properly encoded.
340
- source: str = ""
341
- # Code object corresponding to the current source. It is automatically
342
- # synced to the source, so it can be queried at any time to obtain the code
343
- # object; it will be None if the source doesn't compile to valid Python.
344
- code: Optional[CodeType] = None
345
-
346
- # Private attributes
347
-
348
- # List with lines of input accumulated so far
349
- _buffer: List[str]
350
- # Command compiler
351
- _compile: codeop.CommandCompiler
352
- # Boolean indicating whether the current block is complete
353
- _is_complete: Optional[bool] = None
354
- # Boolean indicating whether the current block has an unrecoverable syntax error
355
- _is_invalid: bool = False
356
-
357
- def __init__(self) -> None:
358
- """Create a new InputSplitter instance."""
359
- self._buffer = []
360
- self._compile = codeop.CommandCompiler()
361
- self.encoding = get_input_encoding()
362
-
363
- def reset(self):
364
- """Reset the input buffer and associated state."""
365
- self._buffer[:] = []
366
- self.source = ''
367
- self.code = None
368
- self._is_complete = False
369
- self._is_invalid = False
370
-
371
- def source_reset(self):
372
- """Return the input source and perform a full reset.
373
- """
374
- out = self.source
375
- self.reset()
376
- return out
377
-
378
- def check_complete(self, source):
379
- """Return whether a block of code is ready to execute, or should be continued
380
-
381
- This is a non-stateful API, and will reset the state of this InputSplitter.
382
-
383
- Parameters
384
- ----------
385
- source : string
386
- Python input code, which can be multiline.
387
-
388
- Returns
389
- -------
390
- status : str
391
- One of 'complete', 'incomplete', or 'invalid' if source is not a
392
- prefix of valid code.
393
- indent_spaces : int or None
394
- The number of spaces by which to indent the next line of code. If
395
- status is not 'incomplete', this is None.
396
- """
397
- self.reset()
398
- try:
399
- self.push(source)
400
- except SyntaxError:
401
- # Transformers in IPythonInputSplitter can raise SyntaxError,
402
- # which push() will not catch.
403
- return 'invalid', None
404
- else:
405
- if self._is_invalid:
406
- return 'invalid', None
407
- elif self.push_accepts_more():
408
- return 'incomplete', self.get_indent_spaces()
409
- else:
410
- return 'complete', None
411
- finally:
412
- self.reset()
413
-
414
- def push(self, lines:str) -> bool:
415
- """Push one or more lines of input.
416
-
417
- This stores the given lines and returns a status code indicating
418
- whether the code forms a complete Python block or not.
419
-
420
- Any exceptions generated in compilation are swallowed, but if an
421
- exception was produced, the method returns True.
422
-
423
- Parameters
424
- ----------
425
- lines : string
426
- One or more lines of Python input.
427
-
428
- Returns
429
- -------
430
- is_complete : boolean
431
- True if the current input source (the result of the current input
432
- plus prior inputs) forms a complete Python execution block. Note that
433
- this value is also stored as a private attribute (``_is_complete``), so it
434
- can be queried at any time.
435
- """
436
- assert isinstance(lines, str)
437
- self._store(lines)
438
- source = self.source
439
-
440
- # Before calling _compile(), reset the code object to None so that if an
441
- # exception is raised in compilation, we don't mislead by having
442
- # inconsistent code/source attributes.
443
- self.code, self._is_complete = None, None
444
- self._is_invalid = False
445
-
446
- # Honor termination lines properly
447
- if source.endswith('\\\n'):
448
- return False
449
-
450
- try:
451
- with warnings.catch_warnings():
452
- warnings.simplefilter('error', SyntaxWarning)
453
- self.code = self._compile(source, symbol="exec")
454
- # Invalid syntax can produce any of a number of different errors from
455
- # inside the compiler, so we have to catch them all. Syntax errors
456
- # immediately produce a 'ready' block, so the invalid Python can be
457
- # sent to the kernel for evaluation with possible ipython
458
- # special-syntax conversion.
459
- except (SyntaxError, OverflowError, ValueError, TypeError,
460
- MemoryError, SyntaxWarning):
461
- self._is_complete = True
462
- self._is_invalid = True
463
- else:
464
- # Compilation didn't produce any exceptions (though it may not have
465
- # given a complete code object)
466
- self._is_complete = self.code is not None
467
-
468
- return self._is_complete
469
-
470
- def push_accepts_more(self):
471
- """Return whether a block of interactive input can accept more input.
472
-
473
- This method is meant to be used by line-oriented frontends, who need to
474
- guess whether a block is complete or not based solely on prior and
475
- current input lines. The InputSplitter considers it has a complete
476
- interactive block and will not accept more input when either:
477
-
478
- * A SyntaxError is raised
479
-
480
- * The code is complete and consists of a single line or a single
481
- non-compound statement
482
-
483
- * The code is complete and has a blank line at the end
484
-
485
- If the current input produces a syntax error, this method immediately
486
- returns False but does *not* raise the syntax error exception, as
487
- typically clients will want to send invalid syntax to an execution
488
- backend which might convert the invalid syntax into valid Python via
489
- one of the dynamic IPython mechanisms.
490
- """
491
-
492
- # With incomplete input, unconditionally accept more
493
- # A syntax error also sets _is_complete to True - see push()
494
- if not self._is_complete:
495
- #print("Not complete") # debug
496
- return True
497
-
498
- # The user can make any (complete) input execute by leaving a blank line
499
- last_line = self.source.splitlines()[-1]
500
- if (not last_line) or last_line.isspace():
501
- #print("Blank line") # debug
502
- return False
503
-
504
- # If there's just a single line or AST node, and we're flush left, as is
505
- # the case after a simple statement such as 'a=1', we want to execute it
506
- # straight away.
507
- if self.get_indent_spaces() == 0:
508
- if len(self.source.splitlines()) <= 1:
509
- return False
510
-
511
- try:
512
- code_ast = ast.parse("".join(self._buffer))
513
- except Exception:
514
- #print("Can't parse AST") # debug
515
- return False
516
- else:
517
- if len(code_ast.body) == 1 and \
518
- not hasattr(code_ast.body[0], 'body'):
519
- #print("Simple statement") # debug
520
- return False
521
-
522
- # General fallback - accept more code
523
- return True
524
-
525
- def get_indent_spaces(self) -> int:
526
- sourcefor, n = self._indent_spaces_cache
527
- if sourcefor == self.source:
528
- assert n is not None
529
- return n
530
-
531
- # self.source always has a trailing newline
532
- n = find_next_indent(self.source[:-1])
533
- self._indent_spaces_cache = (self.source, n)
534
- return n
535
-
536
- # Backwards compatibility. I think all code that used .indent_spaces was
537
- # inside IPython, but we can leave this here until IPython 7 in case any
538
- # other modules are using it. -TK, November 2017
539
- indent_spaces = property(get_indent_spaces)
540
-
541
- def _store(self, lines, buffer=None, store='source'):
542
- """Store one or more lines of input.
543
-
544
- If input lines are not newline-terminated, a newline is automatically
545
- appended."""
546
-
547
- if buffer is None:
548
- buffer = self._buffer
549
-
550
- if lines.endswith('\n'):
551
- buffer.append(lines)
552
- else:
553
- buffer.append(lines+'\n')
554
- setattr(self, store, self._set_source(buffer))
555
-
556
- def _set_source(self, buffer):
557
- return u''.join(buffer)
558
-
559
-
560
- class IPythonInputSplitter(InputSplitter):
561
- """An input splitter that recognizes all of IPython's special syntax."""
562
-
563
- # String with raw, untransformed input.
564
- source_raw = ''
565
-
566
- # Flag to track when a transformer has stored input that it hasn't given
567
- # back yet.
568
- transformer_accumulating = False
569
-
570
- # Flag to track when assemble_python_lines has stored input that it hasn't
571
- # given back yet.
572
- within_python_line = False
573
-
574
- # Private attributes
575
-
576
- # List with lines of raw input accumulated so far.
577
- _buffer_raw: List[str]
578
-
579
- def __init__(self, line_input_checker=True, physical_line_transforms=None,
580
- logical_line_transforms=None, python_line_transforms=None):
581
- super(IPythonInputSplitter, self).__init__()
582
- self._buffer_raw = []
583
- self._validate = True
584
-
585
- if physical_line_transforms is not None:
586
- self.physical_line_transforms = physical_line_transforms
587
- else:
588
- self.physical_line_transforms = [
589
- leading_indent(),
590
- classic_prompt(),
591
- ipy_prompt(),
592
- cellmagic(end_on_blank_line=line_input_checker),
593
- ]
594
-
595
- self.assemble_logical_lines = assemble_logical_lines()
596
- if logical_line_transforms is not None:
597
- self.logical_line_transforms = logical_line_transforms
598
- else:
599
- self.logical_line_transforms = [
600
- help_end(),
601
- escaped_commands(),
602
- assign_from_magic(),
603
- assign_from_system(),
604
- ]
605
-
606
- self.assemble_python_lines = assemble_python_lines()
607
- if python_line_transforms is not None:
608
- self.python_line_transforms = python_line_transforms
609
- else:
610
- # We don't use any of these at present
611
- self.python_line_transforms = []
612
-
613
- @property
614
- def transforms(self):
615
- "Quick access to all transformers."
616
- return self.physical_line_transforms + \
617
- [self.assemble_logical_lines] + self.logical_line_transforms + \
618
- [self.assemble_python_lines] + self.python_line_transforms
619
-
620
- @property
621
- def transforms_in_use(self):
622
- """Transformers, excluding logical line transformers if we're in a
623
- Python line."""
624
- t = self.physical_line_transforms[:]
625
- if not self.within_python_line:
626
- t += [self.assemble_logical_lines] + self.logical_line_transforms
627
- return t + [self.assemble_python_lines] + self.python_line_transforms
628
-
629
- def reset(self):
630
- """Reset the input buffer and associated state."""
631
- super(IPythonInputSplitter, self).reset()
632
- self._buffer_raw[:] = []
633
- self.source_raw = ''
634
- self.transformer_accumulating = False
635
- self.within_python_line = False
636
-
637
- for t in self.transforms:
638
- try:
639
- t.reset()
640
- except SyntaxError:
641
- # Nothing that calls reset() expects to handle transformer
642
- # errors
643
- pass
644
-
645
- def flush_transformers(self: Self):
646
- def _flush(transform, outs: List[str]):
647
- """yield transformed lines
648
-
649
- always strings, never None
650
-
651
- transform: the current transform
652
- outs: an iterable of previously transformed inputs.
653
- Each may be multiline, which will be passed
654
- one line at a time to transform.
655
- """
656
- for out in outs:
657
- for line in out.splitlines():
658
- # push one line at a time
659
- tmp = transform.push(line)
660
- if tmp is not None:
661
- yield tmp
662
-
663
- # reset the transform
664
- tmp = transform.reset()
665
- if tmp is not None:
666
- yield tmp
667
-
668
- out: List[str] = []
669
- for t in self.transforms_in_use:
670
- out = _flush(t, out)
671
-
672
- out = list(out)
673
- if out:
674
- self._store('\n'.join(out))
675
-
676
- def raw_reset(self):
677
- """Return raw input only and perform a full reset.
678
- """
679
- out = self.source_raw
680
- self.reset()
681
- return out
682
-
683
- def source_reset(self):
684
- try:
685
- self.flush_transformers()
686
- return self.source
687
- finally:
688
- self.reset()
689
-
690
- def push_accepts_more(self):
691
- if self.transformer_accumulating:
692
- return True
693
- else:
694
- return super(IPythonInputSplitter, self).push_accepts_more()
695
-
696
- def transform_cell(self, cell):
697
- """Process and translate a cell of input.
698
- """
699
- self.reset()
700
- try:
701
- self.push(cell)
702
- self.flush_transformers()
703
- return self.source
704
- finally:
705
- self.reset()
706
-
707
- def push(self, lines:str) -> bool:
708
- """Push one or more lines of IPython input.
709
-
710
- This stores the given lines and returns a status code indicating
711
- whether the code forms a complete Python block or not, after processing
712
- all input lines for special IPython syntax.
713
-
714
- Any exceptions generated in compilation are swallowed, but if an
715
- exception was produced, the method returns True.
716
-
717
- Parameters
718
- ----------
719
- lines : string
720
- One or more lines of Python input.
721
-
722
- Returns
723
- -------
724
- is_complete : boolean
725
- True if the current input source (the result of the current input
726
- plus prior inputs) forms a complete Python execution block. Note that
727
- this value is also stored as a private attribute (_is_complete), so it
728
- can be queried at any time.
729
- """
730
- assert isinstance(lines, str)
731
- # We must ensure all input is pure unicode
732
- # ''.splitlines() --> [], but we need to push the empty line to transformers
733
- lines_list = lines.splitlines()
734
- if not lines_list:
735
- lines_list = ['']
736
-
737
- # Store raw source before applying any transformations to it. Note
738
- # that this must be done *after* the reset() call that would otherwise
739
- # flush the buffer.
740
- self._store(lines, self._buffer_raw, 'source_raw')
741
-
742
- transformed_lines_list = []
743
- for line in lines_list:
744
- transformed = self._transform_line(line)
745
- if transformed is not None:
746
- transformed_lines_list.append(transformed)
747
-
748
- if transformed_lines_list:
749
- transformed_lines = '\n'.join(transformed_lines_list)
750
- return super(IPythonInputSplitter, self).push(transformed_lines)
751
- else:
752
- # Got nothing back from transformers - they must be waiting for
753
- # more input.
754
- return False
755
-
756
- def _transform_line(self, line):
757
- """Push a line of input code through the various transformers.
758
-
759
- Returns any output from the transformers, or None if a transformer
760
- is accumulating lines.
761
-
762
- Sets self.transformer_accumulating as a side effect.
763
- """
764
- def _accumulating(dbg):
765
- #print(dbg)
766
- self.transformer_accumulating = True
767
- return None
768
-
769
- for transformer in self.physical_line_transforms:
770
- line = transformer.push(line)
771
- if line is None:
772
- return _accumulating(transformer)
773
-
774
- if not self.within_python_line:
775
- line = self.assemble_logical_lines.push(line)
776
- if line is None:
777
- return _accumulating('acc logical line')
778
-
779
- for transformer in self.logical_line_transforms:
780
- line = transformer.push(line)
781
- if line is None:
782
- return _accumulating(transformer)
783
-
784
- line = self.assemble_python_lines.push(line)
785
- if line is None:
786
- self.within_python_line = True
787
- return _accumulating('acc python line')
788
- else:
789
- self.within_python_line = False
790
-
791
- for transformer in self.python_line_transforms:
792
- line = transformer.push(line)
793
- if line is None:
794
- return _accumulating(transformer)
795
-
796
- #print("transformers clear") #debug
797
- self.transformer_accumulating = False
798
- return line
799
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/inputtransformer.py DELETED
@@ -1,577 +0,0 @@
1
- """DEPRECATED: Input transformer classes to support IPython special syntax.
2
-
3
- This module was deprecated in IPython 7.0, in favour of inputtransformer2.
4
-
5
- This includes the machinery to recognise and transform ``%magic`` commands,
6
- ``!system`` commands, ``help?`` querying, prompt stripping, and so forth.
7
- """
8
- import abc
9
- import functools
10
- import re
11
- import tokenize
12
- import warnings
13
- from tokenize import untokenize, TokenError
14
- from io import StringIO
15
-
16
- from IPython.core.splitinput import LineInfo
17
- from IPython.utils import tokenutil
18
-
19
- #-----------------------------------------------------------------------------
20
- # Globals
21
- #-----------------------------------------------------------------------------
22
-
23
- # The escape sequences that define the syntax transformations IPython will
24
- # apply to user input. These can NOT be just changed here: many regular
25
- # expressions and other parts of the code may use their hardcoded values, and
26
- # for all intents and purposes they constitute the 'IPython syntax', so they
27
- # should be considered fixed.
28
-
29
- ESC_SHELL = '!' # Send line to underlying system shell
30
- ESC_SH_CAP = '!!' # Send line to system shell and capture output
31
- ESC_HELP = '?' # Find information about object
32
- ESC_HELP2 = '??' # Find extra-detailed information about object
33
- ESC_MAGIC = '%' # Call magic function
34
- ESC_MAGIC2 = '%%' # Call cell-magic function
35
- ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
36
- ESC_QUOTE2 = ';' # Quote all args as a single string, call
37
- ESC_PAREN = '/' # Call first argument with rest of line as arguments
38
-
39
- ESC_SEQUENCES = [ESC_SHELL, ESC_SH_CAP, ESC_HELP ,\
40
- ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,\
41
- ESC_QUOTE, ESC_QUOTE2, ESC_PAREN ]
42
-
43
-
44
- class InputTransformer(metaclass=abc.ABCMeta):
45
- """Abstract base class for line-based input transformers."""
46
-
47
- def __init__(self):
48
- warnings.warn(
49
- "`InputTransformer` has been deprecated since IPython 7.0"
50
- " and emit a warnig since IPython 8.31, it"
51
- " will be removed in the future",
52
- DeprecationWarning,
53
- stacklevel=2,
54
- )
55
-
56
- @abc.abstractmethod
57
- def push(self, line):
58
- """Send a line of input to the transformer, returning the transformed
59
- input or None if the transformer is waiting for more input.
60
-
61
- Must be overridden by subclasses.
62
-
63
- Implementations may raise ``SyntaxError`` if the input is invalid. No
64
- other exceptions may be raised.
65
- """
66
- pass
67
-
68
- @abc.abstractmethod
69
- def reset(self):
70
- """Return, transformed any lines that the transformer has accumulated,
71
- and reset its internal state.
72
-
73
- Must be overridden by subclasses.
74
- """
75
- pass
76
-
77
- @classmethod
78
- def wrap(cls, func):
79
- """Can be used by subclasses as a decorator, to return a factory that
80
- will allow instantiation with the decorated object.
81
- """
82
- @functools.wraps(func)
83
- def transformer_factory(**kwargs):
84
- return cls(func, **kwargs) # type: ignore [call-arg]
85
-
86
- return transformer_factory
87
-
88
- class StatelessInputTransformer(InputTransformer):
89
- """Wrapper for a stateless input transformer implemented as a function."""
90
- def __init__(self, func):
91
- super().__init__()
92
- warnings.warn(
93
- "`StatelessInputTransformer` has been deprecated since IPython 7.0"
94
- " and emit a warnig since IPython 8.31, it"
95
- " will be removed in the future",
96
- DeprecationWarning,
97
- stacklevel=2,
98
- )
99
- self.func = func
100
-
101
- def __repr__(self):
102
- return "StatelessInputTransformer(func={0!r})".format(self.func)
103
-
104
- def push(self, line):
105
- """Send a line of input to the transformer, returning the
106
- transformed input."""
107
- return self.func(line)
108
-
109
- def reset(self):
110
- """No-op - exists for compatibility."""
111
- pass
112
-
113
- class CoroutineInputTransformer(InputTransformer):
114
- """Wrapper for an input transformer implemented as a coroutine."""
115
- def __init__(self, coro, **kwargs):
116
- # Prime it
117
- super().__init__()
118
- warnings.warn(
119
- "`CoroutineInputTransformer` has been deprecated since IPython 7.0"
120
- " and emit a warnig since IPython 8.31, it"
121
- " will be removed in the future",
122
- DeprecationWarning,
123
- stacklevel=2,
124
- )
125
- self.coro = coro(**kwargs)
126
- next(self.coro)
127
-
128
- def __repr__(self):
129
- return "CoroutineInputTransformer(coro={0!r})".format(self.coro)
130
-
131
- def push(self, line):
132
- """Send a line of input to the transformer, returning the
133
- transformed input or None if the transformer is waiting for more
134
- input.
135
- """
136
- return self.coro.send(line)
137
-
138
- def reset(self):
139
- """Return, transformed any lines that the transformer has
140
- accumulated, and reset its internal state.
141
- """
142
- return self.coro.send(None)
143
-
144
- class TokenInputTransformer(InputTransformer):
145
- """Wrapper for a token-based input transformer.
146
-
147
- func should accept a list of tokens (5-tuples, see tokenize docs), and
148
- return an iterable which can be passed to tokenize.untokenize().
149
- """
150
- def __init__(self, func):
151
- warnings.warn(
152
- "`CoroutineInputTransformer` has been deprecated since IPython 7.0"
153
- " and emit a warnig since IPython 8.31, it"
154
- " will be removed in the future",
155
- DeprecationWarning,
156
- stacklevel=2,
157
- )
158
- self.func = func
159
- self.buf = []
160
- self.reset_tokenizer()
161
-
162
- def reset_tokenizer(self):
163
- it = iter(self.buf)
164
- self.tokenizer = tokenutil.generate_tokens_catch_errors(it.__next__)
165
-
166
- def push(self, line):
167
- self.buf.append(line + '\n')
168
- if all(l.isspace() for l in self.buf):
169
- return self.reset()
170
-
171
- tokens = []
172
- stop_at_NL = False
173
- try:
174
- for intok in self.tokenizer:
175
- tokens.append(intok)
176
- t = intok[0]
177
- if t == tokenize.NEWLINE or (stop_at_NL and t == tokenize.NL):
178
- # Stop before we try to pull a line we don't have yet
179
- break
180
- elif t == tokenize.ERRORTOKEN:
181
- stop_at_NL = True
182
- except TokenError:
183
- # Multi-line statement - stop and try again with the next line
184
- self.reset_tokenizer()
185
- return None
186
-
187
- return self.output(tokens)
188
-
189
- def output(self, tokens):
190
- self.buf.clear()
191
- self.reset_tokenizer()
192
- return untokenize(self.func(tokens)).rstrip('\n')
193
-
194
- def reset(self):
195
- l = ''.join(self.buf)
196
- self.buf.clear()
197
- self.reset_tokenizer()
198
- if l:
199
- return l.rstrip('\n')
200
-
201
- class assemble_python_lines(TokenInputTransformer):
202
- def __init__(self):
203
- super().__init__(None)
204
-
205
- def output(self, tokens):
206
- return self.reset()
207
-
208
- @CoroutineInputTransformer.wrap
209
- def assemble_logical_lines():
210
- r"""Join lines following explicit line continuations (\)"""
211
- line = ''
212
- while True:
213
- line = (yield line)
214
- if not line or line.isspace():
215
- continue
216
-
217
- parts = []
218
- while line is not None:
219
- if line.endswith('\\') and (not has_comment(line)):
220
- parts.append(line[:-1])
221
- line = (yield None) # Get another line
222
- else:
223
- parts.append(line)
224
- break
225
-
226
- # Output
227
- line = ''.join(parts)
228
-
229
- # Utilities
230
- def _make_help_call(target: str, esc: str, lspace: str) -> str:
231
- """Prepares a pinfo(2)/psearch call from a target name and the escape
232
- (i.e. ? or ??)"""
233
- method = 'pinfo2' if esc == '??' \
234
- else 'psearch' if '*' in target \
235
- else 'pinfo'
236
- arg = " ".join([method, target])
237
- #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
238
- t_magic_name, _, t_magic_arg_s = arg.partition(' ')
239
- t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
240
- return "%sget_ipython().run_line_magic(%r, %r)" % (
241
- lspace,
242
- t_magic_name,
243
- t_magic_arg_s,
244
- )
245
-
246
-
247
- # These define the transformations for the different escape characters.
248
- def _tr_system(line_info: LineInfo):
249
- "Translate lines escaped with: !"
250
- cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
251
- return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
252
-
253
-
254
- def _tr_system2(line_info: LineInfo):
255
- "Translate lines escaped with: !!"
256
- cmd = line_info.line.lstrip()[2:]
257
- return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
258
-
259
-
260
- def _tr_help(line_info: LineInfo):
261
- "Translate lines escaped with: ?/??"
262
- # A naked help line should just fire the intro help screen
263
- if not line_info.line[1:]:
264
- return 'get_ipython().show_usage()'
265
-
266
- return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
267
-
268
-
269
- def _tr_magic(line_info: LineInfo):
270
- "Translate lines escaped with: %"
271
- tpl = '%sget_ipython().run_line_magic(%r, %r)'
272
- if line_info.line.startswith(ESC_MAGIC2):
273
- return line_info.line
274
- cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
275
- #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
276
- t_magic_name, _, t_magic_arg_s = cmd.partition(' ')
277
- t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
278
- return tpl % (line_info.pre, t_magic_name, t_magic_arg_s)
279
-
280
-
281
- def _tr_quote(line_info: LineInfo):
282
- "Translate lines escaped with: ,"
283
- return '%s%s("%s")' % (line_info.pre, line_info.ifun,
284
- '", "'.join(line_info.the_rest.split()) )
285
-
286
-
287
- def _tr_quote2(line_info: LineInfo):
288
- "Translate lines escaped with: ;"
289
- return '%s%s("%s")' % (line_info.pre, line_info.ifun,
290
- line_info.the_rest)
291
-
292
-
293
- def _tr_paren(line_info: LineInfo):
294
- "Translate lines escaped with: /"
295
- return '%s%s(%s)' % (line_info.pre, line_info.ifun,
296
- ", ".join(line_info.the_rest.split()))
297
-
298
- tr = { ESC_SHELL : _tr_system,
299
- ESC_SH_CAP : _tr_system2,
300
- ESC_HELP : _tr_help,
301
- ESC_HELP2 : _tr_help,
302
- ESC_MAGIC : _tr_magic,
303
- ESC_QUOTE : _tr_quote,
304
- ESC_QUOTE2 : _tr_quote2,
305
- ESC_PAREN : _tr_paren }
306
-
307
- @StatelessInputTransformer.wrap
308
- def escaped_commands(line: str):
309
- """Transform escaped commands - %magic, !system, ?help + various autocalls."""
310
- if not line or line.isspace():
311
- return line
312
- lineinf = LineInfo(line)
313
- if lineinf.esc not in tr:
314
- return line
315
-
316
- return tr[lineinf.esc](lineinf)
317
-
318
- _initial_space_re = re.compile(r'\s*')
319
-
320
- _help_end_re = re.compile(r"""(%{0,2}
321
- (?!\d)[\w*]+ # Variable name
322
- (\.(?!\d)[\w*]+)* # .etc.etc
323
- )
324
- (\?\??)$ # ? or ??
325
- """,
326
- re.VERBOSE)
327
-
328
- # Extra pseudotokens for multiline strings and data structures
329
- _MULTILINE_STRING = object()
330
- _MULTILINE_STRUCTURE = object()
331
-
332
- def _line_tokens(line):
333
- """Helper for has_comment and ends_in_comment_or_string."""
334
- readline = StringIO(line).readline
335
- toktypes = set()
336
- try:
337
- for t in tokenutil.generate_tokens_catch_errors(readline):
338
- toktypes.add(t[0])
339
- except TokenError as e:
340
- # There are only two cases where a TokenError is raised.
341
- if 'multi-line string' in e.args[0]:
342
- toktypes.add(_MULTILINE_STRING)
343
- else:
344
- toktypes.add(_MULTILINE_STRUCTURE)
345
- return toktypes
346
-
347
- def has_comment(src):
348
- """Indicate whether an input line has (i.e. ends in, or is) a comment.
349
-
350
- This uses tokenize, so it can distinguish comments from # inside strings.
351
-
352
- Parameters
353
- ----------
354
- src : string
355
- A single line input string.
356
-
357
- Returns
358
- -------
359
- comment : bool
360
- True if source has a comment.
361
- """
362
- return (tokenize.COMMENT in _line_tokens(src))
363
-
364
- def ends_in_comment_or_string(src):
365
- """Indicates whether or not an input line ends in a comment or within
366
- a multiline string.
367
-
368
- Parameters
369
- ----------
370
- src : string
371
- A single line input string.
372
-
373
- Returns
374
- -------
375
- comment : bool
376
- True if source ends in a comment or multiline string.
377
- """
378
- toktypes = _line_tokens(src)
379
- return (tokenize.COMMENT in toktypes) or (_MULTILINE_STRING in toktypes)
380
-
381
-
382
- @StatelessInputTransformer.wrap
383
- def help_end(line: str):
384
- """Translate lines with ?/?? at the end"""
385
- m = _help_end_re.search(line)
386
- if m is None or ends_in_comment_or_string(line):
387
- return line
388
- target = m.group(1)
389
- esc = m.group(3)
390
- match = _initial_space_re.match(line)
391
- assert match is not None
392
- lspace = match.group(0)
393
-
394
- return _make_help_call(target, esc, lspace)
395
-
396
-
397
- @CoroutineInputTransformer.wrap
398
- def cellmagic(end_on_blank_line: bool = False):
399
- """Captures & transforms cell magics.
400
-
401
- After a cell magic is started, this stores up any lines it gets until it is
402
- reset (sent None).
403
- """
404
- tpl = 'get_ipython().run_cell_magic(%r, %r, %r)'
405
- cellmagic_help_re = re.compile(r'%%\w+\?')
406
- line = ''
407
- while True:
408
- line = (yield line)
409
- # consume leading empty lines
410
- while not line:
411
- line = (yield line)
412
-
413
- if not line.startswith(ESC_MAGIC2):
414
- # This isn't a cell magic, idle waiting for reset then start over
415
- while line is not None:
416
- line = (yield line)
417
- continue
418
-
419
- if cellmagic_help_re.match(line):
420
- # This case will be handled by help_end
421
- continue
422
-
423
- first = line
424
- body = []
425
- line = (yield None)
426
- while (line is not None) and \
427
- ((line.strip() != '') or not end_on_blank_line):
428
- body.append(line)
429
- line = (yield None)
430
-
431
- # Output
432
- magic_name, _, first = first.partition(' ')
433
- magic_name = magic_name.lstrip(ESC_MAGIC2)
434
- line = tpl % (magic_name, first, u'\n'.join(body))
435
-
436
-
437
- def _strip_prompts(prompt_re, initial_re=None, turnoff_re=None):
438
- """Remove matching input prompts from a block of input.
439
-
440
- Parameters
441
- ----------
442
- prompt_re : regular expression
443
- A regular expression matching any input prompt (including continuation)
444
- initial_re : regular expression, optional
445
- A regular expression matching only the initial prompt, but not continuation.
446
- If no initial expression is given, prompt_re will be used everywhere.
447
- Used mainly for plain Python prompts, where the continuation prompt
448
- ``...`` is a valid Python expression in Python 3, so shouldn't be stripped.
449
-
450
- Notes
451
- -----
452
- If `initial_re` and `prompt_re differ`,
453
- only `initial_re` will be tested against the first line.
454
- If any prompt is found on the first two lines,
455
- prompts will be stripped from the rest of the block.
456
- """
457
- if initial_re is None:
458
- initial_re = prompt_re
459
- line = ''
460
- while True:
461
- line = (yield line)
462
-
463
- # First line of cell
464
- if line is None:
465
- continue
466
- out, n1 = initial_re.subn('', line, count=1)
467
- if turnoff_re and not n1:
468
- if turnoff_re.match(line):
469
- # We're in e.g. a cell magic; disable this transformer for
470
- # the rest of the cell.
471
- while line is not None:
472
- line = (yield line)
473
- continue
474
-
475
- line = (yield out)
476
-
477
- if line is None:
478
- continue
479
- # check for any prompt on the second line of the cell,
480
- # because people often copy from just after the first prompt,
481
- # so we might not see it in the first line.
482
- out, n2 = prompt_re.subn('', line, count=1)
483
- line = (yield out)
484
-
485
- if n1 or n2:
486
- # Found a prompt in the first two lines - check for it in
487
- # the rest of the cell as well.
488
- while line is not None:
489
- line = (yield prompt_re.sub('', line, count=1))
490
-
491
- else:
492
- # Prompts not in input - wait for reset
493
- while line is not None:
494
- line = (yield line)
495
-
496
- @CoroutineInputTransformer.wrap
497
- def classic_prompt():
498
- """Strip the >>>/... prompts of the Python interactive shell."""
499
- # FIXME: non-capturing version (?:...) usable?
500
- prompt_re = re.compile(r'^(>>>|\.\.\.)( |$)')
501
- initial_re = re.compile(r'^>>>( |$)')
502
- # Any %magic/!system is IPython syntax, so we needn't look for >>> prompts
503
- turnoff_re = re.compile(r'^[%!]')
504
- return _strip_prompts(prompt_re, initial_re, turnoff_re)
505
-
506
- @CoroutineInputTransformer.wrap
507
- def ipy_prompt():
508
- """Strip IPython's In [1]:/...: prompts."""
509
- # FIXME: non-capturing version (?:...) usable?
510
- prompt_re = re.compile(r'^(In \[\d+\]: |\s*\.{3,}: ?)')
511
- # Disable prompt stripping inside cell magics
512
- turnoff_re = re.compile(r'^%%')
513
- return _strip_prompts(prompt_re, turnoff_re=turnoff_re)
514
-
515
-
516
- @CoroutineInputTransformer.wrap
517
- def leading_indent():
518
- """Remove leading indentation.
519
-
520
- If the first line starts with a spaces or tabs, the same whitespace will be
521
- removed from each following line until it is reset.
522
- """
523
- space_re = re.compile(r'^[ \t]+')
524
- line = ''
525
- while True:
526
- line = (yield line)
527
-
528
- if line is None:
529
- continue
530
-
531
- m = space_re.match(line)
532
- if m:
533
- space = m.group(0)
534
- while line is not None:
535
- if line.startswith(space):
536
- line = line[len(space):]
537
- line = (yield line)
538
- else:
539
- # No leading spaces - wait for reset
540
- while line is not None:
541
- line = (yield line)
542
-
543
-
544
- _assign_pat = \
545
- r'''(?P<lhs>(\s*)
546
- ([\w\.]+) # Initial identifier
547
- (\s*,\s*
548
- \*?[\w\.]+)* # Further identifiers for unpacking
549
- \s*?,? # Trailing comma
550
- )
551
- \s*=\s*
552
- '''
553
-
554
- assign_system_re = re.compile(r'{}!\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
555
- assign_system_template = '%s = get_ipython().getoutput(%r)'
556
- @StatelessInputTransformer.wrap
557
- def assign_from_system(line):
558
- """Transform assignment from system commands (e.g. files = !ls)"""
559
- m = assign_system_re.match(line)
560
- if m is None:
561
- return line
562
-
563
- return assign_system_template % m.group('lhs', 'cmd')
564
-
565
- assign_magic_re = re.compile(r'{}%\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
566
- assign_magic_template = '%s = get_ipython().run_line_magic(%r, %r)'
567
- @StatelessInputTransformer.wrap
568
- def assign_from_magic(line):
569
- """Transform assignment from magic commands (e.g. a = %who_ls)"""
570
- m = assign_magic_re.match(line)
571
- if m is None:
572
- return line
573
- #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
574
- m_lhs, m_cmd = m.group('lhs', 'cmd')
575
- t_magic_name, _, t_magic_arg_s = m_cmd.partition(' ')
576
- t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
577
- return assign_magic_template % (m_lhs, t_magic_name, t_magic_arg_s)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/inputtransformer2.py DELETED
@@ -1,830 +0,0 @@
1
- """Input transformer machinery to support IPython special syntax.
2
-
3
- This includes the machinery to recognise and transform ``%magic`` commands,
4
- ``!system`` commands, ``help?`` querying, prompt stripping, and so forth.
5
-
6
- Added: IPython 7.0. Replaces inputsplitter and inputtransformer which were
7
- deprecated in 7.0.
8
- """
9
-
10
- # Copyright (c) IPython Development Team.
11
- # Distributed under the terms of the Modified BSD License.
12
-
13
- import ast
14
- from codeop import CommandCompiler, Compile
15
- import re
16
- import sys
17
- import tokenize
18
- from typing import List, Tuple, Optional, Any
19
- import warnings
20
-
21
- from IPython.utils import tokenutil
22
-
23
- _indent_re = re.compile(r'^[ \t]+')
24
-
25
- def leading_empty_lines(lines):
26
- """Remove leading empty lines
27
-
28
- If the leading lines are empty or contain only whitespace, they will be
29
- removed.
30
- """
31
- if not lines:
32
- return lines
33
- for i, line in enumerate(lines):
34
- if line and not line.isspace():
35
- return lines[i:]
36
- return lines
37
-
38
- def leading_indent(lines):
39
- """Remove leading indentation.
40
-
41
- If the first line starts with a spaces or tabs, the same whitespace will be
42
- removed from each following line in the cell.
43
- """
44
- if not lines:
45
- return lines
46
- m = _indent_re.match(lines[0])
47
- if not m:
48
- return lines
49
- space = m.group(0)
50
- n = len(space)
51
- return [l[n:] if l.startswith(space) else l
52
- for l in lines]
53
-
54
- class PromptStripper:
55
- """Remove matching input prompts from a block of input.
56
-
57
- Parameters
58
- ----------
59
- prompt_re : regular expression
60
- A regular expression matching any input prompt (including continuation,
61
- e.g. ``...``)
62
- initial_re : regular expression, optional
63
- A regular expression matching only the initial prompt, but not continuation.
64
- If no initial expression is given, prompt_re will be used everywhere.
65
- Used mainly for plain Python prompts (``>>>``), where the continuation prompt
66
- ``...`` is a valid Python expression in Python 3, so shouldn't be stripped.
67
-
68
- Notes
69
- -----
70
-
71
- If initial_re and prompt_re differ,
72
- only initial_re will be tested against the first line.
73
- If any prompt is found on the first two lines,
74
- prompts will be stripped from the rest of the block.
75
- """
76
- def __init__(self, prompt_re, initial_re=None):
77
- self.prompt_re = prompt_re
78
- self.initial_re = initial_re or prompt_re
79
-
80
- def _strip(self, lines):
81
- return [self.prompt_re.sub('', l, count=1) for l in lines]
82
-
83
- def __call__(self, lines):
84
- if not lines:
85
- return lines
86
- if self.initial_re.match(lines[0]) or \
87
- (len(lines) > 1 and self.prompt_re.match(lines[1])):
88
- return self._strip(lines)
89
- return lines
90
-
91
- classic_prompt = PromptStripper(
92
- prompt_re=re.compile(r'^(>>>|\.\.\.)( |$)'),
93
- initial_re=re.compile(r'^>>>( |$)')
94
- )
95
-
96
- ipython_prompt = PromptStripper(
97
- re.compile(
98
- r"""
99
- ^( # Match from the beginning of a line, either:
100
-
101
- # 1. First-line prompt:
102
- ((\[nav\]|\[ins\])?\ )? # Vi editing mode prompt, if it's there
103
- In\ # The 'In' of the prompt, with a space
104
- \[\d+\]: # Command index, as displayed in the prompt
105
- \ # With a mandatory trailing space
106
-
107
- | # ... or ...
108
-
109
- # 2. The three dots of the multiline prompt
110
- \s* # All leading whitespace characters
111
- \.{3,}: # The three (or more) dots
112
- \ ? # With an optional trailing space
113
-
114
- )
115
- """,
116
- re.VERBOSE,
117
- )
118
- )
119
-
120
-
121
- def cell_magic(lines):
122
- if not lines or not lines[0].startswith('%%'):
123
- return lines
124
- if re.match(r'%%\w+\?', lines[0]):
125
- # This case will be handled by help_end
126
- return lines
127
- magic_name, _, first_line = lines[0][2:].rstrip().partition(' ')
128
- body = ''.join(lines[1:])
129
- return ['get_ipython().run_cell_magic(%r, %r, %r)\n'
130
- % (magic_name, first_line, body)]
131
-
132
-
133
- def _find_assign_op(token_line) -> Optional[int]:
134
- """Get the index of the first assignment in the line ('=' not inside brackets)
135
-
136
- Note: We don't try to support multiple special assignment (a = b = %foo)
137
- """
138
- paren_level = 0
139
- for i, ti in enumerate(token_line):
140
- s = ti.string
141
- if s == '=' and paren_level == 0:
142
- return i
143
- if s in {'(','[','{'}:
144
- paren_level += 1
145
- elif s in {')', ']', '}'}:
146
- if paren_level > 0:
147
- paren_level -= 1
148
- return None
149
-
150
- def find_end_of_continued_line(lines, start_line: int):
151
- """Find the last line of a line explicitly extended using backslashes.
152
-
153
- Uses 0-indexed line numbers.
154
- """
155
- end_line = start_line
156
- while lines[end_line].endswith('\\\n'):
157
- end_line += 1
158
- if end_line >= len(lines):
159
- break
160
- return end_line
161
-
162
- def assemble_continued_line(lines, start: Tuple[int, int], end_line: int):
163
- r"""Assemble a single line from multiple continued line pieces
164
-
165
- Continued lines are lines ending in ``\``, and the line following the last
166
- ``\`` in the block.
167
-
168
- For example, this code continues over multiple lines::
169
-
170
- if (assign_ix is not None) \
171
- and (len(line) >= assign_ix + 2) \
172
- and (line[assign_ix+1].string == '%') \
173
- and (line[assign_ix+2].type == tokenize.NAME):
174
-
175
- This statement contains four continued line pieces.
176
- Assembling these pieces into a single line would give::
177
-
178
- if (assign_ix is not None) and (len(line) >= assign_ix + 2) and (line[...
179
-
180
- This uses 0-indexed line numbers. *start* is (lineno, colno).
181
-
182
- Used to allow ``%magic`` and ``!system`` commands to be continued over
183
- multiple lines.
184
- """
185
- parts = [lines[start[0]][start[1]:]] + lines[start[0]+1:end_line+1]
186
- return ' '.join([p.rstrip()[:-1] for p in parts[:-1]] # Strip backslash+newline
187
- + [parts[-1].rstrip()]) # Strip newline from last line
188
-
189
- class TokenTransformBase:
190
- """Base class for transformations which examine tokens.
191
-
192
- Special syntax should not be transformed when it occurs inside strings or
193
- comments. This is hard to reliably avoid with regexes. The solution is to
194
- tokenise the code as Python, and recognise the special syntax in the tokens.
195
-
196
- IPython's special syntax is not valid Python syntax, so tokenising may go
197
- wrong after the special syntax starts. These classes therefore find and
198
- transform *one* instance of special syntax at a time into regular Python
199
- syntax. After each transformation, tokens are regenerated to find the next
200
- piece of special syntax.
201
-
202
- Subclasses need to implement one class method (find)
203
- and one regular method (transform).
204
-
205
- The priority attribute can select which transformation to apply if multiple
206
- transformers match in the same place. Lower numbers have higher priority.
207
- This allows "%magic?" to be turned into a help call rather than a magic call.
208
- """
209
- # Lower numbers -> higher priority (for matches in the same location)
210
- priority = 10
211
-
212
- def sortby(self):
213
- return self.start_line, self.start_col, self.priority
214
-
215
- def __init__(self, start):
216
- self.start_line = start[0] - 1 # Shift from 1-index to 0-index
217
- self.start_col = start[1]
218
-
219
- @classmethod
220
- def find(cls, tokens_by_line):
221
- """Find one instance of special syntax in the provided tokens.
222
-
223
- Tokens are grouped into logical lines for convenience,
224
- so it is easy to e.g. look at the first token of each line.
225
- *tokens_by_line* is a list of lists of tokenize.TokenInfo objects.
226
-
227
- This should return an instance of its class, pointing to the start
228
- position it has found, or None if it found no match.
229
- """
230
- raise NotImplementedError
231
-
232
- def transform(self, lines: List[str]):
233
- """Transform one instance of special syntax found by ``find()``
234
-
235
- Takes a list of strings representing physical lines,
236
- returns a similar list of transformed lines.
237
- """
238
- raise NotImplementedError
239
-
240
- class MagicAssign(TokenTransformBase):
241
- """Transformer for assignments from magics (a = %foo)"""
242
- @classmethod
243
- def find(cls, tokens_by_line):
244
- """Find the first magic assignment (a = %foo) in the cell.
245
- """
246
- for line in tokens_by_line:
247
- assign_ix = _find_assign_op(line)
248
- if (assign_ix is not None) \
249
- and (len(line) >= assign_ix + 2) \
250
- and (line[assign_ix+1].string == '%') \
251
- and (line[assign_ix+2].type == tokenize.NAME):
252
- return cls(line[assign_ix+1].start)
253
-
254
- def transform(self, lines: List[str]):
255
- """Transform a magic assignment found by the ``find()`` classmethod.
256
- """
257
- start_line, start_col = self.start_line, self.start_col
258
- lhs = lines[start_line][:start_col]
259
- end_line = find_end_of_continued_line(lines, start_line)
260
- rhs = assemble_continued_line(lines, (start_line, start_col), end_line)
261
- assert rhs.startswith('%'), rhs
262
- magic_name, _, args = rhs[1:].partition(' ')
263
-
264
- lines_before = lines[:start_line]
265
- call = "get_ipython().run_line_magic({!r}, {!r})".format(magic_name, args)
266
- new_line = lhs + call + '\n'
267
- lines_after = lines[end_line+1:]
268
-
269
- return lines_before + [new_line] + lines_after
270
-
271
-
272
- class SystemAssign(TokenTransformBase):
273
- """Transformer for assignments from system commands (a = !foo)"""
274
- @classmethod
275
- def find_pre_312(cls, tokens_by_line):
276
- for line in tokens_by_line:
277
- assign_ix = _find_assign_op(line)
278
- if (assign_ix is not None) \
279
- and not line[assign_ix].line.strip().startswith('=') \
280
- and (len(line) >= assign_ix + 2) \
281
- and (line[assign_ix + 1].type == tokenize.ERRORTOKEN):
282
- ix = assign_ix + 1
283
-
284
- while ix < len(line) and line[ix].type == tokenize.ERRORTOKEN:
285
- if line[ix].string == '!':
286
- return cls(line[ix].start)
287
- elif not line[ix].string.isspace():
288
- break
289
- ix += 1
290
-
291
- @classmethod
292
- def find_post_312(cls, tokens_by_line):
293
- for line in tokens_by_line:
294
- assign_ix = _find_assign_op(line)
295
- if (
296
- (assign_ix is not None)
297
- and not line[assign_ix].line.strip().startswith("=")
298
- and (len(line) >= assign_ix + 2)
299
- and (line[assign_ix + 1].type == tokenize.OP)
300
- and (line[assign_ix + 1].string == "!")
301
- ):
302
- return cls(line[assign_ix + 1].start)
303
-
304
- @classmethod
305
- def find(cls, tokens_by_line):
306
- """Find the first system assignment (a = !foo) in the cell."""
307
- if sys.version_info < (3, 12):
308
- return cls.find_pre_312(tokens_by_line)
309
- return cls.find_post_312(tokens_by_line)
310
-
311
- def transform(self, lines: List[str]):
312
- """Transform a system assignment found by the ``find()`` classmethod.
313
- """
314
- start_line, start_col = self.start_line, self.start_col
315
-
316
- lhs = lines[start_line][:start_col]
317
- end_line = find_end_of_continued_line(lines, start_line)
318
- rhs = assemble_continued_line(lines, (start_line, start_col), end_line)
319
- assert rhs.startswith('!'), rhs
320
- cmd = rhs[1:]
321
-
322
- lines_before = lines[:start_line]
323
- call = "get_ipython().getoutput({!r})".format(cmd)
324
- new_line = lhs + call + '\n'
325
- lines_after = lines[end_line + 1:]
326
-
327
- return lines_before + [new_line] + lines_after
328
-
329
- # The escape sequences that define the syntax transformations IPython will
330
- # apply to user input. These can NOT be just changed here: many regular
331
- # expressions and other parts of the code may use their hardcoded values, and
332
- # for all intents and purposes they constitute the 'IPython syntax', so they
333
- # should be considered fixed.
334
-
335
- ESC_SHELL = '!' # Send line to underlying system shell
336
- ESC_SH_CAP = '!!' # Send line to system shell and capture output
337
- ESC_HELP = '?' # Find information about object
338
- ESC_HELP2 = '??' # Find extra-detailed information about object
339
- ESC_MAGIC = '%' # Call magic function
340
- ESC_MAGIC2 = '%%' # Call cell-magic function
341
- ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
342
- ESC_QUOTE2 = ';' # Quote all args as a single string, call
343
- ESC_PAREN = '/' # Call first argument with rest of line as arguments
344
-
345
- ESCAPE_SINGLES = {'!', '?', '%', ',', ';', '/'}
346
- ESCAPE_DOUBLES = {'!!', '??'} # %% (cell magic) is handled separately
347
-
348
- def _make_help_call(target, esc):
349
- """Prepares a pinfo(2)/psearch call from a target name and the escape
350
- (i.e. ? or ??)"""
351
- method = 'pinfo2' if esc == '??' \
352
- else 'psearch' if '*' in target \
353
- else 'pinfo'
354
- arg = " ".join([method, target])
355
- #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
356
- t_magic_name, _, t_magic_arg_s = arg.partition(' ')
357
- t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
358
- return "get_ipython().run_line_magic(%r, %r)" % (t_magic_name, t_magic_arg_s)
359
-
360
-
361
- def _tr_help(content):
362
- """Translate lines escaped with: ?
363
-
364
- A naked help line should fire the intro help screen (shell.show_usage())
365
- """
366
- if not content:
367
- return 'get_ipython().show_usage()'
368
-
369
- return _make_help_call(content, '?')
370
-
371
- def _tr_help2(content):
372
- """Translate lines escaped with: ??
373
-
374
- A naked help line should fire the intro help screen (shell.show_usage())
375
- """
376
- if not content:
377
- return 'get_ipython().show_usage()'
378
-
379
- return _make_help_call(content, '??')
380
-
381
- def _tr_magic(content):
382
- "Translate lines escaped with a percent sign: %"
383
- name, _, args = content.partition(' ')
384
- return 'get_ipython().run_line_magic(%r, %r)' % (name, args)
385
-
386
- def _tr_quote(content):
387
- "Translate lines escaped with a comma: ,"
388
- name, _, args = content.partition(' ')
389
- return '%s("%s")' % (name, '", "'.join(args.split()) )
390
-
391
- def _tr_quote2(content):
392
- "Translate lines escaped with a semicolon: ;"
393
- name, _, args = content.partition(' ')
394
- return '%s("%s")' % (name, args)
395
-
396
- def _tr_paren(content):
397
- "Translate lines escaped with a slash: /"
398
- name, _, args = content.partition(" ")
399
- if name == "":
400
- raise SyntaxError(f'"{ESC_SHELL}" must be followed by a callable name')
401
-
402
- return '%s(%s)' % (name, ", ".join(args.split()))
403
-
404
- tr = { ESC_SHELL : 'get_ipython().system({!r})'.format,
405
- ESC_SH_CAP : 'get_ipython().getoutput({!r})'.format,
406
- ESC_HELP : _tr_help,
407
- ESC_HELP2 : _tr_help2,
408
- ESC_MAGIC : _tr_magic,
409
- ESC_QUOTE : _tr_quote,
410
- ESC_QUOTE2 : _tr_quote2,
411
- ESC_PAREN : _tr_paren }
412
-
413
- class EscapedCommand(TokenTransformBase):
414
- """Transformer for escaped commands like %foo, !foo, or /foo"""
415
- @classmethod
416
- def find(cls, tokens_by_line):
417
- """Find the first escaped command (%foo, !foo, etc.) in the cell.
418
- """
419
- for line in tokens_by_line:
420
- if not line:
421
- continue
422
- ix = 0
423
- ll = len(line)
424
- while ll > ix and line[ix].type in {tokenize.INDENT, tokenize.DEDENT}:
425
- ix += 1
426
- if ix >= ll:
427
- continue
428
- if line[ix].string in ESCAPE_SINGLES:
429
- return cls(line[ix].start)
430
-
431
- def transform(self, lines):
432
- """Transform an escaped line found by the ``find()`` classmethod.
433
- """
434
- start_line, start_col = self.start_line, self.start_col
435
-
436
- indent = lines[start_line][:start_col]
437
- end_line = find_end_of_continued_line(lines, start_line)
438
- line = assemble_continued_line(lines, (start_line, start_col), end_line)
439
-
440
- if len(line) > 1 and line[:2] in ESCAPE_DOUBLES:
441
- escape, content = line[:2], line[2:]
442
- else:
443
- escape, content = line[:1], line[1:]
444
-
445
- if escape in tr:
446
- call = tr[escape](content)
447
- else:
448
- call = ''
449
-
450
- lines_before = lines[:start_line]
451
- new_line = indent + call + '\n'
452
- lines_after = lines[end_line + 1:]
453
-
454
- return lines_before + [new_line] + lines_after
455
-
456
-
457
- _help_end_re = re.compile(
458
- r"""(%{0,2}
459
- (?!\d)[\w*]+ # Variable name
460
- (\.(?!\d)[\w*]+|\[-?[0-9]+\])* # .etc.etc or [0], we only support literal integers.
461
- )
462
- (\?\??)$ # ? or ??
463
- """,
464
- re.VERBOSE,
465
- )
466
-
467
-
468
- class HelpEnd(TokenTransformBase):
469
- """Transformer for help syntax: obj? and obj??"""
470
- # This needs to be higher priority (lower number) than EscapedCommand so
471
- # that inspecting magics (%foo?) works.
472
- priority = 5
473
-
474
- def __init__(self, start, q_locn):
475
- super().__init__(start)
476
- self.q_line = q_locn[0] - 1 # Shift from 1-indexed to 0-indexed
477
- self.q_col = q_locn[1]
478
-
479
- @classmethod
480
- def find(cls, tokens_by_line):
481
- """Find the first help command (foo?) in the cell.
482
- """
483
- for line in tokens_by_line:
484
- # Last token is NEWLINE; look at last but one
485
- if len(line) > 2 and line[-2].string == '?':
486
- # Find the first token that's not INDENT/DEDENT
487
- ix = 0
488
- while line[ix].type in {tokenize.INDENT, tokenize.DEDENT}:
489
- ix += 1
490
- return cls(line[ix].start, line[-2].start)
491
-
492
- def transform(self, lines):
493
- """Transform a help command found by the ``find()`` classmethod.
494
- """
495
-
496
- piece = "".join(lines[self.start_line : self.q_line + 1])
497
- indent, content = piece[: self.start_col], piece[self.start_col :]
498
- lines_before = lines[: self.start_line]
499
- lines_after = lines[self.q_line + 1 :]
500
-
501
- m = _help_end_re.search(content)
502
- if not m:
503
- raise SyntaxError(content)
504
- assert m is not None, content
505
- target = m.group(1)
506
- esc = m.group(3)
507
-
508
-
509
- call = _make_help_call(target, esc)
510
- new_line = indent + call + '\n'
511
-
512
- return lines_before + [new_line] + lines_after
513
-
514
- def make_tokens_by_line(lines:List[str]):
515
- """Tokenize a series of lines and group tokens by line.
516
-
517
- The tokens for a multiline Python string or expression are grouped as one
518
- line. All lines except the last lines should keep their line ending ('\\n',
519
- '\\r\\n') for this to properly work. Use `.splitlines(keeplineending=True)`
520
- for example when passing block of text to this function.
521
-
522
- """
523
- # NL tokens are used inside multiline expressions, but also after blank
524
- # lines or comments. This is intentional - see https://bugs.python.org/issue17061
525
- # We want to group the former case together but split the latter, so we
526
- # track parentheses level, similar to the internals of tokenize.
527
-
528
- # reexported from token on 3.7+
529
- NEWLINE, NL = tokenize.NEWLINE, tokenize.NL # type: ignore
530
- tokens_by_line: List[List[Any]] = [[]]
531
- if len(lines) > 1 and not lines[0].endswith(("\n", "\r", "\r\n", "\x0b", "\x0c")):
532
- warnings.warn(
533
- "`make_tokens_by_line` received a list of lines which do not have lineending markers ('\\n', '\\r', '\\r\\n', '\\x0b', '\\x0c'), behavior will be unspecified",
534
- stacklevel=2,
535
- )
536
- parenlev = 0
537
- try:
538
- for token in tokenutil.generate_tokens_catch_errors(
539
- iter(lines).__next__, extra_errors_to_catch=["expected EOF"]
540
- ):
541
- tokens_by_line[-1].append(token)
542
- if (token.type == NEWLINE) \
543
- or ((token.type == NL) and (parenlev <= 0)):
544
- tokens_by_line.append([])
545
- elif token.string in {'(', '[', '{'}:
546
- parenlev += 1
547
- elif token.string in {')', ']', '}'}:
548
- if parenlev > 0:
549
- parenlev -= 1
550
- except tokenize.TokenError:
551
- # Input ended in a multiline string or expression. That's OK for us.
552
- pass
553
-
554
-
555
- if not tokens_by_line[-1]:
556
- tokens_by_line.pop()
557
-
558
-
559
- return tokens_by_line
560
-
561
-
562
- def has_sunken_brackets(tokens: List[tokenize.TokenInfo]):
563
- """Check if the depth of brackets in the list of tokens drops below 0"""
564
- parenlev = 0
565
- for token in tokens:
566
- if token.string in {"(", "[", "{"}:
567
- parenlev += 1
568
- elif token.string in {")", "]", "}"}:
569
- parenlev -= 1
570
- if parenlev < 0:
571
- return True
572
- return False
573
-
574
-
575
- def show_linewise_tokens(s: str):
576
- """For investigation and debugging"""
577
- warnings.warn(
578
- "show_linewise_tokens is deprecated since IPython 8.6",
579
- DeprecationWarning,
580
- stacklevel=2,
581
- )
582
- if not s.endswith("\n"):
583
- s += "\n"
584
- lines = s.splitlines(keepends=True)
585
- for line in make_tokens_by_line(lines):
586
- print("Line -------")
587
- for tokinfo in line:
588
- print(" ", tokinfo)
589
-
590
- # Arbitrary limit to prevent getting stuck in infinite loops
591
- TRANSFORM_LOOP_LIMIT = 500
592
-
593
- class TransformerManager:
594
- """Applies various transformations to a cell or code block.
595
-
596
- The key methods for external use are ``transform_cell()``
597
- and ``check_complete()``.
598
- """
599
- def __init__(self):
600
- self.cleanup_transforms = [
601
- leading_empty_lines,
602
- leading_indent,
603
- classic_prompt,
604
- ipython_prompt,
605
- ]
606
- self.line_transforms = [
607
- cell_magic,
608
- ]
609
- self.token_transformers = [
610
- MagicAssign,
611
- SystemAssign,
612
- EscapedCommand,
613
- HelpEnd,
614
- ]
615
-
616
- def do_one_token_transform(self, lines):
617
- """Find and run the transform earliest in the code.
618
-
619
- Returns (changed, lines).
620
-
621
- This method is called repeatedly until changed is False, indicating
622
- that all available transformations are complete.
623
-
624
- The tokens following IPython special syntax might not be valid, so
625
- the transformed code is retokenised every time to identify the next
626
- piece of special syntax. Hopefully long code cells are mostly valid
627
- Python, not using lots of IPython special syntax, so this shouldn't be
628
- a performance issue.
629
- """
630
- tokens_by_line = make_tokens_by_line(lines)
631
- candidates = []
632
- for transformer_cls in self.token_transformers:
633
- transformer = transformer_cls.find(tokens_by_line)
634
- if transformer:
635
- candidates.append(transformer)
636
-
637
- if not candidates:
638
- # Nothing to transform
639
- return False, lines
640
- ordered_transformers = sorted(candidates, key=TokenTransformBase.sortby)
641
- for transformer in ordered_transformers:
642
- try:
643
- return True, transformer.transform(lines)
644
- except SyntaxError:
645
- pass
646
- return False, lines
647
-
648
- def do_token_transforms(self, lines):
649
- for _ in range(TRANSFORM_LOOP_LIMIT):
650
- changed, lines = self.do_one_token_transform(lines)
651
- if not changed:
652
- return lines
653
-
654
- raise RuntimeError("Input transformation still changing after "
655
- "%d iterations. Aborting." % TRANSFORM_LOOP_LIMIT)
656
-
657
- def transform_cell(self, cell: str) -> str:
658
- """Transforms a cell of input code"""
659
- if not cell.endswith('\n'):
660
- cell += '\n' # Ensure the cell has a trailing newline
661
- lines = cell.splitlines(keepends=True)
662
- for transform in self.cleanup_transforms + self.line_transforms:
663
- lines = transform(lines)
664
-
665
- lines = self.do_token_transforms(lines)
666
- return ''.join(lines)
667
-
668
- def check_complete(self, cell: str):
669
- """Return whether a block of code is ready to execute, or should be continued
670
-
671
- Parameters
672
- ----------
673
- cell : string
674
- Python input code, which can be multiline.
675
-
676
- Returns
677
- -------
678
- status : str
679
- One of 'complete', 'incomplete', or 'invalid' if source is not a
680
- prefix of valid code.
681
- indent_spaces : int or None
682
- The number of spaces by which to indent the next line of code. If
683
- status is not 'incomplete', this is None.
684
- """
685
- # Remember if the lines ends in a new line.
686
- ends_with_newline = False
687
- for character in reversed(cell):
688
- if character == '\n':
689
- ends_with_newline = True
690
- break
691
- elif character.strip():
692
- break
693
- else:
694
- continue
695
-
696
- if not ends_with_newline:
697
- # Append an newline for consistent tokenization
698
- # See https://bugs.python.org/issue33899
699
- cell += '\n'
700
-
701
- lines = cell.splitlines(keepends=True)
702
-
703
- if not lines:
704
- return 'complete', None
705
-
706
- for line in reversed(lines):
707
- if not line.strip():
708
- continue
709
- elif line.strip("\n").endswith("\\"):
710
- return "incomplete", find_last_indent(lines)
711
- else:
712
- break
713
-
714
- try:
715
- for transform in self.cleanup_transforms:
716
- if not getattr(transform, 'has_side_effects', False):
717
- lines = transform(lines)
718
- except SyntaxError:
719
- return 'invalid', None
720
-
721
- if lines[0].startswith('%%'):
722
- # Special case for cell magics - completion marked by blank line
723
- if lines[-1].strip():
724
- return 'incomplete', find_last_indent(lines)
725
- else:
726
- return 'complete', None
727
-
728
- try:
729
- for transform in self.line_transforms:
730
- if not getattr(transform, 'has_side_effects', False):
731
- lines = transform(lines)
732
- lines = self.do_token_transforms(lines)
733
- except SyntaxError:
734
- return 'invalid', None
735
-
736
- tokens_by_line = make_tokens_by_line(lines)
737
-
738
- # Bail if we got one line and there are more closing parentheses than
739
- # the opening ones
740
- if (
741
- len(lines) == 1
742
- and tokens_by_line
743
- and has_sunken_brackets(tokens_by_line[0])
744
- ):
745
- return "invalid", None
746
-
747
- if not tokens_by_line:
748
- return 'incomplete', find_last_indent(lines)
749
-
750
- if (
751
- tokens_by_line[-1][-1].type != tokenize.ENDMARKER
752
- and tokens_by_line[-1][-1].type != tokenize.ERRORTOKEN
753
- ):
754
- # We're in a multiline string or expression
755
- return 'incomplete', find_last_indent(lines)
756
-
757
- newline_types = {tokenize.NEWLINE, tokenize.COMMENT, tokenize.ENDMARKER} # type: ignore
758
-
759
- # Pop the last line which only contains DEDENTs and ENDMARKER
760
- last_token_line = None
761
- if {t.type for t in tokens_by_line[-1]} in [
762
- {tokenize.DEDENT, tokenize.ENDMARKER},
763
- {tokenize.ENDMARKER}
764
- ] and len(tokens_by_line) > 1:
765
- last_token_line = tokens_by_line.pop()
766
-
767
- while tokens_by_line[-1] and tokens_by_line[-1][-1].type in newline_types:
768
- tokens_by_line[-1].pop()
769
-
770
- if not tokens_by_line[-1]:
771
- return 'incomplete', find_last_indent(lines)
772
-
773
- if tokens_by_line[-1][-1].string == ':':
774
- # The last line starts a block (e.g. 'if foo:')
775
- ix = 0
776
- while tokens_by_line[-1][ix].type in {tokenize.INDENT, tokenize.DEDENT}:
777
- ix += 1
778
-
779
- indent = tokens_by_line[-1][ix].start[1]
780
- return 'incomplete', indent + 4
781
-
782
- if tokens_by_line[-1][0].line.endswith('\\'):
783
- return 'incomplete', None
784
-
785
- # At this point, our checks think the code is complete (or invalid).
786
- # We'll use codeop.compile_command to check this with the real parser
787
- try:
788
- with warnings.catch_warnings():
789
- warnings.simplefilter('error', SyntaxWarning)
790
- res = compile_command(''.join(lines), symbol='exec')
791
- except (SyntaxError, OverflowError, ValueError, TypeError,
792
- MemoryError, SyntaxWarning):
793
- return 'invalid', None
794
- else:
795
- if res is None:
796
- return 'incomplete', find_last_indent(lines)
797
-
798
- if last_token_line and last_token_line[0].type == tokenize.DEDENT:
799
- if ends_with_newline:
800
- return 'complete', None
801
- return 'incomplete', find_last_indent(lines)
802
-
803
- # If there's a blank line at the end, assume we're ready to execute
804
- if not lines[-1].strip():
805
- return 'complete', None
806
-
807
- return 'complete', None
808
-
809
-
810
- def find_last_indent(lines):
811
- m = _indent_re.match(lines[-1])
812
- if not m:
813
- return 0
814
- return len(m.group(0).replace('\t', ' '*4))
815
-
816
-
817
- class MaybeAsyncCompile(Compile):
818
- def __init__(self, extra_flags=0):
819
- super().__init__()
820
- self.flags |= extra_flags
821
-
822
-
823
- class MaybeAsyncCommandCompiler(CommandCompiler):
824
- def __init__(self, extra_flags=0):
825
- self.compiler = MaybeAsyncCompile(extra_flags=extra_flags)
826
-
827
-
828
- _extra_flags = ast.PyCF_ALLOW_TOP_LEVEL_AWAIT
829
-
830
- compile_command = MaybeAsyncCommandCompiler(extra_flags=_extra_flags)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/interactiveshell.py DELETED
The diff for this file is too large to render. See raw diff
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/latex_symbols.py DELETED
@@ -1,1301 +0,0 @@
1
- # encoding: utf-8
2
-
3
- # DO NOT EDIT THIS FILE BY HAND.
4
-
5
- # To update this file, run the script /tools/gen_latex_symbols.py using Python 3
6
-
7
- # This file is autogenerated from the file:
8
- # https://raw.githubusercontent.com/JuliaLang/julia/master/base/latex_symbols.jl
9
- # This original list is filtered to remove any unicode characters that are not valid
10
- # Python identifiers.
11
-
12
- latex_symbols = {
13
-
14
- "\\euler" : "ℯ",
15
- "\\^a" : "ᵃ",
16
- "\\^b" : "ᵇ",
17
- "\\^c" : "ᶜ",
18
- "\\^d" : "ᵈ",
19
- "\\^e" : "ᵉ",
20
- "\\^f" : "ᶠ",
21
- "\\^g" : "ᵍ",
22
- "\\^h" : "ʰ",
23
- "\\^i" : "ⁱ",
24
- "\\^j" : "ʲ",
25
- "\\^k" : "ᵏ",
26
- "\\^l" : "ˡ",
27
- "\\^m" : "ᵐ",
28
- "\\^n" : "ⁿ",
29
- "\\^o" : "ᵒ",
30
- "\\^p" : "ᵖ",
31
- "\\^r" : "ʳ",
32
- "\\^s" : "ˢ",
33
- "\\^t" : "ᵗ",
34
- "\\^u" : "ᵘ",
35
- "\\^v" : "ᵛ",
36
- "\\^w" : "ʷ",
37
- "\\^x" : "ˣ",
38
- "\\^y" : "ʸ",
39
- "\\^z" : "ᶻ",
40
- "\\^A" : "ᴬ",
41
- "\\^B" : "ᴮ",
42
- "\\^D" : "ᴰ",
43
- "\\^E" : "ᴱ",
44
- "\\^G" : "ᴳ",
45
- "\\^H" : "ᴴ",
46
- "\\^I" : "ᴵ",
47
- "\\^J" : "ᴶ",
48
- "\\^K" : "ᴷ",
49
- "\\^L" : "ᴸ",
50
- "\\^M" : "ᴹ",
51
- "\\^N" : "ᴺ",
52
- "\\^O" : "ᴼ",
53
- "\\^P" : "ᴾ",
54
- "\\^R" : "ᴿ",
55
- "\\^T" : "ᵀ",
56
- "\\^U" : "ᵁ",
57
- "\\^V" : "ⱽ",
58
- "\\^W" : "ᵂ",
59
- "\\^alpha" : "ᵅ",
60
- "\\^beta" : "ᵝ",
61
- "\\^gamma" : "ᵞ",
62
- "\\^delta" : "ᵟ",
63
- "\\^epsilon" : "ᵋ",
64
- "\\^theta" : "ᶿ",
65
- "\\^iota" : "ᶥ",
66
- "\\^phi" : "ᵠ",
67
- "\\^chi" : "ᵡ",
68
- "\\^Phi" : "ᶲ",
69
- "\\_a" : "ₐ",
70
- "\\_e" : "ₑ",
71
- "\\_h" : "ₕ",
72
- "\\_i" : "ᵢ",
73
- "\\_j" : "ⱼ",
74
- "\\_k" : "ₖ",
75
- "\\_l" : "ₗ",
76
- "\\_m" : "ₘ",
77
- "\\_n" : "ₙ",
78
- "\\_o" : "ₒ",
79
- "\\_p" : "ₚ",
80
- "\\_r" : "ᵣ",
81
- "\\_s" : "ₛ",
82
- "\\_t" : "ₜ",
83
- "\\_u" : "ᵤ",
84
- "\\_v" : "ᵥ",
85
- "\\_x" : "ₓ",
86
- "\\_schwa" : "ₔ",
87
- "\\_beta" : "ᵦ",
88
- "\\_gamma" : "ᵧ",
89
- "\\_rho" : "ᵨ",
90
- "\\_phi" : "ᵩ",
91
- "\\_chi" : "ᵪ",
92
- "\\hbar" : "ħ",
93
- "\\sout" : "̶",
94
- "\\ordfeminine" : "ª",
95
- "\\cdotp" : "·",
96
- "\\ordmasculine" : "º",
97
- "\\AA" : "Å",
98
- "\\AE" : "Æ",
99
- "\\DH" : "Ð",
100
- "\\O" : "Ø",
101
- "\\TH" : "Þ",
102
- "\\ss" : "ß",
103
- "\\aa" : "å",
104
- "\\ae" : "æ",
105
- "\\eth" : "ð",
106
- "\\dh" : "ð",
107
- "\\o" : "ø",
108
- "\\th" : "þ",
109
- "\\DJ" : "Đ",
110
- "\\dj" : "đ",
111
- "\\imath" : "ı",
112
- "\\jmath" : "ȷ",
113
- "\\L" : "Ł",
114
- "\\l" : "ł",
115
- "\\NG" : "Ŋ",
116
- "\\ng" : "ŋ",
117
- "\\OE" : "Œ",
118
- "\\oe" : "œ",
119
- "\\hvlig" : "ƕ",
120
- "\\nrleg" : "ƞ",
121
- "\\doublepipe" : "ǂ",
122
- "\\trna" : "ɐ",
123
- "\\trnsa" : "ɒ",
124
- "\\openo" : "ɔ",
125
- "\\rtld" : "ɖ",
126
- "\\schwa" : "ə",
127
- "\\varepsilon" : "ε",
128
- "\\pgamma" : "ɣ",
129
- "\\pbgam" : "ɤ",
130
- "\\trnh" : "ɥ",
131
- "\\btdl" : "ɬ",
132
- "\\rtll" : "ɭ",
133
- "\\trnm" : "ɯ",
134
- "\\trnmlr" : "ɰ",
135
- "\\ltlmr" : "ɱ",
136
- "\\ltln" : "ɲ",
137
- "\\rtln" : "ɳ",
138
- "\\clomeg" : "ɷ",
139
- "\\ltphi" : "ɸ",
140
- "\\trnr" : "ɹ",
141
- "\\trnrl" : "ɺ",
142
- "\\rttrnr" : "ɻ",
143
- "\\rl" : "ɼ",
144
- "\\rtlr" : "ɽ",
145
- "\\fhr" : "ɾ",
146
- "\\rtls" : "ʂ",
147
- "\\esh" : "ʃ",
148
- "\\trnt" : "ʇ",
149
- "\\rtlt" : "ʈ",
150
- "\\pupsil" : "ʊ",
151
- "\\pscrv" : "ʋ",
152
- "\\invv" : "ʌ",
153
- "\\invw" : "ʍ",
154
- "\\trny" : "ʎ",
155
- "\\rtlz" : "ʐ",
156
- "\\yogh" : "ʒ",
157
- "\\glst" : "ʔ",
158
- "\\reglst" : "ʕ",
159
- "\\inglst" : "ʖ",
160
- "\\turnk" : "ʞ",
161
- "\\dyogh" : "ʤ",
162
- "\\tesh" : "ʧ",
163
- "\\rasp" : "ʼ",
164
- "\\verts" : "ˈ",
165
- "\\verti" : "ˌ",
166
- "\\lmrk" : "ː",
167
- "\\hlmrk" : "ˑ",
168
- "\\grave" : "̀",
169
- "\\acute" : "́",
170
- "\\hat" : "̂",
171
- "\\tilde" : "̃",
172
- "\\bar" : "̄",
173
- "\\breve" : "̆",
174
- "\\dot" : "̇",
175
- "\\ddot" : "̈",
176
- "\\ocirc" : "̊",
177
- "\\H" : "̋",
178
- "\\check" : "̌",
179
- "\\palh" : "̡",
180
- "\\rh" : "̢",
181
- "\\c" : "̧",
182
- "\\k" : "̨",
183
- "\\sbbrg" : "̪",
184
- "\\strike" : "̶",
185
- "\\Alpha" : "Α",
186
- "\\Beta" : "Β",
187
- "\\Gamma" : "Γ",
188
- "\\Delta" : "Δ",
189
- "\\Epsilon" : "Ε",
190
- "\\Zeta" : "Ζ",
191
- "\\Eta" : "Η",
192
- "\\Theta" : "Θ",
193
- "\\Iota" : "Ι",
194
- "\\Kappa" : "Κ",
195
- "\\Lambda" : "Λ",
196
- "\\Xi" : "Ξ",
197
- "\\Pi" : "Π",
198
- "\\Rho" : "Ρ",
199
- "\\Sigma" : "Σ",
200
- "\\Tau" : "Τ",
201
- "\\Upsilon" : "Υ",
202
- "\\Phi" : "Φ",
203
- "\\Chi" : "Χ",
204
- "\\Psi" : "Ψ",
205
- "\\Omega" : "Ω",
206
- "\\alpha" : "α",
207
- "\\beta" : "β",
208
- "\\gamma" : "γ",
209
- "\\delta" : "δ",
210
- "\\zeta" : "ζ",
211
- "\\eta" : "η",
212
- "\\theta" : "θ",
213
- "\\iota" : "ι",
214
- "\\kappa" : "κ",
215
- "\\lambda" : "λ",
216
- "\\mu" : "μ",
217
- "\\nu" : "ν",
218
- "\\xi" : "ξ",
219
- "\\pi" : "π",
220
- "\\rho" : "ρ",
221
- "\\varsigma" : "ς",
222
- "\\sigma" : "σ",
223
- "\\tau" : "τ",
224
- "\\upsilon" : "υ",
225
- "\\varphi" : "φ",
226
- "\\chi" : "χ",
227
- "\\psi" : "ψ",
228
- "\\omega" : "ω",
229
- "\\vartheta" : "ϑ",
230
- "\\phi" : "ϕ",
231
- "\\varpi" : "ϖ",
232
- "\\Stigma" : "Ϛ",
233
- "\\Digamma" : "Ϝ",
234
- "\\digamma" : "ϝ",
235
- "\\Koppa" : "Ϟ",
236
- "\\Sampi" : "Ϡ",
237
- "\\varkappa" : "ϰ",
238
- "\\varrho" : "ϱ",
239
- "\\varTheta" : "ϴ",
240
- "\\epsilon" : "ϵ",
241
- "\\dddot" : "⃛",
242
- "\\ddddot" : "⃜",
243
- "\\hslash" : "ℏ",
244
- "\\Im" : "ℑ",
245
- "\\ell" : "ℓ",
246
- "\\wp" : "℘",
247
- "\\Re" : "ℜ",
248
- "\\aleph" : "ℵ",
249
- "\\beth" : "ℶ",
250
- "\\gimel" : "ℷ",
251
- "\\daleth" : "ℸ",
252
- "\\bbPi" : "ℿ",
253
- "\\Zbar" : "Ƶ",
254
- "\\overbar" : "̅",
255
- "\\ovhook" : "̉",
256
- "\\candra" : "̐",
257
- "\\oturnedcomma" : "̒",
258
- "\\ocommatopright" : "̕",
259
- "\\droang" : "̚",
260
- "\\wideutilde" : "̰",
261
- "\\not" : "̸",
262
- "\\upMu" : "Μ",
263
- "\\upNu" : "Ν",
264
- "\\upOmicron" : "Ο",
265
- "\\upepsilon" : "ε",
266
- "\\upomicron" : "ο",
267
- "\\upvarbeta" : "ϐ",
268
- "\\upoldKoppa" : "Ϙ",
269
- "\\upoldkoppa" : "ϙ",
270
- "\\upstigma" : "ϛ",
271
- "\\upkoppa" : "ϟ",
272
- "\\upsampi" : "ϡ",
273
- "\\tieconcat" : "⁀",
274
- "\\leftharpoonaccent" : "⃐",
275
- "\\rightharpoonaccent" : "⃑",
276
- "\\vertoverlay" : "⃒",
277
- "\\overleftarrow" : "⃖",
278
- "\\vec" : "⃗",
279
- "\\overleftrightarrow" : "⃡",
280
- "\\annuity" : "⃧",
281
- "\\threeunderdot" : "⃨",
282
- "\\widebridgeabove" : "⃩",
283
- "\\bbC" : "ℂ",
284
- "\\eulermascheroni" : "ℇ",
285
- "\\scrg" : "ℊ",
286
- "\\scrH" : "ℋ",
287
- "\\frakH" : "ℌ",
288
- "\\bbH" : "ℍ",
289
- "\\planck" : "ℎ",
290
- "\\scrI" : "ℐ",
291
- "\\scrL" : "ℒ",
292
- "\\bbN" : "ℕ",
293
- "\\bbP" : "ℙ",
294
- "\\bbQ" : "ℚ",
295
- "\\scrR" : "ℛ",
296
- "\\bbR" : "ℝ",
297
- "\\bbZ" : "ℤ",
298
- "\\frakZ" : "ℨ",
299
- "\\Angstrom" : "Å",
300
- "\\scrB" : "ℬ",
301
- "\\frakC" : "ℭ",
302
- "\\scre" : "ℯ",
303
- "\\scrE" : "ℰ",
304
- "\\scrF" : "ℱ",
305
- "\\Finv" : "Ⅎ",
306
- "\\scrM" : "ℳ",
307
- "\\scro" : "ℴ",
308
- "\\bbgamma" : "ℽ",
309
- "\\bbGamma" : "ℾ",
310
- "\\bbiD" : "ⅅ",
311
- "\\bbid" : "ⅆ",
312
- "\\bbie" : "ⅇ",
313
- "\\bbii" : "ⅈ",
314
- "\\bbij" : "ⅉ",
315
- "\\bfA" : "𝐀",
316
- "\\bfB" : "𝐁",
317
- "\\bfC" : "𝐂",
318
- "\\bfD" : "𝐃",
319
- "\\bfE" : "𝐄",
320
- "\\bfF" : "𝐅",
321
- "\\bfG" : "𝐆",
322
- "\\bfH" : "𝐇",
323
- "\\bfI" : "𝐈",
324
- "\\bfJ" : "𝐉",
325
- "\\bfK" : "𝐊",
326
- "\\bfL" : "𝐋",
327
- "\\bfM" : "𝐌",
328
- "\\bfN" : "𝐍",
329
- "\\bfO" : "𝐎",
330
- "\\bfP" : "𝐏",
331
- "\\bfQ" : "𝐐",
332
- "\\bfR" : "𝐑",
333
- "\\bfS" : "𝐒",
334
- "\\bfT" : "𝐓",
335
- "\\bfU" : "𝐔",
336
- "\\bfV" : "𝐕",
337
- "\\bfW" : "𝐖",
338
- "\\bfX" : "𝐗",
339
- "\\bfY" : "𝐘",
340
- "\\bfZ" : "𝐙",
341
- "\\bfa" : "𝐚",
342
- "\\bfb" : "𝐛",
343
- "\\bfc" : "𝐜",
344
- "\\bfd" : "𝐝",
345
- "\\bfe" : "𝐞",
346
- "\\bff" : "𝐟",
347
- "\\bfg" : "𝐠",
348
- "\\bfh" : "𝐡",
349
- "\\bfi" : "𝐢",
350
- "\\bfj" : "𝐣",
351
- "\\bfk" : "𝐤",
352
- "\\bfl" : "𝐥",
353
- "\\bfm" : "𝐦",
354
- "\\bfn" : "𝐧",
355
- "\\bfo" : "𝐨",
356
- "\\bfp" : "𝐩",
357
- "\\bfq" : "𝐪",
358
- "\\bfr" : "𝐫",
359
- "\\bfs" : "𝐬",
360
- "\\bft" : "𝐭",
361
- "\\bfu" : "𝐮",
362
- "\\bfv" : "𝐯",
363
- "\\bfw" : "𝐰",
364
- "\\bfx" : "𝐱",
365
- "\\bfy" : "𝐲",
366
- "\\bfz" : "𝐳",
367
- "\\itA" : "𝐴",
368
- "\\itB" : "𝐵",
369
- "\\itC" : "𝐶",
370
- "\\itD" : "𝐷",
371
- "\\itE" : "𝐸",
372
- "\\itF" : "𝐹",
373
- "\\itG" : "𝐺",
374
- "\\itH" : "𝐻",
375
- "\\itI" : "𝐼",
376
- "\\itJ" : "𝐽",
377
- "\\itK" : "𝐾",
378
- "\\itL" : "𝐿",
379
- "\\itM" : "𝑀",
380
- "\\itN" : "𝑁",
381
- "\\itO" : "𝑂",
382
- "\\itP" : "𝑃",
383
- "\\itQ" : "𝑄",
384
- "\\itR" : "𝑅",
385
- "\\itS" : "𝑆",
386
- "\\itT" : "𝑇",
387
- "\\itU" : "𝑈",
388
- "\\itV" : "𝑉",
389
- "\\itW" : "𝑊",
390
- "\\itX" : "𝑋",
391
- "\\itY" : "𝑌",
392
- "\\itZ" : "𝑍",
393
- "\\ita" : "𝑎",
394
- "\\itb" : "𝑏",
395
- "\\itc" : "𝑐",
396
- "\\itd" : "𝑑",
397
- "\\ite" : "𝑒",
398
- "\\itf" : "𝑓",
399
- "\\itg" : "𝑔",
400
- "\\iti" : "𝑖",
401
- "\\itj" : "𝑗",
402
- "\\itk" : "𝑘",
403
- "\\itl" : "𝑙",
404
- "\\itm" : "𝑚",
405
- "\\itn" : "𝑛",
406
- "\\ito" : "𝑜",
407
- "\\itp" : "𝑝",
408
- "\\itq" : "𝑞",
409
- "\\itr" : "𝑟",
410
- "\\its" : "𝑠",
411
- "\\itt" : "𝑡",
412
- "\\itu" : "𝑢",
413
- "\\itv" : "𝑣",
414
- "\\itw" : "𝑤",
415
- "\\itx" : "𝑥",
416
- "\\ity" : "𝑦",
417
- "\\itz" : "𝑧",
418
- "\\biA" : "𝑨",
419
- "\\biB" : "𝑩",
420
- "\\biC" : "𝑪",
421
- "\\biD" : "𝑫",
422
- "\\biE" : "𝑬",
423
- "\\biF" : "𝑭",
424
- "\\biG" : "𝑮",
425
- "\\biH" : "𝑯",
426
- "\\biI" : "𝑰",
427
- "\\biJ" : "𝑱",
428
- "\\biK" : "𝑲",
429
- "\\biL" : "𝑳",
430
- "\\biM" : "𝑴",
431
- "\\biN" : "𝑵",
432
- "\\biO" : "𝑶",
433
- "\\biP" : "𝑷",
434
- "\\biQ" : "𝑸",
435
- "\\biR" : "𝑹",
436
- "\\biS" : "𝑺",
437
- "\\biT" : "𝑻",
438
- "\\biU" : "𝑼",
439
- "\\biV" : "𝑽",
440
- "\\biW" : "𝑾",
441
- "\\biX" : "𝑿",
442
- "\\biY" : "𝒀",
443
- "\\biZ" : "𝒁",
444
- "\\bia" : "𝒂",
445
- "\\bib" : "𝒃",
446
- "\\bic" : "𝒄",
447
- "\\bid" : "𝒅",
448
- "\\bie" : "𝒆",
449
- "\\bif" : "𝒇",
450
- "\\big" : "𝒈",
451
- "\\bih" : "𝒉",
452
- "\\bii" : "𝒊",
453
- "\\bij" : "𝒋",
454
- "\\bik" : "𝒌",
455
- "\\bil" : "𝒍",
456
- "\\bim" : "𝒎",
457
- "\\bin" : "𝒏",
458
- "\\bio" : "𝒐",
459
- "\\bip" : "𝒑",
460
- "\\biq" : "𝒒",
461
- "\\bir" : "𝒓",
462
- "\\bis" : "𝒔",
463
- "\\bit" : "𝒕",
464
- "\\biu" : "𝒖",
465
- "\\biv" : "𝒗",
466
- "\\biw" : "𝒘",
467
- "\\bix" : "𝒙",
468
- "\\biy" : "𝒚",
469
- "\\biz" : "𝒛",
470
- "\\scrA" : "𝒜",
471
- "\\scrC" : "𝒞",
472
- "\\scrD" : "𝒟",
473
- "\\scrG" : "𝒢",
474
- "\\scrJ" : "𝒥",
475
- "\\scrK" : "𝒦",
476
- "\\scrN" : "𝒩",
477
- "\\scrO" : "𝒪",
478
- "\\scrP" : "𝒫",
479
- "\\scrQ" : "𝒬",
480
- "\\scrS" : "𝒮",
481
- "\\scrT" : "𝒯",
482
- "\\scrU" : "𝒰",
483
- "\\scrV" : "𝒱",
484
- "\\scrW" : "𝒲",
485
- "\\scrX" : "𝒳",
486
- "\\scrY" : "𝒴",
487
- "\\scrZ" : "𝒵",
488
- "\\scra" : "𝒶",
489
- "\\scrb" : "𝒷",
490
- "\\scrc" : "𝒸",
491
- "\\scrd" : "𝒹",
492
- "\\scrf" : "𝒻",
493
- "\\scrh" : "𝒽",
494
- "\\scri" : "𝒾",
495
- "\\scrj" : "𝒿",
496
- "\\scrk" : "𝓀",
497
- "\\scrm" : "𝓂",
498
- "\\scrn" : "𝓃",
499
- "\\scrp" : "𝓅",
500
- "\\scrq" : "𝓆",
501
- "\\scrr" : "𝓇",
502
- "\\scrs" : "𝓈",
503
- "\\scrt" : "𝓉",
504
- "\\scru" : "𝓊",
505
- "\\scrv" : "𝓋",
506
- "\\scrw" : "𝓌",
507
- "\\scrx" : "𝓍",
508
- "\\scry" : "𝓎",
509
- "\\scrz" : "𝓏",
510
- "\\bscrA" : "𝓐",
511
- "\\bscrB" : "𝓑",
512
- "\\bscrC" : "𝓒",
513
- "\\bscrD" : "𝓓",
514
- "\\bscrE" : "𝓔",
515
- "\\bscrF" : "𝓕",
516
- "\\bscrG" : "𝓖",
517
- "\\bscrH" : "𝓗",
518
- "\\bscrI" : "𝓘",
519
- "\\bscrJ" : "𝓙",
520
- "\\bscrK" : "𝓚",
521
- "\\bscrL" : "𝓛",
522
- "\\bscrM" : "𝓜",
523
- "\\bscrN" : "𝓝",
524
- "\\bscrO" : "𝓞",
525
- "\\bscrP" : "𝓟",
526
- "\\bscrQ" : "𝓠",
527
- "\\bscrR" : "𝓡",
528
- "\\bscrS" : "𝓢",
529
- "\\bscrT" : "𝓣",
530
- "\\bscrU" : "𝓤",
531
- "\\bscrV" : "𝓥",
532
- "\\bscrW" : "𝓦",
533
- "\\bscrX" : "𝓧",
534
- "\\bscrY" : "𝓨",
535
- "\\bscrZ" : "𝓩",
536
- "\\bscra" : "𝓪",
537
- "\\bscrb" : "𝓫",
538
- "\\bscrc" : "𝓬",
539
- "\\bscrd" : "𝓭",
540
- "\\bscre" : "𝓮",
541
- "\\bscrf" : "𝓯",
542
- "\\bscrg" : "𝓰",
543
- "\\bscrh" : "𝓱",
544
- "\\bscri" : "𝓲",
545
- "\\bscrj" : "𝓳",
546
- "\\bscrk" : "𝓴",
547
- "\\bscrl" : "𝓵",
548
- "\\bscrm" : "𝓶",
549
- "\\bscrn" : "𝓷",
550
- "\\bscro" : "𝓸",
551
- "\\bscrp" : "𝓹",
552
- "\\bscrq" : "𝓺",
553
- "\\bscrr" : "𝓻",
554
- "\\bscrs" : "𝓼",
555
- "\\bscrt" : "𝓽",
556
- "\\bscru" : "𝓾",
557
- "\\bscrv" : "𝓿",
558
- "\\bscrw" : "𝔀",
559
- "\\bscrx" : "𝔁",
560
- "\\bscry" : "𝔂",
561
- "\\bscrz" : "𝔃",
562
- "\\frakA" : "𝔄",
563
- "\\frakB" : "𝔅",
564
- "\\frakD" : "𝔇",
565
- "\\frakE" : "𝔈",
566
- "\\frakF" : "𝔉",
567
- "\\frakG" : "𝔊",
568
- "\\frakJ" : "𝔍",
569
- "\\frakK" : "𝔎",
570
- "\\frakL" : "𝔏",
571
- "\\frakM" : "𝔐",
572
- "\\frakN" : "𝔑",
573
- "\\frakO" : "𝔒",
574
- "\\frakP" : "𝔓",
575
- "\\frakQ" : "𝔔",
576
- "\\frakS" : "𝔖",
577
- "\\frakT" : "𝔗",
578
- "\\frakU" : "𝔘",
579
- "\\frakV" : "𝔙",
580
- "\\frakW" : "𝔚",
581
- "\\frakX" : "𝔛",
582
- "\\frakY" : "𝔜",
583
- "\\fraka" : "𝔞",
584
- "\\frakb" : "𝔟",
585
- "\\frakc" : "𝔠",
586
- "\\frakd" : "𝔡",
587
- "\\frake" : "𝔢",
588
- "\\frakf" : "𝔣",
589
- "\\frakg" : "𝔤",
590
- "\\frakh" : "𝔥",
591
- "\\fraki" : "𝔦",
592
- "\\frakj" : "𝔧",
593
- "\\frakk" : "𝔨",
594
- "\\frakl" : "𝔩",
595
- "\\frakm" : "𝔪",
596
- "\\frakn" : "𝔫",
597
- "\\frako" : "𝔬",
598
- "\\frakp" : "𝔭",
599
- "\\frakq" : "𝔮",
600
- "\\frakr" : "𝔯",
601
- "\\fraks" : "𝔰",
602
- "\\frakt" : "𝔱",
603
- "\\fraku" : "𝔲",
604
- "\\frakv" : "𝔳",
605
- "\\frakw" : "𝔴",
606
- "\\frakx" : "𝔵",
607
- "\\fraky" : "𝔶",
608
- "\\frakz" : "𝔷",
609
- "\\bbA" : "𝔸",
610
- "\\bbB" : "𝔹",
611
- "\\bbD" : "𝔻",
612
- "\\bbE" : "𝔼",
613
- "\\bbF" : "𝔽",
614
- "\\bbG" : "𝔾",
615
- "\\bbI" : "𝕀",
616
- "\\bbJ" : "𝕁",
617
- "\\bbK" : "𝕂",
618
- "\\bbL" : "𝕃",
619
- "\\bbM" : "𝕄",
620
- "\\bbO" : "𝕆",
621
- "\\bbS" : "𝕊",
622
- "\\bbT" : "𝕋",
623
- "\\bbU" : "𝕌",
624
- "\\bbV" : "𝕍",
625
- "\\bbW" : "𝕎",
626
- "\\bbX" : "𝕏",
627
- "\\bbY" : "𝕐",
628
- "\\bba" : "𝕒",
629
- "\\bbb" : "𝕓",
630
- "\\bbc" : "𝕔",
631
- "\\bbd" : "𝕕",
632
- "\\bbe" : "𝕖",
633
- "\\bbf" : "𝕗",
634
- "\\bbg" : "𝕘",
635
- "\\bbh" : "𝕙",
636
- "\\bbi" : "𝕚",
637
- "\\bbj" : "𝕛",
638
- "\\bbk" : "𝕜",
639
- "\\bbl" : "𝕝",
640
- "\\bbm" : "𝕞",
641
- "\\bbn" : "𝕟",
642
- "\\bbo" : "𝕠",
643
- "\\bbp" : "𝕡",
644
- "\\bbq" : "𝕢",
645
- "\\bbr" : "𝕣",
646
- "\\bbs" : "𝕤",
647
- "\\bbt" : "𝕥",
648
- "\\bbu" : "𝕦",
649
- "\\bbv" : "𝕧",
650
- "\\bbw" : "𝕨",
651
- "\\bbx" : "𝕩",
652
- "\\bby" : "𝕪",
653
- "\\bbz" : "𝕫",
654
- "\\bfrakA" : "𝕬",
655
- "\\bfrakB" : "𝕭",
656
- "\\bfrakC" : "𝕮",
657
- "\\bfrakD" : "𝕯",
658
- "\\bfrakE" : "𝕰",
659
- "\\bfrakF" : "𝕱",
660
- "\\bfrakG" : "𝕲",
661
- "\\bfrakH" : "𝕳",
662
- "\\bfrakI" : "𝕴",
663
- "\\bfrakJ" : "𝕵",
664
- "\\bfrakK" : "𝕶",
665
- "\\bfrakL" : "𝕷",
666
- "\\bfrakM" : "𝕸",
667
- "\\bfrakN" : "𝕹",
668
- "\\bfrakO" : "𝕺",
669
- "\\bfrakP" : "𝕻",
670
- "\\bfrakQ" : "𝕼",
671
- "\\bfrakR" : "𝕽",
672
- "\\bfrakS" : "𝕾",
673
- "\\bfrakT" : "𝕿",
674
- "\\bfrakU" : "𝖀",
675
- "\\bfrakV" : "𝖁",
676
- "\\bfrakW" : "𝖂",
677
- "\\bfrakX" : "𝖃",
678
- "\\bfrakY" : "𝖄",
679
- "\\bfrakZ" : "𝖅",
680
- "\\bfraka" : "𝖆",
681
- "\\bfrakb" : "𝖇",
682
- "\\bfrakc" : "𝖈",
683
- "\\bfrakd" : "𝖉",
684
- "\\bfrake" : "𝖊",
685
- "\\bfrakf" : "𝖋",
686
- "\\bfrakg" : "𝖌",
687
- "\\bfrakh" : "𝖍",
688
- "\\bfraki" : "𝖎",
689
- "\\bfrakj" : "𝖏",
690
- "\\bfrakk" : "𝖐",
691
- "\\bfrakl" : "𝖑",
692
- "\\bfrakm" : "𝖒",
693
- "\\bfrakn" : "𝖓",
694
- "\\bfrako" : "𝖔",
695
- "\\bfrakp" : "𝖕",
696
- "\\bfrakq" : "𝖖",
697
- "\\bfrakr" : "𝖗",
698
- "\\bfraks" : "𝖘",
699
- "\\bfrakt" : "𝖙",
700
- "\\bfraku" : "𝖚",
701
- "\\bfrakv" : "𝖛",
702
- "\\bfrakw" : "𝖜",
703
- "\\bfrakx" : "𝖝",
704
- "\\bfraky" : "𝖞",
705
- "\\bfrakz" : "𝖟",
706
- "\\sansA" : "𝖠",
707
- "\\sansB" : "𝖡",
708
- "\\sansC" : "𝖢",
709
- "\\sansD" : "𝖣",
710
- "\\sansE" : "𝖤",
711
- "\\sansF" : "𝖥",
712
- "\\sansG" : "𝖦",
713
- "\\sansH" : "𝖧",
714
- "\\sansI" : "𝖨",
715
- "\\sansJ" : "𝖩",
716
- "\\sansK" : "𝖪",
717
- "\\sansL" : "𝖫",
718
- "\\sansM" : "𝖬",
719
- "\\sansN" : "𝖭",
720
- "\\sansO" : "𝖮",
721
- "\\sansP" : "𝖯",
722
- "\\sansQ" : "𝖰",
723
- "\\sansR" : "𝖱",
724
- "\\sansS" : "𝖲",
725
- "\\sansT" : "𝖳",
726
- "\\sansU" : "𝖴",
727
- "\\sansV" : "𝖵",
728
- "\\sansW" : "𝖶",
729
- "\\sansX" : "𝖷",
730
- "\\sansY" : "𝖸",
731
- "\\sansZ" : "𝖹",
732
- "\\sansa" : "𝖺",
733
- "\\sansb" : "𝖻",
734
- "\\sansc" : "𝖼",
735
- "\\sansd" : "𝖽",
736
- "\\sanse" : "𝖾",
737
- "\\sansf" : "𝖿",
738
- "\\sansg" : "𝗀",
739
- "\\sansh" : "𝗁",
740
- "\\sansi" : "𝗂",
741
- "\\sansj" : "𝗃",
742
- "\\sansk" : "𝗄",
743
- "\\sansl" : "𝗅",
744
- "\\sansm" : "𝗆",
745
- "\\sansn" : "𝗇",
746
- "\\sanso" : "𝗈",
747
- "\\sansp" : "𝗉",
748
- "\\sansq" : "𝗊",
749
- "\\sansr" : "𝗋",
750
- "\\sanss" : "𝗌",
751
- "\\sanst" : "𝗍",
752
- "\\sansu" : "𝗎",
753
- "\\sansv" : "𝗏",
754
- "\\sansw" : "𝗐",
755
- "\\sansx" : "𝗑",
756
- "\\sansy" : "𝗒",
757
- "\\sansz" : "𝗓",
758
- "\\bsansA" : "𝗔",
759
- "\\bsansB" : "𝗕",
760
- "\\bsansC" : "𝗖",
761
- "\\bsansD" : "𝗗",
762
- "\\bsansE" : "𝗘",
763
- "\\bsansF" : "𝗙",
764
- "\\bsansG" : "𝗚",
765
- "\\bsansH" : "𝗛",
766
- "\\bsansI" : "𝗜",
767
- "\\bsansJ" : "𝗝",
768
- "\\bsansK" : "𝗞",
769
- "\\bsansL" : "𝗟",
770
- "\\bsansM" : "𝗠",
771
- "\\bsansN" : "𝗡",
772
- "\\bsansO" : "𝗢",
773
- "\\bsansP" : "𝗣",
774
- "\\bsansQ" : "𝗤",
775
- "\\bsansR" : "𝗥",
776
- "\\bsansS" : "𝗦",
777
- "\\bsansT" : "𝗧",
778
- "\\bsansU" : "𝗨",
779
- "\\bsansV" : "𝗩",
780
- "\\bsansW" : "𝗪",
781
- "\\bsansX" : "𝗫",
782
- "\\bsansY" : "𝗬",
783
- "\\bsansZ" : "𝗭",
784
- "\\bsansa" : "𝗮",
785
- "\\bsansb" : "𝗯",
786
- "\\bsansc" : "𝗰",
787
- "\\bsansd" : "𝗱",
788
- "\\bsanse" : "𝗲",
789
- "\\bsansf" : "𝗳",
790
- "\\bsansg" : "𝗴",
791
- "\\bsansh" : "𝗵",
792
- "\\bsansi" : "𝗶",
793
- "\\bsansj" : "𝗷",
794
- "\\bsansk" : "𝗸",
795
- "\\bsansl" : "𝗹",
796
- "\\bsansm" : "𝗺",
797
- "\\bsansn" : "𝗻",
798
- "\\bsanso" : "𝗼",
799
- "\\bsansp" : "𝗽",
800
- "\\bsansq" : "𝗾",
801
- "\\bsansr" : "𝗿",
802
- "\\bsanss" : "𝘀",
803
- "\\bsanst" : "𝘁",
804
- "\\bsansu" : "𝘂",
805
- "\\bsansv" : "𝘃",
806
- "\\bsansw" : "𝘄",
807
- "\\bsansx" : "𝘅",
808
- "\\bsansy" : "𝘆",
809
- "\\bsansz" : "𝘇",
810
- "\\isansA" : "𝘈",
811
- "\\isansB" : "𝘉",
812
- "\\isansC" : "𝘊",
813
- "\\isansD" : "𝘋",
814
- "\\isansE" : "𝘌",
815
- "\\isansF" : "𝘍",
816
- "\\isansG" : "𝘎",
817
- "\\isansH" : "𝘏",
818
- "\\isansI" : "𝘐",
819
- "\\isansJ" : "𝘑",
820
- "\\isansK" : "𝘒",
821
- "\\isansL" : "𝘓",
822
- "\\isansM" : "𝘔",
823
- "\\isansN" : "𝘕",
824
- "\\isansO" : "𝘖",
825
- "\\isansP" : "𝘗",
826
- "\\isansQ" : "𝘘",
827
- "\\isansR" : "𝘙",
828
- "\\isansS" : "𝘚",
829
- "\\isansT" : "𝘛",
830
- "\\isansU" : "𝘜",
831
- "\\isansV" : "𝘝",
832
- "\\isansW" : "𝘞",
833
- "\\isansX" : "𝘟",
834
- "\\isansY" : "𝘠",
835
- "\\isansZ" : "𝘡",
836
- "\\isansa" : "𝘢",
837
- "\\isansb" : "𝘣",
838
- "\\isansc" : "𝘤",
839
- "\\isansd" : "𝘥",
840
- "\\isanse" : "𝘦",
841
- "\\isansf" : "𝘧",
842
- "\\isansg" : "𝘨",
843
- "\\isansh" : "𝘩",
844
- "\\isansi" : "𝘪",
845
- "\\isansj" : "𝘫",
846
- "\\isansk" : "𝘬",
847
- "\\isansl" : "𝘭",
848
- "\\isansm" : "𝘮",
849
- "\\isansn" : "𝘯",
850
- "\\isanso" : "𝘰",
851
- "\\isansp" : "𝘱",
852
- "\\isansq" : "𝘲",
853
- "\\isansr" : "𝘳",
854
- "\\isanss" : "𝘴",
855
- "\\isanst" : "𝘵",
856
- "\\isansu" : "𝘶",
857
- "\\isansv" : "𝘷",
858
- "\\isansw" : "𝘸",
859
- "\\isansx" : "𝘹",
860
- "\\isansy" : "𝘺",
861
- "\\isansz" : "𝘻",
862
- "\\bisansA" : "𝘼",
863
- "\\bisansB" : "𝘽",
864
- "\\bisansC" : "𝘾",
865
- "\\bisansD" : "𝘿",
866
- "\\bisansE" : "𝙀",
867
- "\\bisansF" : "𝙁",
868
- "\\bisansG" : "𝙂",
869
- "\\bisansH" : "𝙃",
870
- "\\bisansI" : "𝙄",
871
- "\\bisansJ" : "𝙅",
872
- "\\bisansK" : "𝙆",
873
- "\\bisansL" : "𝙇",
874
- "\\bisansM" : "𝙈",
875
- "\\bisansN" : "𝙉",
876
- "\\bisansO" : "𝙊",
877
- "\\bisansP" : "𝙋",
878
- "\\bisansQ" : "𝙌",
879
- "\\bisansR" : "𝙍",
880
- "\\bisansS" : "𝙎",
881
- "\\bisansT" : "𝙏",
882
- "\\bisansU" : "𝙐",
883
- "\\bisansV" : "𝙑",
884
- "\\bisansW" : "𝙒",
885
- "\\bisansX" : "𝙓",
886
- "\\bisansY" : "𝙔",
887
- "\\bisansZ" : "𝙕",
888
- "\\bisansa" : "𝙖",
889
- "\\bisansb" : "𝙗",
890
- "\\bisansc" : "𝙘",
891
- "\\bisansd" : "𝙙",
892
- "\\bisanse" : "𝙚",
893
- "\\bisansf" : "𝙛",
894
- "\\bisansg" : "𝙜",
895
- "\\bisansh" : "𝙝",
896
- "\\bisansi" : "𝙞",
897
- "\\bisansj" : "𝙟",
898
- "\\bisansk" : "𝙠",
899
- "\\bisansl" : "𝙡",
900
- "\\bisansm" : "𝙢",
901
- "\\bisansn" : "𝙣",
902
- "\\bisanso" : "𝙤",
903
- "\\bisansp" : "𝙥",
904
- "\\bisansq" : "𝙦",
905
- "\\bisansr" : "𝙧",
906
- "\\bisanss" : "𝙨",
907
- "\\bisanst" : "𝙩",
908
- "\\bisansu" : "𝙪",
909
- "\\bisansv" : "𝙫",
910
- "\\bisansw" : "𝙬",
911
- "\\bisansx" : "𝙭",
912
- "\\bisansy" : "𝙮",
913
- "\\bisansz" : "𝙯",
914
- "\\ttA" : "𝙰",
915
- "\\ttB" : "𝙱",
916
- "\\ttC" : "𝙲",
917
- "\\ttD" : "𝙳",
918
- "\\ttE" : "𝙴",
919
- "\\ttF" : "𝙵",
920
- "\\ttG" : "𝙶",
921
- "\\ttH" : "𝙷",
922
- "\\ttI" : "𝙸",
923
- "\\ttJ" : "𝙹",
924
- "\\ttK" : "𝙺",
925
- "\\ttL" : "𝙻",
926
- "\\ttM" : "𝙼",
927
- "\\ttN" : "𝙽",
928
- "\\ttO" : "𝙾",
929
- "\\ttP" : "𝙿",
930
- "\\ttQ" : "𝚀",
931
- "\\ttR" : "𝚁",
932
- "\\ttS" : "𝚂",
933
- "\\ttT" : "𝚃",
934
- "\\ttU" : "𝚄",
935
- "\\ttV" : "𝚅",
936
- "\\ttW" : "𝚆",
937
- "\\ttX" : "𝚇",
938
- "\\ttY" : "𝚈",
939
- "\\ttZ" : "𝚉",
940
- "\\tta" : "𝚊",
941
- "\\ttb" : "𝚋",
942
- "\\ttc" : "𝚌",
943
- "\\ttd" : "𝚍",
944
- "\\tte" : "𝚎",
945
- "\\ttf" : "𝚏",
946
- "\\ttg" : "𝚐",
947
- "\\tth" : "𝚑",
948
- "\\tti" : "𝚒",
949
- "\\ttj" : "𝚓",
950
- "\\ttk" : "𝚔",
951
- "\\ttl" : "𝚕",
952
- "\\ttm" : "𝚖",
953
- "\\ttn" : "𝚗",
954
- "\\tto" : "𝚘",
955
- "\\ttp" : "𝚙",
956
- "\\ttq" : "𝚚",
957
- "\\ttr" : "𝚛",
958
- "\\tts" : "𝚜",
959
- "\\ttt" : "𝚝",
960
- "\\ttu" : "𝚞",
961
- "\\ttv" : "𝚟",
962
- "\\ttw" : "𝚠",
963
- "\\ttx" : "𝚡",
964
- "\\tty" : "𝚢",
965
- "\\ttz" : "𝚣",
966
- "\\bfAlpha" : "𝚨",
967
- "\\bfBeta" : "𝚩",
968
- "\\bfGamma" : "𝚪",
969
- "\\bfDelta" : "𝚫",
970
- "\\bfEpsilon" : "𝚬",
971
- "\\bfZeta" : "𝚭",
972
- "\\bfEta" : "𝚮",
973
- "\\bfTheta" : "𝚯",
974
- "\\bfIota" : "𝚰",
975
- "\\bfKappa" : "𝚱",
976
- "\\bfLambda" : "𝚲",
977
- "\\bfMu" : "𝚳",
978
- "\\bfNu" : "𝚴",
979
- "\\bfXi" : "𝚵",
980
- "\\bfOmicron" : "𝚶",
981
- "\\bfPi" : "𝚷",
982
- "\\bfRho" : "𝚸",
983
- "\\bfvarTheta" : "𝚹",
984
- "\\bfSigma" : "𝚺",
985
- "\\bfTau" : "𝚻",
986
- "\\bfUpsilon" : "𝚼",
987
- "\\bfPhi" : "𝚽",
988
- "\\bfChi" : "𝚾",
989
- "\\bfPsi" : "𝚿",
990
- "\\bfOmega" : "𝛀",
991
- "\\bfalpha" : "𝛂",
992
- "\\bfbeta" : "𝛃",
993
- "\\bfgamma" : "𝛄",
994
- "\\bfdelta" : "𝛅",
995
- "\\bfepsilon" : "𝛆",
996
- "\\bfzeta" : "𝛇",
997
- "\\bfeta" : "𝛈",
998
- "\\bftheta" : "𝛉",
999
- "\\bfiota" : "𝛊",
1000
- "\\bfkappa" : "𝛋",
1001
- "\\bflambda" : "𝛌",
1002
- "\\bfmu" : "𝛍",
1003
- "\\bfnu" : "𝛎",
1004
- "\\bfxi" : "𝛏",
1005
- "\\bfomicron" : "𝛐",
1006
- "\\bfpi" : "𝛑",
1007
- "\\bfrho" : "𝛒",
1008
- "\\bfvarsigma" : "𝛓",
1009
- "\\bfsigma" : "𝛔",
1010
- "\\bftau" : "𝛕",
1011
- "\\bfupsilon" : "𝛖",
1012
- "\\bfvarphi" : "𝛗",
1013
- "\\bfchi" : "𝛘",
1014
- "\\bfpsi" : "𝛙",
1015
- "\\bfomega" : "𝛚",
1016
- "\\bfvarepsilon" : "𝛜",
1017
- "\\bfvartheta" : "𝛝",
1018
- "\\bfvarkappa" : "𝛞",
1019
- "\\bfphi" : "𝛟",
1020
- "\\bfvarrho" : "𝛠",
1021
- "\\bfvarpi" : "𝛡",
1022
- "\\itAlpha" : "𝛢",
1023
- "\\itBeta" : "𝛣",
1024
- "\\itGamma" : "𝛤",
1025
- "\\itDelta" : "𝛥",
1026
- "\\itEpsilon" : "𝛦",
1027
- "\\itZeta" : "𝛧",
1028
- "\\itEta" : "𝛨",
1029
- "\\itTheta" : "𝛩",
1030
- "\\itIota" : "𝛪",
1031
- "\\itKappa" : "𝛫",
1032
- "\\itLambda" : "𝛬",
1033
- "\\itMu" : "𝛭",
1034
- "\\itNu" : "𝛮",
1035
- "\\itXi" : "𝛯",
1036
- "\\itOmicron" : "𝛰",
1037
- "\\itPi" : "𝛱",
1038
- "\\itRho" : "𝛲",
1039
- "\\itvarTheta" : "𝛳",
1040
- "\\itSigma" : "𝛴",
1041
- "\\itTau" : "𝛵",
1042
- "\\itUpsilon" : "𝛶",
1043
- "\\itPhi" : "𝛷",
1044
- "\\itChi" : "𝛸",
1045
- "\\itPsi" : "𝛹",
1046
- "\\itOmega" : "𝛺",
1047
- "\\italpha" : "𝛼",
1048
- "\\itbeta" : "𝛽",
1049
- "\\itgamma" : "𝛾",
1050
- "\\itdelta" : "𝛿",
1051
- "\\itepsilon" : "𝜀",
1052
- "\\itzeta" : "𝜁",
1053
- "\\iteta" : "𝜂",
1054
- "\\ittheta" : "𝜃",
1055
- "\\itiota" : "𝜄",
1056
- "\\itkappa" : "𝜅",
1057
- "\\itlambda" : "𝜆",
1058
- "\\itmu" : "𝜇",
1059
- "\\itnu" : "𝜈",
1060
- "\\itxi" : "𝜉",
1061
- "\\itomicron" : "𝜊",
1062
- "\\itpi" : "𝜋",
1063
- "\\itrho" : "𝜌",
1064
- "\\itvarsigma" : "𝜍",
1065
- "\\itsigma" : "𝜎",
1066
- "\\ittau" : "𝜏",
1067
- "\\itupsilon" : "𝜐",
1068
- "\\itphi" : "𝜑",
1069
- "\\itchi" : "𝜒",
1070
- "\\itpsi" : "𝜓",
1071
- "\\itomega" : "𝜔",
1072
- "\\itvarepsilon" : "𝜖",
1073
- "\\itvartheta" : "𝜗",
1074
- "\\itvarkappa" : "𝜘",
1075
- "\\itvarphi" : "𝜙",
1076
- "\\itvarrho" : "𝜚",
1077
- "\\itvarpi" : "𝜛",
1078
- "\\biAlpha" : "𝜜",
1079
- "\\biBeta" : "𝜝",
1080
- "\\biGamma" : "𝜞",
1081
- "\\biDelta" : "𝜟",
1082
- "\\biEpsilon" : "𝜠",
1083
- "\\biZeta" : "𝜡",
1084
- "\\biEta" : "𝜢",
1085
- "\\biTheta" : "𝜣",
1086
- "\\biIota" : "𝜤",
1087
- "\\biKappa" : "𝜥",
1088
- "\\biLambda" : "𝜦",
1089
- "\\biMu" : "𝜧",
1090
- "\\biNu" : "𝜨",
1091
- "\\biXi" : "𝜩",
1092
- "\\biOmicron" : "𝜪",
1093
- "\\biPi" : "𝜫",
1094
- "\\biRho" : "𝜬",
1095
- "\\bivarTheta" : "𝜭",
1096
- "\\biSigma" : "𝜮",
1097
- "\\biTau" : "𝜯",
1098
- "\\biUpsilon" : "𝜰",
1099
- "\\biPhi" : "𝜱",
1100
- "\\biChi" : "𝜲",
1101
- "\\biPsi" : "𝜳",
1102
- "\\biOmega" : "𝜴",
1103
- "\\bialpha" : "𝜶",
1104
- "\\bibeta" : "𝜷",
1105
- "\\bigamma" : "𝜸",
1106
- "\\bidelta" : "𝜹",
1107
- "\\biepsilon" : "𝜺",
1108
- "\\bizeta" : "𝜻",
1109
- "\\bieta" : "𝜼",
1110
- "\\bitheta" : "𝜽",
1111
- "\\biiota" : "𝜾",
1112
- "\\bikappa" : "𝜿",
1113
- "\\bilambda" : "𝝀",
1114
- "\\bimu" : "𝝁",
1115
- "\\binu" : "𝝂",
1116
- "\\bixi" : "𝝃",
1117
- "\\biomicron" : "𝝄",
1118
- "\\bipi" : "𝝅",
1119
- "\\birho" : "𝝆",
1120
- "\\bivarsigma" : "𝝇",
1121
- "\\bisigma" : "𝝈",
1122
- "\\bitau" : "𝝉",
1123
- "\\biupsilon" : "𝝊",
1124
- "\\biphi" : "𝝋",
1125
- "\\bichi" : "𝝌",
1126
- "\\bipsi" : "𝝍",
1127
- "\\biomega" : "𝝎",
1128
- "\\bivarepsilon" : "𝝐",
1129
- "\\bivartheta" : "𝝑",
1130
- "\\bivarkappa" : "𝝒",
1131
- "\\bivarphi" : "𝝓",
1132
- "\\bivarrho" : "𝝔",
1133
- "\\bivarpi" : "𝝕",
1134
- "\\bsansAlpha" : "𝝖",
1135
- "\\bsansBeta" : "𝝗",
1136
- "\\bsansGamma" : "𝝘",
1137
- "\\bsansDelta" : "𝝙",
1138
- "\\bsansEpsilon" : "𝝚",
1139
- "\\bsansZeta" : "𝝛",
1140
- "\\bsansEta" : "𝝜",
1141
- "\\bsansTheta" : "𝝝",
1142
- "\\bsansIota" : "𝝞",
1143
- "\\bsansKappa" : "𝝟",
1144
- "\\bsansLambda" : "𝝠",
1145
- "\\bsansMu" : "𝝡",
1146
- "\\bsansNu" : "𝝢",
1147
- "\\bsansXi" : "𝝣",
1148
- "\\bsansOmicron" : "𝝤",
1149
- "\\bsansPi" : "𝝥",
1150
- "\\bsansRho" : "𝝦",
1151
- "\\bsansvarTheta" : "𝝧",
1152
- "\\bsansSigma" : "𝝨",
1153
- "\\bsansTau" : "𝝩",
1154
- "\\bsansUpsilon" : "𝝪",
1155
- "\\bsansPhi" : "𝝫",
1156
- "\\bsansChi" : "𝝬",
1157
- "\\bsansPsi" : "𝝭",
1158
- "\\bsansOmega" : "𝝮",
1159
- "\\bsansalpha" : "𝝰",
1160
- "\\bsansbeta" : "𝝱",
1161
- "\\bsansgamma" : "𝝲",
1162
- "\\bsansdelta" : "𝝳",
1163
- "\\bsansepsilon" : "𝝴",
1164
- "\\bsanszeta" : "𝝵",
1165
- "\\bsanseta" : "𝝶",
1166
- "\\bsanstheta" : "𝝷",
1167
- "\\bsansiota" : "𝝸",
1168
- "\\bsanskappa" : "𝝹",
1169
- "\\bsanslambda" : "𝝺",
1170
- "\\bsansmu" : "𝝻",
1171
- "\\bsansnu" : "𝝼",
1172
- "\\bsansxi" : "𝝽",
1173
- "\\bsansomicron" : "𝝾",
1174
- "\\bsanspi" : "𝝿",
1175
- "\\bsansrho" : "𝞀",
1176
- "\\bsansvarsigma" : "𝞁",
1177
- "\\bsanssigma" : "𝞂",
1178
- "\\bsanstau" : "𝞃",
1179
- "\\bsansupsilon" : "𝞄",
1180
- "\\bsansphi" : "𝞅",
1181
- "\\bsanschi" : "𝞆",
1182
- "\\bsanspsi" : "𝞇",
1183
- "\\bsansomega" : "𝞈",
1184
- "\\bsansvarepsilon" : "𝞊",
1185
- "\\bsansvartheta" : "𝞋",
1186
- "\\bsansvarkappa" : "𝞌",
1187
- "\\bsansvarphi" : "𝞍",
1188
- "\\bsansvarrho" : "𝞎",
1189
- "\\bsansvarpi" : "𝞏",
1190
- "\\bisansAlpha" : "𝞐",
1191
- "\\bisansBeta" : "𝞑",
1192
- "\\bisansGamma" : "𝞒",
1193
- "\\bisansDelta" : "𝞓",
1194
- "\\bisansEpsilon" : "𝞔",
1195
- "\\bisansZeta" : "𝞕",
1196
- "\\bisansEta" : "𝞖",
1197
- "\\bisansTheta" : "𝞗",
1198
- "\\bisansIota" : "𝞘",
1199
- "\\bisansKappa" : "𝞙",
1200
- "\\bisansLambda" : "𝞚",
1201
- "\\bisansMu" : "𝞛",
1202
- "\\bisansNu" : "𝞜",
1203
- "\\bisansXi" : "𝞝",
1204
- "\\bisansOmicron" : "𝞞",
1205
- "\\bisansPi" : "𝞟",
1206
- "\\bisansRho" : "𝞠",
1207
- "\\bisansvarTheta" : "𝞡",
1208
- "\\bisansSigma" : "𝞢",
1209
- "\\bisansTau" : "𝞣",
1210
- "\\bisansUpsilon" : "𝞤",
1211
- "\\bisansPhi" : "𝞥",
1212
- "\\bisansChi" : "𝞦",
1213
- "\\bisansPsi" : "𝞧",
1214
- "\\bisansOmega" : "𝞨",
1215
- "\\bisansalpha" : "𝞪",
1216
- "\\bisansbeta" : "𝞫",
1217
- "\\bisansgamma" : "𝞬",
1218
- "\\bisansdelta" : "𝞭",
1219
- "\\bisansepsilon" : "𝞮",
1220
- "\\bisanszeta" : "𝞯",
1221
- "\\bisanseta" : "𝞰",
1222
- "\\bisanstheta" : "𝞱",
1223
- "\\bisansiota" : "𝞲",
1224
- "\\bisanskappa" : "𝞳",
1225
- "\\bisanslambda" : "𝞴",
1226
- "\\bisansmu" : "𝞵",
1227
- "\\bisansnu" : "𝞶",
1228
- "\\bisansxi" : "𝞷",
1229
- "\\bisansomicron" : "𝞸",
1230
- "\\bisanspi" : "𝞹",
1231
- "\\bisansrho" : "𝞺",
1232
- "\\bisansvarsigma" : "𝞻",
1233
- "\\bisanssigma" : "𝞼",
1234
- "\\bisanstau" : "𝞽",
1235
- "\\bisansupsilon" : "𝞾",
1236
- "\\bisansphi" : "𝞿",
1237
- "\\bisanschi" : "𝟀",
1238
- "\\bisanspsi" : "𝟁",
1239
- "\\bisansomega" : "𝟂",
1240
- "\\bisansvarepsilon" : "𝟄",
1241
- "\\bisansvartheta" : "𝟅",
1242
- "\\bisansvarkappa" : "𝟆",
1243
- "\\bisansvarphi" : "𝟇",
1244
- "\\bisansvarrho" : "𝟈",
1245
- "\\bisansvarpi" : "𝟉",
1246
- "\\bfzero" : "𝟎",
1247
- "\\bfone" : "𝟏",
1248
- "\\bftwo" : "𝟐",
1249
- "\\bfthree" : "𝟑",
1250
- "\\bffour" : "𝟒",
1251
- "\\bffive" : "𝟓",
1252
- "\\bfsix" : "𝟔",
1253
- "\\bfseven" : "𝟕",
1254
- "\\bfeight" : "𝟖",
1255
- "\\bfnine" : "𝟗",
1256
- "\\bbzero" : "𝟘",
1257
- "\\bbone" : "𝟙",
1258
- "\\bbtwo" : "𝟚",
1259
- "\\bbthree" : "𝟛",
1260
- "\\bbfour" : "𝟜",
1261
- "\\bbfive" : "𝟝",
1262
- "\\bbsix" : "𝟞",
1263
- "\\bbseven" : "𝟟",
1264
- "\\bbeight" : "𝟠",
1265
- "\\bbnine" : "𝟡",
1266
- "\\sanszero" : "𝟢",
1267
- "\\sansone" : "𝟣",
1268
- "\\sanstwo" : "𝟤",
1269
- "\\sansthree" : "𝟥",
1270
- "\\sansfour" : "𝟦",
1271
- "\\sansfive" : "𝟧",
1272
- "\\sanssix" : "𝟨",
1273
- "\\sansseven" : "𝟩",
1274
- "\\sanseight" : "𝟪",
1275
- "\\sansnine" : "𝟫",
1276
- "\\bsanszero" : "𝟬",
1277
- "\\bsansone" : "𝟭",
1278
- "\\bsanstwo" : "𝟮",
1279
- "\\bsansthree" : "𝟯",
1280
- "\\bsansfour" : "𝟰",
1281
- "\\bsansfive" : "𝟱",
1282
- "\\bsanssix" : "𝟲",
1283
- "\\bsansseven" : "𝟳",
1284
- "\\bsanseight" : "𝟴",
1285
- "\\bsansnine" : "𝟵",
1286
- "\\ttzero" : "𝟶",
1287
- "\\ttone" : "𝟷",
1288
- "\\tttwo" : "𝟸",
1289
- "\\ttthree" : "𝟹",
1290
- "\\ttfour" : "𝟺",
1291
- "\\ttfive" : "𝟻",
1292
- "\\ttsix" : "𝟼",
1293
- "\\ttseven" : "𝟽",
1294
- "\\tteight" : "𝟾",
1295
- "\\ttnine" : "𝟿",
1296
- "\\underbar" : "̲",
1297
- "\\underleftrightarrow" : "͍",
1298
- }
1299
-
1300
-
1301
- reverse_latex_symbol = { v:k for k,v in latex_symbols.items()}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/logger.py DELETED
@@ -1,231 +0,0 @@
1
- """Logger class for IPython's logging facilities.
2
- """
3
-
4
- #*****************************************************************************
5
- # Copyright (C) 2001 Janko Hauser <[email protected]> and
6
- # Copyright (C) 2001-2006 Fernando Perez <[email protected]>
7
- #
8
- # Distributed under the terms of the BSD License. The full license is in
9
- # the file COPYING, distributed as part of this software.
10
- #*****************************************************************************
11
-
12
- #****************************************************************************
13
- # Modules and globals
14
-
15
- # Python standard modules
16
- import glob
17
- import io
18
- import logging
19
- import os
20
- import time
21
-
22
-
23
- # prevent jedi/parso's debug messages pipe into interactiveshell
24
- logging.getLogger("parso").setLevel(logging.WARNING)
25
-
26
- #****************************************************************************
27
- # FIXME: This class isn't a mixin anymore, but it still needs attributes from
28
- # ipython and does input cache management. Finish cleanup later...
29
-
30
- class Logger(object):
31
- """A Logfile class with different policies for file creation"""
32
-
33
- def __init__(self, home_dir, logfname='Logger.log', loghead=u'',
34
- logmode='over'):
35
-
36
- # this is the full ipython instance, we need some attributes from it
37
- # which won't exist until later. What a mess, clean up later...
38
- self.home_dir = home_dir
39
-
40
- self.logfname = logfname
41
- self.loghead = loghead
42
- self.logmode = logmode
43
- self.logfile = None
44
-
45
- # Whether to log raw or processed input
46
- self.log_raw_input = False
47
-
48
- # whether to also log output
49
- self.log_output = False
50
-
51
- # whether to put timestamps before each log entry
52
- self.timestamp = False
53
-
54
- # activity control flags
55
- self.log_active = False
56
-
57
- # logmode is a validated property
58
- def _set_mode(self,mode):
59
- if mode not in ['append','backup','global','over','rotate']:
60
- raise ValueError('invalid log mode %s given' % mode)
61
- self._logmode = mode
62
-
63
- def _get_mode(self):
64
- return self._logmode
65
-
66
- logmode = property(_get_mode,_set_mode)
67
-
68
- def logstart(self, logfname=None, loghead=None, logmode=None,
69
- log_output=False, timestamp=False, log_raw_input=False):
70
- """Generate a new log-file with a default header.
71
-
72
- Raises RuntimeError if the log has already been started"""
73
-
74
- if self.logfile is not None:
75
- raise RuntimeError('Log file is already active: %s' %
76
- self.logfname)
77
-
78
- # The parameters can override constructor defaults
79
- if logfname is not None: self.logfname = logfname
80
- if loghead is not None: self.loghead = loghead
81
- if logmode is not None: self.logmode = logmode
82
-
83
- # Parameters not part of the constructor
84
- self.timestamp = timestamp
85
- self.log_output = log_output
86
- self.log_raw_input = log_raw_input
87
-
88
- # init depending on the log mode requested
89
- isfile = os.path.isfile
90
- logmode = self.logmode
91
-
92
- if logmode == 'append':
93
- self.logfile = io.open(self.logfname, 'a', encoding='utf-8')
94
-
95
- elif logmode == 'backup':
96
- if isfile(self.logfname):
97
- backup_logname = self.logfname+'~'
98
- # Manually remove any old backup, since os.rename may fail
99
- # under Windows.
100
- if isfile(backup_logname):
101
- os.remove(backup_logname)
102
- os.rename(self.logfname,backup_logname)
103
- self.logfile = io.open(self.logfname, 'w', encoding='utf-8')
104
-
105
- elif logmode == 'global':
106
- self.logfname = os.path.join(self.home_dir,self.logfname)
107
- self.logfile = io.open(self.logfname, 'a', encoding='utf-8')
108
-
109
- elif logmode == 'over':
110
- if isfile(self.logfname):
111
- os.remove(self.logfname)
112
- self.logfile = io.open(self.logfname,'w', encoding='utf-8')
113
-
114
- elif logmode == 'rotate':
115
- if isfile(self.logfname):
116
- if isfile(self.logfname+'.001~'):
117
- old = glob.glob(self.logfname+'.*~')
118
- old.sort()
119
- old.reverse()
120
- for f in old:
121
- root, ext = os.path.splitext(f)
122
- num = int(ext[1:-1])+1
123
- os.rename(f, root+'.'+repr(num).zfill(3)+'~')
124
- os.rename(self.logfname, self.logfname+'.001~')
125
- self.logfile = io.open(self.logfname, 'w', encoding='utf-8')
126
-
127
- if logmode != 'append':
128
- self.logfile.write(self.loghead)
129
-
130
- self.logfile.flush()
131
- self.log_active = True
132
-
133
- def switch_log(self,val):
134
- """Switch logging on/off. val should be ONLY a boolean."""
135
-
136
- if val not in [False,True,0,1]:
137
- raise ValueError('Call switch_log ONLY with a boolean argument, '
138
- 'not with: %s' % val)
139
-
140
- label = {0:'OFF',1:'ON',False:'OFF',True:'ON'}
141
-
142
- if self.logfile is None:
143
- print("""
144
- Logging hasn't been started yet (use logstart for that).
145
-
146
- %logon/%logoff are for temporarily starting and stopping logging for a logfile
147
- which already exists. But you must first start the logging process with
148
- %logstart (optionally giving a logfile name).""")
149
-
150
- else:
151
- if self.log_active == val:
152
- print('Logging is already',label[val])
153
- else:
154
- print('Switching logging',label[val])
155
- self.log_active = not self.log_active
156
- self.log_active_out = self.log_active
157
-
158
- def logstate(self):
159
- """Print a status message about the logger."""
160
- if self.logfile is None:
161
- print('Logging has not been activated.')
162
- else:
163
- state = self.log_active and 'active' or 'temporarily suspended'
164
- print('Filename :', self.logfname)
165
- print('Mode :', self.logmode)
166
- print('Output logging :', self.log_output)
167
- print('Raw input log :', self.log_raw_input)
168
- print('Timestamping :', self.timestamp)
169
- print('State :', state)
170
-
171
- def log(self, line_mod, line_ori):
172
- """Write the sources to a log.
173
-
174
- Inputs:
175
-
176
- - line_mod: possibly modified input, such as the transformations made
177
- by input prefilters or input handlers of various kinds. This should
178
- always be valid Python.
179
-
180
- - line_ori: unmodified input line from the user. This is not
181
- necessarily valid Python.
182
- """
183
-
184
- # Write the log line, but decide which one according to the
185
- # log_raw_input flag, set when the log is started.
186
- if self.log_raw_input:
187
- self.log_write(line_ori)
188
- else:
189
- self.log_write(line_mod)
190
-
191
- def log_write(self, data, kind='input'):
192
- """Write data to the log file, if active"""
193
-
194
- # print('data: %r' % data) # dbg
195
- if self.log_active and data:
196
- write = self.logfile.write
197
- if kind=='input':
198
- if self.timestamp:
199
- write(time.strftime('# %a, %d %b %Y %H:%M:%S\n', time.localtime()))
200
- write(data)
201
- elif kind=='output' and self.log_output:
202
- odata = u'\n'.join([u'#[Out]# %s' % s
203
- for s in data.splitlines()])
204
- write(u'%s\n' % odata)
205
- try:
206
- self.logfile.flush()
207
- except OSError:
208
- print("Failed to flush the log file.")
209
- print(
210
- f"Please check that {self.logfname} exists and have the right permissions."
211
- )
212
- print(
213
- "Also consider turning off the log with `%logstop` to avoid this warning."
214
- )
215
-
216
- def logstop(self):
217
- """Fully stop logging and close log file.
218
-
219
- In order to start logging again, a new logstart() call needs to be
220
- made, possibly (though not necessarily) with a new filename, mode and
221
- other options."""
222
-
223
- if self.logfile is not None:
224
- self.logfile.close()
225
- self.logfile = None
226
- else:
227
- print("Logging hadn't been started.")
228
- self.log_active = False
229
-
230
- # For backwards compatibility, in case anyone was using this.
231
- close_log = logstop
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/macro.py DELETED
@@ -1,53 +0,0 @@
1
- """Support for interactive macros in IPython"""
2
-
3
- #*****************************************************************************
4
- # Copyright (C) 2001-2005 Fernando Perez <[email protected]>
5
- #
6
- # Distributed under the terms of the BSD License. The full license is in
7
- # the file COPYING, distributed as part of this software.
8
- #*****************************************************************************
9
-
10
- import re
11
-
12
- from IPython.utils.encoding import DEFAULT_ENCODING
13
-
14
- coding_declaration = re.compile(r"#\s*coding[:=]\s*([-\w.]+)")
15
-
16
- class Macro(object):
17
- """Simple class to store the value of macros as strings.
18
-
19
- Macro is just a callable that executes a string of IPython
20
- input when called.
21
- """
22
-
23
- def __init__(self,code):
24
- """store the macro value, as a single string which can be executed"""
25
- lines = []
26
- enc = None
27
- for line in code.splitlines():
28
- coding_match = coding_declaration.match(line)
29
- if coding_match:
30
- enc = coding_match.group(1)
31
- else:
32
- lines.append(line)
33
- code = "\n".join(lines)
34
- if isinstance(code, bytes):
35
- code = code.decode(enc or DEFAULT_ENCODING)
36
- self.value = code + '\n'
37
-
38
- def __str__(self):
39
- return self.value
40
-
41
- def __repr__(self):
42
- return 'IPython.macro.Macro(%s)' % repr(self.value)
43
-
44
- def __getstate__(self):
45
- """ needed for safe pickling via %store """
46
- return {'value': self.value}
47
-
48
- def __add__(self, other):
49
- if isinstance(other, Macro):
50
- return Macro(self.value + other.value)
51
- elif isinstance(other, str):
52
- return Macro(self.value + other)
53
- raise TypeError
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/magic.py DELETED
@@ -1,759 +0,0 @@
1
- # encoding: utf-8
2
- """Magic functions for InteractiveShell.
3
- """
4
-
5
- #-----------------------------------------------------------------------------
6
- # Copyright (C) 2001 Janko Hauser <[email protected]> and
7
- # Copyright (C) 2001 Fernando Perez <[email protected]>
8
- # Copyright (C) 2008 The IPython Development Team
9
-
10
- # Distributed under the terms of the BSD License. The full license is in
11
- # the file COPYING, distributed as part of this software.
12
- #-----------------------------------------------------------------------------
13
-
14
- import os
15
- import re
16
- import sys
17
- from getopt import getopt, GetoptError
18
-
19
- from traitlets.config.configurable import Configurable
20
- from . import oinspect
21
- from .error import UsageError
22
- from .inputtransformer2 import ESC_MAGIC, ESC_MAGIC2
23
- from ..utils.ipstruct import Struct
24
- from ..utils.process import arg_split
25
- from ..utils.text import dedent
26
- from traitlets import Bool, Dict, Instance, observe
27
- from logging import error
28
-
29
- import typing as t
30
-
31
- #-----------------------------------------------------------------------------
32
- # Globals
33
- #-----------------------------------------------------------------------------
34
-
35
- # A dict we'll use for each class that has magics, used as temporary storage to
36
- # pass information between the @line/cell_magic method decorators and the
37
- # @magics_class class decorator, because the method decorators have no
38
- # access to the class when they run. See for more details:
39
- # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
40
-
41
- magics: t.Dict = dict(line={}, cell={})
42
-
43
- magic_kinds = ('line', 'cell')
44
- magic_spec = ('line', 'cell', 'line_cell')
45
- magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
46
-
47
- #-----------------------------------------------------------------------------
48
- # Utility classes and functions
49
- #-----------------------------------------------------------------------------
50
-
51
- class Bunch: pass
52
-
53
-
54
- def on_off(tag):
55
- """Return an ON/OFF string for a 1/0 input. Simple utility function."""
56
- return ['OFF','ON'][tag]
57
-
58
-
59
- def compress_dhist(dh):
60
- """Compress a directory history into a new one with at most 20 entries.
61
-
62
- Return a new list made from the first and last 10 elements of dhist after
63
- removal of duplicates.
64
- """
65
- head, tail = dh[:-10], dh[-10:]
66
-
67
- newhead = []
68
- done = set()
69
- for h in head:
70
- if h in done:
71
- continue
72
- newhead.append(h)
73
- done.add(h)
74
-
75
- return newhead + tail
76
-
77
-
78
- def needs_local_scope(func):
79
- """Decorator to mark magic functions which need to local scope to run."""
80
- func.needs_local_scope = True
81
- return func
82
-
83
- #-----------------------------------------------------------------------------
84
- # Class and method decorators for registering magics
85
- #-----------------------------------------------------------------------------
86
-
87
- def magics_class(cls):
88
- """Class decorator for all subclasses of the main Magics class.
89
-
90
- Any class that subclasses Magics *must* also apply this decorator, to
91
- ensure that all the methods that have been decorated as line/cell magics
92
- get correctly registered in the class instance. This is necessary because
93
- when method decorators run, the class does not exist yet, so they
94
- temporarily store their information into a module global. Application of
95
- this class decorator copies that global data to the class instance and
96
- clears the global.
97
-
98
- Obviously, this mechanism is not thread-safe, which means that the
99
- *creation* of subclasses of Magic should only be done in a single-thread
100
- context. Instantiation of the classes has no restrictions. Given that
101
- these classes are typically created at IPython startup time and before user
102
- application code becomes active, in practice this should not pose any
103
- problems.
104
- """
105
- cls.registered = True
106
- cls.magics = dict(line = magics['line'],
107
- cell = magics['cell'])
108
- magics['line'] = {}
109
- magics['cell'] = {}
110
- return cls
111
-
112
-
113
- def record_magic(dct, magic_kind, magic_name, func):
114
- """Utility function to store a function as a magic of a specific kind.
115
-
116
- Parameters
117
- ----------
118
- dct : dict
119
- A dictionary with 'line' and 'cell' subdicts.
120
- magic_kind : str
121
- Kind of magic to be stored.
122
- magic_name : str
123
- Key to store the magic as.
124
- func : function
125
- Callable object to store.
126
- """
127
- if magic_kind == 'line_cell':
128
- dct['line'][magic_name] = dct['cell'][magic_name] = func
129
- else:
130
- dct[magic_kind][magic_name] = func
131
-
132
-
133
- def validate_type(magic_kind):
134
- """Ensure that the given magic_kind is valid.
135
-
136
- Check that the given magic_kind is one of the accepted spec types (stored
137
- in the global `magic_spec`), raise ValueError otherwise.
138
- """
139
- if magic_kind not in magic_spec:
140
- raise ValueError('magic_kind must be one of %s, %s given' %
141
- magic_kinds, magic_kind)
142
-
143
-
144
- # The docstrings for the decorator below will be fairly similar for the two
145
- # types (method and function), so we generate them here once and reuse the
146
- # templates below.
147
- _docstring_template = \
148
- """Decorate the given {0} as {1} magic.
149
-
150
- The decorator can be used with or without arguments, as follows.
151
-
152
- i) without arguments: it will create a {1} magic named as the {0} being
153
- decorated::
154
-
155
- @deco
156
- def foo(...)
157
-
158
- will create a {1} magic named `foo`.
159
-
160
- ii) with one string argument: which will be used as the actual name of the
161
- resulting magic::
162
-
163
- @deco('bar')
164
- def foo(...)
165
-
166
- will create a {1} magic named `bar`.
167
-
168
- To register a class magic use ``Interactiveshell.register_magic(class or instance)``.
169
- """
170
-
171
- # These two are decorator factories. While they are conceptually very similar,
172
- # there are enough differences in the details that it's simpler to have them
173
- # written as completely standalone functions rather than trying to share code
174
- # and make a single one with convoluted logic.
175
-
176
- def _method_magic_marker(magic_kind):
177
- """Decorator factory for methods in Magics subclasses.
178
- """
179
-
180
- validate_type(magic_kind)
181
-
182
- # This is a closure to capture the magic_kind. We could also use a class,
183
- # but it's overkill for just that one bit of state.
184
- def magic_deco(arg):
185
- if callable(arg):
186
- # "Naked" decorator call (just @foo, no args)
187
- func = arg
188
- name = func.__name__
189
- retval = arg
190
- record_magic(magics, magic_kind, name, name)
191
- elif isinstance(arg, str):
192
- # Decorator called with arguments (@foo('bar'))
193
- name = arg
194
- def mark(func, *a, **kw):
195
- record_magic(magics, magic_kind, name, func.__name__)
196
- return func
197
- retval = mark
198
- else:
199
- raise TypeError("Decorator can only be called with "
200
- "string or function")
201
- return retval
202
-
203
- # Ensure the resulting decorator has a usable docstring
204
- magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
205
- return magic_deco
206
-
207
-
208
- def _function_magic_marker(magic_kind):
209
- """Decorator factory for standalone functions.
210
- """
211
- validate_type(magic_kind)
212
-
213
- # This is a closure to capture the magic_kind. We could also use a class,
214
- # but it's overkill for just that one bit of state.
215
- def magic_deco(arg):
216
- # Find get_ipython() in the caller's namespace
217
- caller = sys._getframe(1)
218
- for ns in ['f_locals', 'f_globals', 'f_builtins']:
219
- get_ipython = getattr(caller, ns).get('get_ipython')
220
- if get_ipython is not None:
221
- break
222
- else:
223
- raise NameError('Decorator can only run in context where '
224
- '`get_ipython` exists')
225
-
226
- ip = get_ipython()
227
-
228
- if callable(arg):
229
- # "Naked" decorator call (just @foo, no args)
230
- func = arg
231
- name = func.__name__
232
- ip.register_magic_function(func, magic_kind, name)
233
- retval = arg
234
- elif isinstance(arg, str):
235
- # Decorator called with arguments (@foo('bar'))
236
- name = arg
237
- def mark(func, *a, **kw):
238
- ip.register_magic_function(func, magic_kind, name)
239
- return func
240
- retval = mark
241
- else:
242
- raise TypeError("Decorator can only be called with "
243
- "string or function")
244
- return retval
245
-
246
- # Ensure the resulting decorator has a usable docstring
247
- ds = _docstring_template.format('function', magic_kind)
248
-
249
- ds += dedent("""
250
- Note: this decorator can only be used in a context where IPython is already
251
- active, so that the `get_ipython()` call succeeds. You can therefore use
252
- it in your startup files loaded after IPython initializes, but *not* in the
253
- IPython configuration file itself, which is executed before IPython is
254
- fully up and running. Any file located in the `startup` subdirectory of
255
- your configuration profile will be OK in this sense.
256
- """)
257
-
258
- magic_deco.__doc__ = ds
259
- return magic_deco
260
-
261
-
262
- MAGIC_NO_VAR_EXPAND_ATTR = "_ipython_magic_no_var_expand"
263
- MAGIC_OUTPUT_CAN_BE_SILENCED = "_ipython_magic_output_can_be_silenced"
264
-
265
-
266
- def no_var_expand(magic_func):
267
- """Mark a magic function as not needing variable expansion
268
-
269
- By default, IPython interprets `{a}` or `$a` in the line passed to magics
270
- as variables that should be interpolated from the interactive namespace
271
- before passing the line to the magic function.
272
- This is not always desirable, e.g. when the magic executes Python code
273
- (%timeit, %time, etc.).
274
- Decorate magics with `@no_var_expand` to opt-out of variable expansion.
275
-
276
- .. versionadded:: 7.3
277
- """
278
- setattr(magic_func, MAGIC_NO_VAR_EXPAND_ATTR, True)
279
- return magic_func
280
-
281
-
282
- def output_can_be_silenced(magic_func):
283
- """Mark a magic function so its output may be silenced.
284
-
285
- The output is silenced if the Python code used as a parameter of
286
- the magic ends in a semicolon, not counting a Python comment that can
287
- follow it.
288
- """
289
- setattr(magic_func, MAGIC_OUTPUT_CAN_BE_SILENCED, True)
290
- return magic_func
291
-
292
- # Create the actual decorators for public use
293
-
294
- # These three are used to decorate methods in class definitions
295
- line_magic = _method_magic_marker('line')
296
- cell_magic = _method_magic_marker('cell')
297
- line_cell_magic = _method_magic_marker('line_cell')
298
-
299
- # These three decorate standalone functions and perform the decoration
300
- # immediately. They can only run where get_ipython() works
301
- register_line_magic = _function_magic_marker('line')
302
- register_cell_magic = _function_magic_marker('cell')
303
- register_line_cell_magic = _function_magic_marker('line_cell')
304
-
305
- #-----------------------------------------------------------------------------
306
- # Core Magic classes
307
- #-----------------------------------------------------------------------------
308
-
309
- class MagicsManager(Configurable):
310
- """Object that handles all magic-related functionality for IPython.
311
- """
312
- # Non-configurable class attributes
313
-
314
- # A two-level dict, first keyed by magic type, then by magic function, and
315
- # holding the actual callable object as value. This is the dict used for
316
- # magic function dispatch
317
- magics = Dict()
318
- lazy_magics = Dict(
319
- help="""
320
- Mapping from magic names to modules to load.
321
-
322
- This can be used in IPython/IPykernel configuration to declare lazy magics
323
- that will only be imported/registered on first use.
324
-
325
- For example::
326
-
327
- c.MagicsManager.lazy_magics = {
328
- "my_magic": "slow.to.import",
329
- "my_other_magic": "also.slow",
330
- }
331
-
332
- On first invocation of `%my_magic`, `%%my_magic`, `%%my_other_magic` or
333
- `%%my_other_magic`, the corresponding module will be loaded as an ipython
334
- extensions as if you had previously done `%load_ext ipython`.
335
-
336
- Magics names should be without percent(s) as magics can be both cell
337
- and line magics.
338
-
339
- Lazy loading happen relatively late in execution process, and
340
- complex extensions that manipulate Python/IPython internal state or global state
341
- might not support lazy loading.
342
- """
343
- ).tag(
344
- config=True,
345
- )
346
-
347
- # A registry of the original objects that we've been given holding magics.
348
- registry = Dict()
349
-
350
- shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
351
-
352
- auto_magic = Bool(True, help=
353
- "Automatically call line magics without requiring explicit % prefix"
354
- ).tag(config=True)
355
- @observe('auto_magic')
356
- def _auto_magic_changed(self, change):
357
- self.shell.automagic = change['new']
358
-
359
- _auto_status = [
360
- 'Automagic is OFF, % prefix IS needed for line magics.',
361
- 'Automagic is ON, % prefix IS NOT needed for line magics.']
362
-
363
- user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
364
-
365
- def __init__(self, shell=None, config=None, user_magics=None, **traits):
366
-
367
- super(MagicsManager, self).__init__(shell=shell, config=config,
368
- user_magics=user_magics, **traits)
369
- self.magics = dict(line={}, cell={})
370
- # Let's add the user_magics to the registry for uniformity, so *all*
371
- # registered magic containers can be found there.
372
- self.registry[user_magics.__class__.__name__] = user_magics
373
-
374
- def auto_status(self):
375
- """Return descriptive string with automagic status."""
376
- return self._auto_status[self.auto_magic]
377
-
378
- def lsmagic(self):
379
- """Return a dict of currently available magic functions.
380
-
381
- The return dict has the keys 'line' and 'cell', corresponding to the
382
- two types of magics we support. Each value is a list of names.
383
- """
384
- return self.magics
385
-
386
- def lsmagic_docs(self, brief=False, missing=''):
387
- """Return dict of documentation of magic functions.
388
-
389
- The return dict has the keys 'line' and 'cell', corresponding to the
390
- two types of magics we support. Each value is a dict keyed by magic
391
- name whose value is the function docstring. If a docstring is
392
- unavailable, the value of `missing` is used instead.
393
-
394
- If brief is True, only the first line of each docstring will be returned.
395
- """
396
- docs = {}
397
- for m_type in self.magics:
398
- m_docs = {}
399
- for m_name, m_func in self.magics[m_type].items():
400
- if m_func.__doc__:
401
- if brief:
402
- m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
403
- else:
404
- m_docs[m_name] = m_func.__doc__.rstrip()
405
- else:
406
- m_docs[m_name] = missing
407
- docs[m_type] = m_docs
408
- return docs
409
-
410
- def register_lazy(self, name: str, fully_qualified_name: str):
411
- """
412
- Lazily register a magic via an extension.
413
-
414
-
415
- Parameters
416
- ----------
417
- name : str
418
- Name of the magic you wish to register.
419
- fully_qualified_name :
420
- Fully qualified name of the module/submodule that should be loaded
421
- as an extensions when the magic is first called.
422
- It is assumed that loading this extensions will register the given
423
- magic.
424
- """
425
-
426
- self.lazy_magics[name] = fully_qualified_name
427
-
428
- def register(self, *magic_objects):
429
- """Register one or more instances of Magics.
430
-
431
- Take one or more classes or instances of classes that subclass the main
432
- `core.Magic` class, and register them with IPython to use the magic
433
- functions they provide. The registration process will then ensure that
434
- any methods that have decorated to provide line and/or cell magics will
435
- be recognized with the `%x`/`%%x` syntax as a line/cell magic
436
- respectively.
437
-
438
- If classes are given, they will be instantiated with the default
439
- constructor. If your classes need a custom constructor, you should
440
- instanitate them first and pass the instance.
441
-
442
- The provided arguments can be an arbitrary mix of classes and instances.
443
-
444
- Parameters
445
- ----------
446
- *magic_objects : one or more classes or instances
447
- """
448
- # Start by validating them to ensure they have all had their magic
449
- # methods registered at the instance level
450
- for m in magic_objects:
451
- if not m.registered:
452
- raise ValueError("Class of magics %r was constructed without "
453
- "the @register_magics class decorator")
454
- if isinstance(m, type):
455
- # If we're given an uninstantiated class
456
- m = m(shell=self.shell)
457
-
458
- # Now that we have an instance, we can register it and update the
459
- # table of callables
460
- self.registry[m.__class__.__name__] = m
461
- for mtype in magic_kinds:
462
- self.magics[mtype].update(m.magics[mtype])
463
-
464
- def register_function(self, func, magic_kind='line', magic_name=None):
465
- """Expose a standalone function as magic function for IPython.
466
-
467
- This will create an IPython magic (line, cell or both) from a
468
- standalone function. The functions should have the following
469
- signatures:
470
-
471
- * For line magics: `def f(line)`
472
- * For cell magics: `def f(line, cell)`
473
- * For a function that does both: `def f(line, cell=None)`
474
-
475
- In the latter case, the function will be called with `cell==None` when
476
- invoked as `%f`, and with cell as a string when invoked as `%%f`.
477
-
478
- Parameters
479
- ----------
480
- func : callable
481
- Function to be registered as a magic.
482
- magic_kind : str
483
- Kind of magic, one of 'line', 'cell' or 'line_cell'
484
- magic_name : optional str
485
- If given, the name the magic will have in the IPython namespace. By
486
- default, the name of the function itself is used.
487
- """
488
-
489
- # Create the new method in the user_magics and register it in the
490
- # global table
491
- validate_type(magic_kind)
492
- magic_name = func.__name__ if magic_name is None else magic_name
493
- setattr(self.user_magics, magic_name, func)
494
- record_magic(self.magics, magic_kind, magic_name, func)
495
-
496
- def register_alias(self, alias_name, magic_name, magic_kind='line', magic_params=None):
497
- """Register an alias to a magic function.
498
-
499
- The alias is an instance of :class:`MagicAlias`, which holds the
500
- name and kind of the magic it should call. Binding is done at
501
- call time, so if the underlying magic function is changed the alias
502
- will call the new function.
503
-
504
- Parameters
505
- ----------
506
- alias_name : str
507
- The name of the magic to be registered.
508
- magic_name : str
509
- The name of an existing magic.
510
- magic_kind : str
511
- Kind of magic, one of 'line' or 'cell'
512
- """
513
-
514
- # `validate_type` is too permissive, as it allows 'line_cell'
515
- # which we do not handle.
516
- if magic_kind not in magic_kinds:
517
- raise ValueError('magic_kind must be one of %s, %s given' %
518
- magic_kinds, magic_kind)
519
-
520
- alias = MagicAlias(self.shell, magic_name, magic_kind, magic_params)
521
- setattr(self.user_magics, alias_name, alias)
522
- record_magic(self.magics, magic_kind, alias_name, alias)
523
-
524
- # Key base class that provides the central functionality for magics.
525
-
526
-
527
- class Magics(Configurable):
528
- """Base class for implementing magic functions.
529
-
530
- Shell functions which can be reached as %function_name. All magic
531
- functions should accept a string, which they can parse for their own
532
- needs. This can make some functions easier to type, eg `%cd ../`
533
- vs. `%cd("../")`
534
-
535
- Classes providing magic functions need to subclass this class, and they
536
- MUST:
537
-
538
- - Use the method decorators `@line_magic` and `@cell_magic` to decorate
539
- individual methods as magic functions, AND
540
-
541
- - Use the class decorator `@magics_class` to ensure that the magic
542
- methods are properly registered at the instance level upon instance
543
- initialization.
544
-
545
- See :mod:`magic_functions` for examples of actual implementation classes.
546
- """
547
- # Dict holding all command-line options for each magic.
548
- options_table = None
549
- # Dict for the mapping of magic names to methods, set by class decorator
550
- magics = None
551
- # Flag to check that the class decorator was properly applied
552
- registered = False
553
- # Instance of IPython shell
554
- shell = None
555
-
556
- def __init__(self, shell=None, **kwargs):
557
- if not(self.__class__.registered):
558
- raise ValueError('Magics subclass without registration - '
559
- 'did you forget to apply @magics_class?')
560
- if shell is not None:
561
- if hasattr(shell, 'configurables'):
562
- shell.configurables.append(self)
563
- if hasattr(shell, 'config'):
564
- kwargs.setdefault('parent', shell)
565
-
566
- self.shell = shell
567
- self.options_table = {}
568
- # The method decorators are run when the instance doesn't exist yet, so
569
- # they can only record the names of the methods they are supposed to
570
- # grab. Only now, that the instance exists, can we create the proper
571
- # mapping to bound methods. So we read the info off the original names
572
- # table and replace each method name by the actual bound method.
573
- # But we mustn't clobber the *class* mapping, in case of multiple instances.
574
- class_magics = self.magics
575
- self.magics = {}
576
- for mtype in magic_kinds:
577
- tab = self.magics[mtype] = {}
578
- cls_tab = class_magics[mtype]
579
- for magic_name, meth_name in cls_tab.items():
580
- if isinstance(meth_name, str):
581
- # it's a method name, grab it
582
- tab[magic_name] = getattr(self, meth_name)
583
- else:
584
- # it's the real thing
585
- tab[magic_name] = meth_name
586
- # Configurable **needs** to be initiated at the end or the config
587
- # magics get screwed up.
588
- super(Magics, self).__init__(**kwargs)
589
-
590
- def arg_err(self,func):
591
- """Print docstring if incorrect arguments were passed"""
592
- print('Error in arguments:')
593
- print(oinspect.getdoc(func))
594
-
595
- def format_latex(self, strng):
596
- """Format a string for latex inclusion."""
597
-
598
- # Characters that need to be escaped for latex:
599
- escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
600
- # Magic command names as headers:
601
- cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
602
- re.MULTILINE)
603
- # Magic commands
604
- cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
605
- re.MULTILINE)
606
- # Paragraph continue
607
- par_re = re.compile(r'\\$',re.MULTILINE)
608
-
609
- # The "\n" symbol
610
- newline_re = re.compile(r'\\n')
611
-
612
- # Now build the string for output:
613
- #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
614
- strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
615
- strng)
616
- strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
617
- strng = par_re.sub(r'\\\\',strng)
618
- strng = escape_re.sub(r'\\\1',strng)
619
- strng = newline_re.sub(r'\\textbackslash{}n',strng)
620
- return strng
621
-
622
- def parse_options(self, arg_str, opt_str, *long_opts, **kw):
623
- """Parse options passed to an argument string.
624
-
625
- The interface is similar to that of :func:`getopt.getopt`, but it
626
- returns a :class:`~IPython.utils.struct.Struct` with the options as keys
627
- and the stripped argument string still as a string.
628
-
629
- arg_str is quoted as a true sys.argv vector by using shlex.split.
630
- This allows us to easily expand variables, glob files, quote
631
- arguments, etc.
632
-
633
- Parameters
634
- ----------
635
- arg_str : str
636
- The arguments to parse.
637
- opt_str : str
638
- The options specification.
639
- mode : str, default 'string'
640
- If given as 'list', the argument string is returned as a list (split
641
- on whitespace) instead of a string.
642
- list_all : bool, default False
643
- Put all option values in lists. Normally only options
644
- appearing more than once are put in a list.
645
- posix : bool, default True
646
- Whether to split the input line in POSIX mode or not, as per the
647
- conventions outlined in the :mod:`shlex` module from the standard
648
- library.
649
- """
650
-
651
- # inject default options at the beginning of the input line
652
- caller = sys._getframe(1).f_code.co_name
653
- arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
654
-
655
- mode = kw.get('mode','string')
656
- if mode not in ['string','list']:
657
- raise ValueError('incorrect mode given: %s' % mode)
658
- # Get options
659
- list_all = kw.get('list_all',0)
660
- posix = kw.get('posix', os.name == 'posix')
661
- strict = kw.get('strict', True)
662
-
663
- preserve_non_opts = kw.get("preserve_non_opts", False)
664
- remainder_arg_str = arg_str
665
-
666
- # Check if we have more than one argument to warrant extra processing:
667
- odict = {} # Dictionary with options
668
- args = arg_str.split()
669
- if len(args) >= 1:
670
- # If the list of inputs only has 0 or 1 thing in it, there's no
671
- # need to look for options
672
- argv = arg_split(arg_str, posix, strict)
673
- # Do regular option processing
674
- try:
675
- opts,args = getopt(argv, opt_str, long_opts)
676
- except GetoptError as e:
677
- raise UsageError(
678
- '%s ( allowed: "%s" %s)' % (e.msg, opt_str, " ".join(long_opts))
679
- ) from e
680
- for o, a in opts:
681
- if mode == "string" and preserve_non_opts:
682
- # remove option-parts from the original args-string and preserve remaining-part.
683
- # This relies on the arg_split(...) and getopt(...)'s impl spec, that the parsed options are
684
- # returned in the original order.
685
- remainder_arg_str = remainder_arg_str.replace(o, "", 1).replace(
686
- a, "", 1
687
- )
688
- if o.startswith("--"):
689
- o = o[2:]
690
- else:
691
- o = o[1:]
692
- try:
693
- odict[o].append(a)
694
- except AttributeError:
695
- odict[o] = [odict[o],a]
696
- except KeyError:
697
- if list_all:
698
- odict[o] = [a]
699
- else:
700
- odict[o] = a
701
-
702
- # Prepare opts,args for return
703
- opts = Struct(odict)
704
- if mode == 'string':
705
- if preserve_non_opts:
706
- args = remainder_arg_str.lstrip()
707
- else:
708
- args = " ".join(args)
709
-
710
- return opts,args
711
-
712
- def default_option(self, fn, optstr):
713
- """Make an entry in the options_table for fn, with value optstr"""
714
-
715
- if fn not in self.lsmagic():
716
- error("%s is not a magic function" % fn)
717
- self.options_table[fn] = optstr
718
-
719
-
720
- class MagicAlias(object):
721
- """An alias to another magic function.
722
-
723
- An alias is determined by its magic name and magic kind. Lookup
724
- is done at call time, so if the underlying magic changes the alias
725
- will call the new function.
726
-
727
- Use the :meth:`MagicsManager.register_alias` method or the
728
- `%alias_magic` magic function to create and register a new alias.
729
- """
730
- def __init__(self, shell, magic_name, magic_kind, magic_params=None):
731
- self.shell = shell
732
- self.magic_name = magic_name
733
- self.magic_params = magic_params
734
- self.magic_kind = magic_kind
735
-
736
- self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
737
- self.__doc__ = "Alias for `%s`." % self.pretty_target
738
-
739
- self._in_call = False
740
-
741
- def __call__(self, *args, **kwargs):
742
- """Call the magic alias."""
743
- fn = self.shell.find_magic(self.magic_name, self.magic_kind)
744
- if fn is None:
745
- raise UsageError("Magic `%s` not found." % self.pretty_target)
746
-
747
- # Protect against infinite recursion.
748
- if self._in_call:
749
- raise UsageError("Infinite recursion detected; "
750
- "magic aliases cannot call themselves.")
751
- self._in_call = True
752
- try:
753
- if self.magic_params:
754
- args_list = list(args)
755
- args_list[0] = self.magic_params + " " + args[0]
756
- args = tuple(args_list)
757
- return fn(*args, **kwargs)
758
- finally:
759
- self._in_call = False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/magic_arguments.py DELETED
@@ -1,310 +0,0 @@
1
- ''' A decorator-based method of constructing IPython magics with `argparse`
2
- option handling.
3
-
4
- New magic functions can be defined like so::
5
-
6
- from IPython.core.magic_arguments import (argument, magic_arguments,
7
- parse_argstring)
8
-
9
- @magic_arguments()
10
- @argument('-o', '--option', help='An optional argument.')
11
- @argument('arg', type=int, help='An integer positional argument.')
12
- def magic_cool(self, arg):
13
- """ A really cool magic command.
14
-
15
- """
16
- args = parse_argstring(magic_cool, arg)
17
- ...
18
-
19
- The `@magic_arguments` decorator marks the function as having argparse arguments.
20
- The `@argument` decorator adds an argument using the same syntax as argparse's
21
- `add_argument()` method. More sophisticated uses may also require the
22
- `@argument_group` or `@kwds` decorator to customize the formatting and the
23
- parsing.
24
-
25
- Help text for the magic is automatically generated from the docstring and the
26
- arguments::
27
-
28
- In[1]: %cool?
29
- %cool [-o OPTION] arg
30
-
31
- A really cool magic command.
32
-
33
- positional arguments:
34
- arg An integer positional argument.
35
-
36
- optional arguments:
37
- -o OPTION, --option OPTION
38
- An optional argument.
39
-
40
- Here is an elaborated example that uses default parameters in `argument` and calls the `args` in the cell magic::
41
-
42
- from IPython.core.magic import register_cell_magic
43
- from IPython.core.magic_arguments import (argument, magic_arguments,
44
- parse_argstring)
45
-
46
-
47
- @magic_arguments()
48
- @argument(
49
- "--option",
50
- "-o",
51
- help=("Add an option here"),
52
- )
53
- @argument(
54
- "--style",
55
- "-s",
56
- default="foo",
57
- help=("Add some style arguments"),
58
- )
59
- @register_cell_magic
60
- def my_cell_magic(line, cell):
61
- args = parse_argstring(my_cell_magic, line)
62
- print(f"{args.option=}")
63
- print(f"{args.style=}")
64
- print(f"{cell=}")
65
-
66
- In a jupyter notebook, this cell magic can be executed like this::
67
-
68
- %%my_cell_magic -o Hello
69
- print("bar")
70
- i = 42
71
-
72
- Inheritance diagram:
73
-
74
- .. inheritance-diagram:: IPython.core.magic_arguments
75
- :parts: 3
76
-
77
- '''
78
- #-----------------------------------------------------------------------------
79
- # Copyright (C) 2010-2011, IPython Development Team.
80
- #
81
- # Distributed under the terms of the Modified BSD License.
82
- #
83
- # The full license is in the file COPYING.txt, distributed with this software.
84
- #-----------------------------------------------------------------------------
85
- import argparse
86
- import re
87
-
88
- # Our own imports
89
- from IPython.core.error import UsageError
90
- from IPython.utils.decorators import undoc
91
- from IPython.utils.process import arg_split
92
- from IPython.utils.text import dedent
93
-
94
- NAME_RE = re.compile(r"[a-zA-Z][a-zA-Z0-9_-]*$")
95
-
96
- @undoc
97
- class MagicHelpFormatter(argparse.RawDescriptionHelpFormatter):
98
- """A HelpFormatter with a couple of changes to meet our needs.
99
- """
100
- # Modified to dedent text.
101
- def _fill_text(self, text, width, indent):
102
- return argparse.RawDescriptionHelpFormatter._fill_text(self, dedent(text), width, indent)
103
-
104
- # Modified to wrap argument placeholders in <> where necessary.
105
- def _format_action_invocation(self, action):
106
- if not action.option_strings:
107
- metavar, = self._metavar_formatter(action, action.dest)(1)
108
- return metavar
109
-
110
- else:
111
- parts = []
112
-
113
- # if the Optional doesn't take a value, format is:
114
- # -s, --long
115
- if action.nargs == 0:
116
- parts.extend(action.option_strings)
117
-
118
- # if the Optional takes a value, format is:
119
- # -s ARGS, --long ARGS
120
- else:
121
- default = action.dest.upper()
122
- args_string = self._format_args(action, default)
123
- # IPYTHON MODIFICATION: If args_string is not a plain name, wrap
124
- # it in <> so it's valid RST.
125
- if not NAME_RE.match(args_string):
126
- args_string = "<%s>" % args_string
127
- for option_string in action.option_strings:
128
- parts.append('%s %s' % (option_string, args_string))
129
-
130
- return ', '.join(parts)
131
-
132
- # Override the default prefix ('usage') to our % magic escape,
133
- # in a code block.
134
- def add_usage(self, usage, actions, groups, prefix="::\n\n %"):
135
- super(MagicHelpFormatter, self).add_usage(usage, actions, groups, prefix)
136
-
137
- class MagicArgumentParser(argparse.ArgumentParser):
138
- """ An ArgumentParser tweaked for use by IPython magics.
139
- """
140
- def __init__(self,
141
- prog=None,
142
- usage=None,
143
- description=None,
144
- epilog=None,
145
- parents=None,
146
- formatter_class=MagicHelpFormatter,
147
- prefix_chars='-',
148
- argument_default=None,
149
- conflict_handler='error',
150
- add_help=False):
151
- if parents is None:
152
- parents = []
153
- super(MagicArgumentParser, self).__init__(prog=prog, usage=usage,
154
- description=description, epilog=epilog,
155
- parents=parents, formatter_class=formatter_class,
156
- prefix_chars=prefix_chars, argument_default=argument_default,
157
- conflict_handler=conflict_handler, add_help=add_help)
158
-
159
- def error(self, message):
160
- """ Raise a catchable error instead of exiting.
161
- """
162
- raise UsageError(message)
163
-
164
- def parse_argstring(self, argstring):
165
- """ Split a string into an argument list and parse that argument list.
166
- """
167
- argv = arg_split(argstring)
168
- return self.parse_args(argv)
169
-
170
-
171
- def construct_parser(magic_func):
172
- """ Construct an argument parser using the function decorations.
173
- """
174
- kwds = getattr(magic_func, 'argcmd_kwds', {})
175
- if 'description' not in kwds:
176
- kwds['description'] = getattr(magic_func, '__doc__', None)
177
- arg_name = real_name(magic_func)
178
- parser = MagicArgumentParser(arg_name, **kwds)
179
- # Reverse the list of decorators in order to apply them in the
180
- # order in which they appear in the source.
181
- group = None
182
- for deco in magic_func.decorators[::-1]:
183
- result = deco.add_to_parser(parser, group)
184
- if result is not None:
185
- group = result
186
-
187
- # Replace the magic function's docstring with the full help text.
188
- magic_func.__doc__ = parser.format_help()
189
-
190
- return parser
191
-
192
-
193
- def parse_argstring(magic_func, argstring):
194
- """ Parse the string of arguments for the given magic function.
195
- """
196
- return magic_func.parser.parse_argstring(argstring)
197
-
198
-
199
- def real_name(magic_func):
200
- """ Find the real name of the magic.
201
- """
202
- magic_name = magic_func.__name__
203
- if magic_name.startswith('magic_'):
204
- magic_name = magic_name[len('magic_'):]
205
- return getattr(magic_func, 'argcmd_name', magic_name)
206
-
207
-
208
- class ArgDecorator(object):
209
- """ Base class for decorators to add ArgumentParser information to a method.
210
- """
211
-
212
- def __call__(self, func):
213
- if not getattr(func, 'has_arguments', False):
214
- func.has_arguments = True
215
- func.decorators = []
216
- func.decorators.append(self)
217
- return func
218
-
219
- def add_to_parser(self, parser, group):
220
- """ Add this object's information to the parser, if necessary.
221
- """
222
- pass
223
-
224
-
225
- class magic_arguments(ArgDecorator):
226
- """ Mark the magic as having argparse arguments and possibly adjust the
227
- name.
228
- """
229
-
230
- def __init__(self, name=None):
231
- self.name = name
232
-
233
- def __call__(self, func):
234
- if not getattr(func, 'has_arguments', False):
235
- func.has_arguments = True
236
- func.decorators = []
237
- if self.name is not None:
238
- func.argcmd_name = self.name
239
- # This should be the first decorator in the list of decorators, thus the
240
- # last to execute. Build the parser.
241
- func.parser = construct_parser(func)
242
- return func
243
-
244
-
245
- class ArgMethodWrapper(ArgDecorator):
246
-
247
- """
248
- Base class to define a wrapper for ArgumentParser method.
249
-
250
- Child class must define either `_method_name` or `add_to_parser`.
251
-
252
- """
253
-
254
- _method_name: str
255
-
256
- def __init__(self, *args, **kwds):
257
- self.args = args
258
- self.kwds = kwds
259
-
260
- def add_to_parser(self, parser, group):
261
- """ Add this object's information to the parser.
262
- """
263
- if group is not None:
264
- parser = group
265
- getattr(parser, self._method_name)(*self.args, **self.kwds)
266
- return None
267
-
268
-
269
- class argument(ArgMethodWrapper):
270
- """ Store arguments and keywords to pass to add_argument().
271
-
272
- Instances also serve to decorate command methods.
273
- """
274
- _method_name = 'add_argument'
275
-
276
-
277
- class defaults(ArgMethodWrapper):
278
- """ Store arguments and keywords to pass to set_defaults().
279
-
280
- Instances also serve to decorate command methods.
281
- """
282
- _method_name = 'set_defaults'
283
-
284
-
285
- class argument_group(ArgMethodWrapper):
286
- """ Store arguments and keywords to pass to add_argument_group().
287
-
288
- Instances also serve to decorate command methods.
289
- """
290
-
291
- def add_to_parser(self, parser, group):
292
- """ Add this object's information to the parser.
293
- """
294
- return parser.add_argument_group(*self.args, **self.kwds)
295
-
296
-
297
- class kwds(ArgDecorator):
298
- """ Provide other keywords to the sub-parser constructor.
299
- """
300
- def __init__(self, **kwds):
301
- self.kwds = kwds
302
-
303
- def __call__(self, func):
304
- func = super(kwds, self).__call__(func)
305
- func.argcmd_kwds = self.kwds
306
- return func
307
-
308
-
309
- __all__ = ['magic_arguments', 'argument', 'argument_group', 'kwds',
310
- 'parse_argstring']
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/__init__.py DELETED
@@ -1,42 +0,0 @@
1
- """Implementation of all the magic functions built into IPython.
2
- """
3
- #-----------------------------------------------------------------------------
4
- # Copyright (c) 2012 The IPython Development Team.
5
- #
6
- # Distributed under the terms of the Modified BSD License.
7
- #
8
- # The full license is in the file COPYING.txt, distributed with this software.
9
- #-----------------------------------------------------------------------------
10
-
11
- #-----------------------------------------------------------------------------
12
- # Imports
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
- #-----------------------------------------------------------------------------
32
- # Magic implementation classes
33
- #-----------------------------------------------------------------------------
34
-
35
- @magics_class
36
- class UserMagics(Magics):
37
- """Placeholder for user-defined magics to be added at runtime.
38
-
39
- All magics are eventually merged into a single namespace at runtime, but we
40
- use this class to isolate the magics defined dynamically by the user into
41
- their own class.
42
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/ast_mod.py DELETED
@@ -1,330 +0,0 @@
1
- """
2
- This module contains utility function and classes to inject simple ast
3
- transformations based on code strings into IPython. While it is already possible
4
- with ast-transformers it is not easy to directly manipulate ast.
5
-
6
-
7
- IPython has pre-code and post-code hooks, but are ran from within the IPython
8
- machinery so may be inappropriate, for example for performance measurement.
9
-
10
- This module give you tools to simplify this, and expose 2 classes:
11
-
12
- - `ReplaceCodeTransformer` which is a simple ast transformer based on code
13
- template,
14
-
15
- and for advance case:
16
-
17
- - `Mangler` which is a simple ast transformer that mangle names in the ast.
18
-
19
-
20
- Example, let's try to make a simple version of the ``timeit`` magic, that run a
21
- code snippet 10 times and print the average time taken.
22
-
23
- Basically we want to run :
24
-
25
- .. code-block:: python
26
-
27
- from time import perf_counter
28
- now = perf_counter()
29
- for i in range(10):
30
- __code__ # our code
31
- print(f"Time taken: {(perf_counter() - now)/10}")
32
- __ret__ # the result of the last statement
33
-
34
- Where ``__code__`` is the code snippet we want to run, and ``__ret__`` is the
35
- result, so that if we for example run `dataframe.head()` IPython still display
36
- the head of dataframe instead of nothing.
37
-
38
- Here is a complete example of a file `timit2.py` that define such a magic:
39
-
40
- .. code-block:: python
41
-
42
- from IPython.core.magic import (
43
- Magics,
44
- magics_class,
45
- line_cell_magic,
46
- )
47
- from IPython.core.magics.ast_mod import ReplaceCodeTransformer
48
- from textwrap import dedent
49
- import ast
50
-
51
- template = template = dedent('''
52
- from time import perf_counter
53
- now = perf_counter()
54
- for i in range(10):
55
- __code__
56
- print(f"Time taken: {(perf_counter() - now)/10}")
57
- __ret__
58
- '''
59
- )
60
-
61
-
62
- @magics_class
63
- class AstM(Magics):
64
- @line_cell_magic
65
- def t2(self, line, cell):
66
- transformer = ReplaceCodeTransformer.from_string(template)
67
- transformer.debug = True
68
- transformer.mangler.debug = True
69
- new_code = transformer.visit(ast.parse(cell))
70
- return exec(compile(new_code, "<ast>", "exec"))
71
-
72
-
73
- def load_ipython_extension(ip):
74
- ip.register_magics(AstM)
75
-
76
-
77
-
78
- .. code-block:: python
79
-
80
- In [1]: %load_ext timit2
81
-
82
- In [2]: %%t2
83
- ...: import time
84
- ...: time.sleep(0.05)
85
- ...:
86
- ...:
87
- Time taken: 0.05435649999999441
88
-
89
-
90
- If you wish to ran all the code enter in IPython in an ast transformer, you can
91
- do so as well:
92
-
93
- .. code-block:: python
94
-
95
- In [1]: from IPython.core.magics.ast_mod import ReplaceCodeTransformer
96
- ...:
97
- ...: template = '''
98
- ...: from time import perf_counter
99
- ...: now = perf_counter()
100
- ...: __code__
101
- ...: print(f"Code ran in {perf_counter()-now}")
102
- ...: __ret__'''
103
- ...:
104
- ...: get_ipython().ast_transformers.append(ReplaceCodeTransformer.from_string(template))
105
-
106
- In [2]: 1+1
107
- Code ran in 3.40410006174352e-05
108
- Out[2]: 2
109
-
110
-
111
-
112
- Hygiene and Mangling
113
- --------------------
114
-
115
- The ast transformer above is not hygienic, it may not work if the user code use
116
- the same variable names as the ones used in the template. For example.
117
-
118
- To help with this by default the `ReplaceCodeTransformer` will mangle all names
119
- staring with 3 underscores. This is a simple heuristic that should work in most
120
- case, but can be cumbersome in some case. We provide a `Mangler` class that can
121
- be overridden to change the mangling heuristic, or simply use the `mangle_all`
122
- utility function. It will _try_ to mangle all names (except `__ret__` and
123
- `__code__`), but this include builtins (``print``, ``range``, ``type``) and
124
- replace those by invalid identifiers py prepending ``mangle-``:
125
- ``mangle-print``, ``mangle-range``, ``mangle-type`` etc. This is not a problem
126
- as currently Python AST support invalid identifiers, but it may not be the case
127
- in the future.
128
-
129
- You can set `ReplaceCodeTransformer.debug=True` and
130
- `ReplaceCodeTransformer.mangler.debug=True` to see the code after mangling and
131
- transforming:
132
-
133
- .. code-block:: python
134
-
135
-
136
- In [1]: from IPython.core.magics.ast_mod import ReplaceCodeTransformer, mangle_all
137
- ...:
138
- ...: template = '''
139
- ...: from builtins import type, print
140
- ...: from time import perf_counter
141
- ...: now = perf_counter()
142
- ...: __code__
143
- ...: print(f"Code ran in {perf_counter()-now}")
144
- ...: __ret__'''
145
- ...:
146
- ...: transformer = ReplaceCodeTransformer.from_string(template, mangling_predicate=mangle_all)
147
-
148
-
149
- In [2]: transformer.debug = True
150
- ...: transformer.mangler.debug = True
151
- ...: get_ipython().ast_transformers.append(transformer)
152
-
153
- In [3]: 1+1
154
- Mangling Alias mangle-type
155
- Mangling Alias mangle-print
156
- Mangling Alias mangle-perf_counter
157
- Mangling now
158
- Mangling perf_counter
159
- Not mangling __code__
160
- Mangling print
161
- Mangling perf_counter
162
- Mangling now
163
- Not mangling __ret__
164
- ---- Transformed code ----
165
- from builtins import type as mangle-type, print as mangle-print
166
- from time import perf_counter as mangle-perf_counter
167
- mangle-now = mangle-perf_counter()
168
- ret-tmp = 1 + 1
169
- mangle-print(f'Code ran in {mangle-perf_counter() - mangle-now}')
170
- ret-tmp
171
- ---- ---------------- ----
172
- Code ran in 0.00013654199938173406
173
- Out[3]: 2
174
-
175
-
176
- """
177
-
178
- __skip_doctest__ = True
179
-
180
-
181
- from ast import (
182
- NodeTransformer,
183
- Store,
184
- Load,
185
- Name,
186
- Expr,
187
- Assign,
188
- Module,
189
- Import,
190
- ImportFrom,
191
- )
192
- import ast
193
- import copy
194
-
195
- from typing import Dict, Optional, Union
196
-
197
-
198
- mangle_all = lambda name: False if name in ("__ret__", "__code__") else True
199
-
200
-
201
- class Mangler(NodeTransformer):
202
- """
203
- Mangle given names in and ast tree to make sure they do not conflict with
204
- user code.
205
- """
206
-
207
- enabled: bool = True
208
- debug: bool = False
209
-
210
- def log(self, *args, **kwargs):
211
- if self.debug:
212
- print(*args, **kwargs)
213
-
214
- def __init__(self, predicate=None):
215
- if predicate is None:
216
- predicate = lambda name: name.startswith("___")
217
- self.predicate = predicate
218
-
219
- def visit_Name(self, node):
220
- if self.predicate(node.id):
221
- self.log("Mangling", node.id)
222
- # Once in the ast we do not need
223
- # names to be valid identifiers.
224
- node.id = "mangle-" + node.id
225
- else:
226
- self.log("Not mangling", node.id)
227
- return node
228
-
229
- def visit_FunctionDef(self, node):
230
- if self.predicate(node.name):
231
- self.log("Mangling", node.name)
232
- node.name = "mangle-" + node.name
233
- else:
234
- self.log("Not mangling", node.name)
235
-
236
- for arg in node.args.args:
237
- if self.predicate(arg.arg):
238
- self.log("Mangling function arg", arg.arg)
239
- arg.arg = "mangle-" + arg.arg
240
- else:
241
- self.log("Not mangling function arg", arg.arg)
242
- return self.generic_visit(node)
243
-
244
- def visit_ImportFrom(self, node: ImportFrom):
245
- return self._visit_Import_and_ImportFrom(node)
246
-
247
- def visit_Import(self, node: Import):
248
- return self._visit_Import_and_ImportFrom(node)
249
-
250
- def _visit_Import_and_ImportFrom(self, node: Union[Import, ImportFrom]):
251
- for alias in node.names:
252
- asname = alias.name if alias.asname is None else alias.asname
253
- if self.predicate(asname):
254
- new_name: str = "mangle-" + asname
255
- self.log("Mangling Alias", new_name)
256
- alias.asname = new_name
257
- else:
258
- self.log("Not mangling Alias", alias.asname)
259
- return node
260
-
261
-
262
- class ReplaceCodeTransformer(NodeTransformer):
263
- enabled: bool = True
264
- debug: bool = False
265
- mangler: Mangler
266
-
267
- def __init__(
268
- self, template: Module, mapping: Optional[Dict] = None, mangling_predicate=None
269
- ):
270
- assert isinstance(mapping, (dict, type(None)))
271
- assert isinstance(mangling_predicate, (type(None), type(lambda: None)))
272
- assert isinstance(template, ast.Module)
273
- self.template = template
274
- self.mangler = Mangler(predicate=mangling_predicate)
275
- if mapping is None:
276
- mapping = {}
277
- self.mapping = mapping
278
-
279
- @classmethod
280
- def from_string(
281
- cls, template: str, mapping: Optional[Dict] = None, mangling_predicate=None
282
- ):
283
- return cls(
284
- ast.parse(template), mapping=mapping, mangling_predicate=mangling_predicate
285
- )
286
-
287
- def visit_Module(self, code):
288
- if not self.enabled:
289
- return code
290
- # if not isinstance(code, ast.Module):
291
- # recursively called...
292
- # return generic_visit(self, code)
293
- last = code.body[-1]
294
- if isinstance(last, Expr):
295
- code.body.pop()
296
- code.body.append(Assign([Name("ret-tmp", ctx=Store())], value=last.value))
297
- ast.fix_missing_locations(code)
298
- ret = Expr(value=Name("ret-tmp", ctx=Load()))
299
- ret = ast.fix_missing_locations(ret)
300
- self.mapping["__ret__"] = ret
301
- else:
302
- self.mapping["__ret__"] = ast.parse("None").body[0]
303
- self.mapping["__code__"] = code.body
304
- tpl = ast.fix_missing_locations(self.template)
305
-
306
- tx = copy.deepcopy(tpl)
307
- tx = self.mangler.visit(tx)
308
- node = self.generic_visit(tx)
309
- node_2 = ast.fix_missing_locations(node)
310
- if self.debug:
311
- print("---- Transformed code ----")
312
- print(ast.unparse(node_2))
313
- print("---- ---------------- ----")
314
- return node_2
315
-
316
- # this does not work as the name might be in a list and one might want to extend the list.
317
- # def visit_Name(self, name):
318
- # if name.id in self.mapping and name.id == "__ret__":
319
- # print(name, "in mapping")
320
- # if isinstance(name.ctx, ast.Store):
321
- # return Name("tmp", ctx=Store())
322
- # else:
323
- # return copy.deepcopy(self.mapping[name.id])
324
- # return name
325
-
326
- def visit_Expr(self, expr):
327
- if isinstance(expr.value, Name) and expr.value.id in self.mapping:
328
- if self.mapping[expr.value.id] is not None:
329
- return copy.deepcopy(self.mapping[expr.value.id])
330
- return self.generic_visit(expr)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/auto.py DELETED
@@ -1,144 +0,0 @@
1
- """Implementation of magic functions that control various automatic behaviors.
2
- """
3
- #-----------------------------------------------------------------------------
4
- # Copyright (c) 2012 The IPython Development Team.
5
- #
6
- # Distributed under the terms of the Modified BSD License.
7
- #
8
- # The full license is in the file COPYING.txt, distributed with this software.
9
- #-----------------------------------------------------------------------------
10
-
11
- #-----------------------------------------------------------------------------
12
- # Imports
13
- #-----------------------------------------------------------------------------
14
-
15
- # Our own packages
16
- from IPython.core.magic import Bunch, Magics, magics_class, line_magic
17
- from IPython.testing.skipdoctest import skip_doctest
18
- from logging import error
19
-
20
- #-----------------------------------------------------------------------------
21
- # Magic implementation classes
22
- #-----------------------------------------------------------------------------
23
-
24
- @magics_class
25
- class AutoMagics(Magics):
26
- """Magics that control various autoX behaviors."""
27
-
28
- def __init__(self, shell):
29
- super(AutoMagics, self).__init__(shell)
30
- # namespace for holding state we may need
31
- self._magic_state = Bunch()
32
-
33
- @line_magic
34
- def automagic(self, parameter_s=''):
35
- """Make magic functions callable without having to type the initial %.
36
-
37
- Without arguments toggles on/off (when off, you must call it as
38
- %automagic, of course). With arguments it sets the value, and you can
39
- use any of (case insensitive):
40
-
41
- - on, 1, True: to activate
42
-
43
- - off, 0, False: to deactivate.
44
-
45
- Note that magic functions have lowest priority, so if there's a
46
- variable whose name collides with that of a magic fn, automagic won't
47
- work for that function (you get the variable instead). However, if you
48
- delete the variable (del var), the previously shadowed magic function
49
- becomes visible to automagic again."""
50
-
51
- arg = parameter_s.lower()
52
- mman = self.shell.magics_manager
53
- if arg in ('on', '1', 'true'):
54
- val = True
55
- elif arg in ('off', '0', 'false'):
56
- val = False
57
- else:
58
- val = not mman.auto_magic
59
- mman.auto_magic = val
60
- print('\n' + self.shell.magics_manager.auto_status())
61
-
62
- @skip_doctest
63
- @line_magic
64
- def autocall(self, parameter_s=''):
65
- """Make functions callable without having to type parentheses.
66
-
67
- Usage:
68
-
69
- %autocall [mode]
70
-
71
- The mode can be one of: 0->Off, 1->Smart, 2->Full. If not given, the
72
- value is toggled on and off (remembering the previous state).
73
-
74
- In more detail, these values mean:
75
-
76
- 0 -> fully disabled
77
-
78
- 1 -> active, but do not apply if there are no arguments on the line.
79
-
80
- In this mode, you get::
81
-
82
- In [1]: callable
83
- Out[1]: <built-in function callable>
84
-
85
- In [2]: callable 'hello'
86
- ------> callable('hello')
87
- Out[2]: False
88
-
89
- 2 -> Active always. Even if no arguments are present, the callable
90
- object is called::
91
-
92
- In [2]: float
93
- ------> float()
94
- Out[2]: 0.0
95
-
96
- Note that even with autocall off, you can still use '/' at the start of
97
- a line to treat the first argument on the command line as a function
98
- and add parentheses to it::
99
-
100
- In [8]: /str 43
101
- ------> str(43)
102
- Out[8]: '43'
103
-
104
- # all-random (note for auto-testing)
105
- """
106
-
107
- valid_modes = {
108
- 0: "Off",
109
- 1: "Smart",
110
- 2: "Full",
111
- }
112
-
113
- def errorMessage() -> str:
114
- error = "Valid modes: "
115
- for k, v in valid_modes.items():
116
- error += str(k) + "->" + v + ", "
117
- error = error[:-2] # remove tailing `, ` after last element
118
- return error
119
-
120
- if parameter_s:
121
- if not parameter_s in map(str, valid_modes.keys()):
122
- error(errorMessage())
123
- return
124
- arg = int(parameter_s)
125
- else:
126
- arg = 'toggle'
127
-
128
- if not arg in (*list(valid_modes.keys()), "toggle"):
129
- error(errorMessage())
130
- return
131
-
132
- if arg in (valid_modes.keys()):
133
- self.shell.autocall = arg
134
- else: # toggle
135
- if self.shell.autocall:
136
- self._magic_state.autocall_save = self.shell.autocall
137
- self.shell.autocall = 0
138
- else:
139
- try:
140
- self.shell.autocall = self._magic_state.autocall_save
141
- except AttributeError:
142
- self.shell.autocall = self._magic_state.autocall_save = 1
143
-
144
- print("Automatic calling is:", list(valid_modes.values())[self.shell.autocall])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/basic.py DELETED
@@ -1,666 +0,0 @@
1
- """Implementation of basic magic functions."""
2
-
3
-
4
- from logging import error
5
- import io
6
- import os
7
- from pprint import pformat
8
- import sys
9
- from warnings import warn
10
-
11
- from traitlets.utils.importstring import import_item
12
- from IPython.core import magic_arguments, page
13
- from IPython.core.error import UsageError
14
- from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
15
- from IPython.utils.text import format_screen, dedent, indent
16
- from IPython.testing.skipdoctest import skip_doctest
17
- from IPython.utils.ipstruct import Struct
18
-
19
-
20
- class MagicsDisplay(object):
21
- def __init__(self, magics_manager, ignore=None):
22
- self.ignore = ignore if ignore else []
23
- self.magics_manager = magics_manager
24
-
25
- def _lsmagic(self):
26
- """The main implementation of the %lsmagic"""
27
- mesc = magic_escapes['line']
28
- cesc = magic_escapes['cell']
29
- mman = self.magics_manager
30
- magics = mman.lsmagic()
31
- out = ['Available line magics:',
32
- mesc + (' '+mesc).join(sorted([m for m,v in magics['line'].items() if (v not in self.ignore)])),
33
- '',
34
- 'Available cell magics:',
35
- cesc + (' '+cesc).join(sorted([m for m,v in magics['cell'].items() if (v not in self.ignore)])),
36
- '',
37
- mman.auto_status()]
38
- return '\n'.join(out)
39
-
40
- def _repr_pretty_(self, p, cycle):
41
- p.text(self._lsmagic())
42
-
43
- def __repr__(self):
44
- return self.__str__()
45
-
46
- def __str__(self):
47
- return self._lsmagic()
48
-
49
- def _jsonable(self):
50
- """turn magics dict into jsonable dict of the same structure
51
-
52
- replaces object instances with their class names as strings
53
- """
54
- magic_dict = {}
55
- mman = self.magics_manager
56
- magics = mman.lsmagic()
57
- for key, subdict in magics.items():
58
- d = {}
59
- magic_dict[key] = d
60
- for name, obj in subdict.items():
61
- try:
62
- classname = obj.__self__.__class__.__name__
63
- except AttributeError:
64
- classname = 'Other'
65
-
66
- d[name] = classname
67
- return magic_dict
68
-
69
- def _repr_json_(self):
70
- return self._jsonable()
71
-
72
-
73
- @magics_class
74
- class BasicMagics(Magics):
75
- """Magics that provide central IPython functionality.
76
-
77
- These are various magics that don't fit into specific categories but that
78
- are all part of the base 'IPython experience'."""
79
-
80
- @skip_doctest
81
- @magic_arguments.magic_arguments()
82
- @magic_arguments.argument(
83
- '-l', '--line', action='store_true',
84
- help="""Create a line magic alias."""
85
- )
86
- @magic_arguments.argument(
87
- '-c', '--cell', action='store_true',
88
- help="""Create a cell magic alias."""
89
- )
90
- @magic_arguments.argument(
91
- 'name',
92
- help="""Name of the magic to be created."""
93
- )
94
- @magic_arguments.argument(
95
- 'target',
96
- help="""Name of the existing line or cell magic."""
97
- )
98
- @magic_arguments.argument(
99
- '-p', '--params', default=None,
100
- help="""Parameters passed to the magic function."""
101
- )
102
- @line_magic
103
- def alias_magic(self, line=''):
104
- """Create an alias for an existing line or cell magic.
105
-
106
- Examples
107
- --------
108
- ::
109
-
110
- In [1]: %alias_magic t timeit
111
- Created `%t` as an alias for `%timeit`.
112
- Created `%%t` as an alias for `%%timeit`.
113
-
114
- In [2]: %t -n1 pass
115
- 107 ns ± 43.6 ns per loop (mean ± std. dev. of 7 runs, 1 loop each)
116
-
117
- In [3]: %%t -n1
118
- ...: pass
119
- ...:
120
- 107 ns ± 58.3 ns per loop (mean ± std. dev. of 7 runs, 1 loop each)
121
-
122
- In [4]: %alias_magic --cell whereami pwd
123
- UsageError: Cell magic function `%%pwd` not found.
124
- In [5]: %alias_magic --line whereami pwd
125
- Created `%whereami` as an alias for `%pwd`.
126
-
127
- In [6]: %whereami
128
- Out[6]: '/home/testuser'
129
-
130
- In [7]: %alias_magic h history -p "-l 30" --line
131
- Created `%h` as an alias for `%history -l 30`.
132
- """
133
-
134
- args = magic_arguments.parse_argstring(self.alias_magic, line)
135
- shell = self.shell
136
- mman = self.shell.magics_manager
137
- escs = ''.join(magic_escapes.values())
138
-
139
- target = args.target.lstrip(escs)
140
- name = args.name.lstrip(escs)
141
-
142
- params = args.params
143
- if (params and
144
- ((params.startswith('"') and params.endswith('"'))
145
- or (params.startswith("'") and params.endswith("'")))):
146
- params = params[1:-1]
147
-
148
- # Find the requested magics.
149
- m_line = shell.find_magic(target, 'line')
150
- m_cell = shell.find_magic(target, 'cell')
151
- if args.line and m_line is None:
152
- raise UsageError('Line magic function `%s%s` not found.' %
153
- (magic_escapes['line'], target))
154
- if args.cell and m_cell is None:
155
- raise UsageError('Cell magic function `%s%s` not found.' %
156
- (magic_escapes['cell'], target))
157
-
158
- # If --line and --cell are not specified, default to the ones
159
- # that are available.
160
- if not args.line and not args.cell:
161
- if not m_line and not m_cell:
162
- raise UsageError(
163
- 'No line or cell magic with name `%s` found.' % target
164
- )
165
- args.line = bool(m_line)
166
- args.cell = bool(m_cell)
167
-
168
- params_str = "" if params is None else " " + params
169
-
170
- if args.line:
171
- mman.register_alias(name, target, 'line', params)
172
- print('Created `%s%s` as an alias for `%s%s%s`.' % (
173
- magic_escapes['line'], name,
174
- magic_escapes['line'], target, params_str))
175
-
176
- if args.cell:
177
- mman.register_alias(name, target, 'cell', params)
178
- print('Created `%s%s` as an alias for `%s%s%s`.' % (
179
- magic_escapes['cell'], name,
180
- magic_escapes['cell'], target, params_str))
181
-
182
- @line_magic
183
- def lsmagic(self, parameter_s=''):
184
- """List currently available magic functions."""
185
- return MagicsDisplay(self.shell.magics_manager, ignore=[])
186
-
187
- def _magic_docs(self, brief=False, rest=False):
188
- """Return docstrings from magic functions."""
189
- mman = self.shell.magics_manager
190
- docs = mman.lsmagic_docs(brief, missing='No documentation')
191
-
192
- if rest:
193
- format_string = '**%s%s**::\n\n%s\n\n'
194
- else:
195
- format_string = '%s%s:\n%s\n'
196
-
197
- return ''.join(
198
- [format_string % (magic_escapes['line'], fname,
199
- indent(dedent(fndoc)))
200
- for fname, fndoc in sorted(docs['line'].items())]
201
- +
202
- [format_string % (magic_escapes['cell'], fname,
203
- indent(dedent(fndoc)))
204
- for fname, fndoc in sorted(docs['cell'].items())]
205
- )
206
-
207
- @line_magic
208
- def magic(self, parameter_s=''):
209
- """Print information about the magic function system.
210
-
211
- Supported formats: -latex, -brief, -rest
212
- """
213
-
214
- mode = ''
215
- try:
216
- mode = parameter_s.split()[0][1:]
217
- except IndexError:
218
- pass
219
-
220
- brief = (mode == 'brief')
221
- rest = (mode == 'rest')
222
- magic_docs = self._magic_docs(brief, rest)
223
-
224
- if mode == 'latex':
225
- print(self.format_latex(magic_docs))
226
- return
227
- else:
228
- magic_docs = format_screen(magic_docs)
229
-
230
- out = ["""
231
- IPython's 'magic' functions
232
- ===========================
233
-
234
- The magic function system provides a series of functions which allow you to
235
- control the behavior of IPython itself, plus a lot of system-type
236
- features. There are two kinds of magics, line-oriented and cell-oriented.
237
-
238
- Line magics are prefixed with the % character and work much like OS
239
- command-line calls: they get as an argument the rest of the line, where
240
- arguments are passed without parentheses or quotes. For example, this will
241
- time the given statement::
242
-
243
- %timeit range(1000)
244
-
245
- Cell magics are prefixed with a double %%, and they are functions that get as
246
- an argument not only the rest of the line, but also the lines below it in a
247
- separate argument. These magics are called with two arguments: the rest of the
248
- call line and the body of the cell, consisting of the lines below the first.
249
- For example::
250
-
251
- %%timeit x = numpy.random.randn((100, 100))
252
- numpy.linalg.svd(x)
253
-
254
- will time the execution of the numpy svd routine, running the assignment of x
255
- as part of the setup phase, which is not timed.
256
-
257
- In a line-oriented client (the terminal or Qt console IPython), starting a new
258
- input with %% will automatically enter cell mode, and IPython will continue
259
- reading input until a blank line is given. In the notebook, simply type the
260
- whole cell as one entity, but keep in mind that the %% escape can only be at
261
- the very start of the cell.
262
-
263
- NOTE: If you have 'automagic' enabled (via the command line option or with the
264
- %automagic function), you don't need to type in the % explicitly for line
265
- magics; cell magics always require an explicit '%%' escape. By default,
266
- IPython ships with automagic on, so you should only rarely need the % escape.
267
-
268
- Example: typing '%cd mydir' (without the quotes) changes your working directory
269
- to 'mydir', if it exists.
270
-
271
- For a list of the available magic functions, use %lsmagic. For a description
272
- of any of them, type %magic_name?, e.g. '%cd?'.
273
-
274
- Currently the magic system has the following functions:""",
275
- magic_docs,
276
- "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
277
- str(self.lsmagic()),
278
- ]
279
- page.page('\n'.join(out))
280
-
281
-
282
- @line_magic
283
- def page(self, parameter_s=''):
284
- """Pretty print the object and display it through a pager.
285
-
286
- %page [options] OBJECT
287
-
288
- If no object is given, use _ (last output).
289
-
290
- Options:
291
-
292
- -r: page str(object), don't pretty-print it."""
293
-
294
- # After a function contributed by Olivier Aubert, slightly modified.
295
-
296
- # Process options/args
297
- opts, args = self.parse_options(parameter_s, 'r')
298
- raw = 'r' in opts
299
-
300
- oname = args and args or '_'
301
- info = self.shell._ofind(oname)
302
- if info.found:
303
- if raw:
304
- txt = str(info.obj)
305
- else:
306
- txt = pformat(info.obj)
307
- page.page(txt)
308
- else:
309
- print('Object `%s` not found' % oname)
310
-
311
- @line_magic
312
- def pprint(self, parameter_s=''):
313
- """Toggle pretty printing on/off."""
314
- ptformatter = self.shell.display_formatter.formatters['text/plain']
315
- ptformatter.pprint = bool(1 - ptformatter.pprint)
316
- print('Pretty printing has been turned',
317
- ['OFF','ON'][ptformatter.pprint])
318
-
319
- @line_magic
320
- def colors(self, parameter_s=''):
321
- """Switch color scheme for prompts, info system and exception handlers.
322
-
323
- Currently implemented schemes: NoColor, Linux, LightBG.
324
-
325
- Color scheme names are not case-sensitive.
326
-
327
- Examples
328
- --------
329
- To get a plain black and white terminal::
330
-
331
- %colors nocolor
332
- """
333
- def color_switch_err(name):
334
- warn('Error changing %s color schemes.\n%s' %
335
- (name, sys.exc_info()[1]), stacklevel=2)
336
-
337
-
338
- new_scheme = parameter_s.strip()
339
- if not new_scheme:
340
- raise UsageError(
341
- "%colors: you must specify a color scheme. See '%colors?'")
342
- # local shortcut
343
- shell = self.shell
344
-
345
- # Set shell colour scheme
346
- try:
347
- shell.colors = new_scheme
348
- shell.refresh_style()
349
- except:
350
- color_switch_err('shell')
351
-
352
- # Set exception colors
353
- try:
354
- shell.InteractiveTB.set_colors(scheme = new_scheme)
355
- shell.SyntaxTB.set_colors(scheme = new_scheme)
356
- except:
357
- color_switch_err('exception')
358
-
359
- # Set info (for 'object?') colors
360
- if shell.color_info:
361
- try:
362
- shell.inspector.set_active_scheme(new_scheme)
363
- except:
364
- color_switch_err('object inspector')
365
- else:
366
- shell.inspector.set_active_scheme('NoColor')
367
-
368
- @line_magic
369
- def xmode(self, parameter_s=''):
370
- """Switch modes for the exception handlers.
371
-
372
- Valid modes: Plain, Context, Verbose, and Minimal.
373
-
374
- If called without arguments, acts as a toggle.
375
-
376
- When in verbose mode the value `--show` (and `--hide`)
377
- will respectively show (or hide) frames with ``__tracebackhide__ =
378
- True`` value set.
379
- """
380
-
381
- def xmode_switch_err(name):
382
- warn('Error changing %s exception modes.\n%s' %
383
- (name,sys.exc_info()[1]))
384
-
385
- shell = self.shell
386
- if parameter_s.strip() == "--show":
387
- shell.InteractiveTB.skip_hidden = False
388
- return
389
- if parameter_s.strip() == "--hide":
390
- shell.InteractiveTB.skip_hidden = True
391
- return
392
-
393
- new_mode = parameter_s.strip().capitalize()
394
- try:
395
- shell.InteractiveTB.set_mode(mode=new_mode)
396
- print('Exception reporting mode:',shell.InteractiveTB.mode)
397
- except:
398
- xmode_switch_err('user')
399
-
400
- @line_magic
401
- def quickref(self, arg):
402
- """ Show a quick reference sheet """
403
- from IPython.core.usage import quick_reference
404
- qr = quick_reference + self._magic_docs(brief=True)
405
- page.page(qr)
406
-
407
- @line_magic
408
- def doctest_mode(self, parameter_s=''):
409
- """Toggle doctest mode on and off.
410
-
411
- This mode is intended to make IPython behave as much as possible like a
412
- plain Python shell, from the perspective of how its prompts, exceptions
413
- and output look. This makes it easy to copy and paste parts of a
414
- session into doctests. It does so by:
415
-
416
- - Changing the prompts to the classic ``>>>`` ones.
417
- - Changing the exception reporting mode to 'Plain'.
418
- - Disabling pretty-printing of output.
419
-
420
- Note that IPython also supports the pasting of code snippets that have
421
- leading '>>>' and '...' prompts in them. This means that you can paste
422
- doctests from files or docstrings (even if they have leading
423
- whitespace), and the code will execute correctly. You can then use
424
- '%history -t' to see the translated history; this will give you the
425
- input after removal of all the leading prompts and whitespace, which
426
- can be pasted back into an editor.
427
-
428
- With these features, you can switch into this mode easily whenever you
429
- need to do testing and changes to doctests, without having to leave
430
- your existing IPython session.
431
- """
432
-
433
- # Shorthands
434
- shell = self.shell
435
- meta = shell.meta
436
- disp_formatter = self.shell.display_formatter
437
- ptformatter = disp_formatter.formatters['text/plain']
438
- # dstore is a data store kept in the instance metadata bag to track any
439
- # changes we make, so we can undo them later.
440
- dstore = meta.setdefault('doctest_mode',Struct())
441
- save_dstore = dstore.setdefault
442
-
443
- # save a few values we'll need to recover later
444
- mode = save_dstore('mode',False)
445
- save_dstore('rc_pprint',ptformatter.pprint)
446
- save_dstore('xmode',shell.InteractiveTB.mode)
447
- save_dstore('rc_separate_out',shell.separate_out)
448
- save_dstore('rc_separate_out2',shell.separate_out2)
449
- save_dstore('rc_separate_in',shell.separate_in)
450
- save_dstore('rc_active_types',disp_formatter.active_types)
451
-
452
- if not mode:
453
- # turn on
454
-
455
- # Prompt separators like plain python
456
- shell.separate_in = ''
457
- shell.separate_out = ''
458
- shell.separate_out2 = ''
459
-
460
-
461
- ptformatter.pprint = False
462
- disp_formatter.active_types = ['text/plain']
463
-
464
- shell.run_line_magic("xmode", "Plain")
465
- else:
466
- # turn off
467
- shell.separate_in = dstore.rc_separate_in
468
-
469
- shell.separate_out = dstore.rc_separate_out
470
- shell.separate_out2 = dstore.rc_separate_out2
471
-
472
- ptformatter.pprint = dstore.rc_pprint
473
- disp_formatter.active_types = dstore.rc_active_types
474
-
475
- shell.run_line_magic("xmode", dstore.xmode)
476
-
477
- # mode here is the state before we switch; switch_doctest_mode takes
478
- # the mode we're switching to.
479
- shell.switch_doctest_mode(not mode)
480
-
481
- # Store new mode and inform
482
- dstore.mode = bool(not mode)
483
- mode_label = ['OFF','ON'][dstore.mode]
484
- print('Doctest mode is:', mode_label)
485
-
486
- @line_magic
487
- def gui(self, parameter_s=''):
488
- """Enable or disable IPython GUI event loop integration.
489
-
490
- %gui [GUINAME]
491
-
492
- This magic replaces IPython's threaded shells that were activated
493
- using the (pylab/wthread/etc.) command line flags. GUI toolkits
494
- can now be enabled at runtime and keyboard
495
- interrupts should work without any problems. The following toolkits
496
- are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
497
-
498
- %gui wx # enable wxPython event loop integration
499
- %gui qt # enable PyQt/PySide event loop integration
500
- # with the latest version available.
501
- %gui qt6 # enable PyQt6/PySide6 event loop integration
502
- %gui qt5 # enable PyQt5/PySide2 event loop integration
503
- %gui gtk # enable PyGTK event loop integration
504
- %gui gtk3 # enable Gtk3 event loop integration
505
- %gui gtk4 # enable Gtk4 event loop integration
506
- %gui tk # enable Tk event loop integration
507
- %gui osx # enable Cocoa event loop integration
508
- # (requires %matplotlib 1.1)
509
- %gui # disable all event loop integration
510
-
511
- WARNING: after any of these has been called you can simply create
512
- an application object, but DO NOT start the event loop yourself, as
513
- we have already handled that.
514
- """
515
- opts, arg = self.parse_options(parameter_s, '')
516
- if arg=='': arg = None
517
- try:
518
- return self.shell.enable_gui(arg)
519
- except Exception as e:
520
- # print simple error message, rather than traceback if we can't
521
- # hook up the GUI
522
- error(str(e))
523
-
524
- @skip_doctest
525
- @line_magic
526
- def precision(self, s=''):
527
- """Set floating point precision for pretty printing.
528
-
529
- Can set either integer precision or a format string.
530
-
531
- If numpy has been imported and precision is an int,
532
- numpy display precision will also be set, via ``numpy.set_printoptions``.
533
-
534
- If no argument is given, defaults will be restored.
535
-
536
- Examples
537
- --------
538
- ::
539
-
540
- In [1]: from math import pi
541
-
542
- In [2]: %precision 3
543
- Out[2]: '%.3f'
544
-
545
- In [3]: pi
546
- Out[3]: 3.142
547
-
548
- In [4]: %precision %i
549
- Out[4]: '%i'
550
-
551
- In [5]: pi
552
- Out[5]: 3
553
-
554
- In [6]: %precision %e
555
- Out[6]: '%e'
556
-
557
- In [7]: pi**10
558
- Out[7]: 9.364805e+04
559
-
560
- In [8]: %precision
561
- Out[8]: '%r'
562
-
563
- In [9]: pi**10
564
- Out[9]: 93648.047476082982
565
- """
566
- ptformatter = self.shell.display_formatter.formatters['text/plain']
567
- ptformatter.float_precision = s
568
- return ptformatter.float_format
569
-
570
- @magic_arguments.magic_arguments()
571
- @magic_arguments.argument(
572
- 'filename', type=str,
573
- help='Notebook name or filename'
574
- )
575
- @line_magic
576
- def notebook(self, s):
577
- """Export and convert IPython notebooks.
578
-
579
- This function can export the current IPython history to a notebook file.
580
- For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb".
581
- """
582
- args = magic_arguments.parse_argstring(self.notebook, s)
583
- outfname = os.path.expanduser(args.filename)
584
-
585
- from nbformat import write, v4
586
-
587
- cells = []
588
- hist = list(self.shell.history_manager.get_range())
589
- if(len(hist)<=1):
590
- raise ValueError('History is empty, cannot export')
591
- for session, execution_count, source in hist[:-1]:
592
- cells.append(v4.new_code_cell(
593
- execution_count=execution_count,
594
- source=source
595
- ))
596
- nb = v4.new_notebook(cells=cells)
597
- with io.open(outfname, "w", encoding="utf-8") as f:
598
- write(nb, f, version=4)
599
-
600
- @magics_class
601
- class AsyncMagics(BasicMagics):
602
-
603
- @line_magic
604
- def autoawait(self, parameter_s):
605
- """
606
- Allow to change the status of the autoawait option.
607
-
608
- This allow you to set a specific asynchronous code runner.
609
-
610
- If no value is passed, print the currently used asynchronous integration
611
- and whether it is activated.
612
-
613
- It can take a number of value evaluated in the following order:
614
-
615
- - False/false/off deactivate autoawait integration
616
- - True/true/on activate autoawait integration using configured default
617
- loop
618
- - asyncio/curio/trio activate autoawait integration and use integration
619
- with said library.
620
-
621
- - `sync` turn on the pseudo-sync integration (mostly used for
622
- `IPython.embed()` which does not run IPython with a real eventloop and
623
- deactivate running asynchronous code. Turning on Asynchronous code with
624
- the pseudo sync loop is undefined behavior and may lead IPython to crash.
625
-
626
- If the passed parameter does not match any of the above and is a python
627
- identifier, get said object from user namespace and set it as the
628
- runner, and activate autoawait.
629
-
630
- If the object is a fully qualified object name, attempt to import it and
631
- set it as the runner, and activate autoawait.
632
-
633
- The exact behavior of autoawait is experimental and subject to change
634
- across version of IPython and Python.
635
- """
636
-
637
- param = parameter_s.strip()
638
- d = {True: "on", False: "off"}
639
-
640
- if not param:
641
- print("IPython autoawait is `{}`, and set to use `{}`".format(
642
- d[self.shell.autoawait],
643
- self.shell.loop_runner
644
- ))
645
- return None
646
-
647
- if param.lower() in ('false', 'off'):
648
- self.shell.autoawait = False
649
- return None
650
- if param.lower() in ('true', 'on'):
651
- self.shell.autoawait = True
652
- return None
653
-
654
- if param in self.shell.loop_runner_map:
655
- self.shell.loop_runner, self.shell.autoawait = self.shell.loop_runner_map[param]
656
- return None
657
-
658
- if param in self.shell.user_ns :
659
- self.shell.loop_runner = self.shell.user_ns[param]
660
- self.shell.autoawait = True
661
- return None
662
-
663
- runner = import_item(param)
664
-
665
- self.shell.loop_runner = runner
666
- self.shell.autoawait = True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/code.py DELETED
@@ -1,757 +0,0 @@
1
- """Implementation of code management magic functions.
2
- """
3
- #-----------------------------------------------------------------------------
4
- # Copyright (c) 2012 The IPython Development Team.
5
- #
6
- # Distributed under the terms of the Modified BSD License.
7
- #
8
- # The full license is in the file COPYING.txt, distributed with this software.
9
- #-----------------------------------------------------------------------------
10
-
11
- #-----------------------------------------------------------------------------
12
- # Imports
13
- #-----------------------------------------------------------------------------
14
-
15
- # Stdlib
16
- import inspect
17
- import io
18
- import os
19
- import re
20
- import sys
21
- import ast
22
- from itertools import chain
23
- from urllib.request import Request, urlopen
24
- from urllib.parse import urlencode
25
- from pathlib import Path
26
-
27
- # Our own packages
28
- from IPython.core.error import TryNext, StdinNotImplementedError, UsageError
29
- from IPython.core.macro import Macro
30
- from IPython.core.magic import Magics, magics_class, line_magic
31
- from IPython.core.oinspect import find_file, find_source_lines
32
- from IPython.core.release import version
33
- from IPython.testing.skipdoctest import skip_doctest
34
- from IPython.utils.contexts import preserve_keys
35
- from IPython.utils.path import get_py_filename
36
- from warnings import warn
37
- from logging import error
38
- from IPython.utils.text import get_text_list
39
-
40
- #-----------------------------------------------------------------------------
41
- # Magic implementation classes
42
- #-----------------------------------------------------------------------------
43
-
44
- # Used for exception handling in magic_edit
45
- class MacroToEdit(ValueError): pass
46
-
47
- ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$")
48
-
49
- # To match, e.g. 8-10 1:5 :10 3-
50
- range_re = re.compile(r"""
51
- (?P<start>\d+)?
52
- ((?P<sep>[\-:])
53
- (?P<end>\d+)?)?
54
- $""", re.VERBOSE)
55
-
56
-
57
- def extract_code_ranges(ranges_str):
58
- """Turn a string of range for %%load into 2-tuples of (start, stop)
59
- ready to use as a slice of the content split by lines.
60
-
61
- Examples
62
- --------
63
- list(extract_input_ranges("5-10 2"))
64
- [(4, 10), (1, 2)]
65
- """
66
- for range_str in ranges_str.split():
67
- rmatch = range_re.match(range_str)
68
- if not rmatch:
69
- continue
70
- sep = rmatch.group("sep")
71
- start = rmatch.group("start")
72
- end = rmatch.group("end")
73
-
74
- if sep == '-':
75
- start = int(start) - 1 if start else None
76
- end = int(end) if end else None
77
- elif sep == ':':
78
- start = int(start) - 1 if start else None
79
- end = int(end) - 1 if end else None
80
- else:
81
- end = int(start)
82
- start = int(start) - 1
83
- yield (start, end)
84
-
85
-
86
- def extract_symbols(code, symbols):
87
- """
88
- Return a tuple (blocks, not_found)
89
- where ``blocks`` is a list of code fragments
90
- for each symbol parsed from code, and ``not_found`` are
91
- symbols not found in the code.
92
-
93
- For example::
94
-
95
- In [1]: code = '''a = 10
96
- ...: def b(): return 42
97
- ...: class A: pass'''
98
-
99
- In [2]: extract_symbols(code, 'A,b,z')
100
- Out[2]: (['class A: pass\\n', 'def b(): return 42\\n'], ['z'])
101
- """
102
- symbols = symbols.split(',')
103
-
104
- # this will raise SyntaxError if code isn't valid Python
105
- py_code = ast.parse(code)
106
-
107
- marks = [(getattr(s, 'name', None), s.lineno) for s in py_code.body]
108
- code = code.split('\n')
109
-
110
- symbols_lines = {}
111
-
112
- # we already know the start_lineno of each symbol (marks).
113
- # To find each end_lineno, we traverse in reverse order until each
114
- # non-blank line
115
- end = len(code)
116
- for name, start in reversed(marks):
117
- while not code[end - 1].strip():
118
- end -= 1
119
- if name:
120
- symbols_lines[name] = (start - 1, end)
121
- end = start - 1
122
-
123
- # Now symbols_lines is a map
124
- # {'symbol_name': (start_lineno, end_lineno), ...}
125
-
126
- # fill a list with chunks of codes for each requested symbol
127
- blocks = []
128
- not_found = []
129
- for symbol in symbols:
130
- if symbol in symbols_lines:
131
- start, end = symbols_lines[symbol]
132
- blocks.append('\n'.join(code[start:end]) + '\n')
133
- else:
134
- not_found.append(symbol)
135
-
136
- return blocks, not_found
137
-
138
- def strip_initial_indent(lines):
139
- """For %load, strip indent from lines until finding an unindented line.
140
-
141
- https://github.com/ipython/ipython/issues/9775
142
- """
143
- indent_re = re.compile(r'\s+')
144
-
145
- it = iter(lines)
146
- first_line = next(it)
147
- indent_match = indent_re.match(first_line)
148
-
149
- if indent_match:
150
- # First line was indented
151
- indent = indent_match.group()
152
- yield first_line[len(indent):]
153
-
154
- for line in it:
155
- if line.startswith(indent):
156
- yield line[len(indent) :]
157
- elif line in ("\n", "\r\n") or len(line) == 0:
158
- yield line
159
- else:
160
- # Less indented than the first line - stop dedenting
161
- yield line
162
- break
163
- else:
164
- yield first_line
165
-
166
- # Pass the remaining lines through without dedenting
167
- for line in it:
168
- yield line
169
-
170
-
171
- class InteractivelyDefined(Exception):
172
- """Exception for interactively defined variable in magic_edit"""
173
- def __init__(self, index):
174
- self.index = index
175
-
176
-
177
- @magics_class
178
- class CodeMagics(Magics):
179
- """Magics related to code management (loading, saving, editing, ...)."""
180
-
181
- def __init__(self, *args, **kwargs):
182
- self._knowntemps = set()
183
- super(CodeMagics, self).__init__(*args, **kwargs)
184
-
185
- @line_magic
186
- def save(self, parameter_s=''):
187
- """Save a set of lines or a macro to a given filename.
188
-
189
- Usage:\\
190
- %save [options] filename [history]
191
-
192
- Options:
193
-
194
- -r: use 'raw' input. By default, the 'processed' history is used,
195
- so that magics are loaded in their transformed version to valid
196
- Python. If this option is given, the raw input as typed as the
197
- command line is used instead.
198
-
199
- -f: force overwrite. If file exists, %save will prompt for overwrite
200
- unless -f is given.
201
-
202
- -a: append to the file instead of overwriting it.
203
-
204
- The history argument uses the same syntax as %history for input ranges,
205
- then saves the lines to the filename you specify.
206
-
207
- If no ranges are specified, saves history of the current session up to
208
- this point.
209
-
210
- It adds a '.py' extension to the file if you don't do so yourself, and
211
- it asks for confirmation before overwriting existing files.
212
-
213
- If `-r` option is used, the default extension is `.ipy`.
214
- """
215
-
216
- opts,args = self.parse_options(parameter_s,'fra',mode='list')
217
- if not args:
218
- raise UsageError('Missing filename.')
219
- raw = 'r' in opts
220
- force = 'f' in opts
221
- append = 'a' in opts
222
- mode = 'a' if append else 'w'
223
- ext = '.ipy' if raw else '.py'
224
- fname, codefrom = args[0], " ".join(args[1:])
225
- if not fname.endswith(('.py','.ipy')):
226
- fname += ext
227
- fname = os.path.expanduser(fname)
228
- file_exists = os.path.isfile(fname)
229
- if file_exists and not force and not append:
230
- try:
231
- overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
232
- except StdinNotImplementedError:
233
- print("File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s))
234
- return
235
- if not overwrite :
236
- print('Operation cancelled.')
237
- return
238
- try:
239
- cmds = self.shell.find_user_code(codefrom,raw)
240
- except (TypeError, ValueError) as e:
241
- print(e.args[0])
242
- return
243
- with io.open(fname, mode, encoding="utf-8") as f:
244
- if not file_exists or not append:
245
- f.write("# coding: utf-8\n")
246
- f.write(cmds)
247
- # make sure we end on a newline
248
- if not cmds.endswith('\n'):
249
- f.write('\n')
250
- print('The following commands were written to file `%s`:' % fname)
251
- print(cmds)
252
-
253
- @line_magic
254
- def pastebin(self, parameter_s=''):
255
- """Upload code to dpaste.com, returning the URL.
256
-
257
- Usage:\\
258
- %pastebin [-d "Custom description"][-e 24] 1-7
259
-
260
- The argument can be an input history range, a filename, or the name of a
261
- string or macro.
262
-
263
- If no arguments are given, uploads the history of this session up to
264
- this point.
265
-
266
- Options:
267
-
268
- -d: Pass a custom description. The default will say
269
- "Pasted from IPython".
270
- -e: Pass number of days for the link to be expired.
271
- The default will be 7 days.
272
- """
273
- opts, args = self.parse_options(parameter_s, "d:e:")
274
-
275
- try:
276
- code = self.shell.find_user_code(args)
277
- except (ValueError, TypeError) as e:
278
- print(e.args[0])
279
- return
280
-
281
- expiry_days = 7
282
- try:
283
- expiry_days = int(opts.get("e", 7))
284
- except ValueError as e:
285
- print(e.args[0].capitalize())
286
- return
287
- if expiry_days < 1 or expiry_days > 365:
288
- print("Expiry days should be in range of 1 to 365")
289
- return
290
-
291
- post_data = urlencode(
292
- {
293
- "title": opts.get("d", "Pasted from IPython"),
294
- "syntax": "python",
295
- "content": code,
296
- "expiry_days": expiry_days,
297
- }
298
- ).encode("utf-8")
299
-
300
- request = Request(
301
- "https://dpaste.com/api/v2/",
302
- headers={"User-Agent": "IPython v{}".format(version)},
303
- )
304
- response = urlopen(request, post_data)
305
- return response.headers.get('Location')
306
-
307
- @line_magic
308
- def loadpy(self, arg_s):
309
- """Alias of `%load`
310
-
311
- `%loadpy` has gained some flexibility and dropped the requirement of a `.py`
312
- extension. So it has been renamed simply into %load. You can look at
313
- `%load`'s docstring for more info.
314
- """
315
- self.load(arg_s)
316
-
317
- @line_magic
318
- def load(self, arg_s):
319
- """Load code into the current frontend.
320
-
321
- Usage:\\
322
- %load [options] source
323
-
324
- where source can be a filename, URL, input history range, macro, or
325
- element in the user namespace
326
-
327
- If no arguments are given, loads the history of this session up to this
328
- point.
329
-
330
- Options:
331
-
332
- -r <lines>: Specify lines or ranges of lines to load from the source.
333
- Ranges could be specified as x-y (x..y) or in python-style x:y
334
- (x..(y-1)). Both limits x and y can be left blank (meaning the
335
- beginning and end of the file, respectively).
336
-
337
- -s <symbols>: Specify function or classes to load from python source.
338
-
339
- -y : Don't ask confirmation for loading source above 200 000 characters.
340
-
341
- -n : Include the user's namespace when searching for source code.
342
-
343
- This magic command can either take a local filename, a URL, an history
344
- range (see %history) or a macro as argument, it will prompt for
345
- confirmation before loading source with more than 200 000 characters, unless
346
- -y flag is passed or if the frontend does not support raw_input::
347
-
348
- %load
349
- %load myscript.py
350
- %load 7-27
351
- %load myMacro
352
- %load http://www.example.com/myscript.py
353
- %load -r 5-10 myscript.py
354
- %load -r 10-20,30,40: foo.py
355
- %load -s MyClass,wonder_function myscript.py
356
- %load -n MyClass
357
- %load -n my_module.wonder_function
358
- """
359
- opts,args = self.parse_options(arg_s,'yns:r:')
360
- search_ns = 'n' in opts
361
- contents = self.shell.find_user_code(args, search_ns=search_ns)
362
-
363
- if 's' in opts:
364
- try:
365
- blocks, not_found = extract_symbols(contents, opts['s'])
366
- except SyntaxError:
367
- # non python code
368
- error("Unable to parse the input as valid Python code")
369
- return
370
-
371
- if len(not_found) == 1:
372
- warn('The symbol `%s` was not found' % not_found[0])
373
- elif len(not_found) > 1:
374
- warn('The symbols %s were not found' % get_text_list(not_found,
375
- wrap_item_with='`')
376
- )
377
-
378
- contents = '\n'.join(blocks)
379
-
380
- if 'r' in opts:
381
- ranges = opts['r'].replace(',', ' ')
382
- lines = contents.split('\n')
383
- slices = extract_code_ranges(ranges)
384
- contents = [lines[slice(*slc)] for slc in slices]
385
- contents = '\n'.join(strip_initial_indent(chain.from_iterable(contents)))
386
-
387
- l = len(contents)
388
-
389
- # 200 000 is ~ 2500 full 80 character lines
390
- # so in average, more than 5000 lines
391
- if l > 200000 and 'y' not in opts:
392
- try:
393
- ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
394
- " (%d characters). Continue (y/[N]) ?" % l), default='n' )
395
- except StdinNotImplementedError:
396
- #assume yes if raw input not implemented
397
- ans = True
398
-
399
- if ans is False :
400
- print('Operation cancelled.')
401
- return
402
-
403
- contents = "# %load {}\n".format(arg_s) + contents
404
-
405
- self.shell.set_next_input(contents, replace=True)
406
-
407
- @staticmethod
408
- def _find_edit_target(shell, args, opts, last_call):
409
- """Utility method used by magic_edit to find what to edit."""
410
-
411
- def make_filename(arg):
412
- "Make a filename from the given args"
413
- try:
414
- filename = get_py_filename(arg)
415
- except IOError:
416
- # If it ends with .py but doesn't already exist, assume we want
417
- # a new file.
418
- if arg.endswith('.py'):
419
- filename = arg
420
- else:
421
- filename = None
422
- return filename
423
-
424
- # Set a few locals from the options for convenience:
425
- opts_prev = 'p' in opts
426
- opts_raw = 'r' in opts
427
-
428
- # custom exceptions
429
- class DataIsObject(Exception): pass
430
-
431
- # Default line number value
432
- lineno = opts.get('n',None)
433
-
434
- if opts_prev:
435
- args = '_%s' % last_call[0]
436
- if args not in shell.user_ns:
437
- args = last_call[1]
438
-
439
- # by default this is done with temp files, except when the given
440
- # arg is a filename
441
- use_temp = True
442
-
443
- data = ''
444
-
445
- # First, see if the arguments should be a filename.
446
- filename = make_filename(args)
447
- if filename:
448
- use_temp = False
449
- elif args:
450
- # Mode where user specifies ranges of lines, like in %macro.
451
- data = shell.extract_input_lines(args, opts_raw)
452
- if not data:
453
- try:
454
- # Load the parameter given as a variable. If not a string,
455
- # process it as an object instead (below)
456
-
457
- # print('*** args',args,'type',type(args)) # dbg
458
- data = eval(args, shell.user_ns)
459
- if not isinstance(data, str):
460
- raise DataIsObject
461
-
462
- except (NameError,SyntaxError):
463
- # given argument is not a variable, try as a filename
464
- filename = make_filename(args)
465
- if filename is None:
466
- warn("Argument given (%s) can't be found as a variable "
467
- "or as a filename." % args)
468
- return (None, None, None)
469
- use_temp = False
470
-
471
- except DataIsObject as e:
472
- # macros have a special edit function
473
- if isinstance(data, Macro):
474
- raise MacroToEdit(data) from e
475
-
476
- # For objects, try to edit the file where they are defined
477
- filename = find_file(data)
478
- if filename:
479
- if 'fakemodule' in filename.lower() and \
480
- inspect.isclass(data):
481
- # class created by %edit? Try to find source
482
- # by looking for method definitions instead, the
483
- # __module__ in those classes is FakeModule.
484
- attrs = [getattr(data, aname) for aname in dir(data)]
485
- for attr in attrs:
486
- if not inspect.ismethod(attr):
487
- continue
488
- filename = find_file(attr)
489
- if filename and \
490
- 'fakemodule' not in filename.lower():
491
- # change the attribute to be the edit
492
- # target instead
493
- data = attr
494
- break
495
-
496
- m = ipython_input_pat.match(os.path.basename(filename))
497
- if m:
498
- raise InteractivelyDefined(int(m.groups()[0])) from e
499
-
500
- datafile = 1
501
- if filename is None:
502
- filename = make_filename(args)
503
- datafile = 1
504
- if filename is not None:
505
- # only warn about this if we get a real name
506
- warn('Could not find file where `%s` is defined.\n'
507
- 'Opening a file named `%s`' % (args, filename))
508
- # Now, make sure we can actually read the source (if it was
509
- # in a temp file it's gone by now).
510
- if datafile:
511
- if lineno is None:
512
- lineno = find_source_lines(data)
513
- if lineno is None:
514
- filename = make_filename(args)
515
- if filename is None:
516
- warn('The file where `%s` was defined '
517
- 'cannot be read or found.' % data)
518
- return (None, None, None)
519
- use_temp = False
520
-
521
- if use_temp:
522
- filename = shell.mktempfile(data)
523
- print('IPython will make a temporary file named:',filename)
524
-
525
- # use last_call to remember the state of the previous call, but don't
526
- # let it be clobbered by successive '-p' calls.
527
- try:
528
- last_call[0] = shell.displayhook.prompt_count
529
- if not opts_prev:
530
- last_call[1] = args
531
- except:
532
- pass
533
-
534
-
535
- return filename, lineno, use_temp
536
-
537
- def _edit_macro(self,mname,macro):
538
- """open an editor with the macro data in a file"""
539
- filename = self.shell.mktempfile(macro.value)
540
- self.shell.hooks.editor(filename)
541
-
542
- # and make a new macro object, to replace the old one
543
- mvalue = Path(filename).read_text(encoding="utf-8")
544
- self.shell.user_ns[mname] = Macro(mvalue)
545
-
546
- @skip_doctest
547
- @line_magic
548
- def edit(self, parameter_s='',last_call=['','']):
549
- """Bring up an editor and execute the resulting code.
550
-
551
- Usage:
552
- %edit [options] [args]
553
-
554
- %edit runs IPython's editor hook. The default version of this hook is
555
- set to call the editor specified by your $EDITOR environment variable.
556
- If this isn't found, it will default to vi under Linux/Unix and to
557
- notepad under Windows. See the end of this docstring for how to change
558
- the editor hook.
559
-
560
- You can also set the value of this editor via the
561
- ``TerminalInteractiveShell.editor`` option in your configuration file.
562
- This is useful if you wish to use a different editor from your typical
563
- default with IPython (and for Windows users who typically don't set
564
- environment variables).
565
-
566
- This command allows you to conveniently edit multi-line code right in
567
- your IPython session.
568
-
569
- If called without arguments, %edit opens up an empty editor with a
570
- temporary file and will execute the contents of this file when you
571
- close it (don't forget to save it!).
572
-
573
-
574
- Options:
575
-
576
- -n <number>: open the editor at a specified line number. By default,
577
- the IPython editor hook uses the unix syntax 'editor +N filename', but
578
- you can configure this by providing your own modified hook if your
579
- favorite editor supports line-number specifications with a different
580
- syntax.
581
-
582
- -p: this will call the editor with the same data as the previous time
583
- it was used, regardless of how long ago (in your current session) it
584
- was.
585
-
586
- -r: use 'raw' input. This option only applies to input taken from the
587
- user's history. By default, the 'processed' history is used, so that
588
- magics are loaded in their transformed version to valid Python. If
589
- this option is given, the raw input as typed as the command line is
590
- used instead. When you exit the editor, it will be executed by
591
- IPython's own processor.
592
-
593
- -x: do not execute the edited code immediately upon exit. This is
594
- mainly useful if you are editing programs which need to be called with
595
- command line arguments, which you can then do using %run.
596
-
597
-
598
- Arguments:
599
-
600
- If arguments are given, the following possibilities exist:
601
-
602
- - If the argument is a filename, IPython will load that into the
603
- editor. It will execute its contents with execfile() when you exit,
604
- loading any code in the file into your interactive namespace.
605
-
606
- - The arguments are ranges of input history, e.g. "7 ~1/4-6".
607
- The syntax is the same as in the %history magic.
608
-
609
- - If the argument is a string variable, its contents are loaded
610
- into the editor. You can thus edit any string which contains
611
- python code (including the result of previous edits).
612
-
613
- - If the argument is the name of an object (other than a string),
614
- IPython will try to locate the file where it was defined and open the
615
- editor at the point where it is defined. You can use `%edit function`
616
- to load an editor exactly at the point where 'function' is defined,
617
- edit it and have the file be executed automatically.
618
-
619
- - If the object is a macro (see %macro for details), this opens up your
620
- specified editor with a temporary file containing the macro's data.
621
- Upon exit, the macro is reloaded with the contents of the file.
622
-
623
- Note: opening at an exact line is only supported under Unix, and some
624
- editors (like kedit and gedit up to Gnome 2.8) do not understand the
625
- '+NUMBER' parameter necessary for this feature. Good editors like
626
- (X)Emacs, vi, jed, pico and joe all do.
627
-
628
- After executing your code, %edit will return as output the code you
629
- typed in the editor (except when it was an existing file). This way
630
- you can reload the code in further invocations of %edit as a variable,
631
- via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
632
- the output.
633
-
634
- Note that %edit is also available through the alias %ed.
635
-
636
- This is an example of creating a simple function inside the editor and
637
- then modifying it. First, start up the editor::
638
-
639
- In [1]: edit
640
- Editing... done. Executing edited code...
641
- Out[1]: 'def foo():\\n print("foo() was defined in an editing
642
- session")\\n'
643
-
644
- We can then call the function foo()::
645
-
646
- In [2]: foo()
647
- foo() was defined in an editing session
648
-
649
- Now we edit foo. IPython automatically loads the editor with the
650
- (temporary) file where foo() was previously defined::
651
-
652
- In [3]: edit foo
653
- Editing... done. Executing edited code...
654
-
655
- And if we call foo() again we get the modified version::
656
-
657
- In [4]: foo()
658
- foo() has now been changed!
659
-
660
- Here is an example of how to edit a code snippet successive
661
- times. First we call the editor::
662
-
663
- In [5]: edit
664
- Editing... done. Executing edited code...
665
- hello
666
- Out[5]: "print('hello')\\n"
667
-
668
- Now we call it again with the previous output (stored in _)::
669
-
670
- In [6]: edit _
671
- Editing... done. Executing edited code...
672
- hello world
673
- Out[6]: "print('hello world')\\n"
674
-
675
- Now we call it with the output #8 (stored in _8, also as Out[8])::
676
-
677
- In [7]: edit _8
678
- Editing... done. Executing edited code...
679
- hello again
680
- Out[7]: "print('hello again')\\n"
681
-
682
-
683
- Changing the default editor hook:
684
-
685
- If you wish to write your own editor hook, you can put it in a
686
- configuration file which you load at startup time. The default hook
687
- is defined in the IPython.core.hooks module, and you can use that as a
688
- starting example for further modifications. That file also has
689
- general instructions on how to set a new hook for use once you've
690
- defined it."""
691
- opts,args = self.parse_options(parameter_s,'prxn:')
692
-
693
- try:
694
- filename, lineno, is_temp = self._find_edit_target(self.shell,
695
- args, opts, last_call)
696
- except MacroToEdit as e:
697
- self._edit_macro(args, e.args[0])
698
- return
699
- except InteractivelyDefined as e:
700
- print("Editing In[%i]" % e.index)
701
- args = str(e.index)
702
- filename, lineno, is_temp = self._find_edit_target(self.shell,
703
- args, opts, last_call)
704
- if filename is None:
705
- # nothing was found, warnings have already been issued,
706
- # just give up.
707
- return
708
-
709
- if is_temp:
710
- self._knowntemps.add(filename)
711
- elif (filename in self._knowntemps):
712
- is_temp = True
713
-
714
-
715
- # do actual editing here
716
- print('Editing...', end=' ')
717
- sys.stdout.flush()
718
- filepath = Path(filename)
719
- try:
720
- # Quote filenames that may have spaces in them when opening
721
- # the editor
722
- quoted = filename = str(filepath.absolute())
723
- if " " in quoted:
724
- quoted = "'%s'" % quoted
725
- self.shell.hooks.editor(quoted, lineno)
726
- except TryNext:
727
- warn('Could not open editor')
728
- return
729
-
730
- # XXX TODO: should this be generalized for all string vars?
731
- # For now, this is special-cased to blocks created by cpaste
732
- if args.strip() == "pasted_block":
733
- self.shell.user_ns["pasted_block"] = filepath.read_text(encoding="utf-8")
734
-
735
- if 'x' in opts: # -x prevents actual execution
736
- print()
737
- else:
738
- print('done. Executing edited code...')
739
- with preserve_keys(self.shell.user_ns, '__file__'):
740
- if not is_temp:
741
- self.shell.user_ns["__file__"] = filename
742
- if "r" in opts: # Untranslated IPython code
743
- source = filepath.read_text(encoding="utf-8")
744
- self.shell.run_cell(source, store_history=False)
745
- else:
746
- self.shell.safe_execfile(filename, self.shell.user_ns,
747
- self.shell.user_ns)
748
-
749
- if is_temp:
750
- try:
751
- return filepath.read_text(encoding="utf-8")
752
- except IOError as msg:
753
- if Path(msg.filename) == filepath:
754
- warn('File not found. Did you forget to save?')
755
- return
756
- else:
757
- self.shell.showtraceback()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/config.py DELETED
@@ -1,140 +0,0 @@
1
- """Implementation of configuration-related magic functions.
2
- """
3
- #-----------------------------------------------------------------------------
4
- # Copyright (c) 2012 The IPython Development Team.
5
- #
6
- # Distributed under the terms of the Modified BSD License.
7
- #
8
- # The full license is in the file COPYING.txt, distributed with this software.
9
- #-----------------------------------------------------------------------------
10
-
11
- #-----------------------------------------------------------------------------
12
- # Imports
13
- #-----------------------------------------------------------------------------
14
-
15
- # Stdlib
16
- import re
17
-
18
- # Our own packages
19
- from IPython.core.error import UsageError
20
- from IPython.core.magic import Magics, magics_class, line_magic
21
- from logging import error
22
-
23
- #-----------------------------------------------------------------------------
24
- # Magic implementation classes
25
- #-----------------------------------------------------------------------------
26
-
27
- reg = re.compile(r'^\w+\.\w+$')
28
- @magics_class
29
- class ConfigMagics(Magics):
30
-
31
- def __init__(self, shell):
32
- super(ConfigMagics, self).__init__(shell)
33
- self.configurables = []
34
-
35
- @line_magic
36
- def config(self, s):
37
- """configure IPython
38
-
39
- %config Class[.trait=value]
40
-
41
- This magic exposes most of the IPython config system. Any
42
- Configurable class should be able to be configured with the simple
43
- line::
44
-
45
- %config Class.trait=value
46
-
47
- Where `value` will be resolved in the user's namespace, if it is an
48
- expression or variable name.
49
-
50
- Examples
51
- --------
52
-
53
- To see what classes are available for config, pass no arguments::
54
-
55
- In [1]: %config
56
- Available objects for config:
57
- AliasManager
58
- DisplayFormatter
59
- HistoryManager
60
- IPCompleter
61
- LoggingMagics
62
- MagicsManager
63
- OSMagics
64
- PrefilterManager
65
- ScriptMagics
66
- TerminalInteractiveShell
67
-
68
- To view what is configurable on a given class, just pass the class
69
- name::
70
-
71
- In [2]: %config LoggingMagics
72
- LoggingMagics(Magics) options
73
- ---------------------------
74
- LoggingMagics.quiet=<Bool>
75
- Suppress output of log state when logging is enabled
76
- Current: False
77
-
78
- but the real use is in setting values::
79
-
80
- In [3]: %config LoggingMagics.quiet = True
81
-
82
- and these values are read from the user_ns if they are variables::
83
-
84
- In [4]: feeling_quiet=False
85
-
86
- In [5]: %config LoggingMagics.quiet = feeling_quiet
87
-
88
- """
89
- from traitlets.config.loader import Config
90
- # some IPython objects are Configurable, but do not yet have
91
- # any configurable traits. Exclude them from the effects of
92
- # this magic, as their presence is just noise:
93
- configurables = sorted(set([ c for c in self.shell.configurables
94
- if c.__class__.class_traits(config=True)
95
- ]), key=lambda x: x.__class__.__name__)
96
- classnames = [ c.__class__.__name__ for c in configurables ]
97
-
98
- line = s.strip()
99
- if not line:
100
- # print available configurable names
101
- print("Available objects for config:")
102
- for name in classnames:
103
- print(" ", name)
104
- return
105
- elif line in classnames:
106
- # `%config TerminalInteractiveShell` will print trait info for
107
- # TerminalInteractiveShell
108
- c = configurables[classnames.index(line)]
109
- cls = c.__class__
110
- help = cls.class_get_help(c)
111
- # strip leading '--' from cl-args:
112
- help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
113
- print(help)
114
- return
115
- elif reg.match(line):
116
- cls, attr = line.split('.')
117
- return getattr(configurables[classnames.index(cls)],attr)
118
- elif '=' not in line:
119
- msg = "Invalid config statement: %r, "\
120
- "should be `Class.trait = value`."
121
-
122
- ll = line.lower()
123
- for classname in classnames:
124
- if ll == classname.lower():
125
- msg = msg + '\nDid you mean %s (note the case)?' % classname
126
- break
127
-
128
- raise UsageError( msg % line)
129
-
130
- # otherwise, assume we are setting configurables.
131
- # leave quotes on args when splitting, because we want
132
- # unquoted args to eval in user_ns
133
- cfg = Config()
134
- exec("cfg."+line, self.shell.user_ns, locals())
135
-
136
- for configurable in configurables:
137
- try:
138
- configurable.update_config(cfg)
139
- except Exception as e:
140
- error(e)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/display.py DELETED
@@ -1,93 +0,0 @@
1
- """Simple magics for display formats"""
2
- #-----------------------------------------------------------------------------
3
- # Copyright (c) 2012 The IPython Development Team.
4
- #
5
- # Distributed under the terms of the Modified BSD License.
6
- #
7
- # The full license is in the file COPYING.txt, distributed with this software.
8
- #-----------------------------------------------------------------------------
9
-
10
- #-----------------------------------------------------------------------------
11
- # Imports
12
- #-----------------------------------------------------------------------------
13
-
14
- # Our own packages
15
- from IPython.display import display, Javascript, Latex, SVG, HTML, Markdown
16
- from IPython.core.magic import (
17
- Magics, magics_class, cell_magic
18
- )
19
- from IPython.core import magic_arguments
20
-
21
- #-----------------------------------------------------------------------------
22
- # Magic implementation classes
23
- #-----------------------------------------------------------------------------
24
-
25
-
26
- @magics_class
27
- class DisplayMagics(Magics):
28
- """Magics for displaying various output types with literals
29
-
30
- Defines javascript/latex/svg/html cell magics for writing
31
- blocks in those languages, to be rendered in the frontend.
32
- """
33
-
34
- @cell_magic
35
- def js(self, line, cell):
36
- """Run the cell block of Javascript code
37
-
38
- Alias of `%%javascript`
39
-
40
- Starting with IPython 8.0 %%javascript is pending deprecation to be replaced
41
- by a more flexible system
42
-
43
- Please See https://github.com/ipython/ipython/issues/13376
44
- """
45
- self.javascript(line, cell)
46
-
47
- @cell_magic
48
- def javascript(self, line, cell):
49
- """Run the cell block of Javascript code
50
-
51
- Starting with IPython 8.0 %%javascript is pending deprecation to be replaced
52
- by a more flexible system
53
-
54
- Please See https://github.com/ipython/ipython/issues/13376
55
- """
56
- display(Javascript(cell))
57
-
58
-
59
- @cell_magic
60
- def latex(self, line, cell):
61
- """Render the cell as a block of LaTeX
62
-
63
- The subset of LaTeX which is supported depends on the implementation in
64
- the client. In the Jupyter Notebook, this magic only renders the subset
65
- of LaTeX defined by MathJax
66
- [here](https://docs.mathjax.org/en/v2.5-latest/tex.html)."""
67
- display(Latex(cell))
68
-
69
- @cell_magic
70
- def svg(self, line, cell):
71
- """Render the cell as an SVG literal"""
72
- display(SVG(cell))
73
-
74
- @magic_arguments.magic_arguments()
75
- @magic_arguments.argument(
76
- '--isolated', action='store_true', default=False,
77
- help="""Annotate the cell as 'isolated'.
78
- Isolated cells are rendered inside their own <iframe> tag"""
79
- )
80
- @cell_magic
81
- def html(self, line, cell):
82
- """Render the cell as a block of HTML"""
83
- args = magic_arguments.parse_argstring(self.html, line)
84
- html = HTML(cell)
85
- if args.isolated:
86
- display(html, metadata={'text/html':{'isolated':True}})
87
- else:
88
- display(html)
89
-
90
- @cell_magic
91
- def markdown(self, line, cell):
92
- """Render the cell as Markdown text block"""
93
- display(Markdown(cell))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/execution.py DELETED
@@ -1,1624 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """Implementation of execution-related magic functions."""
3
-
4
- # Copyright (c) IPython Development Team.
5
- # Distributed under the terms of the Modified BSD License.
6
-
7
-
8
- import ast
9
- import bdb
10
- import builtins as builtin_mod
11
- import copy
12
- import cProfile as profile
13
- import gc
14
- import itertools
15
- import math
16
- import os
17
- import pstats
18
- import re
19
- import shlex
20
- import sys
21
- import time
22
- import timeit
23
- from typing import Dict, Any
24
- from ast import (
25
- Assign,
26
- Call,
27
- Expr,
28
- Load,
29
- Module,
30
- Name,
31
- NodeTransformer,
32
- Store,
33
- parse,
34
- unparse,
35
- )
36
- from io import StringIO
37
- from logging import error
38
- from pathlib import Path
39
- from pdb import Restart
40
- from textwrap import dedent, indent
41
- from warnings import warn
42
-
43
- from IPython.core import magic_arguments, oinspect, page
44
- from IPython.core.displayhook import DisplayHook
45
- from IPython.core.error import UsageError
46
- from IPython.core.macro import Macro
47
- from IPython.core.magic import (
48
- Magics,
49
- cell_magic,
50
- line_cell_magic,
51
- line_magic,
52
- magics_class,
53
- needs_local_scope,
54
- no_var_expand,
55
- on_off,
56
- output_can_be_silenced,
57
- )
58
- from IPython.testing.skipdoctest import skip_doctest
59
- from IPython.utils.capture import capture_output
60
- from IPython.utils.contexts import preserve_keys
61
- from IPython.utils.ipstruct import Struct
62
- from IPython.utils.module_paths import find_mod
63
- from IPython.utils.path import get_py_filename, shellglob
64
- from IPython.utils.timing import clock, clock2
65
- from IPython.core.magics.ast_mod import ReplaceCodeTransformer
66
-
67
- #-----------------------------------------------------------------------------
68
- # Magic implementation classes
69
- #-----------------------------------------------------------------------------
70
-
71
-
72
- class TimeitResult(object):
73
- """
74
- Object returned by the timeit magic with info about the run.
75
-
76
- Contains the following attributes :
77
-
78
- loops: (int) number of loops done per measurement
79
- repeat: (int) number of times the measurement has been repeated
80
- best: (float) best execution time / number
81
- all_runs: (list of float) execution time of each run (in s)
82
- compile_time: (float) time of statement compilation (s)
83
-
84
- """
85
- def __init__(self, loops, repeat, best, worst, all_runs, compile_time, precision):
86
- self.loops = loops
87
- self.repeat = repeat
88
- self.best = best
89
- self.worst = worst
90
- self.all_runs = all_runs
91
- self.compile_time = compile_time
92
- self._precision = precision
93
- self.timings = [ dt / self.loops for dt in all_runs]
94
-
95
- @property
96
- def average(self):
97
- return math.fsum(self.timings) / len(self.timings)
98
-
99
- @property
100
- def stdev(self):
101
- mean = self.average
102
- return (math.fsum([(x - mean) ** 2 for x in self.timings]) / len(self.timings)) ** 0.5
103
-
104
- def __str__(self):
105
- pm = '+-'
106
- if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
107
- try:
108
- u'\xb1'.encode(sys.stdout.encoding)
109
- pm = u'\xb1'
110
- except:
111
- pass
112
- return "{mean} {pm} {std} per loop (mean {pm} std. dev. of {runs} run{run_plural}, {loops:,} loop{loop_plural} each)".format(
113
- pm=pm,
114
- runs=self.repeat,
115
- loops=self.loops,
116
- loop_plural="" if self.loops == 1 else "s",
117
- run_plural="" if self.repeat == 1 else "s",
118
- mean=_format_time(self.average, self._precision),
119
- std=_format_time(self.stdev, self._precision),
120
- )
121
-
122
- def _repr_pretty_(self, p , cycle):
123
- unic = self.__str__()
124
- p.text(u'<TimeitResult : '+unic+u'>')
125
-
126
-
127
- class TimeitTemplateFiller(ast.NodeTransformer):
128
- """Fill in the AST template for timing execution.
129
-
130
- This is quite closely tied to the template definition, which is in
131
- :meth:`ExecutionMagics.timeit`.
132
- """
133
- def __init__(self, ast_setup, ast_stmt):
134
- self.ast_setup = ast_setup
135
- self.ast_stmt = ast_stmt
136
-
137
- def visit_FunctionDef(self, node):
138
- "Fill in the setup statement"
139
- self.generic_visit(node)
140
- if node.name == "inner":
141
- node.body[:1] = self.ast_setup.body
142
-
143
- return node
144
-
145
- def visit_For(self, node):
146
- "Fill in the statement to be timed"
147
- if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt':
148
- node.body = self.ast_stmt.body
149
- return node
150
-
151
-
152
- class Timer(timeit.Timer):
153
- """Timer class that explicitly uses self.inner
154
-
155
- which is an undocumented implementation detail of CPython,
156
- not shared by PyPy.
157
- """
158
- # Timer.timeit copied from CPython 3.4.2
159
- def timeit(self, number=timeit.default_number):
160
- """Time 'number' executions of the main statement.
161
-
162
- To be precise, this executes the setup statement once, and
163
- then returns the time it takes to execute the main statement
164
- a number of times, as a float measured in seconds. The
165
- argument is the number of times through the loop, defaulting
166
- to one million. The main statement, the setup statement and
167
- the timer function to be used are passed to the constructor.
168
- """
169
- it = itertools.repeat(None, number)
170
- gcold = gc.isenabled()
171
- gc.disable()
172
- try:
173
- timing = self.inner(it, self.timer)
174
- finally:
175
- if gcold:
176
- gc.enable()
177
- return timing
178
-
179
-
180
- @magics_class
181
- class ExecutionMagics(Magics):
182
- """Magics related to code execution, debugging, profiling, etc."""
183
-
184
- _transformers: Dict[str, Any] = {}
185
-
186
- def __init__(self, shell):
187
- super(ExecutionMagics, self).__init__(shell)
188
- # Default execution function used to actually run user code.
189
- self.default_runner = None
190
-
191
- @skip_doctest
192
- @no_var_expand
193
- @line_cell_magic
194
- def prun(self, parameter_s='', cell=None):
195
-
196
- """Run a statement through the python code profiler.
197
-
198
- **Usage, in line mode:**
199
-
200
- %prun [options] statement
201
-
202
- **Usage, in cell mode:**
203
-
204
- %%prun [options] [statement]
205
-
206
- code...
207
-
208
- code...
209
-
210
- In cell mode, the additional code lines are appended to the (possibly
211
- empty) statement in the first line. Cell mode allows you to easily
212
- profile multiline blocks without having to put them in a separate
213
- function.
214
-
215
- The given statement (which doesn't require quote marks) is run via the
216
- python profiler in a manner similar to the profile.run() function.
217
- Namespaces are internally managed to work correctly; profile.run
218
- cannot be used in IPython because it makes certain assumptions about
219
- namespaces which do not hold under IPython.
220
-
221
- Options:
222
-
223
- -l <limit>
224
- you can place restrictions on what or how much of the
225
- profile gets printed. The limit value can be:
226
-
227
- * A string: only information for function names containing this string
228
- is printed.
229
-
230
- * An integer: only these many lines are printed.
231
-
232
- * A float (between 0 and 1): this fraction of the report is printed
233
- (for example, use a limit of 0.4 to see the topmost 40% only).
234
-
235
- You can combine several limits with repeated use of the option. For
236
- example, ``-l __init__ -l 5`` will print only the topmost 5 lines of
237
- information about class constructors.
238
-
239
- -r
240
- return the pstats.Stats object generated by the profiling. This
241
- object has all the information about the profile in it, and you can
242
- later use it for further analysis or in other functions.
243
-
244
- -s <key>
245
- sort profile by given key. You can provide more than one key
246
- by using the option several times: '-s key1 -s key2 -s key3...'. The
247
- default sorting key is 'time'.
248
-
249
- The following is copied verbatim from the profile documentation
250
- referenced below:
251
-
252
- When more than one key is provided, additional keys are used as
253
- secondary criteria when the there is equality in all keys selected
254
- before them.
255
-
256
- Abbreviations can be used for any key names, as long as the
257
- abbreviation is unambiguous. The following are the keys currently
258
- defined:
259
-
260
- ============ =====================
261
- Valid Arg Meaning
262
- ============ =====================
263
- "calls" call count
264
- "cumulative" cumulative time
265
- "file" file name
266
- "module" file name
267
- "pcalls" primitive call count
268
- "line" line number
269
- "name" function name
270
- "nfl" name/file/line
271
- "stdname" standard name
272
- "time" internal time
273
- ============ =====================
274
-
275
- Note that all sorts on statistics are in descending order (placing
276
- most time consuming items first), where as name, file, and line number
277
- searches are in ascending order (i.e., alphabetical). The subtle
278
- distinction between "nfl" and "stdname" is that the standard name is a
279
- sort of the name as printed, which means that the embedded line
280
- numbers get compared in an odd way. For example, lines 3, 20, and 40
281
- would (if the file names were the same) appear in the string order
282
- "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
283
- line numbers. In fact, sort_stats("nfl") is the same as
284
- sort_stats("name", "file", "line").
285
-
286
- -T <filename>
287
- save profile results as shown on screen to a text
288
- file. The profile is still shown on screen.
289
-
290
- -D <filename>
291
- save (via dump_stats) profile statistics to given
292
- filename. This data is in a format understood by the pstats module, and
293
- is generated by a call to the dump_stats() method of profile
294
- objects. The profile is still shown on screen.
295
-
296
- -q
297
- suppress output to the pager. Best used with -T and/or -D above.
298
-
299
- If you want to run complete programs under the profiler's control, use
300
- ``%run -p [prof_opts] filename.py [args to program]`` where prof_opts
301
- contains profiler specific options as described here.
302
-
303
- You can read the complete documentation for the profile module with::
304
-
305
- In [1]: import profile; profile.help()
306
-
307
- .. versionchanged:: 7.3
308
- User variables are no longer expanded,
309
- the magic line is always left unmodified.
310
-
311
- """
312
- opts, arg_str = self.parse_options(parameter_s, 'D:l:rs:T:q',
313
- list_all=True, posix=False)
314
- if cell is not None:
315
- arg_str += '\n' + cell
316
- arg_str = self.shell.transform_cell(arg_str)
317
- return self._run_with_profiler(arg_str, opts, self.shell.user_ns)
318
-
319
- def _run_with_profiler(self, code, opts, namespace):
320
- """
321
- Run `code` with profiler. Used by ``%prun`` and ``%run -p``.
322
-
323
- Parameters
324
- ----------
325
- code : str
326
- Code to be executed.
327
- opts : Struct
328
- Options parsed by `self.parse_options`.
329
- namespace : dict
330
- A dictionary for Python namespace (e.g., `self.shell.user_ns`).
331
-
332
- """
333
-
334
- # Fill default values for unspecified options:
335
- opts.merge(Struct(D=[''], l=[], s=['time'], T=['']))
336
-
337
- prof = profile.Profile()
338
- try:
339
- prof = prof.runctx(code, namespace, namespace)
340
- sys_exit = ''
341
- except SystemExit:
342
- sys_exit = """*** SystemExit exception caught in code being profiled."""
343
-
344
- stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
345
-
346
- lims = opts.l
347
- if lims:
348
- lims = [] # rebuild lims with ints/floats/strings
349
- for lim in opts.l:
350
- try:
351
- lims.append(int(lim))
352
- except ValueError:
353
- try:
354
- lims.append(float(lim))
355
- except ValueError:
356
- lims.append(lim)
357
-
358
- # Trap output.
359
- stdout_trap = StringIO()
360
- stats_stream = stats.stream
361
- try:
362
- stats.stream = stdout_trap
363
- stats.print_stats(*lims)
364
- finally:
365
- stats.stream = stats_stream
366
-
367
- output = stdout_trap.getvalue()
368
- output = output.rstrip()
369
-
370
- if 'q' not in opts:
371
- page.page(output)
372
- print(sys_exit, end=' ')
373
-
374
- dump_file = opts.D[0]
375
- text_file = opts.T[0]
376
- if dump_file:
377
- prof.dump_stats(dump_file)
378
- print(
379
- f"\n*** Profile stats marshalled to file {repr(dump_file)}.{sys_exit}"
380
- )
381
- if text_file:
382
- pfile = Path(text_file)
383
- pfile.touch(exist_ok=True)
384
- pfile.write_text(output, encoding="utf-8")
385
-
386
- print(
387
- f"\n*** Profile printout saved to text file {repr(text_file)}.{sys_exit}"
388
- )
389
-
390
- if 'r' in opts:
391
- return stats
392
-
393
- return None
394
-
395
- @line_magic
396
- def pdb(self, parameter_s=''):
397
- """Control the automatic calling of the pdb interactive debugger.
398
-
399
- Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
400
- argument it works as a toggle.
401
-
402
- When an exception is triggered, IPython can optionally call the
403
- interactive pdb debugger after the traceback printout. %pdb toggles
404
- this feature on and off.
405
-
406
- The initial state of this feature is set in your configuration
407
- file (the option is ``InteractiveShell.pdb``).
408
-
409
- If you want to just activate the debugger AFTER an exception has fired,
410
- without having to type '%pdb on' and rerunning your code, you can use
411
- the %debug magic."""
412
-
413
- par = parameter_s.strip().lower()
414
-
415
- if par:
416
- try:
417
- new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
418
- except KeyError:
419
- print ('Incorrect argument. Use on/1, off/0, '
420
- 'or nothing for a toggle.')
421
- return
422
- else:
423
- # toggle
424
- new_pdb = not self.shell.call_pdb
425
-
426
- # set on the shell
427
- self.shell.call_pdb = new_pdb
428
- print('Automatic pdb calling has been turned',on_off(new_pdb))
429
-
430
- @magic_arguments.magic_arguments()
431
- @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE',
432
- help="""
433
- Set break point at LINE in FILE.
434
- """
435
- )
436
- @magic_arguments.argument('statement', nargs='*',
437
- help="""
438
- Code to run in debugger.
439
- You can omit this in cell magic mode.
440
- """
441
- )
442
- @no_var_expand
443
- @line_cell_magic
444
- @needs_local_scope
445
- def debug(self, line="", cell=None, local_ns=None):
446
- """Activate the interactive debugger.
447
-
448
- This magic command support two ways of activating debugger.
449
- One is to activate debugger before executing code. This way, you
450
- can set a break point, to step through the code from the point.
451
- You can use this mode by giving statements to execute and optionally
452
- a breakpoint.
453
-
454
- The other one is to activate debugger in post-mortem mode. You can
455
- activate this mode simply running %debug without any argument.
456
- If an exception has just occurred, this lets you inspect its stack
457
- frames interactively. Note that this will always work only on the last
458
- traceback that occurred, so you must call this quickly after an
459
- exception that you wish to inspect has fired, because if another one
460
- occurs, it clobbers the previous one.
461
-
462
- If you want IPython to automatically do this on every exception, see
463
- the %pdb magic for more details.
464
-
465
- .. versionchanged:: 7.3
466
- When running code, user variables are no longer expanded,
467
- the magic line is always left unmodified.
468
-
469
- """
470
- args = magic_arguments.parse_argstring(self.debug, line)
471
-
472
- if not (args.breakpoint or args.statement or cell):
473
- self._debug_post_mortem()
474
- elif not (args.breakpoint or cell):
475
- # If there is no breakpoints, the line is just code to execute
476
- self._debug_exec(line, None, local_ns)
477
- else:
478
- # Here we try to reconstruct the code from the output of
479
- # parse_argstring. This might not work if the code has spaces
480
- # For example this fails for `print("a b")`
481
- code = "\n".join(args.statement)
482
- if cell:
483
- code += "\n" + cell
484
- self._debug_exec(code, args.breakpoint, local_ns)
485
-
486
- def _debug_post_mortem(self):
487
- self.shell.debugger(force=True)
488
-
489
- def _debug_exec(self, code, breakpoint, local_ns=None):
490
- if breakpoint:
491
- (filename, bp_line) = breakpoint.rsplit(':', 1)
492
- bp_line = int(bp_line)
493
- else:
494
- (filename, bp_line) = (None, None)
495
- self._run_with_debugger(
496
- code, self.shell.user_ns, filename, bp_line, local_ns=local_ns
497
- )
498
-
499
- @line_magic
500
- def tb(self, s):
501
- """Print the last traceback.
502
-
503
- Optionally, specify an exception reporting mode, tuning the
504
- verbosity of the traceback. By default the currently-active exception
505
- mode is used. See %xmode for changing exception reporting modes.
506
-
507
- Valid modes: Plain, Context, Verbose, and Minimal.
508
- """
509
- interactive_tb = self.shell.InteractiveTB
510
- if s:
511
- # Switch exception reporting mode for this one call.
512
- # Ensure it is switched back.
513
- def xmode_switch_err(name):
514
- warn('Error changing %s exception modes.\n%s' %
515
- (name,sys.exc_info()[1]))
516
-
517
- new_mode = s.strip().capitalize()
518
- original_mode = interactive_tb.mode
519
- try:
520
- try:
521
- interactive_tb.set_mode(mode=new_mode)
522
- except Exception:
523
- xmode_switch_err('user')
524
- else:
525
- self.shell.showtraceback()
526
- finally:
527
- interactive_tb.set_mode(mode=original_mode)
528
- else:
529
- self.shell.showtraceback()
530
-
531
- @skip_doctest
532
- @line_magic
533
- def run(self, parameter_s='', runner=None,
534
- file_finder=get_py_filename):
535
- """Run the named file inside IPython as a program.
536
-
537
- Usage::
538
-
539
- %run [-n -i -e -G]
540
- [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )]
541
- ( -m mod | filename ) [args]
542
-
543
- The filename argument should be either a pure Python script (with
544
- extension ``.py``), or a file with custom IPython syntax (such as
545
- magics). If the latter, the file can be either a script with ``.ipy``
546
- extension, or a Jupyter notebook with ``.ipynb`` extension. When running
547
- a Jupyter notebook, the output from print statements and other
548
- displayed objects will appear in the terminal (even matplotlib figures
549
- will open, if a terminal-compliant backend is being used). Note that,
550
- at the system command line, the ``jupyter run`` command offers similar
551
- functionality for executing notebooks (albeit currently with some
552
- differences in supported options).
553
-
554
- Parameters after the filename are passed as command-line arguments to
555
- the program (put in sys.argv). Then, control returns to IPython's
556
- prompt.
557
-
558
- This is similar to running at a system prompt ``python file args``,
559
- but with the advantage of giving you IPython's tracebacks, and of
560
- loading all variables into your interactive namespace for further use
561
- (unless -p is used, see below).
562
-
563
- The file is executed in a namespace initially consisting only of
564
- ``__name__=='__main__'`` and sys.argv constructed as indicated. It thus
565
- sees its environment as if it were being run as a stand-alone program
566
- (except for sharing global objects such as previously imported
567
- modules). But after execution, the IPython interactive namespace gets
568
- updated with all variables defined in the program (except for __name__
569
- and sys.argv). This allows for very convenient loading of code for
570
- interactive work, while giving each program a 'clean sheet' to run in.
571
-
572
- Arguments are expanded using shell-like glob match. Patterns
573
- '*', '?', '[seq]' and '[!seq]' can be used. Additionally,
574
- tilde '~' will be expanded into user's home directory. Unlike
575
- real shells, quotation does not suppress expansions. Use
576
- *two* back slashes (e.g. ``\\\\*``) to suppress expansions.
577
- To completely disable these expansions, you can use -G flag.
578
-
579
- On Windows systems, the use of single quotes `'` when specifying
580
- a file is not supported. Use double quotes `"`.
581
-
582
- Options:
583
-
584
- -n
585
- __name__ is NOT set to '__main__', but to the running file's name
586
- without extension (as python does under import). This allows running
587
- scripts and reloading the definitions in them without calling code
588
- protected by an ``if __name__ == "__main__"`` clause.
589
-
590
- -i
591
- run the file in IPython's namespace instead of an empty one. This
592
- is useful if you are experimenting with code written in a text editor
593
- which depends on variables defined interactively.
594
-
595
- -e
596
- ignore sys.exit() calls or SystemExit exceptions in the script
597
- being run. This is particularly useful if IPython is being used to
598
- run unittests, which always exit with a sys.exit() call. In such
599
- cases you are interested in the output of the test results, not in
600
- seeing a traceback of the unittest module.
601
-
602
- -t
603
- print timing information at the end of the run. IPython will give
604
- you an estimated CPU time consumption for your script, which under
605
- Unix uses the resource module to avoid the wraparound problems of
606
- time.clock(). Under Unix, an estimate of time spent on system tasks
607
- is also given (for Windows platforms this is reported as 0.0).
608
-
609
- If -t is given, an additional ``-N<N>`` option can be given, where <N>
610
- must be an integer indicating how many times you want the script to
611
- run. The final timing report will include total and per run results.
612
-
613
- For example (testing the script uniq_stable.py)::
614
-
615
- In [1]: run -t uniq_stable
616
-
617
- IPython CPU timings (estimated):
618
- User : 0.19597 s.
619
- System: 0.0 s.
620
-
621
- In [2]: run -t -N5 uniq_stable
622
-
623
- IPython CPU timings (estimated):
624
- Total runs performed: 5
625
- Times : Total Per run
626
- User : 0.910862 s, 0.1821724 s.
627
- System: 0.0 s, 0.0 s.
628
-
629
- -d
630
- run your program under the control of pdb, the Python debugger.
631
- This allows you to execute your program step by step, watch variables,
632
- etc. Internally, what IPython does is similar to calling::
633
-
634
- pdb.run('execfile("YOURFILENAME")')
635
-
636
- with a breakpoint set on line 1 of your file. You can change the line
637
- number for this automatic breakpoint to be <N> by using the -bN option
638
- (where N must be an integer). For example::
639
-
640
- %run -d -b40 myscript
641
-
642
- will set the first breakpoint at line 40 in myscript.py. Note that
643
- the first breakpoint must be set on a line which actually does
644
- something (not a comment or docstring) for it to stop execution.
645
-
646
- Or you can specify a breakpoint in a different file::
647
-
648
- %run -d -b myotherfile.py:20 myscript
649
-
650
- When the pdb debugger starts, you will see a (Pdb) prompt. You must
651
- first enter 'c' (without quotes) to start execution up to the first
652
- breakpoint.
653
-
654
- Entering 'help' gives information about the use of the debugger. You
655
- can easily see pdb's full documentation with "import pdb;pdb.help()"
656
- at a prompt.
657
-
658
- -p
659
- run program under the control of the Python profiler module (which
660
- prints a detailed report of execution times, function calls, etc).
661
-
662
- You can pass other options after -p which affect the behavior of the
663
- profiler itself. See the docs for %prun for details.
664
-
665
- In this mode, the program's variables do NOT propagate back to the
666
- IPython interactive namespace (because they remain in the namespace
667
- where the profiler executes them).
668
-
669
- Internally this triggers a call to %prun, see its documentation for
670
- details on the options available specifically for profiling.
671
-
672
- There is one special usage for which the text above doesn't apply:
673
- if the filename ends with .ipy[nb], the file is run as ipython script,
674
- just as if the commands were written on IPython prompt.
675
-
676
- -m
677
- specify module name to load instead of script path. Similar to
678
- the -m option for the python interpreter. Use this option last if you
679
- want to combine with other %run options. Unlike the python interpreter
680
- only source modules are allowed no .pyc or .pyo files.
681
- For example::
682
-
683
- %run -m example
684
-
685
- will run the example module.
686
-
687
- -G
688
- disable shell-like glob expansion of arguments.
689
-
690
- """
691
-
692
- # Logic to handle issue #3664
693
- # Add '--' after '-m <module_name>' to ignore additional args passed to a module.
694
- if '-m' in parameter_s and '--' not in parameter_s:
695
- argv = shlex.split(parameter_s, posix=(os.name == 'posix'))
696
- for idx, arg in enumerate(argv):
697
- if arg and arg.startswith('-') and arg != '-':
698
- if arg == '-m':
699
- argv.insert(idx + 2, '--')
700
- break
701
- else:
702
- # Positional arg, break
703
- break
704
- parameter_s = ' '.join(shlex.quote(arg) for arg in argv)
705
-
706
- # get arguments and set sys.argv for program to be run.
707
- opts, arg_lst = self.parse_options(parameter_s,
708
- 'nidtN:b:pD:l:rs:T:em:G',
709
- mode='list', list_all=1)
710
- if "m" in opts:
711
- modulename = opts["m"][0]
712
- modpath = find_mod(modulename)
713
- if modpath is None:
714
- msg = '%r is not a valid modulename on sys.path'%modulename
715
- raise Exception(msg)
716
- arg_lst = [modpath] + arg_lst
717
- try:
718
- fpath = None # initialize to make sure fpath is in scope later
719
- fpath = arg_lst[0]
720
- filename = file_finder(fpath)
721
- except IndexError as e:
722
- msg = 'you must provide at least a filename.'
723
- raise Exception(msg) from e
724
- except IOError as e:
725
- try:
726
- msg = str(e)
727
- except UnicodeError:
728
- msg = e.message
729
- if os.name == 'nt' and re.match(r"^'.*'$",fpath):
730
- warn('For Windows, use double quotes to wrap a filename: %run "mypath\\myfile.py"')
731
- raise Exception(msg) from e
732
- except TypeError:
733
- if fpath in sys.meta_path:
734
- filename = ""
735
- else:
736
- raise
737
-
738
- if filename.lower().endswith(('.ipy', '.ipynb')):
739
- with preserve_keys(self.shell.user_ns, '__file__'):
740
- self.shell.user_ns['__file__'] = filename
741
- self.shell.safe_execfile_ipy(filename, raise_exceptions=True)
742
- return
743
-
744
- # Control the response to exit() calls made by the script being run
745
- exit_ignore = 'e' in opts
746
-
747
- # Make sure that the running script gets a proper sys.argv as if it
748
- # were run from a system shell.
749
- save_argv = sys.argv # save it for later restoring
750
-
751
- if 'G' in opts:
752
- args = arg_lst[1:]
753
- else:
754
- # tilde and glob expansion
755
- args = shellglob(map(os.path.expanduser, arg_lst[1:]))
756
-
757
- sys.argv = [filename] + args # put in the proper filename
758
-
759
- if 'n' in opts:
760
- name = Path(filename).stem
761
- else:
762
- name = '__main__'
763
-
764
- if 'i' in opts:
765
- # Run in user's interactive namespace
766
- prog_ns = self.shell.user_ns
767
- __name__save = self.shell.user_ns['__name__']
768
- prog_ns['__name__'] = name
769
- main_mod = self.shell.user_module
770
-
771
- # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
772
- # set the __file__ global in the script's namespace
773
- # TK: Is this necessary in interactive mode?
774
- prog_ns['__file__'] = filename
775
- else:
776
- # Run in a fresh, empty namespace
777
-
778
- # The shell MUST hold a reference to prog_ns so after %run
779
- # exits, the python deletion mechanism doesn't zero it out
780
- # (leaving dangling references). See interactiveshell for details
781
- main_mod = self.shell.new_main_mod(filename, name)
782
- prog_ns = main_mod.__dict__
783
-
784
- # pickle fix. See interactiveshell for an explanation. But we need to
785
- # make sure that, if we overwrite __main__, we replace it at the end
786
- main_mod_name = prog_ns['__name__']
787
-
788
- if main_mod_name == '__main__':
789
- restore_main = sys.modules['__main__']
790
- else:
791
- restore_main = False
792
-
793
- # This needs to be undone at the end to prevent holding references to
794
- # every single object ever created.
795
- sys.modules[main_mod_name] = main_mod
796
-
797
- if 'p' in opts or 'd' in opts:
798
- if 'm' in opts:
799
- code = 'run_module(modulename, prog_ns)'
800
- code_ns = {
801
- 'run_module': self.shell.safe_run_module,
802
- 'prog_ns': prog_ns,
803
- 'modulename': modulename,
804
- }
805
- else:
806
- if 'd' in opts:
807
- # allow exceptions to raise in debug mode
808
- code = 'execfile(filename, prog_ns, raise_exceptions=True)'
809
- else:
810
- code = 'execfile(filename, prog_ns)'
811
- code_ns = {
812
- 'execfile': self.shell.safe_execfile,
813
- 'prog_ns': prog_ns,
814
- 'filename': get_py_filename(filename),
815
- }
816
-
817
- try:
818
- stats = None
819
- if 'p' in opts:
820
- stats = self._run_with_profiler(code, opts, code_ns)
821
- else:
822
- if 'd' in opts:
823
- bp_file, bp_line = parse_breakpoint(
824
- opts.get('b', ['1'])[0], filename)
825
- self._run_with_debugger(
826
- code, code_ns, filename, bp_line, bp_file)
827
- else:
828
- if 'm' in opts:
829
- def run():
830
- self.shell.safe_run_module(modulename, prog_ns)
831
- else:
832
- if runner is None:
833
- runner = self.default_runner
834
- if runner is None:
835
- runner = self.shell.safe_execfile
836
-
837
- def run():
838
- runner(filename, prog_ns, prog_ns,
839
- exit_ignore=exit_ignore)
840
-
841
- if 't' in opts:
842
- # timed execution
843
- try:
844
- nruns = int(opts['N'][0])
845
- if nruns < 1:
846
- error('Number of runs must be >=1')
847
- return
848
- except (KeyError):
849
- nruns = 1
850
- self._run_with_timing(run, nruns)
851
- else:
852
- # regular execution
853
- run()
854
-
855
- if 'i' in opts:
856
- self.shell.user_ns['__name__'] = __name__save
857
- else:
858
- # update IPython interactive namespace
859
-
860
- # Some forms of read errors on the file may mean the
861
- # __name__ key was never set; using pop we don't have to
862
- # worry about a possible KeyError.
863
- prog_ns.pop('__name__', None)
864
-
865
- with preserve_keys(self.shell.user_ns, '__file__'):
866
- self.shell.user_ns.update(prog_ns)
867
- finally:
868
- # It's a bit of a mystery why, but __builtins__ can change from
869
- # being a module to becoming a dict missing some key data after
870
- # %run. As best I can see, this is NOT something IPython is doing
871
- # at all, and similar problems have been reported before:
872
- # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
873
- # Since this seems to be done by the interpreter itself, the best
874
- # we can do is to at least restore __builtins__ for the user on
875
- # exit.
876
- self.shell.user_ns['__builtins__'] = builtin_mod
877
-
878
- # Ensure key global structures are restored
879
- sys.argv = save_argv
880
- if restore_main:
881
- sys.modules['__main__'] = restore_main
882
- if '__mp_main__' in sys.modules:
883
- sys.modules['__mp_main__'] = restore_main
884
- else:
885
- # Remove from sys.modules the reference to main_mod we'd
886
- # added. Otherwise it will trap references to objects
887
- # contained therein.
888
- del sys.modules[main_mod_name]
889
-
890
- return stats
891
-
892
- def _run_with_debugger(
893
- self, code, code_ns, filename=None, bp_line=None, bp_file=None, local_ns=None
894
- ):
895
- """
896
- Run `code` in debugger with a break point.
897
-
898
- Parameters
899
- ----------
900
- code : str
901
- Code to execute.
902
- code_ns : dict
903
- A namespace in which `code` is executed.
904
- filename : str
905
- `code` is ran as if it is in `filename`.
906
- bp_line : int, optional
907
- Line number of the break point.
908
- bp_file : str, optional
909
- Path to the file in which break point is specified.
910
- `filename` is used if not given.
911
- local_ns : dict, optional
912
- A local namespace in which `code` is executed.
913
-
914
- Raises
915
- ------
916
- UsageError
917
- If the break point given by `bp_line` is not valid.
918
-
919
- """
920
- deb = self.shell.InteractiveTB.pdb
921
- if not deb:
922
- self.shell.InteractiveTB.pdb = self.shell.InteractiveTB.debugger_cls()
923
- deb = self.shell.InteractiveTB.pdb
924
-
925
- # deb.checkline() fails if deb.curframe exists but is None; it can
926
- # handle it not existing. https://github.com/ipython/ipython/issues/10028
927
- if hasattr(deb, 'curframe'):
928
- del deb.curframe
929
-
930
- # reset Breakpoint state, which is moronically kept
931
- # in a class
932
- bdb.Breakpoint.next = 1
933
- bdb.Breakpoint.bplist = {}
934
- bdb.Breakpoint.bpbynumber = [None]
935
- deb.clear_all_breaks()
936
- if bp_line is not None:
937
- # Set an initial breakpoint to stop execution
938
- maxtries = 10
939
- bp_file = bp_file or filename
940
- checkline = deb.checkline(bp_file, bp_line)
941
- if not checkline:
942
- for bp in range(bp_line + 1, bp_line + maxtries + 1):
943
- if deb.checkline(bp_file, bp):
944
- break
945
- else:
946
- msg = ("\nI failed to find a valid line to set "
947
- "a breakpoint\n"
948
- "after trying up to line: %s.\n"
949
- "Please set a valid breakpoint manually "
950
- "with the -b option." % bp)
951
- raise UsageError(msg)
952
- # if we find a good linenumber, set the breakpoint
953
- deb.do_break('%s:%s' % (bp_file, bp_line))
954
-
955
- if filename:
956
- # Mimic Pdb._runscript(...)
957
- deb._wait_for_mainpyfile = True
958
- deb.mainpyfile = deb.canonic(filename)
959
-
960
- # Start file run
961
- print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt)
962
- try:
963
- if filename:
964
- # save filename so it can be used by methods on the deb object
965
- deb._exec_filename = filename
966
- while True:
967
- try:
968
- trace = sys.gettrace()
969
- deb.run(code, code_ns, local_ns)
970
- except Restart:
971
- print("Restarting")
972
- if filename:
973
- deb._wait_for_mainpyfile = True
974
- deb.mainpyfile = deb.canonic(filename)
975
- continue
976
- else:
977
- break
978
- finally:
979
- sys.settrace(trace)
980
-
981
-
982
- except:
983
- etype, value, tb = sys.exc_info()
984
- # Skip three frames in the traceback: the %run one,
985
- # one inside bdb.py, and the command-line typed by the
986
- # user (run by exec in pdb itself).
987
- self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
988
-
989
- @staticmethod
990
- def _run_with_timing(run, nruns):
991
- """
992
- Run function `run` and print timing information.
993
-
994
- Parameters
995
- ----------
996
- run : callable
997
- Any callable object which takes no argument.
998
- nruns : int
999
- Number of times to execute `run`.
1000
-
1001
- """
1002
- twall0 = time.perf_counter()
1003
- if nruns == 1:
1004
- t0 = clock2()
1005
- run()
1006
- t1 = clock2()
1007
- t_usr = t1[0] - t0[0]
1008
- t_sys = t1[1] - t0[1]
1009
- print("\nIPython CPU timings (estimated):")
1010
- print(" User : %10.2f s." % t_usr)
1011
- print(" System : %10.2f s." % t_sys)
1012
- else:
1013
- runs = range(nruns)
1014
- t0 = clock2()
1015
- for nr in runs:
1016
- run()
1017
- t1 = clock2()
1018
- t_usr = t1[0] - t0[0]
1019
- t_sys = t1[1] - t0[1]
1020
- print("\nIPython CPU timings (estimated):")
1021
- print("Total runs performed:", nruns)
1022
- print(" Times : %10s %10s" % ('Total', 'Per run'))
1023
- print(" User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns))
1024
- print(" System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns))
1025
- twall1 = time.perf_counter()
1026
- print("Wall time: %10.2f s." % (twall1 - twall0))
1027
-
1028
- @skip_doctest
1029
- @no_var_expand
1030
- @line_cell_magic
1031
- @needs_local_scope
1032
- def timeit(self, line='', cell=None, local_ns=None):
1033
- """Time execution of a Python statement or expression
1034
-
1035
- **Usage, in line mode:**
1036
-
1037
- %timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] statement
1038
-
1039
- **or in cell mode:**
1040
-
1041
- %%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] setup_code
1042
-
1043
- code
1044
-
1045
- code...
1046
-
1047
- Time execution of a Python statement or expression using the timeit
1048
- module. This function can be used both as a line and cell magic:
1049
-
1050
- - In line mode you can time a single-line statement (though multiple
1051
- ones can be chained with using semicolons).
1052
-
1053
- - In cell mode, the statement in the first line is used as setup code
1054
- (executed but not timed) and the body of the cell is timed. The cell
1055
- body has access to any variables created in the setup code.
1056
-
1057
- Options:
1058
-
1059
- -n<N>: execute the given statement <N> times in a loop. If <N> is not
1060
- provided, <N> is determined so as to get sufficient accuracy.
1061
-
1062
- -r<R>: number of repeats <R>, each consisting of <N> loops, and take the
1063
- average result.
1064
- Default: 7
1065
-
1066
- -t: use time.time to measure the time, which is the default on Unix.
1067
- This function measures wall time.
1068
-
1069
- -c: use time.clock to measure the time, which is the default on
1070
- Windows and measures wall time. On Unix, resource.getrusage is used
1071
- instead and returns the CPU user time.
1072
-
1073
- -p<P>: use a precision of <P> digits to display the timing result.
1074
- Default: 3
1075
-
1076
- -q: Quiet, do not print result.
1077
-
1078
- -o: return a TimeitResult that can be stored in a variable to inspect
1079
- the result in more details.
1080
-
1081
- .. versionchanged:: 7.3
1082
- User variables are no longer expanded,
1083
- the magic line is always left unmodified.
1084
-
1085
- Examples
1086
- --------
1087
- ::
1088
-
1089
- In [1]: %timeit pass
1090
- 8.26 ns ± 0.12 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
1091
-
1092
- In [2]: u = None
1093
-
1094
- In [3]: %timeit u is None
1095
- 29.9 ns ± 0.643 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
1096
-
1097
- In [4]: %timeit -r 4 u == None
1098
-
1099
- In [5]: import time
1100
-
1101
- In [6]: %timeit -n1 time.sleep(2)
1102
-
1103
- The times reported by %timeit will be slightly higher than those
1104
- reported by the timeit.py script when variables are accessed. This is
1105
- due to the fact that %timeit executes the statement in the namespace
1106
- of the shell, compared with timeit.py, which uses a single setup
1107
- statement to import function or create variables. Generally, the bias
1108
- does not matter as long as results from timeit.py are not mixed with
1109
- those from %timeit."""
1110
-
1111
- opts, stmt = self.parse_options(
1112
- line, "n:r:tcp:qo", posix=False, strict=False, preserve_non_opts=True
1113
- )
1114
- if stmt == "" and cell is None:
1115
- return
1116
-
1117
- timefunc = timeit.default_timer
1118
- number = int(getattr(opts, "n", 0))
1119
- default_repeat = 7 if timeit.default_repeat < 7 else timeit.default_repeat
1120
- repeat = int(getattr(opts, "r", default_repeat))
1121
- precision = int(getattr(opts, "p", 3))
1122
- quiet = 'q' in opts
1123
- return_result = 'o' in opts
1124
- if hasattr(opts, "t"):
1125
- timefunc = time.time
1126
- if hasattr(opts, "c"):
1127
- timefunc = clock
1128
-
1129
- timer = Timer(timer=timefunc)
1130
- # this code has tight coupling to the inner workings of timeit.Timer,
1131
- # but is there a better way to achieve that the code stmt has access
1132
- # to the shell namespace?
1133
- transform = self.shell.transform_cell
1134
-
1135
- if cell is None:
1136
- # called as line magic
1137
- ast_setup = self.shell.compile.ast_parse("pass")
1138
- ast_stmt = self.shell.compile.ast_parse(transform(stmt))
1139
- else:
1140
- ast_setup = self.shell.compile.ast_parse(transform(stmt))
1141
- ast_stmt = self.shell.compile.ast_parse(transform(cell))
1142
-
1143
- ast_setup = self.shell.transform_ast(ast_setup)
1144
- ast_stmt = self.shell.transform_ast(ast_stmt)
1145
-
1146
- # Check that these compile to valid Python code *outside* the timer func
1147
- # Invalid code may become valid when put inside the function & loop,
1148
- # which messes up error messages.
1149
- # https://github.com/ipython/ipython/issues/10636
1150
- self.shell.compile(ast_setup, "<magic-timeit-setup>", "exec")
1151
- self.shell.compile(ast_stmt, "<magic-timeit-stmt>", "exec")
1152
-
1153
- # This codestring is taken from timeit.template - we fill it in as an
1154
- # AST, so that we can apply our AST transformations to the user code
1155
- # without affecting the timing code.
1156
- timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
1157
- ' setup\n'
1158
- ' _t0 = _timer()\n'
1159
- ' for _i in _it:\n'
1160
- ' stmt\n'
1161
- ' _t1 = _timer()\n'
1162
- ' return _t1 - _t0\n')
1163
-
1164
- timeit_ast = TimeitTemplateFiller(ast_setup, ast_stmt).visit(timeit_ast_template)
1165
- timeit_ast = ast.fix_missing_locations(timeit_ast)
1166
-
1167
- # Track compilation time so it can be reported if too long
1168
- # Minimum time above which compilation time will be reported
1169
- tc_min = 0.1
1170
-
1171
- t0 = clock()
1172
- code = self.shell.compile(timeit_ast, "<magic-timeit>", "exec")
1173
- tc = clock()-t0
1174
-
1175
- ns = {}
1176
- glob = self.shell.user_ns
1177
- # handles global vars with same name as local vars. We store them in conflict_globs.
1178
- conflict_globs = {}
1179
- if local_ns and cell is None:
1180
- for var_name, var_val in glob.items():
1181
- if var_name in local_ns:
1182
- conflict_globs[var_name] = var_val
1183
- glob.update(local_ns)
1184
-
1185
- exec(code, glob, ns)
1186
- timer.inner = ns["inner"]
1187
-
1188
- # This is used to check if there is a huge difference between the
1189
- # best and worst timings.
1190
- # Issue: https://github.com/ipython/ipython/issues/6471
1191
- if number == 0:
1192
- # determine number so that 0.2 <= total time < 2.0
1193
- for index in range(0, 10):
1194
- number = 10 ** index
1195
- time_number = timer.timeit(number)
1196
- if time_number >= 0.2:
1197
- break
1198
-
1199
- all_runs = timer.repeat(repeat, number)
1200
- best = min(all_runs) / number
1201
- worst = max(all_runs) / number
1202
- timeit_result = TimeitResult(number, repeat, best, worst, all_runs, tc, precision)
1203
-
1204
- # Restore global vars from conflict_globs
1205
- if conflict_globs:
1206
- glob.update(conflict_globs)
1207
-
1208
- if not quiet :
1209
- # Check best timing is greater than zero to avoid a
1210
- # ZeroDivisionError.
1211
- # In cases where the slowest timing is lesser than a microsecond
1212
- # we assume that it does not really matter if the fastest
1213
- # timing is 4 times faster than the slowest timing or not.
1214
- if worst > 4 * best and best > 0 and worst > 1e-6:
1215
- print("The slowest run took %0.2f times longer than the "
1216
- "fastest. This could mean that an intermediate result "
1217
- "is being cached." % (worst / best))
1218
-
1219
- print( timeit_result )
1220
-
1221
- if tc > tc_min:
1222
- print("Compiler time: %.2f s" % tc)
1223
- if return_result:
1224
- return timeit_result
1225
-
1226
- @skip_doctest
1227
- @no_var_expand
1228
- @needs_local_scope
1229
- @line_cell_magic
1230
- @output_can_be_silenced
1231
- def time(self,line='', cell=None, local_ns=None):
1232
- """Time execution of a Python statement or expression.
1233
-
1234
- The CPU and wall clock times are printed, and the value of the
1235
- expression (if any) is returned. Note that under Win32, system time
1236
- is always reported as 0, since it can not be measured.
1237
-
1238
- This function can be used both as a line and cell magic:
1239
-
1240
- - In line mode you can time a single-line statement (though multiple
1241
- ones can be chained with using semicolons).
1242
-
1243
- - In cell mode, you can time the cell body (a directly
1244
- following statement raises an error).
1245
-
1246
- This function provides very basic timing functionality. Use the timeit
1247
- magic for more control over the measurement.
1248
-
1249
- .. versionchanged:: 7.3
1250
- User variables are no longer expanded,
1251
- the magic line is always left unmodified.
1252
-
1253
- Examples
1254
- --------
1255
- ::
1256
-
1257
- In [1]: %time 2**128
1258
- CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1259
- Wall time: 0.00
1260
- Out[1]: 340282366920938463463374607431768211456L
1261
-
1262
- In [2]: n = 1000000
1263
-
1264
- In [3]: %time sum(range(n))
1265
- CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1266
- Wall time: 1.37
1267
- Out[3]: 499999500000L
1268
-
1269
- In [4]: %time print('hello world')
1270
- hello world
1271
- CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1272
- Wall time: 0.00
1273
-
1274
- .. note::
1275
- The time needed by Python to compile the given expression will be
1276
- reported if it is more than 0.1s.
1277
-
1278
- In the example below, the actual exponentiation is done by Python
1279
- at compilation time, so while the expression can take a noticeable
1280
- amount of time to compute, that time is purely due to the
1281
- compilation::
1282
-
1283
- In [5]: %time 3**9999;
1284
- CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1285
- Wall time: 0.00 s
1286
-
1287
- In [6]: %time 3**999999;
1288
- CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1289
- Wall time: 0.00 s
1290
- Compiler : 0.78 s
1291
- """
1292
- # fail immediately if the given expression can't be compiled
1293
-
1294
- if line and cell:
1295
- raise UsageError("Can't use statement directly after '%%time'!")
1296
-
1297
- if cell:
1298
- expr = self.shell.transform_cell(cell)
1299
- else:
1300
- expr = self.shell.transform_cell(line)
1301
-
1302
- # Minimum time above which parse time will be reported
1303
- tp_min = 0.1
1304
-
1305
- t0 = clock()
1306
- expr_ast = self.shell.compile.ast_parse(expr)
1307
- tp = clock()-t0
1308
-
1309
- # Apply AST transformations
1310
- expr_ast = self.shell.transform_ast(expr_ast)
1311
-
1312
- # Minimum time above which compilation time will be reported
1313
- tc_min = 0.1
1314
-
1315
- expr_val=None
1316
- if len(expr_ast.body)==1 and isinstance(expr_ast.body[0], ast.Expr):
1317
- mode = 'eval'
1318
- source = '<timed eval>'
1319
- expr_ast = ast.Expression(expr_ast.body[0].value)
1320
- else:
1321
- mode = 'exec'
1322
- source = '<timed exec>'
1323
- # multi-line %%time case
1324
- if len(expr_ast.body) > 1 and isinstance(expr_ast.body[-1], ast.Expr):
1325
- expr_val= expr_ast.body[-1]
1326
- expr_ast = expr_ast.body[:-1]
1327
- expr_ast = Module(expr_ast, [])
1328
- expr_val = ast.Expression(expr_val.value)
1329
-
1330
- t0 = clock()
1331
- code = self.shell.compile(expr_ast, source, mode)
1332
- tc = clock()-t0
1333
-
1334
- # skew measurement as little as possible
1335
- glob = self.shell.user_ns
1336
- wtime = time.time
1337
- # time execution
1338
- wall_st = wtime()
1339
- if mode=='eval':
1340
- st = clock2()
1341
- try:
1342
- out = eval(code, glob, local_ns)
1343
- except:
1344
- self.shell.showtraceback()
1345
- return
1346
- end = clock2()
1347
- else:
1348
- st = clock2()
1349
- try:
1350
- exec(code, glob, local_ns)
1351
- out=None
1352
- # multi-line %%time case
1353
- if expr_val is not None:
1354
- code_2 = self.shell.compile(expr_val, source, 'eval')
1355
- out = eval(code_2, glob, local_ns)
1356
- except:
1357
- self.shell.showtraceback()
1358
- return
1359
- end = clock2()
1360
-
1361
- wall_end = wtime()
1362
- # Compute actual times and report
1363
- wall_time = wall_end - wall_st
1364
- cpu_user = end[0] - st[0]
1365
- cpu_sys = end[1] - st[1]
1366
- cpu_tot = cpu_user + cpu_sys
1367
- # On windows cpu_sys is always zero, so only total is displayed
1368
- if sys.platform != "win32":
1369
- print(
1370
- f"CPU times: user {_format_time(cpu_user)}, sys: {_format_time(cpu_sys)}, total: {_format_time(cpu_tot)}"
1371
- )
1372
- else:
1373
- print(f"CPU times: total: {_format_time(cpu_tot)}")
1374
- print(f"Wall time: {_format_time(wall_time)}")
1375
- if tc > tc_min:
1376
- print(f"Compiler : {_format_time(tc)}")
1377
- if tp > tp_min:
1378
- print(f"Parser : {_format_time(tp)}")
1379
- return out
1380
-
1381
- @skip_doctest
1382
- @line_magic
1383
- def macro(self, parameter_s=''):
1384
- """Define a macro for future re-execution. It accepts ranges of history,
1385
- filenames or string objects.
1386
-
1387
- Usage:\\
1388
- %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1389
-
1390
- Options:
1391
-
1392
- -r: use 'raw' input. By default, the 'processed' history is used,
1393
- so that magics are loaded in their transformed version to valid
1394
- Python. If this option is given, the raw input as typed at the
1395
- command line is used instead.
1396
-
1397
- -q: quiet macro definition. By default, a tag line is printed
1398
- to indicate the macro has been created, and then the contents of
1399
- the macro are printed. If this option is given, then no printout
1400
- is produced once the macro is created.
1401
-
1402
- This will define a global variable called `name` which is a string
1403
- made of joining the slices and lines you specify (n1,n2,... numbers
1404
- above) from your input history into a single string. This variable
1405
- acts like an automatic function which re-executes those lines as if
1406
- you had typed them. You just type 'name' at the prompt and the code
1407
- executes.
1408
-
1409
- The syntax for indicating input ranges is described in %history.
1410
-
1411
- Note: as a 'hidden' feature, you can also use traditional python slice
1412
- notation, where N:M means numbers N through M-1.
1413
-
1414
- For example, if your history contains (print using %hist -n )::
1415
-
1416
- 44: x=1
1417
- 45: y=3
1418
- 46: z=x+y
1419
- 47: print(x)
1420
- 48: a=5
1421
- 49: print('x',x,'y',y)
1422
-
1423
- you can create a macro with lines 44 through 47 (included) and line 49
1424
- called my_macro with::
1425
-
1426
- In [55]: %macro my_macro 44-47 49
1427
-
1428
- Now, typing `my_macro` (without quotes) will re-execute all this code
1429
- in one pass.
1430
-
1431
- You don't need to give the line-numbers in order, and any given line
1432
- number can appear multiple times. You can assemble macros with any
1433
- lines from your input history in any order.
1434
-
1435
- The macro is a simple object which holds its value in an attribute,
1436
- but IPython's display system checks for macros and executes them as
1437
- code instead of printing them when you type their name.
1438
-
1439
- You can view a macro's contents by explicitly printing it with::
1440
-
1441
- print(macro_name)
1442
-
1443
- """
1444
- opts,args = self.parse_options(parameter_s,'rq',mode='list')
1445
- if not args: # List existing macros
1446
- return sorted(k for k,v in self.shell.user_ns.items() if isinstance(v, Macro))
1447
- if len(args) == 1:
1448
- raise UsageError(
1449
- "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
1450
- name, codefrom = args[0], " ".join(args[1:])
1451
-
1452
- # print('rng',ranges) # dbg
1453
- try:
1454
- lines = self.shell.find_user_code(codefrom, 'r' in opts)
1455
- except (ValueError, TypeError) as e:
1456
- print(e.args[0])
1457
- return
1458
- macro = Macro(lines)
1459
- self.shell.define_macro(name, macro)
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=' ')
1464
-
1465
- @magic_arguments.magic_arguments()
1466
- @magic_arguments.argument('output', type=str, default='', nargs='?',
1467
- help="""The name of the variable in which to store output.
1468
- This is a utils.io.CapturedIO object with stdout/err attributes
1469
- for the text of the captured output.
1470
-
1471
- CapturedOutput also has a show() method for displaying the output,
1472
- and __call__ as well, so you can use that to quickly display the
1473
- output.
1474
-
1475
- If unspecified, captured output is discarded.
1476
- """
1477
- )
1478
- @magic_arguments.argument('--no-stderr', action="store_true",
1479
- help="""Don't capture stderr."""
1480
- )
1481
- @magic_arguments.argument('--no-stdout', action="store_true",
1482
- help="""Don't capture stdout."""
1483
- )
1484
- @magic_arguments.argument('--no-display', action="store_true",
1485
- help="""Don't capture IPython's rich display."""
1486
- )
1487
- @cell_magic
1488
- def capture(self, line, cell):
1489
- """run the cell, capturing stdout, stderr, and IPython's rich display() calls."""
1490
- args = magic_arguments.parse_argstring(self.capture, line)
1491
- out = not args.no_stdout
1492
- err = not args.no_stderr
1493
- disp = not args.no_display
1494
- with capture_output(out, err, disp) as io:
1495
- self.shell.run_cell(cell)
1496
- if DisplayHook.semicolon_at_end_of_expression(cell):
1497
- if args.output in self.shell.user_ns:
1498
- del self.shell.user_ns[args.output]
1499
- elif args.output:
1500
- self.shell.user_ns[args.output] = io
1501
-
1502
- @skip_doctest
1503
- @magic_arguments.magic_arguments()
1504
- @magic_arguments.argument("name", type=str, default="default", nargs="?")
1505
- @magic_arguments.argument(
1506
- "--remove", action="store_true", help="remove the current transformer"
1507
- )
1508
- @magic_arguments.argument(
1509
- "--list", action="store_true", help="list existing transformers name"
1510
- )
1511
- @magic_arguments.argument(
1512
- "--list-all",
1513
- action="store_true",
1514
- help="list existing transformers name and code template",
1515
- )
1516
- @line_cell_magic
1517
- def code_wrap(self, line, cell=None):
1518
- """
1519
- Simple magic to quickly define a code transformer for all IPython's future input.
1520
-
1521
- ``__code__`` and ``__ret__`` are special variable that represent the code to run
1522
- and the value of the last expression of ``__code__`` respectively.
1523
-
1524
- Examples
1525
- --------
1526
-
1527
- .. ipython::
1528
-
1529
- In [1]: %%code_wrap before_after
1530
- ...: print('before')
1531
- ...: __code__
1532
- ...: print('after')
1533
- ...: __ret__
1534
-
1535
-
1536
- In [2]: 1
1537
- before
1538
- after
1539
- Out[2]: 1
1540
-
1541
- In [3]: %code_wrap --list
1542
- before_after
1543
-
1544
- In [4]: %code_wrap --list-all
1545
- before_after :
1546
- print('before')
1547
- __code__
1548
- print('after')
1549
- __ret__
1550
-
1551
- In [5]: %code_wrap --remove before_after
1552
-
1553
- """
1554
- args = magic_arguments.parse_argstring(self.code_wrap, line)
1555
-
1556
- if args.list:
1557
- for name in self._transformers.keys():
1558
- print(name)
1559
- return
1560
- if args.list_all:
1561
- for name, _t in self._transformers.items():
1562
- print(name, ":")
1563
- print(indent(ast.unparse(_t.template), " "))
1564
- print()
1565
- return
1566
-
1567
- to_remove = self._transformers.pop(args.name, None)
1568
- if to_remove in self.shell.ast_transformers:
1569
- self.shell.ast_transformers.remove(to_remove)
1570
- if cell is None or args.remove:
1571
- return
1572
-
1573
- _trs = ReplaceCodeTransformer(ast.parse(cell))
1574
-
1575
- self._transformers[args.name] = _trs
1576
- self.shell.ast_transformers.append(_trs)
1577
-
1578
-
1579
- def parse_breakpoint(text, current_file):
1580
- '''Returns (file, line) for file:line and (current_file, line) for line'''
1581
- colon = text.find(':')
1582
- if colon == -1:
1583
- return current_file, int(text)
1584
- else:
1585
- return text[:colon], int(text[colon+1:])
1586
-
1587
- def _format_time(timespan, precision=3):
1588
- """Formats the timespan in a human readable form"""
1589
-
1590
- if timespan >= 60.0:
1591
- # we have more than a minute, format that in a human readable form
1592
- # Idea from http://snipplr.com/view/5713/
1593
- parts = [("d", 60*60*24),("h", 60*60),("min", 60), ("s", 1)]
1594
- time = []
1595
- leftover = timespan
1596
- for suffix, length in parts:
1597
- value = int(leftover / length)
1598
- if value > 0:
1599
- leftover = leftover % length
1600
- time.append(u'%s%s' % (str(value), suffix))
1601
- if leftover < 1:
1602
- break
1603
- return " ".join(time)
1604
-
1605
-
1606
- # Unfortunately characters outside of range(128) can cause problems in
1607
- # certain terminals.
1608
- # See bug: https://bugs.launchpad.net/ipython/+bug/348466
1609
- # Try to prevent crashes by being more secure than it needs to
1610
- # E.g. eclipse is able to print a µ, but has no sys.stdout.encoding set.
1611
- units = ["s", "ms", "us", "ns"] # the safe value
1612
- if hasattr(sys.stdout, "encoding") and sys.stdout.encoding:
1613
- try:
1614
- "μ".encode(sys.stdout.encoding)
1615
- units = ["s", "ms", "μs", "ns"]
1616
- except:
1617
- pass
1618
- scaling = [1, 1e3, 1e6, 1e9]
1619
-
1620
- if timespan > 0.0:
1621
- order = min(-int(math.floor(math.log10(timespan)) // 3), 3)
1622
- else:
1623
- order = 3
1624
- return "%.*g %s" % (precision, timespan * scaling[order], units[order])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/extension.py DELETED
@@ -1,63 +0,0 @@
1
- """Implementation of magic functions for the extension machinery.
2
- """
3
- #-----------------------------------------------------------------------------
4
- # Copyright (c) 2012 The IPython Development Team.
5
- #
6
- # Distributed under the terms of the Modified BSD License.
7
- #
8
- # The full license is in the file COPYING.txt, distributed with this software.
9
- #-----------------------------------------------------------------------------
10
-
11
- #-----------------------------------------------------------------------------
12
- # Imports
13
- #-----------------------------------------------------------------------------
14
-
15
-
16
- # Our own packages
17
- from IPython.core.error import UsageError
18
- from IPython.core.magic import Magics, magics_class, line_magic
19
-
20
- #-----------------------------------------------------------------------------
21
- # Magic implementation classes
22
- #-----------------------------------------------------------------------------
23
-
24
- @magics_class
25
- class ExtensionMagics(Magics):
26
- """Magics to manage the IPython extensions system."""
27
-
28
- @line_magic
29
- def load_ext(self, module_str):
30
- """Load an IPython extension by its module name."""
31
- if not module_str:
32
- raise UsageError('Missing module name.')
33
- res = self.shell.extension_manager.load_extension(module_str)
34
-
35
- if res == 'already loaded':
36
- print("The %s extension is already loaded. To reload it, use:" % module_str)
37
- print(" %reload_ext", module_str)
38
- elif res == 'no load function':
39
- print("The %s module is not an IPython extension." % module_str)
40
-
41
- @line_magic
42
- def unload_ext(self, module_str):
43
- """Unload an IPython extension by its module name.
44
-
45
- Not all extensions can be unloaded, only those which define an
46
- ``unload_ipython_extension`` function.
47
- """
48
- if not module_str:
49
- raise UsageError('Missing module name.')
50
-
51
- res = self.shell.extension_manager.unload_extension(module_str)
52
-
53
- if res == 'no unload function':
54
- print("The %s extension doesn't define how to unload it." % module_str)
55
- elif res == "not loaded":
56
- print("The %s extension is not loaded." % module_str)
57
-
58
- @line_magic
59
- def reload_ext(self, module_str):
60
- """Reload an IPython extension by its module name."""
61
- if not module_str:
62
- raise UsageError('Missing module name.')
63
- self.shell.extension_manager.reload_extension(module_str)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/history.py DELETED
@@ -1,338 +0,0 @@
1
- """Implementation of magic functions related to History.
2
- """
3
- #-----------------------------------------------------------------------------
4
- # Copyright (c) 2012, IPython Development Team.
5
- #
6
- # Distributed under the terms of the Modified BSD License.
7
- #
8
- # The full license is in the file COPYING.txt, distributed with this software.
9
- #-----------------------------------------------------------------------------
10
-
11
- #-----------------------------------------------------------------------------
12
- # Imports
13
- #-----------------------------------------------------------------------------
14
-
15
- # Stdlib
16
- import os
17
- import sys
18
- from io import open as io_open
19
- import fnmatch
20
-
21
- # Our own packages
22
- from IPython.core.error import StdinNotImplementedError
23
- from IPython.core.magic import Magics, magics_class, line_magic
24
- from IPython.core.magic_arguments import (argument, magic_arguments,
25
- parse_argstring)
26
- from IPython.testing.skipdoctest import skip_doctest
27
- from IPython.utils import io
28
-
29
- #-----------------------------------------------------------------------------
30
- # Magics class implementation
31
- #-----------------------------------------------------------------------------
32
-
33
-
34
- _unspecified = object()
35
-
36
-
37
- @magics_class
38
- class HistoryMagics(Magics):
39
-
40
- @magic_arguments()
41
- @argument(
42
- '-n', dest='print_nums', action='store_true', default=False,
43
- help="""
44
- print line numbers for each input.
45
- This feature is only available if numbered prompts are in use.
46
- """)
47
- @argument(
48
- '-o', dest='get_output', action='store_true', default=False,
49
- help="also print outputs for each input.")
50
- @argument(
51
- '-p', dest='pyprompts', action='store_true', default=False,
52
- help="""
53
- print classic '>>>' python prompts before each input.
54
- This is useful for making documentation, and in conjunction
55
- with -o, for producing doctest-ready output.
56
- """)
57
- @argument(
58
- '-t', dest='raw', action='store_false', default=True,
59
- help="""
60
- print the 'translated' history, as IPython understands it.
61
- IPython filters your input and converts it all into valid Python
62
- source before executing it (things like magics or aliases are turned
63
- into function calls, for example). With this option, you'll see the
64
- native history instead of the user-entered version: '%%cd /' will be
65
- seen as 'get_ipython().run_line_magic("cd", "/")' instead of '%%cd /'.
66
- """)
67
- @argument(
68
- '-f', dest='filename',
69
- help="""
70
- FILENAME: instead of printing the output to the screen, redirect
71
- it to the given file. The file is always overwritten, though *when
72
- it can*, IPython asks for confirmation first. In particular, running
73
- the command 'history -f FILENAME' from the IPython Notebook
74
- interface will replace FILENAME even if it already exists *without*
75
- confirmation.
76
- """)
77
- @argument(
78
- '-g', dest='pattern', nargs='*', default=None,
79
- help="""
80
- treat the arg as a glob pattern to search for in (full) history.
81
- This includes the saved history (almost all commands ever written).
82
- The pattern may contain '?' to match one unknown character and '*'
83
- to match any number of unknown characters. Use '%%hist -g' to show
84
- full saved history (may be very long).
85
- """)
86
- @argument(
87
- '-l', dest='limit', type=int, nargs='?', default=_unspecified,
88
- help="""
89
- get the last n lines from all sessions. Specify n as a single
90
- arg, or the default is the last 10 lines.
91
- """)
92
- @argument(
93
- '-u', dest='unique', action='store_true',
94
- help="""
95
- when searching history using `-g`, show only unique history.
96
- """)
97
- @argument('range', nargs='*')
98
- @skip_doctest
99
- @line_magic
100
- def history(self, parameter_s = ''):
101
- """Print input history (_i<n> variables), with most recent last.
102
-
103
- By default, input history is printed without line numbers so it can be
104
- directly pasted into an editor. Use -n to show them.
105
-
106
- By default, all input history from the current session is displayed.
107
- Ranges of history can be indicated using the syntax:
108
-
109
- ``4``
110
- Line 4, current session
111
- ``4-6``
112
- Lines 4-6, current session
113
- ``243/1-5``
114
- Lines 1-5, session 243
115
- ``~2/7``
116
- Line 7, session 2 before current
117
- ``~8/1-~6/5``
118
- From the first line of 8 sessions ago, to the fifth line of 6
119
- sessions ago.
120
-
121
- Multiple ranges can be entered, separated by spaces
122
-
123
- The same syntax is used by %macro, %save, %edit, %rerun
124
-
125
- Examples
126
- --------
127
- ::
128
-
129
- In [6]: %history -n 4-6
130
- 4:a = 12
131
- 5:print(a**2)
132
- 6:%history -n 4-6
133
-
134
- """
135
-
136
- args = parse_argstring(self.history, parameter_s)
137
-
138
- # For brevity
139
- history_manager = self.shell.history_manager
140
-
141
- def _format_lineno(session, line):
142
- """Helper function to format line numbers properly."""
143
- if session in (0, history_manager.session_number):
144
- return str(line)
145
- return "%s/%s" % (session, line)
146
-
147
- # Check if output to specific file was requested.
148
- outfname = args.filename
149
- if not outfname:
150
- outfile = sys.stdout # default
151
- # We don't want to close stdout at the end!
152
- close_at_end = False
153
- else:
154
- outfname = os.path.expanduser(outfname)
155
- if os.path.exists(outfname):
156
- try:
157
- ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname)
158
- except StdinNotImplementedError:
159
- ans = True
160
- if not ans:
161
- print('Aborting.')
162
- return
163
- print("Overwriting file.")
164
- outfile = io_open(outfname, 'w', encoding='utf-8')
165
- close_at_end = True
166
-
167
- print_nums = args.print_nums
168
- get_output = args.get_output
169
- pyprompts = args.pyprompts
170
- raw = args.raw
171
-
172
- pattern = None
173
- limit = None if args.limit is _unspecified else args.limit
174
-
175
- range_pattern = False
176
- if args.pattern is not None and not args.range:
177
- if args.pattern:
178
- pattern = "*" + " ".join(args.pattern) + "*"
179
- else:
180
- pattern = "*"
181
- hist = history_manager.search(pattern, raw=raw, output=get_output,
182
- n=limit, unique=args.unique)
183
- print_nums = True
184
- elif args.limit is not _unspecified:
185
- n = 10 if limit is None else limit
186
- hist = history_manager.get_tail(n, raw=raw, output=get_output)
187
- else:
188
- if args.pattern:
189
- range_pattern = "*" + " ".join(args.pattern) + "*"
190
- print_nums = True
191
- hist = history_manager.get_range_by_str(
192
- " ".join(args.range), raw, get_output
193
- )
194
-
195
- # We could be displaying the entire history, so let's not try to pull
196
- # it into a list in memory. Anything that needs more space will just
197
- # misalign.
198
- width = 4
199
-
200
- for session, lineno, inline in hist:
201
- # Print user history with tabs expanded to 4 spaces. The GUI
202
- # clients use hard tabs for easier usability in auto-indented code,
203
- # but we want to produce PEP-8 compliant history for safe pasting
204
- # into an editor.
205
- if get_output:
206
- inline, output = inline
207
- if range_pattern:
208
- if not fnmatch.fnmatch(inline, range_pattern):
209
- continue
210
- inline = inline.expandtabs(4).rstrip()
211
-
212
- multiline = "\n" in inline
213
- line_sep = '\n' if multiline else ' '
214
- if print_nums:
215
- print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width),
216
- line_sep), file=outfile, end=u'')
217
- if pyprompts:
218
- print(u">>> ", end=u"", file=outfile)
219
- if multiline:
220
- inline = "\n... ".join(inline.splitlines()) + "\n..."
221
- print(inline, file=outfile)
222
- if get_output and output:
223
- print(output, file=outfile)
224
-
225
- if close_at_end:
226
- outfile.close()
227
-
228
- @line_magic
229
- def recall(self, arg):
230
- r"""Repeat a command, or get command to input line for editing.
231
-
232
- %recall and %rep are equivalent.
233
-
234
- - %recall (no arguments):
235
-
236
- Place a string version of last computation result (stored in the
237
- special '_' variable) to the next input prompt. Allows you to create
238
- elaborate command lines without using copy-paste::
239
-
240
- In[1]: l = ["hei", "vaan"]
241
- In[2]: "".join(l)
242
- Out[2]: heivaan
243
- In[3]: %recall
244
- In[4]: heivaan_ <== cursor blinking
245
-
246
- %recall 45
247
-
248
- Place history line 45 on the next input prompt. Use %hist to find
249
- out the number.
250
-
251
- %recall 1-4
252
-
253
- Combine the specified lines into one cell, and place it on the next
254
- input prompt. See %history for the slice syntax.
255
-
256
- %recall foo+bar
257
-
258
- If foo+bar can be evaluated in the user namespace, the result is
259
- placed at the next input prompt. Otherwise, the history is searched
260
- for lines which contain that substring, and the most recent one is
261
- placed at the next input prompt.
262
- """
263
- if not arg: # Last output
264
- self.shell.set_next_input(str(self.shell.user_ns["_"]))
265
- return
266
- # Get history range
267
- histlines = self.shell.history_manager.get_range_by_str(arg)
268
- cmd = "\n".join(x[2] for x in histlines)
269
- if cmd:
270
- self.shell.set_next_input(cmd.rstrip())
271
- return
272
-
273
- try: # Variable in user namespace
274
- cmd = str(eval(arg, self.shell.user_ns))
275
- except Exception: # Search for term in history
276
- histlines = self.shell.history_manager.search("*"+arg+"*")
277
- for h in reversed([x[2] for x in histlines]):
278
- if 'recall' in h or 'rep' in h:
279
- continue
280
- self.shell.set_next_input(h.rstrip())
281
- return
282
- else:
283
- self.shell.set_next_input(cmd.rstrip())
284
- return
285
- print("Couldn't evaluate or find in history:", arg)
286
-
287
- @line_magic
288
- def rerun(self, parameter_s=''):
289
- """Re-run previous input
290
-
291
- By default, you can specify ranges of input history to be repeated
292
- (as with %history). With no arguments, it will repeat the last line.
293
-
294
- Options:
295
-
296
- -l <n> : Repeat the last n lines of input, not including the
297
- current command.
298
-
299
- -g foo : Repeat the most recent line which contains foo
300
- """
301
- opts, args = self.parse_options(parameter_s, 'l:g:', mode='string')
302
- if "l" in opts: # Last n lines
303
- try:
304
- n = int(opts["l"])
305
- except ValueError:
306
- print("Number of lines must be an integer")
307
- return
308
-
309
- if n == 0:
310
- print("Requested 0 last lines - nothing to run")
311
- return
312
- elif n < 0:
313
- print("Number of lines to rerun cannot be negative")
314
- return
315
-
316
- hist = self.shell.history_manager.get_tail(n)
317
- elif "g" in opts: # Search
318
- p = "*"+opts['g']+"*"
319
- hist = list(self.shell.history_manager.search(p))
320
- for l in reversed(hist):
321
- if "rerun" not in l[2]:
322
- hist = [l] # The last match which isn't a %rerun
323
- break
324
- else:
325
- hist = [] # No matches except %rerun
326
- elif args: # Specify history ranges
327
- hist = self.shell.history_manager.get_range_by_str(args)
328
- else: # Last line
329
- hist = self.shell.history_manager.get_tail(1)
330
- hist = [x[2] for x in hist]
331
- if not hist:
332
- print("No lines in history match specification")
333
- return
334
- histlines = "\n".join(hist)
335
- print("=== Executing: ===")
336
- print(histlines)
337
- print("=== Output: ===")
338
- self.shell.run_cell("\n".join(hist), store_history=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openalex_env_map/lib/python3.10/site-packages/IPython/core/magics/logging.py DELETED
@@ -1,195 +0,0 @@
1
- """Implementation of magic functions for IPython's own logging.
2
- """
3
- #-----------------------------------------------------------------------------
4
- # Copyright (c) 2012 The IPython Development Team.
5
- #
6
- # Distributed under the terms of the Modified BSD License.
7
- #
8
- # The full license is in the file COPYING.txt, distributed with this software.
9
- #-----------------------------------------------------------------------------
10
-
11
- #-----------------------------------------------------------------------------
12
- # Imports
13
- #-----------------------------------------------------------------------------
14
-
15
- # Stdlib
16
- import os
17
- import sys
18
-
19
- # Our own packages
20
- from IPython.core.magic import Magics, magics_class, line_magic
21
- from warnings import warn
22
- from traitlets import Bool
23
-
24
- #-----------------------------------------------------------------------------
25
- # Magic implementation classes
26
- #-----------------------------------------------------------------------------
27
-
28
- @magics_class
29
- class LoggingMagics(Magics):
30
- """Magics related to all logging machinery."""
31
-
32
- quiet = Bool(False, help=
33
- """
34
- Suppress output of log state when logging is enabled
35
- """
36
- ).tag(config=True)
37
-
38
- @line_magic
39
- def logstart(self, parameter_s=''):
40
- """Start logging anywhere in a session.
41
-
42
- %logstart [-o|-r|-t|-q] [log_name [log_mode]]
43
-
44
- If no name is given, it defaults to a file named 'ipython_log.py' in your
45
- current directory, in 'rotate' mode (see below).
46
-
47
- '%logstart name' saves to file 'name' in 'backup' mode. It saves your
48
- history up to that point and then continues logging.
49
-
50
- %logstart takes a second optional parameter: logging mode. This can be one
51
- of (note that the modes are given unquoted):
52
-
53
- append
54
- Keep logging at the end of any existing file.
55
-
56
- backup
57
- Rename any existing file to name~ and start name.
58
-
59
- global
60
- Append to a single logfile in your home directory.
61
-
62
- over
63
- Overwrite any existing log.
64
-
65
- rotate
66
- Create rotating logs: name.1~, name.2~, etc.
67
-
68
- Options:
69
-
70
- -o
71
- log also IPython's output. In this mode, all commands which
72
- generate an Out[NN] prompt are recorded to the logfile, right after
73
- their corresponding input line. The output lines are always
74
- prepended with a '#[Out]# ' marker, so that the log remains valid
75
- Python code.
76
-
77
- Since this marker is always the same, filtering only the output from
78
- a log is very easy, using for example a simple awk call::
79
-
80
- awk -F'#\\[Out\\]# ' '{if($2) {print $2}}' ipython_log.py
81
-
82
- -r
83
- log 'raw' input. Normally, IPython's logs contain the processed
84
- input, so that user lines are logged in their final form, converted
85
- into valid Python. For example, %Exit is logged as
86
- _ip.run_line_magic("Exit"). If the -r flag is given, all input is logged
87
- exactly as typed, with no transformations applied.
88
-
89
- -t
90
- put timestamps before each input line logged (these are put in
91
- comments).
92
-
93
- -q
94
- suppress output of logstate message when logging is invoked
95
- """
96
-
97
- opts,par = self.parse_options(parameter_s,'ortq')
98
- log_output = 'o' in opts
99
- log_raw_input = 'r' in opts
100
- timestamp = 't' in opts
101
- quiet = 'q' in opts
102
-
103
- logger = self.shell.logger
104
-
105
- # if no args are given, the defaults set in the logger constructor by
106
- # ipython remain valid
107
- if par:
108
- try:
109
- logfname,logmode = par.split()
110
- except:
111
- logfname = par
112
- logmode = 'backup'
113
- else:
114
- logfname = logger.logfname
115
- logmode = logger.logmode
116
- # put logfname into rc struct as if it had been called on the command
117
- # line, so it ends up saved in the log header Save it in case we need
118
- # to restore it...
119
- old_logfile = self.shell.logfile
120
- if logfname:
121
- logfname = os.path.expanduser(logfname)
122
- self.shell.logfile = logfname
123
-
124
- loghead = u'# IPython log file\n\n'
125
- try:
126
- logger.logstart(logfname, loghead, logmode, log_output, timestamp,
127
- log_raw_input)
128
- except:
129
- self.shell.logfile = old_logfile
130
- warn("Couldn't start log: %s" % sys.exc_info()[1])
131
- else:
132
- # log input history up to this point, optionally interleaving
133
- # output if requested
134
-
135
- if timestamp:
136
- # disable timestamping for the previous history, since we've
137
- # lost those already (no time machine here).
138
- logger.timestamp = False
139
-
140
- if log_raw_input:
141
- input_hist = self.shell.history_manager.input_hist_raw
142
- else:
143
- input_hist = self.shell.history_manager.input_hist_parsed
144
-
145
- if log_output:
146
- log_write = logger.log_write
147
- output_hist = self.shell.history_manager.output_hist
148
- for n in range(1,len(input_hist)-1):
149
- log_write(input_hist[n].rstrip() + u'\n')
150
- if n in output_hist:
151
- log_write(repr(output_hist[n]),'output')
152
- else:
153
- logger.log_write(u'\n'.join(input_hist[1:]))
154
- logger.log_write(u'\n')
155
- if timestamp:
156
- # re-enable timestamping
157
- logger.timestamp = True
158
-
159
- if not (self.quiet or quiet):
160
- print ('Activating auto-logging. '
161
- 'Current session state plus future input saved.')
162
- logger.logstate()
163
-
164
- @line_magic
165
- def logstop(self, parameter_s=''):
166
- """Fully stop logging and close log file.
167
-
168
- In order to start logging again, a new %logstart call needs to be made,
169
- possibly (though not necessarily) with a new filename, mode and other
170
- options."""
171
- self.shell.logger.logstop()
172
-
173
- @line_magic
174
- def logoff(self, parameter_s=''):
175
- """Temporarily stop logging.
176
-
177
- You must have previously started logging."""
178
- self.shell.logger.switch_log(0)
179
-
180
- @line_magic
181
- def logon(self, parameter_s=''):
182
- """Restart logging.
183
-
184
- This function is for restarting logging which you've temporarily
185
- stopped with %logoff. For starting logging for the first time, you
186
- must use the %logstart function, which allows you to specify an
187
- optional log filename."""
188
-
189
- self.shell.logger.switch_log(1)
190
-
191
- @line_magic
192
- def logstate(self, parameter_s=''):
193
- """Print the status of the logging system."""
194
-
195
- self.shell.logger.logstate()