##// END OF EJS Templates
Merge branch 'master' into feature-add-autoreload-option-3
skalaydzhiyski -
r26415:aaf09dd1 merge
parent child Browse files
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-asyncio
40 - pip install codecov check-manifest pytest-cov --upgrade anyio pytest-trio
41
41
42
42
43 script:
43 script:
@@ -112,25 +112,53 b' class CachingCompiler(codeop.Compile):'
112 """
112 """
113 return self.flags
113 return self.flags
114
114
115 def cache(self, code, number=0):
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
@@ -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:: Unstable
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:: Unstable
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:: Unstable
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:: Unstable
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:: Unstable
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 = os.getcwd()
155 rptdir = Path.cwd()
155 if rptdir is None or not os.path.isdir(rptdir):
156 if rptdir is None or not Path.is_dir(rptdir):
156 rptdir = os.getcwd()
157 rptdir = Path.cwd()
157 report_name = os.path.join(rptdir,self.crash_report_fname)
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
@@ -50,6 +50,7 b' from pdb import Pdb as OldPdb'
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:
@@ -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['__main__'] = save_main
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,6 +320,18 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
@@ -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 = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
417 tpl_link = "%s%%s%s" % (Colors.filenameEm, ColorsNormal)
406 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
418 tpl_call = "%s%%s%s%%s%s" % (Colors.vName, Colors.valEm, ColorsNormal)
407 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
419 tpl_line = "%%s%s%%s %s%%s" % (Colors.lineno, ColorsNormal)
408 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
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(u'%s(%s)%s\n' % (link,lineno,call))
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)
@@ -449,14 +460,14 b' class Pdb(OldPdb):'
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 = (start + 1 + i == lineno)
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 or tpl_line
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 ''.join(ret)
470 return "".join(ret)
460
471
461 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
472 def __format_line(self, tpl_line, filename, lineno, line, arrow=False):
462 bp_mark = ""
473 bp_mark = ""
@@ -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(tpl_line_em, filename, lineno, line, arrow = True)
520 line = self.__format_line(
521 tpl_line_em, filename, lineno, line, arrow=True
522 )
511 else:
523 else:
512 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
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 ## modified version of upstream that skips
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
@@ -656,7 +656,6 b' class GeoJSON(JSON):'
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: : list or str
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.
@@ -851,18 +850,26 b' class Image(DisplayObject):'
851
850
852 Examples
851 Examples
853 --------
852 --------
854 # embedded image data, works in qtconsole and notebook
853 embedded image data, works in qtconsole and notebook
855 # when passed positionally, the first arg can be any of raw image data,
854 when passed positionally, the first arg can be any of raw image data,
856 # a URL, or a filename from which to load image data.
855 a URL, or a filename from which to load image data.
857 # The result is always embedding image data for inline images.
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,24 +1043,23 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
1057 mimetype: unicode
1063 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.
@@ -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
@@ -443,6 +443,7 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 compiler_class = Type(CachingCompiler)
446
447
447 sphinxify_docstring = Bool(False, help=
448 sphinxify_docstring = Bool(False, help=
448 """
449 """
@@ -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 = CachingCompiler()
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"]).joinpath(
936 virtual_env = Path(os.environ["VIRTUAL_ENV"], "Lib", "site-packages")
938 "Lib", "site-packages"
939 )
940 else:
937 else:
941 virtual_env = Path(os.environ["VIRTUAL_ENV"]).joinpath(
938 virtual_env_path = Path(
942 "lib", "python{}.{}".format(*sys.version_info[:2]), "site-packages"
939 os.environ["VIRTUAL_ENV"], "lib", "python{}.{}", "site-packages"
943 )
940 )
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()
944
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)
@@ -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:
@@ -2289,8 +2306,9 b' class InteractiveShell(SingletonConfigurable):'
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(func,
2309 self.magics_manager.register_function(
2293 magic_kind=magic_kind, magic_name=magic_name)
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.
@@ -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 CachingCompiler()
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(cell, self.execution_count)
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
@@ -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's paste bin, returning the URL.
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 for the gist. The default will say
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 if args.pattern is not None:
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.
@@ -83,8 +82,9 b' class PackagingMagics(Magics):'
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(quality=10)
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"), ('complete', None))
258 nt.assert_equal(cc("a = 1"), ("complete", None))
259 nt.assert_equal(cc("for a in range(5):"), ('incomplete', 4))
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:"), ('incomplete', 8))
260 nt.assert_equal(cc("for a in range(5):\n if a > 0:"), ("incomplete", 8))
261 nt.assert_equal(cc("raise = 2"), ('invalid', None))
261 nt.assert_equal(cc("raise = 2"), ("invalid", None))
262 nt.assert_equal(cc("a = [1,\n2,"), ('incomplete', 0))
262 nt.assert_equal(cc("a = [1,\n2,"), ("incomplete", 0))
263 nt.assert_equal(cc(")"), ('incomplete', 0))
263 nt.assert_equal(cc("(\n))"), ("incomplete", 0))
264 nt.assert_equal(cc("\\\r\n"), ('incomplete', 0))
264 nt.assert_equal(cc("\\\r\n"), ("incomplete", 0))
265 nt.assert_equal(cc("a = '''\n hi"), ('incomplete', 3))
265 nt.assert_equal(cc("a = '''\n hi"), ("incomplete", 3))
266 nt.assert_equal(cc("def a():\n x=1\n global x"), ('invalid', None))
266 nt.assert_equal(cc("def a():\n x=1\n global x"), ("invalid", None))
267 nt.assert_equal(cc("a \\ "), ('invalid', None)) # Nothing allowed after backslash
267 nt.assert_equal(cc("a \\ "), ("invalid", None)) # Nothing allowed after backslash
268 nt.assert_equal(cc("1\\\n+2"), ('complete', None))
268 nt.assert_equal(cc("1\\\n+2"), ("complete", None))
269 nt.assert_equal(cc("exit"), ('complete', None))
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 10 def sysexit(stat, mode):
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
@@ -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('<h').tostring(), nchan
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, suspend_to_bg, cursor_in_leading_ws
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
@@ -45,10 +39,8 b' class TerminalPdb(Pdb):'
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(shell=self.shell,
42 compl = IPCompleter(
49 namespace={},
43 shell=self.shell, namespace={}, global_namespace={}, parent=self.shell
50 global_namespace={},
51 parent=self.shell,
52 )
44 )
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_")]
@@ -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,14 +77,31 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,
89 void_p,
90 void_p,
91 void_p,
92 void_p,
93 void_p,
94 void_p,
95 void_p,
96 void_p,
97 void_p,
98 ]
99 event = msg(
100 C("NSEvent"),
101 n(
102 "otherEventWithType:location:modifierFlags:"
103 "timestamp:windowNumber:context:subtype:data1:data2:"
104 ),
88 15, # Type
105 15, # Type
89 0, # location
106 0, # location
90 0, # flags
107 0, # flags
@@ -95,6 +112,7 b' def _wake(NSApp):'
95 0, # data1
112 0, # data1
96 0, # data2
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 are described more in detail in further part of the documentation.
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, or after an object available in current
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 to need to access the underlying shell.
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 in the right hand side of an assignment, just
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 which case the
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 ``!`` will be split out into lines
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 Magics function are often present in the form of shell-like syntax, but are
205 Magic functions (magics) are often present in the form of shell-like syntax, but they are
206 under the hood python function. The syntax and assignment possibility are
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 sign percent will act only on one line:
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 And support assignment:
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 two percent sign can spread over multiple lines, but does not support assignment:
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
@@ -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 = ['ipyparallel'],
174 parallel=["ipyparallel"],
175 qtconsole = ['qtconsole'],
175 qtconsole=["qtconsole"],
176 doc = ['Sphinx>=1.3'],
176 doc=["Sphinx>=1.3"],
177 test = ['nose>=0.10.1', 'requests', 'testpath', 'pygments', 'nbformat', 'ipykernel', 'numpy>=1.14'],
177 test=[
178 "nose>=0.10.1",
179 "requests",
180 "testpath",
181 "pygments",
182 "nbformat",
183 "ipykernel",
184 "numpy>=1.16",
185 ],
178 terminal = [],
186 terminal=[],
179 kernel = ['ipykernel'],
187 kernel=["ipykernel"],
180 nbformat = ['nbformat'],
188 nbformat=["nbformat"],
181 notebook = ['notebook', 'ipywidgets'],
189 notebook=["notebook", "ipywidgets"],
182 nbconvert = ['nbconvert'],
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