##// END OF EJS Templates
add __repr__ to MagicsDisplay (#14378)...
M Bussonnier -
r28698:a570c92c merge
parent child Browse files
Show More
@@ -1,40 +1,40 b''
1 # This workflow will install Python dependencies, run tests and lint with a variety of Python versions
1 # This workflow will install Python dependencies, run tests and lint with a variety of Python versions
2 # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
2 # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
3
3
4 name: Python package
4 name: Python package
5
5
6 permissions:
6 permissions:
7 contents: read
7 contents: read
8
8
9 on:
9 on:
10 push:
10 push:
11 branches: [ main, 7.x ]
11 branches: [ main, 7.x ]
12 pull_request:
12 pull_request:
13 branches: [ main, 7.x ]
13 branches: [ main, 7.x ]
14
14
15 jobs:
15 jobs:
16 formatting:
16 formatting:
17
17
18 runs-on: ubuntu-latest
18 runs-on: ubuntu-latest
19 timeout-minutes: 5
19 timeout-minutes: 5
20 steps:
20 steps:
21 - uses: actions/checkout@v3
21 - uses: actions/checkout@v3
22 with:
22 with:
23 fetch-depth: 0
23 fetch-depth: 0
24 - name: Set up Python
24 - name: Set up Python
25 uses: actions/setup-python@v4
25 uses: actions/setup-python@v4
26 with:
26 with:
27 python-version: 3.x
27 python-version: 3.x
28 - name: Install dependencies
28 - name: Install dependencies
29 run: |
29 run: |
30 python -m pip install --upgrade pip
30 python -m pip install --upgrade pip
31 # when changing the versions please update CONTRIBUTING.md too
31 # when changing the versions please update CONTRIBUTING.md too
32 pip install --only-binary ':all:' darker==1.5.1 black==22.10.0
32 pip install --only-binary ':all:' darker==1.5.1 black==22.10.0
33 - name: Lint with darker
33 - name: Lint with darker
34 run: |
34 run: |
35 darker -r 60625f241f298b5039cb2debc365db38aa7bb522 --check --diff . || (
35 darker -r 60625f241f298b5039cb2debc365db38aa7bb522 --check --diff . || (
36 echo "Changes need auto-formatting. Run:"
36 echo "Changes need auto-formatting. Run:"
37 echo " darker -r 60625f241f298b5039cb2debc365db38aa7bb522"
37 echo " darker -r 60625f241f298b5039cb2debc365db38aa7bb522 ."
38 echo "then commit and push changes to fix."
38 echo "then commit and push changes to fix."
39 exit 1
39 exit 1
40 )
40 )
@@ -1,663 +1,666 b''
1 """Implementation of basic magic functions."""
1 """Implementation of basic magic functions."""
2
2
3
3
4 from logging import error
4 from logging import error
5 import io
5 import io
6 import os
6 import os
7 from pprint import pformat
7 from pprint import pformat
8 import sys
8 import sys
9 from warnings import warn
9 from warnings import warn
10
10
11 from traitlets.utils.importstring import import_item
11 from traitlets.utils.importstring import import_item
12 from IPython.core import magic_arguments, page
12 from IPython.core import magic_arguments, page
13 from IPython.core.error import UsageError
13 from IPython.core.error import UsageError
14 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
14 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
15 from IPython.utils.text import format_screen, dedent, indent
15 from IPython.utils.text import format_screen, dedent, indent
16 from IPython.testing.skipdoctest import skip_doctest
16 from IPython.testing.skipdoctest import skip_doctest
17 from IPython.utils.ipstruct import Struct
17 from IPython.utils.ipstruct import Struct
18
18
19
19
20 class MagicsDisplay(object):
20 class MagicsDisplay(object):
21 def __init__(self, magics_manager, ignore=None):
21 def __init__(self, magics_manager, ignore=None):
22 self.ignore = ignore if ignore else []
22 self.ignore = ignore if ignore else []
23 self.magics_manager = magics_manager
23 self.magics_manager = magics_manager
24
24
25 def _lsmagic(self):
25 def _lsmagic(self):
26 """The main implementation of the %lsmagic"""
26 """The main implementation of the %lsmagic"""
27 mesc = magic_escapes['line']
27 mesc = magic_escapes['line']
28 cesc = magic_escapes['cell']
28 cesc = magic_escapes['cell']
29 mman = self.magics_manager
29 mman = self.magics_manager
30 magics = mman.lsmagic()
30 magics = mman.lsmagic()
31 out = ['Available line magics:',
31 out = ['Available line magics:',
32 mesc + (' '+mesc).join(sorted([m for m,v in magics['line'].items() if (v not in self.ignore)])),
32 mesc + (' '+mesc).join(sorted([m for m,v in magics['line'].items() if (v not in self.ignore)])),
33 '',
33 '',
34 'Available cell magics:',
34 'Available cell magics:',
35 cesc + (' '+cesc).join(sorted([m for m,v in magics['cell'].items() if (v not in self.ignore)])),
35 cesc + (' '+cesc).join(sorted([m for m,v in magics['cell'].items() if (v not in self.ignore)])),
36 '',
36 '',
37 mman.auto_status()]
37 mman.auto_status()]
38 return '\n'.join(out)
38 return '\n'.join(out)
39
39
40 def _repr_pretty_(self, p, cycle):
40 def _repr_pretty_(self, p, cycle):
41 p.text(self._lsmagic())
41 p.text(self._lsmagic())
42
42
43 def __repr__(self):
44 return self.__str__()
45
43 def __str__(self):
46 def __str__(self):
44 return self._lsmagic()
47 return self._lsmagic()
45
48
46 def _jsonable(self):
49 def _jsonable(self):
47 """turn magics dict into jsonable dict of the same structure
50 """turn magics dict into jsonable dict of the same structure
48
51
49 replaces object instances with their class names as strings
52 replaces object instances with their class names as strings
50 """
53 """
51 magic_dict = {}
54 magic_dict = {}
52 mman = self.magics_manager
55 mman = self.magics_manager
53 magics = mman.lsmagic()
56 magics = mman.lsmagic()
54 for key, subdict in magics.items():
57 for key, subdict in magics.items():
55 d = {}
58 d = {}
56 magic_dict[key] = d
59 magic_dict[key] = d
57 for name, obj in subdict.items():
60 for name, obj in subdict.items():
58 try:
61 try:
59 classname = obj.__self__.__class__.__name__
62 classname = obj.__self__.__class__.__name__
60 except AttributeError:
63 except AttributeError:
61 classname = 'Other'
64 classname = 'Other'
62
65
63 d[name] = classname
66 d[name] = classname
64 return magic_dict
67 return magic_dict
65
68
66 def _repr_json_(self):
69 def _repr_json_(self):
67 return self._jsonable()
70 return self._jsonable()
68
71
69
72
70 @magics_class
73 @magics_class
71 class BasicMagics(Magics):
74 class BasicMagics(Magics):
72 """Magics that provide central IPython functionality.
75 """Magics that provide central IPython functionality.
73
76
74 These are various magics that don't fit into specific categories but that
77 These are various magics that don't fit into specific categories but that
75 are all part of the base 'IPython experience'."""
78 are all part of the base 'IPython experience'."""
76
79
77 @skip_doctest
80 @skip_doctest
78 @magic_arguments.magic_arguments()
81 @magic_arguments.magic_arguments()
79 @magic_arguments.argument(
82 @magic_arguments.argument(
80 '-l', '--line', action='store_true',
83 '-l', '--line', action='store_true',
81 help="""Create a line magic alias."""
84 help="""Create a line magic alias."""
82 )
85 )
83 @magic_arguments.argument(
86 @magic_arguments.argument(
84 '-c', '--cell', action='store_true',
87 '-c', '--cell', action='store_true',
85 help="""Create a cell magic alias."""
88 help="""Create a cell magic alias."""
86 )
89 )
87 @magic_arguments.argument(
90 @magic_arguments.argument(
88 'name',
91 'name',
89 help="""Name of the magic to be created."""
92 help="""Name of the magic to be created."""
90 )
93 )
91 @magic_arguments.argument(
94 @magic_arguments.argument(
92 'target',
95 'target',
93 help="""Name of the existing line or cell magic."""
96 help="""Name of the existing line or cell magic."""
94 )
97 )
95 @magic_arguments.argument(
98 @magic_arguments.argument(
96 '-p', '--params', default=None,
99 '-p', '--params', default=None,
97 help="""Parameters passed to the magic function."""
100 help="""Parameters passed to the magic function."""
98 )
101 )
99 @line_magic
102 @line_magic
100 def alias_magic(self, line=''):
103 def alias_magic(self, line=''):
101 """Create an alias for an existing line or cell magic.
104 """Create an alias for an existing line or cell magic.
102
105
103 Examples
106 Examples
104 --------
107 --------
105 ::
108 ::
106
109
107 In [1]: %alias_magic t timeit
110 In [1]: %alias_magic t timeit
108 Created `%t` as an alias for `%timeit`.
111 Created `%t` as an alias for `%timeit`.
109 Created `%%t` as an alias for `%%timeit`.
112 Created `%%t` as an alias for `%%timeit`.
110
113
111 In [2]: %t -n1 pass
114 In [2]: %t -n1 pass
112 107 ns Β± 43.6 ns per loop (mean Β± std. dev. of 7 runs, 1 loop each)
115 107 ns Β± 43.6 ns per loop (mean Β± std. dev. of 7 runs, 1 loop each)
113
116
114 In [3]: %%t -n1
117 In [3]: %%t -n1
115 ...: pass
118 ...: pass
116 ...:
119 ...:
117 107 ns Β± 58.3 ns per loop (mean Β± std. dev. of 7 runs, 1 loop each)
120 107 ns Β± 58.3 ns per loop (mean Β± std. dev. of 7 runs, 1 loop each)
118
121
119 In [4]: %alias_magic --cell whereami pwd
122 In [4]: %alias_magic --cell whereami pwd
120 UsageError: Cell magic function `%%pwd` not found.
123 UsageError: Cell magic function `%%pwd` not found.
121 In [5]: %alias_magic --line whereami pwd
124 In [5]: %alias_magic --line whereami pwd
122 Created `%whereami` as an alias for `%pwd`.
125 Created `%whereami` as an alias for `%pwd`.
123
126
124 In [6]: %whereami
127 In [6]: %whereami
125 Out[6]: '/home/testuser'
128 Out[6]: '/home/testuser'
126
129
127 In [7]: %alias_magic h history -p "-l 30" --line
130 In [7]: %alias_magic h history -p "-l 30" --line
128 Created `%h` as an alias for `%history -l 30`.
131 Created `%h` as an alias for `%history -l 30`.
129 """
132 """
130
133
131 args = magic_arguments.parse_argstring(self.alias_magic, line)
134 args = magic_arguments.parse_argstring(self.alias_magic, line)
132 shell = self.shell
135 shell = self.shell
133 mman = self.shell.magics_manager
136 mman = self.shell.magics_manager
134 escs = ''.join(magic_escapes.values())
137 escs = ''.join(magic_escapes.values())
135
138
136 target = args.target.lstrip(escs)
139 target = args.target.lstrip(escs)
137 name = args.name.lstrip(escs)
140 name = args.name.lstrip(escs)
138
141
139 params = args.params
142 params = args.params
140 if (params and
143 if (params and
141 ((params.startswith('"') and params.endswith('"'))
144 ((params.startswith('"') and params.endswith('"'))
142 or (params.startswith("'") and params.endswith("'")))):
145 or (params.startswith("'") and params.endswith("'")))):
143 params = params[1:-1]
146 params = params[1:-1]
144
147
145 # Find the requested magics.
148 # Find the requested magics.
146 m_line = shell.find_magic(target, 'line')
149 m_line = shell.find_magic(target, 'line')
147 m_cell = shell.find_magic(target, 'cell')
150 m_cell = shell.find_magic(target, 'cell')
148 if args.line and m_line is None:
151 if args.line and m_line is None:
149 raise UsageError('Line magic function `%s%s` not found.' %
152 raise UsageError('Line magic function `%s%s` not found.' %
150 (magic_escapes['line'], target))
153 (magic_escapes['line'], target))
151 if args.cell and m_cell is None:
154 if args.cell and m_cell is None:
152 raise UsageError('Cell magic function `%s%s` not found.' %
155 raise UsageError('Cell magic function `%s%s` not found.' %
153 (magic_escapes['cell'], target))
156 (magic_escapes['cell'], target))
154
157
155 # If --line and --cell are not specified, default to the ones
158 # If --line and --cell are not specified, default to the ones
156 # that are available.
159 # that are available.
157 if not args.line and not args.cell:
160 if not args.line and not args.cell:
158 if not m_line and not m_cell:
161 if not m_line and not m_cell:
159 raise UsageError(
162 raise UsageError(
160 'No line or cell magic with name `%s` found.' % target
163 'No line or cell magic with name `%s` found.' % target
161 )
164 )
162 args.line = bool(m_line)
165 args.line = bool(m_line)
163 args.cell = bool(m_cell)
166 args.cell = bool(m_cell)
164
167
165 params_str = "" if params is None else " " + params
168 params_str = "" if params is None else " " + params
166
169
167 if args.line:
170 if args.line:
168 mman.register_alias(name, target, 'line', params)
171 mman.register_alias(name, target, 'line', params)
169 print('Created `%s%s` as an alias for `%s%s%s`.' % (
172 print('Created `%s%s` as an alias for `%s%s%s`.' % (
170 magic_escapes['line'], name,
173 magic_escapes['line'], name,
171 magic_escapes['line'], target, params_str))
174 magic_escapes['line'], target, params_str))
172
175
173 if args.cell:
176 if args.cell:
174 mman.register_alias(name, target, 'cell', params)
177 mman.register_alias(name, target, 'cell', params)
175 print('Created `%s%s` as an alias for `%s%s%s`.' % (
178 print('Created `%s%s` as an alias for `%s%s%s`.' % (
176 magic_escapes['cell'], name,
179 magic_escapes['cell'], name,
177 magic_escapes['cell'], target, params_str))
180 magic_escapes['cell'], target, params_str))
178
181
179 @line_magic
182 @line_magic
180 def lsmagic(self, parameter_s=''):
183 def lsmagic(self, parameter_s=''):
181 """List currently available magic functions."""
184 """List currently available magic functions."""
182 return MagicsDisplay(self.shell.magics_manager, ignore=[])
185 return MagicsDisplay(self.shell.magics_manager, ignore=[])
183
186
184 def _magic_docs(self, brief=False, rest=False):
187 def _magic_docs(self, brief=False, rest=False):
185 """Return docstrings from magic functions."""
188 """Return docstrings from magic functions."""
186 mman = self.shell.magics_manager
189 mman = self.shell.magics_manager
187 docs = mman.lsmagic_docs(brief, missing='No documentation')
190 docs = mman.lsmagic_docs(brief, missing='No documentation')
188
191
189 if rest:
192 if rest:
190 format_string = '**%s%s**::\n\n%s\n\n'
193 format_string = '**%s%s**::\n\n%s\n\n'
191 else:
194 else:
192 format_string = '%s%s:\n%s\n'
195 format_string = '%s%s:\n%s\n'
193
196
194 return ''.join(
197 return ''.join(
195 [format_string % (magic_escapes['line'], fname,
198 [format_string % (magic_escapes['line'], fname,
196 indent(dedent(fndoc)))
199 indent(dedent(fndoc)))
197 for fname, fndoc in sorted(docs['line'].items())]
200 for fname, fndoc in sorted(docs['line'].items())]
198 +
201 +
199 [format_string % (magic_escapes['cell'], fname,
202 [format_string % (magic_escapes['cell'], fname,
200 indent(dedent(fndoc)))
203 indent(dedent(fndoc)))
201 for fname, fndoc in sorted(docs['cell'].items())]
204 for fname, fndoc in sorted(docs['cell'].items())]
202 )
205 )
203
206
204 @line_magic
207 @line_magic
205 def magic(self, parameter_s=''):
208 def magic(self, parameter_s=''):
206 """Print information about the magic function system.
209 """Print information about the magic function system.
207
210
208 Supported formats: -latex, -brief, -rest
211 Supported formats: -latex, -brief, -rest
209 """
212 """
210
213
211 mode = ''
214 mode = ''
212 try:
215 try:
213 mode = parameter_s.split()[0][1:]
216 mode = parameter_s.split()[0][1:]
214 except IndexError:
217 except IndexError:
215 pass
218 pass
216
219
217 brief = (mode == 'brief')
220 brief = (mode == 'brief')
218 rest = (mode == 'rest')
221 rest = (mode == 'rest')
219 magic_docs = self._magic_docs(brief, rest)
222 magic_docs = self._magic_docs(brief, rest)
220
223
221 if mode == 'latex':
224 if mode == 'latex':
222 print(self.format_latex(magic_docs))
225 print(self.format_latex(magic_docs))
223 return
226 return
224 else:
227 else:
225 magic_docs = format_screen(magic_docs)
228 magic_docs = format_screen(magic_docs)
226
229
227 out = ["""
230 out = ["""
228 IPython's 'magic' functions
231 IPython's 'magic' functions
229 ===========================
232 ===========================
230
233
231 The magic function system provides a series of functions which allow you to
234 The magic function system provides a series of functions which allow you to
232 control the behavior of IPython itself, plus a lot of system-type
235 control the behavior of IPython itself, plus a lot of system-type
233 features. There are two kinds of magics, line-oriented and cell-oriented.
236 features. There are two kinds of magics, line-oriented and cell-oriented.
234
237
235 Line magics are prefixed with the % character and work much like OS
238 Line magics are prefixed with the % character and work much like OS
236 command-line calls: they get as an argument the rest of the line, where
239 command-line calls: they get as an argument the rest of the line, where
237 arguments are passed without parentheses or quotes. For example, this will
240 arguments are passed without parentheses or quotes. For example, this will
238 time the given statement::
241 time the given statement::
239
242
240 %timeit range(1000)
243 %timeit range(1000)
241
244
242 Cell magics are prefixed with a double %%, and they are functions that get as
245 Cell magics are prefixed with a double %%, and they are functions that get as
243 an argument not only the rest of the line, but also the lines below it in a
246 an argument not only the rest of the line, but also the lines below it in a
244 separate argument. These magics are called with two arguments: the rest of the
247 separate argument. These magics are called with two arguments: the rest of the
245 call line and the body of the cell, consisting of the lines below the first.
248 call line and the body of the cell, consisting of the lines below the first.
246 For example::
249 For example::
247
250
248 %%timeit x = numpy.random.randn((100, 100))
251 %%timeit x = numpy.random.randn((100, 100))
249 numpy.linalg.svd(x)
252 numpy.linalg.svd(x)
250
253
251 will time the execution of the numpy svd routine, running the assignment of x
254 will time the execution of the numpy svd routine, running the assignment of x
252 as part of the setup phase, which is not timed.
255 as part of the setup phase, which is not timed.
253
256
254 In a line-oriented client (the terminal or Qt console IPython), starting a new
257 In a line-oriented client (the terminal or Qt console IPython), starting a new
255 input with %% will automatically enter cell mode, and IPython will continue
258 input with %% will automatically enter cell mode, and IPython will continue
256 reading input until a blank line is given. In the notebook, simply type the
259 reading input until a blank line is given. In the notebook, simply type the
257 whole cell as one entity, but keep in mind that the %% escape can only be at
260 whole cell as one entity, but keep in mind that the %% escape can only be at
258 the very start of the cell.
261 the very start of the cell.
259
262
260 NOTE: If you have 'automagic' enabled (via the command line option or with the
263 NOTE: If you have 'automagic' enabled (via the command line option or with the
261 %automagic function), you don't need to type in the % explicitly for line
264 %automagic function), you don't need to type in the % explicitly for line
262 magics; cell magics always require an explicit '%%' escape. By default,
265 magics; cell magics always require an explicit '%%' escape. By default,
263 IPython ships with automagic on, so you should only rarely need the % escape.
266 IPython ships with automagic on, so you should only rarely need the % escape.
264
267
265 Example: typing '%cd mydir' (without the quotes) changes your working directory
268 Example: typing '%cd mydir' (without the quotes) changes your working directory
266 to 'mydir', if it exists.
269 to 'mydir', if it exists.
267
270
268 For a list of the available magic functions, use %lsmagic. For a description
271 For a list of the available magic functions, use %lsmagic. For a description
269 of any of them, type %magic_name?, e.g. '%cd?'.
272 of any of them, type %magic_name?, e.g. '%cd?'.
270
273
271 Currently the magic system has the following functions:""",
274 Currently the magic system has the following functions:""",
272 magic_docs,
275 magic_docs,
273 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
276 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
274 str(self.lsmagic()),
277 str(self.lsmagic()),
275 ]
278 ]
276 page.page('\n'.join(out))
279 page.page('\n'.join(out))
277
280
278
281
279 @line_magic
282 @line_magic
280 def page(self, parameter_s=''):
283 def page(self, parameter_s=''):
281 """Pretty print the object and display it through a pager.
284 """Pretty print the object and display it through a pager.
282
285
283 %page [options] OBJECT
286 %page [options] OBJECT
284
287
285 If no object is given, use _ (last output).
288 If no object is given, use _ (last output).
286
289
287 Options:
290 Options:
288
291
289 -r: page str(object), don't pretty-print it."""
292 -r: page str(object), don't pretty-print it."""
290
293
291 # After a function contributed by Olivier Aubert, slightly modified.
294 # After a function contributed by Olivier Aubert, slightly modified.
292
295
293 # Process options/args
296 # Process options/args
294 opts, args = self.parse_options(parameter_s, 'r')
297 opts, args = self.parse_options(parameter_s, 'r')
295 raw = 'r' in opts
298 raw = 'r' in opts
296
299
297 oname = args and args or '_'
300 oname = args and args or '_'
298 info = self.shell._ofind(oname)
301 info = self.shell._ofind(oname)
299 if info.found:
302 if info.found:
300 if raw:
303 if raw:
301 txt = str(info.obj)
304 txt = str(info.obj)
302 else:
305 else:
303 txt = pformat(info.obj)
306 txt = pformat(info.obj)
304 page.page(txt)
307 page.page(txt)
305 else:
308 else:
306 print('Object `%s` not found' % oname)
309 print('Object `%s` not found' % oname)
307
310
308 @line_magic
311 @line_magic
309 def pprint(self, parameter_s=''):
312 def pprint(self, parameter_s=''):
310 """Toggle pretty printing on/off."""
313 """Toggle pretty printing on/off."""
311 ptformatter = self.shell.display_formatter.formatters['text/plain']
314 ptformatter = self.shell.display_formatter.formatters['text/plain']
312 ptformatter.pprint = bool(1 - ptformatter.pprint)
315 ptformatter.pprint = bool(1 - ptformatter.pprint)
313 print('Pretty printing has been turned',
316 print('Pretty printing has been turned',
314 ['OFF','ON'][ptformatter.pprint])
317 ['OFF','ON'][ptformatter.pprint])
315
318
316 @line_magic
319 @line_magic
317 def colors(self, parameter_s=''):
320 def colors(self, parameter_s=''):
318 """Switch color scheme for prompts, info system and exception handlers.
321 """Switch color scheme for prompts, info system and exception handlers.
319
322
320 Currently implemented schemes: NoColor, Linux, LightBG.
323 Currently implemented schemes: NoColor, Linux, LightBG.
321
324
322 Color scheme names are not case-sensitive.
325 Color scheme names are not case-sensitive.
323
326
324 Examples
327 Examples
325 --------
328 --------
326 To get a plain black and white terminal::
329 To get a plain black and white terminal::
327
330
328 %colors nocolor
331 %colors nocolor
329 """
332 """
330 def color_switch_err(name):
333 def color_switch_err(name):
331 warn('Error changing %s color schemes.\n%s' %
334 warn('Error changing %s color schemes.\n%s' %
332 (name, sys.exc_info()[1]), stacklevel=2)
335 (name, sys.exc_info()[1]), stacklevel=2)
333
336
334
337
335 new_scheme = parameter_s.strip()
338 new_scheme = parameter_s.strip()
336 if not new_scheme:
339 if not new_scheme:
337 raise UsageError(
340 raise UsageError(
338 "%colors: you must specify a color scheme. See '%colors?'")
341 "%colors: you must specify a color scheme. See '%colors?'")
339 # local shortcut
342 # local shortcut
340 shell = self.shell
343 shell = self.shell
341
344
342 # Set shell colour scheme
345 # Set shell colour scheme
343 try:
346 try:
344 shell.colors = new_scheme
347 shell.colors = new_scheme
345 shell.refresh_style()
348 shell.refresh_style()
346 except:
349 except:
347 color_switch_err('shell')
350 color_switch_err('shell')
348
351
349 # Set exception colors
352 # Set exception colors
350 try:
353 try:
351 shell.InteractiveTB.set_colors(scheme = new_scheme)
354 shell.InteractiveTB.set_colors(scheme = new_scheme)
352 shell.SyntaxTB.set_colors(scheme = new_scheme)
355 shell.SyntaxTB.set_colors(scheme = new_scheme)
353 except:
356 except:
354 color_switch_err('exception')
357 color_switch_err('exception')
355
358
356 # Set info (for 'object?') colors
359 # Set info (for 'object?') colors
357 if shell.color_info:
360 if shell.color_info:
358 try:
361 try:
359 shell.inspector.set_active_scheme(new_scheme)
362 shell.inspector.set_active_scheme(new_scheme)
360 except:
363 except:
361 color_switch_err('object inspector')
364 color_switch_err('object inspector')
362 else:
365 else:
363 shell.inspector.set_active_scheme('NoColor')
366 shell.inspector.set_active_scheme('NoColor')
364
367
365 @line_magic
368 @line_magic
366 def xmode(self, parameter_s=''):
369 def xmode(self, parameter_s=''):
367 """Switch modes for the exception handlers.
370 """Switch modes for the exception handlers.
368
371
369 Valid modes: Plain, Context, Verbose, and Minimal.
372 Valid modes: Plain, Context, Verbose, and Minimal.
370
373
371 If called without arguments, acts as a toggle.
374 If called without arguments, acts as a toggle.
372
375
373 When in verbose mode the value `--show` (and `--hide`)
376 When in verbose mode the value `--show` (and `--hide`)
374 will respectively show (or hide) frames with ``__tracebackhide__ =
377 will respectively show (or hide) frames with ``__tracebackhide__ =
375 True`` value set.
378 True`` value set.
376 """
379 """
377
380
378 def xmode_switch_err(name):
381 def xmode_switch_err(name):
379 warn('Error changing %s exception modes.\n%s' %
382 warn('Error changing %s exception modes.\n%s' %
380 (name,sys.exc_info()[1]))
383 (name,sys.exc_info()[1]))
381
384
382 shell = self.shell
385 shell = self.shell
383 if parameter_s.strip() == "--show":
386 if parameter_s.strip() == "--show":
384 shell.InteractiveTB.skip_hidden = False
387 shell.InteractiveTB.skip_hidden = False
385 return
388 return
386 if parameter_s.strip() == "--hide":
389 if parameter_s.strip() == "--hide":
387 shell.InteractiveTB.skip_hidden = True
390 shell.InteractiveTB.skip_hidden = True
388 return
391 return
389
392
390 new_mode = parameter_s.strip().capitalize()
393 new_mode = parameter_s.strip().capitalize()
391 try:
394 try:
392 shell.InteractiveTB.set_mode(mode=new_mode)
395 shell.InteractiveTB.set_mode(mode=new_mode)
393 print('Exception reporting mode:',shell.InteractiveTB.mode)
396 print('Exception reporting mode:',shell.InteractiveTB.mode)
394 except:
397 except:
395 xmode_switch_err('user')
398 xmode_switch_err('user')
396
399
397 @line_magic
400 @line_magic
398 def quickref(self, arg):
401 def quickref(self, arg):
399 """ Show a quick reference sheet """
402 """ Show a quick reference sheet """
400 from IPython.core.usage import quick_reference
403 from IPython.core.usage import quick_reference
401 qr = quick_reference + self._magic_docs(brief=True)
404 qr = quick_reference + self._magic_docs(brief=True)
402 page.page(qr)
405 page.page(qr)
403
406
404 @line_magic
407 @line_magic
405 def doctest_mode(self, parameter_s=''):
408 def doctest_mode(self, parameter_s=''):
406 """Toggle doctest mode on and off.
409 """Toggle doctest mode on and off.
407
410
408 This mode is intended to make IPython behave as much as possible like a
411 This mode is intended to make IPython behave as much as possible like a
409 plain Python shell, from the perspective of how its prompts, exceptions
412 plain Python shell, from the perspective of how its prompts, exceptions
410 and output look. This makes it easy to copy and paste parts of a
413 and output look. This makes it easy to copy and paste parts of a
411 session into doctests. It does so by:
414 session into doctests. It does so by:
412
415
413 - Changing the prompts to the classic ``>>>`` ones.
416 - Changing the prompts to the classic ``>>>`` ones.
414 - Changing the exception reporting mode to 'Plain'.
417 - Changing the exception reporting mode to 'Plain'.
415 - Disabling pretty-printing of output.
418 - Disabling pretty-printing of output.
416
419
417 Note that IPython also supports the pasting of code snippets that have
420 Note that IPython also supports the pasting of code snippets that have
418 leading '>>>' and '...' prompts in them. This means that you can paste
421 leading '>>>' and '...' prompts in them. This means that you can paste
419 doctests from files or docstrings (even if they have leading
422 doctests from files or docstrings (even if they have leading
420 whitespace), and the code will execute correctly. You can then use
423 whitespace), and the code will execute correctly. You can then use
421 '%history -t' to see the translated history; this will give you the
424 '%history -t' to see the translated history; this will give you the
422 input after removal of all the leading prompts and whitespace, which
425 input after removal of all the leading prompts and whitespace, which
423 can be pasted back into an editor.
426 can be pasted back into an editor.
424
427
425 With these features, you can switch into this mode easily whenever you
428 With these features, you can switch into this mode easily whenever you
426 need to do testing and changes to doctests, without having to leave
429 need to do testing and changes to doctests, without having to leave
427 your existing IPython session.
430 your existing IPython session.
428 """
431 """
429
432
430 # Shorthands
433 # Shorthands
431 shell = self.shell
434 shell = self.shell
432 meta = shell.meta
435 meta = shell.meta
433 disp_formatter = self.shell.display_formatter
436 disp_formatter = self.shell.display_formatter
434 ptformatter = disp_formatter.formatters['text/plain']
437 ptformatter = disp_formatter.formatters['text/plain']
435 # dstore is a data store kept in the instance metadata bag to track any
438 # dstore is a data store kept in the instance metadata bag to track any
436 # changes we make, so we can undo them later.
439 # changes we make, so we can undo them later.
437 dstore = meta.setdefault('doctest_mode',Struct())
440 dstore = meta.setdefault('doctest_mode',Struct())
438 save_dstore = dstore.setdefault
441 save_dstore = dstore.setdefault
439
442
440 # save a few values we'll need to recover later
443 # save a few values we'll need to recover later
441 mode = save_dstore('mode',False)
444 mode = save_dstore('mode',False)
442 save_dstore('rc_pprint',ptformatter.pprint)
445 save_dstore('rc_pprint',ptformatter.pprint)
443 save_dstore('xmode',shell.InteractiveTB.mode)
446 save_dstore('xmode',shell.InteractiveTB.mode)
444 save_dstore('rc_separate_out',shell.separate_out)
447 save_dstore('rc_separate_out',shell.separate_out)
445 save_dstore('rc_separate_out2',shell.separate_out2)
448 save_dstore('rc_separate_out2',shell.separate_out2)
446 save_dstore('rc_separate_in',shell.separate_in)
449 save_dstore('rc_separate_in',shell.separate_in)
447 save_dstore('rc_active_types',disp_formatter.active_types)
450 save_dstore('rc_active_types',disp_formatter.active_types)
448
451
449 if not mode:
452 if not mode:
450 # turn on
453 # turn on
451
454
452 # Prompt separators like plain python
455 # Prompt separators like plain python
453 shell.separate_in = ''
456 shell.separate_in = ''
454 shell.separate_out = ''
457 shell.separate_out = ''
455 shell.separate_out2 = ''
458 shell.separate_out2 = ''
456
459
457
460
458 ptformatter.pprint = False
461 ptformatter.pprint = False
459 disp_formatter.active_types = ['text/plain']
462 disp_formatter.active_types = ['text/plain']
460
463
461 shell.magic('xmode Plain')
464 shell.magic('xmode Plain')
462 else:
465 else:
463 # turn off
466 # turn off
464 shell.separate_in = dstore.rc_separate_in
467 shell.separate_in = dstore.rc_separate_in
465
468
466 shell.separate_out = dstore.rc_separate_out
469 shell.separate_out = dstore.rc_separate_out
467 shell.separate_out2 = dstore.rc_separate_out2
470 shell.separate_out2 = dstore.rc_separate_out2
468
471
469 ptformatter.pprint = dstore.rc_pprint
472 ptformatter.pprint = dstore.rc_pprint
470 disp_formatter.active_types = dstore.rc_active_types
473 disp_formatter.active_types = dstore.rc_active_types
471
474
472 shell.magic('xmode ' + dstore.xmode)
475 shell.magic('xmode ' + dstore.xmode)
473
476
474 # mode here is the state before we switch; switch_doctest_mode takes
477 # mode here is the state before we switch; switch_doctest_mode takes
475 # the mode we're switching to.
478 # the mode we're switching to.
476 shell.switch_doctest_mode(not mode)
479 shell.switch_doctest_mode(not mode)
477
480
478 # Store new mode and inform
481 # Store new mode and inform
479 dstore.mode = bool(not mode)
482 dstore.mode = bool(not mode)
480 mode_label = ['OFF','ON'][dstore.mode]
483 mode_label = ['OFF','ON'][dstore.mode]
481 print('Doctest mode is:', mode_label)
484 print('Doctest mode is:', mode_label)
482
485
483 @line_magic
486 @line_magic
484 def gui(self, parameter_s=''):
487 def gui(self, parameter_s=''):
485 """Enable or disable IPython GUI event loop integration.
488 """Enable or disable IPython GUI event loop integration.
486
489
487 %gui [GUINAME]
490 %gui [GUINAME]
488
491
489 This magic replaces IPython's threaded shells that were activated
492 This magic replaces IPython's threaded shells that were activated
490 using the (pylab/wthread/etc.) command line flags. GUI toolkits
493 using the (pylab/wthread/etc.) command line flags. GUI toolkits
491 can now be enabled at runtime and keyboard
494 can now be enabled at runtime and keyboard
492 interrupts should work without any problems. The following toolkits
495 interrupts should work without any problems. The following toolkits
493 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
496 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
494
497
495 %gui wx # enable wxPython event loop integration
498 %gui wx # enable wxPython event loop integration
496 %gui qt # enable PyQt/PySide event loop integration
499 %gui qt # enable PyQt/PySide event loop integration
497 # with the latest version available.
500 # with the latest version available.
498 %gui qt6 # enable PyQt6/PySide6 event loop integration
501 %gui qt6 # enable PyQt6/PySide6 event loop integration
499 %gui qt5 # enable PyQt5/PySide2 event loop integration
502 %gui qt5 # enable PyQt5/PySide2 event loop integration
500 %gui gtk # enable PyGTK event loop integration
503 %gui gtk # enable PyGTK event loop integration
501 %gui gtk3 # enable Gtk3 event loop integration
504 %gui gtk3 # enable Gtk3 event loop integration
502 %gui gtk4 # enable Gtk4 event loop integration
505 %gui gtk4 # enable Gtk4 event loop integration
503 %gui tk # enable Tk event loop integration
506 %gui tk # enable Tk event loop integration
504 %gui osx # enable Cocoa event loop integration
507 %gui osx # enable Cocoa event loop integration
505 # (requires %matplotlib 1.1)
508 # (requires %matplotlib 1.1)
506 %gui # disable all event loop integration
509 %gui # disable all event loop integration
507
510
508 WARNING: after any of these has been called you can simply create
511 WARNING: after any of these has been called you can simply create
509 an application object, but DO NOT start the event loop yourself, as
512 an application object, but DO NOT start the event loop yourself, as
510 we have already handled that.
513 we have already handled that.
511 """
514 """
512 opts, arg = self.parse_options(parameter_s, '')
515 opts, arg = self.parse_options(parameter_s, '')
513 if arg=='': arg = None
516 if arg=='': arg = None
514 try:
517 try:
515 return self.shell.enable_gui(arg)
518 return self.shell.enable_gui(arg)
516 except Exception as e:
519 except Exception as e:
517 # print simple error message, rather than traceback if we can't
520 # print simple error message, rather than traceback if we can't
518 # hook up the GUI
521 # hook up the GUI
519 error(str(e))
522 error(str(e))
520
523
521 @skip_doctest
524 @skip_doctest
522 @line_magic
525 @line_magic
523 def precision(self, s=''):
526 def precision(self, s=''):
524 """Set floating point precision for pretty printing.
527 """Set floating point precision for pretty printing.
525
528
526 Can set either integer precision or a format string.
529 Can set either integer precision or a format string.
527
530
528 If numpy has been imported and precision is an int,
531 If numpy has been imported and precision is an int,
529 numpy display precision will also be set, via ``numpy.set_printoptions``.
532 numpy display precision will also be set, via ``numpy.set_printoptions``.
530
533
531 If no argument is given, defaults will be restored.
534 If no argument is given, defaults will be restored.
532
535
533 Examples
536 Examples
534 --------
537 --------
535 ::
538 ::
536
539
537 In [1]: from math import pi
540 In [1]: from math import pi
538
541
539 In [2]: %precision 3
542 In [2]: %precision 3
540 Out[2]: '%.3f'
543 Out[2]: '%.3f'
541
544
542 In [3]: pi
545 In [3]: pi
543 Out[3]: 3.142
546 Out[3]: 3.142
544
547
545 In [4]: %precision %i
548 In [4]: %precision %i
546 Out[4]: '%i'
549 Out[4]: '%i'
547
550
548 In [5]: pi
551 In [5]: pi
549 Out[5]: 3
552 Out[5]: 3
550
553
551 In [6]: %precision %e
554 In [6]: %precision %e
552 Out[6]: '%e'
555 Out[6]: '%e'
553
556
554 In [7]: pi**10
557 In [7]: pi**10
555 Out[7]: 9.364805e+04
558 Out[7]: 9.364805e+04
556
559
557 In [8]: %precision
560 In [8]: %precision
558 Out[8]: '%r'
561 Out[8]: '%r'
559
562
560 In [9]: pi**10
563 In [9]: pi**10
561 Out[9]: 93648.047476082982
564 Out[9]: 93648.047476082982
562 """
565 """
563 ptformatter = self.shell.display_formatter.formatters['text/plain']
566 ptformatter = self.shell.display_formatter.formatters['text/plain']
564 ptformatter.float_precision = s
567 ptformatter.float_precision = s
565 return ptformatter.float_format
568 return ptformatter.float_format
566
569
567 @magic_arguments.magic_arguments()
570 @magic_arguments.magic_arguments()
568 @magic_arguments.argument(
571 @magic_arguments.argument(
569 'filename', type=str,
572 'filename', type=str,
570 help='Notebook name or filename'
573 help='Notebook name or filename'
571 )
574 )
572 @line_magic
575 @line_magic
573 def notebook(self, s):
576 def notebook(self, s):
574 """Export and convert IPython notebooks.
577 """Export and convert IPython notebooks.
575
578
576 This function can export the current IPython history to a notebook file.
579 This function can export the current IPython history to a notebook file.
577 For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb".
580 For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb".
578 """
581 """
579 args = magic_arguments.parse_argstring(self.notebook, s)
582 args = magic_arguments.parse_argstring(self.notebook, s)
580 outfname = os.path.expanduser(args.filename)
583 outfname = os.path.expanduser(args.filename)
581
584
582 from nbformat import write, v4
585 from nbformat import write, v4
583
586
584 cells = []
587 cells = []
585 hist = list(self.shell.history_manager.get_range())
588 hist = list(self.shell.history_manager.get_range())
586 if(len(hist)<=1):
589 if(len(hist)<=1):
587 raise ValueError('History is empty, cannot export')
590 raise ValueError('History is empty, cannot export')
588 for session, execution_count, source in hist[:-1]:
591 for session, execution_count, source in hist[:-1]:
589 cells.append(v4.new_code_cell(
592 cells.append(v4.new_code_cell(
590 execution_count=execution_count,
593 execution_count=execution_count,
591 source=source
594 source=source
592 ))
595 ))
593 nb = v4.new_notebook(cells=cells)
596 nb = v4.new_notebook(cells=cells)
594 with io.open(outfname, "w", encoding="utf-8") as f:
597 with io.open(outfname, "w", encoding="utf-8") as f:
595 write(nb, f, version=4)
598 write(nb, f, version=4)
596
599
597 @magics_class
600 @magics_class
598 class AsyncMagics(BasicMagics):
601 class AsyncMagics(BasicMagics):
599
602
600 @line_magic
603 @line_magic
601 def autoawait(self, parameter_s):
604 def autoawait(self, parameter_s):
602 """
605 """
603 Allow to change the status of the autoawait option.
606 Allow to change the status of the autoawait option.
604
607
605 This allow you to set a specific asynchronous code runner.
608 This allow you to set a specific asynchronous code runner.
606
609
607 If no value is passed, print the currently used asynchronous integration
610 If no value is passed, print the currently used asynchronous integration
608 and whether it is activated.
611 and whether it is activated.
609
612
610 It can take a number of value evaluated in the following order:
613 It can take a number of value evaluated in the following order:
611
614
612 - False/false/off deactivate autoawait integration
615 - False/false/off deactivate autoawait integration
613 - True/true/on activate autoawait integration using configured default
616 - True/true/on activate autoawait integration using configured default
614 loop
617 loop
615 - asyncio/curio/trio activate autoawait integration and use integration
618 - asyncio/curio/trio activate autoawait integration and use integration
616 with said library.
619 with said library.
617
620
618 - `sync` turn on the pseudo-sync integration (mostly used for
621 - `sync` turn on the pseudo-sync integration (mostly used for
619 `IPython.embed()` which does not run IPython with a real eventloop and
622 `IPython.embed()` which does not run IPython with a real eventloop and
620 deactivate running asynchronous code. Turning on Asynchronous code with
623 deactivate running asynchronous code. Turning on Asynchronous code with
621 the pseudo sync loop is undefined behavior and may lead IPython to crash.
624 the pseudo sync loop is undefined behavior and may lead IPython to crash.
622
625
623 If the passed parameter does not match any of the above and is a python
626 If the passed parameter does not match any of the above and is a python
624 identifier, get said object from user namespace and set it as the
627 identifier, get said object from user namespace and set it as the
625 runner, and activate autoawait.
628 runner, and activate autoawait.
626
629
627 If the object is a fully qualified object name, attempt to import it and
630 If the object is a fully qualified object name, attempt to import it and
628 set it as the runner, and activate autoawait.
631 set it as the runner, and activate autoawait.
629
632
630 The exact behavior of autoawait is experimental and subject to change
633 The exact behavior of autoawait is experimental and subject to change
631 across version of IPython and Python.
634 across version of IPython and Python.
632 """
635 """
633
636
634 param = parameter_s.strip()
637 param = parameter_s.strip()
635 d = {True: "on", False: "off"}
638 d = {True: "on", False: "off"}
636
639
637 if not param:
640 if not param:
638 print("IPython autoawait is `{}`, and set to use `{}`".format(
641 print("IPython autoawait is `{}`, and set to use `{}`".format(
639 d[self.shell.autoawait],
642 d[self.shell.autoawait],
640 self.shell.loop_runner
643 self.shell.loop_runner
641 ))
644 ))
642 return None
645 return None
643
646
644 if param.lower() in ('false', 'off'):
647 if param.lower() in ('false', 'off'):
645 self.shell.autoawait = False
648 self.shell.autoawait = False
646 return None
649 return None
647 if param.lower() in ('true', 'on'):
650 if param.lower() in ('true', 'on'):
648 self.shell.autoawait = True
651 self.shell.autoawait = True
649 return None
652 return None
650
653
651 if param in self.shell.loop_runner_map:
654 if param in self.shell.loop_runner_map:
652 self.shell.loop_runner, self.shell.autoawait = self.shell.loop_runner_map[param]
655 self.shell.loop_runner, self.shell.autoawait = self.shell.loop_runner_map[param]
653 return None
656 return None
654
657
655 if param in self.shell.user_ns :
658 if param in self.shell.user_ns :
656 self.shell.loop_runner = self.shell.user_ns[param]
659 self.shell.loop_runner = self.shell.user_ns[param]
657 self.shell.autoawait = True
660 self.shell.autoawait = True
658 return None
661 return None
659
662
660 runner = import_item(param)
663 runner = import_item(param)
661
664
662 self.shell.loop_runner = runner
665 self.shell.loop_runner = runner
663 self.shell.autoawait = True
666 self.shell.autoawait = True
General Comments 0
You need to be logged in to leave comments. Login now