Show More
@@ -0,0 +1,33 b'' | |||||
|
1 | BSD 3-Clause License | |||
|
2 | ||||
|
3 | - Copyright (c) 2008-Present, IPython Development Team | |||
|
4 | - Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu> | |||
|
5 | - Copyright (c) 2001, Janko Hauser <jhauser@zscout.de> | |||
|
6 | - Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu> | |||
|
7 | ||||
|
8 | All rights reserved. | |||
|
9 | ||||
|
10 | Redistribution and use in source and binary forms, with or without | |||
|
11 | modification, are permitted provided that the following conditions are met: | |||
|
12 | ||||
|
13 | * Redistributions of source code must retain the above copyright notice, this | |||
|
14 | list of conditions and the following disclaimer. | |||
|
15 | ||||
|
16 | * Redistributions in binary form must reproduce the above copyright notice, | |||
|
17 | this list of conditions and the following disclaimer in the documentation | |||
|
18 | and/or other materials provided with the distribution. | |||
|
19 | ||||
|
20 | * Neither the name of the copyright holder nor the names of its | |||
|
21 | contributors may be used to endorse or promote products derived from | |||
|
22 | this software without specific prior written permission. | |||
|
23 | ||||
|
24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |||
|
25 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
|
26 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
|
27 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |||
|
28 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
|
29 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |||
|
30 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |||
|
31 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
|
32 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |||
|
33 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
@@ -0,0 +1,7 b'' | |||||
|
1 | A couple of unused function and methods have been deprecated and will be removed | |||
|
2 | in future versions: | |||
|
3 | ||||
|
4 | - ``IPython.utils.io.raw_print_err`` | |||
|
5 | - ``IPython.utils.io.raw_print`` | |||
|
6 | ||||
|
7 |
@@ -2,10 +2,10 b'' | |||||
2 | language: python |
|
2 | language: python | |
3 | python: |
|
3 | python: | |
4 | - "nightly" |
|
4 | - "nightly" | |
|
5 | - "3.7-dev" | |||
5 | - 3.6 |
|
6 | - 3.6 | |
6 | - 3.5 |
|
7 | - 3.5 | |
7 | - 3.4 |
|
8 | - 3.4 | |
8 | - 3.3 |
|
|||
9 | sudo: false |
|
9 | sudo: false | |
10 | env: |
|
10 | env: | |
11 | global: |
|
11 | global: | |
@@ -16,9 +16,10 b' before_install:' | |||||
16 | install: |
|
16 | install: | |
17 | - pip install setuptools pip --upgrade |
|
17 | - pip install setuptools pip --upgrade | |
18 | - pip install -e file://$PWD#egg=ipython[test] --upgrade |
|
18 | - pip install -e file://$PWD#egg=ipython[test] --upgrade | |
19 | - pip install codecov --upgrade |
|
19 | - pip install codecov check-manifest --upgrade | |
20 | - sudo apt-get install graphviz |
|
20 | - sudo apt-get install graphviz | |
21 | script: |
|
21 | script: | |
|
22 | - check-manifest | |||
22 | - cd /tmp && iptest --coverage xml && cd - |
|
23 | - cd /tmp && iptest --coverage xml && cd - | |
23 | # On the latest Python only, make sure that the docs build. |
|
24 | # On the latest Python only, make sure that the docs build. | |
24 | - | |
|
25 | - | |
@@ -3,39 +3,8 b'' | |||||
3 | ============================= |
|
3 | ============================= | |
4 |
|
4 | |||
5 | IPython is licensed under the terms of the Modified BSD License (also known as |
|
5 | IPython is licensed under the terms of the Modified BSD License (also known as | |
6 |
New or Revised or 3-Clause BSD) |
|
6 | New or Revised or 3-Clause BSD). See the LICENSE file. | |
7 |
|
7 | |||
8 | - Copyright (c) 2008-2014, IPython Development Team |
|
|||
9 | - Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu> |
|
|||
10 | - Copyright (c) 2001, Janko Hauser <jhauser@zscout.de> |
|
|||
11 | - Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu> |
|
|||
12 |
|
||||
13 | All rights reserved. |
|
|||
14 |
|
||||
15 | Redistribution and use in source and binary forms, with or without |
|
|||
16 | modification, are permitted provided that the following conditions are met: |
|
|||
17 |
|
||||
18 | Redistributions of source code must retain the above copyright notice, this |
|
|||
19 | list of conditions and the following disclaimer. |
|
|||
20 |
|
||||
21 | Redistributions in binary form must reproduce the above copyright notice, this |
|
|||
22 | list of conditions and the following disclaimer in the documentation and/or |
|
|||
23 | other materials provided with the distribution. |
|
|||
24 |
|
||||
25 | Neither the name of the IPython Development Team nor the names of its |
|
|||
26 | contributors may be used to endorse or promote products derived from this |
|
|||
27 | software without specific prior written permission. |
|
|||
28 |
|
||||
29 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
|
|||
30 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
|||
31 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
|||
32 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE |
|
|||
33 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
|||
34 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|
|||
35 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
|
|||
36 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
|
|||
37 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
|||
38 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
|||
39 |
|
8 | |||
40 | About the IPython Development Team |
|
9 | About the IPython Development Team | |
41 | ---------------------------------- |
|
10 | ---------------------------------- | |
@@ -45,9 +14,7 b' Fernando Perez began IPython in 2001 based on code from Janko Hauser' | |||||
45 | the project lead. |
|
14 | the project lead. | |
46 |
|
15 | |||
47 | The IPython Development Team is the set of all contributors to the IPython |
|
16 | The IPython Development Team is the set of all contributors to the IPython | |
48 |
project. This includes all of the IPython subprojects. |
|
17 | project. This includes all of the IPython subprojects. | |
49 | details is kept in the documentation directory, in the file |
|
|||
50 | ``about/credits.txt``. |
|
|||
51 |
|
18 | |||
52 | The core team that coordinates development on GitHub can be found here: |
|
19 | The core team that coordinates development on GitHub can be found here: | |
53 | https://github.com/ipython/. |
|
20 | https://github.com/ipython/. |
@@ -27,12 +27,12 b' import sys' | |||||
27 | #----------------------------------------------------------------------------- |
|
27 | #----------------------------------------------------------------------------- | |
28 |
|
28 | |||
29 | # Don't forget to also update setup.py when this changes! |
|
29 | # Don't forget to also update setup.py when this changes! | |
30 |
if sys.version_info < (3, |
|
30 | if sys.version_info < (3,4): | |
31 | raise ImportError( |
|
31 | raise ImportError( | |
32 | """ |
|
32 | """ | |
33 | IPython 6.0+ does not support Python 2.6, 2.7, 3.0, 3.1, or 3.2. |
|
33 | IPython 7.0+ supports Python 3.4 and above. | |
34 | When using Python 2.7, please install IPython 5.x LTS Long Term Support version. |
|
34 | When using Python 2.7, please install IPython 5.x LTS Long Term Support version. | |
35 | Beginning with IPython 6.0, Python 3.3 and above is required. |
|
35 | Python 3.3 was supported up to IPython 6.x. | |
36 |
|
36 | |||
37 | See IPython `README.rst` file for more information: |
|
37 | See IPython `README.rst` file for more information: | |
38 |
|
38 |
@@ -6,7 +6,7 b' Shim to maintain backwards compatibility with old IPython.consoleapp imports.' | |||||
6 |
|
6 | |||
7 | from warnings import warn |
|
7 | from warnings import warn | |
8 |
|
8 | |||
9 |
warn("The `IPython.consoleapp` package has been deprecated |
|
9 | warn("The `IPython.consoleapp` package has been deprecated since IPython 4.0." | |
10 | "You should import from jupyter_client.consoleapp instead.") |
|
10 | "You should import from jupyter_client.consoleapp instead.", stacklevel=2) | |
11 |
|
11 | |||
12 | from jupyter_client.consoleapp import * |
|
12 | from jupyter_client.consoleapp import * |
@@ -90,13 +90,31 b' class CachingCompiler(codeop.Compile):' | |||||
90 | # stdlib that call it outside our control go through our codepath |
|
90 | # stdlib that call it outside our control go through our codepath | |
91 | # (otherwise we'd lose our tracebacks). |
|
91 | # (otherwise we'd lose our tracebacks). | |
92 | linecache.checkcache = check_linecache_ipython |
|
92 | linecache.checkcache = check_linecache_ipython | |
|
93 | ||||
|
94 | ||||
|
95 | def _fix_module_ds(self, module): | |||
|
96 | """ | |||
|
97 | Starting in python 3.7 the AST for mule have changed, and if | |||
|
98 | the first expressions encountered is a string it is attached to the | |||
|
99 | `docstring` attribute of the `Module` ast node. | |||
|
100 | ||||
|
101 | This breaks IPython, as if this string is the only expression, IPython | |||
|
102 | will not return it as the result of the current cell. | |||
|
103 | """ | |||
|
104 | from ast import Str, Expr, Module, fix_missing_locations | |||
|
105 | docstring = getattr(module, 'docstring', None) | |||
|
106 | if not docstring: | |||
|
107 | return module | |||
|
108 | new_body=[Expr(Str(docstring, lineno=1, col_offset=0), lineno=1, col_offset=0)] | |||
|
109 | new_body.extend(module.body) | |||
|
110 | return fix_missing_locations(Module(new_body)) | |||
93 |
|
111 | |||
94 | def ast_parse(self, source, filename='<unknown>', symbol='exec'): |
|
112 | def ast_parse(self, source, filename='<unknown>', symbol='exec'): | |
95 | """Parse code to an AST with the current compiler flags active. |
|
113 | """Parse code to an AST with the current compiler flags active. | |
96 |
|
114 | |||
97 | Arguments are exactly the same as ast.parse (in the standard library), |
|
115 | Arguments are exactly the same as ast.parse (in the standard library), | |
98 | and are passed to the built-in compile function.""" |
|
116 | and are passed to the built-in compile function.""" | |
99 | return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1) |
|
117 | return self._fix_module_ds(compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1)) | |
100 |
|
118 | |||
101 | def reset_compiler_flags(self): |
|
119 | def reset_compiler_flags(self): | |
102 | """Reset compiler flags to default state.""" |
|
120 | """Reset compiler flags to default state.""" |
@@ -576,9 +576,9 b' class Completer(Configurable):' | |||||
576 | """ |
|
576 | """ | |
577 | ).tag(config=True) |
|
577 | ).tag(config=True) | |
578 |
|
578 | |||
579 |
use_jedi = Bool(default_value= |
|
579 | use_jedi = Bool(default_value=False, | |
580 | help="Experimental: Use Jedi to generate autocompletions. " |
|
580 | help="Experimental: Use Jedi to generate autocompletions. " | |
581 |
" |
|
581 | "Off by default.").tag(config=True) | |
582 |
|
582 | |||
583 | jedi_compute_type_timeout = Int(default_value=400, |
|
583 | jedi_compute_type_timeout = Int(default_value=400, | |
584 | help="""Experimental: restrict time (in milliseconds) during which Jedi can compute types. |
|
584 | help="""Experimental: restrict time (in milliseconds) during which Jedi can compute types. | |
@@ -683,7 +683,7 b' class Completer(Configurable):' | |||||
683 | Assuming the text is of the form NAME.NAME....[NAME], and is |
|
683 | Assuming the text is of the form NAME.NAME....[NAME], and is | |
684 | evaluatable in self.namespace or self.global_namespace, it will be |
|
684 | evaluatable in self.namespace or self.global_namespace, it will be | |
685 | evaluated and its attributes (as revealed by dir()) are used as |
|
685 | evaluated and its attributes (as revealed by dir()) are used as | |
686 |
possible completions. (For class instances, class members are |
|
686 | possible completions. (For class instances, class members are | |
687 | also considered.) |
|
687 | also considered.) | |
688 |
|
688 | |||
689 | WARNING: this can still invoke arbitrary C code, if an object |
|
689 | WARNING: this can still invoke arbitrary C code, if an object | |
@@ -869,7 +869,7 b' def position_to_cursor(text:str, offset:int)->Tuple[int, int]:' | |||||
869 |
|
869 | |||
870 | """ |
|
870 | """ | |
871 |
|
871 | |||
872 | assert 0 < offset <= len(text) , "0 < %s <= %s" % (offset , len(text)) |
|
872 | assert 0 <= offset <= len(text) , "0 <= %s <= %s" % (offset , len(text)) | |
873 |
|
873 | |||
874 | before = text[:offset] |
|
874 | before = text[:offset] | |
875 | blines = before.split('\n') # ! splitnes trim trailing \n |
|
875 | blines = before.split('\n') # ! splitnes trim trailing \n | |
@@ -949,8 +949,8 b' def _formatparamchildren(parameter) -> str:' | |||||
949 |
|
949 | |||
950 | Jedi does not expose a simple way to get `param=value` from its API. |
|
950 | Jedi does not expose a simple way to get `param=value` from its API. | |
951 |
|
951 | |||
952 | Prameter |
|
952 | Parameter | |
953 | ======== |
|
953 | ========= | |
954 |
|
954 | |||
955 | parameter: |
|
955 | parameter: | |
956 | Jedi's function `Param` |
|
956 | Jedi's function `Param` | |
@@ -1340,7 +1340,6 b' class IPCompleter(Completer):' | |||||
1340 | namespaces.append(self.global_namespace) |
|
1340 | namespaces.append(self.global_namespace) | |
1341 |
|
1341 | |||
1342 | completion_filter = lambda x:x |
|
1342 | completion_filter = lambda x:x | |
1343 | # cursor_pos is an it, jedi wants line and column |
|
|||
1344 | offset = cursor_to_position(text, cursor_line, cursor_column) |
|
1343 | offset = cursor_to_position(text, cursor_line, cursor_column) | |
1345 | # filter output if we are completing for object members |
|
1344 | # filter output if we are completing for object members | |
1346 | if offset: |
|
1345 | if offset: | |
@@ -1356,7 +1355,7 b' class IPCompleter(Completer):' | |||||
1356 | raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names)) |
|
1355 | raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names)) | |
1357 |
|
1356 | |||
1358 | interpreter = jedi.Interpreter( |
|
1357 | interpreter = jedi.Interpreter( | |
1359 | text, namespaces, column=cursor_column, line=cursor_line + 1) |
|
1358 | text[:offset], namespaces, column=cursor_column, line=cursor_line + 1) | |
1360 | try_jedi = True |
|
1359 | try_jedi = True | |
1361 |
|
1360 | |||
1362 | try: |
|
1361 | try: | |
@@ -1371,7 +1370,7 b' class IPCompleter(Completer):' | |||||
1371 | next_to_last_tree = interpreter._get_module().tree_node.children[-2] |
|
1370 | next_to_last_tree = interpreter._get_module().tree_node.children[-2] | |
1372 | completing_string = False |
|
1371 | completing_string = False | |
1373 | if isinstance(next_to_last_tree, ErrorLeaf): |
|
1372 | if isinstance(next_to_last_tree, ErrorLeaf): | |
1374 | completing_string = next_to_last_tree.value[0] in {'"', "'"} |
|
1373 | completing_string = next_to_last_tree.value.lstrip()[0] in {'"', "'"} | |
1375 | # if we are in a string jedi is likely not the right candidate for |
|
1374 | # if we are in a string jedi is likely not the right candidate for | |
1376 | # now. Skip it. |
|
1375 | # now. Skip it. | |
1377 | try_jedi = not completing_string |
|
1376 | try_jedi = not completing_string | |
@@ -1805,11 +1804,16 b' class IPCompleter(Completer):' | |||||
1805 | category=ProvisionalCompleterWarning, stacklevel=2) |
|
1804 | category=ProvisionalCompleterWarning, stacklevel=2) | |
1806 |
|
1805 | |||
1807 | seen = set() |
|
1806 | seen = set() | |
1808 | for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000): |
|
1807 | try: | |
1809 | if c and (c in seen): |
|
1808 | for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000): | |
1810 |
|
|
1809 | if c and (c in seen): | |
1811 | yield c |
|
1810 | continue | |
1812 |
|
|
1811 | yield c | |
|
1812 | seen.add(c) | |||
|
1813 | except KeyboardInterrupt: | |||
|
1814 | """if completions take too long and users send keyboard interrupt, | |||
|
1815 | do not crash and return ASAP. """ | |||
|
1816 | pass | |||
1813 |
|
1817 | |||
1814 | def _completions(self, full_text: str, offset: int, *, _timeout)->Iterator[Completion]: |
|
1818 | def _completions(self, full_text: str, offset: int, *, _timeout)->Iterator[Completion]: | |
1815 | """ |
|
1819 | """ |
@@ -667,7 +667,7 b' class Pretty(TextDisplayObject):' | |||||
667 | class HTML(TextDisplayObject): |
|
667 | class HTML(TextDisplayObject): | |
668 |
|
668 | |||
669 | def _repr_html_(self): |
|
669 | def _repr_html_(self): | |
670 | return self.data |
|
670 | return self._data_and_metadata() | |
671 |
|
671 | |||
672 | def __html__(self): |
|
672 | def __html__(self): | |
673 | """ |
|
673 | """ | |
@@ -681,20 +681,23 b' class HTML(TextDisplayObject):' | |||||
681 | class Markdown(TextDisplayObject): |
|
681 | class Markdown(TextDisplayObject): | |
682 |
|
682 | |||
683 | def _repr_markdown_(self): |
|
683 | def _repr_markdown_(self): | |
684 | return self.data |
|
684 | return self._data_and_metadata() | |
685 |
|
685 | |||
686 |
|
686 | |||
687 | class Math(TextDisplayObject): |
|
687 | class Math(TextDisplayObject): | |
688 |
|
688 | |||
689 | def _repr_latex_(self): |
|
689 | def _repr_latex_(self): | |
690 | s = self.data.strip('$') |
|
690 | s = "$$%s$$" % self.data.strip('$') | |
691 | return "$$%s$$" % s |
|
691 | if self.metadata: | |
|
692 | return s, deepcopy(self.metadata) | |||
|
693 | else: | |||
|
694 | return s | |||
692 |
|
695 | |||
693 |
|
696 | |||
694 | class Latex(TextDisplayObject): |
|
697 | class Latex(TextDisplayObject): | |
695 |
|
698 | |||
696 | def _repr_latex_(self): |
|
699 | def _repr_latex_(self): | |
697 | return self.data |
|
700 | return self._data_and_metadata() | |
698 |
|
701 | |||
699 |
|
702 | |||
700 | class SVG(DisplayObject): |
|
703 | class SVG(DisplayObject): |
@@ -317,4 +317,4 b' class CapturingDisplayHook(object):' | |||||
317 | if result is None: |
|
317 | if result is None: | |
318 | return |
|
318 | return | |
319 | format_dict, md_dict = self.shell.display_formatter.format(result) |
|
319 | format_dict, md_dict = self.shell.display_formatter.format(result) | |
320 |
self.outputs.append( |
|
320 | self.outputs.append({ 'data': format_dict, 'metadata': md_dict }) |
@@ -7,18 +7,13 b'' | |||||
7 | import os |
|
7 | import os | |
8 | import os.path |
|
8 | import os.path | |
9 | import sys |
|
9 | import sys | |
10 | from importlib import import_module |
|
10 | from importlib import import_module, reload | |
11 |
|
11 | |||
12 | from traitlets.config.configurable import Configurable |
|
12 | from traitlets.config.configurable import Configurable | |
13 | from IPython.utils.path import ensure_dir_exists, compress_user |
|
13 | from IPython.utils.path import ensure_dir_exists, compress_user | |
14 | from IPython.utils.decorators import undoc |
|
14 | from IPython.utils.decorators import undoc | |
15 | from traitlets import Instance |
|
15 | from traitlets import Instance | |
16 |
|
16 | |||
17 | try: |
|
|||
18 | from importlib import reload |
|
|||
19 | except ImportError : |
|
|||
20 | ## deprecated since 3.4 |
|
|||
21 | from imp import reload |
|
|||
22 |
|
17 | |||
23 | #----------------------------------------------------------------------------- |
|
18 | #----------------------------------------------------------------------------- | |
24 | # Main class |
|
19 | # Main class |
@@ -20,7 +20,7 b' import threading' | |||||
20 | from traitlets.config.configurable import LoggingConfigurable |
|
20 | from traitlets.config.configurable import LoggingConfigurable | |
21 | from decorator import decorator |
|
21 | from decorator import decorator | |
22 | from IPython.utils.decorators import undoc |
|
22 | from IPython.utils.decorators import undoc | |
23 |
from IPython. |
|
23 | from IPython.paths import locate_profile | |
24 | from traitlets import ( |
|
24 | from traitlets import ( | |
25 | Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError, |
|
25 | Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError, | |
26 | default, observe, |
|
26 | default, observe, |
@@ -170,7 +170,7 b' class SeparateUnicode(Unicode):' | |||||
170 | class DummyMod(object): |
|
170 | class DummyMod(object): | |
171 | """A dummy module used for IPython's interactive module when |
|
171 | """A dummy module used for IPython's interactive module when | |
172 | a namespace must be assigned to the module's __dict__.""" |
|
172 | a namespace must be assigned to the module's __dict__.""" | |
173 | pass |
|
173 | __spec__ = None | |
174 |
|
174 | |||
175 |
|
175 | |||
176 | class ExecutionInfo(object): |
|
176 | class ExecutionInfo(object): | |
@@ -748,7 +748,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
748 |
|
748 | |||
749 | # executable path should end like /bin/python or \\scripts\\python.exe |
|
749 | # executable path should end like /bin/python or \\scripts\\python.exe | |
750 | p_exe_up2 = os.path.dirname(os.path.dirname(p)) |
|
750 | p_exe_up2 = os.path.dirname(os.path.dirname(p)) | |
751 | if p_exe_up2 and os.path.samefile(p_exe_up2, p_venv): |
|
751 | if p_exe_up2 and os.path.exists(p_venv) and os.path.samefile(p_exe_up2, p_venv): | |
752 | # Our exe is inside the virtualenv, don't need to do anything. |
|
752 | # Our exe is inside the virtualenv, don't need to do anything. | |
753 | return |
|
753 | return | |
754 |
|
754 | |||
@@ -1190,7 +1190,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
1190 | ----- |
|
1190 | ----- | |
1191 | All data structures here are only filled in, they are NOT reset by this |
|
1191 | All data structures here are only filled in, they are NOT reset by this | |
1192 | method. If they were not empty before, data will simply be added to |
|
1192 | method. If they were not empty before, data will simply be added to | |
1193 |
the |
|
1193 | them. | |
1194 | """ |
|
1194 | """ | |
1195 | # This function works in two parts: first we put a few things in |
|
1195 | # This function works in two parts: first we put a few things in | |
1196 | # user_ns, and we sync that contents into user_ns_hidden so that these |
|
1196 | # user_ns, and we sync that contents into user_ns_hidden so that these | |
@@ -2884,7 +2884,6 b' class InteractiveShell(SingletonConfigurable):' | |||||
2884 | """ |
|
2884 | """ | |
2885 | if not nodelist: |
|
2885 | if not nodelist: | |
2886 | return |
|
2886 | return | |
2887 |
|
||||
2888 | if interactivity == 'last_expr_or_assign': |
|
2887 | if interactivity == 'last_expr_or_assign': | |
2889 | if isinstance(nodelist[-1], _assign_nodes): |
|
2888 | if isinstance(nodelist[-1], _assign_nodes): | |
2890 | asg = nodelist[-1] |
|
2889 | asg = nodelist[-1] | |
@@ -2914,7 +2913,6 b' class InteractiveShell(SingletonConfigurable):' | |||||
2914 | to_run_exec, to_run_interactive = [], nodelist |
|
2913 | to_run_exec, to_run_interactive = [], nodelist | |
2915 | else: |
|
2914 | else: | |
2916 | raise ValueError("Interactivity was %r" % interactivity) |
|
2915 | raise ValueError("Interactivity was %r" % interactivity) | |
2917 |
|
||||
2918 | try: |
|
2916 | try: | |
2919 | for i, node in enumerate(to_run_exec): |
|
2917 | for i, node in enumerate(to_run_exec): | |
2920 | mod = ast.Module([node]) |
|
2918 | mod = ast.Module([node]) |
@@ -302,21 +302,6 b' Currently the magic system has the following functions:""",' | |||||
302 | print('Object `%s` not found' % oname) |
|
302 | print('Object `%s` not found' % oname) | |
303 |
|
303 | |||
304 | @line_magic |
|
304 | @line_magic | |
305 | def profile(self, parameter_s=''): |
|
|||
306 | """DEPRECATED since IPython 2.0. |
|
|||
307 |
|
||||
308 | Raise `UsageError`. To profile code use the :magic:`prun` magic. |
|
|||
309 |
|
||||
310 |
|
||||
311 | See Also |
|
|||
312 | -------- |
|
|||
313 | prun : run code using the Python profiler (:magic:`prun`) |
|
|||
314 | """ |
|
|||
315 | raise UsageError("The `%profile` magic has been deprecated since IPython 2.0. " |
|
|||
316 | "and removed in IPython 6.0. Please use the value of `get_ipython().profile` instead " |
|
|||
317 | "to see current profile in use. Perhaps you meant to use `%prun` to profile code?") |
|
|||
318 |
|
||||
319 | @line_magic |
|
|||
320 | def pprint(self, parameter_s=''): |
|
305 | def pprint(self, parameter_s=''): | |
321 | """Toggle pretty printing on/off.""" |
|
306 | """Toggle pretty printing on/off.""" | |
322 | ptformatter = self.shell.display_formatter.formatters['text/plain'] |
|
307 | ptformatter = self.shell.display_formatter.formatters['text/plain'] |
@@ -20,6 +20,8 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 | |||
|
24 | from urllib.parse import urlencode | |||
23 |
|
25 | |||
24 | # Our own packages |
|
26 | # Our own packages | |
25 | from IPython.core.error import TryNext, StdinNotImplementedError, UsageError |
|
27 | from IPython.core.error import TryNext, StdinNotImplementedError, UsageError | |
@@ -244,7 +246,7 b' class CodeMagics(Magics):' | |||||
244 |
|
246 | |||
245 | @line_magic |
|
247 | @line_magic | |
246 | def pastebin(self, parameter_s=''): |
|
248 | def pastebin(self, parameter_s=''): | |
247 |
"""Upload code to |
|
249 | """Upload code to dpaste's paste bin, returning the URL. | |
248 |
|
250 | |||
249 | Usage:\\ |
|
251 | Usage:\\ | |
250 | %pastebin [-d "Custom description"] 1-7 |
|
252 | %pastebin [-d "Custom description"] 1-7 | |
@@ -265,25 +267,14 b' class CodeMagics(Magics):' | |||||
265 | print(e.args[0]) |
|
267 | print(e.args[0]) | |
266 | return |
|
268 | return | |
267 |
|
269 | |||
268 | # Deferred import |
|
270 | post_data = urlencode({ | |
269 | try: |
|
271 | "title": opts.get('d', "Pasted from IPython"), | |
270 | from urllib.request import urlopen # Py 3 |
|
272 | "syntax": "python3", | |
271 | except ImportError: |
|
273 | "content": code | |
272 | from urllib2 import urlopen |
|
|||
273 | import json |
|
|||
274 | post_data = json.dumps({ |
|
|||
275 | "description": opts.get('d', "Pasted from IPython"), |
|
|||
276 | "public": True, |
|
|||
277 | "files": { |
|
|||
278 | "file1.py": { |
|
|||
279 | "content": code |
|
|||
280 | } |
|
|||
281 | } |
|
|||
282 | }).encode('utf-8') |
|
274 | }).encode('utf-8') | |
283 |
|
275 | |||
284 |
response = urlopen("http |
|
276 | response = urlopen("http://dpaste.com/api/v2/", post_data) | |
285 | response_data = json.loads(response.read().decode('utf-8')) |
|
277 | return response.headers.get('Location') | |
286 | return response_data['html_url'] |
|
|||
287 |
|
278 | |||
288 | @line_magic |
|
279 | @line_magic | |
289 | def loadpy(self, arg_s): |
|
280 | def loadpy(self, arg_s): |
@@ -110,7 +110,6 b' class TimeitResult(object):' | |||||
110 | p.text(u'<TimeitResult : '+unic+u'>') |
|
110 | p.text(u'<TimeitResult : '+unic+u'>') | |
111 |
|
111 | |||
112 |
|
112 | |||
113 |
|
||||
114 | class TimeitTemplateFiller(ast.NodeTransformer): |
|
113 | class TimeitTemplateFiller(ast.NodeTransformer): | |
115 | """Fill in the AST template for timing execution. |
|
114 | """Fill in the AST template for timing execution. | |
116 |
|
115 |
@@ -31,14 +31,14 b' def script_args(f):' | |||||
31 | '--out', type=str, |
|
31 | '--out', type=str, | |
32 | help="""The variable in which to store stdout from the script. |
|
32 | help="""The variable in which to store stdout from the script. | |
33 | If the script is backgrounded, this will be the stdout *pipe*, |
|
33 | If the script is backgrounded, this will be the stdout *pipe*, | |
34 | instead of the stderr text itself. |
|
34 | instead of the stderr text itself and will not be auto closed. | |
35 | """ |
|
35 | """ | |
36 | ), |
|
36 | ), | |
37 | magic_arguments.argument( |
|
37 | magic_arguments.argument( | |
38 | '--err', type=str, |
|
38 | '--err', type=str, | |
39 | help="""The variable in which to store stderr from the script. |
|
39 | help="""The variable in which to store stderr from the script. | |
40 | If the script is backgrounded, this will be the stderr *pipe*, |
|
40 | If the script is backgrounded, this will be the stderr *pipe*, | |
41 | instead of the stderr text itself. |
|
41 | instead of the stderr text itself and will not be autoclosed. | |
42 | """ |
|
42 | """ | |
43 | ), |
|
43 | ), | |
44 | magic_arguments.argument( |
|
44 | magic_arguments.argument( | |
@@ -187,11 +187,16 b' class ScriptMagics(Magics):' | |||||
187 | if args.bg: |
|
187 | if args.bg: | |
188 | self.bg_processes.append(p) |
|
188 | self.bg_processes.append(p) | |
189 | self._gc_bg_processes() |
|
189 | self._gc_bg_processes() | |
|
190 | to_close = [] | |||
190 | if args.out: |
|
191 | if args.out: | |
191 | self.shell.user_ns[args.out] = p.stdout |
|
192 | self.shell.user_ns[args.out] = p.stdout | |
|
193 | else: | |||
|
194 | to_close.append(p.stdout) | |||
192 | if args.err: |
|
195 | if args.err: | |
193 | self.shell.user_ns[args.err] = p.stderr |
|
196 | self.shell.user_ns[args.err] = p.stderr | |
194 | self.job_manager.new(self._run_script, p, cell, daemon=True) |
|
197 | else: | |
|
198 | to_close.append(p.stderr) | |||
|
199 | self.job_manager.new(self._run_script, p, cell, to_close, daemon=True) | |||
195 | if args.proc: |
|
200 | if args.proc: | |
196 | self.shell.user_ns[args.proc] = p |
|
201 | self.shell.user_ns[args.proc] = p | |
197 | return |
|
202 | return | |
@@ -231,10 +236,12 b' class ScriptMagics(Magics):' | |||||
231 | sys.stderr.write(err) |
|
236 | sys.stderr.write(err) | |
232 | sys.stderr.flush() |
|
237 | sys.stderr.flush() | |
233 |
|
238 | |||
234 | def _run_script(self, p, cell): |
|
239 | def _run_script(self, p, cell, to_close): | |
235 | """callback for running the script in the background""" |
|
240 | """callback for running the script in the background""" | |
236 | p.stdin.write(cell) |
|
241 | p.stdin.write(cell) | |
237 | p.stdin.close() |
|
242 | p.stdin.close() | |
|
243 | for s in to_close: | |||
|
244 | s.close() | |||
238 | p.wait() |
|
245 | p.wait() | |
239 |
|
246 | |||
240 | @line_magic("killbgscripts") |
|
247 | @line_magic("killbgscripts") |
@@ -46,6 +46,9 b" backend2gui['CocoaAgg'] = 'osx'" | |||||
46 | # And some backends that don't need GUI integration |
|
46 | # And some backends that don't need GUI integration | |
47 | del backend2gui['nbAgg'] |
|
47 | del backend2gui['nbAgg'] | |
48 | del backend2gui['agg'] |
|
48 | del backend2gui['agg'] | |
|
49 | del backend2gui['svg'] | |||
|
50 | del backend2gui['pdf'] | |||
|
51 | del backend2gui['ps'] | |||
49 | del backend2gui['module://ipykernel.pylab.backend_inline'] |
|
52 | del backend2gui['module://ipykernel.pylab.backend_inline'] | |
50 |
|
53 | |||
51 | #----------------------------------------------------------------------------- |
|
54 | #----------------------------------------------------------------------------- |
@@ -19,12 +19,12 b" name = 'ipython'" | |||||
19 | # IPython version information. An empty _version_extra corresponds to a full |
|
19 | # IPython version information. An empty _version_extra corresponds to a full | |
20 | # release. 'dev' as a _version_extra string means this is a development |
|
20 | # release. 'dev' as a _version_extra string means this is a development | |
21 | # version |
|
21 | # version | |
22 |
_version_major = |
|
22 | _version_major = 7 | |
23 |
_version_minor = |
|
23 | _version_minor = 0 | |
24 | _version_patch = 0 |
|
24 | _version_patch = 0 | |
25 | _version_extra = '.dev' |
|
25 | _version_extra = '.dev' | |
26 | # _version_extra = 'rc2' |
|
26 | # _version_extra = 'rc2' | |
27 | #_version_extra = '' # Uncomment this for full releases |
|
27 | # _version_extra = '' # Uncomment this for full releases | |
28 |
|
28 | |||
29 | # Construct full version string from these. |
|
29 | # Construct full version string from these. | |
30 | _ver = [_version_major, _version_minor, _version_patch] |
|
30 | _ver = [_version_major, _version_minor, _version_patch] |
@@ -14,7 +14,6 b' from IPython.testing.globalipapp import get_ipython' | |||||
14 | ip = get_ipython() |
|
14 | ip = get_ipython() | |
15 |
|
15 | |||
16 |
|
16 | |||
17 | @py3compat.doctest_refactor_print |
|
|||
18 | def doctest_autocall(): |
|
17 | def doctest_autocall(): | |
19 | """ |
|
18 | """ | |
20 | In [1]: def f1(a,b,c): |
|
19 | In [1]: def f1(a,b,c): | |
@@ -39,7 +38,7 b' def doctest_autocall():' | |||||
39 |
|
38 | |||
40 | In [7]: assert _ == 'abc' |
|
39 | In [7]: assert _ == 'abc' | |
41 |
|
40 | |||
42 |
In [8]: print |
|
41 | In [8]: print(_) | |
43 | abc |
|
42 | abc | |
44 |
|
43 | |||
45 | In [9]: /f1 1,2,3 |
|
44 | In [9]: /f1 1,2,3 |
@@ -316,13 +316,17 b' def test_jedi():' | |||||
316 | start = start if start is not None else l |
|
316 | start = start if start is not None else l | |
317 | end = end if end is not None else l |
|
317 | end = end if end is not None else l | |
318 | with provisionalcompleter(): |
|
318 | with provisionalcompleter(): | |
|
319 | ip.Completer.use_jedi = True | |||
319 | completions = set(ip.Completer.completions(s, l)) |
|
320 | completions = set(ip.Completer.completions(s, l)) | |
|
321 | ip.Completer.use_jedi = False | |||
320 | assert_in(Completion(start, end, comp), completions, reason) |
|
322 | assert_in(Completion(start, end, comp), completions, reason) | |
321 |
|
323 | |||
322 | def _test_not_complete(reason, s, comp): |
|
324 | def _test_not_complete(reason, s, comp): | |
323 | l = len(s) |
|
325 | l = len(s) | |
324 | with provisionalcompleter(): |
|
326 | with provisionalcompleter(): | |
|
327 | ip.Completer.use_jedi = True | |||
325 | completions = set(ip.Completer.completions(s, l)) |
|
328 | completions = set(ip.Completer.completions(s, l)) | |
|
329 | ip.Completer.use_jedi = False | |||
326 | assert_not_in(Completion(l, l, comp), completions, reason) |
|
330 | assert_not_in(Completion(l, l, comp), completions, reason) | |
327 |
|
331 | |||
328 | import jedi |
|
332 | import jedi | |
@@ -341,8 +345,10 b' def test_completion_have_signature():' | |||||
341 | """ |
|
345 | """ | |
342 | ip = get_ipython() |
|
346 | ip = get_ipython() | |
343 | with provisionalcompleter(): |
|
347 | with provisionalcompleter(): | |
|
348 | ip.Completer.use_jedi = True | |||
344 | completions = ip.Completer.completions('ope', 3) |
|
349 | completions = ip.Completer.completions('ope', 3) | |
345 | c = next(completions) # should be `open` |
|
350 | c = next(completions) # should be `open` | |
|
351 | ip.Completer.use_jedi = False | |||
346 | assert 'file' in c.signature, "Signature of function was not found by completer" |
|
352 | assert 'file' in c.signature, "Signature of function was not found by completer" | |
347 | assert 'encoding' in c.signature, "Signature of function was not found by completer" |
|
353 | assert 'encoding' in c.signature, "Signature of function was not found by completer" | |
348 |
|
354 | |||
@@ -357,7 +363,9 b' def test_deduplicate_completions():' | |||||
357 | zoo = 1 |
|
363 | zoo = 1 | |
358 | ''')) |
|
364 | ''')) | |
359 | with provisionalcompleter(): |
|
365 | with provisionalcompleter(): | |
|
366 | ip.Completer.use_jedi = True | |||
360 | l = list(_deduplicate_completions('Z.z', ip.Completer.completions('Z.z', 3))) |
|
367 | l = list(_deduplicate_completions('Z.z', ip.Completer.completions('Z.z', 3))) | |
|
368 | ip.Completer.use_jedi = False | |||
361 |
|
369 | |||
362 | assert len(l) == 1, 'Completions (Z.z<tab>) correctly deduplicate: %s ' % l |
|
370 | assert len(l) == 1, 'Completions (Z.z<tab>) correctly deduplicate: %s ' % l | |
363 | assert l[0].text == 'zoo' # and not `it.accumulate` |
|
371 | assert l[0].text == 'zoo' # and not `it.accumulate` | |
@@ -412,10 +420,10 b' def test_omit__names():' | |||||
412 | nt.assert_in('ip.__str__', matches) |
|
420 | nt.assert_in('ip.__str__', matches) | |
413 | nt.assert_in('ip._hidden_attr', matches) |
|
421 | nt.assert_in('ip._hidden_attr', matches) | |
414 |
|
422 | |||
415 | c.use_jedi = True |
|
423 | # c.use_jedi = True | |
416 | completions = set(c.completions('ip.', 3)) |
|
424 | # completions = set(c.completions('ip.', 3)) | |
417 | nt.assert_in(Completion(3, 3, '__str__'), completions) |
|
425 | # nt.assert_in(Completion(3, 3, '__str__'), completions) | |
418 | nt.assert_in(Completion(3,3, "_hidden_attr"), completions) |
|
426 | # nt.assert_in(Completion(3,3, "_hidden_attr"), completions) | |
419 |
|
427 | |||
420 |
|
428 | |||
421 | cfg = Config() |
|
429 | cfg = Config() | |
@@ -427,10 +435,10 b' def test_omit__names():' | |||||
427 | nt.assert_not_in('ip.__str__', matches) |
|
435 | nt.assert_not_in('ip.__str__', matches) | |
428 | # nt.assert_in('ip._hidden_attr', matches) |
|
436 | # nt.assert_in('ip._hidden_attr', matches) | |
429 |
|
437 | |||
430 | c.use_jedi = True |
|
438 | # c.use_jedi = True | |
431 | completions = set(c.completions('ip.', 3)) |
|
439 | # completions = set(c.completions('ip.', 3)) | |
432 | nt.assert_not_in(Completion(3,3,'__str__'), completions) |
|
440 | # nt.assert_not_in(Completion(3,3,'__str__'), completions) | |
433 | nt.assert_in(Completion(3,3, "_hidden_attr"), completions) |
|
441 | # nt.assert_in(Completion(3,3, "_hidden_attr"), completions) | |
434 |
|
442 | |||
435 | cfg = Config() |
|
443 | cfg = Config() | |
436 | cfg.IPCompleter.omit__names = 2 |
|
444 | cfg.IPCompleter.omit__names = 2 | |
@@ -441,19 +449,19 b' def test_omit__names():' | |||||
441 | nt.assert_not_in('ip.__str__', matches) |
|
449 | nt.assert_not_in('ip.__str__', matches) | |
442 | nt.assert_not_in('ip._hidden_attr', matches) |
|
450 | nt.assert_not_in('ip._hidden_attr', matches) | |
443 |
|
451 | |||
444 | c.use_jedi = True |
|
452 | # c.use_jedi = True | |
445 | completions = set(c.completions('ip.', 3)) |
|
453 | # completions = set(c.completions('ip.', 3)) | |
446 | nt.assert_not_in(Completion(3,3,'__str__'), completions) |
|
454 | # nt.assert_not_in(Completion(3,3,'__str__'), completions) | |
447 | nt.assert_not_in(Completion(3,3, "_hidden_attr"), completions) |
|
455 | # nt.assert_not_in(Completion(3,3, "_hidden_attr"), completions) | |
448 |
|
456 | |||
449 | with provisionalcompleter(): |
|
457 | with provisionalcompleter(): | |
450 | c.use_jedi = False |
|
458 | c.use_jedi = False | |
451 | s,matches = c.complete('ip._x.') |
|
459 | s,matches = c.complete('ip._x.') | |
452 | nt.assert_in('ip._x.keys', matches) |
|
460 | nt.assert_in('ip._x.keys', matches) | |
453 |
|
461 | |||
454 | c.use_jedi = True |
|
462 | # c.use_jedi = True | |
455 | completions = set(c.completions('ip._x.', 6)) |
|
463 | # completions = set(c.completions('ip._x.', 6)) | |
456 | nt.assert_in(Completion(6,6, "keys"), completions) |
|
464 | # nt.assert_in(Completion(6,6, "keys"), completions) | |
457 |
|
465 | |||
458 | del ip._hidden_attr |
|
466 | del ip._hidden_attr | |
459 | del ip._x |
|
467 | del ip._x |
@@ -275,6 +275,10 b' def test_video_embedding():' | |||||
275 | html = v._repr_html_() |
|
275 | html = v._repr_html_() | |
276 | nt.assert_in('src="data:video/xyz;base64,YWJj"',html) |
|
276 | nt.assert_in('src="data:video/xyz;base64,YWJj"',html) | |
277 |
|
277 | |||
|
278 | def test_html_metadata(): | |||
|
279 | s = "<h1>Test</h1>" | |||
|
280 | h = display.HTML(s, metadata={"isolated": True}) | |||
|
281 | nt.assert_equal(h._repr_html_(), (s, {"isolated": True})) | |||
278 |
|
282 | |||
279 | def test_display_id(): |
|
283 | def test_display_id(): | |
280 | ip = get_ipython() |
|
284 | ip = get_ipython() |
@@ -1,4 +1,7 b'' | |||||
|
1 | import sys | |||
1 | from IPython.testing.tools import AssertPrints, AssertNotPrints |
|
2 | from IPython.testing.tools import AssertPrints, AssertNotPrints | |
|
3 | from IPython.core.displayhook import CapturingDisplayHook | |||
|
4 | from IPython.utils.capture import CapturedIO | |||
2 |
|
5 | |||
3 | ip = get_ipython() |
|
6 | ip = get_ipython() | |
4 |
|
7 | |||
@@ -101,3 +104,11 b' def test_interactivehooks_ast_modes_semi_supress():' | |||||
101 |
|
104 | |||
102 | finally: |
|
105 | finally: | |
103 | ip.ast_node_interactivity = saved_mode |
|
106 | ip.ast_node_interactivity = saved_mode | |
|
107 | ||||
|
108 | def test_capture_display_hook_format(): | |||
|
109 | """Tests that the capture display hook conforms to the CapturedIO output format""" | |||
|
110 | hook = CapturingDisplayHook(ip) | |||
|
111 | hook({"foo": "bar"}) | |||
|
112 | captured = CapturedIO(sys.stdout, sys.stderr, hook.outputs) | |||
|
113 | # Should not raise with RichOutput transformation error | |||
|
114 | captured.outputs |
@@ -72,7 +72,7 b' In [4]: run simpleerr.py' | |||||
72 | --------------------------------------------------------------------------- |
|
72 | --------------------------------------------------------------------------- | |
73 | ZeroDivisionError Traceback (most recent call last) |
|
73 | ZeroDivisionError Traceback (most recent call last) | |
74 | <BLANKLINE> |
|
74 | <BLANKLINE> | |
75 |
... in <module> |
|
75 | ... in <module> | |
76 | 30 mode = 'div' |
|
76 | 30 mode = 'div' | |
77 | 31 |
|
77 | 31 | |
78 | ---> 32 bar(mode) |
|
78 | ---> 32 bar(mode) | |
@@ -104,7 +104,7 b' In [6]: run simpleerr.py' | |||||
104 | --------------------------------------------------------------------------- |
|
104 | --------------------------------------------------------------------------- | |
105 | ZeroDivisionError Traceback (most recent call last) |
|
105 | ZeroDivisionError Traceback (most recent call last) | |
106 | <BLANKLINE> |
|
106 | <BLANKLINE> | |
107 |
... in <module> |
|
107 | ... in <module> | |
108 | 30 mode = 'div' |
|
108 | 30 mode = 'div' | |
109 | 31 |
|
109 | 31 | |
110 | ---> 32 bar(mode) |
|
110 | ---> 32 bar(mode) | |
@@ -161,7 +161,7 b' In [22]: %tb' | |||||
161 | --------------------------------------------------------------------------- |
|
161 | --------------------------------------------------------------------------- | |
162 | SystemExit Traceback (most recent call last) |
|
162 | SystemExit Traceback (most recent call last) | |
163 | <BLANKLINE> |
|
163 | <BLANKLINE> | |
164 |
...<module> |
|
164 | ...<module> | |
165 | 30 mode = 'div' |
|
165 | 30 mode = 'div' | |
166 | 31 |
|
166 | 31 | |
167 | ---> 32 bar(mode) |
|
167 | ---> 32 bar(mode) | |
@@ -189,7 +189,7 b' In [24]: %tb' | |||||
189 | --------------------------------------------------------------------------- |
|
189 | --------------------------------------------------------------------------- | |
190 | SystemExit Traceback (most recent call last) |
|
190 | SystemExit Traceback (most recent call last) | |
191 | <BLANKLINE> |
|
191 | <BLANKLINE> | |
192 |
... in <module> |
|
192 | ... in <module> | |
193 | 30 mode = 'div' |
|
193 | 30 mode = 'div' | |
194 | 31 |
|
194 | 31 | |
195 | ---> 32 bar(mode) |
|
195 | ---> 32 bar(mode) |
@@ -26,7 +26,6 b' from IPython.core.magic import (Magics, magics_class, line_magic,' | |||||
26 | from IPython.core.magics import execution, script, code, logging |
|
26 | from IPython.core.magics import execution, script, code, logging | |
27 | from IPython.testing import decorators as dec |
|
27 | from IPython.testing import decorators as dec | |
28 | from IPython.testing import tools as tt |
|
28 | from IPython.testing import tools as tt | |
29 | from IPython.utils import py3compat |
|
|||
30 | from IPython.utils.io import capture_output |
|
29 | from IPython.utils.io import capture_output | |
31 | from IPython.utils.tempdir import TemporaryDirectory |
|
30 | from IPython.utils.tempdir import TemporaryDirectory | |
32 | from IPython.utils.process import find_cmd |
|
31 | from IPython.utils.process import find_cmd | |
@@ -304,12 +303,10 b' def test_macro_run():' | |||||
304 | """Test that we can run a multi-line macro successfully.""" |
|
303 | """Test that we can run a multi-line macro successfully.""" | |
305 | ip = get_ipython() |
|
304 | ip = get_ipython() | |
306 | ip.history_manager.reset() |
|
305 | ip.history_manager.reset() | |
307 |
cmds = ["a=10", "a+=1", |
|
306 | cmds = ["a=10", "a+=1", "print(a)", "%macro test 2-3"] | |
308 | "%macro test 2-3"] |
|
|||
309 | for cmd in cmds: |
|
307 | for cmd in cmds: | |
310 | ip.run_cell(cmd, store_history=True) |
|
308 | ip.run_cell(cmd, store_history=True) | |
311 | nt.assert_equal(ip.user_ns["test"].value, |
|
309 | nt.assert_equal(ip.user_ns["test"].value, "a+=1\nprint(a)\n") | |
312 | py3compat.doctest_refactor_print("a+=1\nprint a\n")) |
|
|||
313 | with tt.AssertPrints("12"): |
|
310 | with tt.AssertPrints("12"): | |
314 | ip.run_cell("test") |
|
311 | ip.run_cell("test") | |
315 | with tt.AssertPrints("13"): |
|
312 | with tt.AssertPrints("13"): | |
@@ -532,7 +529,6 b' def test_whos():' | |||||
532 | _ip.user_ns['a'] = A() |
|
529 | _ip.user_ns['a'] = A() | |
533 | _ip.magic("whos") |
|
530 | _ip.magic("whos") | |
534 |
|
531 | |||
535 | @py3compat.u_format |
|
|||
536 | def doctest_precision(): |
|
532 | def doctest_precision(): | |
537 | """doctest for %precision |
|
533 | """doctest for %precision | |
538 |
|
534 | |||
@@ -566,11 +562,6 b' def test_timeit_shlex():' | |||||
566 | _ip.magic('timeit -r1 -n1 f("a " + "b ")') |
|
562 | _ip.magic('timeit -r1 -n1 f("a " + "b ")') | |
567 |
|
563 | |||
568 |
|
564 | |||
569 | def test_timeit_arguments(): |
|
|||
570 | "Test valid timeit arguments, should not cause SyntaxError (GH #1269)" |
|
|||
571 | _ip.magic("timeit ('#')") |
|
|||
572 |
|
||||
573 |
|
||||
574 | def test_timeit_special_syntax(): |
|
565 | def test_timeit_special_syntax(): | |
575 | "Test %%timeit with IPython special syntax" |
|
566 | "Test %%timeit with IPython special syntax" | |
576 | @register_line_magic |
|
567 | @register_line_magic | |
@@ -837,13 +828,16 b' def test_script_out_err():' | |||||
837 | def test_script_bg_out(): |
|
828 | def test_script_bg_out(): | |
838 | ip = get_ipython() |
|
829 | ip = get_ipython() | |
839 | ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'") |
|
830 | ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'") | |
|
831 | ||||
840 | nt.assert_equal(ip.user_ns['output'].read(), b'hi\n') |
|
832 | nt.assert_equal(ip.user_ns['output'].read(), b'hi\n') | |
|
833 | ip.user_ns['output'].close() | |||
841 |
|
834 | |||
842 | @dec.skip_win32 |
|
835 | @dec.skip_win32 | |
843 | def test_script_bg_err(): |
|
836 | def test_script_bg_err(): | |
844 | ip = get_ipython() |
|
837 | ip = get_ipython() | |
845 | ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2") |
|
838 | ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2") | |
846 | nt.assert_equal(ip.user_ns['error'].read(), b'hello\n') |
|
839 | nt.assert_equal(ip.user_ns['error'].read(), b'hello\n') | |
|
840 | ip.user_ns['error'].close() | |||
847 |
|
841 | |||
848 | @dec.skip_win32 |
|
842 | @dec.skip_win32 | |
849 | def test_script_bg_out_err(): |
|
843 | def test_script_bg_out_err(): | |
@@ -851,6 +845,8 b' def test_script_bg_out_err():' | |||||
851 | ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2") |
|
845 | ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2") | |
852 | nt.assert_equal(ip.user_ns['output'].read(), b'hi\n') |
|
846 | nt.assert_equal(ip.user_ns['output'].read(), b'hi\n') | |
853 | nt.assert_equal(ip.user_ns['error'].read(), b'hello\n') |
|
847 | nt.assert_equal(ip.user_ns['error'].read(), b'hello\n') | |
|
848 | ip.user_ns['output'].close() | |||
|
849 | ip.user_ns['error'].close() | |||
854 |
|
850 | |||
855 | def test_script_defaults(): |
|
851 | def test_script_defaults(): | |
856 | ip = get_ipython() |
|
852 | ip = get_ipython() | |
@@ -1070,4 +1066,15 b' def test_logging_magic_not_quiet():' | |||||
1070 | lm.logstart(os.path.join(td, "not_quiet.log")) |
|
1066 | lm.logstart(os.path.join(td, "not_quiet.log")) | |
1071 | finally: |
|
1067 | finally: | |
1072 | _ip.logger.logstop() |
|
1068 | _ip.logger.logstop() | |
1073 |
|
1069 | |||
|
1070 | ## | |||
|
1071 | # this is slow, put at the end for local testing. | |||
|
1072 | ## | |||
|
1073 | def test_timeit_arguments(): | |||
|
1074 | "Test valid timeit arguments, should not cause SyntaxError (GH #1269)" | |||
|
1075 | if sys.version_info < (3,7): | |||
|
1076 | _ip.magic("timeit ('#')") | |||
|
1077 | else: | |||
|
1078 | # 3.7 optimize no-op statement like above out, and complain there is | |||
|
1079 | # nothing in the for loop. | |||
|
1080 | _ip.magic("timeit a=('#')") |
@@ -430,8 +430,5 b' def test_init_colors():' | |||||
430 | def test_builtin_init(): |
|
430 | def test_builtin_init(): | |
431 | info = inspector.info(list) |
|
431 | info = inspector.info(list) | |
432 | init_def = info['init_definition'] |
|
432 | init_def = info['init_definition'] | |
433 | # Python < 3.4 can't get init definition from builtins, |
|
433 | nt.assert_is_not_none(init_def) | |
434 | # but still exercise the inspection in case of error-raising bugs. |
|
|||
435 | if sys.version_info >= (3,4): |
|
|||
436 | nt.assert_is_not_none(init_def) |
|
|||
437 |
|
434 |
@@ -34,7 +34,6 b' from IPython.core.profiledir import ProfileDir' | |||||
34 |
|
34 | |||
35 | from IPython.testing import decorators as dec |
|
35 | from IPython.testing import decorators as dec | |
36 | from IPython.testing import tools as tt |
|
36 | from IPython.testing import tools as tt | |
37 | from IPython.utils import py3compat |
|
|||
38 | from IPython.utils.process import getoutput |
|
37 | from IPython.utils.process import getoutput | |
39 | from IPython.utils.tempdir import TemporaryDirectory |
|
38 | from IPython.utils.tempdir import TemporaryDirectory | |
40 |
|
39 | |||
@@ -100,15 +99,14 b' class ProfileStartupTest(TestCase):' | |||||
100 | f.write(startup) |
|
99 | f.write(startup) | |
101 | # write simple test file, to check that the startup file was run |
|
100 | # write simple test file, to check that the startup file was run | |
102 | with open(self.fname, 'w') as f: |
|
101 | with open(self.fname, 'w') as f: | |
103 | f.write(py3compat.doctest_refactor_print(test)) |
|
102 | f.write(test) | |
104 |
|
103 | |||
105 | def validate(self, output): |
|
104 | def validate(self, output): | |
106 | tt.ipexec_validate(self.fname, output, '', options=self.options) |
|
105 | tt.ipexec_validate(self.fname, output, '', options=self.options) | |
107 |
|
106 | |||
108 | @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows") |
|
107 | @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows") | |
109 | def test_startup_py(self): |
|
108 | def test_startup_py(self): | |
110 | self.init('00-start.py', 'zzz=123\n', |
|
109 | self.init('00-start.py', 'zzz=123\n', 'print(zzz)\n') | |
111 | py3compat.doctest_refactor_print('print zzz\n')) |
|
|||
112 | self.validate('123') |
|
110 | self.validate('123') | |
113 |
|
111 | |||
114 | @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows") |
|
112 | @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows") |
@@ -105,7 +105,7 b' def test_select_figure_formats_kwargs():' | |||||
105 | f = formatter.lookup_by_type(Figure) |
|
105 | f = formatter.lookup_by_type(Figure) | |
106 | cell = f.__closure__[0].cell_contents |
|
106 | cell = f.__closure__[0].cell_contents | |
107 | nt.assert_equal(cell, kwargs) |
|
107 | nt.assert_equal(cell, kwargs) | |
108 |
|
108 | |||
109 | # check that the formatter doesn't raise |
|
109 | # check that the formatter doesn't raise | |
110 | fig = plt.figure() |
|
110 | fig = plt.figure() | |
111 | ax = fig.add_subplot(1,1,1) |
|
111 | ax = fig.add_subplot(1,1,1) | |
@@ -150,7 +150,7 b' class TestPylabSwitch(object):' | |||||
150 | class Shell(InteractiveShell): |
|
150 | class Shell(InteractiveShell): | |
151 | def enable_gui(self, gui): |
|
151 | def enable_gui(self, gui): | |
152 | pass |
|
152 | pass | |
153 |
|
153 | |||
154 | def setup(self): |
|
154 | def setup(self): | |
155 | import matplotlib |
|
155 | import matplotlib | |
156 | def act_mpl(backend): |
|
156 | def act_mpl(backend): | |
@@ -244,3 +244,7 b' class TestPylabSwitch(object):' | |||||
244 | nt.assert_equal(gui, 'qt') |
|
244 | nt.assert_equal(gui, 'qt') | |
245 | nt.assert_equal(s.pylab_gui_select, 'qt') |
|
245 | nt.assert_equal(s.pylab_gui_select, 'qt') | |
246 |
|
246 | |||
|
247 | ||||
|
248 | def test_no_gui_backends(): | |||
|
249 | for k in ['agg', 'svg', 'pdf', 'ps']: | |||
|
250 | assert k not in pt.backend2gui |
@@ -31,7 +31,6 b' from nose import SkipTest' | |||||
31 |
|
31 | |||
32 | from IPython.testing import decorators as dec |
|
32 | from IPython.testing import decorators as dec | |
33 | from IPython.testing import tools as tt |
|
33 | from IPython.testing import tools as tt | |
34 | from IPython.utils import py3compat |
|
|||
35 | from IPython.utils.io import capture_output |
|
34 | from IPython.utils.io import capture_output | |
36 | from IPython.utils.tempdir import TemporaryDirectory |
|
35 | from IPython.utils.tempdir import TemporaryDirectory | |
37 | from IPython.core import debugger |
|
36 | from IPython.core import debugger | |
@@ -145,13 +144,12 b' def doctest_run_option_parser_for_windows():' | |||||
145 | """ |
|
144 | """ | |
146 |
|
145 | |||
147 |
|
146 | |||
148 | @py3compat.doctest_refactor_print |
|
|||
149 | def doctest_reset_del(): |
|
147 | def doctest_reset_del(): | |
150 | """Test that resetting doesn't cause errors in __del__ methods. |
|
148 | """Test that resetting doesn't cause errors in __del__ methods. | |
151 |
|
149 | |||
152 | In [2]: class A(object): |
|
150 | In [2]: class A(object): | |
153 | ...: def __del__(self): |
|
151 | ...: def __del__(self): | |
154 |
...: print |
|
152 | ...: print(str("Hi")) | |
155 | ...: |
|
153 | ...: | |
156 |
|
154 | |||
157 | In [3]: a = A() |
|
155 | In [3]: a = A() | |
@@ -248,9 +246,9 b' class TestMagicRunSimple(tt.TempFileMixin):' | |||||
248 | raise SkipTest("Test requires pywin32") |
|
246 | raise SkipTest("Test requires pywin32") | |
249 | src = ("class A(object):\n" |
|
247 | src = ("class A(object):\n" | |
250 | " def __del__(self):\n" |
|
248 | " def __del__(self):\n" | |
251 |
" print |
|
249 | " print('object A deleted')\n" | |
252 | "a = A()\n") |
|
250 | "a = A()\n") | |
253 | self.mktmp(py3compat.doctest_refactor_print(src)) |
|
251 | self.mktmp(src) | |
254 | if dec.module_not_available('sqlite3'): |
|
252 | if dec.module_not_available('sqlite3'): | |
255 | err = 'WARNING: IPython History requires SQLite, your history will not be saved\n' |
|
253 | err = 'WARNING: IPython History requires SQLite, your history will not be saved\n' | |
256 | else: |
|
254 | else: |
@@ -116,13 +116,15 b' from IPython.core import debugger' | |||||
116 | from IPython.core.display_trap import DisplayTrap |
|
116 | from IPython.core.display_trap import DisplayTrap | |
117 | from IPython.core.excolors import exception_colors |
|
117 | from IPython.core.excolors import exception_colors | |
118 | from IPython.utils import PyColorize |
|
118 | from IPython.utils import PyColorize | |
119 | from IPython.utils import openpy |
|
|||
120 | from IPython.utils import path as util_path |
|
119 | from IPython.utils import path as util_path | |
121 | from IPython.utils import py3compat |
|
120 | from IPython.utils import py3compat | |
122 | from IPython.utils.data import uniq_stable |
|
121 | from IPython.utils.data import uniq_stable | |
123 | from IPython.utils.terminal import get_terminal_size |
|
122 | from IPython.utils.terminal import get_terminal_size | |
|
123 | ||||
124 | from logging import info, error, debug |
|
124 | from logging import info, error, debug | |
125 |
|
125 | |||
|
126 | from importlib.util import source_from_cache | |||
|
127 | ||||
126 | import IPython.utils.colorable as colorable |
|
128 | import IPython.utils.colorable as colorable | |
127 |
|
129 | |||
128 | # Globals |
|
130 | # Globals | |
@@ -374,16 +376,32 b' def _fixed_getinnerframes(etb, context=1, tb_offset=0):' | |||||
374 | # (SyntaxErrors have to be treated specially because they have no traceback) |
|
376 | # (SyntaxErrors have to be treated specially because they have no traceback) | |
375 |
|
377 | |||
376 |
|
378 | |||
377 |
def _format_traceback_lines(lnum, index, lines, Colors, lvals |
|
379 | def _format_traceback_lines(lnum, index, lines, Colors, lvals, _line_format): | |
|
380 | """ | |||
|
381 | Format tracebacks lines with pointing arrow, leading numbers... | |||
|
382 | ||||
|
383 | Parameters | |||
|
384 | ========== | |||
|
385 | ||||
|
386 | lnum: int | |||
|
387 | index: int | |||
|
388 | lines: list[string] | |||
|
389 | Colors: | |||
|
390 | ColorScheme used. | |||
|
391 | lvals: bytes | |||
|
392 | Values of local variables, already colored, to inject just after the error line. | |||
|
393 | _line_format: f (str) -> (str, bool) | |||
|
394 | return (colorized version of str, failure to do so) | |||
|
395 | """ | |||
378 | numbers_width = INDENT_SIZE - 1 |
|
396 | numbers_width = INDENT_SIZE - 1 | |
379 | res = [] |
|
397 | res = [] | |
380 | i = lnum - index |
|
|||
381 |
|
398 | |||
382 | for line in lines: |
|
399 | for i,line in enumerate(lines, lnum-index): | |
383 | line = py3compat.cast_unicode(line) |
|
400 | line = py3compat.cast_unicode(line) | |
384 |
|
401 | |||
385 | new_line, err = _line_format(line, 'str') |
|
402 | new_line, err = _line_format(line, 'str') | |
386 |
if not err: |
|
403 | if not err: | |
|
404 | line = new_line | |||
387 |
|
405 | |||
388 | if i == lnum: |
|
406 | if i == lnum: | |
389 | # This is the line with the error |
|
407 | # This is the line with the error | |
@@ -399,7 +417,6 b' def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, _line_forma' | |||||
399 | res.append(line) |
|
417 | res.append(line) | |
400 | if lvals and i == lnum: |
|
418 | if lvals and i == lnum: | |
401 | res.append(lvals + '\n') |
|
419 | res.append(lvals + '\n') | |
402 | i = i + 1 |
|
|||
403 | return res |
|
420 | return res | |
404 |
|
421 | |||
405 | def is_recursion_error(etype, value, records): |
|
422 | def is_recursion_error(etype, value, records): | |
@@ -621,16 +638,6 b' class ListTB(TBTools):' | |||||
621 | lines = ''.join(self._format_exception_only(etype, value)) |
|
638 | lines = ''.join(self._format_exception_only(etype, value)) | |
622 | out_list.append(lines) |
|
639 | out_list.append(lines) | |
623 |
|
640 | |||
624 | # Note: this code originally read: |
|
|||
625 |
|
||||
626 | ## for line in lines[:-1]: |
|
|||
627 | ## out_list.append(" "+line) |
|
|||
628 | ## out_list.append(lines[-1]) |
|
|||
629 |
|
||||
630 | # This means it was indenting everything but the last line by a little |
|
|||
631 | # bit. I've disabled this for now, but if we see ugliness somewhere we |
|
|||
632 | # can restore it. |
|
|||
633 |
|
||||
634 | return out_list |
|
641 | return out_list | |
635 |
|
642 | |||
636 | def _format_list(self, extracted_list): |
|
643 | def _format_list(self, extracted_list): | |
@@ -841,13 +848,6 b' class VerboseTB(TBTools):' | |||||
841 | Colors.vName, ColorsNormal) |
|
848 | Colors.vName, ColorsNormal) | |
842 | tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal) |
|
849 | tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal) | |
843 |
|
850 | |||
844 | tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal) |
|
|||
845 | tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line, |
|
|||
846 | ColorsNormal) |
|
|||
847 |
|
||||
848 | abspath = os.path.abspath |
|
|||
849 |
|
||||
850 |
|
||||
851 | if not file: |
|
851 | if not file: | |
852 | file = '?' |
|
852 | file = '?' | |
853 | elif file.startswith(str("<")) and file.endswith(str(">")): |
|
853 | elif file.startswith(str("<")) and file.endswith(str(">")): | |
@@ -869,17 +869,19 b' class VerboseTB(TBTools):' | |||||
869 |
|
869 | |||
870 | file = py3compat.cast_unicode(file, util_path.fs_encoding) |
|
870 | file = py3compat.cast_unicode(file, util_path.fs_encoding) | |
871 | link = tpl_link % util_path.compress_user(file) |
|
871 | link = tpl_link % util_path.compress_user(file) | |
872 | args, varargs, varkw, locals = inspect.getargvalues(frame) |
|
872 | args, varargs, varkw, locals_ = inspect.getargvalues(frame) | |
873 |
|
873 | |||
874 | if func == '?': |
|
874 | if func == '?': | |
875 | call = '' |
|
875 | call = '' | |
|
876 | elif func == '<module>': | |||
|
877 | call = tpl_call % (func, '') | |||
876 | else: |
|
878 | else: | |
877 | # Decide whether to include variable details or not |
|
879 | # Decide whether to include variable details or not | |
878 |
var_repr = self.include_vars |
|
880 | var_repr = eqrepr if self.include_vars else nullrepr | |
879 | try: |
|
881 | try: | |
880 | call = tpl_call % (func, inspect.formatargvalues(args, |
|
882 | call = tpl_call % (func, inspect.formatargvalues(args, | |
881 | varargs, varkw, |
|
883 | varargs, varkw, | |
882 | locals, formatvalue=var_repr)) |
|
884 | locals_, formatvalue=var_repr)) | |
883 | except KeyError: |
|
885 | except KeyError: | |
884 | # This happens in situations like errors inside generator |
|
886 | # This happens in situations like errors inside generator | |
885 | # expressions, where local variables are listed in the |
|
887 | # expressions, where local variables are listed in the | |
@@ -906,7 +908,7 b' class VerboseTB(TBTools):' | |||||
906 | elif file.endswith(('.pyc', '.pyo')): |
|
908 | elif file.endswith(('.pyc', '.pyo')): | |
907 | # Look up the corresponding source file. |
|
909 | # Look up the corresponding source file. | |
908 | try: |
|
910 | try: | |
909 |
file = |
|
911 | file = source_from_cache(file) | |
910 | except ValueError: |
|
912 | except ValueError: | |
911 | # Failed to get the source file for some reason |
|
913 | # Failed to get the source file for some reason | |
912 | # E.g. https://github.com/ipython/ipython/issues/9486 |
|
914 | # E.g. https://github.com/ipython/ipython/issues/9486 | |
@@ -968,14 +970,15 b' class VerboseTB(TBTools):' | |||||
968 | unique_names = uniq_stable(names) |
|
970 | unique_names = uniq_stable(names) | |
969 |
|
971 | |||
970 | # Start loop over vars |
|
972 | # Start loop over vars | |
971 |
lvals = |
|
973 | lvals = '' | |
|
974 | lvals_list = [] | |||
972 | if self.include_vars: |
|
975 | if self.include_vars: | |
973 | for name_full in unique_names: |
|
976 | for name_full in unique_names: | |
974 | name_base = name_full.split('.', 1)[0] |
|
977 | name_base = name_full.split('.', 1)[0] | |
975 | if name_base in frame.f_code.co_varnames: |
|
978 | if name_base in frame.f_code.co_varnames: | |
976 | if name_base in locals: |
|
979 | if name_base in locals_: | |
977 | try: |
|
980 | try: | |
978 | value = repr(eval(name_full, locals)) |
|
981 | value = repr(eval(name_full, locals_)) | |
979 | except: |
|
982 | except: | |
980 | value = undefined |
|
983 | value = undefined | |
981 | else: |
|
984 | else: | |
@@ -990,11 +993,9 b' class VerboseTB(TBTools):' | |||||
990 | else: |
|
993 | else: | |
991 | value = undefined |
|
994 | value = undefined | |
992 | name = tpl_global_var % name_full |
|
995 | name = tpl_global_var % name_full | |
993 | lvals.append(tpl_name_val % (name, value)) |
|
996 | lvals_list.append(tpl_name_val % (name, value)) | |
994 | if lvals: |
|
997 | if lvals_list: | |
995 | lvals = '%s%s' % (indent, em_normal.join(lvals)) |
|
998 | lvals = '%s%s' % (indent, em_normal.join(lvals_list)) | |
996 | else: |
|
|||
997 | lvals = '' |
|
|||
998 |
|
999 | |||
999 | level = '%s %s\n' % (link, call) |
|
1000 | level = '%s %s\n' % (link, call) | |
1000 |
|
1001 | |||
@@ -1041,7 +1042,6 b' class VerboseTB(TBTools):' | |||||
1041 | def format_exception(self, etype, evalue): |
|
1042 | def format_exception(self, etype, evalue): | |
1042 | colors = self.Colors # just a shorthand + quicker name lookup |
|
1043 | colors = self.Colors # just a shorthand + quicker name lookup | |
1043 | colorsnormal = colors.Normal # used a lot |
|
1044 | colorsnormal = colors.Normal # used a lot | |
1044 | indent = ' ' * INDENT_SIZE |
|
|||
1045 | # Get (safely) a string form of the exception info |
|
1045 | # Get (safely) a string form of the exception info | |
1046 | try: |
|
1046 | try: | |
1047 | etype_str, evalue_str = map(str, (etype, evalue)) |
|
1047 | etype_str, evalue_str = map(str, (etype, evalue)) |
@@ -339,10 +339,3 b' default_banner_parts = ["Python %s\\n"%sys.version.split("\\n")[0],' | |||||
339 | ] |
|
339 | ] | |
340 |
|
340 | |||
341 | default_banner = ''.join(default_banner_parts) |
|
341 | default_banner = ''.join(default_banner_parts) | |
342 |
|
||||
343 | # deprecated GUI banner |
|
|||
344 |
|
||||
345 | default_gui_banner = '\n'.join([ |
|
|||
346 | 'DEPRECATED: IPython.core.usage.default_gui_banner is deprecated and will be removed', |
|
|||
347 | default_banner, |
|
|||
348 | ]) |
|
@@ -116,10 +116,9 b' import traceback' | |||||
116 | import types |
|
116 | import types | |
117 | import weakref |
|
117 | import weakref | |
118 | from importlib import import_module |
|
118 | from importlib import import_module | |
|
119 | from importlib.util import source_from_cache | |||
119 | from imp import reload |
|
120 | from imp import reload | |
120 |
|
121 | |||
121 | from IPython.utils import openpy |
|
|||
122 |
|
||||
123 | #------------------------------------------------------------------------------ |
|
122 | #------------------------------------------------------------------------------ | |
124 | # Autoreload functionality |
|
123 | # Autoreload functionality | |
125 | #------------------------------------------------------------------------------ |
|
124 | #------------------------------------------------------------------------------ | |
@@ -195,7 +194,7 b' class ModuleReloader(object):' | |||||
195 | py_filename = filename |
|
194 | py_filename = filename | |
196 | else: |
|
195 | else: | |
197 | try: |
|
196 | try: | |
198 |
py_filename = |
|
197 | py_filename = source_from_cache(filename) | |
199 | except ValueError: |
|
198 | except ValueError: | |
200 | return None, None |
|
199 | return None, None | |
201 |
|
200 |
@@ -109,47 +109,6 b' def loaded_api():' | |||||
109 | def has_binding(api): |
|
109 | def has_binding(api): | |
110 | """Safely check for PyQt4/5, PySide or PySide2, without importing submodules |
|
110 | """Safely check for PyQt4/5, PySide or PySide2, without importing submodules | |
111 |
|
111 | |||
112 | Supports Python <= 3.3 |
|
|||
113 |
|
||||
114 | Parameters |
|
|||
115 | ---------- |
|
|||
116 | api : str [ 'pyqtv1' | 'pyqt' | 'pyqt5' | 'pyside' | 'pyside2' | 'pyqtdefault'] |
|
|||
117 | Which module to check for |
|
|||
118 |
|
||||
119 | Returns |
|
|||
120 | ------- |
|
|||
121 | True if the relevant module appears to be importable |
|
|||
122 | """ |
|
|||
123 | # we can't import an incomplete pyside and pyqt4 |
|
|||
124 | # this will cause a crash in sip (#1431) |
|
|||
125 | # check for complete presence before importing |
|
|||
126 | module_name = api_to_module[api] |
|
|||
127 |
|
||||
128 | import imp |
|
|||
129 | try: |
|
|||
130 | #importing top level PyQt4/PySide module is ok... |
|
|||
131 | mod = import_module(module_name) |
|
|||
132 | #...importing submodules is not |
|
|||
133 | imp.find_module('QtCore', mod.__path__) |
|
|||
134 | imp.find_module('QtGui', mod.__path__) |
|
|||
135 | imp.find_module('QtSvg', mod.__path__) |
|
|||
136 | if api in (QT_API_PYQT5, QT_API_PYSIDE2): |
|
|||
137 | # QT5 requires QtWidgets too |
|
|||
138 | imp.find_module('QtWidgets', mod.__path__) |
|
|||
139 |
|
||||
140 | #we can also safely check PySide version |
|
|||
141 | if api == QT_API_PYSIDE: |
|
|||
142 | return check_version(mod.__version__, '1.0.3') |
|
|||
143 | else: |
|
|||
144 | return True |
|
|||
145 | except ImportError: |
|
|||
146 | return False |
|
|||
147 |
|
||||
148 | def has_binding_new(api): |
|
|||
149 | """Safely check for PyQt4/5, PySide or PySide2, without importing submodules |
|
|||
150 |
|
||||
151 | Supports Python >= 3.4 |
|
|||
152 |
|
||||
153 | Parameters |
|
112 | Parameters | |
154 | ---------- |
|
113 | ---------- | |
155 | api : str [ 'pyqtv1' | 'pyqt' | 'pyqt5' | 'pyside' | 'pyside2' | 'pyqtdefault'] |
|
114 | api : str [ 'pyqtv1' | 'pyqt' | 'pyqt5' | 'pyside' | 'pyside2' | 'pyqtdefault'] | |
@@ -185,8 +144,6 b' def has_binding_new(api):' | |||||
185 |
|
144 | |||
186 | return True |
|
145 | return True | |
187 |
|
146 | |||
188 | if sys.version_info >= (3, 4): |
|
|||
189 | has_binding = has_binding_new |
|
|||
190 |
|
147 | |||
191 | def qtapi_version(): |
|
148 | def qtapi_version(): | |
192 | """Return which QString API has been set, if any |
|
149 | """Return which QString API has been set, if any |
@@ -2,13 +2,14 b'' | |||||
2 |
|
2 | |||
3 | Authors : MinRK, gregcaporaso, dannystaple |
|
3 | Authors : MinRK, gregcaporaso, dannystaple | |
4 | """ |
|
4 | """ | |
|
5 | from html import escape as html_escape | |||
5 | from os.path import exists, isfile, splitext, abspath, join, isdir |
|
6 | from os.path import exists, isfile, splitext, abspath, join, isdir | |
6 | from os import walk, sep |
|
7 | from os import walk, sep, fsdecode | |
7 |
|
8 | |||
8 | from IPython.core.display import DisplayObject |
|
9 | from IPython.core.display import DisplayObject, TextDisplayObject | |
9 |
|
10 | |||
10 | __all__ = ['Audio', 'IFrame', 'YouTubeVideo', 'VimeoVideo', 'ScribdDocument', |
|
11 | __all__ = ['Audio', 'IFrame', 'YouTubeVideo', 'VimeoVideo', 'ScribdDocument', | |
11 | 'FileLink', 'FileLinks'] |
|
12 | 'FileLink', 'FileLinks', 'Code'] | |
12 |
|
13 | |||
13 |
|
14 | |||
14 | class Audio(DisplayObject): |
|
15 | class Audio(DisplayObject): | |
@@ -334,15 +335,16 b' class FileLink(object):' | |||||
334 | if isdir(path): |
|
335 | if isdir(path): | |
335 | raise ValueError("Cannot display a directory using FileLink. " |
|
336 | raise ValueError("Cannot display a directory using FileLink. " | |
336 | "Use FileLinks to display '%s'." % path) |
|
337 | "Use FileLinks to display '%s'." % path) | |
337 | self.path = path |
|
338 | self.path = fsdecode(path) | |
338 | self.url_prefix = url_prefix |
|
339 | self.url_prefix = url_prefix | |
339 | self.result_html_prefix = result_html_prefix |
|
340 | self.result_html_prefix = result_html_prefix | |
340 | self.result_html_suffix = result_html_suffix |
|
341 | self.result_html_suffix = result_html_suffix | |
341 |
|
342 | |||
342 | def _format_path(self): |
|
343 | def _format_path(self): | |
343 | fp = ''.join([self.url_prefix,self.path]) |
|
344 | fp = ''.join([self.url_prefix, html_escape(self.path)]) | |
344 | return ''.join([self.result_html_prefix, |
|
345 | return ''.join([self.result_html_prefix, | |
345 |
self.html_link_str % |
|
346 | self.html_link_str % \ | |
|
347 | (fp, html_escape(self.path, quote=False)), | |||
346 | self.result_html_suffix]) |
|
348 | self.result_html_suffix]) | |
347 |
|
349 | |||
348 | def _repr_html_(self): |
|
350 | def _repr_html_(self): | |
@@ -555,3 +557,52 b' class FileLinks(FileLink):' | |||||
555 | for dirname, subdirs, fnames in walked_dir: |
|
557 | for dirname, subdirs, fnames in walked_dir: | |
556 | result_lines += self.terminal_display_formatter(dirname, fnames, self.included_suffixes) |
|
558 | result_lines += self.terminal_display_formatter(dirname, fnames, self.included_suffixes) | |
557 | return '\n'.join(result_lines) |
|
559 | return '\n'.join(result_lines) | |
|
560 | ||||
|
561 | ||||
|
562 | class Code(TextDisplayObject): | |||
|
563 | """Display syntax-highlighted source code. | |||
|
564 | ||||
|
565 | This uses Pygments to highlight the code for HTML and Latex output. | |||
|
566 | ||||
|
567 | Parameters | |||
|
568 | ---------- | |||
|
569 | data : str | |||
|
570 | The code as a string | |||
|
571 | url : str | |||
|
572 | A URL to fetch the code from | |||
|
573 | filename : str | |||
|
574 | A local filename to load the code from | |||
|
575 | language : str | |||
|
576 | The short name of a Pygments lexer to use for highlighting. | |||
|
577 | If not specified, it will guess the lexer based on the filename | |||
|
578 | or the code. Available lexers: http://pygments.org/docs/lexers/ | |||
|
579 | """ | |||
|
580 | def __init__(self, data=None, url=None, filename=None, language=None): | |||
|
581 | self.language = language | |||
|
582 | super().__init__(data=data, url=url, filename=filename) | |||
|
583 | ||||
|
584 | def _get_lexer(self): | |||
|
585 | if self.language: | |||
|
586 | from pygments.lexers import get_lexer_by_name | |||
|
587 | return get_lexer_by_name(self.language) | |||
|
588 | elif self.filename: | |||
|
589 | from pygments.lexers import get_lexer_for_filename | |||
|
590 | return get_lexer_for_filename(self.filename) | |||
|
591 | else: | |||
|
592 | from pygments.lexers import guess_lexer | |||
|
593 | return guess_lexer(self.data) | |||
|
594 | ||||
|
595 | def __repr__(self): | |||
|
596 | return self.data | |||
|
597 | ||||
|
598 | def _repr_html_(self): | |||
|
599 | from pygments import highlight | |||
|
600 | from pygments.formatters import HtmlFormatter | |||
|
601 | fmt = HtmlFormatter() | |||
|
602 | style = '<style>{}</style>'.format(fmt.get_style_defs('.output_html')) | |||
|
603 | return style + highlight(self.data, self._get_lexer(), fmt) | |||
|
604 | ||||
|
605 | def _repr_latex_(self): | |||
|
606 | from pygments import highlight | |||
|
607 | from pygments.formatters import LatexFormatter | |||
|
608 | return highlight(self.data, self._get_lexer(), LatexFormatter()) |
@@ -2,7 +2,7 b'' | |||||
2 | """ |
|
2 | """ | |
3 | Support for creating GUI apps and starting event loops. |
|
3 | Support for creating GUI apps and starting event loops. | |
4 |
|
4 | |||
5 | IPython's GUI integration allows interative plotting and GUI usage in IPython |
|
5 | IPython's GUI integration allows interactive plotting and GUI usage in IPython | |
6 | session. IPython has two different types of GUI integration: |
|
6 | session. IPython has two different types of GUI integration: | |
7 |
|
7 | |||
8 | 1. The terminal based IPython supports GUI event loops through Python's |
|
8 | 1. The terminal based IPython supports GUI event loops through Python's |
@@ -34,7 +34,9 b' This includes:' | |||||
34 | import re |
|
34 | import re | |
35 |
|
35 | |||
36 | # Third party |
|
36 | # Third party | |
37 |
from pygments.lexers import |
|
37 | from pygments.lexers import ( | |
|
38 | BashLexer, HtmlLexer, JavascriptLexer, RubyLexer, PerlLexer, PythonLexer, | |||
|
39 | Python3Lexer, TexLexer) | |||
38 | from pygments.lexer import ( |
|
40 | from pygments.lexer import ( | |
39 | Lexer, DelegatingLexer, RegexLexer, do_insertions, bygroups, using, |
|
41 | Lexer, DelegatingLexer, RegexLexer, do_insertions, bygroups, using, | |
40 | ) |
|
42 | ) | |
@@ -51,19 +53,6 b" __all__ = ['build_ipy_lexer', 'IPython3Lexer', 'IPythonLexer'," | |||||
51 | 'IPythonPartialTracebackLexer', 'IPythonTracebackLexer', |
|
53 | 'IPythonPartialTracebackLexer', 'IPythonTracebackLexer', | |
52 | 'IPythonConsoleLexer', 'IPyLexer'] |
|
54 | 'IPythonConsoleLexer', 'IPyLexer'] | |
53 |
|
55 | |||
54 | ipython_tokens = [ |
|
|||
55 | (r"(?s)(\s*)(%%)(\w+)(.*)", bygroups(Text, Operator, Keyword, Text)), |
|
|||
56 | (r'(?s)(^\s*)(%%!)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(BashLexer))), |
|
|||
57 | (r"(%%?)(\w+)(\?\??)$", bygroups(Operator, Keyword, Operator)), |
|
|||
58 | (r"\b(\?\??)(\s*)$", bygroups(Operator, Text)), |
|
|||
59 | (r'(%)(sx|sc|system)(.*)(\n)', bygroups(Operator, Keyword, |
|
|||
60 | using(BashLexer), Text)), |
|
|||
61 | (r'(%)(\w+)(.*\n)', bygroups(Operator, Keyword, Text)), |
|
|||
62 | (r'^(!!)(.+)(\n)', bygroups(Operator, using(BashLexer), Text)), |
|
|||
63 | (r'(!)(?!=)(.+)(\n)', bygroups(Operator, using(BashLexer), Text)), |
|
|||
64 | (r'^(\s*)(\?\??)(\s*%{0,2}[\w\.\*]*)', bygroups(Text, Operator, Text)), |
|
|||
65 | (r'(\s*%{0,2}[\w\.\*]*)(\?\??)(\s*)$', bygroups(Text, Operator, Text)), |
|
|||
66 | ] |
|
|||
67 |
|
56 | |||
68 | def build_ipy_lexer(python3): |
|
57 | def build_ipy_lexer(python3): | |
69 | """Builds IPython lexers depending on the value of `python3`. |
|
58 | """Builds IPython lexers depending on the value of `python3`. | |
@@ -92,6 +81,36 b' def build_ipy_lexer(python3):' | |||||
92 | aliases = ['ipython2', 'ipython'] |
|
81 | aliases = ['ipython2', 'ipython'] | |
93 | doc = """IPython Lexer""" |
|
82 | doc = """IPython Lexer""" | |
94 |
|
83 | |||
|
84 | ipython_tokens = [ | |||
|
85 | (r'(?s)(\s*)(%%capture)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), | |||
|
86 | (r'(?s)(\s*)(%%debug)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), | |||
|
87 | (r'(?is)(\s*)(%%html)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(HtmlLexer))), | |||
|
88 | (r'(?s)(\s*)(%%javascript)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(JavascriptLexer))), | |||
|
89 | (r'(?s)(\s*)(%%js)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(JavascriptLexer))), | |||
|
90 | (r'(?s)(\s*)(%%latex)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(TexLexer))), | |||
|
91 | (r'(?s)(\s*)(%%pypy)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PerlLexer))), | |||
|
92 | (r'(?s)(\s*)(%%prun)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), | |||
|
93 | (r'(?s)(\s*)(%%pypy)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), | |||
|
94 | (r'(?s)(\s*)(%%python)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), | |||
|
95 | (r'(?s)(\s*)(%%python2)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PythonLexer))), | |||
|
96 | (r'(?s)(\s*)(%%python3)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(Python3Lexer))), | |||
|
97 | (r'(?s)(\s*)(%%ruby)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(RubyLexer))), | |||
|
98 | (r'(?s)(\s*)(%%time)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), | |||
|
99 | (r'(?s)(\s*)(%%timeit)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), | |||
|
100 | (r'(?s)(\s*)(%%writefile)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), | |||
|
101 | (r"(?s)(\s*)(%%)(\w+)(.*)", bygroups(Text, Operator, Keyword, Text)), | |||
|
102 | (r'(?s)(^\s*)(%%!)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(BashLexer))), | |||
|
103 | (r"(%%?)(\w+)(\?\??)$", bygroups(Operator, Keyword, Operator)), | |||
|
104 | (r"\b(\?\??)(\s*)$", bygroups(Operator, Text)), | |||
|
105 | (r'(%)(sx|sc|system)(.*)(\n)', bygroups(Operator, Keyword, | |||
|
106 | using(BashLexer), Text)), | |||
|
107 | (r'(%)(\w+)(.*\n)', bygroups(Operator, Keyword, Text)), | |||
|
108 | (r'^(!!)(.+)(\n)', bygroups(Operator, using(BashLexer), Text)), | |||
|
109 | (r'(!)(?!=)(.+)(\n)', bygroups(Operator, using(BashLexer), Text)), | |||
|
110 | (r'^(\s*)(\?\??)(\s*%{0,2}[\w\.\*]*)', bygroups(Text, Operator, Text)), | |||
|
111 | (r'(\s*%{0,2}[\w\.\*]*)(\?\??)(\s*)$', bygroups(Text, Operator, Text)), | |||
|
112 | ] | |||
|
113 | ||||
95 | tokens = PyLexer.tokens.copy() |
|
114 | tokens = PyLexer.tokens.copy() | |
96 | tokens['root'] = ipython_tokens + tokens['root'] |
|
115 | tokens['root'] = ipython_tokens + tokens['root'] | |
97 |
|
116 | |||
@@ -217,7 +236,7 b' class IPythonConsoleLexer(Lexer):' | |||||
217 |
|
236 | |||
218 | --------------------------------------------------------------------------- |
|
237 | --------------------------------------------------------------------------- | |
219 | Exception Traceback (most recent call last) |
|
238 | Exception Traceback (most recent call last) | |
220 |
<ipython-input-1-fca2ab0ca76b> in <module> |
|
239 | <ipython-input-1-fca2ab0ca76b> in <module> | |
221 | ----> 1 raise Exception |
|
240 | ----> 1 raise Exception | |
222 |
|
241 | |||
223 | Exception: |
|
242 | Exception: |
@@ -77,11 +77,13 b' Inheritance diagram:' | |||||
77 | Portions (c) 2009 by Robert Kern. |
|
77 | Portions (c) 2009 by Robert Kern. | |
78 | :license: BSD License. |
|
78 | :license: BSD License. | |
79 | """ |
|
79 | """ | |
|
80 | ||||
80 | from contextlib import contextmanager |
|
81 | from contextlib import contextmanager | |
|
82 | import datetime | |||
|
83 | import os | |||
|
84 | import re | |||
81 | import sys |
|
85 | import sys | |
82 | import types |
|
86 | import types | |
83 | import re |
|
|||
84 | import datetime |
|
|||
85 | from collections import deque |
|
87 | from collections import deque | |
86 | from io import StringIO |
|
88 | from io import StringIO | |
87 | from warnings import warn |
|
89 | from warnings import warn | |
@@ -742,7 +744,6 b' _type_pprinters = {' | |||||
742 | tuple: _seq_pprinter_factory('(', ')'), |
|
744 | tuple: _seq_pprinter_factory('(', ')'), | |
743 | list: _seq_pprinter_factory('[', ']'), |
|
745 | list: _seq_pprinter_factory('[', ']'), | |
744 | dict: _dict_pprinter_factory('{', '}'), |
|
746 | dict: _dict_pprinter_factory('{', '}'), | |
745 |
|
||||
746 | set: _set_pprinter_factory('{', '}'), |
|
747 | set: _set_pprinter_factory('{', '}'), | |
747 | frozenset: _set_pprinter_factory('frozenset({', '})'), |
|
748 | frozenset: _set_pprinter_factory('frozenset({', '})'), | |
748 | super: _super_pprint, |
|
749 | super: _super_pprint, | |
@@ -751,12 +752,17 b' _type_pprinters = {' | |||||
751 | types.FunctionType: _function_pprint, |
|
752 | types.FunctionType: _function_pprint, | |
752 | types.BuiltinFunctionType: _function_pprint, |
|
753 | types.BuiltinFunctionType: _function_pprint, | |
753 | types.MethodType: _repr_pprint, |
|
754 | types.MethodType: _repr_pprint, | |
754 |
|
||||
755 | datetime.datetime: _repr_pprint, |
|
755 | datetime.datetime: _repr_pprint, | |
756 | datetime.timedelta: _repr_pprint, |
|
756 | datetime.timedelta: _repr_pprint, | |
757 | _exception_base: _exception_pprint |
|
757 | _exception_base: _exception_pprint | |
758 | } |
|
758 | } | |
759 |
|
759 | |||
|
760 | # render os.environ like a dict | |||
|
761 | _env_type = type(os.environ) | |||
|
762 | # future-proof in case os.environ becomes a plain dict? | |||
|
763 | if _env_type is not dict: | |||
|
764 | _type_pprinters[_env_type] = _dict_pprinter_factory('environ{', '}') | |||
|
765 | ||||
760 | try: |
|
766 | try: | |
761 | # In PyPy, types.DictProxyType is dict, setting the dictproxy printer |
|
767 | # In PyPy, types.DictProxyType is dict, setting the dictproxy printer | |
762 | # using dict.setdefault avoids overwritting the dict printer |
|
768 | # using dict.setdefault avoids overwritting the dict printer | |
@@ -768,7 +774,7 b' except AttributeError: # Python 3' | |||||
768 | _type_pprinters[types.MappingProxyType] = \ |
|
774 | _type_pprinters[types.MappingProxyType] = \ | |
769 | _dict_pprinter_factory('mappingproxy({', '})') |
|
775 | _dict_pprinter_factory('mappingproxy({', '})') | |
770 | _type_pprinters[slice] = _repr_pprint |
|
776 | _type_pprinters[slice] = _repr_pprint | |
771 |
|
777 | |||
772 | try: |
|
778 | try: | |
773 | _type_pprinters[long] = _repr_pprint |
|
779 | _type_pprinters[long] = _repr_pprint | |
774 | _type_pprinters[unicode] = _repr_pprint |
|
780 | _type_pprinters[unicode] = _repr_pprint |
@@ -14,6 +14,11 b'' | |||||
14 | #----------------------------------------------------------------------------- |
|
14 | #----------------------------------------------------------------------------- | |
15 | from tempfile import NamedTemporaryFile, mkdtemp |
|
15 | from tempfile import NamedTemporaryFile, mkdtemp | |
16 | from os.path import split, join as pjoin, dirname |
|
16 | from os.path import split, join as pjoin, dirname | |
|
17 | import sys | |||
|
18 | try: | |||
|
19 | import pathlib | |||
|
20 | except ImportError: | |||
|
21 | pass | |||
17 |
|
22 | |||
18 | # Third-party imports |
|
23 | # Third-party imports | |
19 | import nose.tools as nt |
|
24 | import nose.tools as nt | |
@@ -33,6 +38,9 b' from IPython.testing.decorators import skipif_not_numpy' | |||||
33 | def test_instantiation_FileLink(): |
|
38 | def test_instantiation_FileLink(): | |
34 | """FileLink: Test class can be instantiated""" |
|
39 | """FileLink: Test class can be instantiated""" | |
35 | fl = display.FileLink('example.txt') |
|
40 | fl = display.FileLink('example.txt') | |
|
41 | # TODO: remove if when only Python >= 3.6 is supported | |||
|
42 | if sys.version_info >= (3, 6): | |||
|
43 | fl = display.FileLink(pathlib.PurePath('example.txt')) | |||
36 |
|
44 | |||
37 | def test_warning_on_non_existant_path_FileLink(): |
|
45 | def test_warning_on_non_existant_path_FileLink(): | |
38 | """FileLink: Calling _repr_html_ on non-existant files returns a warning |
|
46 | """FileLink: Calling _repr_html_ on non-existant files returns a warning | |
@@ -175,3 +183,7 b' def test_recursive_FileLinks():' | |||||
175 | def test_audio_from_file(): |
|
183 | def test_audio_from_file(): | |
176 | path = pjoin(dirname(__file__), 'test.wav') |
|
184 | path = pjoin(dirname(__file__), 'test.wav') | |
177 | display.Audio(filename=path) |
|
185 | display.Audio(filename=path) | |
|
186 | ||||
|
187 | def test_code_from_file(): | |||
|
188 | c = display.Code(filename=__file__) | |||
|
189 | assert c._repr_html_().startswith('<style>') |
@@ -127,3 +127,50 b' class TestLexers(TestCase):' | |||||
127 | (Token.Text, '\n'), |
|
127 | (Token.Text, '\n'), | |
128 | ] |
|
128 | ] | |
129 | self.assertEqual(tokens, list(self.lexer.get_tokens(fragment))) |
|
129 | self.assertEqual(tokens, list(self.lexer.get_tokens(fragment))) | |
|
130 | ||||
|
131 | fragment = '%%writefile -a foo.py\nif a == b:\n pass' | |||
|
132 | tokens = [ | |||
|
133 | (Token.Operator, '%%writefile'), | |||
|
134 | (Token.Text, ' -a foo.py\n'), | |||
|
135 | (Token.Keyword, 'if'), | |||
|
136 | (Token.Text, ' '), | |||
|
137 | (Token.Name, 'a'), | |||
|
138 | (Token.Text, ' '), | |||
|
139 | (Token.Operator, '=='), | |||
|
140 | (Token.Text, ' '), | |||
|
141 | (Token.Name, 'b'), | |||
|
142 | (Token.Punctuation, ':'), | |||
|
143 | (Token.Text, '\n'), | |||
|
144 | (Token.Text, ' '), | |||
|
145 | (Token.Keyword, 'pass'), | |||
|
146 | (Token.Text, '\n'), | |||
|
147 | ] | |||
|
148 | self.assertEqual(tokens, list(self.lexer.get_tokens(fragment))) | |||
|
149 | ||||
|
150 | fragment = '%%timeit\nmath.sin(0)' | |||
|
151 | tokens = [ | |||
|
152 | (Token.Operator, '%%timeit\n'), | |||
|
153 | (Token.Name, 'math'), | |||
|
154 | (Token.Operator, '.'), | |||
|
155 | (Token.Name, 'sin'), | |||
|
156 | (Token.Punctuation, '('), | |||
|
157 | (Token.Literal.Number.Integer, '0'), | |||
|
158 | (Token.Punctuation, ')'), | |||
|
159 | (Token.Text, '\n'), | |||
|
160 | ] | |||
|
161 | ||||
|
162 | fragment = '%%HTML\n<div>foo</div>' | |||
|
163 | tokens = [ | |||
|
164 | (Token.Operator, '%%HTML'), | |||
|
165 | (Token.Text, '\n'), | |||
|
166 | (Token.Punctuation, '<'), | |||
|
167 | (Token.Name.Tag, 'div'), | |||
|
168 | (Token.Punctuation, '>'), | |||
|
169 | (Token.Text, 'foo'), | |||
|
170 | (Token.Punctuation, '<'), | |||
|
171 | (Token.Punctuation, '/'), | |||
|
172 | (Token.Name.Tag, 'div'), | |||
|
173 | (Token.Punctuation, '>'), | |||
|
174 | (Token.Text, '\n'), | |||
|
175 | ] | |||
|
176 | self.assertEqual(tokens, list(self.lexer.get_tokens(fragment))) |
@@ -6,6 +6,7 b'' | |||||
6 |
|
6 | |||
7 |
|
7 | |||
8 | from collections import Counter, defaultdict, deque, OrderedDict |
|
8 | from collections import Counter, defaultdict, deque, OrderedDict | |
|
9 | import os | |||
9 | import types |
|
10 | import types | |
10 | import string |
|
11 | import string | |
11 | import unittest |
|
12 | import unittest | |
@@ -406,6 +407,15 b' def test_mappingproxy():' | |||||
406 | for obj, expected in cases: |
|
407 | for obj, expected in cases: | |
407 | nt.assert_equal(pretty.pretty(obj), expected) |
|
408 | nt.assert_equal(pretty.pretty(obj), expected) | |
408 |
|
409 | |||
|
410 | ||||
|
411 | def test_pretty_environ(): | |||
|
412 | dict_repr = pretty.pretty(dict(os.environ)) | |||
|
413 | # reindent to align with 'environ' prefix | |||
|
414 | dict_indented = dict_repr.replace('\n', '\n' + (' ' * len('environ'))) | |||
|
415 | env_repr = pretty.pretty(os.environ) | |||
|
416 | nt.assert_equals(env_repr, 'environ' + dict_indented) | |||
|
417 | ||||
|
418 | ||||
409 | def test_function_pretty(): |
|
419 | def test_function_pretty(): | |
410 | "Test pretty print of function" |
|
420 | "Test pretty print of function" | |
411 | # posixpath is a pure python module, its interface is consistent |
|
421 | # posixpath is a pure python module, its interface is consistent |
@@ -8,15 +8,14 b' from .ptutils import IPythonPTCompleter' | |||||
8 | from .shortcuts import suspend_to_bg, cursor_in_leading_ws |
|
8 | from .shortcuts import suspend_to_bg, cursor_in_leading_ws | |
9 |
|
9 | |||
10 | from prompt_toolkit.enums import DEFAULT_BUFFER |
|
10 | from prompt_toolkit.enums import DEFAULT_BUFFER | |
11 |
from prompt_toolkit.filters import (Condition, |
|
11 | from prompt_toolkit.filters import (Condition, has_focus, has_selection, | |
12 |
|
|
12 | vi_insert_mode, emacs_insert_mode) | |
13 |
from prompt_toolkit.key |
|
13 | from prompt_toolkit.key_binding import KeyBindings | |
14 | from prompt_toolkit.key_binding.manager import KeyBindingManager |
|
|||
15 | from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline |
|
14 | from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline | |
16 |
from p |
|
15 | from pygments.token import Token | |
17 |
from prompt_toolkit.shortcuts import |
|
16 | from prompt_toolkit.shortcuts.prompt import PromptSession | |
18 | from prompt_toolkit.interface import CommandLineInterface |
|
|||
19 | from prompt_toolkit.enums import EditingMode |
|
17 | from prompt_toolkit.enums import EditingMode | |
|
18 | from prompt_toolkit.formatted_text import PygmentsTokens | |||
20 |
|
19 | |||
21 |
|
20 | |||
22 | class TerminalPdb(Pdb): |
|
21 | class TerminalPdb(Pdb): | |
@@ -26,46 +25,40 b' class TerminalPdb(Pdb):' | |||||
26 | self.pt_init() |
|
25 | self.pt_init() | |
27 |
|
26 | |||
28 | def pt_init(self): |
|
27 | def pt_init(self): | |
29 |
def get_prompt_tokens( |
|
28 | def get_prompt_tokens(): | |
30 | return [(Token.Prompt, self.prompt)] |
|
29 | return [(Token.Prompt, self.prompt)] | |
31 |
|
30 | |||
32 | def patch_stdout(**kwargs): |
|
|||
33 | return self.pt_cli.patch_stdout_context(**kwargs) |
|
|||
34 |
|
||||
35 | if self._ptcomp is None: |
|
31 | if self._ptcomp is None: | |
36 | compl = IPCompleter(shell=self.shell, |
|
32 | compl = IPCompleter(shell=self.shell, | |
37 | namespace={}, |
|
33 | namespace={}, | |
38 | global_namespace={}, |
|
34 | global_namespace={}, | |
39 | parent=self.shell, |
|
35 | parent=self.shell, | |
40 | ) |
|
36 | ) | |
41 |
self._ptcomp = IPythonPTCompleter(compl |
|
37 | self._ptcomp = IPythonPTCompleter(compl) | |
42 |
|
38 | |||
43 |
kb |
|
39 | kb = KeyBindings() | |
44 |
supports_suspend = Condition(lambda |
|
40 | supports_suspend = Condition(lambda: hasattr(signal, 'SIGTSTP')) | |
45 | kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend |
|
41 | kb.add('c-z', filter=supports_suspend)(suspend_to_bg) | |
46 | )(suspend_to_bg) |
|
|||
47 |
|
42 | |||
48 | if self.shell.display_completions == 'readlinelike': |
|
43 | if self.shell.display_completions == 'readlinelike': | |
49 | kbmanager.registry.add_binding(Keys.ControlI, |
|
44 | kb.add('tab', filter=(has_focus(DEFAULT_BUFFER) | |
50 |
|
|
45 | & ~has_selection | |
51 |
|
|
46 | & vi_insert_mode | emacs_insert_mode | |
52 | & ViInsertMode() | EmacsInsertMode() |
|
47 | & ~cursor_in_leading_ws | |
53 | & ~cursor_in_leading_ws |
|
48 | ))(display_completions_like_readline) | |
54 | ))(display_completions_like_readline) |
|
49 | ||
55 | multicolumn = (self.shell.display_completions == 'multicolumn') |
|
50 | self.pt_app = PromptSession( | |
56 |
|
51 | message=(lambda: PygmentsTokens(get_prompt_tokens())), | ||
57 | self._pt_app = create_prompt_application( |
|
|||
58 | editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()), |
|
52 | editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()), | |
59 |
key_bindings |
|
53 | key_bindings=kb, | |
60 | history=self.shell.debugger_history, |
|
54 | history=self.shell.debugger_history, | |
61 |
completer= |
|
55 | completer=self._ptcomp, | |
62 | enable_history_search=True, |
|
56 | enable_history_search=True, | |
63 | mouse_support=self.shell.mouse_support, |
|
57 | mouse_support=self.shell.mouse_support, | |
64 |
|
|
58 | complete_style=self.shell.pt_complete_style, | |
65 | display_completions_in_columns=multicolumn, |
|
59 | style=self.shell.style, | |
66 |
|
|
60 | inputhook=self.shell.inputhook, | |
67 | ) |
|
61 | ) | |
68 | self.pt_cli = CommandLineInterface(self._pt_app, eventloop=self.shell._eventloop) |
|
|||
69 |
|
62 | |||
70 | def cmdloop(self, intro=None): |
|
63 | def cmdloop(self, intro=None): | |
71 | """Repeatedly issue a prompt, accept input, parse an initial prefix |
|
64 | """Repeatedly issue a prompt, accept input, parse an initial prefix | |
@@ -92,7 +85,7 b' class TerminalPdb(Pdb):' | |||||
92 | self._ptcomp.ipy_completer.namespace = self.curframe_locals |
|
85 | self._ptcomp.ipy_completer.namespace = self.curframe_locals | |
93 | self._ptcomp.ipy_completer.global_namespace = self.curframe.f_globals |
|
86 | self._ptcomp.ipy_completer.global_namespace = self.curframe.f_globals | |
94 | try: |
|
87 | try: | |
95 |
line = self.pt_ |
|
88 | line = self.pt_app.prompt() # reset_current_buffer=True) | |
96 | except EOFError: |
|
89 | except EOFError: | |
97 | line = 'EOF' |
|
90 | line = 'EOF' | |
98 | line = self.precmd(line) |
|
91 | line = self.precmd(line) |
@@ -15,15 +15,16 b' from traitlets import (' | |||||
15 | Any, |
|
15 | Any, | |
16 | ) |
|
16 | ) | |
17 |
|
17 | |||
18 | from prompt_toolkit.document import Document |
|
|||
19 | from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode |
|
18 | from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode | |
20 | from prompt_toolkit.filters import (HasFocus, Condition, IsDone) |
|
19 | from prompt_toolkit.filters import (HasFocus, Condition, IsDone) | |
|
20 | from prompt_toolkit.formatted_text import PygmentsTokens | |||
21 | from prompt_toolkit.history import InMemoryHistory |
|
21 | from prompt_toolkit.history import InMemoryHistory | |
22 | from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output |
|
|||
23 | from prompt_toolkit.interface import CommandLineInterface |
|
|||
24 | from prompt_toolkit.key_binding.manager import KeyBindingManager |
|
|||
25 | from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor |
|
22 | from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor | |
26 | from prompt_toolkit.styles import PygmentsStyle, DynamicStyle |
|
23 | from prompt_toolkit.output import ColorDepth | |
|
24 | from prompt_toolkit.patch_stdout import patch_stdout | |||
|
25 | from prompt_toolkit.shortcuts import PromptSession, CompleteStyle, print_formatted_text | |||
|
26 | from prompt_toolkit.styles import DynamicStyle, merge_styles | |||
|
27 | from prompt_toolkit.styles.pygments import style_from_pygments_cls, style_from_pygments_dict | |||
27 |
|
28 | |||
28 | from pygments.styles import get_style_by_name |
|
29 | from pygments.styles import get_style_by_name | |
29 | from pygments.style import Style |
|
30 | from pygments.style import Style | |
@@ -34,7 +35,7 b' from .magics import TerminalMagics' | |||||
34 | from .pt_inputhooks import get_inputhook_name_and_func |
|
35 | from .pt_inputhooks import get_inputhook_name_and_func | |
35 | from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook |
|
36 | from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook | |
36 | from .ptutils import IPythonPTCompleter, IPythonPTLexer |
|
37 | from .ptutils import IPythonPTCompleter, IPythonPTLexer | |
37 |
from .shortcuts import |
|
38 | from .shortcuts import create_ipython_shortcuts | |
38 |
|
39 | |||
39 | DISPLAY_BANNER_DEPRECATED = object() |
|
40 | DISPLAY_BANNER_DEPRECATED = object() | |
40 |
|
41 | |||
@@ -88,15 +89,11 b" _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)" | |||||
88 |
|
89 | |||
89 | class TerminalInteractiveShell(InteractiveShell): |
|
90 | class TerminalInteractiveShell(InteractiveShell): | |
90 | space_for_menu = Integer(6, help='Number of line at the bottom of the screen ' |
|
91 | space_for_menu = Integer(6, help='Number of line at the bottom of the screen ' | |
91 |
|
|
92 | 'to reserve for the completion menu' | |
92 | ).tag(config=True) |
|
93 | ).tag(config=True) | |
93 |
|
94 | |||
94 | def _space_for_menu_changed(self, old, new): |
|
95 | pt_app = None | |
95 | self._update_layout() |
|
|||
96 |
|
||||
97 | pt_cli = None |
|
|||
98 | debugger_history = None |
|
96 | debugger_history = None | |
99 | _pt_app = None |
|
|||
100 |
|
97 | |||
101 | simple_prompt = Bool(_use_simple_prompt, |
|
98 | simple_prompt = Bool(_use_simple_prompt, | |
102 | help="""Use `raw_input` for the REPL, without completion and prompt colors. |
|
99 | help="""Use `raw_input` for the REPL, without completion and prompt colors. | |
@@ -167,9 +164,9 b' class TerminalInteractiveShell(InteractiveShell):' | |||||
167 | def _prompts_default(self): |
|
164 | def _prompts_default(self): | |
168 | return self.prompts_class(self) |
|
165 | return self.prompts_class(self) | |
169 |
|
166 | |||
170 | @observe('prompts') |
|
167 | # @observe('prompts') | |
171 | def _(self, change): |
|
168 | # def _(self, change): | |
172 | self._update_layout() |
|
169 | # self._update_layout() | |
173 |
|
170 | |||
174 | @default('displayhook_class') |
|
171 | @default('displayhook_class') | |
175 | def _displayhook_class_default(self): |
|
172 | def _displayhook_class_default(self): | |
@@ -241,10 +238,7 b' class TerminalInteractiveShell(InteractiveShell):' | |||||
241 | return |
|
238 | return | |
242 |
|
239 | |||
243 | # Set up keyboard shortcuts |
|
240 | # Set up keyboard shortcuts | |
244 | kbmanager = KeyBindingManager.for_prompt( |
|
241 | key_bindings = create_ipython_shortcuts(self) | |
245 | enable_open_in_editor=self.extra_open_editor_shortcuts, |
|
|||
246 | ) |
|
|||
247 | register_ipython_shortcuts(kbmanager.registry, self) |
|
|||
248 |
|
242 | |||
249 | # Pre-populate history from IPython's history database |
|
243 | # Pre-populate history from IPython's history database | |
250 | history = InMemoryHistory() |
|
244 | history = InMemoryHistory() | |
@@ -254,7 +248,7 b' class TerminalInteractiveShell(InteractiveShell):' | |||||
254 | # Ignore blank lines and consecutive duplicates |
|
248 | # Ignore blank lines and consecutive duplicates | |
255 | cell = cell.rstrip() |
|
249 | cell = cell.rstrip() | |
256 | if cell and (cell != last_cell): |
|
250 | if cell and (cell != last_cell): | |
257 | history.append(cell) |
|
251 | history.append_string(cell) | |
258 | last_cell = cell |
|
252 | last_cell = cell | |
259 |
|
253 | |||
260 | self._style = self._make_style_from_name_or_cls(self.highlighting_style) |
|
254 | self._style = self._make_style_from_name_or_cls(self.highlighting_style) | |
@@ -262,24 +256,18 b' class TerminalInteractiveShell(InteractiveShell):' | |||||
262 |
|
256 | |||
263 | editing_mode = getattr(EditingMode, self.editing_mode.upper()) |
|
257 | editing_mode = getattr(EditingMode, self.editing_mode.upper()) | |
264 |
|
258 | |||
265 | def patch_stdout(**kwargs): |
|
259 | self.pt_app = PromptSession( | |
266 | return self.pt_cli.patch_stdout_context(**kwargs) |
|
|||
267 |
|
||||
268 | self._pt_app = create_prompt_application( |
|
|||
269 | editing_mode=editing_mode, |
|
260 | editing_mode=editing_mode, | |
270 |
key_bindings |
|
261 | key_bindings=key_bindings, | |
271 | history=history, |
|
262 | history=history, | |
272 | completer=IPythonPTCompleter(shell=self, |
|
263 | completer=IPythonPTCompleter(shell=self), | |
273 | patch_stdout=patch_stdout), |
|
264 | enable_history_search = self.enable_history_search, | |
274 | enable_history_search=self.enable_history_search, |
|
|||
275 | style=self.style, |
|
265 | style=self.style, | |
|
266 | include_default_pygments_style=False, | |||
276 | mouse_support=self.mouse_support, |
|
267 | mouse_support=self.mouse_support, | |
277 | **self._layout_options() |
|
268 | enable_open_in_editor=self.extra_open_editor_shortcuts, | |
278 | ) |
|
269 | color_depth=(ColorDepth.TRUE_COLOR if self.true_color else None), | |
279 | self._eventloop = create_eventloop(self.inputhook) |
|
270 | **self._extra_prompt_options()) | |
280 | self.pt_cli = CommandLineInterface( |
|
|||
281 | self._pt_app, eventloop=self._eventloop, |
|
|||
282 | output=create_output(true_color=self.true_color)) |
|
|||
283 |
|
271 | |||
284 | def _make_style_from_name_or_cls(self, name_or_cls): |
|
272 | def _make_style_from_name_or_cls(self, name_or_cls): | |
285 | """ |
|
273 | """ | |
@@ -340,44 +328,60 b' class TerminalInteractiveShell(InteractiveShell):' | |||||
340 | Token.OutPromptNum: '#ff0000 bold', |
|
328 | Token.OutPromptNum: '#ff0000 bold', | |
341 | } |
|
329 | } | |
342 | style_overrides.update(self.highlighting_style_overrides) |
|
330 | style_overrides.update(self.highlighting_style_overrides) | |
343 | style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls, |
|
331 | style = merge_styles([ | |
344 | style_dict=style_overrides) |
|
332 | style_from_pygments_cls(style_cls), | |
|
333 | style_from_pygments_dict(style_overrides), | |||
|
334 | ]) | |||
345 |
|
335 | |||
346 | return style |
|
336 | return style | |
347 |
|
337 | |||
348 | def _layout_options(self): |
|
338 | @property | |
|
339 | def pt_complete_style(self): | |||
|
340 | return { | |||
|
341 | 'multicolumn': CompleteStyle.MULTI_COLUMN, | |||
|
342 | 'column': CompleteStyle.COLUMN, | |||
|
343 | 'readlinelike': CompleteStyle.READLINE_LIKE, | |||
|
344 | }[self.display_completions] | |||
|
345 | ||||
|
346 | def _extra_prompt_options(self): | |||
349 | """ |
|
347 | """ | |
350 | Return the current layout option for the current Terminal InteractiveShell |
|
348 | Return the current layout option for the current Terminal InteractiveShell | |
351 | """ |
|
349 | """ | |
|
350 | def get_message(): | |||
|
351 | return PygmentsTokens(self.prompts.in_prompt_tokens()) | |||
|
352 | ||||
352 | return { |
|
353 | return { | |
|
354 | 'complete_in_thread': False, | |||
353 | 'lexer':IPythonPTLexer(), |
|
355 | 'lexer':IPythonPTLexer(), | |
354 | 'reserve_space_for_menu':self.space_for_menu, |
|
356 | 'reserve_space_for_menu':self.space_for_menu, | |
355 | 'get_prompt_tokens':self.prompts.in_prompt_tokens, |
|
357 | 'message': get_message, | |
356 | 'get_continuation_tokens':self.prompts.continuation_prompt_tokens, |
|
358 | 'prompt_continuation': ( | |
357 | 'multiline':True, |
|
359 | lambda width, lineno, is_soft_wrap: | |
358 | 'display_completions_in_columns': (self.display_completions == 'multicolumn'), |
|
360 | PygmentsTokens(self.prompts.continuation_prompt_tokens(width))), | |
|
361 | 'multiline': True, | |||
|
362 | 'complete_style': self.pt_complete_style, | |||
359 |
|
363 | |||
360 | # Highlight matching brackets, but only when this setting is |
|
364 | # Highlight matching brackets, but only when this setting is | |
361 | # enabled, and only when the DEFAULT_BUFFER has the focus. |
|
365 | # enabled, and only when the DEFAULT_BUFFER has the focus. | |
362 |
' |
|
366 | 'input_processors': [ConditionalProcessor( | |
363 | processor=HighlightMatchingBracketProcessor(chars='[](){}'), |
|
367 | processor=HighlightMatchingBracketProcessor(chars='[](){}'), | |
364 | filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() & |
|
368 | filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() & | |
365 |
Condition(lambda |
|
369 | Condition(lambda: self.highlight_matching_brackets))], | |
366 | } |
|
370 | } | |
367 |
|
371 | |||
368 | def _update_layout(self): |
|
|||
369 | """ |
|
|||
370 | Ask for a re computation of the application layout, if for example , |
|
|||
371 | some configuration options have changed. |
|
|||
372 | """ |
|
|||
373 | if self._pt_app: |
|
|||
374 | self._pt_app.layout = create_prompt_layout(**self._layout_options()) |
|
|||
375 |
|
||||
376 | def prompt_for_code(self): |
|
372 | def prompt_for_code(self): | |
377 | with self.pt_cli.patch_stdout_context(raw=True): |
|
373 | if self.rl_next_input: | |
378 |
d |
|
374 | default = self.rl_next_input | |
379 | pre_run=self.pre_prompt, reset_current_buffer=True) |
|
375 | self.rl_next_input = None | |
380 | return document.text |
|
376 | else: | |
|
377 | default = '' | |||
|
378 | ||||
|
379 | with patch_stdout(raw=True): | |||
|
380 | text = self.pt_app.prompt( | |||
|
381 | default=default, | |||
|
382 | # pre_run=self.pre_prompt,# reset_current_buffer=True, | |||
|
383 | **self._extra_prompt_options()) | |||
|
384 | return text | |||
381 |
|
385 | |||
382 | def enable_win_unicode_console(self): |
|
386 | def enable_win_unicode_console(self): | |
383 | if sys.version_info >= (3, 6): |
|
387 | if sys.version_info >= (3, 6): | |
@@ -437,22 +441,6 b' class TerminalInteractiveShell(InteractiveShell):' | |||||
437 |
|
441 | |||
438 | rl_next_input = None |
|
442 | rl_next_input = None | |
439 |
|
443 | |||
440 | def pre_prompt(self): |
|
|||
441 | if self.rl_next_input: |
|
|||
442 | # We can't set the buffer here, because it will be reset just after |
|
|||
443 | # this. Adding a callable to pre_run_callables does what we need |
|
|||
444 | # after the buffer is reset. |
|
|||
445 | s = self.rl_next_input |
|
|||
446 | def set_doc(): |
|
|||
447 | self.pt_cli.application.buffer.document = Document(s) |
|
|||
448 | if hasattr(self.pt_cli, 'pre_run_callables'): |
|
|||
449 | self.pt_cli.pre_run_callables.append(set_doc) |
|
|||
450 | else: |
|
|||
451 | # Older version of prompt_toolkit; it's OK to set the document |
|
|||
452 | # directly here. |
|
|||
453 | set_doc() |
|
|||
454 | self.rl_next_input = None |
|
|||
455 |
|
||||
456 | def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED): |
|
444 | def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED): | |
457 |
|
445 | |||
458 | if display_banner is not DISPLAY_BANNER_DEPRECATED: |
|
446 | if display_banner is not DISPLAY_BANNER_DEPRECATED: | |
@@ -515,8 +503,9 b' class TerminalInteractiveShell(InteractiveShell):' | |||||
515 | return |
|
503 | return | |
516 |
|
504 | |||
517 | tokens = self.prompts.rewrite_prompt_tokens() |
|
505 | tokens = self.prompts.rewrite_prompt_tokens() | |
518 |
if self.pt_ |
|
506 | if self.pt_app: | |
519 | self.pt_cli.print_tokens(tokens) |
|
507 | print_formatted_text(PygmentsTokens(tokens), end='', | |
|
508 | style=self.pt_app.app.style) | |||
520 | print(cmd) |
|
509 | print(cmd) | |
521 | else: |
|
510 | else: | |
522 | prompt = ''.join(s for t, s in tokens) |
|
511 | prompt = ''.join(s for t, s in tokens) | |
@@ -531,7 +520,7 b' class TerminalInteractiveShell(InteractiveShell):' | |||||
531 | elif self._prompts_before: |
|
520 | elif self._prompts_before: | |
532 | self.prompts = self._prompts_before |
|
521 | self.prompts = self._prompts_before | |
533 | self._prompts_before = None |
|
522 | self._prompts_before = None | |
534 | self._update_layout() |
|
523 | # self._update_layout() | |
535 |
|
524 | |||
536 |
|
525 | |||
537 | InteractiveShellABC.register(TerminalInteractiveShell) |
|
526 | InteractiveShellABC.register(TerminalInteractiveShell) |
@@ -5,13 +5,15 b' import sys' | |||||
5 |
|
5 | |||
6 | from IPython.core.displayhook import DisplayHook |
|
6 | from IPython.core.displayhook import DisplayHook | |
7 |
|
7 | |||
8 |
from prompt_toolkit. |
|
8 | from prompt_toolkit.formatted_text import fragment_list_width, PygmentsTokens | |
|
9 | from prompt_toolkit.shortcuts import print_formatted_text | |||
|
10 | ||||
9 |
|
11 | |||
10 | class Prompts(object): |
|
12 | class Prompts(object): | |
11 | def __init__(self, shell): |
|
13 | def __init__(self, shell): | |
12 | self.shell = shell |
|
14 | self.shell = shell | |
13 |
|
15 | |||
14 |
def in_prompt_tokens(self |
|
16 | def in_prompt_tokens(self): | |
15 | return [ |
|
17 | return [ | |
16 | (Token.Prompt, 'In ['), |
|
18 | (Token.Prompt, 'In ['), | |
17 | (Token.PromptNum, str(self.shell.execution_count)), |
|
19 | (Token.PromptNum, str(self.shell.execution_count)), | |
@@ -19,9 +21,9 b' class Prompts(object):' | |||||
19 | ] |
|
21 | ] | |
20 |
|
22 | |||
21 | def _width(self): |
|
23 | def _width(self): | |
22 |
return |
|
24 | return fragment_list_width(self.in_prompt_tokens()) | |
23 |
|
25 | |||
24 |
def continuation_prompt_tokens(self, |
|
26 | def continuation_prompt_tokens(self, width=None): | |
25 | if width is None: |
|
27 | if width is None: | |
26 | width = self._width() |
|
28 | width = self._width() | |
27 | return [ |
|
29 | return [ | |
@@ -42,12 +44,12 b' class Prompts(object):' | |||||
42 | ] |
|
44 | ] | |
43 |
|
45 | |||
44 | class ClassicPrompts(Prompts): |
|
46 | class ClassicPrompts(Prompts): | |
45 |
def in_prompt_tokens(self |
|
47 | def in_prompt_tokens(self): | |
46 | return [ |
|
48 | return [ | |
47 | (Token.Prompt, '>>> '), |
|
49 | (Token.Prompt, '>>> '), | |
48 | ] |
|
50 | ] | |
49 |
|
51 | |||
50 |
def continuation_prompt_tokens(self, |
|
52 | def continuation_prompt_tokens(self, width=None): | |
51 | return [ |
|
53 | return [ | |
52 | (Token.Prompt, '... ') |
|
54 | (Token.Prompt, '... ') | |
53 | ] |
|
55 | ] | |
@@ -73,7 +75,9 b' class RichPromptDisplayHook(DisplayHook):' | |||||
73 | # Ask for a newline before multiline output |
|
75 | # Ask for a newline before multiline output | |
74 | self.prompt_end_newline = False |
|
76 | self.prompt_end_newline = False | |
75 |
|
77 | |||
76 |
if self.shell.pt_ |
|
78 | if self.shell.pt_app: | |
77 |
|
|
79 | print_formatted_text(PygmentsTokens(tokens), | |
|
80 | style=self.shell.pt_app.app.style, end='', | |||
|
81 | ) | |||
78 | else: |
|
82 | else: | |
79 | sys.stdout.write(prompt_txt) |
|
83 | sys.stdout.write(prompt_txt) |
@@ -14,8 +14,9 b' from IPython.core.completer import (' | |||||
14 | provisionalcompleter, cursor_to_position, |
|
14 | provisionalcompleter, cursor_to_position, | |
15 | _deduplicate_completions) |
|
15 | _deduplicate_completions) | |
16 | from prompt_toolkit.completion import Completer, Completion |
|
16 | from prompt_toolkit.completion import Completer, Completion | |
17 |
from prompt_toolkit |
|
17 | from prompt_toolkit.lexers import Lexer | |
18 |
from prompt_toolkit |
|
18 | from prompt_toolkit.lexers import PygmentsLexer | |
|
19 | from prompt_toolkit.patch_stdout import patch_stdout | |||
19 |
|
20 | |||
20 | import pygments.lexers as pygments_lexers |
|
21 | import pygments.lexers as pygments_lexers | |
21 |
|
22 | |||
@@ -52,14 +53,11 b' def _adjust_completion_text_based_on_context(text, body, offset):' | |||||
52 |
|
53 | |||
53 | class IPythonPTCompleter(Completer): |
|
54 | class IPythonPTCompleter(Completer): | |
54 | """Adaptor to provide IPython completions to prompt_toolkit""" |
|
55 | """Adaptor to provide IPython completions to prompt_toolkit""" | |
55 |
def __init__(self, ipy_completer=None, shell=None |
|
56 | def __init__(self, ipy_completer=None, shell=None): | |
56 | if shell is None and ipy_completer is None: |
|
57 | if shell is None and ipy_completer is None: | |
57 | raise TypeError("Please pass shell=an InteractiveShell instance.") |
|
58 | raise TypeError("Please pass shell=an InteractiveShell instance.") | |
58 | self._ipy_completer = ipy_completer |
|
59 | self._ipy_completer = ipy_completer | |
59 | self.shell = shell |
|
60 | self.shell = shell | |
60 | if patch_stdout is None: |
|
|||
61 | raise TypeError("Please pass patch_stdout") |
|
|||
62 | self.patch_stdout = patch_stdout |
|
|||
63 |
|
61 | |||
64 | @property |
|
62 | @property | |
65 | def ipy_completer(self): |
|
63 | def ipy_completer(self): | |
@@ -75,7 +73,7 b' class IPythonPTCompleter(Completer):' | |||||
75 | # is imported). This context manager ensures that doesn't interfere with |
|
73 | # is imported). This context manager ensures that doesn't interfere with | |
76 | # the prompt. |
|
74 | # the prompt. | |
77 |
|
75 | |||
78 |
with |
|
76 | with patch_stdout(), provisionalcompleter(): | |
79 | body = document.text |
|
77 | body = document.text | |
80 | cursor_row = document.cursor_position_row |
|
78 | cursor_row = document.cursor_position_row | |
81 | cursor_col = document.cursor_position_col |
|
79 | cursor_col = document.cursor_position_col | |
@@ -143,7 +141,7 b' class IPythonPTLexer(Lexer):' | |||||
143 | 'latex': PygmentsLexer(l.TexLexer), |
|
141 | 'latex': PygmentsLexer(l.TexLexer), | |
144 | } |
|
142 | } | |
145 |
|
143 | |||
146 |
def lex_document(self, |
|
144 | def lex_document(self, document): | |
147 | text = document.text.lstrip() |
|
145 | text = document.text.lstrip() | |
148 |
|
146 | |||
149 | lexer = self.python_lexer |
|
147 | lexer = self.python_lexer | |
@@ -157,4 +155,4 b' class IPythonPTLexer(Lexer):' | |||||
157 | lexer = l |
|
155 | lexer = l | |
158 | break |
|
156 | break | |
159 |
|
157 | |||
160 |
return lexer.lex_document( |
|
158 | return lexer.lex_document(document) |
@@ -12,91 +12,78 b' import sys' | |||||
12 | from typing import Callable |
|
12 | from typing import Callable | |
13 |
|
13 | |||
14 |
|
14 | |||
|
15 | from prompt_toolkit.application.current import get_app | |||
15 | from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER |
|
16 | from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER | |
16 |
from prompt_toolkit.filters import ( |
|
17 | from prompt_toolkit.filters import (has_focus, has_selection, Condition, | |
17 |
|
|
18 | vi_insert_mode, emacs_insert_mode, has_completions, vi_mode) | |
18 | from prompt_toolkit.filters.cli import ViMode, ViNavigationMode |
|
|||
19 | from prompt_toolkit.keys import Keys |
|
|||
20 | from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline |
|
19 | from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline | |
|
20 | from prompt_toolkit.key_binding import KeyBindings | |||
21 |
|
21 | |||
22 | from IPython.utils.decorators import undoc |
|
22 | from IPython.utils.decorators import undoc | |
23 |
|
23 | |||
24 | @undoc |
|
24 | @undoc | |
25 | @Condition |
|
25 | @Condition | |
26 |
def cursor_in_leading_ws( |
|
26 | def cursor_in_leading_ws(): | |
27 |
before = |
|
27 | before = get_app().current_buffer.document.current_line_before_cursor | |
28 | return (not before) or before.isspace() |
|
28 | return (not before) or before.isspace() | |
29 |
|
29 | |||
30 | def register_ipython_shortcuts(registry, shell): |
|
30 | ||
|
31 | def create_ipython_shortcuts(shell): | |||
31 | """Set up the prompt_toolkit keyboard shortcuts for IPython""" |
|
32 | """Set up the prompt_toolkit keyboard shortcuts for IPython""" | |
32 | insert_mode = ViInsertMode() | EmacsInsertMode() |
|
33 | ||
|
34 | kb = KeyBindings() | |||
|
35 | insert_mode = vi_insert_mode | emacs_insert_mode | |||
33 |
|
36 | |||
34 | if getattr(shell, 'handle_return', None): |
|
37 | if getattr(shell, 'handle_return', None): | |
35 | return_handler = shell.handle_return(shell) |
|
38 | return_handler = shell.handle_return(shell) | |
36 | else: |
|
39 | else: | |
37 | return_handler = newline_or_execute_outer(shell) |
|
40 | return_handler = newline_or_execute_outer(shell) | |
38 |
|
41 | |||
39 | # Ctrl+J == Enter, seemingly |
|
42 | kb.add('enter', filter=(has_focus(DEFAULT_BUFFER) | |
40 | registry.add_binding(Keys.ControlJ, |
|
43 | & ~has_selection | |
41 | filter=(HasFocus(DEFAULT_BUFFER) |
|
44 | & insert_mode | |
42 | & ~HasSelection() |
|
|||
43 | & insert_mode |
|
|||
44 | ))(return_handler) |
|
45 | ))(return_handler) | |
45 |
|
46 | |||
46 | registry.add_binding(Keys.ControlBackslash)(force_exit) |
|
47 | kb.add('c-\\')(force_exit) | |
47 |
|
48 | |||
48 | registry.add_binding(Keys.ControlP, |
|
49 | kb.add('c-p', filter=(vi_insert_mode & has_focus(DEFAULT_BUFFER)) | |
49 | filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER) |
|
50 | )(previous_history_or_previous_completion) | |
50 | ))(previous_history_or_previous_completion) |
|
|||
51 |
|
51 | |||
52 | registry.add_binding(Keys.ControlN, |
|
52 | kb.add('c-n', filter=(vi_insert_mode & has_focus(DEFAULT_BUFFER)) | |
53 | filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER) |
|
53 | )(next_history_or_next_completion) | |
54 | ))(next_history_or_next_completion) |
|
|||
55 |
|
54 | |||
56 | registry.add_binding(Keys.ControlG, |
|
55 | kb.add('c-g', filter=(has_focus(DEFAULT_BUFFER) & has_completions) | |
57 | filter=(HasFocus(DEFAULT_BUFFER) & HasCompletions() |
|
56 | )(dismiss_completion) | |
58 | ))(dismiss_completion) |
|
|||
59 |
|
57 | |||
60 | registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER) |
|
58 | kb.add('c-c', filter=has_focus(DEFAULT_BUFFER))(reset_buffer) | |
61 | )(reset_buffer) |
|
|||
62 |
|
59 | |||
63 | registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER) |
|
60 | kb.add('c-c', filter=has_focus(SEARCH_BUFFER))(reset_search_buffer) | |
64 | )(reset_search_buffer) |
|
|||
65 |
|
61 | |||
66 |
supports_suspend = Condition(lambda |
|
62 | supports_suspend = Condition(lambda: hasattr(signal, 'SIGTSTP')) | |
67 | registry.add_binding(Keys.ControlZ, filter=supports_suspend |
|
63 | kb.add('c-z', filter=supports_suspend)(suspend_to_bg) | |
68 | )(suspend_to_bg) |
|
|||
69 |
|
64 | |||
70 | # Ctrl+I == Tab |
|
65 | # Ctrl+I == Tab | |
71 | registry.add_binding(Keys.ControlI, |
|
66 | kb.add('tab', filter=(has_focus(DEFAULT_BUFFER) | |
72 | filter=(HasFocus(DEFAULT_BUFFER) |
|
67 | & ~has_selection | |
73 |
|
|
68 | & insert_mode | |
74 |
|
|
69 | & cursor_in_leading_ws | |
75 | & cursor_in_leading_ws |
|
|||
76 | ))(indent_buffer) |
|
70 | ))(indent_buffer) | |
|
71 | kb.add('c-o', filter=(has_focus(DEFAULT_BUFFER) | |||
|
72 | & emacs_insert_mode))(newline_autoindent_outer(shell.input_transformer_manager)) | |||
77 |
|
73 | |||
78 | registry.add_binding(Keys.ControlO, |
|
74 | kb.add('f2', filter=has_focus(DEFAULT_BUFFER))(open_input_in_editor) | |
79 | filter=(HasFocus(DEFAULT_BUFFER) |
|
|||
80 | & EmacsInsertMode()))(newline_autoindent_outer(shell.input_transformer_manager)) |
|
|||
81 |
|
||||
82 | registry.add_binding(Keys.F2, |
|
|||
83 | filter=HasFocus(DEFAULT_BUFFER) |
|
|||
84 | )(open_input_in_editor) |
|
|||
85 |
|
75 | |||
86 | if shell.display_completions == 'readlinelike': |
|
76 | if shell.display_completions == 'readlinelike': | |
87 | registry.add_binding(Keys.ControlI, |
|
77 | kb.add('c-i', filter=(has_focus(DEFAULT_BUFFER) | |
88 | filter=(HasFocus(DEFAULT_BUFFER) |
|
78 | & ~has_selection | |
89 |
|
|
79 | & insert_mode | |
90 |
|
|
80 | & ~cursor_in_leading_ws | |
91 | & ~cursor_in_leading_ws |
|
81 | ))(display_completions_like_readline) | |
92 | ))(display_completions_like_readline) |
|
|||
93 |
|
82 | |||
94 | if sys.platform == 'win32': |
|
83 | if sys.platform == 'win32': | |
95 | registry.add_binding(Keys.ControlV, |
|
84 | kb.add('c-v', filter=(has_focus(DEFAULT_BUFFER) & ~vi_mode))(win_paste) | |
96 | filter=( |
|
85 | ||
97 | HasFocus( |
|
86 | return kb | |
98 | DEFAULT_BUFFER) & ~ViMode() |
|
|||
99 | ))(win_paste) |
|
|||
100 |
|
87 | |||
101 |
|
88 | |||
102 | def newline_or_execute_outer(shell): |
|
89 | def newline_or_execute_outer(shell): | |
@@ -127,8 +114,8 b' def newline_or_execute_outer(shell):' | |||||
127 | b.insert_text('\n' + indent) |
|
114 | b.insert_text('\n' + indent) | |
128 | return |
|
115 | return | |
129 |
|
116 | |||
130 |
if (status != 'incomplete') and b.accept_ |
|
117 | if (status != 'incomplete') and b.accept_handler: | |
131 |
b. |
|
118 | b.validate_and_handle() | |
132 | else: |
|
119 | else: | |
133 | b.insert_text('\n' + indent) |
|
120 | b.insert_text('\n' + indent) | |
134 | return newline_or_execute |
|
121 | return newline_or_execute | |
@@ -170,10 +157,10 b' def reset_search_buffer(event):' | |||||
170 | if event.current_buffer.document.text: |
|
157 | if event.current_buffer.document.text: | |
171 | event.current_buffer.reset() |
|
158 | event.current_buffer.reset() | |
172 | else: |
|
159 | else: | |
173 |
event. |
|
160 | event.app.layout.focus(DEFAULT_BUFFER) | |
174 |
|
161 | |||
175 | def suspend_to_bg(event): |
|
162 | def suspend_to_bg(event): | |
176 |
event. |
|
163 | event.app.suspend_to_background() | |
177 |
|
164 | |||
178 | def force_exit(event): |
|
165 | def force_exit(event): | |
179 | """ |
|
166 | """ | |
@@ -232,8 +219,8 b' def newline_autoindent_outer(inputsplitter) -> Callable[..., None]:' | |||||
232 |
|
219 | |||
233 |
|
220 | |||
234 | def open_input_in_editor(event): |
|
221 | def open_input_in_editor(event): | |
235 |
event. |
|
222 | event.app.current_buffer.tempfile_suffix = ".py" | |
236 |
event. |
|
223 | event.app.current_buffer.open_in_editor() | |
237 |
|
224 | |||
238 |
|
225 | |||
239 | if sys.platform == 'win32': |
|
226 | if sys.platform == 'win32': |
@@ -69,7 +69,7 b' if version_info < (6,):' | |||||
69 | warnings.filterwarnings( |
|
69 | warnings.filterwarnings( | |
70 | 'ignore', message='.*Please use assertEqual instead', category=Warning, module='IPython.*') |
|
70 | 'ignore', message='.*Please use assertEqual instead', category=Warning, module='IPython.*') | |
71 |
|
71 | |||
72 |
if version_info < ( |
|
72 | if version_info < (8,): | |
73 | warnings.filterwarnings('ignore', message='.*Completer.complete.*', |
|
73 | warnings.filterwarnings('ignore', message='.*Completer.complete.*', | |
74 | category=PendingDeprecationWarning, module='.*') |
|
74 | category=PendingDeprecationWarning, module='.*') | |
75 | else: |
|
75 | else: |
@@ -46,29 +46,26 b' Authors' | |||||
46 | #----------------------------------------------------------------------------- |
|
46 | #----------------------------------------------------------------------------- | |
47 |
|
47 | |||
48 | from IPython.testing.ipunittest import ipdoctest, ipdocstring |
|
48 | from IPython.testing.ipunittest import ipdoctest, ipdocstring | |
49 | from IPython.utils.py3compat import doctest_refactor_print |
|
|||
50 |
|
49 | |||
51 | #----------------------------------------------------------------------------- |
|
50 | #----------------------------------------------------------------------------- | |
52 | # Test classes and functions |
|
51 | # Test classes and functions | |
53 | #----------------------------------------------------------------------------- |
|
52 | #----------------------------------------------------------------------------- | |
54 | @ipdoctest |
|
53 | @ipdoctest | |
55 | @doctest_refactor_print |
|
|||
56 | def simple_dt(): |
|
54 | def simple_dt(): | |
57 | """ |
|
55 | """ | |
58 |
>>> print |
|
56 | >>> print(1+1) | |
59 | 2 |
|
57 | 2 | |
60 | """ |
|
58 | """ | |
61 |
|
59 | |||
62 |
|
60 | |||
63 | @ipdoctest |
|
61 | @ipdoctest | |
64 | @doctest_refactor_print |
|
|||
65 | def ipdt_flush(): |
|
62 | def ipdt_flush(): | |
66 | """ |
|
63 | """ | |
67 |
In [20]: print |
|
64 | In [20]: print(1) | |
68 | 1 |
|
65 | 1 | |
69 |
|
66 | |||
70 | In [26]: for i in range(4): |
|
67 | In [26]: for i in range(4): | |
71 |
....: print |
|
68 | ....: print(i) | |
72 | ....: |
|
69 | ....: | |
73 | ....: |
|
70 | ....: | |
74 | 0 |
|
71 | 0 | |
@@ -82,14 +79,13 b' Out[27]: 7' | |||||
82 |
|
79 | |||
83 |
|
80 | |||
84 | @ipdoctest |
|
81 | @ipdoctest | |
85 | @doctest_refactor_print |
|
|||
86 | def ipdt_indented_test(): |
|
82 | def ipdt_indented_test(): | |
87 | """ |
|
83 | """ | |
88 |
In [20]: print |
|
84 | In [20]: print(1) | |
89 | 1 |
|
85 | 1 | |
90 |
|
86 | |||
91 | In [26]: for i in range(4): |
|
87 | In [26]: for i in range(4): | |
92 |
....: print |
|
88 | ....: print(i) | |
93 | ....: |
|
89 | ....: | |
94 | ....: |
|
90 | ....: | |
95 | 0 |
|
91 | 0 | |
@@ -110,14 +106,13 b' class Foo(object):' | |||||
110 | """ |
|
106 | """ | |
111 |
|
107 | |||
112 | @ipdocstring |
|
108 | @ipdocstring | |
113 | @doctest_refactor_print |
|
|||
114 | def ipdt_method(self): |
|
109 | def ipdt_method(self): | |
115 | """ |
|
110 | """ | |
116 |
In [20]: print |
|
111 | In [20]: print(1) | |
117 | 1 |
|
112 | 1 | |
118 |
|
113 | |||
119 | In [26]: for i in range(4): |
|
114 | In [26]: for i in range(4): | |
120 |
....: print |
|
115 | ....: print(i) | |
121 | ....: |
|
116 | ....: | |
122 | ....: |
|
117 | ....: | |
123 | 0 |
|
118 | 0 | |
@@ -129,9 +124,8 b' class Foo(object):' | |||||
129 | Out[27]: 7 |
|
124 | Out[27]: 7 | |
130 | """ |
|
125 | """ | |
131 |
|
126 | |||
132 | @doctest_refactor_print |
|
|||
133 | def normaldt_method(self): |
|
127 | def normaldt_method(self): | |
134 | """ |
|
128 | """ | |
135 |
>>> print |
|
129 | >>> print(1+1) | |
136 | 2 |
|
130 | 2 | |
137 | """ |
|
131 | """ |
@@ -270,20 +270,25 b' class TempFileMixin(object):' | |||||
270 | def mktmp(self, src, ext='.py'): |
|
270 | def mktmp(self, src, ext='.py'): | |
271 | """Make a valid python temp file.""" |
|
271 | """Make a valid python temp file.""" | |
272 | fname, f = temp_pyfile(src, ext) |
|
272 | fname, f = temp_pyfile(src, ext) | |
273 | self.tmpfile = f |
|
273 | if not hasattr(self, 'tmps'): | |
|
274 | self.tmps=[] | |||
|
275 | self.tmps.append((f, fname)) | |||
274 | self.fname = fname |
|
276 | self.fname = fname | |
275 |
|
277 | |||
276 | def tearDown(self): |
|
278 | def tearDown(self): | |
277 | if hasattr(self, 'tmpfile'): |
|
279 | # If the tmpfile wasn't made because of skipped tests, like in | |
278 | # If the tmpfile wasn't made because of skipped tests, like in |
|
280 | # win32, there's nothing to cleanup. | |
279 | # win32, there's nothing to cleanup. |
|
281 | if hasattr(self, 'tmps'): | |
280 |
self.tmp |
|
282 | for f,fname in self.tmps: | |
281 | try: |
|
283 | # If the tmpfile wasn't made because of skipped tests, like in | |
282 | os.unlink(self.fname) |
|
284 | # win32, there's nothing to cleanup. | |
283 | except: |
|
285 | f.close() | |
284 | # On Windows, even though we close the file, we still can't |
|
286 | try: | |
285 | # delete it. I have no clue why |
|
287 | os.unlink(fname) | |
286 |
|
|
288 | except: | |
|
289 | # On Windows, even though we close the file, we still can't | |||
|
290 | # delete it. I have no clue why | |||
|
291 | pass | |||
287 |
|
292 | |||
288 | def __enter__(self): |
|
293 | def __enter__(self): | |
289 | return self |
|
294 | return self |
@@ -29,7 +29,7 b' scan Python source code and re-emit it with no changes to its original' | |||||
29 | formatting (which is the hard part). |
|
29 | formatting (which is the hard part). | |
30 | """ |
|
30 | """ | |
31 |
|
31 | |||
32 | __all__ = ['ANSICodeColors','Parser'] |
|
32 | __all__ = ['ANSICodeColors', 'Parser'] | |
33 |
|
33 | |||
34 | _scheme_default = 'Linux' |
|
34 | _scheme_default = 'Linux' | |
35 |
|
35 | |||
@@ -43,7 +43,7 b' import tokenize' | |||||
43 |
|
43 | |||
44 | generate_tokens = tokenize.generate_tokens |
|
44 | generate_tokens = tokenize.generate_tokens | |
45 |
|
45 | |||
46 |
from IPython.utils.coloransi import TermColors, InputTermColors |
|
46 | from IPython.utils.coloransi import TermColors, InputTermColors,ColorScheme, ColorSchemeTable | |
47 | from .colorable import Colorable |
|
47 | from .colorable import Colorable | |
48 | from io import StringIO |
|
48 | from io import StringIO | |
49 |
|
49 | |||
@@ -185,8 +185,11 b' class Parser(Colorable):' | |||||
185 |
|
185 | |||
186 | super(Parser, self).__init__(parent=parent) |
|
186 | super(Parser, self).__init__(parent=parent) | |
187 |
|
187 | |||
188 |
self.color_table = color_table |
|
188 | self.color_table = color_table if color_table else ANSICodeColors | |
189 | self.out = out |
|
189 | self.out = out | |
|
190 | self.pos = None | |||
|
191 | self.lines = None | |||
|
192 | self.raw = None | |||
190 | if not style: |
|
193 | if not style: | |
191 | self.style = self.default_style |
|
194 | self.style = self.default_style | |
192 | else: |
|
195 | else: | |
@@ -213,7 +216,7 b' class Parser(Colorable):' | |||||
213 |
|
216 | |||
214 | string_output = 0 |
|
217 | string_output = 0 | |
215 | if out == 'str' or self.out == 'str' or \ |
|
218 | if out == 'str' or self.out == 'str' or \ | |
216 | isinstance(self.out,StringIO): |
|
219 | isinstance(self.out, StringIO): | |
217 | # XXX - I don't really like this state handling logic, but at this |
|
220 | # XXX - I don't really like this state handling logic, but at this | |
218 | # point I don't want to make major changes, so adding the |
|
221 | # point I don't want to make major changes, so adding the | |
219 | # isinstance() check is the simplest I can do to ensure correct |
|
222 | # isinstance() check is the simplest I can do to ensure correct | |
@@ -223,15 +226,16 b' class Parser(Colorable):' | |||||
223 | string_output = 1 |
|
226 | string_output = 1 | |
224 | elif out is not None: |
|
227 | elif out is not None: | |
225 | self.out = out |
|
228 | self.out = out | |
|
229 | else: | |||
|
230 | raise ValueError('`out` or `self.out` should be file-like or the value `"str"`') | |||
226 |
|
231 | |||
227 | # Fast return of the unmodified input for NoColor scheme |
|
232 | # Fast return of the unmodified input for NoColor scheme | |
228 | if self.style == 'NoColor': |
|
233 | if self.style == 'NoColor': | |
229 | error = False |
|
234 | error = False | |
230 | self.out.write(raw) |
|
235 | self.out.write(raw) | |
231 | if string_output: |
|
236 | if string_output: | |
232 | return raw,error |
|
237 | return raw, error | |
233 | else: |
|
238 | return None, error | |
234 | return None,error |
|
|||
235 |
|
239 | |||
236 | # local shorthands |
|
240 | # local shorthands | |
237 | colors = self.color_table[self.style].colors |
|
241 | colors = self.color_table[self.style].colors | |
@@ -245,9 +249,10 b' class Parser(Colorable):' | |||||
245 | pos = 0 |
|
249 | pos = 0 | |
246 | raw_find = self.raw.find |
|
250 | raw_find = self.raw.find | |
247 | lines_append = self.lines.append |
|
251 | lines_append = self.lines.append | |
248 |
while |
|
252 | while True: | |
249 | pos = raw_find('\n', pos) + 1 |
|
253 | pos = raw_find('\n', pos) + 1 | |
250 |
if not pos: |
|
254 | if not pos: | |
|
255 | break | |||
251 | lines_append(pos) |
|
256 | lines_append(pos) | |
252 | lines_append(len(self.raw)) |
|
257 | lines_append(len(self.raw)) | |
253 |
|
258 | |||
@@ -275,12 +280,13 b' class Parser(Colorable):' | |||||
275 | return (output, error) |
|
280 | return (output, error) | |
276 | return (None, error) |
|
281 | return (None, error) | |
277 |
|
282 | |||
278 | def __call__(self, toktype, toktext, start_pos, end_pos, line): |
|
283 | ||
279 | """ Token handler, with syntax highlighting.""" |
|
284 | def _inner_call_(self, toktype, toktext, start_pos): | |
280 | (srow,scol) = start_pos |
|
285 | """like call but write to a temporary buffer""" | |
281 | (erow,ecol) = end_pos |
|
286 | buff = StringIO() | |
|
287 | srow, scol = start_pos | |||
282 | colors = self.colors |
|
288 | colors = self.colors | |
283 |
owrite = |
|
289 | owrite = buff.write | |
284 |
|
290 | |||
285 | # line separator, so this works across platforms |
|
291 | # line separator, so this works across platforms | |
286 | linesep = os.linesep |
|
292 | linesep = os.linesep | |
@@ -297,7 +303,8 b' class Parser(Colorable):' | |||||
297 | # skip indenting tokens |
|
303 | # skip indenting tokens | |
298 | if toktype in [token.INDENT, token.DEDENT]: |
|
304 | if toktype in [token.INDENT, token.DEDENT]: | |
299 | self.pos = newpos |
|
305 | self.pos = newpos | |
300 |
|
|
306 | buff.seek(0) | |
|
307 | return buff.read() | |||
301 |
|
308 | |||
302 | # map token type to a color group |
|
309 | # map token type to a color group | |
303 | if token.LPAR <= toktype <= token.OP: |
|
310 | if token.LPAR <= toktype <= token.OP: | |
@@ -306,8 +313,6 b' class Parser(Colorable):' | |||||
306 | toktype = _KEYWORD |
|
313 | toktype = _KEYWORD | |
307 | color = colors.get(toktype, colors[_TEXT]) |
|
314 | color = colors.get(toktype, colors[_TEXT]) | |
308 |
|
315 | |||
309 | #print '<%s>' % toktext, # dbg |
|
|||
310 |
|
||||
311 | # Triple quoted strings must be handled carefully so that backtracking |
|
316 | # Triple quoted strings must be handled carefully so that backtracking | |
312 | # in pagers works correctly. We need color terminators on _each_ line. |
|
317 | # in pagers works correctly. We need color terminators on _each_ line. | |
313 | if linesep in toktext: |
|
318 | if linesep in toktext: | |
@@ -316,3 +321,11 b' class Parser(Colorable):' | |||||
316 |
|
321 | |||
317 | # send text |
|
322 | # send text | |
318 | owrite('%s%s%s' % (color,toktext,colors.normal)) |
|
323 | owrite('%s%s%s' % (color,toktext,colors.normal)) | |
|
324 | buff.seek(0) | |||
|
325 | return buff.read() | |||
|
326 | ||||
|
327 | ||||
|
328 | def __call__(self, toktype, toktext, start_pos, end_pos, line): | |||
|
329 | """ Token handler, with syntax highlighting.""" | |||
|
330 | self.out.write( | |||
|
331 | self._inner_call_(toktype, toktext, start_pos)) |
@@ -23,12 +23,6 b' def uniq_stable(elems):' | |||||
23 | return [x for x in elems if x not in seen and not seen.add(x)] |
|
23 | return [x for x in elems if x not in seen and not seen.add(x)] | |
24 |
|
24 | |||
25 |
|
25 | |||
26 | def flatten(seq): |
|
|||
27 | """Flatten a list of lists (NOT recursive, only works for 2d lists).""" |
|
|||
28 |
|
||||
29 | return [x for subseq in seq for x in subseq] |
|
|||
30 |
|
||||
31 |
|
||||
32 | def chop(seq, size): |
|
26 | def chop(seq, size): | |
33 | """Chop a sequence into chunks of the given size.""" |
|
27 | """Chop a sequence into chunks of the given size.""" | |
34 | return [seq[i:i+size] for i in range(0,len(seq),size)] |
|
28 | return [seq[i:i+size] for i in range(0,len(seq),size)] |
@@ -21,7 +21,6 b' from IPython.utils import py3compat' | |||||
21 | # Code |
|
21 | # Code | |
22 | #----------------------------------------------------------------------------- |
|
22 | #----------------------------------------------------------------------------- | |
23 |
|
23 | |||
24 | @py3compat.doctest_refactor_print |
|
|||
25 | def extract_vars(*names,**kw): |
|
24 | def extract_vars(*names,**kw): | |
26 | """Extract a set of variables by name from another frame. |
|
25 | """Extract a set of variables by name from another frame. | |
27 |
|
26 |
@@ -17,7 +17,6 b' from warnings import warn' | |||||
17 |
|
17 | |||
18 | from IPython.utils.decorators import undoc |
|
18 | from IPython.utils.decorators import undoc | |
19 | from .capture import CapturedIO, capture_output |
|
19 | from .capture import CapturedIO, capture_output | |
20 | from .py3compat import input |
|
|||
21 |
|
20 | |||
22 | @undoc |
|
21 | @undoc | |
23 | class IOStream: |
|
22 | class IOStream: | |
@@ -211,35 +210,34 b" def temp_pyfile(src, ext='.py'):" | |||||
211 | f.flush() |
|
210 | f.flush() | |
212 | return fname, f |
|
211 | return fname, f | |
213 |
|
212 | |||
|
213 | @undoc | |||
214 | def atomic_writing(*args, **kwargs): |
|
214 | def atomic_writing(*args, **kwargs): | |
215 | """DEPRECATED: moved to notebook.services.contents.fileio""" |
|
215 | """DEPRECATED: moved to notebook.services.contents.fileio""" | |
216 | warn("IPython.utils.io.atomic_writing has moved to notebook.services.contents.fileio", stacklevel=2) |
|
216 | warn("IPython.utils.io.atomic_writing has moved to notebook.services.contents.fileio since IPython 4.0", DeprecationWarning, stacklevel=2) | |
217 | from notebook.services.contents.fileio import atomic_writing |
|
217 | from notebook.services.contents.fileio import atomic_writing | |
218 | return atomic_writing(*args, **kwargs) |
|
218 | return atomic_writing(*args, **kwargs) | |
219 |
|
219 | |||
|
220 | @undoc | |||
220 | def raw_print(*args, **kw): |
|
221 | def raw_print(*args, **kw): | |
221 | """Raw print to sys.__stdout__, otherwise identical interface to print().""" |
|
222 | """DEPRECATED: Raw print to sys.__stdout__, otherwise identical interface to print().""" | |
|
223 | warn("IPython.utils.io.raw_print has been deprecated since IPython 7.0", DeprecationWarning, stacklevel=2) | |||
222 |
|
224 | |||
223 | print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'), |
|
225 | print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'), | |
224 | file=sys.__stdout__) |
|
226 | file=sys.__stdout__) | |
225 | sys.__stdout__.flush() |
|
227 | sys.__stdout__.flush() | |
226 |
|
228 | |||
227 |
|
229 | @undoc | ||
228 | def raw_print_err(*args, **kw): |
|
230 | def raw_print_err(*args, **kw): | |
229 | """Raw print to sys.__stderr__, otherwise identical interface to print().""" |
|
231 | """DEPRECATED: Raw print to sys.__stderr__, otherwise identical interface to print().""" | |
|
232 | warn("IPython.utils.io.raw_print_err has been deprecated since IPython 7.0", DeprecationWarning, stacklevel=2) | |||
230 |
|
233 | |||
231 | print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'), |
|
234 | print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'), | |
232 | file=sys.__stderr__) |
|
235 | file=sys.__stderr__) | |
233 | sys.__stderr__.flush() |
|
236 | sys.__stderr__.flush() | |
234 |
|
237 | |||
235 |
|
238 | @undoc | ||
236 | # Short aliases for quick debugging, do NOT use these in production code. |
|
|||
237 | rprint = raw_print |
|
|||
238 | rprinte = raw_print_err |
|
|||
239 |
|
||||
240 |
|
||||
241 | def unicode_std_stream(stream='stdout'): |
|
239 | def unicode_std_stream(stream='stdout'): | |
242 | """DEPRECATED, moved to nbconvert.utils.io""" |
|
240 | """DEPRECATED, moved to nbconvert.utils.io""" | |
243 | warn("IPython.utils.io.unicode_std_stream has moved to nbconvert.utils.io", stacklevel=2) |
|
241 | warn("IPython.utils.io.unicode_std_stream has moved to nbconvert.utils.io since IPython 4.0", DeprecationWarning, stacklevel=2) | |
244 | from nbconvert.utils.io import unicode_std_stream |
|
242 | from nbconvert.utils.io import unicode_std_stream | |
245 | return unicode_std_stream(stream) |
|
243 | return unicode_std_stream(stream) |
@@ -103,19 +103,3 b" def read_py_url(url, errors='replace', skip_encoding_cookie=True):" | |||||
103 | response = urlopen(url) |
|
103 | response = urlopen(url) | |
104 | buffer = io.BytesIO(response.read()) |
|
104 | buffer = io.BytesIO(response.read()) | |
105 | return source_to_unicode(buffer, errors, skip_encoding_cookie) |
|
105 | return source_to_unicode(buffer, errors, skip_encoding_cookie) | |
106 |
|
||||
107 | def _list_readline(x): |
|
|||
108 | """Given a list, returns a readline() function that returns the next element |
|
|||
109 | with each call. |
|
|||
110 | """ |
|
|||
111 | x = iter(x) |
|
|||
112 | def readline(): |
|
|||
113 | return next(x) |
|
|||
114 | return readline |
|
|||
115 |
|
||||
116 | # Code for going between .py files and cached .pyc files ---------------------- |
|
|||
117 | try: |
|
|||
118 | from importlib.util import source_from_cache, cache_from_source |
|
|||
119 | except ImportError : |
|
|||
120 | ## deprecated since 3.4 |
|
|||
121 | from imp import source_from_cache, cache_from_source |
|
@@ -21,7 +21,7 b' import sys' | |||||
21 | import subprocess |
|
21 | import subprocess | |
22 |
|
22 | |||
23 | from IPython.core import release |
|
23 | from IPython.core import release | |
24 |
from IPython.utils import |
|
24 | from IPython.utils import _sysinfo, encoding | |
25 |
|
25 | |||
26 | #----------------------------------------------------------------------------- |
|
26 | #----------------------------------------------------------------------------- | |
27 | # Code |
|
27 | # Code | |
@@ -98,7 +98,6 b' def get_sys_info():' | |||||
98 | path = p.realpath(p.dirname(p.abspath(p.join(__file__, '..')))) |
|
98 | path = p.realpath(p.dirname(p.abspath(p.join(__file__, '..')))) | |
99 | return pkg_info(path) |
|
99 | return pkg_info(path) | |
100 |
|
100 | |||
101 | @py3compat.doctest_refactor_print |
|
|||
102 | def sys_info(): |
|
101 | def sys_info(): | |
103 | """Return useful information about IPython and the system, as a string. |
|
102 | """Return useful information about IPython and the system, as a string. | |
104 |
|
103 | |||
@@ -106,7 +105,7 b' def sys_info():' | |||||
106 | -------- |
|
105 | -------- | |
107 | :: |
|
106 | :: | |
108 |
|
107 | |||
109 |
In [2]: print |
|
108 | In [2]: print(sys_info()) | |
110 | {'commit_hash': '144fdae', # random |
|
109 | {'commit_hash': '144fdae', # random | |
111 | 'commit_source': 'repository', |
|
110 | 'commit_source': 'repository', | |
112 | 'ipython_path': '/home/fperez/usr/lib/python2.6/site-packages/IPython', |
|
111 | 'ipython_path': '/home/fperez/usr/lib/python2.6/site-packages/IPython', |
@@ -18,7 +18,6 b' import nose.tools as nt' | |||||
18 |
|
18 | |||
19 | from IPython.testing.decorators import skipif, skip_win32 |
|
19 | from IPython.testing.decorators import skipif, skip_win32 | |
20 | from IPython.utils.io import IOStream, Tee, capture_output |
|
20 | from IPython.utils.io import IOStream, Tee, capture_output | |
21 | from IPython.utils.py3compat import doctest_refactor_print |
|
|||
22 | from IPython.utils.tempdir import TemporaryDirectory |
|
21 | from IPython.utils.tempdir import TemporaryDirectory | |
23 |
|
22 | |||
24 |
|
23 | |||
@@ -59,7 +58,7 b' class TeeTestCase(unittest.TestCase):' | |||||
59 | def test_io_init(): |
|
58 | def test_io_init(): | |
60 | """Test that io.stdin/out/err exist at startup""" |
|
59 | """Test that io.stdin/out/err exist at startup""" | |
61 | for name in ('stdin', 'stdout', 'stderr'): |
|
60 | for name in ('stdin', 'stdout', 'stderr'): | |
62 |
cmd = |
|
61 | cmd = "from IPython.utils import io;print(io.%s.__class__)"%name | |
63 | p = Popen([sys.executable, '-c', cmd], |
|
62 | p = Popen([sys.executable, '-c', cmd], | |
64 | stdout=PIPE) |
|
63 | stdout=PIPE) | |
65 | p.wait() |
|
64 | p.wait() |
@@ -29,11 +29,3 b' def test_source_to_unicode():' | |||||
29 |
|
29 | |||
30 | source_no_cookie = openpy.source_to_unicode(source_bytes, skip_encoding_cookie=True) |
|
30 | source_no_cookie = openpy.source_to_unicode(source_bytes, skip_encoding_cookie=True) | |
31 | nt.assert_not_in(u'coding: iso-8859-5', source_no_cookie) |
|
31 | nt.assert_not_in(u'coding: iso-8859-5', source_no_cookie) | |
32 |
|
||||
33 | def test_list_readline(): |
|
|||
34 | l = ['a', 'b'] |
|
|||
35 | readline = openpy._list_readline(l) |
|
|||
36 | nt.assert_equal(readline(), 'a') |
|
|||
37 | nt.assert_equal(readline(), 'b') |
|
|||
38 | with nt.assert_raises(StopIteration): |
|
|||
39 | readline() No newline at end of file |
|
@@ -18,11 +18,7 b' import random' | |||||
18 | import sys |
|
18 | import sys | |
19 |
|
19 | |||
20 | import nose.tools as nt |
|
20 | import nose.tools as nt | |
21 | try: |
|
21 | from pathlib import Path | |
22 | from pathlib import Path |
|
|||
23 | except ImportError: |
|
|||
24 | # for Python 3.3 |
|
|||
25 | from pathlib2 import Path |
|
|||
26 |
|
22 | |||
27 | from IPython.utils import text |
|
23 | from IPython.utils import text | |
28 |
|
24 | |||
@@ -137,13 +133,9 b' def eval_formatter_no_slicing_check(f):' | |||||
137 |
|
133 | |||
138 | s = f.format('{stuff[slice(1,4)]}', **ns) |
|
134 | s = f.format('{stuff[slice(1,4)]}', **ns) | |
139 | nt.assert_equal(s, 'ell') |
|
135 | nt.assert_equal(s, 'ell') | |
140 |
|
136 | |||
141 | if sys.version_info >= (3, 4): |
|
137 | s = f.format("{a[:]}", a=[1, 2]) | |
142 | # String formatting has changed in Python 3.4, so this now works. |
|
138 | nt.assert_equal(s, "[1, 2]") | |
143 | s = f.format("{a[:]}", a=[1, 2]) |
|
|||
144 | nt.assert_equal(s, "[1, 2]") |
|
|||
145 | else: |
|
|||
146 | nt.assert_raises(SyntaxError, f.format, "{a[:]}") |
|
|||
147 |
|
139 | |||
148 | def test_eval_formatter(): |
|
140 | def test_eval_formatter(): | |
149 | f = text.EvalFormatter() |
|
141 | f = text.EvalFormatter() |
@@ -13,11 +13,7 b' import re' | |||||
13 | import sys |
|
13 | import sys | |
14 | import textwrap |
|
14 | import textwrap | |
15 | from string import Formatter |
|
15 | from string import Formatter | |
16 | try: |
|
16 | from pathlib import Path | |
17 | from pathlib import Path |
|
|||
18 | except ImportError: |
|
|||
19 | # for Python 3.3 |
|
|||
20 | from pathlib2 import Path |
|
|||
21 |
|
17 | |||
22 | from IPython.utils import py3compat |
|
18 | from IPython.utils import py3compat | |
23 |
|
19 | |||
@@ -665,7 +661,7 b' def compute_item_matrix(items, row_first=False, empty=None, *args, **kwargs) :' | |||||
665 | empty : (default None) |
|
661 | empty : (default None) | |
666 | default value to fill list if needed |
|
662 | default value to fill list if needed | |
667 | separator_size : int (default=2) |
|
663 | separator_size : int (default=2) | |
668 | How much caracters will be used as a separation between each columns. |
|
664 | How much characters will be used as a separation between each columns. | |
669 | displaywidth : int (default=80) |
|
665 | displaywidth : int (default=80) | |
670 | The width of the area onto which the columns should enter |
|
666 | The width of the area onto which the columns should enter | |
671 |
|
667 |
@@ -1,7 +1,16 b'' | |||||
1 | include README.rst |
|
1 | include README.rst | |
2 | include COPYING.rst |
|
2 | include COPYING.rst | |
|
3 | include LICENSE | |||
3 | include setupbase.py |
|
4 | include setupbase.py | |
4 | include setupegg.py |
|
5 | include setupegg.py | |
|
6 | include MANIFEST.in | |||
|
7 | include tox.ini | |||
|
8 | include .mailmap | |||
|
9 | ||||
|
10 | recursive-exclude tools * | |||
|
11 | exclude tools | |||
|
12 | exclude CONTRIBUTING.md | |||
|
13 | exclude .editorconfig | |||
5 |
|
14 | |||
6 | graft setupext |
|
15 | graft setupext | |
7 |
|
16 | |||
@@ -29,6 +38,7 b' prune docs/dist' | |||||
29 | # Patterns to exclude from any directory |
|
38 | # Patterns to exclude from any directory | |
30 | global-exclude *~ |
|
39 | global-exclude *~ | |
31 | global-exclude *.flc |
|
40 | global-exclude *.flc | |
|
41 | global-exclude *.yml | |||
32 | global-exclude *.pyc |
|
42 | global-exclude *.pyc | |
33 | global-exclude *.pyo |
|
43 | global-exclude *.pyo | |
34 | global-exclude .dircopy.log |
|
44 | global-exclude .dircopy.log |
@@ -23,7 +23,9 b' contribute to the project.' | |||||
23 |
|
23 | |||
24 | **IPython versions and Python Support** |
|
24 | **IPython versions and Python Support** | |
25 |
|
25 | |||
26 |
**IPython |
|
26 | **IPython 7.0** requires Python version 3.4 and above. | |
|
27 | ||||
|
28 | **IPython 6.x** requires Python version 3.3 and above. | |||
27 |
|
29 | |||
28 | **IPython 5.x LTS** is the compatible release for Python 2.7. |
|
30 | **IPython 5.x LTS** is the compatible release for Python 2.7. | |
29 | If you require Python 2 support, you **must** use IPython 5.x LTS. Please |
|
31 | If you require Python 2 support, you **must** use IPython 5.x LTS. Please | |
@@ -31,7 +33,7 b' update your project configurations and requirements as necessary.' | |||||
31 |
|
33 | |||
32 |
|
34 | |||
33 | The Notebook, Qt console and a number of other pieces are now parts of *Jupyter*. |
|
35 | The Notebook, Qt console and a number of other pieces are now parts of *Jupyter*. | |
34 | See the `Jupyter installation docs <http://jupyter.readthedocs.io/en/latest/install.html>`__ |
|
36 | See the `Jupyter installation docs <https://jupyter.readthedocs.io/en/latest/install.html>`__ | |
35 | if you want to use these. |
|
37 | if you want to use these. | |
36 |
|
38 | |||
37 |
|
39 | |||
@@ -41,7 +43,7 b' Development and Instant running' | |||||
41 | =============================== |
|
43 | =============================== | |
42 |
|
44 | |||
43 | You can find the latest version of the development documentation on `readthedocs |
|
45 | You can find the latest version of the development documentation on `readthedocs | |
44 | <http://ipython.readthedocs.io/en/latest/>`_. |
|
46 | <https://ipython.readthedocs.io/en/latest/>`_. | |
45 |
|
47 | |||
46 | You can run IPython from this directory without even installing it system-wide |
|
48 | You can run IPython from this directory without even installing it system-wide | |
47 | by typing at the terminal:: |
|
49 | by typing at the terminal:: | |
@@ -49,7 +51,7 b' by typing at the terminal::' | |||||
49 | $ python -m IPython |
|
51 | $ python -m IPython | |
50 |
|
52 | |||
51 | Or see the `development installation docs |
|
53 | Or see the `development installation docs | |
52 | <http://ipython.readthedocs.io/en/latest/install/install.html#installing-the-development-version>`_ |
|
54 | <https://ipython.readthedocs.io/en/latest/install/install.html#installing-the-development-version>`_ | |
53 | for the latest revision on read the docs. |
|
55 | for the latest revision on read the docs. | |
54 |
|
56 | |||
55 | Documentation and installation instructions for older version of IPython can be |
|
57 | Documentation and installation instructions for older version of IPython can be | |
@@ -68,14 +70,14 b' Support version.' | |||||
68 |
|
70 | |||
69 | If you are encountering this error message you are likely trying to install or |
|
71 | If you are encountering this error message you are likely trying to install or | |
70 | use IPython from source. You need to checkout the remote 5.x branch. If you are |
|
72 | use IPython from source. You need to checkout the remote 5.x branch. If you are | |
71 | using git the following should work: |
|
73 | using git the following should work:: | |
72 |
|
|
74 | ||
73 | $ git fetch origin |
|
75 | $ git fetch origin | |
74 |
$ git checkout 5.x |
|
76 | $ git checkout 5.x | |
75 |
|
|
77 | ||
76 | If you encounter this error message with a regular install of IPython, then you |
|
78 | If you encounter this error message with a regular install of IPython, then you | |
77 | likely need to update your package manager, for example if you are using `pip` |
|
79 | likely need to update your package manager, for example if you are using `pip` | |
78 | check the version of pip with |
|
80 | check the version of pip with:: | |
79 |
|
|
81 | ||
80 | $ pip --version |
|
82 | $ pip --version | |
81 |
|
83 |
@@ -8,8 +8,8 b' environment:' | |||||
8 | PYTHON_VERSION: "3.6.x" |
|
8 | PYTHON_VERSION: "3.6.x" | |
9 | PYTHON_ARCH: "32" |
|
9 | PYTHON_ARCH: "32" | |
10 |
|
10 | |||
11 |
- PYTHON: "C:\\Python3 |
|
11 | - PYTHON: "C:\\Python34-x64" | |
12 |
PYTHON_VERSION: "3. |
|
12 | PYTHON_VERSION: "3.4.x" | |
13 | PYTHON_ARCH: "64" |
|
13 | PYTHON_ARCH: "64" | |
14 |
|
14 | |||
15 | - PYTHON: "C:\\Python36-x64" |
|
15 | - PYTHON: "C:\\Python36-x64" | |
@@ -21,7 +21,7 b' init:' | |||||
21 |
|
21 | |||
22 | install: |
|
22 | install: | |
23 | - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" |
|
23 | - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" | |
24 |
- "%CMD_IN_ENV% pip install |
|
24 | - "%CMD_IN_ENV% python -m pip install --upgrade setuptools pip" | |
25 | - "%CMD_IN_ENV% pip install nose coverage" |
|
25 | - "%CMD_IN_ENV% pip install nose coverage" | |
26 | - "%CMD_IN_ENV% pip install .[test]" |
|
26 | - "%CMD_IN_ENV% pip install .[test]" | |
27 | - "%CMD_IN_ENV% mkdir results" |
|
27 | - "%CMD_IN_ENV% mkdir results" |
@@ -48,7 +48,7 b' API documentation. This build target skips that.' | |||||
48 | You can run ``make help`` to see information on all possible make targets. |
|
48 | You can run ``make help`` to see information on all possible make targets. | |
49 |
|
49 | |||
50 | To save time, |
|
50 | To save time, | |
51 |
the make targets above only proce |
|
51 | the make targets above only process the files that have been changed since the | |
52 | previous docs build. |
|
52 | previous docs build. | |
53 | To remove the previous docs build you can use ``make clean``. |
|
53 | To remove the previous docs build you can use ``make clean``. | |
54 | You can also combine ``clean`` with other `make` commands; |
|
54 | You can also combine ``clean`` with other `make` commands; |
@@ -1,7 +1,6 b'' | |||||
1 | from os.path import abspath, dirname, join |
|
1 | from os.path import abspath, dirname, join | |
2 |
|
2 | |||
3 | from IPython.terminal.interactiveshell import KeyBindingManager |
|
3 | from IPython.terminal.shortcuts import create_ipython_shortcuts | |
4 |
|
||||
5 |
|
4 | |||
6 | def name(c): |
|
5 | def name(c): | |
7 | s = c.__class__.__name__ |
|
6 | s = c.__class__.__name__ | |
@@ -42,8 +41,14 b' def multi_filter_str(flt):' | |||||
42 | log_filters = {'_AndList': 'And', '_OrList': 'Or'} |
|
41 | log_filters = {'_AndList': 'And', '_OrList': 'Or'} | |
43 | log_invert = {'_Invert'} |
|
42 | log_invert = {'_Invert'} | |
44 |
|
43 | |||
45 | kbm = KeyBindingManager.for_prompt() |
|
44 | class _DummyTerminal(object): | |
46 | ipy_bindings = kbm.registry.key_bindings |
|
45 | """Used as a buffer to get prompt_toolkit bindings | |
|
46 | """ | |||
|
47 | handle_return = None | |||
|
48 | input_splitter = None | |||
|
49 | display_completions = None | |||
|
50 | ||||
|
51 | ipy_bindings = create_ipython_shortcuts(_DummyTerminal()).bindings | |||
47 |
|
52 | |||
48 | dummy_docs = [] # ignore bindings without proper documentation |
|
53 | dummy_docs = [] # ignore bindings without proper documentation | |
49 |
|
54 |
@@ -42,6 +42,13 b' For example::' | |||||
42 | def _repr_html_(self): |
|
42 | def _repr_html_(self): | |
43 | return "<h1>" + self.text + "</h1>" |
|
43 | return "<h1>" + self.text + "</h1>" | |
44 |
|
44 | |||
|
45 | We often want to provide frontends with guidance on how to display the data. To | |||
|
46 | support this, ``_repr_*_()`` methods can also return a ``(data, metadata)`` | |||
|
47 | tuple where ``metadata`` is a dictionary containing arbitrary key-value pairs for | |||
|
48 | the frontend to interpret. An example use case is ``_repr_jpeg_()``, which can | |||
|
49 | be set to return a jpeg image and a ``{'height': 400, 'width': 600}`` dictionary | |||
|
50 | to inform the frontend how to size the image. | |||
|
51 | ||||
45 | There are also two more powerful display methods: |
|
52 | There are also two more powerful display methods: | |
46 |
|
53 | |||
47 | .. class:: MyObject |
|
54 | .. class:: MyObject |
@@ -11,7 +11,7 b' In order for this to be possible, you need to use the ``display()`` function,' | |||||
11 | that should be available by default on IPython 5.4+ and 6.1+, or that you can |
|
11 | that should be available by default on IPython 5.4+ and 6.1+, or that you can | |
12 | import with ``from IPython.display import display``. Then use ``display(<your |
|
12 | import with ``from IPython.display import display``. Then use ``display(<your | |
13 | object>)`` instead of ``print()``, and if possible your object will be displayed |
|
13 | object>)`` instead of ``print()``, and if possible your object will be displayed | |
14 | with a richer representation. In the terminal of course, there wont be much |
|
14 | with a richer representation. In the terminal of course, there won't be much | |
15 | difference as object are most of the time represented by text, but in notebook |
|
15 | difference as object are most of the time represented by text, but in notebook | |
16 | and similar interface you will get richer outputs. |
|
16 | and similar interface you will get richer outputs. | |
17 |
|
17 |
@@ -308,6 +308,9 b' one of (note that the modes are given unquoted):' | |||||
308 | * [append:] well, that says it. |
|
308 | * [append:] well, that says it. | |
309 | * [rotate:] create rotating logs log_name.1~, log_name.2~, etc. |
|
309 | * [rotate:] create rotating logs log_name.1~, log_name.2~, etc. | |
310 |
|
310 | |||
|
311 | Adding the '-o' flag to '%logstart' magic (as in '%logstart -o [log_name [log_mode]]') | |||
|
312 | will also include output from iPython in the log file. | |||
|
313 | ||||
311 | The :magic:`logoff` and :magic:`logon` functions allow you to temporarily stop and |
|
314 | The :magic:`logoff` and :magic:`logon` functions allow you to temporarily stop and | |
312 | resume logging to a file which had previously been started with |
|
315 | resume logging to a file which had previously been started with | |
313 | %logstart. They will fail (with an explanation) if you try to use them |
|
316 | %logstart. They will fail (with an explanation) if you try to use them | |
@@ -607,12 +610,66 b' startup files, and everything, just as if it were a normal IPython session.' | |||||
607 | For information on setting configuration options when running IPython from |
|
610 | For information on setting configuration options when running IPython from | |
608 | python, see :ref:`configure_start_ipython`. |
|
611 | python, see :ref:`configure_start_ipython`. | |
609 |
|
612 | |||
610 |
It is also possible to embed an IPython shell in a namespace in your Python |
|
613 | It is also possible to embed an IPython shell in a namespace in your Python | |
611 | This allows you to evaluate dynamically the state of your code, |
|
614 | code. This allows you to evaluate dynamically the state of your code, operate | |
612 |
|
|
615 | with your variables, analyze them, etc. For example, if you run the following | |
613 | any changes you make to values while in the shell do not propagate back |
|
616 | code snippet:: | |
614 | to the running code, so it is safe to modify your values because you |
|
617 | ||
615 | won't break your code in bizarre ways by doing so. |
|
618 | import IPython | |
|
619 | ||||
|
620 | a = 42 | |||
|
621 | IPython.embed() | |||
|
622 | ||||
|
623 | and within the IPython shell, you reassign `a` to `23` to do further testing of | |||
|
624 | some sort, you can then exit:: | |||
|
625 | ||||
|
626 | >>> IPython.embed() | |||
|
627 | Python 3.6.2 (default, Jul 17 2017, 16:44:45) | |||
|
628 | Type 'copyright', 'credits' or 'license' for more information | |||
|
629 | IPython 6.2.0.dev -- An enhanced Interactive Python. Type '?' for help. | |||
|
630 | ||||
|
631 | In [1]: a = 23 | |||
|
632 | ||||
|
633 | In [2]: exit() | |||
|
634 | ||||
|
635 | Once you exit and print `a`, the value 23 will be shown:: | |||
|
636 | ||||
|
637 | ||||
|
638 | In: print(a) | |||
|
639 | 23 | |||
|
640 | ||||
|
641 | It's important to note that the code run in the embedded IPython shell will | |||
|
642 | *not* change the state of your code and variables, **unless** the shell is | |||
|
643 | contained within the global namespace. In the above example, `a` is changed | |||
|
644 | because this is true. | |||
|
645 | ||||
|
646 | To further exemplify this, consider the following example:: | |||
|
647 | ||||
|
648 | import IPython | |||
|
649 | def do(): | |||
|
650 | a = 42 | |||
|
651 | print(a) | |||
|
652 | IPython.embed() | |||
|
653 | print(a) | |||
|
654 | ||||
|
655 | Now if call the function and complete the state changes as we did above, the | |||
|
656 | value `42` will be printed. Again, this is because it's not in the global | |||
|
657 | namespace:: | |||
|
658 | ||||
|
659 | do() | |||
|
660 | ||||
|
661 | Running a file with the above code can lead to the following session:: | |||
|
662 | ||||
|
663 | >>> do() | |||
|
664 | 42 | |||
|
665 | Python 3.6.2 (default, Jul 17 2017, 16:44:45) | |||
|
666 | Type 'copyright', 'credits' or 'license' for more information | |||
|
667 | IPython 6.2.0.dev -- An enhanced Interactive Python. Type '?' for help. | |||
|
668 | ||||
|
669 | In [1]: a = 23 | |||
|
670 | ||||
|
671 | In [2]: exit() | |||
|
672 | 42 | |||
616 |
|
|
673 | ||
617 | .. note:: |
|
674 | .. note:: | |
618 |
|
675 | |||
@@ -711,7 +768,7 b' context line to show. This allows to a many line of context on shallow stack tra' | |||||
711 | In[6]: foo(1) |
|
768 | In[6]: foo(1) | |
712 | # ... |
|
769 | # ... | |
713 | ipdb> where 8 |
|
770 | ipdb> where 8 | |
714 |
<ipython-input-6-9e45007b2b59>(1)<module> |
|
771 | <ipython-input-6-9e45007b2b59>(1)<module> | |
715 | ----> 1 foo(1) |
|
772 | ----> 1 foo(1) | |
716 |
|
773 | |||
717 | <ipython-input-5-7baadc3d1465>(5)foo() |
|
774 | <ipython-input-5-7baadc3d1465>(5)foo() | |
@@ -740,7 +797,7 b' And less context on shallower Stack Trace:' | |||||
740 | .. code:: |
|
797 | .. code:: | |
741 |
|
798 | |||
742 | ipdb> where 1 |
|
799 | ipdb> where 1 | |
743 |
<ipython-input-13-afa180a57233>(1)<module> |
|
800 | <ipython-input-13-afa180a57233>(1)<module> | |
744 | ----> 1 foo(7) |
|
801 | ----> 1 foo(7) | |
745 |
|
802 | |||
746 | <ipython-input-5-7baadc3d1465>(5)foo() |
|
803 | <ipython-input-5-7baadc3d1465>(5)foo() |
@@ -217,29 +217,30 b' running, use the ``%connect_info`` magic to get the unique connection file,' | |||||
217 | which will be something like ``--existing kernel-19732.json`` but with |
|
217 | which will be something like ``--existing kernel-19732.json`` but with | |
218 | different numbers which correspond to the Process ID of the kernel. |
|
218 | different numbers which correspond to the Process ID of the kernel. | |
219 |
|
219 | |||
220 |
You can read more about using `jupyter qtconsole |
|
220 | You can read more about using `jupyter qtconsole | |
221 | <http://jupyter.org/qtconsole/>`_, and |
|
221 | <http://jupyter.org/qtconsole/>`_, and | |
222 | `jupyter notebook <http://jupyter-notebook.readthedocs.io/en/latest/>`_. There |
|
222 | `jupyter notebook <http://jupyter-notebook.readthedocs.io/en/latest/>`_. There | |
223 |
is also a :ref:`message spec <messaging>` which documents the protocol for |
|
223 | is also a :ref:`message spec <messaging>` which documents the protocol for | |
224 | communication between kernels |
|
224 | communication between kernels | |
225 | and clients. |
|
225 | and clients. | |
226 |
|
226 | |||
227 | .. seealso:: |
|
227 | .. seealso:: | |
228 |
|
228 | |||
229 | `Frontend/Kernel Model`_ example notebook |
|
229 | `Frontend/Kernel Model`_ example notebook | |
230 |
|
230 | |||
231 |
|
231 | |||
232 | Interactive parallel computing |
|
232 | Interactive parallel computing | |
233 | ============================== |
|
233 | ============================== | |
234 |
|
234 | |||
235 |
|
235 | |||
236 | This functionality is optional and now part of the `ipyparallel |
|
236 | This functionality is optional and now part of the `ipyparallel | |
237 | <http://ipyparallel.readthedocs.io/>`_ project. |
|
237 | <http://ipyparallel.readthedocs.io/>`_ project. | |
238 |
|
238 | |||
239 | Portability and Python requirements |
|
239 | Portability and Python requirements | |
240 | ----------------------------------- |
|
240 | ----------------------------------- | |
241 |
|
241 | |||
242 |
Version |
|
242 | Version 7.0+ supports Python 3.4 and higher. | |
|
243 | Versions 6.x support Python 3.3 and higher. | |||
243 | Versions 2.0 to 5.x work with Python 2.7.x releases and Python 3.3 and higher. |
|
244 | Versions 2.0 to 5.x work with Python 2.7.x releases and Python 3.3 and higher. | |
244 | Version 1.0 additionally worked with Python 2.6 and 3.2. |
|
245 | Version 1.0 additionally worked with Python 2.6 and 3.2. | |
245 | Version 0.12 was the first version to fully support Python 3. |
|
246 | Version 0.12 was the first version to fully support Python 3. |
@@ -384,7 +384,7 b' Regular issues (285):' | |||||
384 | * `326 <https://github.com/ipython/ipython/issues/326>`_: Update docs and examples for parallel stuff to reflect movement away from Twisted |
|
384 | * `326 <https://github.com/ipython/ipython/issues/326>`_: Update docs and examples for parallel stuff to reflect movement away from Twisted | |
385 | * `341 <https://github.com/ipython/ipython/issues/341>`_: FIx Parallel Magics for newparallel |
|
385 | * `341 <https://github.com/ipython/ipython/issues/341>`_: FIx Parallel Magics for newparallel | |
386 | * `338 <https://github.com/ipython/ipython/issues/338>`_: Usability improvements to Qt console |
|
386 | * `338 <https://github.com/ipython/ipython/issues/338>`_: Usability improvements to Qt console | |
387 | * `142 <https://github.com/ipython/ipython/issues/142>`_: unexpected auto-indenting when varibles names that start with 'pass' |
|
387 | * `142 <https://github.com/ipython/ipython/issues/142>`_: unexpected auto-indenting when variables names that start with 'pass' | |
388 | * `296 <https://github.com/ipython/ipython/issues/296>`_: Automatic PDB via %pdb doesn't work |
|
388 | * `296 <https://github.com/ipython/ipython/issues/296>`_: Automatic PDB via %pdb doesn't work | |
389 | * `337 <https://github.com/ipython/ipython/issues/337>`_: exit( and quit( in Qt console produces phantom signature/docstring popup, even though quit() or exit() raises NameError |
|
389 | * `337 <https://github.com/ipython/ipython/issues/337>`_: exit( and quit( in Qt console produces phantom signature/docstring popup, even though quit() or exit() raises NameError | |
390 | * `318 <https://github.com/ipython/ipython/issues/318>`_: %debug broken in master: invokes missing save_history() method |
|
390 | * `318 <https://github.com/ipython/ipython/issues/318>`_: %debug broken in master: invokes missing save_history() method |
@@ -580,7 +580,7 b' Pull Requests (793):' | |||||
580 | * :ghpull:`3576`: Added support for markdown in heading cells when they are nbconverted. |
|
580 | * :ghpull:`3576`: Added support for markdown in heading cells when they are nbconverted. | |
581 | * :ghpull:`3575`: tweak `run -d` message to 'continue execution' |
|
581 | * :ghpull:`3575`: tweak `run -d` message to 'continue execution' | |
582 | * :ghpull:`3569`: add PYTHONSTARTUP to startup files |
|
582 | * :ghpull:`3569`: add PYTHONSTARTUP to startup files | |
583 | * :ghpull:`3567`: Trigger a single event on js app initilized |
|
583 | * :ghpull:`3567`: Trigger a single event on js app initialized | |
584 | * :ghpull:`3565`: style.min.css should always exist... |
|
584 | * :ghpull:`3565`: style.min.css should always exist... | |
585 | * :ghpull:`3531`: allow markdown in heading cells |
|
585 | * :ghpull:`3531`: allow markdown in heading cells | |
586 | * :ghpull:`3577`: Simplify codemirror ipython-mode |
|
586 | * :ghpull:`3577`: Simplify codemirror ipython-mode | |
@@ -1195,7 +1195,7 b' Issues (691):' | |||||
1195 | * :ghissue:`3957`: Notebook help page broken in Firefox |
|
1195 | * :ghissue:`3957`: Notebook help page broken in Firefox | |
1196 | * :ghissue:`3894`: nbconvert test failure |
|
1196 | * :ghissue:`3894`: nbconvert test failure | |
1197 | * :ghissue:`3887`: 1.0.0a1 shows blank screen in both firefox and chrome (windows 7) |
|
1197 | * :ghissue:`3887`: 1.0.0a1 shows blank screen in both firefox and chrome (windows 7) | |
1198 |
* :ghissue:`3703`: `nbconvert`: Output options -- names and documentat |
|
1198 | * :ghissue:`3703`: `nbconvert`: Output options -- names and documentation | |
1199 | * :ghissue:`3931`: Tab completion not working during debugging in the notebook |
|
1199 | * :ghissue:`3931`: Tab completion not working during debugging in the notebook | |
1200 | * :ghissue:`3936`: Ipcluster plugin is not working with Ipython 1.0dev |
|
1200 | * :ghissue:`3936`: Ipcluster plugin is not working with Ipython 1.0dev | |
1201 | * :ghissue:`3941`: IPython Notebook kernel crash on Win7x64 |
|
1201 | * :ghissue:`3941`: IPython Notebook kernel crash on Win7x64 | |
@@ -1264,7 +1264,7 b' Issues (691):' | |||||
1264 | * :ghissue:`3737`: ipython nbconvert crashes with ValueError: Invalid format string. |
|
1264 | * :ghissue:`3737`: ipython nbconvert crashes with ValueError: Invalid format string. | |
1265 | * :ghissue:`3730`: nbconvert: unhelpful error when pandoc isn't installed |
|
1265 | * :ghissue:`3730`: nbconvert: unhelpful error when pandoc isn't installed | |
1266 | * :ghissue:`3718`: markdown cell cursor misaligned in notebook |
|
1266 | * :ghissue:`3718`: markdown cell cursor misaligned in notebook | |
1267 | * :ghissue:`3710`: mutiple input fields for %debug in the notebook after resetting the kernel |
|
1267 | * :ghissue:`3710`: multiple input fields for %debug in the notebook after resetting the kernel | |
1268 | * :ghissue:`3713`: PyCharm has problems with IPython working inside PyPy created by virtualenv |
|
1268 | * :ghissue:`3713`: PyCharm has problems with IPython working inside PyPy created by virtualenv | |
1269 | * :ghissue:`3712`: Code completion: Complete on dictionary keys |
|
1269 | * :ghissue:`3712`: Code completion: Complete on dictionary keys | |
1270 | * :ghissue:`3680`: --pylab and --matplotlib flag |
|
1270 | * :ghissue:`3680`: --pylab and --matplotlib flag | |
@@ -1405,7 +1405,7 b' Issues (691):' | |||||
1405 | * :ghissue:`3519`: IPython Parallel map mysteriously turns pandas Series into numpy ndarray |
|
1405 | * :ghissue:`3519`: IPython Parallel map mysteriously turns pandas Series into numpy ndarray | |
1406 | * :ghissue:`3345`: IPython embedded shells ask if I want to exit, but I set confirm_exit = False |
|
1406 | * :ghissue:`3345`: IPython embedded shells ask if I want to exit, but I set confirm_exit = False | |
1407 | * :ghissue:`3509`: IPython won't close without asking "Are you sure?" in Firefox |
|
1407 | * :ghissue:`3509`: IPython won't close without asking "Are you sure?" in Firefox | |
1408 | * :ghissue:`3471`: Notebook jinja2/markupsafe depedencies in manual |
|
1408 | * :ghissue:`3471`: Notebook jinja2/markupsafe dependencies in manual | |
1409 | * :ghissue:`3502`: Notebook broken in master |
|
1409 | * :ghissue:`3502`: Notebook broken in master | |
1410 | * :ghissue:`3302`: autoreload does not work in ipython 0.13.x, python 3.3 |
|
1410 | * :ghissue:`3302`: autoreload does not work in ipython 0.13.x, python 3.3 | |
1411 | * :ghissue:`3475`: no warning when leaving/closing notebook on master without saved changes |
|
1411 | * :ghissue:`3475`: no warning when leaving/closing notebook on master without saved changes | |
@@ -1477,7 +1477,7 b' Issues (691):' | |||||
1477 | * :ghissue:`3380`: simple call to kernel |
|
1477 | * :ghissue:`3380`: simple call to kernel | |
1478 | * :ghissue:`3379`: TaskRecord key 'started' not set |
|
1478 | * :ghissue:`3379`: TaskRecord key 'started' not set | |
1479 | * :ghissue:`3241`: notebook connection time out |
|
1479 | * :ghissue:`3241`: notebook connection time out | |
1480 |
* :ghissue:`3334`: magic interpreter interpret |
|
1480 | * :ghissue:`3334`: magic interpreter interprets non magic commands? | |
1481 | * :ghissue:`3326`: python3.3: Type error when launching SGE cluster in IPython notebook |
|
1481 | * :ghissue:`3326`: python3.3: Type error when launching SGE cluster in IPython notebook | |
1482 | * :ghissue:`3349`: pip3 doesn't run 2to3? |
|
1482 | * :ghissue:`3349`: pip3 doesn't run 2to3? | |
1483 | * :ghissue:`3347`: Longlist support in ipdb |
|
1483 | * :ghissue:`3347`: Longlist support in ipdb |
@@ -3,6 +3,28 b'' | |||||
3 | Issues closed in the 5.x development cycle |
|
3 | Issues closed in the 5.x development cycle | |
4 | ========================================== |
|
4 | ========================================== | |
5 |
|
5 | |||
|
6 | Issues closed in 5.6 | |||
|
7 | -------------------- | |||
|
8 | ||||
|
9 | GitHub stats for 2017/09/15 - 2018/04/02 (tag: 5.5.0) | |||
|
10 | ||||
|
11 | These lists are automatically generated, and may be incomplete or contain duplicates. | |||
|
12 | ||||
|
13 | We closed 2 issues and merged 28 pull requests. | |||
|
14 | The full list can be seen `on GitHub <https://github.com/ipython/ipython/issues?q=milestone%3A5.6>`__ | |||
|
15 | ||||
|
16 | The following 10 authors contributed 47 commits. | |||
|
17 | ||||
|
18 | * Benjamin Ragan-Kelley | |||
|
19 | * Henry Fredrick Schreiner | |||
|
20 | * Joris Van den Bossche | |||
|
21 | * Matthias Bussonnier | |||
|
22 | * Mradul Dubey | |||
|
23 | * Roshan Rao | |||
|
24 | * Samuel Lelièvre | |||
|
25 | * Teddy Rendahl | |||
|
26 | * Thomas A Caswell | |||
|
27 | * Thomas Kluyver | |||
6 |
|
28 | |||
7 | Issues closed in 5.4 |
|
29 | Issues closed in 5.4 | |
8 | -------------------- |
|
30 | -------------------- |
@@ -1,10 +1,58 b'' | |||||
1 | Issues closed in the 6.x development cycle |
|
1 | Issues closed in the 6.x development cycle | |
2 | ========================================== |
|
2 | ========================================== | |
3 |
|
3 | |||
4 |
Issues closed in 6. |
|
4 | Issues closed in 6.3 | |
5 | -------------------- |
|
5 | -------------------- | |
6 |
|
6 | |||
7 |
|
7 | |||
|
8 | GitHub stats for 2017/09/15 - 2018/04/02 (tag: 6.2.0) | |||
|
9 | ||||
|
10 | These lists are automatically generated, and may be incomplete or contain duplicates. | |||
|
11 | ||||
|
12 | We closed 10 issues and merged 50 pull requests. | |||
|
13 | The full list can be seen `on GitHub <https://github.com/ipython/ipython/issues?q=milestone%3A6.3>`__ | |||
|
14 | ||||
|
15 | The following 35 authors contributed 253 commits. | |||
|
16 | ||||
|
17 | * Anatoly Techtonik | |||
|
18 | * Antony Lee | |||
|
19 | * Benjamin Ragan-Kelley | |||
|
20 | * Corey McCandless | |||
|
21 | * Craig Citro | |||
|
22 | * Cristian Ciupitu | |||
|
23 | * David Cottrell | |||
|
24 | * David Straub | |||
|
25 | * Doug Latornell | |||
|
26 | * Fabio Niephaus | |||
|
27 | * Gergely Nagy | |||
|
28 | * Henry Fredrick Schreiner | |||
|
29 | * Hugo | |||
|
30 | * Ismael Venegas Castelló | |||
|
31 | * Ivan Gonzalez | |||
|
32 | * J Forde | |||
|
33 | * Jeremy Sikes | |||
|
34 | * Joris Van den Bossche | |||
|
35 | * Lesley Cordero | |||
|
36 | * luzpaz | |||
|
37 | * madhu94 | |||
|
38 | * Matthew R. Scott | |||
|
39 | * Matthias Bussonnier | |||
|
40 | * Matthias Geier | |||
|
41 | * Olesya Baranova | |||
|
42 | * Peter Williams | |||
|
43 | * Rastislav Barlik | |||
|
44 | * Roshan Rao | |||
|
45 | * rs2 | |||
|
46 | * Samuel Lelièvre | |||
|
47 | * Shailyn javier Ortiz jimenez | |||
|
48 | * Sjoerd de Vries | |||
|
49 | * Teddy Rendahl | |||
|
50 | * Thomas A Caswell | |||
|
51 | * Thomas Kluyver | |||
|
52 | ||||
|
53 | Issues closed in 6.2 | |||
|
54 | -------------------- | |||
|
55 | ||||
8 | GitHub stats for 2017/05/31 - 2017/09/15 (tag: 6.1.0) |
|
56 | GitHub stats for 2017/05/31 - 2017/09/15 (tag: 6.1.0) | |
9 |
|
57 | |||
10 | These lists are automatically generated, and may be incomplete or contain duplicates. |
|
58 | These lists are automatically generated, and may be incomplete or contain duplicates. |
@@ -43,5 +43,3 b' development work they do here in a user friendly format.' | |||||
43 | version0.10 |
|
43 | version0.10 | |
44 | version0.9 |
|
44 | version0.9 | |
45 | version0.8 |
|
45 | version0.8 | |
46 |
|
||||
47 |
|
@@ -293,7 +293,7 b' Backwards incompatible changes' | |||||
293 | deprecated, but continue to work. |
|
293 | deprecated, but continue to work. | |
294 |
|
294 | |||
295 | * For embedding a shell, note that the parameters ``user_global_ns`` and |
|
295 | * For embedding a shell, note that the parameters ``user_global_ns`` and | |
296 |
``global_ns`` have been deprec |
|
296 | ``global_ns`` have been deprecated in favour of ``user_module`` and | |
297 | ``module`` respsectively. The new parameters expect a module-like object, |
|
297 | ``module`` respsectively. The new parameters expect a module-like object, | |
298 | rather than a namespace dict. The old parameters remain for backwards |
|
298 | rather than a namespace dict. The old parameters remain for backwards | |
299 | compatibility, although ``user_global_ns`` is now ignored. The ``user_ns`` |
|
299 | compatibility, although ``user_global_ns`` is now ignored. The ``user_ns`` |
@@ -3,6 +3,33 b'' | |||||
3 | ============ |
|
3 | ============ | |
4 |
|
4 | |||
5 |
|
5 | |||
|
6 | .. _whatsnew570: | |||
|
7 | ||||
|
8 | IPython 5.7 | |||
|
9 | =========== | |||
|
10 | ||||
|
11 | * Fix IPython trying to import non-existing matplotlib backends :ghpull:`11087` | |||
|
12 | * fix for display hook not publishing object metadata :ghpull:`11101` | |||
|
13 | ||||
|
14 | .. _whatsnew560: | |||
|
15 | ||||
|
16 | IPython 5.6 | |||
|
17 | =========== | |||
|
18 | ||||
|
19 | * In Python 3.6 and above, dictionaries preserve the order items were added to | |||
|
20 | them. On these versions, IPython will display dictionaries in their native | |||
|
21 | order, rather than sorting by the keys (:ghpull:`10958`). | |||
|
22 | * :class:`~.IPython.display.ProgressBar` can now be used as an iterator | |||
|
23 | (:ghpull:`10813`). | |||
|
24 | * The shell object gains a :meth:`~.InteractiveShell.check_complete` method, | |||
|
25 | to allow a smoother transition to new input processing machinery planned for | |||
|
26 | IPython 7 (:ghpull:`11044`). | |||
|
27 | * IPython should start faster, as it no longer looks for all available pygments | |||
|
28 | styles on startup (:ghpull:`10859`). | |||
|
29 | ||||
|
30 | You can see all the PR marked for the `5.6. milestone <https://github.com/ipython/ipython/pulls?utf8=%E2%9C%93&q=is%3Apr+milestone%3A5.6+is%3Aclosed+NOT+%22Backport+PR%22+>`_, | |||
|
31 | and all the `backport versions <https://github.com/ipython/ipython/pulls?utf8=%E2%9C%93&q=is%3Apr%20milestone%3A5.6%20is%3Aclosed%20%22Backport%20PR%22%20>`__. | |||
|
32 | ||||
6 | .. _whatsnew550: |
|
33 | .. _whatsnew550: | |
7 |
|
34 | |||
8 | IPython 5.5 |
|
35 | IPython 5.5 |
@@ -2,6 +2,55 b'' | |||||
2 | 6.x Series |
|
2 | 6.x Series | |
3 | ============ |
|
3 | ============ | |
4 |
|
4 | |||
|
5 | .. _whatsnew640: | |||
|
6 | ||||
|
7 | IPython 6.4.0 | |||
|
8 | ============= | |||
|
9 | ||||
|
10 | Everything new in :ref:`IPython 5.7 <whatsnew570>` | |||
|
11 | ||||
|
12 | * Fix display object not emitting metadata :ghpull:`11106` | |||
|
13 | * Comments failing Jedi test :ghpull:`11110` | |||
|
14 | ||||
|
15 | ||||
|
16 | .. _whatsnew631: | |||
|
17 | ||||
|
18 | IPython 6.3.1 | |||
|
19 | ============= | |||
|
20 | ||||
|
21 | This is a bugfix release to switch the default completions back to IPython's | |||
|
22 | own completion machinery. We discovered some problems with the completions | |||
|
23 | from Jedi, including completing column names on pandas data frames. | |||
|
24 | ||||
|
25 | You can switch the completions source with the config option | |||
|
26 | :configtrait:`Completer.use_jedi`. | |||
|
27 | ||||
|
28 | .. _whatsnew630: | |||
|
29 | ||||
|
30 | IPython 6.3 | |||
|
31 | =========== | |||
|
32 | ||||
|
33 | IPython 6.3 contains all the bug fixes and features in | |||
|
34 | :ref:`IPython 5.6 <whatsnew560>`. In addition: | |||
|
35 | ||||
|
36 | * A new display class :class:`IPython.display.Code` can be used to display | |||
|
37 | syntax highlighted code in a notebook (:ghpull:`10978`). | |||
|
38 | * The :cellmagic:`html` magic now takes a ``--isolated`` option to put the | |||
|
39 | content in an iframe (:ghpull:`10962`). | |||
|
40 | * The code to find completions using the Jedi library has had various | |||
|
41 | adjustments. This is still a work in progress, but we hope this version has | |||
|
42 | fewer annoyances (:ghpull:`10956`, :ghpull:`10969`, :ghpull:`10999`, | |||
|
43 | :ghpull:`11035`, :ghpull:`11063`, :ghpull:`11065`). | |||
|
44 | * The *post* event callbacks are now always called, even when the execution failed | |||
|
45 | (for example because of a ``SyntaxError``). | |||
|
46 | * The execution info and result objects are now made available in the | |||
|
47 | corresponding *pre* or *post* ``*_run_cell`` :doc:`event callbacks </config/callbacks>` | |||
|
48 | in a backward compatible manner (:ghissue:`10774` and :ghpull:`10795`). | |||
|
49 | * Performance with very long code cells (hundreds of lines) is greatly improved | |||
|
50 | (:ghpull:`10898`). Further improvements are planned for IPython 7. | |||
|
51 | ||||
|
52 | You can see all `pull requests for the 6.3 milestone | |||
|
53 | <https://github.com/ipython/ipython/pulls?utf8=%E2%9C%93&q=is%3Apr+milestone%3A6.3+is%3Aclosed>`__. | |||
5 |
|
54 | |||
6 | .. _whatsnew620: |
|
55 | .. _whatsnew620: | |
7 |
|
56 |
@@ -436,7 +436,7 b'' | |||||
436 | "\n", |
|
436 | "\n", | |
437 | " c.ScriptMagics.scripts = ['R', 'pypy', 'myprogram']\n", |
|
437 | " c.ScriptMagics.scripts = ['R', 'pypy', 'myprogram']\n", | |
438 | "\n", |
|
438 | "\n", | |
439 | "And if any of these programs do not apear on your default PATH, then you would also need to specify their location with:\n", |
|
439 | "And if any of these programs do not appear on your default PATH, then you would also need to specify their location with:\n", | |
440 | "\n", |
|
440 | "\n", | |
441 | " c.ScriptMagics.script_paths = {'myprogram': '/opt/path/to/myprogram'}" |
|
441 | " c.ScriptMagics.script_paths = {'myprogram': '/opt/path/to/myprogram'}" | |
442 | ] |
|
442 | ] |
@@ -1,4 +1,4 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python3 | |
2 | # -*- coding: utf-8 -*- |
|
2 | # -*- coding: utf-8 -*- | |
3 | """Setup script for IPython. |
|
3 | """Setup script for IPython. | |
4 |
|
4 | |||
@@ -26,7 +26,7 b' import sys' | |||||
26 | # |
|
26 | # | |
27 | # This check is also made in IPython/__init__, don't forget to update both when |
|
27 | # This check is also made in IPython/__init__, don't forget to update both when | |
28 | # changing Python version requirements. |
|
28 | # changing Python version requirements. | |
29 |
if sys.version_info < (3, |
|
29 | if sys.version_info < (3, 4): | |
30 | pip_message = 'This may be due to an out of date pip. Make sure you have pip >= 9.0.1.' |
|
30 | pip_message = 'This may be due to an out of date pip. Make sure you have pip >= 9.0.1.' | |
31 | try: |
|
31 | try: | |
32 | import pip |
|
32 | import pip | |
@@ -42,9 +42,9 b' if sys.version_info < (3, 3):' | |||||
42 |
|
42 | |||
43 |
|
43 | |||
44 | error = """ |
|
44 | error = """ | |
45 | IPython 6.0+ does not support Python 2.6, 2.7, 3.0, 3.1, or 3.2. |
|
45 | IPython 7.0+ supports Python 3.4 and above. | |
46 | When using Python 2.7, please install IPython 5.x LTS Long Term Support version. |
|
46 | When using Python 2.7, please install IPython 5.x LTS Long Term Support version. | |
47 | Beginning with IPython 6.0, Python 3.3 and above is required. |
|
47 | Python 3.3 was supported up to IPython 6.x. | |
48 |
|
48 | |||
49 | See IPython `README.rst` file for more information: |
|
49 | See IPython `README.rst` file for more information: | |
50 |
|
50 | |||
@@ -175,7 +175,7 b' extras_require = dict(' | |||||
175 | parallel = ['ipyparallel'], |
|
175 | parallel = ['ipyparallel'], | |
176 | qtconsole = ['qtconsole'], |
|
176 | qtconsole = ['qtconsole'], | |
177 | doc = ['Sphinx>=1.3'], |
|
177 | doc = ['Sphinx>=1.3'], | |
178 | test = ['nose>=0.10.1', 'requests', 'testpath', 'pygments', 'nbformat', 'ipykernel'], |
|
178 | test = ['nose>=0.10.1', 'requests', 'testpath', 'pygments', 'nbformat', 'ipykernel', 'numpy'], | |
179 | terminal = [], |
|
179 | terminal = [], | |
180 | kernel = ['ipykernel'], |
|
180 | kernel = ['ipykernel'], | |
181 | nbformat = ['nbformat'], |
|
181 | nbformat = ['nbformat'], | |
@@ -190,7 +190,7 b' install_requires = [' | |||||
190 | 'pickleshare', |
|
190 | 'pickleshare', | |
191 | 'simplegeneric>0.8', |
|
191 | 'simplegeneric>0.8', | |
192 | 'traitlets>=4.2', |
|
192 | 'traitlets>=4.2', | |
193 |
'prompt_toolkit>= |
|
193 | 'prompt_toolkit>=2.0.0,<2.1.0', | |
194 | 'pygments', |
|
194 | 'pygments', | |
195 | 'backcall', |
|
195 | 'backcall', | |
196 | ] |
|
196 | ] | |
@@ -200,9 +200,7 b' install_requires = [' | |||||
200 | # but requires pip >= 6. pip < 6 ignores these. |
|
200 | # but requires pip >= 6. pip < 6 ignores these. | |
201 |
|
201 | |||
202 | extras_require.update({ |
|
202 | extras_require.update({ | |
203 |
' |
|
203 | ':python_version == "3.4"': ['typing'], | |
204 | ':python_version == "3.3"': ['pathlib2'], |
|
|||
205 | ':python_version <= "3.4"': ['typing'], |
|
|||
206 | ':sys_platform != "win32"': ['pexpect'], |
|
204 | ':sys_platform != "win32"': ['pexpect'], | |
207 | ':sys_platform == "darwin"': ['appnope'], |
|
205 | ':sys_platform == "darwin"': ['appnope'], | |
208 | ':sys_platform == "win32"': ['colorama'], |
|
206 | ':sys_platform == "win32"': ['colorama'], | |
@@ -232,7 +230,7 b' for key, deps in extras_require.items():' | |||||
232 | extras_require['all'] = everything |
|
230 | extras_require['all'] = everything | |
233 |
|
231 | |||
234 | if 'setuptools' in sys.modules: |
|
232 | if 'setuptools' in sys.modules: | |
235 |
setuptools_extra_args['python_requires'] = '>=3. |
|
233 | setuptools_extra_args['python_requires'] = '>=3.4' | |
236 | setuptools_extra_args['zip_safe'] = False |
|
234 | setuptools_extra_args['zip_safe'] = False | |
237 | setuptools_extra_args['entry_points'] = { |
|
235 | setuptools_extra_args['entry_points'] = { | |
238 | 'console_scripts': find_entry_points(), |
|
236 | 'console_scripts': find_entry_points(), |
@@ -65,7 +65,7 b' class install_data_ext(install_data):' | |||||
65 | files = lof[2] |
|
65 | files = lof[2] | |
66 | if len(files) == 0: |
|
66 | if len(files) == 0: | |
67 | # If there are no files listed, the user must be |
|
67 | # If there are no files listed, the user must be | |
68 |
# trying to create an empty directory, so add the |
|
68 | # trying to create an empty directory, so add the | |
69 | # directory to the list of output files. |
|
69 | # directory to the list of output files. | |
70 | self.outfiles.append(dir) |
|
70 | self.outfiles.append(dir) | |
71 | else: |
|
71 | else: |
@@ -1,4 +1,4 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python3 | |
2 | """IPython release build script. |
|
2 | """IPython release build script. | |
3 | """ |
|
3 | """ | |
4 | import os |
|
4 | import os |
@@ -58,7 +58,7 b' def merge_pr(num):' | |||||
58 | cmd = "git pull "+repo+" "+branch |
|
58 | cmd = "git pull "+repo+" "+branch | |
59 | not_merged[str(num)] = cmd |
|
59 | not_merged[str(num)] = cmd | |
60 | print("==============================================================================") |
|
60 | print("==============================================================================") | |
61 |
print("Something went wrong merging this branch, you can try it manually by runn |
|
61 | print("Something went wrong merging this branch, you can try it manually by running :") | |
62 | print(cmd) |
|
62 | print(cmd) | |
63 | print("==============================================================================") |
|
63 | print("==============================================================================") | |
64 |
|
64 | |||
@@ -118,7 +118,7 b' def main(*args):' | |||||
118 |
|
118 | |||
119 | if not_merged : |
|
119 | if not_merged : | |
120 | print('*************************************************************************************') |
|
120 | print('*************************************************************************************') | |
121 |
print(' |
|
121 | print('The following branch has not been merged automatically, consider doing it by hand :') | |
122 | for num, cmd in not_merged.items() : |
|
122 | for num, cmd in not_merged.items() : | |
123 | print( "PR {num}: {cmd}".format(num=num, cmd=cmd)) |
|
123 | print( "PR {num}: {cmd}".format(num=num, cmd=cmd)) | |
124 | print('*************************************************************************************') |
|
124 | print('*************************************************************************************') |
@@ -212,7 +212,7 b' if __name__ == "__main__":' | |||||
212 |
|
212 | |||
213 | print("We closed %d issues and merged %d pull requests." % (n_issues, n_pulls)) |
|
213 | print("We closed %d issues and merged %d pull requests." % (n_issues, n_pulls)) | |
214 | if milestone: |
|
214 | if milestone: | |
215 |
print("The full list can be seen `on GitHub <https://github.com/{project}/issues?q=milestone%3A{milestone} |
|
215 | print("The full list can be seen `on GitHub <https://github.com/{project}/issues?q=milestone%3A{milestone}>`__".format(project=project,milestone=milestone) | |
216 | ) |
|
216 | ) | |
217 |
|
217 | |||
218 | print() |
|
218 | print() |
@@ -1,4 +1,4 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python3 | |
2 | """IPython release script. |
|
2 | """IPython release script. | |
3 |
|
3 | |||
4 | This should ONLY be run at real release time. |
|
4 | This should ONLY be run at real release time. |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now