Show More
@@ -0,0 +1,25 b'' | |||||
|
1 | History Range Glob feature | |||
|
2 | ========================== | |||
|
3 | ||||
|
4 | Previously, when using ``%history``, users could specify either | |||
|
5 | a range of sessions and lines, for example: | |||
|
6 | ||||
|
7 | .. code-block:: python | |||
|
8 | ||||
|
9 | ~8/1-~6/5 # see history from the first line of 8 sessions ago, | |||
|
10 | # to the fifth line of 6 sessions ago.`` | |||
|
11 | ||||
|
12 | Or users could specify a glob pattern: | |||
|
13 | ||||
|
14 | .. code-block:: python | |||
|
15 | ||||
|
16 | -g <pattern> # glob ALL history for the specified pattern. | |||
|
17 | ||||
|
18 | However users could *not* specify both. | |||
|
19 | ||||
|
20 | If a user *did* specify both a range and a glob pattern, | |||
|
21 | then the glob pattern would be used (globbing *all* history) *and the range would be ignored*. | |||
|
22 | ||||
|
23 | --- | |||
|
24 | ||||
|
25 | With this enhancment, if a user specifies both a range and a glob pattern, then the glob pattern will be applied to the specified range of history. |
@@ -0,0 +1,7 b'' | |||||
|
1 | Don't start a multiline cell with sunken parenthesis | |||
|
2 | ---------------------------------------------------- | |||
|
3 | ||||
|
4 | From now on IPython will not ask for the next line of input when given a single | |||
|
5 | line with more closing than opening brackets. For example, this means that if | |||
|
6 | you (mis)type ']]' instead of '[]', a ``SyntaxError`` will show up, instead of | |||
|
7 | the ``...:`` prompt continuation. |
@@ -2,9 +2,9 b' name: Run MyPy' | |||||
2 |
|
2 | |||
3 | on: |
|
3 | on: | |
4 | push: |
|
4 | push: | |
5 | branches: [ master ] |
|
5 | branches: [ master, 7.x] | |
6 | pull_request: |
|
6 | pull_request: | |
7 | branches: [ master ] |
|
7 | branches: [ master, 7.x] | |
8 |
|
8 | |||
9 | jobs: |
|
9 | jobs: | |
10 | build: |
|
10 | build: |
@@ -5,9 +5,9 b' name: Python package' | |||||
5 |
|
5 | |||
6 | on: |
|
6 | on: | |
7 | push: |
|
7 | push: | |
8 | branches: [ master ] |
|
8 | branches: [ master, 7.x ] | |
9 | pull_request: |
|
9 | pull_request: | |
10 | branches: [ master ] |
|
10 | branches: [ master, 7.x ] | |
11 |
|
11 | |||
12 | jobs: |
|
12 | jobs: | |
13 | build: |
|
13 | build: |
@@ -37,7 +37,7 b' install:' | |||||
37 | - pip install -e file://$PWD#egg=ipython[test] --upgrade |
|
37 | - pip install -e file://$PWD#egg=ipython[test] --upgrade | |
38 | - pip install trio curio --upgrade --upgrade-strategy eager |
|
38 | - pip install trio curio --upgrade --upgrade-strategy eager | |
39 | - pip install 'pytest' 'matplotlib !=3.2.0' |
|
39 | - pip install 'pytest' 'matplotlib !=3.2.0' | |
40 |
- pip install codecov check-manifest pytest-cov --upgrade anyio pytest- |
|
40 | - pip install codecov check-manifest pytest-cov --upgrade anyio pytest-trio | |
41 |
|
41 | |||
42 |
|
42 | |||
43 | script: |
|
43 | script: |
@@ -99,7 +99,7 b' class CachingCompiler(codeop.Compile):' | |||||
99 | Arguments are exactly the same as ast.parse (in the standard library), |
|
99 | Arguments are exactly the same as ast.parse (in the standard library), | |
100 | and are passed to the built-in compile function.""" |
|
100 | and are passed to the built-in compile function.""" | |
101 | return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1) |
|
101 | return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1) | |
102 |
|
102 | |||
103 | def reset_compiler_flags(self): |
|
103 | def reset_compiler_flags(self): | |
104 | """Reset compiler flags to default state.""" |
|
104 | """Reset compiler flags to default state.""" | |
105 | # This value is copied from codeop.Compile.__init__, so if that ever |
|
105 | # This value is copied from codeop.Compile.__init__, so if that ever | |
@@ -112,25 +112,53 b' class CachingCompiler(codeop.Compile):' | |||||
112 | """ |
|
112 | """ | |
113 | return self.flags |
|
113 | return self.flags | |
114 |
|
114 | |||
115 |
def |
|
115 | def get_code_name(self, raw_code, transformed_code, number): | |
|
116 | """Compute filename given the code, and the cell number. | |||
|
117 | ||||
|
118 | Parameters | |||
|
119 | ---------- | |||
|
120 | raw_code : str | |||
|
121 | The raw cell code. | |||
|
122 | transformed_code : str | |||
|
123 | The executable Python source code to cache and compile. | |||
|
124 | number : int | |||
|
125 | A number which forms part of the code's name. Used for the execution | |||
|
126 | counter. | |||
|
127 | ||||
|
128 | Returns | |||
|
129 | ------- | |||
|
130 | The computed filename. | |||
|
131 | """ | |||
|
132 | return code_name(transformed_code, number) | |||
|
133 | ||||
|
134 | def cache(self, transformed_code, number=0, raw_code=None): | |||
116 | """Make a name for a block of code, and cache the code. |
|
135 | """Make a name for a block of code, and cache the code. | |
117 |
|
136 | |||
118 | Parameters |
|
137 | Parameters | |
119 | ---------- |
|
138 | ---------- | |
120 | code : str |
|
139 | transformed_code : str | |
121 | The Python source code to cache. |
|
140 | The executable Python source code to cache and compile. | |
122 | number : int |
|
141 | number : int | |
123 | A number which forms part of the code's name. Used for the execution |
|
142 | A number which forms part of the code's name. Used for the execution | |
124 | counter. |
|
143 | counter. | |
|
144 | raw_code : str | |||
|
145 | The raw code before transformation, if None, set to `transformed_code`. | |||
125 |
|
146 | |||
126 | Returns |
|
147 | Returns | |
127 | ------- |
|
148 | ------- | |
128 | The name of the cached code (as a string). Pass this as the filename |
|
149 | The name of the cached code (as a string). Pass this as the filename | |
129 | argument to compilation, so that tracebacks are correctly hooked up. |
|
150 | argument to compilation, so that tracebacks are correctly hooked up. | |
130 | """ |
|
151 | """ | |
131 | name = code_name(code, number) |
|
152 | if raw_code is None: | |
132 | entry = (len(code), time.time(), |
|
153 | raw_code = transformed_code | |
133 | [line+'\n' for line in code.splitlines()], name) |
|
154 | ||
|
155 | name = self.get_code_name(raw_code, transformed_code, number) | |||
|
156 | entry = ( | |||
|
157 | len(transformed_code), | |||
|
158 | time.time(), | |||
|
159 | [line + "\n" for line in transformed_code.splitlines()], | |||
|
160 | name, | |||
|
161 | ) | |||
134 | linecache.cache[name] = entry |
|
162 | linecache.cache[name] = entry | |
135 | linecache._ipython_cache[name] = entry |
|
163 | linecache._ipython_cache[name] = entry | |
136 | return name |
|
164 | return name | |
@@ -146,7 +174,7 b' class CachingCompiler(codeop.Compile):' | |||||
146 | yield |
|
174 | yield | |
147 | finally: |
|
175 | finally: | |
148 | # turn off only the bits we turned on so that something like |
|
176 | # turn off only the bits we turned on so that something like | |
149 |
# __future__ that set flags stays. |
|
177 | # __future__ that set flags stays. | |
150 | self.flags &= ~turn_on_bits |
|
178 | self.flags &= ~turn_on_bits | |
151 |
|
179 | |||
152 |
|
180 |
@@ -201,7 +201,9 b" def provisionalcompleter(action='ignore'):" | |||||
201 |
|
201 | |||
202 | >>> completer.do_experimental_things() # raises. |
|
202 | >>> completer.do_experimental_things() # raises. | |
203 |
|
203 | |||
204 |
.. note:: |
|
204 | .. note:: | |
|
205 | ||||
|
206 | Unstable | |||
205 |
|
207 | |||
206 | By using this context manager you agree that the API in use may change |
|
208 | By using this context manager you agree that the API in use may change | |
207 | without warning, and that you won't complain if they do so. |
|
209 | without warning, and that you won't complain if they do so. | |
@@ -356,7 +358,9 b' class Completion:' | |||||
356 | """ |
|
358 | """ | |
357 | Completion object used and return by IPython completers. |
|
359 | Completion object used and return by IPython completers. | |
358 |
|
360 | |||
359 |
.. warning:: |
|
361 | .. warning:: | |
|
362 | ||||
|
363 | Unstable | |||
360 |
|
364 | |||
361 | This function is unstable, API may change without warning. |
|
365 | This function is unstable, API may change without warning. | |
362 | It will also raise unless use in proper context manager. |
|
366 | It will also raise unless use in proper context manager. | |
@@ -419,7 +423,9 b' def _deduplicate_completions(text: str, completions: _IC)-> _IC:' | |||||
419 | """ |
|
423 | """ | |
420 | Deduplicate a set of completions. |
|
424 | Deduplicate a set of completions. | |
421 |
|
425 | |||
422 |
.. warning:: |
|
426 | .. warning:: | |
|
427 | ||||
|
428 | Unstable | |||
423 |
|
429 | |||
424 | This function is unstable, API may change without warning. |
|
430 | This function is unstable, API may change without warning. | |
425 |
|
431 | |||
@@ -459,7 +465,9 b' def rectify_completions(text: str, completions: _IC, *, _debug=False)->_IC:' | |||||
459 | """ |
|
465 | """ | |
460 | Rectify a set of completions to all have the same ``start`` and ``end`` |
|
466 | Rectify a set of completions to all have the same ``start`` and ``end`` | |
461 |
|
467 | |||
462 |
.. warning:: |
|
468 | .. warning:: | |
|
469 | ||||
|
470 | Unstable | |||
463 |
|
471 | |||
464 | This function is unstable, API may change without warning. |
|
472 | This function is unstable, API may change without warning. | |
465 | It will also raise unless use in proper context manager. |
|
473 | It will also raise unless use in proper context manager. | |
@@ -1837,7 +1845,9 b' class IPCompleter(Completer):' | |||||
1837 | """ |
|
1845 | """ | |
1838 | Returns an iterator over the possible completions |
|
1846 | Returns an iterator over the possible completions | |
1839 |
|
1847 | |||
1840 |
.. warning:: |
|
1848 | .. warning:: | |
|
1849 | ||||
|
1850 | Unstable | |||
1841 |
|
1851 | |||
1842 | This function is unstable, API may change without warning. |
|
1852 | This function is unstable, API may change without warning. | |
1843 | It will also raise unless use in proper context manager. |
|
1853 | It will also raise unless use in proper context manager. |
@@ -23,6 +23,7 b' import os' | |||||
23 | import sys |
|
23 | import sys | |
24 | import traceback |
|
24 | import traceback | |
25 | from pprint import pformat |
|
25 | from pprint import pformat | |
|
26 | from pathlib import Path | |||
26 |
|
27 | |||
27 | from IPython.core import ultratb |
|
28 | from IPython.core import ultratb | |
28 | from IPython.core.release import author_email |
|
29 | from IPython.core.release import author_email | |
@@ -151,10 +152,10 b' class CrashHandler(object):' | |||||
151 | try: |
|
152 | try: | |
152 | rptdir = self.app.ipython_dir |
|
153 | rptdir = self.app.ipython_dir | |
153 | except: |
|
154 | except: | |
154 |
rptdir = |
|
155 | rptdir = Path.cwd() | |
155 |
if rptdir is None or not |
|
156 | if rptdir is None or not Path.is_dir(rptdir): | |
156 |
rptdir = |
|
157 | rptdir = Path.cwd() | |
157 |
report_name = |
|
158 | report_name = rptdir / self.crash_report_fname | |
158 | # write the report filename into the instance dict so it can get |
|
159 | # write the report filename into the instance dict so it can get | |
159 | # properly expanded out in the user message template |
|
160 | # properly expanded out in the user message template | |
160 | self.crash_report_fname = report_name |
|
161 | self.crash_report_fname = report_name |
@@ -43,13 +43,14 b' from IPython.testing.skipdoctest import skip_doctest' | |||||
43 |
|
43 | |||
44 | prompt = 'ipdb> ' |
|
44 | prompt = 'ipdb> ' | |
45 |
|
45 | |||
46 | #We have to check this directly from sys.argv, config struct not yet available |
|
46 | # We have to check this directly from sys.argv, config struct not yet available | |
47 | from pdb import Pdb as OldPdb |
|
47 | from pdb import Pdb as OldPdb | |
48 |
|
48 | |||
49 | # Allow the set_trace code to operate outside of an ipython instance, even if |
|
49 | # Allow the set_trace code to operate outside of an ipython instance, even if | |
50 | # it does so with some limitations. The rest of this support is implemented in |
|
50 | # it does so with some limitations. The rest of this support is implemented in | |
51 | # the Tracer constructor. |
|
51 | # the Tracer constructor. | |
52 |
|
52 | |||
|
53 | ||||
53 | def make_arrow(pad): |
|
54 | def make_arrow(pad): | |
54 | """generate the leading arrow in front of traceback or debugger""" |
|
55 | """generate the leading arrow in front of traceback or debugger""" | |
55 | if pad >= 2: |
|
56 | if pad >= 2: | |
@@ -67,16 +68,16 b' def BdbQuit_excepthook(et, ev, tb, excepthook=None):' | |||||
67 | """ |
|
68 | """ | |
68 | warnings.warn("`BdbQuit_excepthook` is deprecated since version 5.1", |
|
69 | warnings.warn("`BdbQuit_excepthook` is deprecated since version 5.1", | |
69 | DeprecationWarning, stacklevel=2) |
|
70 | DeprecationWarning, stacklevel=2) | |
70 | if et==bdb.BdbQuit: |
|
71 | if et == bdb.BdbQuit: | |
71 | print('Exiting Debugger.') |
|
72 | print('Exiting Debugger.') | |
72 | elif excepthook is not None: |
|
73 | elif excepthook is not None: | |
73 | excepthook(et, ev, tb) |
|
74 | excepthook(et, ev, tb) | |
74 | else: |
|
75 | else: | |
75 | # Backwards compatibility. Raise deprecation warning? |
|
76 | # Backwards compatibility. Raise deprecation warning? | |
76 | BdbQuit_excepthook.excepthook_ori(et,ev,tb) |
|
77 | BdbQuit_excepthook.excepthook_ori(et, ev, tb) | |
77 |
|
78 | |||
78 |
|
79 | |||
79 | def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None): |
|
80 | def BdbQuit_IPython_excepthook(self, et, ev, tb, tb_offset=None): | |
80 | warnings.warn( |
|
81 | warnings.warn( | |
81 | "`BdbQuit_IPython_excepthook` is deprecated since version 5.1", |
|
82 | "`BdbQuit_IPython_excepthook` is deprecated since version 5.1", | |
82 | DeprecationWarning, stacklevel=2) |
|
83 | DeprecationWarning, stacklevel=2) | |
@@ -203,7 +204,7 b' class Pdb(OldPdb):' | |||||
203 | def __init__(self, color_scheme=None, completekey=None, |
|
204 | def __init__(self, color_scheme=None, completekey=None, | |
204 | stdin=None, stdout=None, context=5, **kwargs): |
|
205 | stdin=None, stdout=None, context=5, **kwargs): | |
205 | """Create a new IPython debugger. |
|
206 | """Create a new IPython debugger. | |
206 |
|
207 | |||
207 | :param color_scheme: Deprecated, do not use. |
|
208 | :param color_scheme: Deprecated, do not use. | |
208 | :param completekey: Passed to pdb.Pdb. |
|
209 | :param completekey: Passed to pdb.Pdb. | |
209 | :param stdin: Passed to pdb.Pdb. |
|
210 | :param stdin: Passed to pdb.Pdb. | |
@@ -237,7 +238,7 b' class Pdb(OldPdb):' | |||||
237 | self.shell = TerminalInteractiveShell.instance() |
|
238 | self.shell = TerminalInteractiveShell.instance() | |
238 | # needed by any code which calls __import__("__main__") after |
|
239 | # needed by any code which calls __import__("__main__") after | |
239 | # the debugger was entered. See also #9941. |
|
240 | # the debugger was entered. See also #9941. | |
240 |
sys.modules[ |
|
241 | sys.modules["__main__"] = save_main | |
241 |
|
242 | |||
242 | if color_scheme is not None: |
|
243 | if color_scheme is not None: | |
243 | warnings.warn( |
|
244 | warnings.warn( | |
@@ -272,7 +273,6 b' class Pdb(OldPdb):' | |||||
272 | cst['Neutral'].colors.breakpoint_enabled = C.LightRed |
|
273 | cst['Neutral'].colors.breakpoint_enabled = C.LightRed | |
273 | cst['Neutral'].colors.breakpoint_disabled = C.Red |
|
274 | cst['Neutral'].colors.breakpoint_disabled = C.Red | |
274 |
|
275 | |||
275 |
|
||||
276 | # Add a python parser so we can syntax highlight source while |
|
276 | # Add a python parser so we can syntax highlight source while | |
277 | # debugging. |
|
277 | # debugging. | |
278 | self.parser = PyColorize.Parser(style=color_scheme) |
|
278 | self.parser = PyColorize.Parser(style=color_scheme) | |
@@ -320,13 +320,25 b' class Pdb(OldPdb):' | |||||
320 | except KeyboardInterrupt: |
|
320 | except KeyboardInterrupt: | |
321 | self.stdout.write("\n" + self.shell.get_exception_only()) |
|
321 | self.stdout.write("\n" + self.shell.get_exception_only()) | |
322 |
|
322 | |||
|
323 | def precmd(self, line): | |||
|
324 | """Perform useful escapes on the command before it is executed.""" | |||
|
325 | ||||
|
326 | if line.endswith("??"): | |||
|
327 | line = "pinfo2 " + line[:-2] | |||
|
328 | elif line.endswith("?"): | |||
|
329 | line = "pinfo " + line[:-1] | |||
|
330 | ||||
|
331 | line = super().precmd(line) | |||
|
332 | ||||
|
333 | return line | |||
|
334 | ||||
323 | def new_do_frame(self, arg): |
|
335 | def new_do_frame(self, arg): | |
324 | OldPdb.do_frame(self, arg) |
|
336 | OldPdb.do_frame(self, arg) | |
325 |
|
337 | |||
326 | def new_do_quit(self, arg): |
|
338 | def new_do_quit(self, arg): | |
327 |
|
339 | |||
328 | if hasattr(self, 'old_all_completions'): |
|
340 | if hasattr(self, 'old_all_completions'): | |
329 | self.shell.Completer.all_completions=self.old_all_completions |
|
341 | self.shell.Completer.all_completions = self.old_all_completions | |
330 |
|
342 | |||
331 | return OldPdb.do_quit(self, arg) |
|
343 | return OldPdb.do_quit(self, arg) | |
332 |
|
344 | |||
@@ -344,7 +356,7 b' class Pdb(OldPdb):' | |||||
344 | if context is None: |
|
356 | if context is None: | |
345 | context = self.context |
|
357 | context = self.context | |
346 | try: |
|
358 | try: | |
347 | context=int(context) |
|
359 | context = int(context) | |
348 | if context <= 0: |
|
360 | if context <= 0: | |
349 | raise ValueError("Context must be a positive integer") |
|
361 | raise ValueError("Context must be a positive integer") | |
350 | except (TypeError, ValueError) as e: |
|
362 | except (TypeError, ValueError) as e: | |
@@ -373,7 +385,7 b' class Pdb(OldPdb):' | |||||
373 | if context is None: |
|
385 | if context is None: | |
374 | context = self.context |
|
386 | context = self.context | |
375 | try: |
|
387 | try: | |
376 | context=int(context) |
|
388 | context = int(context) | |
377 | if context <= 0: |
|
389 | if context <= 0: | |
378 | raise ValueError("Context must be a positive integer") |
|
390 | raise ValueError("Context must be a positive integer") | |
379 | except (TypeError, ValueError) as e: |
|
391 | except (TypeError, ValueError) as e: | |
@@ -390,7 +402,7 b' class Pdb(OldPdb):' | |||||
390 | if context is None: |
|
402 | if context is None: | |
391 | context = self.context |
|
403 | context = self.context | |
392 | try: |
|
404 | try: | |
393 | context=int(context) |
|
405 | context = int(context) | |
394 | if context <= 0: |
|
406 | if context <= 0: | |
395 | print("Context must be a positive integer", file=self.stdout) |
|
407 | print("Context must be a positive integer", file=self.stdout) | |
396 | except (TypeError, ValueError): |
|
408 | except (TypeError, ValueError): | |
@@ -402,11 +414,10 b' class Pdb(OldPdb):' | |||||
402 |
|
414 | |||
403 | Colors = self.color_scheme_table.active_colors |
|
415 | Colors = self.color_scheme_table.active_colors | |
404 | ColorsNormal = Colors.Normal |
|
416 | ColorsNormal = Colors.Normal | |
405 |
tpl_link = |
|
417 | tpl_link = "%s%%s%s" % (Colors.filenameEm, ColorsNormal) | |
406 |
tpl_call = |
|
418 | tpl_call = "%s%%s%s%%s%s" % (Colors.vName, Colors.valEm, ColorsNormal) | |
407 |
tpl_line = |
|
419 | tpl_line = "%%s%s%%s %s%%s" % (Colors.lineno, ColorsNormal) | |
408 |
tpl_line_em = |
|
420 | tpl_line_em = "%%s%s%%s %s%%s%s" % (Colors.linenoEm, Colors.line, ColorsNormal) | |
409 | ColorsNormal) |
|
|||
410 |
|
421 | |||
411 | frame, lineno = frame_lineno |
|
422 | frame, lineno = frame_lineno | |
412 |
|
423 | |||
@@ -439,8 +450,8 b' class Pdb(OldPdb):' | |||||
439 | if frame is self.curframe: |
|
450 | if frame is self.curframe: | |
440 | ret.append('> ') |
|
451 | ret.append('> ') | |
441 | else: |
|
452 | else: | |
442 |
ret.append( |
|
453 | ret.append(" ") | |
443 |
ret.append( |
|
454 | ret.append("%s(%s)%s\n" % (link, lineno, call)) | |
444 |
|
455 | |||
445 | start = lineno - 1 - context//2 |
|
456 | start = lineno - 1 - context//2 | |
446 | lines = linecache.getlines(filename) |
|
457 | lines = linecache.getlines(filename) | |
@@ -448,17 +459,17 b' class Pdb(OldPdb):' | |||||
448 | start = max(start, 0) |
|
459 | start = max(start, 0) | |
449 | lines = lines[start : start + context] |
|
460 | lines = lines[start : start + context] | |
450 |
|
461 | |||
451 | for i,line in enumerate(lines): |
|
462 | for i, line in enumerate(lines): | |
452 |
show_arrow = |
|
463 | show_arrow = start + 1 + i == lineno | |
453 |
linetpl = (frame is self.curframe or show_arrow) |
|
464 | linetpl = (frame is self.curframe or show_arrow) and tpl_line_em or tpl_line | |
454 | and tpl_line_em \ |
|
465 | ret.append( | |
455 |
|
|
466 | self.__format_line( | |
456 | ret.append(self.__format_line(linetpl, filename, |
|
467 | linetpl, filename, start + 1 + i, line, arrow=show_arrow | |
457 | start + 1 + i, line, |
|
468 | ) | |
458 | arrow = show_arrow) ) |
|
469 | ) | |
459 |
return |
|
470 | return "".join(ret) | |
460 |
|
471 | |||
461 |
def __format_line(self, tpl_line, filename, lineno, line, arrow |
|
472 | def __format_line(self, tpl_line, filename, lineno, line, arrow=False): | |
462 | bp_mark = "" |
|
473 | bp_mark = "" | |
463 | bp_mark_color = "" |
|
474 | bp_mark_color = "" | |
464 |
|
475 | |||
@@ -488,7 +499,6 b' class Pdb(OldPdb):' | |||||
488 |
|
499 | |||
489 | return tpl_line % (bp_mark_color + bp_mark, num, line) |
|
500 | return tpl_line % (bp_mark_color + bp_mark, num, line) | |
490 |
|
501 | |||
491 |
|
||||
492 | def print_list_lines(self, filename, first, last): |
|
502 | def print_list_lines(self, filename, first, last): | |
493 | """The printing (as opposed to the parsing part of a 'list' |
|
503 | """The printing (as opposed to the parsing part of a 'list' | |
494 | command.""" |
|
504 | command.""" | |
@@ -507,9 +517,13 b' class Pdb(OldPdb):' | |||||
507 | break |
|
517 | break | |
508 |
|
518 | |||
509 | if lineno == self.curframe.f_lineno: |
|
519 | if lineno == self.curframe.f_lineno: | |
510 |
line = self.__format_line( |
|
520 | line = self.__format_line( | |
|
521 | tpl_line_em, filename, lineno, line, arrow=True | |||
|
522 | ) | |||
511 | else: |
|
523 | else: | |
512 |
line = self.__format_line( |
|
524 | line = self.__format_line( | |
|
525 | tpl_line, filename, lineno, line, arrow=False | |||
|
526 | ) | |||
513 |
|
527 | |||
514 | src.append(line) |
|
528 | src.append(line) | |
515 | self.lineno = lineno |
|
529 | self.lineno = lineno | |
@@ -706,7 +720,7 b' class Pdb(OldPdb):' | |||||
706 |
|
720 | |||
707 | Will skip hidden frames. |
|
721 | Will skip hidden frames. | |
708 | """ |
|
722 | """ | |
709 |
|
|
723 | # modified version of upstream that skips | |
710 | # frames with __tracebackide__ |
|
724 | # frames with __tracebackide__ | |
711 | if self.curindex == 0: |
|
725 | if self.curindex == 0: | |
712 | self.error("Oldest frame") |
|
726 | self.error("Oldest frame") | |
@@ -720,11 +734,9 b' class Pdb(OldPdb):' | |||||
720 | if count < 0: |
|
734 | if count < 0: | |
721 | _newframe = 0 |
|
735 | _newframe = 0 | |
722 | else: |
|
736 | else: | |
723 | _newindex = self.curindex |
|
|||
724 | counter = 0 |
|
737 | counter = 0 | |
725 | hidden_frames = self.hidden_frames(self.stack) |
|
738 | hidden_frames = self.hidden_frames(self.stack) | |
726 | for i in range(self.curindex - 1, -1, -1): |
|
739 | for i in range(self.curindex - 1, -1, -1): | |
727 | frame = self.stack[i][0] |
|
|||
728 | if hidden_frames[i] and self.skip_hidden: |
|
740 | if hidden_frames[i] and self.skip_hidden: | |
729 | skipped += 1 |
|
741 | skipped += 1 | |
730 | continue |
|
742 | continue | |
@@ -765,12 +777,10 b' class Pdb(OldPdb):' | |||||
765 | if count < 0: |
|
777 | if count < 0: | |
766 | _newframe = len(self.stack) - 1 |
|
778 | _newframe = len(self.stack) - 1 | |
767 | else: |
|
779 | else: | |
768 | _newindex = self.curindex |
|
|||
769 | counter = 0 |
|
780 | counter = 0 | |
770 | skipped = 0 |
|
781 | skipped = 0 | |
771 | hidden_frames = self.hidden_frames(self.stack) |
|
782 | hidden_frames = self.hidden_frames(self.stack) | |
772 | for i in range(self.curindex + 1, len(self.stack)): |
|
783 | for i in range(self.curindex + 1, len(self.stack)): | |
773 | frame = self.stack[i][0] |
|
|||
774 | if hidden_frames[i] and self.skip_hidden: |
|
784 | if hidden_frames[i] and self.skip_hidden: | |
775 | skipped += 1 |
|
785 | skipped += 1 | |
776 | continue |
|
786 | continue | |
@@ -796,6 +806,20 b' class Pdb(OldPdb):' | |||||
796 | do_d = do_down |
|
806 | do_d = do_down | |
797 | do_u = do_up |
|
807 | do_u = do_up | |
798 |
|
808 | |||
|
809 | def do_context(self, context): | |||
|
810 | """context number_of_lines | |||
|
811 | Set the number of lines of source code to show when displaying | |||
|
812 | stacktrace information. | |||
|
813 | """ | |||
|
814 | try: | |||
|
815 | new_context = int(context) | |||
|
816 | if new_context <= 0: | |||
|
817 | raise ValueError() | |||
|
818 | self.context = new_context | |||
|
819 | except ValueError: | |||
|
820 | self.error("The 'context' command requires a positive integer argument.") | |||
|
821 | ||||
|
822 | ||||
799 | class InterruptiblePdb(Pdb): |
|
823 | class InterruptiblePdb(Pdb): | |
800 | """Version of debugger where KeyboardInterrupt exits the debugger altogether.""" |
|
824 | """Version of debugger where KeyboardInterrupt exits the debugger altogether.""" | |
801 |
|
825 |
@@ -567,7 +567,7 b' class JSON(DisplayObject):' | |||||
567 | Path to a local file to load the data from. |
|
567 | Path to a local file to load the data from. | |
568 | expanded : boolean |
|
568 | expanded : boolean | |
569 | Metadata to control whether a JSON display component is expanded. |
|
569 | Metadata to control whether a JSON display component is expanded. | |
570 | metadata: dict |
|
570 | metadata : dict | |
571 | Specify extra metadata to attach to the json display object. |
|
571 | Specify extra metadata to attach to the json display object. | |
572 | root : str |
|
572 | root : str | |
573 | The name of the root element of the JSON tree |
|
573 | The name of the root element of the JSON tree | |
@@ -651,12 +651,11 b' class GeoJSON(JSON):' | |||||
651 | A URL to download the data from. |
|
651 | A URL to download the data from. | |
652 | filename : unicode |
|
652 | filename : unicode | |
653 | Path to a local file to load the data from. |
|
653 | Path to a local file to load the data from. | |
654 | metadata: dict |
|
654 | metadata : dict | |
655 | Specify extra metadata to attach to the json display object. |
|
655 | Specify extra metadata to attach to the json display object. | |
656 |
|
656 | |||
657 | Examples |
|
657 | Examples | |
658 | -------- |
|
658 | -------- | |
659 |
|
||||
660 | The following will display an interactive map of Mars with a point of |
|
659 | The following will display an interactive map of Mars with a point of | |
661 | interest on frontend that do support GeoJSON display. |
|
660 | interest on frontend that do support GeoJSON display. | |
662 |
|
661 | |||
@@ -723,7 +722,7 b' class Javascript(TextDisplayObject):' | |||||
723 | running the source code. The full URLs of the libraries should |
|
722 | running the source code. The full URLs of the libraries should | |
724 | be given. A single Javascript library URL can also be given as a |
|
723 | be given. A single Javascript library URL can also be given as a | |
725 | string. |
|
724 | string. | |
726 |
css |
|
725 | css : list or str | |
727 | A sequence of css files to load before running the source code. |
|
726 | A sequence of css files to load before running the source code. | |
728 | The full URLs of the css files should be given. A single css URL |
|
727 | The full URLs of the css files should be given. A single css URL | |
729 | can also be given as a string. |
|
728 | can also be given as a string. | |
@@ -844,25 +843,33 b' class Image(DisplayObject):' | |||||
844 | from image data. |
|
843 | from image data. | |
845 | For non-embedded images, you can just set the desired display width |
|
844 | For non-embedded images, you can just set the desired display width | |
846 | and height directly. |
|
845 | and height directly. | |
847 | unconfined: bool |
|
846 | unconfined : bool | |
848 | Set unconfined=True to disable max-width confinement of the image. |
|
847 | Set unconfined=True to disable max-width confinement of the image. | |
849 | metadata: dict |
|
848 | metadata : dict | |
850 | Specify extra metadata to attach to the image. |
|
849 | Specify extra metadata to attach to the image. | |
851 |
|
850 | |||
852 | Examples |
|
851 | Examples | |
853 | -------- |
|
852 | -------- | |
854 |
|
|
853 | embedded image data, works in qtconsole and notebook | |
855 |
|
|
854 | when passed positionally, the first arg can be any of raw image data, | |
856 |
|
|
855 | a URL, or a filename from which to load image data. | |
857 |
|
|
856 | The result is always embedding image data for inline images. | |
858 | Image('http://www.google.fr/images/srpr/logo3w.png') |
|
857 | ||
859 | Image('/path/to/image.jpg') |
|
858 | >>> Image('http://www.google.fr/images/srpr/logo3w.png') | |
860 | Image(b'RAW_PNG_DATA...') |
|
859 | <IPython.core.display.Image object> | |
861 |
|
860 | |||
862 | # Specifying Image(url=...) does not embed the image data, |
|
861 | >>> Image('/path/to/image.jpg') | |
863 | # it only generates `<img>` tag with a link to the source. |
|
862 | <IPython.core.display.Image object> | |
864 | # This will not work in the qtconsole or offline. |
|
863 | ||
865 | Image(url='http://www.google.fr/images/srpr/logo3w.png') |
|
864 | >>> Image(b'RAW_PNG_DATA...') | |
|
865 | <IPython.core.display.Image object> | |||
|
866 | ||||
|
867 | Specifying Image(url=...) does not embed the image data, | |||
|
868 | it only generates ``<img>`` tag with a link to the source. | |||
|
869 | This will not work in the qtconsole or offline. | |||
|
870 | ||||
|
871 | >>> Image(url='http://www.google.fr/images/srpr/logo3w.png') | |||
|
872 | <IPython.core.display.Image object> | |||
866 |
|
873 | |||
867 | """ |
|
874 | """ | |
868 | if isinstance(data, (Path, PurePath)): |
|
875 | if isinstance(data, (Path, PurePath)): | |
@@ -1036,25 +1043,24 b' class Video(DisplayObject):' | |||||
1036 | ---------- |
|
1043 | ---------- | |
1037 | data : unicode, str or bytes |
|
1044 | data : unicode, str or bytes | |
1038 | The raw video data or a URL or filename to load the data from. |
|
1045 | The raw video data or a URL or filename to load the data from. | |
1039 | Raw data will require passing `embed=True`. |
|
1046 | Raw data will require passing ``embed=True``. | |
1040 | url : unicode |
|
1047 | url : unicode | |
1041 | A URL for the video. If you specify `url=`, |
|
1048 | A URL for the video. If you specify ``url=``, | |
1042 | the image data will not be embedded. |
|
1049 | the image data will not be embedded. | |
1043 | filename : unicode |
|
1050 | filename : unicode | |
1044 | Path to a local file containing the video. |
|
1051 | Path to a local file containing the video. | |
1045 | Will be interpreted as a local URL unless `embed=True`. |
|
1052 | Will be interpreted as a local URL unless ``embed=True``. | |
1046 | embed : bool |
|
1053 | embed : bool | |
1047 | Should the video be embedded using a data URI (True) or be |
|
1054 | Should the video be embedded using a data URI (True) or be | |
1048 | loaded using a <video> tag (False). |
|
1055 | loaded using a <video> tag (False). | |
1049 |
|
1056 | |||
1050 | Since videos are large, embedding them should be avoided, if possible. |
|
1057 | Since videos are large, embedding them should be avoided, if possible. | |
1051 | You must confirm embedding as your intention by passing `embed=True`. |
|
1058 | You must confirm embedding as your intention by passing ``embed=True``. | |
1052 |
|
1059 | |||
1053 | Local files can be displayed with URLs without embedding the content, via:: |
|
1060 | Local files can be displayed with URLs without embedding the content, via:: | |
1054 |
|
1061 | |||
1055 | Video('./video.mp4') |
|
1062 | Video('./video.mp4') | |
1056 |
|
1063 | mimetype : unicode | ||
1057 | mimetype: unicode |
|
|||
1058 | Specify the mimetype for embedded videos. |
|
1064 | Specify the mimetype for embedded videos. | |
1059 | Default will be guessed from file extension, if available. |
|
1065 | Default will be guessed from file extension, if available. | |
1060 | width : int |
|
1066 | width : int | |
@@ -1064,14 +1070,13 b' class Video(DisplayObject):' | |||||
1064 | Height in pixels to which to constrain the video in html. |
|
1070 | Height in pixels to which to constrain the video in html. | |
1065 | If not supplied, defaults to the height of the video. |
|
1071 | If not supplied, defaults to the height of the video. | |
1066 | html_attributes : str |
|
1072 | html_attributes : str | |
1067 | Attributes for the HTML `<video>` block. |
|
1073 | Attributes for the HTML ``<video>`` block. | |
1068 | Default: `"controls"` to get video controls. |
|
1074 | Default: ``"controls"`` to get video controls. | |
1069 | Other examples: `"controls muted"` for muted video with controls, |
|
1075 | Other examples: ``"controls muted"`` for muted video with controls, | |
1070 | `"loop autoplay"` for looping autoplaying video without controls. |
|
1076 | ``"loop autoplay"`` for looping autoplaying video without controls. | |
1071 |
|
1077 | |||
1072 | Examples |
|
1078 | Examples | |
1073 | -------- |
|
1079 | -------- | |
1074 |
|
||||
1075 | :: |
|
1080 | :: | |
1076 |
|
1081 | |||
1077 | Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4') |
|
1082 | Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4') | |
@@ -1165,7 +1170,7 b' def set_matplotlib_formats(*formats, **kwargs):' | |||||
1165 | ---------- |
|
1170 | ---------- | |
1166 | *formats : strs |
|
1171 | *formats : strs | |
1167 | One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'. |
|
1172 | One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'. | |
1168 |
**kwargs |
|
1173 | **kwargs | |
1169 | Keyword args will be relayed to ``figure.canvas.print_figure``. |
|
1174 | Keyword args will be relayed to ``figure.canvas.print_figure``. | |
1170 | """ |
|
1175 | """ | |
1171 | from IPython.core.interactiveshell import InteractiveShell |
|
1176 | from IPython.core.interactiveshell import InteractiveShell |
@@ -508,6 +508,20 b' def make_tokens_by_line(lines:List[str]):' | |||||
508 |
|
508 | |||
509 | return tokens_by_line |
|
509 | return tokens_by_line | |
510 |
|
510 | |||
|
511 | ||||
|
512 | def has_sunken_brackets(tokens: List[tokenize.TokenInfo]): | |||
|
513 | """Check if the depth of brackets in the list of tokens drops below 0""" | |||
|
514 | parenlev = 0 | |||
|
515 | for token in tokens: | |||
|
516 | if token.string in {"(", "[", "{"}: | |||
|
517 | parenlev += 1 | |||
|
518 | elif token.string in {")", "]", "}"}: | |||
|
519 | parenlev -= 1 | |||
|
520 | if parenlev < 0: | |||
|
521 | return True | |||
|
522 | return False | |||
|
523 | ||||
|
524 | ||||
511 | def show_linewise_tokens(s: str): |
|
525 | def show_linewise_tokens(s: str): | |
512 | """For investigation and debugging""" |
|
526 | """For investigation and debugging""" | |
513 | if not s.endswith('\n'): |
|
527 | if not s.endswith('\n'): | |
@@ -662,6 +676,15 b' class TransformerManager:' | |||||
662 |
|
676 | |||
663 | tokens_by_line = make_tokens_by_line(lines) |
|
677 | tokens_by_line = make_tokens_by_line(lines) | |
664 |
|
678 | |||
|
679 | # Bail if we got one line and there are more closing parentheses than | |||
|
680 | # the opening ones | |||
|
681 | if ( | |||
|
682 | len(lines) == 1 | |||
|
683 | and tokens_by_line | |||
|
684 | and has_sunken_brackets(tokens_by_line[0]) | |||
|
685 | ): | |||
|
686 | return "invalid", None | |||
|
687 | ||||
665 | if not tokens_by_line: |
|
688 | if not tokens_by_line: | |
666 | return 'incomplete', find_last_indent(lines) |
|
689 | return 'incomplete', find_last_indent(lines) | |
667 |
|
690 |
@@ -340,7 +340,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
340 | """An enhanced, interactive shell for Python.""" |
|
340 | """An enhanced, interactive shell for Python.""" | |
341 |
|
341 | |||
342 | _instance = None |
|
342 | _instance = None | |
343 |
|
343 | |||
344 | ast_transformers = List([], help= |
|
344 | ast_transformers = List([], help= | |
345 | """ |
|
345 | """ | |
346 | A list of ast.NodeTransformer subclass instances, which will be applied |
|
346 | A list of ast.NodeTransformer subclass instances, which will be applied | |
@@ -407,7 +407,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
407 | Enable magic commands to be called without the leading %. |
|
407 | Enable magic commands to be called without the leading %. | |
408 | """ |
|
408 | """ | |
409 | ).tag(config=True) |
|
409 | ).tag(config=True) | |
410 |
|
410 | |||
411 | banner1 = Unicode(default_banner, |
|
411 | banner1 = Unicode(default_banner, | |
412 | help="""The part of the banner to be printed before the profile""" |
|
412 | help="""The part of the banner to be printed before the profile""" | |
413 | ).tag(config=True) |
|
413 | ).tag(config=True) | |
@@ -443,7 +443,8 b' class InteractiveShell(SingletonConfigurable):' | |||||
443 | display_formatter = Instance(DisplayFormatter, allow_none=True) |
|
443 | display_formatter = Instance(DisplayFormatter, allow_none=True) | |
444 | displayhook_class = Type(DisplayHook) |
|
444 | displayhook_class = Type(DisplayHook) | |
445 | display_pub_class = Type(DisplayPublisher) |
|
445 | display_pub_class = Type(DisplayPublisher) | |
446 |
|
446 | compiler_class = Type(CachingCompiler) | ||
|
447 | ||||
447 | sphinxify_docstring = Bool(False, help= |
|
448 | sphinxify_docstring = Bool(False, help= | |
448 | """ |
|
449 | """ | |
449 | Enables rich html representation of docstrings. (This requires the |
|
450 | Enables rich html representation of docstrings. (This requires the | |
@@ -534,7 +535,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
534 | ).tag(config=True) |
|
535 | ).tag(config=True) | |
535 |
|
536 | |||
536 | # deprecated prompt traits: |
|
537 | # deprecated prompt traits: | |
537 |
|
538 | |||
538 | prompt_in1 = Unicode('In [\\#]: ', |
|
539 | prompt_in1 = Unicode('In [\\#]: ', | |
539 | help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly." |
|
540 | help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly." | |
540 | ).tag(config=True) |
|
541 | ).tag(config=True) | |
@@ -547,14 +548,14 b' class InteractiveShell(SingletonConfigurable):' | |||||
547 | prompts_pad_left = Bool(True, |
|
548 | prompts_pad_left = Bool(True, | |
548 | help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly." |
|
549 | help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly." | |
549 | ).tag(config=True) |
|
550 | ).tag(config=True) | |
550 |
|
551 | |||
551 | @observe('prompt_in1', 'prompt_in2', 'prompt_out', 'prompt_pad_left') |
|
552 | @observe('prompt_in1', 'prompt_in2', 'prompt_out', 'prompt_pad_left') | |
552 | def _prompt_trait_changed(self, change): |
|
553 | def _prompt_trait_changed(self, change): | |
553 | name = change['name'] |
|
554 | name = change['name'] | |
554 | warn("InteractiveShell.{name} is deprecated since IPython 4.0" |
|
555 | warn("InteractiveShell.{name} is deprecated since IPython 4.0" | |
555 | " and ignored since 5.0, set TerminalInteractiveShell.prompts" |
|
556 | " and ignored since 5.0, set TerminalInteractiveShell.prompts" | |
556 | " object directly.".format(name=name)) |
|
557 | " object directly.".format(name=name)) | |
557 |
|
558 | |||
558 | # protect against weird cases where self.config may not exist: |
|
559 | # protect against weird cases where self.config may not exist: | |
559 |
|
560 | |||
560 | show_rewritten_input = Bool(True, |
|
561 | show_rewritten_input = Bool(True, | |
@@ -638,7 +639,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
638 | self.init_profile_dir(profile_dir) |
|
639 | self.init_profile_dir(profile_dir) | |
639 | self.init_instance_attrs() |
|
640 | self.init_instance_attrs() | |
640 | self.init_environment() |
|
641 | self.init_environment() | |
641 |
|
642 | |||
642 | # Check if we're in a virtualenv, and set up sys.path. |
|
643 | # Check if we're in a virtualenv, and set up sys.path. | |
643 | self.init_virtualenv() |
|
644 | self.init_virtualenv() | |
644 |
|
645 | |||
@@ -748,7 +749,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
748 | self.more = False |
|
749 | self.more = False | |
749 |
|
750 | |||
750 | # command compiler |
|
751 | # command compiler | |
751 |
self.compile = |
|
752 | self.compile = self.compiler_class() | |
752 |
|
753 | |||
753 | # Make an empty namespace, which extension writers can rely on both |
|
754 | # Make an empty namespace, which extension writers can rely on both | |
754 | # existing and NEVER being used by ipython itself. This gives them a |
|
755 | # existing and NEVER being used by ipython itself. This gives them a | |
@@ -931,17 +932,27 b' class InteractiveShell(SingletonConfigurable):' | |||||
931 | # Our exe is inside or has access to the virtualenv, don't need to do anything. |
|
932 | # Our exe is inside or has access to the virtualenv, don't need to do anything. | |
932 | return |
|
933 | return | |
933 |
|
934 | |||
934 | warn("Attempting to work in a virtualenv. If you encounter problems, please " |
|
|||
935 | "install IPython inside the virtualenv.") |
|
|||
936 | if sys.platform == "win32": |
|
935 | if sys.platform == "win32": | |
937 |
virtual_env = Path(os.environ["VIRTUAL_ENV"]) |
|
936 | virtual_env = Path(os.environ["VIRTUAL_ENV"], "Lib", "site-packages") | |
938 | "Lib", "site-packages" |
|
|||
939 | ) |
|
|||
940 | else: |
|
937 | else: | |
941 |
virtual_env = Path( |
|
938 | virtual_env_path = Path( | |
942 |
"lib", "python{}.{}" |
|
939 | os.environ["VIRTUAL_ENV"], "lib", "python{}.{}", "site-packages" | |
943 | ) |
|
940 | ) | |
944 |
|
941 | p_ver = sys.version_info[:2] | ||
|
942 | ||||
|
943 | # Predict version from py[thon]-x.x in the $VIRTUAL_ENV | |||
|
944 | re_m = re.search(r"\bpy(?:thon)?([23])\.(\d+)\b", os.environ["VIRTUAL_ENV"]) | |||
|
945 | if re_m: | |||
|
946 | predicted_path = Path(str(virtual_env_path).format(*re_m.groups())) | |||
|
947 | if predicted_path.exists(): | |||
|
948 | p_ver = re_m.groups() | |||
|
949 | ||||
|
950 | virtual_env = str(virtual_env_path).format(*p_ver) | |||
|
951 | ||||
|
952 | warn( | |||
|
953 | "Attempting to work in a virtualenv. If you encounter problems, " | |||
|
954 | "please install IPython inside the virtualenv." | |||
|
955 | ) | |||
945 | import site |
|
956 | import site | |
946 | sys.path.insert(0, virtual_env) |
|
957 | sys.path.insert(0, virtual_env) | |
947 | site.addsitedir(virtual_env) |
|
958 | site.addsitedir(virtual_env) | |
@@ -976,7 +987,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
976 | #------------------------------------------------------------------------- |
|
987 | #------------------------------------------------------------------------- | |
977 | # Things related to the banner |
|
988 | # Things related to the banner | |
978 | #------------------------------------------------------------------------- |
|
989 | #------------------------------------------------------------------------- | |
979 |
|
990 | |||
980 | @property |
|
991 | @property | |
981 | def banner(self): |
|
992 | def banner(self): | |
982 | banner = self.banner1 |
|
993 | banner = self.banner1 | |
@@ -990,7 +1001,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
990 | if banner is None: |
|
1001 | if banner is None: | |
991 | banner = self.banner |
|
1002 | banner = self.banner | |
992 | sys.stdout.write(banner) |
|
1003 | sys.stdout.write(banner) | |
993 |
|
1004 | |||
994 | #------------------------------------------------------------------------- |
|
1005 | #------------------------------------------------------------------------- | |
995 | # Things related to hooks |
|
1006 | # Things related to hooks | |
996 | #------------------------------------------------------------------------- |
|
1007 | #------------------------------------------------------------------------- | |
@@ -1007,10 +1018,10 b' class InteractiveShell(SingletonConfigurable):' | |||||
1007 | # default hooks have priority 100, i.e. low; user hooks should have |
|
1018 | # default hooks have priority 100, i.e. low; user hooks should have | |
1008 | # 0-100 priority |
|
1019 | # 0-100 priority | |
1009 | self.set_hook(hook_name,getattr(hooks,hook_name), 100, _warn_deprecated=False) |
|
1020 | self.set_hook(hook_name,getattr(hooks,hook_name), 100, _warn_deprecated=False) | |
1010 |
|
1021 | |||
1011 | if self.display_page: |
|
1022 | if self.display_page: | |
1012 | self.set_hook('show_in_pager', page.as_hook(page.display_page), 90) |
|
1023 | self.set_hook('show_in_pager', page.as_hook(page.display_page), 90) | |
1013 |
|
1024 | |||
1014 | def set_hook(self,name,hook, priority=50, str_key=None, re_key=None, |
|
1025 | def set_hook(self,name,hook, priority=50, str_key=None, re_key=None, | |
1015 | _warn_deprecated=True): |
|
1026 | _warn_deprecated=True): | |
1016 | """set_hook(name,hook) -> sets an internal IPython hook. |
|
1027 | """set_hook(name,hook) -> sets an internal IPython hook. | |
@@ -1074,7 +1085,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
1074 | warn("ip.register_post_execute is deprecated, use " |
|
1085 | warn("ip.register_post_execute is deprecated, use " | |
1075 | "ip.events.register('post_run_cell', func) instead.", stacklevel=2) |
|
1086 | "ip.events.register('post_run_cell', func) instead.", stacklevel=2) | |
1076 | self.events.register('post_run_cell', func) |
|
1087 | self.events.register('post_run_cell', func) | |
1077 |
|
1088 | |||
1078 | def _clear_warning_registry(self): |
|
1089 | def _clear_warning_registry(self): | |
1079 | # clear the warning registry, so that different code blocks with |
|
1090 | # clear the warning registry, so that different code blocks with | |
1080 | # overlapping line number ranges don't cause spurious suppression of |
|
1091 | # overlapping line number ranges don't cause spurious suppression of | |
@@ -1116,12 +1127,12 b' class InteractiveShell(SingletonConfigurable):' | |||||
1116 | else: |
|
1127 | else: | |
1117 | main_mod.__dict__.clear() |
|
1128 | main_mod.__dict__.clear() | |
1118 | main_mod.__name__ = modname |
|
1129 | main_mod.__name__ = modname | |
1119 |
|
1130 | |||
1120 | main_mod.__file__ = filename |
|
1131 | main_mod.__file__ = filename | |
1121 | # It seems pydoc (and perhaps others) needs any module instance to |
|
1132 | # It seems pydoc (and perhaps others) needs any module instance to | |
1122 | # implement a __nonzero__ method |
|
1133 | # implement a __nonzero__ method | |
1123 | main_mod.__nonzero__ = lambda : True |
|
1134 | main_mod.__nonzero__ = lambda : True | |
1124 |
|
1135 | |||
1125 | return main_mod |
|
1136 | return main_mod | |
1126 |
|
1137 | |||
1127 | def clear_main_mod_cache(self): |
|
1138 | def clear_main_mod_cache(self): | |
@@ -1273,7 +1284,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
1273 | 'user_local':self.user_ns, |
|
1284 | 'user_local':self.user_ns, | |
1274 | 'builtin':builtin_mod.__dict__ |
|
1285 | 'builtin':builtin_mod.__dict__ | |
1275 | } |
|
1286 | } | |
1276 |
|
1287 | |||
1277 | @property |
|
1288 | @property | |
1278 | def user_global_ns(self): |
|
1289 | def user_global_ns(self): | |
1279 | return self.user_module.__dict__ |
|
1290 | return self.user_module.__dict__ | |
@@ -1306,17 +1317,17 b' class InteractiveShell(SingletonConfigurable):' | |||||
1306 | user_ns.setdefault("__name__", "__main__") |
|
1317 | user_ns.setdefault("__name__", "__main__") | |
1307 | user_module = DummyMod() |
|
1318 | user_module = DummyMod() | |
1308 | user_module.__dict__ = user_ns |
|
1319 | user_module.__dict__ = user_ns | |
1309 |
|
1320 | |||
1310 | if user_module is None: |
|
1321 | if user_module is None: | |
1311 | user_module = types.ModuleType("__main__", |
|
1322 | user_module = types.ModuleType("__main__", | |
1312 | doc="Automatically created module for IPython interactive environment") |
|
1323 | doc="Automatically created module for IPython interactive environment") | |
1313 |
|
1324 | |||
1314 | # We must ensure that __builtin__ (without the final 's') is always |
|
1325 | # We must ensure that __builtin__ (without the final 's') is always | |
1315 | # available and pointing to the __builtin__ *module*. For more details: |
|
1326 | # available and pointing to the __builtin__ *module*. For more details: | |
1316 | # http://mail.python.org/pipermail/python-dev/2001-April/014068.html |
|
1327 | # http://mail.python.org/pipermail/python-dev/2001-April/014068.html | |
1317 | user_module.__dict__.setdefault('__builtin__', builtin_mod) |
|
1328 | user_module.__dict__.setdefault('__builtin__', builtin_mod) | |
1318 | user_module.__dict__.setdefault('__builtins__', builtin_mod) |
|
1329 | user_module.__dict__.setdefault('__builtins__', builtin_mod) | |
1319 |
|
1330 | |||
1320 | if user_ns is None: |
|
1331 | if user_ns is None: | |
1321 | user_ns = user_module.__dict__ |
|
1332 | user_ns = user_module.__dict__ | |
1322 |
|
1333 | |||
@@ -1372,7 +1383,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
1372 | # For more details: |
|
1383 | # For more details: | |
1373 | # http://mail.python.org/pipermail/python-dev/2001-April/014068.html |
|
1384 | # http://mail.python.org/pipermail/python-dev/2001-April/014068.html | |
1374 | ns = {} |
|
1385 | ns = {} | |
1375 |
|
1386 | |||
1376 | # make global variables for user access to the histories |
|
1387 | # make global variables for user access to the histories | |
1377 | ns['_ih'] = self.history_manager.input_hist_parsed |
|
1388 | ns['_ih'] = self.history_manager.input_hist_parsed | |
1378 | ns['_oh'] = self.history_manager.output_hist |
|
1389 | ns['_oh'] = self.history_manager.output_hist | |
@@ -1385,7 +1396,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
1385 |
|
1396 | |||
1386 | # Store myself as the public api!!! |
|
1397 | # Store myself as the public api!!! | |
1387 | ns['get_ipython'] = self.get_ipython |
|
1398 | ns['get_ipython'] = self.get_ipython | |
1388 |
|
1399 | |||
1389 | ns['exit'] = self.exiter |
|
1400 | ns['exit'] = self.exiter | |
1390 | ns['quit'] = self.exiter |
|
1401 | ns['quit'] = self.exiter | |
1391 |
|
1402 | |||
@@ -1399,7 +1410,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
1399 |
|
1410 | |||
1400 | # Finally, update the real user's namespace |
|
1411 | # Finally, update the real user's namespace | |
1401 | self.user_ns.update(ns) |
|
1412 | self.user_ns.update(ns) | |
1402 |
|
1413 | |||
1403 | @property |
|
1414 | @property | |
1404 | def all_ns_refs(self): |
|
1415 | def all_ns_refs(self): | |
1405 | """Get a list of references to all the namespace dictionaries in which |
|
1416 | """Get a list of references to all the namespace dictionaries in which | |
@@ -1425,7 +1436,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
1425 | # Reset last execution result |
|
1436 | # Reset last execution result | |
1426 | self.last_execution_succeeded = True |
|
1437 | self.last_execution_succeeded = True | |
1427 | self.last_execution_result = None |
|
1438 | self.last_execution_result = None | |
1428 |
|
1439 | |||
1429 | # Flush cached output items |
|
1440 | # Flush cached output items | |
1430 | if self.displayhook.do_full_cache: |
|
1441 | if self.displayhook.do_full_cache: | |
1431 | self.displayhook.flush() |
|
1442 | self.displayhook.flush() | |
@@ -1490,7 +1501,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
1490 | raise ValueError("Refusing to delete %s" % varname) |
|
1501 | raise ValueError("Refusing to delete %s" % varname) | |
1491 |
|
1502 | |||
1492 | ns_refs = self.all_ns_refs |
|
1503 | ns_refs = self.all_ns_refs | |
1493 |
|
1504 | |||
1494 | if by_name: # Delete by name |
|
1505 | if by_name: # Delete by name | |
1495 | for ns in ns_refs: |
|
1506 | for ns in ns_refs: | |
1496 | try: |
|
1507 | try: | |
@@ -1765,8 +1776,14 b' class InteractiveShell(SingletonConfigurable):' | |||||
1765 | if meth == 'pdoc': |
|
1776 | if meth == 'pdoc': | |
1766 | pmethod(info.obj, oname, formatter) |
|
1777 | pmethod(info.obj, oname, formatter) | |
1767 | elif meth == 'pinfo': |
|
1778 | elif meth == 'pinfo': | |
1768 | pmethod(info.obj, oname, formatter, info, |
|
1779 | pmethod( | |
1769 | enable_html_pager=self.enable_html_pager, **kw) |
|
1780 | info.obj, | |
|
1781 | oname, | |||
|
1782 | formatter, | |||
|
1783 | info, | |||
|
1784 | enable_html_pager=self.enable_html_pager, | |||
|
1785 | **kw | |||
|
1786 | ) | |||
1770 | else: |
|
1787 | else: | |
1771 | pmethod(info.obj, oname) |
|
1788 | pmethod(info.obj, oname) | |
1772 | else: |
|
1789 | else: | |
@@ -1890,7 +1907,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
1890 | print('Exception type :', etype) |
|
1907 | print('Exception type :', etype) | |
1891 | print('Exception value:', value) |
|
1908 | print('Exception value:', value) | |
1892 | print('Traceback :', tb) |
|
1909 | print('Traceback :', tb) | |
1893 |
|
1910 | |||
1894 | def validate_stb(stb): |
|
1911 | def validate_stb(stb): | |
1895 | """validate structured traceback return type |
|
1912 | """validate structured traceback return type | |
1896 |
|
1913 | |||
@@ -1919,7 +1936,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
1919 | else: |
|
1936 | else: | |
1920 | def wrapped(self,etype,value,tb,tb_offset=None): |
|
1937 | def wrapped(self,etype,value,tb,tb_offset=None): | |
1921 | """wrap CustomTB handler, to protect IPython from user code |
|
1938 | """wrap CustomTB handler, to protect IPython from user code | |
1922 |
|
1939 | |||
1923 | This makes it harder (but not impossible) for custom exception |
|
1940 | This makes it harder (but not impossible) for custom exception | |
1924 | handlers to crash IPython. |
|
1941 | handlers to crash IPython. | |
1925 | """ |
|
1942 | """ | |
@@ -1968,10 +1985,10 b' class InteractiveShell(SingletonConfigurable):' | |||||
1968 |
|
1985 | |||
1969 | def _get_exc_info(self, exc_tuple=None): |
|
1986 | def _get_exc_info(self, exc_tuple=None): | |
1970 | """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc. |
|
1987 | """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc. | |
1971 |
|
1988 | |||
1972 | Ensures sys.last_type,value,traceback hold the exc_info we found, |
|
1989 | Ensures sys.last_type,value,traceback hold the exc_info we found, | |
1973 | from whichever source. |
|
1990 | from whichever source. | |
1974 |
|
1991 | |||
1975 | raises ValueError if none of these contain any information |
|
1992 | raises ValueError if none of these contain any information | |
1976 | """ |
|
1993 | """ | |
1977 | if exc_tuple is None: |
|
1994 | if exc_tuple is None: | |
@@ -1983,10 +2000,10 b' class InteractiveShell(SingletonConfigurable):' | |||||
1983 | if hasattr(sys, 'last_type'): |
|
2000 | if hasattr(sys, 'last_type'): | |
1984 | etype, value, tb = sys.last_type, sys.last_value, \ |
|
2001 | etype, value, tb = sys.last_type, sys.last_value, \ | |
1985 | sys.last_traceback |
|
2002 | sys.last_traceback | |
1986 |
|
2003 | |||
1987 | if etype is None: |
|
2004 | if etype is None: | |
1988 | raise ValueError("No exception to find") |
|
2005 | raise ValueError("No exception to find") | |
1989 |
|
2006 | |||
1990 | # Now store the exception info in sys.last_type etc. |
|
2007 | # Now store the exception info in sys.last_type etc. | |
1991 | # WARNING: these variables are somewhat deprecated and not |
|
2008 | # WARNING: these variables are somewhat deprecated and not | |
1992 | # necessarily safe to use in a threaded environment, but tools |
|
2009 | # necessarily safe to use in a threaded environment, but tools | |
@@ -1995,16 +2012,16 b' class InteractiveShell(SingletonConfigurable):' | |||||
1995 | sys.last_type = etype |
|
2012 | sys.last_type = etype | |
1996 | sys.last_value = value |
|
2013 | sys.last_value = value | |
1997 | sys.last_traceback = tb |
|
2014 | sys.last_traceback = tb | |
1998 |
|
2015 | |||
1999 | return etype, value, tb |
|
2016 | return etype, value, tb | |
2000 |
|
2017 | |||
2001 | def show_usage_error(self, exc): |
|
2018 | def show_usage_error(self, exc): | |
2002 | """Show a short message for UsageErrors |
|
2019 | """Show a short message for UsageErrors | |
2003 |
|
2020 | |||
2004 | These are special exceptions that shouldn't show a traceback. |
|
2021 | These are special exceptions that shouldn't show a traceback. | |
2005 | """ |
|
2022 | """ | |
2006 | print("UsageError: %s" % exc, file=sys.stderr) |
|
2023 | print("UsageError: %s" % exc, file=sys.stderr) | |
2007 |
|
2024 | |||
2008 | def get_exception_only(self, exc_tuple=None): |
|
2025 | def get_exception_only(self, exc_tuple=None): | |
2009 | """ |
|
2026 | """ | |
2010 | Return as a string (ending with a newline) the exception that |
|
2027 | Return as a string (ending with a newline) the exception that | |
@@ -2118,7 +2135,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
2118 |
|
2135 | |||
2119 | def init_readline(self): |
|
2136 | def init_readline(self): | |
2120 | """DEPRECATED |
|
2137 | """DEPRECATED | |
2121 |
|
2138 | |||
2122 | Moved to terminal subclass, here only to simplify the init logic.""" |
|
2139 | Moved to terminal subclass, here only to simplify the init logic.""" | |
2123 | # Set a number of methods that depend on readline to be no-op |
|
2140 | # Set a number of methods that depend on readline to be no-op | |
2124 | warnings.warn('`init_readline` is no-op since IPython 5.0 and is Deprecated', |
|
2141 | warnings.warn('`init_readline` is no-op since IPython 5.0 and is Deprecated', | |
@@ -2285,12 +2302,13 b' class InteractiveShell(SingletonConfigurable):' | |||||
2285 | # should be split into a prompt manager and displayhook. We probably |
|
2302 | # should be split into a prompt manager and displayhook. We probably | |
2286 | # even need a centralize colors management object. |
|
2303 | # even need a centralize colors management object. | |
2287 | self.run_line_magic('colors', self.colors) |
|
2304 | self.run_line_magic('colors', self.colors) | |
2288 |
|
2305 | |||
2289 | # Defined here so that it's included in the documentation |
|
2306 | # Defined here so that it's included in the documentation | |
2290 | @functools.wraps(magic.MagicsManager.register_function) |
|
2307 | @functools.wraps(magic.MagicsManager.register_function) | |
2291 | def register_magic_function(self, func, magic_kind='line', magic_name=None): |
|
2308 | def register_magic_function(self, func, magic_kind='line', magic_name=None): | |
2292 |
self.magics_manager.register_function( |
|
2309 | self.magics_manager.register_function( | |
2293 |
|
|
2310 | func, magic_kind=magic_kind, magic_name=magic_name | |
|
2311 | ) | |||
2294 |
|
2312 | |||
2295 | def run_line_magic(self, magic_name, line, _stack_depth=1): |
|
2313 | def run_line_magic(self, magic_name, line, _stack_depth=1): | |
2296 | """Execute the given line magic. |
|
2314 | """Execute the given line magic. | |
@@ -2521,7 +2539,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
2521 | ec = 130 |
|
2539 | ec = 130 | |
2522 | if ec > 128: |
|
2540 | if ec > 128: | |
2523 | ec = -(ec - 128) |
|
2541 | ec = -(ec - 128) | |
2524 |
|
2542 | |||
2525 | # We explicitly do NOT return the subprocess status code, because |
|
2543 | # We explicitly do NOT return the subprocess status code, because | |
2526 | # a non-None value would trigger :func:`sys.displayhook` calls. |
|
2544 | # a non-None value would trigger :func:`sys.displayhook` calls. | |
2527 | # Instead, we store the exit_code in user_ns. Note the semantics |
|
2545 | # Instead, we store the exit_code in user_ns. Note the semantics | |
@@ -2584,7 +2602,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
2584 | def init_payload(self): |
|
2602 | def init_payload(self): | |
2585 | self.payload_manager = PayloadManager(parent=self) |
|
2603 | self.payload_manager = PayloadManager(parent=self) | |
2586 | self.configurables.append(self.payload_manager) |
|
2604 | self.configurables.append(self.payload_manager) | |
2587 |
|
2605 | |||
2588 | #------------------------------------------------------------------------- |
|
2606 | #------------------------------------------------------------------------- | |
2589 | # Things related to the prefilter |
|
2607 | # Things related to the prefilter | |
2590 | #------------------------------------------------------------------------- |
|
2608 | #------------------------------------------------------------------------- | |
@@ -2624,13 +2642,13 b' class InteractiveShell(SingletonConfigurable):' | |||||
2624 |
|
2642 | |||
2625 | def _user_obj_error(self): |
|
2643 | def _user_obj_error(self): | |
2626 | """return simple exception dict |
|
2644 | """return simple exception dict | |
2627 |
|
2645 | |||
2628 | for use in user_expressions |
|
2646 | for use in user_expressions | |
2629 | """ |
|
2647 | """ | |
2630 |
|
2648 | |||
2631 | etype, evalue, tb = self._get_exc_info() |
|
2649 | etype, evalue, tb = self._get_exc_info() | |
2632 | stb = self.InteractiveTB.get_exception_only(etype, evalue) |
|
2650 | stb = self.InteractiveTB.get_exception_only(etype, evalue) | |
2633 |
|
2651 | |||
2634 | exc_info = { |
|
2652 | exc_info = { | |
2635 | "status": "error", |
|
2653 | "status": "error", | |
2636 | "traceback": stb, |
|
2654 | "traceback": stb, | |
@@ -2639,13 +2657,13 b' class InteractiveShell(SingletonConfigurable):' | |||||
2639 | } |
|
2657 | } | |
2640 |
|
2658 | |||
2641 | return exc_info |
|
2659 | return exc_info | |
2642 |
|
2660 | |||
2643 | def _format_user_obj(self, obj): |
|
2661 | def _format_user_obj(self, obj): | |
2644 | """format a user object to display dict |
|
2662 | """format a user object to display dict | |
2645 |
|
2663 | |||
2646 | for use in user_expressions |
|
2664 | for use in user_expressions | |
2647 | """ |
|
2665 | """ | |
2648 |
|
2666 | |||
2649 | data, md = self.display_formatter.format(obj) |
|
2667 | data, md = self.display_formatter.format(obj) | |
2650 | value = { |
|
2668 | value = { | |
2651 | 'status' : 'ok', |
|
2669 | 'status' : 'ok', | |
@@ -2653,7 +2671,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
2653 | 'metadata' : md, |
|
2671 | 'metadata' : md, | |
2654 | } |
|
2672 | } | |
2655 | return value |
|
2673 | return value | |
2656 |
|
2674 | |||
2657 | def user_expressions(self, expressions): |
|
2675 | def user_expressions(self, expressions): | |
2658 | """Evaluate a dict of expressions in the user's namespace. |
|
2676 | """Evaluate a dict of expressions in the user's namespace. | |
2659 |
|
2677 | |||
@@ -2672,7 +2690,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
2672 | out = {} |
|
2690 | out = {} | |
2673 | user_ns = self.user_ns |
|
2691 | user_ns = self.user_ns | |
2674 | global_ns = self.user_global_ns |
|
2692 | global_ns = self.user_global_ns | |
2675 |
|
2693 | |||
2676 | for key, expr in expressions.items(): |
|
2694 | for key, expr in expressions.items(): | |
2677 | try: |
|
2695 | try: | |
2678 | value = self._format_user_obj(eval(expr, global_ns, user_ns)) |
|
2696 | value = self._format_user_obj(eval(expr, global_ns, user_ns)) | |
@@ -3086,12 +3104,14 b' class InteractiveShell(SingletonConfigurable):' | |||||
3086 | # Our own compiler remembers the __future__ environment. If we want to |
|
3104 | # Our own compiler remembers the __future__ environment. If we want to | |
3087 | # run code with a separate __future__ environment, use the default |
|
3105 | # run code with a separate __future__ environment, use the default | |
3088 | # compiler |
|
3106 | # compiler | |
3089 |
compiler = self.compile if shell_futures else |
|
3107 | compiler = self.compile if shell_futures else self.compiler_class() | |
3090 |
|
3108 | |||
3091 | _run_async = False |
|
3109 | _run_async = False | |
3092 |
|
3110 | |||
3093 | with self.builtin_trap: |
|
3111 | with self.builtin_trap: | |
3094 |
cell_name = self.compile.cache( |
|
3112 | cell_name = self.compile.cache( | |
|
3113 | cell, self.execution_count, raw_code=raw_cell | |||
|
3114 | ) | |||
3095 |
|
3115 | |||
3096 | with self.display_trap: |
|
3116 | with self.display_trap: | |
3097 | # Compile to bytecode |
|
3117 | # Compile to bytecode | |
@@ -3197,13 +3217,13 b' class InteractiveShell(SingletonConfigurable):' | |||||
3197 |
|
3217 | |||
3198 | def transform_ast(self, node): |
|
3218 | def transform_ast(self, node): | |
3199 | """Apply the AST transformations from self.ast_transformers |
|
3219 | """Apply the AST transformations from self.ast_transformers | |
3200 |
|
3220 | |||
3201 | Parameters |
|
3221 | Parameters | |
3202 | ---------- |
|
3222 | ---------- | |
3203 | node : ast.Node |
|
3223 | node : ast.Node | |
3204 | The root node to be transformed. Typically called with the ast.Module |
|
3224 | The root node to be transformed. Typically called with the ast.Module | |
3205 | produced by parsing user input. |
|
3225 | produced by parsing user input. | |
3206 |
|
3226 | |||
3207 | Returns |
|
3227 | Returns | |
3208 | ------- |
|
3228 | ------- | |
3209 | An ast.Node corresponding to the node it was called with. Note that it |
|
3229 | An ast.Node corresponding to the node it was called with. Note that it | |
@@ -3250,7 +3270,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
3250 | Experimental value: 'async' Will try to run top level interactive |
|
3270 | Experimental value: 'async' Will try to run top level interactive | |
3251 | async/await code in default runner, this will not respect the |
|
3271 | async/await code in default runner, this will not respect the | |
3252 | interactivity setting and will only run the last node if it is an |
|
3272 | interactivity setting and will only run the last node if it is an | |
3253 |
expression. |
|
3273 | expression. | |
3254 |
|
3274 | |||
3255 | compiler : callable |
|
3275 | compiler : callable | |
3256 | A function with the same interface as the built-in compile(), to turn |
|
3276 | A function with the same interface as the built-in compile(), to turn | |
@@ -3471,17 +3491,17 b' class InteractiveShell(SingletonConfigurable):' | |||||
3471 |
|
3491 | |||
3472 | def enable_gui(self, gui=None): |
|
3492 | def enable_gui(self, gui=None): | |
3473 | raise NotImplementedError('Implement enable_gui in a subclass') |
|
3493 | raise NotImplementedError('Implement enable_gui in a subclass') | |
3474 |
|
3494 | |||
3475 | def enable_matplotlib(self, gui=None): |
|
3495 | def enable_matplotlib(self, gui=None): | |
3476 | """Enable interactive matplotlib and inline figure support. |
|
3496 | """Enable interactive matplotlib and inline figure support. | |
3477 |
|
3497 | |||
3478 | This takes the following steps: |
|
3498 | This takes the following steps: | |
3479 |
|
3499 | |||
3480 | 1. select the appropriate eventloop and matplotlib backend |
|
3500 | 1. select the appropriate eventloop and matplotlib backend | |
3481 | 2. set up matplotlib for interactive use with that backend |
|
3501 | 2. set up matplotlib for interactive use with that backend | |
3482 | 3. configure formatters for inline figure display |
|
3502 | 3. configure formatters for inline figure display | |
3483 | 4. enable the selected gui eventloop |
|
3503 | 4. enable the selected gui eventloop | |
3484 |
|
3504 | |||
3485 | Parameters |
|
3505 | Parameters | |
3486 | ---------- |
|
3506 | ---------- | |
3487 | gui : optional, string |
|
3507 | gui : optional, string | |
@@ -3495,7 +3515,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
3495 | """ |
|
3515 | """ | |
3496 | from IPython.core import pylabtools as pt |
|
3516 | from IPython.core import pylabtools as pt | |
3497 | gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select) |
|
3517 | gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select) | |
3498 |
|
3518 | |||
3499 | if gui != 'inline': |
|
3519 | if gui != 'inline': | |
3500 | # If we have our first gui selection, store it |
|
3520 | # If we have our first gui selection, store it | |
3501 | if self.pylab_gui_select is None: |
|
3521 | if self.pylab_gui_select is None: | |
@@ -3505,16 +3525,16 b' class InteractiveShell(SingletonConfigurable):' | |||||
3505 | print('Warning: Cannot change to a different GUI toolkit: %s.' |
|
3525 | print('Warning: Cannot change to a different GUI toolkit: %s.' | |
3506 | ' Using %s instead.' % (gui, self.pylab_gui_select)) |
|
3526 | ' Using %s instead.' % (gui, self.pylab_gui_select)) | |
3507 | gui, backend = pt.find_gui_and_backend(self.pylab_gui_select) |
|
3527 | gui, backend = pt.find_gui_and_backend(self.pylab_gui_select) | |
3508 |
|
3528 | |||
3509 | pt.activate_matplotlib(backend) |
|
3529 | pt.activate_matplotlib(backend) | |
3510 | pt.configure_inline_support(self, backend) |
|
3530 | pt.configure_inline_support(self, backend) | |
3511 |
|
3531 | |||
3512 | # Now we must activate the gui pylab wants to use, and fix %run to take |
|
3532 | # Now we must activate the gui pylab wants to use, and fix %run to take | |
3513 | # plot updates into account |
|
3533 | # plot updates into account | |
3514 | self.enable_gui(gui) |
|
3534 | self.enable_gui(gui) | |
3515 | self.magics_manager.registry['ExecutionMagics'].default_runner = \ |
|
3535 | self.magics_manager.registry['ExecutionMagics'].default_runner = \ | |
3516 | pt.mpl_runner(self.safe_execfile) |
|
3536 | pt.mpl_runner(self.safe_execfile) | |
3517 |
|
3537 | |||
3518 | return gui, backend |
|
3538 | return gui, backend | |
3519 |
|
3539 | |||
3520 | def enable_pylab(self, gui=None, import_all=True, welcome_message=False): |
|
3540 | def enable_pylab(self, gui=None, import_all=True, welcome_message=False): | |
@@ -3524,7 +3544,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
3524 | namespace all of numpy and pylab, and configures IPython to correctly |
|
3544 | namespace all of numpy and pylab, and configures IPython to correctly | |
3525 | interact with the GUI event loop. The GUI backend to be used can be |
|
3545 | interact with the GUI event loop. The GUI backend to be used can be | |
3526 | optionally selected with the optional ``gui`` argument. |
|
3546 | optionally selected with the optional ``gui`` argument. | |
3527 |
|
3547 | |||
3528 | This method only adds preloading the namespace to InteractiveShell.enable_matplotlib. |
|
3548 | This method only adds preloading the namespace to InteractiveShell.enable_matplotlib. | |
3529 |
|
3549 | |||
3530 | Parameters |
|
3550 | Parameters | |
@@ -3544,9 +3564,9 b' class InteractiveShell(SingletonConfigurable):' | |||||
3544 | This argument is ignored, no welcome message will be displayed. |
|
3564 | This argument is ignored, no welcome message will be displayed. | |
3545 | """ |
|
3565 | """ | |
3546 | from IPython.core.pylabtools import import_pylab |
|
3566 | from IPython.core.pylabtools import import_pylab | |
3547 |
|
3567 | |||
3548 | gui, backend = self.enable_matplotlib(gui) |
|
3568 | gui, backend = self.enable_matplotlib(gui) | |
3549 |
|
3569 | |||
3550 | # We want to prevent the loading of pylab to pollute the user's |
|
3570 | # We want to prevent the loading of pylab to pollute the user's | |
3551 | # namespace as shown by the %who* magics, so we execute the activation |
|
3571 | # namespace as shown by the %who* magics, so we execute the activation | |
3552 | # code in an empty namespace, and we update *both* user_ns and |
|
3572 | # code in an empty namespace, and we update *both* user_ns and |
@@ -20,7 +20,7 b' import re' | |||||
20 | import sys |
|
20 | import sys | |
21 | import ast |
|
21 | import ast | |
22 | from itertools import chain |
|
22 | from itertools import chain | |
23 | from urllib.request import urlopen |
|
23 | from urllib.request import Request, urlopen | |
24 | from urllib.parse import urlencode |
|
24 | from urllib.parse import urlencode | |
25 | from pathlib import Path |
|
25 | from pathlib import Path | |
26 |
|
26 | |||
@@ -29,6 +29,7 b' from IPython.core.error import TryNext, StdinNotImplementedError, UsageError' | |||||
29 | from IPython.core.macro import Macro |
|
29 | from IPython.core.macro import Macro | |
30 | from IPython.core.magic import Magics, magics_class, line_magic |
|
30 | from IPython.core.magic import Magics, magics_class, line_magic | |
31 | from IPython.core.oinspect import find_file, find_source_lines |
|
31 | from IPython.core.oinspect import find_file, find_source_lines | |
|
32 | from IPython.core.release import version | |||
32 | from IPython.testing.skipdoctest import skip_doctest |
|
33 | from IPython.testing.skipdoctest import skip_doctest | |
33 | from IPython.utils.contexts import preserve_keys |
|
34 | from IPython.utils.contexts import preserve_keys | |
34 | from IPython.utils.path import get_py_filename |
|
35 | from IPython.utils.path import get_py_filename | |
@@ -245,7 +246,7 b' class CodeMagics(Magics):' | |||||
245 |
|
246 | |||
246 | @line_magic |
|
247 | @line_magic | |
247 | def pastebin(self, parameter_s=''): |
|
248 | def pastebin(self, parameter_s=''): | |
248 |
"""Upload code to dpaste |
|
249 | """Upload code to dpaste.com, returning the URL. | |
249 |
|
250 | |||
250 | Usage:\\ |
|
251 | Usage:\\ | |
251 | %pastebin [-d "Custom description"] 1-7 |
|
252 | %pastebin [-d "Custom description"] 1-7 | |
@@ -255,7 +256,7 b' class CodeMagics(Magics):' | |||||
255 |
|
256 | |||
256 | Options: |
|
257 | Options: | |
257 |
|
258 | |||
258 |
-d: Pass a custom description |
|
259 | -d: Pass a custom description. The default will say | |
259 | "Pasted from IPython". |
|
260 | "Pasted from IPython". | |
260 | """ |
|
261 | """ | |
261 | opts, args = self.parse_options(parameter_s, 'd:') |
|
262 | opts, args = self.parse_options(parameter_s, 'd:') | |
@@ -266,13 +267,19 b' class CodeMagics(Magics):' | |||||
266 | print(e.args[0]) |
|
267 | print(e.args[0]) | |
267 | return |
|
268 | return | |
268 |
|
269 | |||
269 |
post_data = urlencode( |
|
270 | post_data = urlencode( | |
270 | "title": opts.get('d', "Pasted from IPython"), |
|
271 | { | |
271 | "syntax": "python3", |
|
272 | "title": opts.get("d", "Pasted from IPython"), | |
272 | "content": code |
|
273 | "syntax": "python", | |
273 | }).encode('utf-8') |
|
274 | "content": code, | |
274 |
|
275 | } | ||
275 | response = urlopen("http://dpaste.com/api/v2/", post_data) |
|
276 | ).encode("utf-8") | |
|
277 | ||||
|
278 | request = Request( | |||
|
279 | "http://dpaste.com/api/v2/", | |||
|
280 | headers={"User-Agent": "IPython v{}".format(version)}, | |||
|
281 | ) | |||
|
282 | response = urlopen(request, post_data) | |||
276 | return response.headers.get('Location') |
|
283 | return response.headers.get('Location') | |
277 |
|
284 | |||
278 | @line_magic |
|
285 | @line_magic |
@@ -16,6 +16,7 b'' | |||||
16 | import os |
|
16 | import os | |
17 | import sys |
|
17 | import sys | |
18 | from io import open as io_open |
|
18 | from io import open as io_open | |
|
19 | import fnmatch | |||
19 |
|
20 | |||
20 | # Our own packages |
|
21 | # Our own packages | |
21 | from IPython.core.error import StdinNotImplementedError |
|
22 | from IPython.core.error import StdinNotImplementedError | |
@@ -170,7 +171,8 b' class HistoryMagics(Magics):' | |||||
170 | pattern = None |
|
171 | pattern = None | |
171 | limit = None if args.limit is _unspecified else args.limit |
|
172 | limit = None if args.limit is _unspecified else args.limit | |
172 |
|
173 | |||
173 |
|
|
174 | range_pattern = False | |
|
175 | if args.pattern is not None and not args.range: | |||
174 | if args.pattern: |
|
176 | if args.pattern: | |
175 | pattern = "*" + " ".join(args.pattern) + "*" |
|
177 | pattern = "*" + " ".join(args.pattern) + "*" | |
176 | else: |
|
178 | else: | |
@@ -183,6 +185,9 b' class HistoryMagics(Magics):' | |||||
183 | hist = history_manager.get_tail(n, raw=raw, output=get_output) |
|
185 | hist = history_manager.get_tail(n, raw=raw, output=get_output) | |
184 | else: |
|
186 | else: | |
185 | if args.range: # Get history by ranges |
|
187 | if args.range: # Get history by ranges | |
|
188 | if args.pattern: | |||
|
189 | range_pattern = "*" + " ".join(args.pattern) + "*" | |||
|
190 | print_nums = True | |||
186 | hist = history_manager.get_range_by_str(" ".join(args.range), |
|
191 | hist = history_manager.get_range_by_str(" ".join(args.range), | |
187 | raw, get_output) |
|
192 | raw, get_output) | |
188 | else: # Just get history for the current session |
|
193 | else: # Just get history for the current session | |
@@ -200,6 +205,9 b' class HistoryMagics(Magics):' | |||||
200 | # into an editor. |
|
205 | # into an editor. | |
201 | if get_output: |
|
206 | if get_output: | |
202 | inline, output = inline |
|
207 | inline, output = inline | |
|
208 | if range_pattern: | |||
|
209 | if not fnmatch.fnmatch(inline, range_pattern): | |||
|
210 | continue | |||
203 | inline = inline.expandtabs(4).rstrip() |
|
211 | inline = inline.expandtabs(4).rstrip() | |
204 |
|
212 | |||
205 | multiline = "\n" in inline |
|
213 | multiline = "\n" in inline |
@@ -13,7 +13,6 b' import shlex' | |||||
13 | import sys |
|
13 | import sys | |
14 | from pathlib import Path |
|
14 | from pathlib import Path | |
15 |
|
15 | |||
16 | from pathlib import Path |
|
|||
17 | from IPython.core.magic import Magics, magics_class, line_magic |
|
16 | from IPython.core.magic import Magics, magics_class, line_magic | |
18 |
|
17 | |||
19 |
|
18 | |||
@@ -28,7 +27,7 b' def _get_conda_executable():' | |||||
28 | # Check if there is a conda executable in the same directory as the Python executable. |
|
27 | # Check if there is a conda executable in the same directory as the Python executable. | |
29 | # This is the case within conda's root environment. |
|
28 | # This is the case within conda's root environment. | |
30 | conda = Path(sys.executable).parent / "conda" |
|
29 | conda = Path(sys.executable).parent / "conda" | |
31 | if conda.isfile(): |
|
30 | if conda.is_file(): | |
32 | return str(conda) |
|
31 | return str(conda) | |
33 |
|
32 | |||
34 | # Otherwise, attempt to extract the executable from conda history. |
|
33 | # Otherwise, attempt to extract the executable from conda history. | |
@@ -41,7 +40,7 b' def _get_conda_executable():' | |||||
41 | ) |
|
40 | ) | |
42 | if match: |
|
41 | if match: | |
43 | return match.groupdict()["command"] |
|
42 | return match.groupdict()["command"] | |
44 |
|
43 | |||
45 | # Fallback: assume conda is available on the system path. |
|
44 | # Fallback: assume conda is available on the system path. | |
46 | return "conda" |
|
45 | return "conda" | |
47 |
|
46 | |||
@@ -73,18 +72,19 b' class PackagingMagics(Magics):' | |||||
73 | @line_magic |
|
72 | @line_magic | |
74 | def conda(self, line): |
|
73 | def conda(self, line): | |
75 | """Run the conda package manager within the current kernel. |
|
74 | """Run the conda package manager within the current kernel. | |
76 |
|
75 | |||
77 | Usage: |
|
76 | Usage: | |
78 | %conda install [pkgs] |
|
77 | %conda install [pkgs] | |
79 | """ |
|
78 | """ | |
80 | if not _is_conda_environment(): |
|
79 | if not _is_conda_environment(): | |
81 | raise ValueError("The python kernel does not appear to be a conda environment. " |
|
80 | raise ValueError("The python kernel does not appear to be a conda environment. " | |
82 | "Please use ``%pip install`` instead.") |
|
81 | "Please use ``%pip install`` instead.") | |
83 |
|
82 | |||
84 | conda = _get_conda_executable() |
|
83 | conda = _get_conda_executable() | |
85 | args = shlex.split(line) |
|
84 | args = shlex.split(line) | |
86 | command = args[0] |
|
85 | command = args[0] if len(args) > 0 else "" | |
87 | args = args[1:] |
|
86 | args = args[1:] if len(args) > 1 else [""] | |
|
87 | ||||
88 | extra_args = [] |
|
88 | extra_args = [] | |
89 |
|
89 | |||
90 | # When the subprocess does not allow us to respond "yes" during the installation, |
|
90 | # When the subprocess does not allow us to respond "yes" during the installation, |
@@ -183,7 +183,7 b' def test_set_matplotlib_formats_kwargs():' | |||||
183 | ip = get_ipython() |
|
183 | ip = get_ipython() | |
184 | cfg = _get_inline_config() |
|
184 | cfg = _get_inline_config() | |
185 | cfg.print_figure_kwargs.update(dict(foo='bar')) |
|
185 | cfg.print_figure_kwargs.update(dict(foo='bar')) | |
186 |
kwargs = dict( |
|
186 | kwargs = dict(dpi=150) | |
187 | display.set_matplotlib_formats('png', **kwargs) |
|
187 | display.set_matplotlib_formats('png', **kwargs) | |
188 | formatter = ip.display_formatter.formatters['image/png'] |
|
188 | formatter = ip.display_formatter.formatters['image/png'] | |
189 | f = formatter.lookup_by_type(Figure) |
|
189 | f = formatter.lookup_by_type(Figure) |
@@ -255,18 +255,18 b' def test_find_assign_op_dedent():' | |||||
255 |
|
255 | |||
256 | def test_check_complete(): |
|
256 | def test_check_complete(): | |
257 | cc = ipt2.TransformerManager().check_complete |
|
257 | cc = ipt2.TransformerManager().check_complete | |
258 |
nt.assert_equal(cc("a = 1"), ( |
|
258 | nt.assert_equal(cc("a = 1"), ("complete", None)) | |
259 |
nt.assert_equal(cc("for a in range(5):"), ( |
|
259 | nt.assert_equal(cc("for a in range(5):"), ("incomplete", 4)) | |
260 |
nt.assert_equal(cc("for a in range(5):\n if a > 0:"), ( |
|
260 | nt.assert_equal(cc("for a in range(5):\n if a > 0:"), ("incomplete", 8)) | |
261 |
nt.assert_equal(cc("raise = 2"), ( |
|
261 | nt.assert_equal(cc("raise = 2"), ("invalid", None)) | |
262 |
nt.assert_equal(cc("a = [1,\n2,"), ( |
|
262 | nt.assert_equal(cc("a = [1,\n2,"), ("incomplete", 0)) | |
263 |
nt.assert_equal(cc(")"), ( |
|
263 | nt.assert_equal(cc("(\n))"), ("incomplete", 0)) | |
264 |
nt.assert_equal(cc("\\\r\n"), ( |
|
264 | nt.assert_equal(cc("\\\r\n"), ("incomplete", 0)) | |
265 |
nt.assert_equal(cc("a = '''\n hi"), ( |
|
265 | nt.assert_equal(cc("a = '''\n hi"), ("incomplete", 3)) | |
266 |
nt.assert_equal(cc("def a():\n x=1\n global x"), ( |
|
266 | nt.assert_equal(cc("def a():\n x=1\n global x"), ("invalid", None)) | |
267 |
nt.assert_equal(cc("a \\ "), ( |
|
267 | nt.assert_equal(cc("a \\ "), ("invalid", None)) # Nothing allowed after backslash | |
268 |
nt.assert_equal(cc("1\\\n+2"), ( |
|
268 | nt.assert_equal(cc("1\\\n+2"), ("complete", None)) | |
269 |
nt.assert_equal(cc("exit"), ( |
|
269 | nt.assert_equal(cc("exit"), ("complete", None)) | |
270 |
|
270 | |||
271 | example = dedent(""" |
|
271 | example = dedent(""" | |
272 | if True: |
|
272 | if True: | |
@@ -297,6 +297,24 b' def test_check_complete_II():' | |||||
297 | nt.assert_equal(cc('''def foo():\n """'''), ('incomplete', 4)) |
|
297 | nt.assert_equal(cc('''def foo():\n """'''), ('incomplete', 4)) | |
298 |
|
298 | |||
299 |
|
299 | |||
|
300 | def test_check_complete_invalidates_sunken_brackets(): | |||
|
301 | """ | |||
|
302 | Test that a single line with more closing brackets than the opening ones is | |||
|
303 | interpretted as invalid | |||
|
304 | """ | |||
|
305 | cc = ipt2.TransformerManager().check_complete | |||
|
306 | nt.assert_equal(cc(")"), ("invalid", None)) | |||
|
307 | nt.assert_equal(cc("]"), ("invalid", None)) | |||
|
308 | nt.assert_equal(cc("}"), ("invalid", None)) | |||
|
309 | nt.assert_equal(cc(")("), ("invalid", None)) | |||
|
310 | nt.assert_equal(cc("]["), ("invalid", None)) | |||
|
311 | nt.assert_equal(cc("}{"), ("invalid", None)) | |||
|
312 | nt.assert_equal(cc("]()("), ("invalid", None)) | |||
|
313 | nt.assert_equal(cc("())("), ("invalid", None)) | |||
|
314 | nt.assert_equal(cc(")[]("), ("invalid", None)) | |||
|
315 | nt.assert_equal(cc("()]("), ("invalid", None)) | |||
|
316 | ||||
|
317 | ||||
300 | def test_null_cleanup_transformer(): |
|
318 | def test_null_cleanup_transformer(): | |
301 | manager = ipt2.TransformerManager() |
|
319 | manager = ipt2.TransformerManager() | |
302 | manager.cleanup_transforms.insert(0, null_cleanup_transformer) |
|
320 | manager.cleanup_transforms.insert(0, null_cleanup_transformer) |
@@ -117,84 +117,91 b' ZeroDivisionError Traceback (most recent call last)' | |||||
117 | ZeroDivisionError: ... |
|
117 | ZeroDivisionError: ... | |
118 | """ |
|
118 | """ | |
119 |
|
119 | |||
120 | def doctest_tb_sysexit(): |
|
120 | # TODO : Marc 2021 – this seem to fail due | |
121 | """ |
|
121 | # to upstream changes in CI for whatever reason. | |
122 | In [17]: %xmode plain |
|
122 | # Commenting for now, to revive someday (maybe?) | |
123 | Exception reporting mode: Plain |
|
123 | # nose won't work in 3.10 anyway and we'll have to disable iptest. | |
124 |
|
124 | # thus this likely need to bemigrated to pytest. | ||
125 | In [18]: %run simpleerr.py exit |
|
125 | ||
126 | An exception has occurred, use %tb to see the full traceback. |
|
126 | ||
127 | SystemExit: (1, 'Mode = exit') |
|
127 | # def doctest_tb_sysexit(): | |
128 |
|
128 | # """ | ||
129 | In [19]: %run simpleerr.py exit 2 |
|
129 | # In [17]: %xmode plain | |
130 | An exception has occurred, use %tb to see the full traceback. |
|
130 | # Exception reporting mode: Plain | |
131 | SystemExit: (2, 'Mode = exit') |
|
131 | # | |
132 |
|
132 | # In [18]: %run simpleerr.py exit | ||
133 | In [20]: %tb |
|
133 | # An exception has occurred, use %tb to see the full traceback. | |
134 | Traceback (most recent call last): |
|
134 | # SystemExit: (1, 'Mode = exit') | |
135 | File ... in <module> |
|
135 | # | |
136 | bar(mode) |
|
136 | # In [19]: %run simpleerr.py exit 2 | |
137 | File ... line 22, in bar |
|
137 | # An exception has occurred, use %tb to see the full traceback. | |
138 | sysexit(stat, mode) |
|
138 | # SystemExit: (2, 'Mode = exit') | |
139 | File ... line 11, in sysexit |
|
139 | # | |
140 | raise SystemExit(stat, 'Mode = %s' % mode) |
|
140 | # In [20]: %tb | |
141 | SystemExit: (2, 'Mode = exit') |
|
141 | # Traceback (most recent call last): | |
142 |
|
142 | # File ... in <module> | ||
143 | In [21]: %xmode context |
|
143 | # bar(mode) | |
144 | Exception reporting mode: Context |
|
144 | # File ... line 22, in bar | |
145 |
|
145 | # sysexit(stat, mode) | ||
146 | In [22]: %tb |
|
146 | # File ... line 11, in sysexit | |
147 | --------------------------------------------------------------------------- |
|
147 | # raise SystemExit(stat, 'Mode = %s' % mode) | |
148 | SystemExit Traceback (most recent call last) |
|
148 | # SystemExit: (2, 'Mode = exit') | |
149 | <BLANKLINE> |
|
149 | # | |
150 | ...<module> |
|
150 | # In [21]: %xmode context | |
151 | 29 except IndexError: |
|
151 | # Exception reporting mode: Context | |
152 | 30 mode = 'div' |
|
152 | # | |
153 | ---> 32 bar(mode) |
|
153 | # In [22]: %tb | |
154 | <BLANKLINE> |
|
154 | # --------------------------------------------------------------------------- | |
155 | ...bar(mode) |
|
155 | # SystemExit Traceback (most recent call last) | |
156 | 20 except: |
|
156 | # <BLANKLINE> | |
157 | 21 stat = 1 |
|
157 | # ...<module> | |
158 | ---> 22 sysexit(stat, mode) |
|
158 | # 29 except IndexError: | |
159 | 23 else: |
|
159 | # 30 mode = 'div' | |
160 | 24 raise ValueError('Unknown mode') |
|
160 | # ---> 32 bar(mode) | |
161 | <BLANKLINE> |
|
161 | # <BLANKLINE> | |
162 | ...sysexit(stat, mode) |
|
162 | # ...bar(mode) | |
163 | 10 def sysexit(stat, mode): |
|
163 | # 20 except: | |
164 | ---> 11 raise SystemExit(stat, 'Mode = %s' % mode) |
|
164 | # 21 stat = 1 | |
165 | <BLANKLINE> |
|
165 | # ---> 22 sysexit(stat, mode) | |
166 | SystemExit: (2, 'Mode = exit') |
|
166 | # 23 else: | |
167 |
|
167 | # 24 raise ValueError('Unknown mode') | ||
168 | In [23]: %xmode verbose |
|
168 | # <BLANKLINE> | |
169 | Exception reporting mode: Verbose |
|
169 | # ...sysexit(stat, mode) | |
170 |
|
170 | # 10 def sysexit(stat, mode): | ||
171 | In [24]: %tb |
|
171 | # ---> 11 raise SystemExit(stat, 'Mode = %s' % mode) | |
172 | --------------------------------------------------------------------------- |
|
172 | # <BLANKLINE> | |
173 | SystemExit Traceback (most recent call last) |
|
173 | # SystemExit: (2, 'Mode = exit') | |
174 | <BLANKLINE> |
|
174 | # | |
175 | ... in <module> |
|
175 | # In [23]: %xmode verbose | |
176 | 29 except IndexError: |
|
176 | # Exception reporting mode: Verbose | |
177 | 30 mode = 'div' |
|
177 | # | |
178 | ---> 32 bar(mode) |
|
178 | # In [24]: %tb | |
179 | mode = 'exit' |
|
179 | # --------------------------------------------------------------------------- | |
180 | <BLANKLINE> |
|
180 | # SystemExit Traceback (most recent call last) | |
181 | ... in bar(mode='exit') |
|
181 | # <BLANKLINE> | |
182 | 20 except: |
|
182 | # ... in <module> | |
183 | 21 stat = 1 |
|
183 | # 29 except IndexError: | |
184 | ---> 22 sysexit(stat, mode) |
|
184 | # 30 mode = 'div' | |
185 | mode = 'exit' |
|
185 | # ---> 32 bar(mode) | |
186 | stat = 2 |
|
186 | # mode = 'exit' | |
187 | 23 else: |
|
187 | # <BLANKLINE> | |
188 | 24 raise ValueError('Unknown mode') |
|
188 | # ... in bar(mode='exit') | |
189 | <BLANKLINE> |
|
189 | # 20 except: | |
190 | ... in sysexit(stat=2, mode='exit') |
|
190 | # 21 stat = 1 | |
191 |
|
|
191 | # ---> 22 sysexit(stat, mode) | |
192 | ---> 11 raise SystemExit(stat, 'Mode = %s' % mode) |
|
192 | # mode = 'exit' | |
193 | stat = 2 |
|
193 | # stat = 2 | |
194 | mode = 'exit' |
|
194 | # 23 else: | |
195 | <BLANKLINE> |
|
195 | # 24 raise ValueError('Unknown mode') | |
196 | SystemExit: (2, 'Mode = exit') |
|
196 | # <BLANKLINE> | |
197 | """ |
|
197 | # ... in sysexit(stat=2, mode='exit') | |
|
198 | # 10 def sysexit(stat, mode): | |||
|
199 | # ---> 11 raise SystemExit(stat, 'Mode = %s' % mode) | |||
|
200 | # stat = 2 | |||
|
201 | # mode = 'exit' | |||
|
202 | # <BLANKLINE> | |||
|
203 | # SystemExit: (2, 'Mode = exit') | |||
|
204 | # """ | |||
198 |
|
205 | |||
199 |
|
206 | |||
200 | def test_run_cell(): |
|
207 | def test_run_cell(): |
@@ -35,6 +35,8 b' from IPython.utils.tempdir import (TemporaryDirectory,' | |||||
35 | from IPython.utils.process import find_cmd |
|
35 | from IPython.utils.process import find_cmd | |
36 | from .test_debugger import PdbTestInput |
|
36 | from .test_debugger import PdbTestInput | |
37 |
|
37 | |||
|
38 | import pytest | |||
|
39 | ||||
38 |
|
40 | |||
39 | @magic.magics_class |
|
41 | @magic.magics_class | |
40 | class DummyMagics(magic.Magics): pass |
|
42 | class DummyMagics(magic.Magics): pass | |
@@ -954,7 +956,6 b' async def test_script_bg_out():' | |||||
954 | nt.assert_equal((await ip.user_ns["output"].read()), b"hi\n") |
|
956 | nt.assert_equal((await ip.user_ns["output"].read()), b"hi\n") | |
955 | ip.user_ns['output'].close() |
|
957 | ip.user_ns['output'].close() | |
956 |
|
958 | |||
957 |
|
||||
958 | @dec.skip_win32 |
|
959 | @dec.skip_win32 | |
959 | async def test_script_bg_err(): |
|
960 | async def test_script_bg_err(): | |
960 | ip = get_ipython() |
|
961 | ip = get_ipython() |
@@ -8,6 +8,8 b' from os import walk, sep, fsdecode' | |||||
8 |
|
8 | |||
9 | from IPython.core.display import DisplayObject, TextDisplayObject |
|
9 | from IPython.core.display import DisplayObject, TextDisplayObject | |
10 |
|
10 | |||
|
11 | from typing import Tuple | |||
|
12 | ||||
11 | __all__ = ['Audio', 'IFrame', 'YouTubeVideo', 'VimeoVideo', 'ScribdDocument', |
|
13 | __all__ = ['Audio', 'IFrame', 'YouTubeVideo', 'VimeoVideo', 'ScribdDocument', | |
12 | 'FileLink', 'FileLinks', 'Code'] |
|
14 | 'FileLink', 'FileLinks', 'Code'] | |
13 |
|
15 | |||
@@ -70,13 +72,13 b' class Audio(DisplayObject):' | |||||
70 | ... framerate = 44100 |
|
72 | ... framerate = 44100 | |
71 | ... t = np.linspace(0,5,framerate*5) |
|
73 | ... t = np.linspace(0,5,framerate*5) | |
72 | ... data = np.sin(2*np.pi*220*t) + np.sin(2*np.pi*224*t) |
|
74 | ... data = np.sin(2*np.pi*220*t) + np.sin(2*np.pi*224*t) | |
73 | ... Audio(data,rate=framerate) |
|
75 | ... Audio(data, rate=framerate) | |
74 |
|
76 | |||
75 | Can also do stereo or more channels |
|
77 | Can also do stereo or more channels | |
76 |
|
78 | |||
77 | >>> dataleft = np.sin(2*np.pi*220*t) |
|
79 | >>> dataleft = np.sin(2*np.pi*220*t) | |
78 | ... dataright = np.sin(2*np.pi*224*t) |
|
80 | ... dataright = np.sin(2*np.pi*224*t) | |
79 | ... Audio([dataleft, dataright],rate=framerate) |
|
81 | ... Audio([dataleft, dataright], rate=framerate) | |
80 |
|
82 | |||
81 | From URL: |
|
83 | From URL: | |
82 |
|
84 | |||
@@ -159,7 +161,7 b' class Audio(DisplayObject):' | |||||
159 | return val |
|
161 | return val | |
160 |
|
162 | |||
161 | @staticmethod |
|
163 | @staticmethod | |
162 | def _validate_and_normalize_with_numpy(data, normalize): |
|
164 | def _validate_and_normalize_with_numpy(data, normalize) -> Tuple[bytes, int]: | |
163 | import numpy as np |
|
165 | import numpy as np | |
164 |
|
166 | |||
165 | data = np.array(data, dtype=float) |
|
167 | data = np.array(data, dtype=float) | |
@@ -178,8 +180,7 b' class Audio(DisplayObject):' | |||||
178 | max_abs_value = np.max(np.abs(data)) |
|
180 | max_abs_value = np.max(np.abs(data)) | |
179 | normalization_factor = Audio._get_normalization_factor(max_abs_value, normalize) |
|
181 | normalization_factor = Audio._get_normalization_factor(max_abs_value, normalize) | |
180 | scaled = data / normalization_factor * 32767 |
|
182 | scaled = data / normalization_factor * 32767 | |
181 |
return scaled.astype( |
|
183 | return scaled.astype("<h").tobytes(), nchan | |
182 |
|
||||
183 |
|
184 | |||
184 | @staticmethod |
|
185 | @staticmethod | |
185 | def _validate_and_normalize_without_numpy(data, normalize): |
|
186 | def _validate_and_normalize_without_numpy(data, normalize): |
@@ -1,5 +1,4 b'' | |||||
1 | import asyncio |
|
1 | import asyncio | |
2 | import signal |
|
|||
3 | import sys |
|
2 | import sys | |
4 | import threading |
|
3 | import threading | |
5 |
|
4 | |||
@@ -7,13 +6,8 b' from IPython.core.debugger import Pdb' | |||||
7 |
|
6 | |||
8 | from IPython.core.completer import IPCompleter |
|
7 | from IPython.core.completer import IPCompleter | |
9 | from .ptutils import IPythonPTCompleter |
|
8 | from .ptutils import IPythonPTCompleter | |
10 |
from .shortcuts import create_ipython_shortcuts |
|
9 | from .shortcuts import create_ipython_shortcuts | |
11 |
|
10 | |||
12 | from prompt_toolkit.enums import DEFAULT_BUFFER |
|
|||
13 | from prompt_toolkit.filters import (Condition, has_focus, has_selection, |
|
|||
14 | vi_insert_mode, emacs_insert_mode) |
|
|||
15 | from prompt_toolkit.key_binding import KeyBindings |
|
|||
16 | from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline |
|
|||
17 | from pygments.token import Token |
|
11 | from pygments.token import Token | |
18 | from prompt_toolkit.shortcuts.prompt import PromptSession |
|
12 | from prompt_toolkit.shortcuts.prompt import PromptSession | |
19 | from prompt_toolkit.enums import EditingMode |
|
13 | from prompt_toolkit.enums import EditingMode | |
@@ -34,22 +28,20 b' class TerminalPdb(Pdb):' | |||||
34 | def pt_init(self, pt_session_options=None): |
|
28 | def pt_init(self, pt_session_options=None): | |
35 | """Initialize the prompt session and the prompt loop |
|
29 | """Initialize the prompt session and the prompt loop | |
36 | and store them in self.pt_app and self.pt_loop. |
|
30 | and store them in self.pt_app and self.pt_loop. | |
37 |
|
31 | |||
38 | Additional keyword arguments for the PromptSession class |
|
32 | Additional keyword arguments for the PromptSession class | |
39 | can be specified in pt_session_options. |
|
33 | can be specified in pt_session_options. | |
40 | """ |
|
34 | """ | |
41 | if pt_session_options is None: |
|
35 | if pt_session_options is None: | |
42 | pt_session_options = {} |
|
36 | pt_session_options = {} | |
43 |
|
37 | |||
44 | def get_prompt_tokens(): |
|
38 | def get_prompt_tokens(): | |
45 | return [(Token.Prompt, self.prompt)] |
|
39 | return [(Token.Prompt, self.prompt)] | |
46 |
|
40 | |||
47 | if self._ptcomp is None: |
|
41 | if self._ptcomp is None: | |
48 |
compl = IPCompleter( |
|
42 | compl = IPCompleter( | |
49 | namespace={}, |
|
43 | shell=self.shell, namespace={}, global_namespace={}, parent=self.shell | |
50 | global_namespace={}, |
|
44 | ) | |
51 | parent=self.shell, |
|
|||
52 | ) |
|
|||
53 | # add a completer for all the do_ methods |
|
45 | # add a completer for all the do_ methods | |
54 | methods_names = [m[3:] for m in dir(self) if m.startswith("do_")] |
|
46 | methods_names = [m[3:] for m in dir(self) if m.startswith("do_")] | |
55 |
|
47 |
@@ -41,7 +41,7 b" CoreFoundation = ctypes.cdll.LoadLibrary(ctypes.util.find_library('CoreFoundatio" | |||||
41 |
|
41 | |||
42 | CFFileDescriptorCreate = CoreFoundation.CFFileDescriptorCreate |
|
42 | CFFileDescriptorCreate = CoreFoundation.CFFileDescriptorCreate | |
43 | CFFileDescriptorCreate.restype = void_p |
|
43 | CFFileDescriptorCreate.restype = void_p | |
44 | CFFileDescriptorCreate.argtypes = [void_p, ctypes.c_int, ctypes.c_bool, void_p] |
|
44 | CFFileDescriptorCreate.argtypes = [void_p, ctypes.c_int, ctypes.c_bool, void_p, void_p] | |
45 |
|
45 | |||
46 | CFFileDescriptorGetNativeDescriptor = CoreFoundation.CFFileDescriptorGetNativeDescriptor |
|
46 | CFFileDescriptorGetNativeDescriptor = CoreFoundation.CFFileDescriptorGetNativeDescriptor | |
47 | CFFileDescriptorGetNativeDescriptor.restype = ctypes.c_int |
|
47 | CFFileDescriptorGetNativeDescriptor.restype = ctypes.c_int | |
@@ -77,24 +77,42 b" kCFRunLoopCommonModes = void_p.in_dll(CoreFoundation, 'kCFRunLoopCommonModes')" | |||||
77 |
|
77 | |||
78 | def _NSApp(): |
|
78 | def _NSApp(): | |
79 | """Return the global NSApplication instance (NSApp)""" |
|
79 | """Return the global NSApplication instance (NSApp)""" | |
|
80 | objc.objc_msgSend.argtypes = [void_p, void_p] | |||
80 | return msg(C('NSApplication'), n('sharedApplication')) |
|
81 | return msg(C('NSApplication'), n('sharedApplication')) | |
81 |
|
82 | |||
82 |
|
83 | |||
83 | def _wake(NSApp): |
|
84 | def _wake(NSApp): | |
84 | """Wake the Application""" |
|
85 | """Wake the Application""" | |
85 | event = msg(C('NSEvent'), |
|
86 | objc.objc_msgSend.argtypes = [ | |
86 | n('otherEventWithType:location:modifierFlags:' |
|
87 | void_p, | |
87 | 'timestamp:windowNumber:context:subtype:data1:data2:'), |
|
88 | void_p, | |
88 | 15, # Type |
|
89 | void_p, | |
89 | 0, # location |
|
90 | void_p, | |
90 | 0, # flags |
|
91 | void_p, | |
91 | 0, # timestamp |
|
92 | void_p, | |
92 | 0, # window |
|
93 | void_p, | |
93 | None, # context |
|
94 | void_p, | |
94 | 0, # subtype |
|
95 | void_p, | |
95 | 0, # data1 |
|
96 | void_p, | |
96 | 0, # data2 |
|
97 | void_p, | |
|
98 | ] | |||
|
99 | event = msg( | |||
|
100 | C("NSEvent"), | |||
|
101 | n( | |||
|
102 | "otherEventWithType:location:modifierFlags:" | |||
|
103 | "timestamp:windowNumber:context:subtype:data1:data2:" | |||
|
104 | ), | |||
|
105 | 15, # Type | |||
|
106 | 0, # location | |||
|
107 | 0, # flags | |||
|
108 | 0, # timestamp | |||
|
109 | 0, # window | |||
|
110 | None, # context | |||
|
111 | 0, # subtype | |||
|
112 | 0, # data1 | |||
|
113 | 0, # data2 | |||
97 | ) |
|
114 | ) | |
|
115 | objc.objc_msgSend.argtypes = [void_p, void_p, void_p, void_p] | |||
98 | msg(NSApp, n('postEvent:atStart:'), void_p(event), True) |
|
116 | msg(NSApp, n('postEvent:atStart:'), void_p(event), True) | |
99 |
|
117 | |||
100 |
|
118 | |||
@@ -106,6 +124,7 b' def _input_callback(fdref, flags, info):' | |||||
106 | CFFileDescriptorInvalidate(fdref) |
|
124 | CFFileDescriptorInvalidate(fdref) | |
107 | CFRelease(fdref) |
|
125 | CFRelease(fdref) | |
108 | NSApp = _NSApp() |
|
126 | NSApp = _NSApp() | |
|
127 | objc.objc_msgSend.argtypes = [void_p, void_p, void_p] | |||
109 | msg(NSApp, n('stop:'), NSApp) |
|
128 | msg(NSApp, n('stop:'), NSApp) | |
110 | _wake(NSApp) |
|
129 | _wake(NSApp) | |
111 |
|
130 | |||
@@ -128,6 +147,7 b' def inputhook(context):' | |||||
128 | """Inputhook for Cocoa (NSApp)""" |
|
147 | """Inputhook for Cocoa (NSApp)""" | |
129 | NSApp = _NSApp() |
|
148 | NSApp = _NSApp() | |
130 | _stop_on_read(context.fileno()) |
|
149 | _stop_on_read(context.fileno()) | |
|
150 | objc.objc_msgSend.argtypes = [void_p, void_p] | |||
131 | msg(NSApp, n('run')) |
|
151 | msg(NSApp, n('run')) | |
132 | if not _triggered.is_set(): |
|
152 | if not _triggered.is_set(): | |
133 | # app closed without firing callback, |
|
153 | # app closed without firing callback, |
@@ -1,6 +1,7 b'' | |||||
1 | import sys |
|
1 | import sys | |
2 | import os |
|
2 | import os | |
3 | from IPython.external.qt_for_kernel import QtCore, QtGui |
|
3 | from IPython.external.qt_for_kernel import QtCore, QtGui | |
|
4 | from IPython import get_ipython | |||
4 |
|
5 | |||
5 | # If we create a QApplication, keep a reference to it so that it doesn't get |
|
6 | # If we create a QApplication, keep a reference to it so that it doesn't get | |
6 | # garbage collected. |
|
7 | # garbage collected. | |
@@ -8,6 +9,12 b' _appref = None' | |||||
8 | _already_warned = False |
|
9 | _already_warned = False | |
9 |
|
10 | |||
10 |
|
11 | |||
|
12 | def _reclaim_excepthook(): | |||
|
13 | shell = get_ipython() | |||
|
14 | if shell is not None: | |||
|
15 | sys.excepthook = shell.excepthook | |||
|
16 | ||||
|
17 | ||||
11 | def inputhook(context): |
|
18 | def inputhook(context): | |
12 | global _appref |
|
19 | global _appref | |
13 | app = QtCore.QCoreApplication.instance() |
|
20 | app = QtCore.QCoreApplication.instance() | |
@@ -27,6 +34,13 b' def inputhook(context):' | |||||
27 | return |
|
34 | return | |
28 | QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling) |
|
35 | QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling) | |
29 | _appref = app = QtGui.QApplication([" "]) |
|
36 | _appref = app = QtGui.QApplication([" "]) | |
|
37 | ||||
|
38 | # "reclaim" IPython sys.excepthook after event loop starts | |||
|
39 | # without this, it defaults back to BaseIPythonApplication.excepthook | |||
|
40 | # and exceptions in the Qt event loop are rendered without traceback | |||
|
41 | # formatting and look like "bug in IPython". | |||
|
42 | QtCore.QTimer.singleShot(0, _reclaim_excepthook) | |||
|
43 | ||||
30 | event_loop = QtCore.QEventLoop(app) |
|
44 | event_loop = QtCore.QEventLoop(app) | |
31 |
|
45 | |||
32 | if sys.platform == 'win32': |
|
46 | if sys.platform == 'win32': |
@@ -9,6 +9,7 b' Module to define and register Terminal IPython shortcuts with' | |||||
9 | import warnings |
|
9 | import warnings | |
10 | import signal |
|
10 | import signal | |
11 | import sys |
|
11 | import sys | |
|
12 | import re | |||
12 | from typing import Callable |
|
13 | from typing import Callable | |
13 |
|
14 | |||
14 |
|
15 |
@@ -153,6 +153,14 b' Here is a full example of a magic package. You can distribute magics using' | |||||
153 | setuptools, distutils, or any other distribution tools like `flit |
|
153 | setuptools, distutils, or any other distribution tools like `flit | |
154 | <http://flit.readthedocs.io>`_ for pure Python packages. |
|
154 | <http://flit.readthedocs.io>`_ for pure Python packages. | |
155 |
|
155 | |||
|
156 | When distributing magics as part of a package, recommended best practice is to | |||
|
157 | execute the registration inside the `load_ipython_extension` as demonstrated in | |||
|
158 | the example below, instead of directly in the module (as in the initial example | |||
|
159 | with the ``@register_*`` decorators). This means a user will need to explicitly | |||
|
160 | choose to load your magic with ``%load_ext``. instead implicitly getting it when | |||
|
161 | importing the module. This is particularly relevant if loading your magic has | |||
|
162 | side effects, if it is slow to load, or if it might override another magic with | |||
|
163 | the same name. | |||
156 |
|
164 | |||
157 | .. sourcecode:: bash |
|
165 | .. sourcecode:: bash | |
158 |
|
166 |
@@ -119,11 +119,6 b' which adds a directory called ``profile_<name>`` to your IPython directory. Then' | |||||
119 | you can load this profile by adding ``--profile=<name>`` to your command line |
|
119 | you can load this profile by adding ``--profile=<name>`` to your command line | |
120 | options. Profiles are supported by all IPython applications. |
|
120 | options. Profiles are supported by all IPython applications. | |
121 |
|
121 | |||
122 | IPython ships with some sample profiles in :file:`IPython/config/profile`. If |
|
|||
123 | you create profiles with the name of one of our shipped profiles, these config |
|
|||
124 | files will be copied over instead of starting with the automatically generated |
|
|||
125 | config files. |
|
|||
126 |
|
||||
127 | IPython extends the config loader for Python files so that you can inherit |
|
122 | IPython extends the config loader for Python files so that you can inherit | |
128 | config from another profile. To do this, use a line like this in your Python |
|
123 | config from another profile. To do this, use a line like this in your Python | |
129 | config file: |
|
124 | config file: |
@@ -9,15 +9,15 b' IPython Documentation' | |||||
9 | :Release: |release| |
|
9 | :Release: |release| | |
10 | :Date: |today| |
|
10 | :Date: |today| | |
11 |
|
11 | |||
12 | Welcome to the official IPython documentation |
|
12 | Welcome to the official IPython documentation. | |
13 |
|
13 | |||
14 | IPython provides a rich toolkit to help you make the most of using Python |
|
14 | IPython provides a rich toolkit to help you make the most of using Python | |
15 | interactively. Its main components are: |
|
15 | interactively. Its main components are: | |
16 |
|
16 | |||
17 | * A powerful interactive Python shell |
|
17 | * A powerful interactive Python shell. | |
18 |
|
18 | |||
19 |
|
19 | |||
20 | .. image:: /_images/ipython-6-screenshot.png |
|
20 | .. image:: ./_images/ipython-6-screenshot.png | |
21 | :alt: Screenshot of IPython 6.0 |
|
21 | :alt: Screenshot of IPython 6.0 | |
22 | :align: center |
|
22 | :align: center | |
23 |
|
23 | |||
@@ -59,7 +59,7 b' The Command line interface inherits the above functionality and adds' | |||||
59 |
|
59 | |||
60 | * real multi-line editing thanks to `prompt_toolkit <http://python-prompt-toolkit.readthedocs.io/en/stable/>`_. |
|
60 | * real multi-line editing thanks to `prompt_toolkit <http://python-prompt-toolkit.readthedocs.io/en/stable/>`_. | |
61 |
|
61 | |||
62 | * syntax highlighting as you type |
|
62 | * syntax highlighting as you type. | |
63 |
|
63 | |||
64 | * integration with command line editor for a better workflow. |
|
64 | * integration with command line editor for a better workflow. | |
65 |
|
65 | |||
@@ -84,8 +84,6 b" The latest development version is always available from IPython's `GitHub" | |||||
84 | repository <http://github.com/ipython/ipython>`_. |
|
84 | repository <http://github.com/ipython/ipython>`_. | |
85 |
|
85 | |||
86 |
|
86 | |||
87 |
|
||||
88 |
|
||||
89 | .. toctree:: |
|
87 | .. toctree:: | |
90 | :maxdepth: 1 |
|
88 | :maxdepth: 1 | |
91 | :hidden: |
|
89 | :hidden: |
@@ -3,20 +3,20 b' Python vs IPython' | |||||
3 | ================= |
|
3 | ================= | |
4 |
|
4 | |||
5 | This document is meant to highlight the main differences between the Python |
|
5 | This document is meant to highlight the main differences between the Python | |
6 | language and what are the specific construct you can do only in IPython. |
|
6 | language and what are the specific constructs you can do only in IPython. | |
7 |
|
7 | |||
8 | Unless expressed otherwise all of the construct you will see here will raise a |
|
8 | Unless expressed otherwise all of the constructs you will see here will raise a | |
9 | ``SyntaxError`` if run in a pure Python shell, or if executing in a Python |
|
9 | ``SyntaxError`` if run in a pure Python shell, or if executing in a Python | |
10 | script. |
|
10 | script. | |
11 |
|
11 | |||
12 |
Each of these features |
|
12 | Each of these features is described more in detail in the further parts of the documentation. | |
13 |
|
13 | |||
14 |
|
14 | |||
15 | Quick overview: |
|
15 | Quick overview: | |
16 | =============== |
|
16 | =============== | |
17 |
|
17 | |||
18 |
|
18 | |||
19 | All the following construct are valid IPython syntax: |
|
19 | All the following constructs are valid IPython syntax: | |
20 |
|
20 | |||
21 | .. code-block:: ipython |
|
21 | .. code-block:: ipython | |
22 |
|
22 | |||
@@ -58,8 +58,8 b' All the following construct are valid IPython syntax:' | |||||
58 | ...: print $months[0]; |
|
58 | ...: print $months[0]; | |
59 |
|
59 | |||
60 |
|
60 | |||
61 | Each of these construct is compiled by IPython into valid python code and will |
|
61 | Each of these constructs is compiled by IPython into valid python code and will | |
62 | do most of the time what you expect it will do. Let see each of these example |
|
62 | do most of the time what you expect it will do. Let's see each of these examples | |
63 | in more detail. |
|
63 | in more detail. | |
64 |
|
64 | |||
65 |
|
65 | |||
@@ -89,7 +89,7 b' shortcut to get help. A question mark alone will bring up the IPython help:' | |||||
89 | ------------- |
|
89 | ------------- | |
90 | ... |
|
90 | ... | |
91 |
|
91 | |||
92 |
A single question mark before |
|
92 | A single question mark before or after an object available in the current | |
93 | namespace will show help relative to this object: |
|
93 | namespace will show help relative to this object: | |
94 |
|
94 | |||
95 | .. code-block:: ipython |
|
95 | .. code-block:: ipython | |
@@ -127,7 +127,7 b' and if possible display the python source code of this object.' | |||||
127 |
|
127 | |||
128 |
|
128 | |||
129 | If you are looking for an object, the use of wildcards ``*`` in conjunction |
|
129 | If you are looking for an object, the use of wildcards ``*`` in conjunction | |
130 | with question mark will allow you to search current namespace for object with |
|
130 | with a question mark will allow you to search the current namespace for objects with | |
131 | matching names: |
|
131 | matching names: | |
132 |
|
132 | |||
133 | .. code-block:: ipython |
|
133 | .. code-block:: ipython | |
@@ -142,10 +142,10 b' Shell Assignment' | |||||
142 | ================ |
|
142 | ================ | |
143 |
|
143 | |||
144 |
|
144 | |||
145 |
When doing interactive computing it is common |
|
145 | When doing interactive computing it is a common need to access the underlying shell. | |
146 | This is doable through the use of the exclamation mark ``!`` (or bang). |
|
146 | This is doable through the use of the exclamation mark ``!`` (or bang). | |
147 |
|
147 | |||
148 | This allow to execute simple command when present in beginning of line: |
|
148 | This allows to execute simple commands when present in beginning of the line: | |
149 |
|
149 | |||
150 | .. code-block:: ipython |
|
150 | .. code-block:: ipython | |
151 |
|
151 | |||
@@ -167,7 +167,7 b' Or edit file:' | |||||
167 |
|
167 | |||
168 | The line after the bang can call any program installed in the underlying |
|
168 | The line after the bang can call any program installed in the underlying | |
169 | shell, and support variable expansion in the form of ``$variable`` or ``{variable}``. |
|
169 | shell, and support variable expansion in the form of ``$variable`` or ``{variable}``. | |
170 | The later form of expansion supports arbitrary python expression: |
|
170 | The later form of expansion supports arbitrary python expressions: | |
171 |
|
171 | |||
172 | .. code-block:: ipython |
|
172 | .. code-block:: ipython | |
173 |
|
173 | |||
@@ -176,19 +176,19 b' The later form of expansion supports arbitrary python expression:' | |||||
176 | In[2]: !mv $file {file.upper()} |
|
176 | In[2]: !mv $file {file.upper()} | |
177 |
|
177 | |||
178 |
|
178 | |||
179 |
The bang can also be present |
|
179 | The bang (``!``) can also be present on the right hand side of an assignment, just | |
180 |
after the equal sign, or separated from it by a white space. In |
|
180 | after the equal sign, or separated from it by a white space. In this case the | |
181 |
standard output of the command after the bang |
|
181 | standard output of the command after the bang will be split out into lines | |
182 | in a list-like object and assign to the left hand side. |
|
182 | in a list-like object and assigned to the left hand side. | |
183 |
|
183 | |||
184 | This allow you for example to put the list of files of the current working directory in a variable: |
|
184 | This allows you, for example, to put the list of files of the current working directory in a variable: | |
185 |
|
185 | |||
186 | .. code-block:: ipython |
|
186 | .. code-block:: ipython | |
187 |
|
187 | |||
188 | In[1]: my_files = !ls |
|
188 | In[1]: my_files = !ls | |
189 |
|
189 | |||
190 |
|
190 | |||
191 | You can combine the different possibilities in for loops, condition, functions...: |
|
191 | You can combine the different possibilities in for loops, conditions, functions...: | |
192 |
|
192 | |||
193 | .. code-block:: ipython |
|
193 | .. code-block:: ipython | |
194 |
|
194 | |||
@@ -202,19 +202,19 b' You can combine the different possibilities in for loops, condition, functions..' | |||||
202 | Magics |
|
202 | Magics | |
203 | ------ |
|
203 | ------ | |
204 |
|
204 | |||
205 |
Magic |
|
205 | Magic functions (magics) are often present in the form of shell-like syntax, but they are | |
206 |
|
|
206 | python functions under the hood. The syntax and assignment possibilities are | |
207 | similar to the one with the bang (``!``) syntax, but with more flexibility and |
|
207 | similar to the one with the bang (``!``) syntax, but with more flexibility and | |
208 | power. Magic function start with a percent sign (``%``) or double percent (``%%``). |
|
208 | power. Magic functions start with a percent sign (``%``) or double percent signs (``%%``). | |
209 |
|
209 | |||
210 |
A magic call with a si |
|
210 | A magic call with a single percent sign will act only on one line: | |
211 |
|
211 | |||
212 | .. code-block:: ipython |
|
212 | .. code-block:: ipython | |
213 |
|
213 | |||
214 | In[1]: %xmode |
|
214 | In[1]: %xmode | |
215 | Exception reporting mode: Verbose |
|
215 | Exception reporting mode: Verbose | |
216 |
|
216 | |||
217 |
|
|
217 | Magics support assignment: | |
218 |
|
218 | |||
219 | .. code-block:: ipython |
|
219 | .. code-block:: ipython | |
220 |
|
220 | |||
@@ -224,7 +224,7 b' And support assignment:' | |||||
224 | In [2]: results |
|
224 | In [2]: results | |
225 | Out[2]: <TimeitResult : 1 loops, best of 1: 21.1 µs per loop> |
|
225 | Out[2]: <TimeitResult : 1 loops, best of 1: 21.1 µs per loop> | |
226 |
|
226 | |||
227 |
Magic with |
|
227 | Magics with double percent signs (``%%``) can spread over multiple lines, but they do not support assignments: | |
228 |
|
228 | |||
229 | .. code-block:: ipython |
|
229 | .. code-block:: ipython | |
230 |
|
230 |
@@ -22,6 +22,47 b' Need to be updated:' | |||||
22 |
|
22 | |||
23 | pr/* |
|
23 | pr/* | |
24 |
|
24 | |||
|
25 | IPython 8.0 is bringing a number of new features and improvements to both the | |||
|
26 | user of the terminal and of the kernel via Jupyter. The removal of compatibility | |||
|
27 | with older version of Python is also the opportunity to do a couple of | |||
|
28 | performance improvement in particular with respect to startup time. | |||
|
29 | ||||
|
30 | The main change in IPython 8.0 is the integration of the ``stack_data`` package; | |||
|
31 | which provide smarter information in traceback; in particular it will highlight | |||
|
32 | the AST node where an error occurs which can help to quickly narrow down errors. | |||
|
33 | ||||
|
34 | For example in the following snippet:: | |||
|
35 | ||||
|
36 | def foo(i): | |||
|
37 | x = [[[0]]] | |||
|
38 | return x[0][i][0] | |||
|
39 | ||||
|
40 | ||||
|
41 | def bar(): | |||
|
42 | return foo(0) + foo( | |||
|
43 | 1 | |||
|
44 | ) + foo(2) | |||
|
45 | ||||
|
46 | ||||
|
47 | Calling ``bar()`` would raise an ``IndexError`` on the return line of ``foo``, | |||
|
48 | IPython 8.0 is capable of telling you, where the index error occurs:: | |||
|
49 | ||||
|
50 | return x[0][i][0] | |||
|
51 | ^ | |||
|
52 | ||||
|
53 | To prepare for Python 3.10 we have also started working on removing reliance and | |||
|
54 | any dependency that is not Python 3.10 compatible; that include migrating our | |||
|
55 | test suite to Pytest, and starting to remove nose. | |||
|
56 | ||||
|
57 | We are also removing support for Python 3.6 allowing internal code to use more | |||
|
58 | efficient ``pathlib``, and make better use of type annotations. | |||
|
59 | ||||
|
60 | The completer has also seen significant updates and make use of newer Jedi API | |||
|
61 | offering faster and more reliable tab completion. | |||
|
62 | ||||
|
63 | For the terminal users this also enable the auto-suggestion feature, described | |||
|
64 | below, which show "ghost text" ahead of your cursor you can accept without | |||
|
65 | having to press the tab key or ask the completer to suggest completions. | |||
25 |
|
66 | |||
26 |
|
67 | |||
27 | Autosuggestion is a very useful feature available in `fish <https://fishshell.com/>`__, `zsh <https://en.wikipedia.org/wiki/Z_shell>`__, and `prompt-toolkit <https://python-prompt-toolkit.readthedocs.io/en/master/pages/asking_for_input.html#auto-suggestion>`__. |
|
68 | Autosuggestion is a very useful feature available in `fish <https://fishshell.com/>`__, `zsh <https://en.wikipedia.org/wiki/Z_shell>`__, and `prompt-toolkit <https://python-prompt-toolkit.readthedocs.io/en/master/pages/asking_for_input.html#auto-suggestion>`__. | |
@@ -93,6 +134,25 b' Currently, autosuggestions are only shown in the emacs or vi insert editing mode' | |||||
93 | - The ctrl e, ctrl f, and alt f shortcuts work by default in emacs mode. |
|
134 | - The ctrl e, ctrl f, and alt f shortcuts work by default in emacs mode. | |
94 | - To use these shortcuts in vi insert mode, you will have to create `custom keybindings in your config.py <https://github.com/mskar/setup/commit/2892fcee46f9f80ef7788f0749edc99daccc52f4/>`__. |
|
135 | - To use these shortcuts in vi insert mode, you will have to create `custom keybindings in your config.py <https://github.com/mskar/setup/commit/2892fcee46f9f80ef7788f0749edc99daccc52f4/>`__. | |
95 |
|
136 | |||
|
137 | ||||
|
138 | Show pinfo information in ipdb using "?" and "??" | |||
|
139 | ------------------------------------------------- | |||
|
140 | ||||
|
141 | In IPDB, it is now possible to show the information about an object using "?" | |||
|
142 | and "??", in much the same way it can be done when using the IPython prompt:: | |||
|
143 | ||||
|
144 | ipdb> partial? | |||
|
145 | Init signature: partial(self, /, *args, **kwargs) | |||
|
146 | Docstring: | |||
|
147 | partial(func, *args, **keywords) - new function with partial application | |||
|
148 | of the given arguments and keywords. | |||
|
149 | File: ~/.pyenv/versions/3.8.6/lib/python3.8/functools.py | |||
|
150 | Type: type | |||
|
151 | Subclasses: | |||
|
152 | ||||
|
153 | Previously, "pinfo" or "pinfo2" command had to be used for this purpose. | |||
|
154 | ||||
|
155 | ||||
96 | Autoreload 3 feature |
|
156 | Autoreload 3 feature | |
97 | ==================== |
|
157 | ==================== | |
98 |
|
158 | |||
@@ -107,6 +167,7 b' Try ``%autoreload 3`` in an IPython session after running ``%load_ext autoreload' | |||||
107 |
|
167 | |||
108 | For more information please see unit test - |
|
168 | For more information please see unit test - | |
109 | extensions/tests/test_autoreload.py : 'test_autoload_newly_added_objects' |
|
169 | extensions/tests/test_autoreload.py : 'test_autoload_newly_added_objects' | |
|
170 | ======= | |||
110 |
|
171 | |||
111 | .. DO NOT EDIT THIS LINE BEFORE RELEASE. FEATURE INSERTION POINT. |
|
172 | .. DO NOT EDIT THIS LINE BEFORE RELEASE. FEATURE INSERTION POINT. | |
112 |
|
173 |
@@ -2,6 +2,105 b'' | |||||
2 | 7.x Series |
|
2 | 7.x Series | |
3 | ============ |
|
3 | ============ | |
4 |
|
4 | |||
|
5 | .. _version 7.22: | |||
|
6 | ||||
|
7 | IPython 7.22 | |||
|
8 | ============ | |||
|
9 | ||||
|
10 | Second release of IPython for 2021, mostly containing bug fixes. Here is a quick | |||
|
11 | rundown of the few changes. | |||
|
12 | ||||
|
13 | - Fix some ``sys.excepthook`` shenanigan when embedding with qt, recommended if | |||
|
14 | you – for example – use `napari <https://napari.org>`__. :ghpull:`12842`. | |||
|
15 | - Fix bug when using the new ipdb ``%context`` magic :ghpull:`12844` | |||
|
16 | - Couples of deprecation cleanup :ghpull:`12868` | |||
|
17 | - Update for new dpast.com api if you use the ``%pastbin`` magic. :ghpull:`12712` | |||
|
18 | - Remove support for numpy before 1.16. :ghpull:`12836` | |||
|
19 | ||||
|
20 | ||||
|
21 | Thanks | |||
|
22 | ------ | |||
|
23 | ||||
|
24 | We have a new team member that you should see more often on the IPython | |||
|
25 | repository, Błażej Michalik (@MrMino) have been doing regular contributions to | |||
|
26 | IPython, and spent time replying to many issues and guiding new users to the | |||
|
27 | codebase; they now have triage permissions to the IPython repository and we'll | |||
|
28 | work toward giving them more permission in the future. | |||
|
29 | ||||
|
30 | Many thanks to all the contributors to this release you can find all individual | |||
|
31 | contributions to this milestone `on github <https://github.com/ipython/ipython/milestone/84>`__. | |||
|
32 | ||||
|
33 | Thanks as well to organisations, QuantStack for working on debugger | |||
|
34 | compatibility for Xeus_python, and the `D. E. Shaw group | |||
|
35 | <https://deshaw.com/>`__ for sponsoring work on IPython and related libraries. | |||
|
36 | ||||
|
37 | .. _version 721: | |||
|
38 | ||||
|
39 | IPython 7.21 | |||
|
40 | ============ | |||
|
41 | ||||
|
42 | IPython 7.21 is the first release we have back on schedule of one release every | |||
|
43 | month; it contains a number of minor fixes and improvements, notably, the new | |||
|
44 | context command for ipdb | |||
|
45 | ||||
|
46 | ||||
|
47 | New "context" command in ipdb | |||
|
48 | ----------------------------- | |||
|
49 | ||||
|
50 | It is now possible to change the number of lines shown in the backtrace | |||
|
51 | information in ipdb using "context" command. :ghpull:`12826` | |||
|
52 | ||||
|
53 | (thanks @MrMino, there are other improvement from them on master). | |||
|
54 | ||||
|
55 | Other notable changes in IPython 7.21 | |||
|
56 | ------------------------------------- | |||
|
57 | ||||
|
58 | - Fix some issues on new osx-arm64 :ghpull:`12804`, :ghpull:`12807`. | |||
|
59 | - Compatibility with Xeus-Python for debugger protocol, :ghpull:`12809` | |||
|
60 | - Misc docs fixes for compatibility and uniformity with Numpydoc. | |||
|
61 | :ghpull:`12824` | |||
|
62 | ||||
|
63 | ||||
|
64 | Thanks | |||
|
65 | ------ | |||
|
66 | ||||
|
67 | Many thanks to all the contributors to this release you can find all individual | |||
|
68 | contribution to this milestone `on github <https://github.com/ipython/ipython/milestone/83>`__. | |||
|
69 | ||||
|
70 | ||||
|
71 | .. _version 720: | |||
|
72 | ||||
|
73 | IPython 7.20 | |||
|
74 | ============ | |||
|
75 | ||||
|
76 | IPython 7.20 is the accumulation of 3 month of work on IPython, spacing between | |||
|
77 | IPython release have been increased from the usual once a month for various | |||
|
78 | reason. | |||
|
79 | ||||
|
80 | - Mainly as I'm too busy and the effectively sole maintainer, and | |||
|
81 | - Second because not much changes happened before mid December. | |||
|
82 | ||||
|
83 | The main driver for this release was the new version of Jedi 0.18 breaking API; | |||
|
84 | which was taken care of in the master branch early in 2020 but not in 7.x as I | |||
|
85 | though that by now 8.0 would be out. | |||
|
86 | ||||
|
87 | The inclusion of a resolver in pip did not help and actually made things worse. | |||
|
88 | If usually I would have simply pinned Jedi to ``<0.18``; this is not a solution | |||
|
89 | anymore as now pip is free to install Jedi 0.18, and downgrade IPython. | |||
|
90 | ||||
|
91 | I'll do my best to keep the regular release, but as the 8.0-dev branch and 7.x | |||
|
92 | are starting to diverge this is becoming difficult in particular with my limited | |||
|
93 | time, so if you have any cycles to spare I'll appreciate your help to respond to | |||
|
94 | issues and pushing 8.0 forward. | |||
|
95 | ||||
|
96 | Here are thus some of the changes for IPython 7.20. | |||
|
97 | ||||
|
98 | - Support for PyQt5 >= 5.11 :ghpull:`12715` | |||
|
99 | - ``%reset`` remove imports more agressively :ghpull:`12718` | |||
|
100 | - fix the ``%conda`` magic :ghpull:`12739` | |||
|
101 | - compatibility with Jedi 0.18, and bump minimum Jedi version. :ghpull:`12793` | |||
|
102 | ||||
|
103 | ||||
5 | .. _version 719: |
|
104 | .. _version 719: | |
6 |
|
105 | |||
7 | IPython 7.19 |
|
106 | IPython 7.19 | |
@@ -55,7 +154,7 b' IPython 7.17' | |||||
55 | ============ |
|
154 | ============ | |
56 |
|
155 | |||
57 | IPython 7.17 brings a couple of new improvements to API and a couple of user |
|
156 | IPython 7.17 brings a couple of new improvements to API and a couple of user | |
58 |
facing changes to make the terminal experience more user friendly. |
|
157 | facing changes to make the terminal experience more user friendly. | |
59 |
|
158 | |||
60 | :ghpull:`12407` introduces the ability to pass extra argument to the IPython |
|
159 | :ghpull:`12407` introduces the ability to pass extra argument to the IPython | |
61 | debugger class; this is to help a new project from ``kmaork`` |
|
160 | debugger class; this is to help a new project from ``kmaork`` |
@@ -171,15 +171,23 b' setuptools_extra_args = {}' | |||||
171 | # setuptools requirements |
|
171 | # setuptools requirements | |
172 |
|
172 | |||
173 | extras_require = dict( |
|
173 | extras_require = dict( | |
174 |
parallel |
|
174 | parallel=["ipyparallel"], | |
175 |
qtconsole |
|
175 | qtconsole=["qtconsole"], | |
176 |
doc |
|
176 | doc=["Sphinx>=1.3"], | |
177 | test = ['nose>=0.10.1', 'requests', 'testpath', 'pygments', 'nbformat', 'ipykernel', 'numpy>=1.14'], |
|
177 | test=[ | |
178 | terminal = [], |
|
178 | "nose>=0.10.1", | |
179 | kernel = ['ipykernel'], |
|
179 | "requests", | |
180 | nbformat = ['nbformat'], |
|
180 | "testpath", | |
181 | notebook = ['notebook', 'ipywidgets'], |
|
181 | "pygments", | |
182 | nbconvert = ['nbconvert'], |
|
182 | "nbformat", | |
|
183 | "ipykernel", | |||
|
184 | "numpy>=1.16", | |||
|
185 | ], | |||
|
186 | terminal=[], | |||
|
187 | kernel=["ipykernel"], | |||
|
188 | nbformat=["nbformat"], | |||
|
189 | notebook=["notebook", "ipywidgets"], | |||
|
190 | nbconvert=["nbconvert"], | |||
183 | ) |
|
191 | ) | |
184 |
|
192 | |||
185 | install_requires = [ |
|
193 | install_requires = [ |
General Comments 0
You need to be logged in to leave comments.
Login now