##// 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 3 on:
4 4 push:
5 branches: [ master ]
5 branches: [ master, 7.x]
6 6 pull_request:
7 branches: [ master ]
7 branches: [ master, 7.x]
8 8
9 9 jobs:
10 10 build:
@@ -5,9 +5,9 b' name: Python package'
5 5
6 6 on:
7 7 push:
8 branches: [ master ]
8 branches: [ master, 7.x ]
9 9 pull_request:
10 branches: [ master ]
10 branches: [ master, 7.x ]
11 11
12 12 jobs:
13 13 build:
@@ -37,7 +37,7 b' install:'
37 37 - pip install -e file://$PWD#egg=ipython[test] --upgrade
38 38 - pip install trio curio --upgrade --upgrade-strategy eager
39 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 43 script:
@@ -112,25 +112,53 b' class CachingCompiler(codeop.Compile):'
112 112 """
113 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 135 """Make a name for a block of code, and cache the code.
117 136
118 137 Parameters
119 138 ----------
120 code : str
121 The Python source code to cache.
139 transformed_code : str
140 The executable Python source code to cache and compile.
122 141 number : int
123 142 A number which forms part of the code's name. Used for the execution
124 143 counter.
144 raw_code : str
145 The raw code before transformation, if None, set to `transformed_code`.
125 146
126 147 Returns
127 148 -------
128 149 The name of the cached code (as a string). Pass this as the filename
129 150 argument to compilation, so that tracebacks are correctly hooked up.
130 151 """
131 name = code_name(code, number)
132 entry = (len(code), time.time(),
133 [line+'\n' for line in code.splitlines()], name)
152 if raw_code is None:
153 raw_code = transformed_code
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 162 linecache.cache[name] = entry
135 163 linecache._ipython_cache[name] = entry
136 164 return name
@@ -201,7 +201,9 b" def provisionalcompleter(action='ignore'):"
201 201
202 202 >>> completer.do_experimental_things() # raises.
203 203
204 .. note:: Unstable
204 .. note::
205
206 Unstable
205 207
206 208 By using this context manager you agree that the API in use may change
207 209 without warning, and that you won't complain if they do so.
@@ -356,7 +358,9 b' class Completion:'
356 358 """
357 359 Completion object used and return by IPython completers.
358 360
359 .. warning:: Unstable
361 .. warning::
362
363 Unstable
360 364
361 365 This function is unstable, API may change without warning.
362 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 424 Deduplicate a set of completions.
421 425
422 .. warning:: Unstable
426 .. warning::
427
428 Unstable
423 429
424 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 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 472 This function is unstable, API may change without warning.
465 473 It will also raise unless use in proper context manager.
@@ -1837,7 +1845,9 b' class IPCompleter(Completer):'
1837 1845 """
1838 1846 Returns an iterator over the possible completions
1839 1847
1840 .. warning:: Unstable
1848 .. warning::
1849
1850 Unstable
1841 1851
1842 1852 This function is unstable, API may change without warning.
1843 1853 It will also raise unless use in proper context manager.
@@ -23,6 +23,7 b' import os'
23 23 import sys
24 24 import traceback
25 25 from pprint import pformat
26 from pathlib import Path
26 27
27 28 from IPython.core import ultratb
28 29 from IPython.core.release import author_email
@@ -151,10 +152,10 b' class CrashHandler(object):'
151 152 try:
152 153 rptdir = self.app.ipython_dir
153 154 except:
154 rptdir = os.getcwd()
155 if rptdir is None or not os.path.isdir(rptdir):
156 rptdir = os.getcwd()
157 report_name = os.path.join(rptdir,self.crash_report_fname)
155 rptdir = Path.cwd()
156 if rptdir is None or not Path.is_dir(rptdir):
157 rptdir = Path.cwd()
158 report_name = rptdir / self.crash_report_fname
158 159 # write the report filename into the instance dict so it can get
159 160 # properly expanded out in the user message template
160 161 self.crash_report_fname = report_name
@@ -50,6 +50,7 b' from pdb import Pdb as OldPdb'
50 50 # it does so with some limitations. The rest of this support is implemented in
51 51 # the Tracer constructor.
52 52
53
53 54 def make_arrow(pad):
54 55 """generate the leading arrow in front of traceback or debugger"""
55 56 if pad >= 2:
@@ -237,7 +238,7 b' class Pdb(OldPdb):'
237 238 self.shell = TerminalInteractiveShell.instance()
238 239 # needed by any code which calls __import__("__main__") after
239 240 # the debugger was entered. See also #9941.
240 sys.modules['__main__'] = save_main
241 sys.modules["__main__"] = save_main
241 242
242 243 if color_scheme is not None:
243 244 warnings.warn(
@@ -272,7 +273,6 b' class Pdb(OldPdb):'
272 273 cst['Neutral'].colors.breakpoint_enabled = C.LightRed
273 274 cst['Neutral'].colors.breakpoint_disabled = C.Red
274 275
275
276 276 # Add a python parser so we can syntax highlight source while
277 277 # debugging.
278 278 self.parser = PyColorize.Parser(style=color_scheme)
@@ -320,6 +320,18 b' class Pdb(OldPdb):'
320 320 except KeyboardInterrupt:
321 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 335 def new_do_frame(self, arg):
324 336 OldPdb.do_frame(self, arg)
325 337
@@ -402,11 +414,10 b' class Pdb(OldPdb):'
402 414
403 415 Colors = self.color_scheme_table.active_colors
404 416 ColorsNormal = Colors.Normal
405 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
406 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
407 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
408 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
409 ColorsNormal)
417 tpl_link = "%s%%s%s" % (Colors.filenameEm, ColorsNormal)
418 tpl_call = "%s%%s%s%%s%s" % (Colors.vName, Colors.valEm, ColorsNormal)
419 tpl_line = "%%s%s%%s %s%%s" % (Colors.lineno, ColorsNormal)
420 tpl_line_em = "%%s%s%%s %s%%s%s" % (Colors.linenoEm, Colors.line, ColorsNormal)
410 421
411 422 frame, lineno = frame_lineno
412 423
@@ -439,8 +450,8 b' class Pdb(OldPdb):'
439 450 if frame is self.curframe:
440 451 ret.append('> ')
441 452 else:
442 ret.append(' ')
443 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
453 ret.append(" ")
454 ret.append("%s(%s)%s\n" % (link, lineno, call))
444 455
445 456 start = lineno - 1 - context//2
446 457 lines = linecache.getlines(filename)
@@ -449,14 +460,14 b' class Pdb(OldPdb):'
449 460 lines = lines[start : start + context]
450 461
451 462 for i,line in enumerate(lines):
452 show_arrow = (start + 1 + i == lineno)
453 linetpl = (frame is self.curframe or show_arrow) \
454 and tpl_line_em \
455 or tpl_line
456 ret.append(self.__format_line(linetpl, filename,
457 start + 1 + i, line,
458 arrow = show_arrow) )
459 return ''.join(ret)
463 show_arrow = start + 1 + i == lineno
464 linetpl = (frame is self.curframe or show_arrow) and tpl_line_em or tpl_line
465 ret.append(
466 self.__format_line(
467 linetpl, filename, start + 1 + i, line, arrow=show_arrow
468 )
469 )
470 return "".join(ret)
460 471
461 472 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
462 473 bp_mark = ""
@@ -488,7 +499,6 b' class Pdb(OldPdb):'
488 499
489 500 return tpl_line % (bp_mark_color + bp_mark, num, line)
490 501
491
492 502 def print_list_lines(self, filename, first, last):
493 503 """The printing (as opposed to the parsing part of a 'list'
494 504 command."""
@@ -507,9 +517,13 b' class Pdb(OldPdb):'
507 517 break
508 518
509 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 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 528 src.append(line)
515 529 self.lineno = lineno
@@ -706,7 +720,7 b' class Pdb(OldPdb):'
706 720
707 721 Will skip hidden frames.
708 722 """
709 ## modified version of upstream that skips
723 # modified version of upstream that skips
710 724 # frames with __tracebackide__
711 725 if self.curindex == 0:
712 726 self.error("Oldest frame")
@@ -720,11 +734,9 b' class Pdb(OldPdb):'
720 734 if count < 0:
721 735 _newframe = 0
722 736 else:
723 _newindex = self.curindex
724 737 counter = 0
725 738 hidden_frames = self.hidden_frames(self.stack)
726 739 for i in range(self.curindex - 1, -1, -1):
727 frame = self.stack[i][0]
728 740 if hidden_frames[i] and self.skip_hidden:
729 741 skipped += 1
730 742 continue
@@ -765,12 +777,10 b' class Pdb(OldPdb):'
765 777 if count < 0:
766 778 _newframe = len(self.stack) - 1
767 779 else:
768 _newindex = self.curindex
769 780 counter = 0
770 781 skipped = 0
771 782 hidden_frames = self.hidden_frames(self.stack)
772 783 for i in range(self.curindex + 1, len(self.stack)):
773 frame = self.stack[i][0]
774 784 if hidden_frames[i] and self.skip_hidden:
775 785 skipped += 1
776 786 continue
@@ -796,6 +806,20 b' class Pdb(OldPdb):'
796 806 do_d = do_down
797 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 823 class InterruptiblePdb(Pdb):
800 824 """Version of debugger where KeyboardInterrupt exits the debugger altogether."""
801 825
@@ -656,7 +656,6 b' class GeoJSON(JSON):'
656 656
657 657 Examples
658 658 --------
659
660 659 The following will display an interactive map of Mars with a point of
661 660 interest on frontend that do support GeoJSON display.
662 661
@@ -723,7 +722,7 b' class Javascript(TextDisplayObject):'
723 722 running the source code. The full URLs of the libraries should
724 723 be given. A single Javascript library URL can also be given as a
725 724 string.
726 css: : list or str
725 css : list or str
727 726 A sequence of css files to load before running the source code.
728 727 The full URLs of the css files should be given. A single css URL
729 728 can also be given as a string.
@@ -851,18 +850,26 b' class Image(DisplayObject):'
851 850
852 851 Examples
853 852 --------
854 # embedded image data, works in qtconsole and notebook
855 # 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.
857 # The result is always embedding image data for inline images.
858 Image('http://www.google.fr/images/srpr/logo3w.png')
859 Image('/path/to/image.jpg')
860 Image(b'RAW_PNG_DATA...')
861
862 # Specifying Image(url=...) does not embed the image data,
863 # it only generates `<img>` tag with a link to the source.
864 # This will not work in the qtconsole or offline.
865 Image(url='http://www.google.fr/images/srpr/logo3w.png')
853 embedded image data, works in qtconsole and notebook
854 when passed positionally, the first arg can be any of raw image data,
855 a URL, or a filename from which to load image data.
856 The result is always embedding image data for inline images.
857
858 >>> Image('http://www.google.fr/images/srpr/logo3w.png')
859 <IPython.core.display.Image object>
860
861 >>> Image('/path/to/image.jpg')
862 <IPython.core.display.Image object>
863
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 875 if isinstance(data, (Path, PurePath)):
@@ -1036,24 +1043,23 b' class Video(DisplayObject):'
1036 1043 ----------
1037 1044 data : unicode, str or bytes
1038 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 1047 url : unicode
1041 A URL for the video. If you specify `url=`,
1048 A URL for the video. If you specify ``url=``,
1042 1049 the image data will not be embedded.
1043 1050 filename : unicode
1044 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 1053 embed : bool
1047 1054 Should the video be embedded using a data URI (True) or be
1048 1055 loaded using a <video> tag (False).
1049 1056
1050 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 1060 Local files can be displayed with URLs without embedding the content, via::
1054 1061
1055 1062 Video('./video.mp4')
1056
1057 1063 mimetype: unicode
1058 1064 Specify the mimetype for embedded videos.
1059 1065 Default will be guessed from file extension, if available.
@@ -1064,14 +1070,13 b' class Video(DisplayObject):'
1064 1070 Height in pixels to which to constrain the video in html.
1065 1071 If not supplied, defaults to the height of the video.
1066 1072 html_attributes : str
1067 Attributes for the HTML `<video>` block.
1068 Default: `"controls"` to get video controls.
1069 Other examples: `"controls muted"` for muted video with controls,
1070 `"loop autoplay"` for looping autoplaying video without controls.
1073 Attributes for the HTML ``<video>`` block.
1074 Default: ``"controls"`` to get video controls.
1075 Other examples: ``"controls muted"`` for muted video with controls,
1076 ``"loop autoplay"`` for looping autoplaying video without controls.
1071 1077
1072 1078 Examples
1073 1079 --------
1074
1075 1080 ::
1076 1081
1077 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 1171 *formats : strs
1167 1172 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
1168 **kwargs :
1173 **kwargs
1169 1174 Keyword args will be relayed to ``figure.canvas.print_figure``.
1170 1175 """
1171 1176 from IPython.core.interactiveshell import InteractiveShell
@@ -508,6 +508,20 b' def make_tokens_by_line(lines:List[str]):'
508 508
509 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 525 def show_linewise_tokens(s: str):
512 526 """For investigation and debugging"""
513 527 if not s.endswith('\n'):
@@ -662,6 +676,15 b' class TransformerManager:'
662 676
663 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 688 if not tokens_by_line:
666 689 return 'incomplete', find_last_indent(lines)
667 690
@@ -443,6 +443,7 b' class InteractiveShell(SingletonConfigurable):'
443 443 display_formatter = Instance(DisplayFormatter, allow_none=True)
444 444 displayhook_class = Type(DisplayHook)
445 445 display_pub_class = Type(DisplayPublisher)
446 compiler_class = Type(CachingCompiler)
446 447
447 448 sphinxify_docstring = Bool(False, help=
448 449 """
@@ -748,7 +749,7 b' class InteractiveShell(SingletonConfigurable):'
748 749 self.more = False
749 750
750 751 # command compiler
751 self.compile = CachingCompiler()
752 self.compile = self.compiler_class()
752 753
753 754 # Make an empty namespace, which extension writers can rely on both
754 755 # existing and NEVER being used by ipython itself. This gives them a
@@ -931,17 +932,27 b' class InteractiveShell(SingletonConfigurable):'
931 932 # Our exe is inside or has access to the virtualenv, don't need to do anything.
932 933 return
933 934
934 warn("Attempting to work in a virtualenv. If you encounter problems, please "
935 "install IPython inside the virtualenv.")
936 935 if sys.platform == "win32":
937 virtual_env = Path(os.environ["VIRTUAL_ENV"]).joinpath(
938 "Lib", "site-packages"
939 )
936 virtual_env = Path(os.environ["VIRTUAL_ENV"], "Lib", "site-packages")
940 937 else:
941 virtual_env = Path(os.environ["VIRTUAL_ENV"]).joinpath(
942 "lib", "python{}.{}".format(*sys.version_info[:2]), "site-packages"
938 virtual_env_path = Path(
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 956 import site
946 957 sys.path.insert(0, virtual_env)
947 958 site.addsitedir(virtual_env)
@@ -1765,8 +1776,14 b' class InteractiveShell(SingletonConfigurable):'
1765 1776 if meth == 'pdoc':
1766 1777 pmethod(info.obj, oname, formatter)
1767 1778 elif meth == 'pinfo':
1768 pmethod(info.obj, oname, formatter, info,
1769 enable_html_pager=self.enable_html_pager, **kw)
1779 pmethod(
1780 info.obj,
1781 oname,
1782 formatter,
1783 info,
1784 enable_html_pager=self.enable_html_pager,
1785 **kw
1786 )
1770 1787 else:
1771 1788 pmethod(info.obj, oname)
1772 1789 else:
@@ -2289,8 +2306,9 b' class InteractiveShell(SingletonConfigurable):'
2289 2306 # Defined here so that it's included in the documentation
2290 2307 @functools.wraps(magic.MagicsManager.register_function)
2291 2308 def register_magic_function(self, func, magic_kind='line', magic_name=None):
2292 self.magics_manager.register_function(func,
2293 magic_kind=magic_kind, magic_name=magic_name)
2309 self.magics_manager.register_function(
2310 func, magic_kind=magic_kind, magic_name=magic_name
2311 )
2294 2312
2295 2313 def run_line_magic(self, magic_name, line, _stack_depth=1):
2296 2314 """Execute the given line magic.
@@ -3086,12 +3104,14 b' class InteractiveShell(SingletonConfigurable):'
3086 3104 # Our own compiler remembers the __future__ environment. If we want to
3087 3105 # run code with a separate __future__ environment, use the default
3088 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 3109 _run_async = False
3092 3110
3093 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 3116 with self.display_trap:
3097 3117 # Compile to bytecode
@@ -20,7 +20,7 b' import re'
20 20 import sys
21 21 import ast
22 22 from itertools import chain
23 from urllib.request import urlopen
23 from urllib.request import Request, urlopen
24 24 from urllib.parse import urlencode
25 25 from pathlib import Path
26 26
@@ -29,6 +29,7 b' from IPython.core.error import TryNext, StdinNotImplementedError, UsageError'
29 29 from IPython.core.macro import Macro
30 30 from IPython.core.magic import Magics, magics_class, line_magic
31 31 from IPython.core.oinspect import find_file, find_source_lines
32 from IPython.core.release import version
32 33 from IPython.testing.skipdoctest import skip_doctest
33 34 from IPython.utils.contexts import preserve_keys
34 35 from IPython.utils.path import get_py_filename
@@ -245,7 +246,7 b' class CodeMagics(Magics):'
245 246
246 247 @line_magic
247 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 251 Usage:\\
251 252 %pastebin [-d "Custom description"] 1-7
@@ -255,7 +256,7 b' class CodeMagics(Magics):'
255 256
256 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 260 "Pasted from IPython".
260 261 """
261 262 opts, args = self.parse_options(parameter_s, 'd:')
@@ -266,13 +267,19 b' class CodeMagics(Magics):'
266 267 print(e.args[0])
267 268 return
268 269
269 post_data = urlencode({
270 "title": opts.get('d', "Pasted from IPython"),
271 "syntax": "python3",
272 "content": code
273 }).encode('utf-8')
274
275 response = urlopen("http://dpaste.com/api/v2/", post_data)
270 post_data = urlencode(
271 {
272 "title": opts.get("d", "Pasted from IPython"),
273 "syntax": "python",
274 "content": code,
275 }
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 283 return response.headers.get('Location')
277 284
278 285 @line_magic
@@ -16,6 +16,7 b''
16 16 import os
17 17 import sys
18 18 from io import open as io_open
19 import fnmatch
19 20
20 21 # Our own packages
21 22 from IPython.core.error import StdinNotImplementedError
@@ -170,7 +171,8 b' class HistoryMagics(Magics):'
170 171 pattern = None
171 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 176 if args.pattern:
175 177 pattern = "*" + " ".join(args.pattern) + "*"
176 178 else:
@@ -183,6 +185,9 b' class HistoryMagics(Magics):'
183 185 hist = history_manager.get_tail(n, raw=raw, output=get_output)
184 186 else:
185 187 if args.range: # Get history by ranges
188 if args.pattern:
189 range_pattern = "*" + " ".join(args.pattern) + "*"
190 print_nums = True
186 191 hist = history_manager.get_range_by_str(" ".join(args.range),
187 192 raw, get_output)
188 193 else: # Just get history for the current session
@@ -200,6 +205,9 b' class HistoryMagics(Magics):'
200 205 # into an editor.
201 206 if get_output:
202 207 inline, output = inline
208 if range_pattern:
209 if not fnmatch.fnmatch(inline, range_pattern):
210 continue
203 211 inline = inline.expandtabs(4).rstrip()
204 212
205 213 multiline = "\n" in inline
@@ -13,7 +13,6 b' import shlex'
13 13 import sys
14 14 from pathlib import Path
15 15
16 from pathlib import Path
17 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 27 # Check if there is a conda executable in the same directory as the Python executable.
29 28 # This is the case within conda's root environment.
30 29 conda = Path(sys.executable).parent / "conda"
31 if conda.isfile():
30 if conda.is_file():
32 31 return str(conda)
33 32
34 33 # Otherwise, attempt to extract the executable from conda history.
@@ -83,8 +82,9 b' class PackagingMagics(Magics):'
83 82
84 83 conda = _get_conda_executable()
85 84 args = shlex.split(line)
86 command = args[0]
87 args = args[1:]
85 command = args[0] if len(args) > 0 else ""
86 args = args[1:] if len(args) > 1 else [""]
87
88 88 extra_args = []
89 89
90 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 183 ip = get_ipython()
184 184 cfg = _get_inline_config()
185 185 cfg.print_figure_kwargs.update(dict(foo='bar'))
186 kwargs = dict(quality=10)
186 kwargs = dict(dpi=150)
187 187 display.set_matplotlib_formats('png', **kwargs)
188 188 formatter = ip.display_formatter.formatters['image/png']
189 189 f = formatter.lookup_by_type(Figure)
@@ -255,18 +255,18 b' def test_find_assign_op_dedent():'
255 255
256 256 def test_check_complete():
257 257 cc = ipt2.TransformerManager().check_complete
258 nt.assert_equal(cc("a = 1"), ('complete', None))
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))
261 nt.assert_equal(cc("raise = 2"), ('invalid', None))
262 nt.assert_equal(cc("a = [1,\n2,"), ('incomplete', 0))
263 nt.assert_equal(cc(")"), ('incomplete', 0))
264 nt.assert_equal(cc("\\\r\n"), ('incomplete', 0))
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))
267 nt.assert_equal(cc("a \\ "), ('invalid', None)) # Nothing allowed after backslash
268 nt.assert_equal(cc("1\\\n+2"), ('complete', None))
269 nt.assert_equal(cc("exit"), ('complete', None))
258 nt.assert_equal(cc("a = 1"), ("complete", None))
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))
261 nt.assert_equal(cc("raise = 2"), ("invalid", None))
262 nt.assert_equal(cc("a = [1,\n2,"), ("incomplete", 0))
263 nt.assert_equal(cc("(\n))"), ("incomplete", 0))
264 nt.assert_equal(cc("\\\r\n"), ("incomplete", 0))
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))
267 nt.assert_equal(cc("a \\ "), ("invalid", None)) # Nothing allowed after backslash
268 nt.assert_equal(cc("1\\\n+2"), ("complete", None))
269 nt.assert_equal(cc("exit"), ("complete", None))
270 270
271 271 example = dedent("""
272 272 if True:
@@ -297,6 +297,24 b' def test_check_complete_II():'
297 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 318 def test_null_cleanup_transformer():
301 319 manager = ipt2.TransformerManager()
302 320 manager.cleanup_transforms.insert(0, null_cleanup_transformer)
@@ -117,84 +117,91 b' ZeroDivisionError Traceback (most recent call last)'
117 117 ZeroDivisionError: ...
118 118 """
119 119
120 def doctest_tb_sysexit():
121 """
122 In [17]: %xmode plain
123 Exception reporting mode: Plain
124
125 In [18]: %run simpleerr.py exit
126 An exception has occurred, use %tb to see the full traceback.
127 SystemExit: (1, 'Mode = exit')
128
129 In [19]: %run simpleerr.py exit 2
130 An exception has occurred, use %tb to see the full traceback.
131 SystemExit: (2, 'Mode = exit')
132
133 In [20]: %tb
134 Traceback (most recent call last):
135 File ... in <module>
136 bar(mode)
137 File ... line 22, in bar
138 sysexit(stat, mode)
139 File ... line 11, in sysexit
140 raise SystemExit(stat, 'Mode = %s' % mode)
141 SystemExit: (2, 'Mode = exit')
142
143 In [21]: %xmode context
144 Exception reporting mode: Context
145
146 In [22]: %tb
147 ---------------------------------------------------------------------------
148 SystemExit Traceback (most recent call last)
149 <BLANKLINE>
150 ...<module>
151 29 except IndexError:
152 30 mode = 'div'
153 ---> 32 bar(mode)
154 <BLANKLINE>
155 ...bar(mode)
156 20 except:
157 21 stat = 1
158 ---> 22 sysexit(stat, mode)
159 23 else:
160 24 raise ValueError('Unknown mode')
161 <BLANKLINE>
162 ...sysexit(stat, mode)
163 10 def sysexit(stat, mode):
164 ---> 11 raise SystemExit(stat, 'Mode = %s' % mode)
165 <BLANKLINE>
166 SystemExit: (2, 'Mode = exit')
167
168 In [23]: %xmode verbose
169 Exception reporting mode: Verbose
170
171 In [24]: %tb
172 ---------------------------------------------------------------------------
173 SystemExit Traceback (most recent call last)
174 <BLANKLINE>
175 ... in <module>
176 29 except IndexError:
177 30 mode = 'div'
178 ---> 32 bar(mode)
179 mode = 'exit'
180 <BLANKLINE>
181 ... in bar(mode='exit')
182 20 except:
183 21 stat = 1
184 ---> 22 sysexit(stat, mode)
185 mode = 'exit'
186 stat = 2
187 23 else:
188 24 raise ValueError('Unknown mode')
189 <BLANKLINE>
190 ... in sysexit(stat=2, mode='exit')
191 10 def sysexit(stat, mode):
192 ---> 11 raise SystemExit(stat, 'Mode = %s' % mode)
193 stat = 2
194 mode = 'exit'
195 <BLANKLINE>
196 SystemExit: (2, 'Mode = exit')
197 """
120 # TODO : Marc 2021 – this seem to fail due
121 # to upstream changes in CI for whatever reason.
122 # Commenting for now, to revive someday (maybe?)
123 # nose won't work in 3.10 anyway and we'll have to disable iptest.
124 # thus this likely need to bemigrated to pytest.
125
126
127 # def doctest_tb_sysexit():
128 # """
129 # In [17]: %xmode plain
130 # Exception reporting mode: Plain
131 #
132 # In [18]: %run simpleerr.py exit
133 # An exception has occurred, use %tb to see the full traceback.
134 # SystemExit: (1, 'Mode = exit')
135 #
136 # In [19]: %run simpleerr.py exit 2
137 # An exception has occurred, use %tb to see the full traceback.
138 # SystemExit: (2, 'Mode = exit')
139 #
140 # In [20]: %tb
141 # Traceback (most recent call last):
142 # File ... in <module>
143 # bar(mode)
144 # File ... line 22, in bar
145 # sysexit(stat, mode)
146 # File ... line 11, in sysexit
147 # raise SystemExit(stat, 'Mode = %s' % mode)
148 # SystemExit: (2, 'Mode = exit')
149 #
150 # In [21]: %xmode context
151 # Exception reporting mode: Context
152 #
153 # In [22]: %tb
154 # ---------------------------------------------------------------------------
155 # SystemExit Traceback (most recent call last)
156 # <BLANKLINE>
157 # ...<module>
158 # 29 except IndexError:
159 # 30 mode = 'div'
160 # ---> 32 bar(mode)
161 # <BLANKLINE>
162 # ...bar(mode)
163 # 20 except:
164 # 21 stat = 1
165 # ---> 22 sysexit(stat, mode)
166 # 23 else:
167 # 24 raise ValueError('Unknown mode')
168 # <BLANKLINE>
169 # ...sysexit(stat, mode)
170 # 10 def sysexit(stat, mode):
171 # ---> 11 raise SystemExit(stat, 'Mode = %s' % mode)
172 # <BLANKLINE>
173 # SystemExit: (2, 'Mode = exit')
174 #
175 # In [23]: %xmode verbose
176 # Exception reporting mode: Verbose
177 #
178 # In [24]: %tb
179 # ---------------------------------------------------------------------------
180 # SystemExit Traceback (most recent call last)
181 # <BLANKLINE>
182 # ... in <module>
183 # 29 except IndexError:
184 # 30 mode = 'div'
185 # ---> 32 bar(mode)
186 # mode = 'exit'
187 # <BLANKLINE>
188 # ... in bar(mode='exit')
189 # 20 except:
190 # 21 stat = 1
191 # ---> 22 sysexit(stat, mode)
192 # mode = 'exit'
193 # stat = 2
194 # 23 else:
195 # 24 raise ValueError('Unknown mode')
196 # <BLANKLINE>
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 207 def test_run_cell():
@@ -35,6 +35,8 b' from IPython.utils.tempdir import (TemporaryDirectory,'
35 35 from IPython.utils.process import find_cmd
36 36 from .test_debugger import PdbTestInput
37 37
38 import pytest
39
38 40
39 41 @magic.magics_class
40 42 class DummyMagics(magic.Magics): pass
@@ -954,7 +956,6 b' async def test_script_bg_out():'
954 956 nt.assert_equal((await ip.user_ns["output"].read()), b"hi\n")
955 957 ip.user_ns['output'].close()
956 958
957
958 959 @dec.skip_win32
959 960 async def test_script_bg_err():
960 961 ip = get_ipython()
@@ -8,6 +8,8 b' from os import walk, sep, fsdecode'
8 8
9 9 from IPython.core.display import DisplayObject, TextDisplayObject
10 10
11 from typing import Tuple
12
11 13 __all__ = ['Audio', 'IFrame', 'YouTubeVideo', 'VimeoVideo', 'ScribdDocument',
12 14 'FileLink', 'FileLinks', 'Code']
13 15
@@ -159,7 +161,7 b' class Audio(DisplayObject):'
159 161 return val
160 162
161 163 @staticmethod
162 def _validate_and_normalize_with_numpy(data, normalize):
164 def _validate_and_normalize_with_numpy(data, normalize) -> Tuple[bytes, int]:
163 165 import numpy as np
164 166
165 167 data = np.array(data, dtype=float)
@@ -178,8 +180,7 b' class Audio(DisplayObject):'
178 180 max_abs_value = np.max(np.abs(data))
179 181 normalization_factor = Audio._get_normalization_factor(max_abs_value, normalize)
180 182 scaled = data / normalization_factor * 32767
181 return scaled.astype('<h').tostring(), nchan
182
183 return scaled.astype("<h").tobytes(), nchan
183 184
184 185 @staticmethod
185 186 def _validate_and_normalize_without_numpy(data, normalize):
@@ -1,5 +1,4 b''
1 1 import asyncio
2 import signal
3 2 import sys
4 3 import threading
5 4
@@ -7,13 +6,8 b' from IPython.core.debugger import Pdb'
7 6
8 7 from IPython.core.completer import IPCompleter
9 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 11 from pygments.token import Token
18 12 from prompt_toolkit.shortcuts.prompt import PromptSession
19 13 from prompt_toolkit.enums import EditingMode
@@ -45,10 +39,8 b' class TerminalPdb(Pdb):'
45 39 return [(Token.Prompt, self.prompt)]
46 40
47 41 if self._ptcomp is None:
48 compl = IPCompleter(shell=self.shell,
49 namespace={},
50 global_namespace={},
51 parent=self.shell,
42 compl = IPCompleter(
43 shell=self.shell, namespace={}, global_namespace={}, parent=self.shell
52 44 )
53 45 # add a completer for all the do_ methods
54 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 42 CFFileDescriptorCreate = CoreFoundation.CFFileDescriptorCreate
43 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 46 CFFileDescriptorGetNativeDescriptor = CoreFoundation.CFFileDescriptorGetNativeDescriptor
47 47 CFFileDescriptorGetNativeDescriptor.restype = ctypes.c_int
@@ -77,14 +77,31 b" kCFRunLoopCommonModes = void_p.in_dll(CoreFoundation, 'kCFRunLoopCommonModes')"
77 77
78 78 def _NSApp():
79 79 """Return the global NSApplication instance (NSApp)"""
80 objc.objc_msgSend.argtypes = [void_p, void_p]
80 81 return msg(C('NSApplication'), n('sharedApplication'))
81 82
82 83
83 84 def _wake(NSApp):
84 85 """Wake the Application"""
85 event = msg(C('NSEvent'),
86 n('otherEventWithType:location:modifierFlags:'
87 'timestamp:windowNumber:context:subtype:data1:data2:'),
86 objc.objc_msgSend.argtypes = [
87 void_p,
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 105 15, # Type
89 106 0, # location
90 107 0, # flags
@@ -95,6 +112,7 b' def _wake(NSApp):'
95 112 0, # data1
96 113 0, # data2
97 114 )
115 objc.objc_msgSend.argtypes = [void_p, void_p, void_p, void_p]
98 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 124 CFFileDescriptorInvalidate(fdref)
107 125 CFRelease(fdref)
108 126 NSApp = _NSApp()
127 objc.objc_msgSend.argtypes = [void_p, void_p, void_p]
109 128 msg(NSApp, n('stop:'), NSApp)
110 129 _wake(NSApp)
111 130
@@ -128,6 +147,7 b' def inputhook(context):'
128 147 """Inputhook for Cocoa (NSApp)"""
129 148 NSApp = _NSApp()
130 149 _stop_on_read(context.fileno())
150 objc.objc_msgSend.argtypes = [void_p, void_p]
131 151 msg(NSApp, n('run'))
132 152 if not _triggered.is_set():
133 153 # app closed without firing callback,
@@ -1,6 +1,7 b''
1 1 import sys
2 2 import os
3 3 from IPython.external.qt_for_kernel import QtCore, QtGui
4 from IPython import get_ipython
4 5
5 6 # If we create a QApplication, keep a reference to it so that it doesn't get
6 7 # garbage collected.
@@ -8,6 +9,12 b' _appref = None'
8 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 18 def inputhook(context):
12 19 global _appref
13 20 app = QtCore.QCoreApplication.instance()
@@ -27,6 +34,13 b' def inputhook(context):'
27 34 return
28 35 QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
29 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 44 event_loop = QtCore.QEventLoop(app)
31 45
32 46 if sys.platform == 'win32':
@@ -9,6 +9,7 b' Module to define and register Terminal IPython shortcuts with'
9 9 import warnings
10 10 import signal
11 11 import sys
12 import re
12 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 153 setuptools, distutils, or any other distribution tools like `flit
154 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 165 .. sourcecode:: bash
158 166
@@ -119,11 +119,6 b' which adds a directory called ``profile_<name>`` to your IPython directory. Then'
119 119 you can load this profile by adding ``--profile=<name>`` to your command line
120 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 122 IPython extends the config loader for Python files so that you can inherit
128 123 config from another profile. To do this, use a line like this in your Python
129 124 config file:
@@ -9,15 +9,15 b' IPython Documentation'
9 9 :Release: |release|
10 10 :Date: |today|
11 11
12 Welcome to the official IPython documentation
12 Welcome to the official IPython documentation.
13 13
14 14 IPython provides a rich toolkit to help you make the most of using Python
15 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 21 :alt: Screenshot of IPython 6.0
22 22 :align: center
23 23
@@ -59,7 +59,7 b' The Command line interface inherits the above functionality and adds'
59 59
60 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 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 84 repository <http://github.com/ipython/ipython>`_.
85 85
86 86
87
88
89 87 .. toctree::
90 88 :maxdepth: 1
91 89 :hidden:
@@ -3,20 +3,20 b' Python vs IPython'
3 3 =================
4 4
5 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 9 ``SyntaxError`` if run in a pure Python shell, or if executing in a Python
10 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 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 21 .. code-block:: ipython
22 22
@@ -58,8 +58,8 b' All the following construct are valid IPython syntax:'
58 58 ...: print $months[0];
59 59
60 60
61 Each of these construct 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
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's see each of these examples
63 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 93 namespace will show help relative to this object:
94 94
95 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 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 131 matching names:
132 132
133 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 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 150 .. code-block:: ipython
151 151
@@ -167,7 +167,7 b' Or edit file:'
167 167
168 168 The line after the bang can call any program installed in the underlying
169 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 172 .. code-block:: ipython
173 173
@@ -176,19 +176,19 b' The later form of expansion supports arbitrary python expression:'
176 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
180 after the equal sign, or separated from it by a white space. In which case the
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.
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 this case the
181 standard output of the command after the bang will be split out into lines
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 186 .. code-block:: ipython
187 187
188 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 193 .. code-block:: ipython
194 194
@@ -202,19 +202,19 b' You can combine the different possibilities in for loops, condition, functions..'
202 202 Magics
203 203 ------
204 204
205 Magics function are often present in the form of shell-like syntax, but are
206 under the hood python function. The syntax and assignment possibility are
205 Magic functions (magics) are often present in the form of shell-like syntax, but they are
206 python functions under the hood. The syntax and assignment possibilities are
207 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 212 .. code-block:: ipython
213 213
214 214 In[1]: %xmode
215 215 Exception reporting mode: Verbose
216 216
217 And support assignment:
217 Magics support assignment:
218 218
219 219 .. code-block:: ipython
220 220
@@ -224,7 +224,7 b' And support assignment:'
224 224 In [2]: results
225 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 229 .. code-block:: ipython
230 230
@@ -22,6 +22,47 b' Need to be updated:'
22 22
23 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 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 134 - The ctrl e, ctrl f, and alt f shortcuts work by default in emacs mode.
94 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 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 168 For more information please see unit test -
109 169 extensions/tests/test_autoreload.py : 'test_autoload_newly_added_objects'
170 =======
110 171
111 172 .. DO NOT EDIT THIS LINE BEFORE RELEASE. FEATURE INSERTION POINT.
112 173
@@ -2,6 +2,105 b''
2 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 104 .. _version 719:
6 105
7 106 IPython 7.19
@@ -171,15 +171,23 b' setuptools_extra_args = {}'
171 171 # setuptools requirements
172 172
173 173 extras_require = dict(
174 parallel = ['ipyparallel'],
175 qtconsole = ['qtconsole'],
176 doc = ['Sphinx>=1.3'],
177 test = ['nose>=0.10.1', 'requests', 'testpath', 'pygments', 'nbformat', 'ipykernel', 'numpy>=1.14'],
174 parallel=["ipyparallel"],
175 qtconsole=["qtconsole"],
176 doc=["Sphinx>=1.3"],
177 test=[
178 "nose>=0.10.1",
179 "requests",
180 "testpath",
181 "pygments",
182 "nbformat",
183 "ipykernel",
184 "numpy>=1.16",
185 ],
178 186 terminal = [],
179 kernel = ['ipykernel'],
180 nbformat = ['nbformat'],
181 notebook = ['notebook', 'ipywidgets'],
182 nbconvert = ['nbconvert'],
187 kernel=["ipykernel"],
188 nbformat=["nbformat"],
189 notebook=["notebook", "ipywidgets"],
190 nbconvert=["nbconvert"],
183 191 )
184 192
185 193 install_requires = [
General Comments 0
You need to be logged in to leave comments. Login now