##// END OF EJS Templates
Prototype async REPL using IPython, take III...
Matthias Bussonnier -
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -0,0 +1,88 b''
1 """
2 Async helper function that are invalid syntax on Python 3.5 and below.
3
4 Known limitation and possible improvement.
5
6 Top level code that contain a return statement (instead of, or in addition to
7 await) will be detected as requiring being wrapped in async calls. This should
8 be prevented as early return will not work.
9 """
10
11
12
13 import ast
14 import sys
15 import inspect
16 from textwrap import dedent, indent
17 from types import CodeType
18
19
20 def _asyncio_runner(coro):
21 """
22 Handler for asyncio autoawait
23 """
24 import asyncio
25 return asyncio.get_event_loop().run_until_complete(coro)
26
27
28 def _curio_runner(coroutine):
29 """
30 handler for curio autoawait
31 """
32 import curio
33 return curio.run(coroutine)
34
35
36 if sys.version_info > (3, 5):
37 # nose refuses to avoid this file and async def is invalidsyntax
38 s = dedent('''
39 def _trio_runner(function):
40 import trio
41 async def loc(coro):
42 """
43 We need the dummy no-op async def to protect from
44 trio's internal. See https://github.com/python-trio/trio/issues/89
45 """
46 return await coro
47 return trio.run(loc, function)
48 ''')
49 exec(s, globals(), locals())
50
51
52 def _asyncify(code: str) -> str:
53 """wrap code in async def definition.
54
55 And setup a bit of context to run it later.
56 """
57 res = dedent("""
58 async def __wrapper__():
59 try:
60 {usercode}
61 finally:
62 locals()
63 """).format(usercode=indent(code, ' ' * 8)[8:])
64 return res
65
66
67 def _should_be_async(cell: str) -> bool:
68 """Detect if a block of code need to be wrapped in an `async def`
69
70 Attempt to parse the block of code, it it compile we're fine.
71 Otherwise we wrap if and try to compile.
72
73 If it works, assume it should be async. Otherwise Return False.
74
75 Not handled yet: If the block of code has a return statement as the top
76 level, it will be seen as async. This is a know limitation.
77 """
78
79 try:
80 ast.parse(cell)
81 return False
82 except SyntaxError:
83 try:
84 ast.parse(_asyncify(cell))
85 except SyntaxError:
86 return False
87 return True
88 return False
@@ -0,0 +1,52 b''
1 """
2 Test for async helpers.
3
4 Should only trigger on python 3.5+ or will have syntax errors.
5 """
6
7 import sys
8 import nose.tools as nt
9 from textwrap import dedent
10 from unittest import TestCase
11
12 ip = get_ipython()
13 iprc = lambda x: ip.run_cell(dedent(x))
14
15 if sys.version_info > (3,5):
16 from IPython.core.async_helpers import _should_be_async
17
18 class AsyncTest(TestCase):
19
20 def test_should_be_async(self):
21 nt.assert_false(_should_be_async("False"))
22 nt.assert_true(_should_be_async("await bar()"))
23 nt.assert_true(_should_be_async("x = await bar()"))
24 nt.assert_false(_should_be_async(dedent("""
25 async def awaitable():
26 pass
27 """)))
28
29 def test_execute(self):
30 iprc("""
31 import asyncio
32 await asyncio.sleep(0.001)
33 """)
34
35 def test_autoawait(self):
36 ip.run_cell('%autoawait False')
37 ip.run_cell('%autoawait True')
38 iprc('''
39 from asyncio import sleep
40 await.sleep(0.1)
41 ''')
42
43 def test_autoawait_curio(self):
44 ip.run_cell('%autoawait curio')
45
46 def test_autoawait_trio(self):
47 ip.run_cell('%autoawait trio')
48
49 def tearDown(self):
50 ip.loop_runner = 'asyncio'
51
52
@@ -0,0 +1,186 b''
1
2 .. autoawait:
3
4 Asynchronous in REPL: Autoawait
5 ===============================
6
7 Starting with IPython 6.0, and when user Python 3.6 and above, IPython offer the
8 ability to run asynchronous code from the REPL. constructs which are
9 :exc:`SyntaxError` s in the Python REPL can be used seamlessly in IPython.
10
11 When a supported libray is used, IPython will automatically `await` Futures
12 and Coroutines in the REPL. This will happen if an :ref:`await <await>` (or `async`) is
13 use at top level scope, or if any structure valid only in `async def
14 <https://docs.python.org/3/reference/compound_stmts.html#async-def>`_ function
15 context are present. For example, the following being a syntax error in the
16 Python REPL::
17
18 Python 3.6.0
19 [GCC 4.2.1]
20 Type "help", "copyright", "credits" or "license" for more information.
21 >>> import aiohttp
22 >>> result = aiohttp.get('https://api.github.com')
23 >>> response = await result
24 File "<stdin>", line 1
25 response = await result
26 ^
27 SyntaxError: invalid syntax
28
29 Should behave as expected in the IPython REPL::
30
31 Python 3.6.0
32 Type 'copyright', 'credits' or 'license' for more information
33 IPython 6.0.0.dev -- An enhanced Interactive Python. Type '?' for help.
34
35 In [1]: import aiohttp
36 ...: result = aiohttp.get('https://api.github.com')
37
38 In [2]: response = await result
39 <pause for a few 100s ms>
40
41 In [3]: await response.json()
42 Out[3]:
43 {'authorizations_url': 'https://api.github.com/authorizations',
44 'code_search_url': 'https://api.github.com/search/code?q={query}...',
45 ...
46 }
47
48
49 You can use the ``c.InteractiveShell.autoawait`` configuration option and set it
50 to :any:`False` to deactivate automatic wrapping of asynchronous code. You can also
51 use the :magic:`%autoawait` magic to toggle the behavior at runtime::
52
53 In [1]: %autoawait False
54
55 In [2]: %autoawait
56 IPython autoawait is `Off`, and set to use `IPython.core.interactiveshell._asyncio_runner`
57
58
59
60 By default IPython will assume integration with Python's provided
61 :mod:`asyncio`, but integration with other libraries is provided. In particular
62 we provide experimental integration with the ``curio`` and ``trio`` library.
63
64 You can switch current integration by using the
65 ``c.InteractiveShell.loop_runner`` option or the ``autoawait <name
66 integration>`` magic.
67
68 For example::
69
70 In [1]: %autoawait trio
71
72 In [2]: import trio
73
74 In [3]: async def child(i):
75 ...: print(" child %s goes to sleep"%i)
76 ...: await trio.sleep(2)
77 ...: print(" child %s wakes up"%i)
78
79 In [4]: print('parent start')
80 ...: async with trio.open_nursery() as n:
81 ...: for i in range(5):
82 ...: n.spawn(child, i)
83 ...: print('parent end')
84 parent start
85 child 2 goes to sleep
86 child 0 goes to sleep
87 child 3 goes to sleep
88 child 1 goes to sleep
89 child 4 goes to sleep
90 <about 2 seconds pause>
91 child 2 wakes up
92 child 1 wakes up
93 child 0 wakes up
94 child 3 wakes up
95 child 4 wakes up
96 parent end
97
98
99 In the above example, ``async with`` at top level scope is a syntax error in
100 Python.
101
102 Using this mode can have unexpected consequences if used in interaction with
103 other features of IPython and various registered extensions. In particular if you
104 are a direct or indirect user of the AST transformers, these may not apply to
105 your code.
106
107 The default loop, or runner does not run in the background, so top level
108 asynchronous code must finish for the REPL to allow you to enter more code. As
109 with usual Python semantic, the awaitables are started only when awaited for the
110 first time. That is to say, in first example, no network request is done between
111 ``In[1]`` and ``In[2]``.
112
113
114 Internals
115 =========
116
117 As running asynchronous code is not supported in interactive REPL as of Python
118 3.6 we have to rely to a number of complex workaround to allow this to happen.
119 It is interesting to understand how this works in order to understand potential
120 bugs, or provide a custom runner.
121
122 Among the many approaches that are at our disposition, we find only one that
123 suited out need. Under the hood we :ct the code object from a async-def function
124 and run it in global namesapace after modifying the ``__code__`` object.::
125
126 async def inner_async():
127 locals().update(**global_namespace)
128 #
129 # here is user code
130 #
131 return last_user_statement
132 codeobj = modify(inner_async.__code__)
133 coroutine = eval(codeobj, user_ns)
134 display(loop_runner(coroutine))
135
136
137
138 The first thing you'll notice is that unlike classical ``exec``, there is only
139 one name space. Second, user code runs in a function scope, and not a module
140 scope.
141
142 On top of the above there are significant modification to the AST of
143 ``function``, and ``loop_runner`` can be arbitrary complex. So there is a
144 significant overhead to this kind of code.
145
146 By default the generated coroutine function will be consumed by Asyncio's
147 ``loop_runner = asyncio.get_evenloop().run_until_complete()`` method. It is
148 though possible to provide your own.
149
150 A loop runner is a *synchronous* function responsible from running a coroutine
151 object.
152
153 The runner is responsible from ensuring that ``coroutine`` run to completion,
154 and should return the result of executing the coroutine. Let's write a
155 runner for ``trio`` that print a message when used as an exercise, ``trio`` is
156 special as it usually prefer to run a function object and make a coroutine by
157 itself, we can get around this limitation by wrapping it in an async-def without
158 parameters and passing this value to ``trio``::
159
160
161 In [1]: import trio
162 ...: from types import CoroutineType
163 ...:
164 ...: def trio_runner(coro:CoroutineType):
165 ...: print('running asynchronous code')
166 ...: async def corowrap(coro):
167 ...: return await coro
168 ...: return trio.run(corowrap, coro)
169
170 We can set it up by passing it to ``%autoawait``::
171
172 In [2]: %autoawait trio_runner
173
174 In [3]: async def async_hello(name):
175 ...: await trio.sleep(1)
176 ...: print(f'Hello {name} world !')
177 ...: await trio.sleep(1)
178
179 In [4]: await async_hello('async')
180 running asynchronous code
181 Hello async world !
182
183
184 Asynchronous programming in python (and in particular in the REPL) is still a
185 relatively young subject. Feel free to contribute improvements to this codebase
186 and give us feedback.
@@ -0,0 +1,55 b''
1 Await REPL
2 ----------
3
4 :ghpull:`10390` introduced the ability to ``await`` Futures and
5 Coroutines in the REPL. For example::
6
7 Python 3.6.0
8 Type 'copyright', 'credits' or 'license' for more information
9 IPython 6.0.0.dev -- An enhanced Interactive Python. Type '?' for help.
10
11 In [1]: import aiohttp
12 ...: result = aiohttp.get('https://api.github.com')
13
14 In [2]: response = await result
15 <pause for a few 100s ms>
16
17 In [3]: await response.json()
18 Out[3]:
19 {'authorizations_url': 'https://api.github.com/authorizations',
20 'code_search_url': 'https://api.github.com/search/code?q={query}{&page,per_page,sort,order}',
21 ...
22 }
23
24
25 Integration is by default with `asyncio`, but other libraries can be configured,
26 like ``curio`` or ``trio``, to improve concurrency in the REPL::
27
28 In [1]: %autoawait trio
29
30 In [2]: import trio
31
32 In [3]: async def child(i):
33 ...: print(" child %s goes to sleep"%i)
34 ...: await trio.sleep(2)
35 ...: print(" child %s wakes up"%i)
36
37 In [4]: print('parent start')
38 ...: async with trio.open_nursery() as n:
39 ...: for i in range(3):
40 ...: n.spawn(child, i)
41 ...: print('parent end')
42 parent start
43 child 2 goes to sleep
44 child 0 goes to sleep
45 child 1 goes to sleep
46 <about 2 seconds pause>
47 child 2 wakes up
48 child 1 wakes up
49 child 0 wakes up
50 parent end
51
52 See :ref:`autoawait` for more information.
53
54
55
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,599 +1,658 b''
1 """Implementation of basic magic functions."""
1 """Implementation of basic magic functions."""
2
2
3
3
4 import argparse
4 import argparse
5 import textwrap
5 from logging import error
6 import io
6 import io
7 import sys
8 from pprint import pformat
7 from pprint import pformat
8 import textwrap
9 import sys
10 from warnings import warn
9
11
12 from traitlets.utils.importstring import import_item
10 from IPython.core import magic_arguments, page
13 from IPython.core import magic_arguments, page
11 from IPython.core.error import UsageError
14 from IPython.core.error import UsageError
12 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
15 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
13 from IPython.utils.text import format_screen, dedent, indent
16 from IPython.utils.text import format_screen, dedent, indent
14 from IPython.testing.skipdoctest import skip_doctest
17 from IPython.testing.skipdoctest import skip_doctest
15 from IPython.utils.ipstruct import Struct
18 from IPython.utils.ipstruct import Struct
16 from warnings import warn
17 from logging import error
18
19
19
20
20 class MagicsDisplay(object):
21 class MagicsDisplay(object):
21 def __init__(self, magics_manager, ignore=None):
22 def __init__(self, magics_manager, ignore=None):
22 self.ignore = ignore if ignore else []
23 self.ignore = ignore if ignore else []
23 self.magics_manager = magics_manager
24 self.magics_manager = magics_manager
24
25
25 def _lsmagic(self):
26 def _lsmagic(self):
26 """The main implementation of the %lsmagic"""
27 """The main implementation of the %lsmagic"""
27 mesc = magic_escapes['line']
28 mesc = magic_escapes['line']
28 cesc = magic_escapes['cell']
29 cesc = magic_escapes['cell']
29 mman = self.magics_manager
30 mman = self.magics_manager
30 magics = mman.lsmagic()
31 magics = mman.lsmagic()
31 out = ['Available line magics:',
32 out = ['Available line magics:',
32 mesc + (' '+mesc).join(sorted([m for m,v in magics['line'].items() if (v not in self.ignore)])),
33 mesc + (' '+mesc).join(sorted([m for m,v in magics['line'].items() if (v not in self.ignore)])),
33 '',
34 '',
34 'Available cell magics:',
35 'Available cell magics:',
35 cesc + (' '+cesc).join(sorted([m for m,v in magics['cell'].items() if (v not in self.ignore)])),
36 cesc + (' '+cesc).join(sorted([m for m,v in magics['cell'].items() if (v not in self.ignore)])),
36 '',
37 '',
37 mman.auto_status()]
38 mman.auto_status()]
38 return '\n'.join(out)
39 return '\n'.join(out)
39
40
40 def _repr_pretty_(self, p, cycle):
41 def _repr_pretty_(self, p, cycle):
41 p.text(self._lsmagic())
42 p.text(self._lsmagic())
42
43
43 def __str__(self):
44 def __str__(self):
44 return self._lsmagic()
45 return self._lsmagic()
45
46
46 def _jsonable(self):
47 def _jsonable(self):
47 """turn magics dict into jsonable dict of the same structure
48 """turn magics dict into jsonable dict of the same structure
48
49
49 replaces object instances with their class names as strings
50 replaces object instances with their class names as strings
50 """
51 """
51 magic_dict = {}
52 magic_dict = {}
52 mman = self.magics_manager
53 mman = self.magics_manager
53 magics = mman.lsmagic()
54 magics = mman.lsmagic()
54 for key, subdict in magics.items():
55 for key, subdict in magics.items():
55 d = {}
56 d = {}
56 magic_dict[key] = d
57 magic_dict[key] = d
57 for name, obj in subdict.items():
58 for name, obj in subdict.items():
58 try:
59 try:
59 classname = obj.__self__.__class__.__name__
60 classname = obj.__self__.__class__.__name__
60 except AttributeError:
61 except AttributeError:
61 classname = 'Other'
62 classname = 'Other'
62
63
63 d[name] = classname
64 d[name] = classname
64 return magic_dict
65 return magic_dict
65
66
66 def _repr_json_(self):
67 def _repr_json_(self):
67 return self._jsonable()
68 return self._jsonable()
68
69
69
70
70 @magics_class
71 @magics_class
71 class BasicMagics(Magics):
72 class BasicMagics(Magics):
72 """Magics that provide central IPython functionality.
73 """Magics that provide central IPython functionality.
73
74
74 These are various magics that don't fit into specific categories but that
75 These are various magics that don't fit into specific categories but that
75 are all part of the base 'IPython experience'."""
76 are all part of the base 'IPython experience'."""
76
77
77 @magic_arguments.magic_arguments()
78 @magic_arguments.magic_arguments()
78 @magic_arguments.argument(
79 @magic_arguments.argument(
79 '-l', '--line', action='store_true',
80 '-l', '--line', action='store_true',
80 help="""Create a line magic alias."""
81 help="""Create a line magic alias."""
81 )
82 )
82 @magic_arguments.argument(
83 @magic_arguments.argument(
83 '-c', '--cell', action='store_true',
84 '-c', '--cell', action='store_true',
84 help="""Create a cell magic alias."""
85 help="""Create a cell magic alias."""
85 )
86 )
86 @magic_arguments.argument(
87 @magic_arguments.argument(
87 'name',
88 'name',
88 help="""Name of the magic to be created."""
89 help="""Name of the magic to be created."""
89 )
90 )
90 @magic_arguments.argument(
91 @magic_arguments.argument(
91 'target',
92 'target',
92 help="""Name of the existing line or cell magic."""
93 help="""Name of the existing line or cell magic."""
93 )
94 )
94 @magic_arguments.argument(
95 @magic_arguments.argument(
95 '-p', '--params', default=None,
96 '-p', '--params', default=None,
96 help="""Parameters passed to the magic function."""
97 help="""Parameters passed to the magic function."""
97 )
98 )
98 @line_magic
99 @line_magic
99 def alias_magic(self, line=''):
100 def alias_magic(self, line=''):
100 """Create an alias for an existing line or cell magic.
101 """Create an alias for an existing line or cell magic.
101
102
102 Examples
103 Examples
103 --------
104 --------
104 ::
105 ::
105
106
106 In [1]: %alias_magic t timeit
107 In [1]: %alias_magic t timeit
107 Created `%t` as an alias for `%timeit`.
108 Created `%t` as an alias for `%timeit`.
108 Created `%%t` as an alias for `%%timeit`.
109 Created `%%t` as an alias for `%%timeit`.
109
110
110 In [2]: %t -n1 pass
111 In [2]: %t -n1 pass
111 1 loops, best of 3: 954 ns per loop
112 1 loops, best of 3: 954 ns per loop
112
113
113 In [3]: %%t -n1
114 In [3]: %%t -n1
114 ...: pass
115 ...: pass
115 ...:
116 ...:
116 1 loops, best of 3: 954 ns per loop
117 1 loops, best of 3: 954 ns per loop
117
118
118 In [4]: %alias_magic --cell whereami pwd
119 In [4]: %alias_magic --cell whereami pwd
119 UsageError: Cell magic function `%%pwd` not found.
120 UsageError: Cell magic function `%%pwd` not found.
120 In [5]: %alias_magic --line whereami pwd
121 In [5]: %alias_magic --line whereami pwd
121 Created `%whereami` as an alias for `%pwd`.
122 Created `%whereami` as an alias for `%pwd`.
122
123
123 In [6]: %whereami
124 In [6]: %whereami
124 Out[6]: u'/home/testuser'
125 Out[6]: u'/home/testuser'
125
126
126 In [7]: %alias_magic h history -p "-l 30" --line
127 In [7]: %alias_magic h history -p "-l 30" --line
127 Created `%h` as an alias for `%history -l 30`.
128 Created `%h` as an alias for `%history -l 30`.
128 """
129 """
129
130
130 args = magic_arguments.parse_argstring(self.alias_magic, line)
131 args = magic_arguments.parse_argstring(self.alias_magic, line)
131 shell = self.shell
132 shell = self.shell
132 mman = self.shell.magics_manager
133 mman = self.shell.magics_manager
133 escs = ''.join(magic_escapes.values())
134 escs = ''.join(magic_escapes.values())
134
135
135 target = args.target.lstrip(escs)
136 target = args.target.lstrip(escs)
136 name = args.name.lstrip(escs)
137 name = args.name.lstrip(escs)
137
138
138 params = args.params
139 params = args.params
139 if (params and
140 if (params and
140 ((params.startswith('"') and params.endswith('"'))
141 ((params.startswith('"') and params.endswith('"'))
141 or (params.startswith("'") and params.endswith("'")))):
142 or (params.startswith("'") and params.endswith("'")))):
142 params = params[1:-1]
143 params = params[1:-1]
143
144
144 # Find the requested magics.
145 # Find the requested magics.
145 m_line = shell.find_magic(target, 'line')
146 m_line = shell.find_magic(target, 'line')
146 m_cell = shell.find_magic(target, 'cell')
147 m_cell = shell.find_magic(target, 'cell')
147 if args.line and m_line is None:
148 if args.line and m_line is None:
148 raise UsageError('Line magic function `%s%s` not found.' %
149 raise UsageError('Line magic function `%s%s` not found.' %
149 (magic_escapes['line'], target))
150 (magic_escapes['line'], target))
150 if args.cell and m_cell is None:
151 if args.cell and m_cell is None:
151 raise UsageError('Cell magic function `%s%s` not found.' %
152 raise UsageError('Cell magic function `%s%s` not found.' %
152 (magic_escapes['cell'], target))
153 (magic_escapes['cell'], target))
153
154
154 # If --line and --cell are not specified, default to the ones
155 # If --line and --cell are not specified, default to the ones
155 # that are available.
156 # that are available.
156 if not args.line and not args.cell:
157 if not args.line and not args.cell:
157 if not m_line and not m_cell:
158 if not m_line and not m_cell:
158 raise UsageError(
159 raise UsageError(
159 'No line or cell magic with name `%s` found.' % target
160 'No line or cell magic with name `%s` found.' % target
160 )
161 )
161 args.line = bool(m_line)
162 args.line = bool(m_line)
162 args.cell = bool(m_cell)
163 args.cell = bool(m_cell)
163
164
164 params_str = "" if params is None else " " + params
165 params_str = "" if params is None else " " + params
165
166
166 if args.line:
167 if args.line:
167 mman.register_alias(name, target, 'line', params)
168 mman.register_alias(name, target, 'line', params)
168 print('Created `%s%s` as an alias for `%s%s%s`.' % (
169 print('Created `%s%s` as an alias for `%s%s%s`.' % (
169 magic_escapes['line'], name,
170 magic_escapes['line'], name,
170 magic_escapes['line'], target, params_str))
171 magic_escapes['line'], target, params_str))
171
172
172 if args.cell:
173 if args.cell:
173 mman.register_alias(name, target, 'cell', params)
174 mman.register_alias(name, target, 'cell', params)
174 print('Created `%s%s` as an alias for `%s%s%s`.' % (
175 print('Created `%s%s` as an alias for `%s%s%s`.' % (
175 magic_escapes['cell'], name,
176 magic_escapes['cell'], name,
176 magic_escapes['cell'], target, params_str))
177 magic_escapes['cell'], target, params_str))
177
178
178 @line_magic
179 @line_magic
179 def lsmagic(self, parameter_s=''):
180 def lsmagic(self, parameter_s=''):
180 """List currently available magic functions."""
181 """List currently available magic functions."""
181 return MagicsDisplay(self.shell.magics_manager, ignore=[self.pip])
182 return MagicsDisplay(self.shell.magics_manager, ignore=[self.pip])
182
183
183 def _magic_docs(self, brief=False, rest=False):
184 def _magic_docs(self, brief=False, rest=False):
184 """Return docstrings from magic functions."""
185 """Return docstrings from magic functions."""
185 mman = self.shell.magics_manager
186 mman = self.shell.magics_manager
186 docs = mman.lsmagic_docs(brief, missing='No documentation')
187 docs = mman.lsmagic_docs(brief, missing='No documentation')
187
188
188 if rest:
189 if rest:
189 format_string = '**%s%s**::\n\n%s\n\n'
190 format_string = '**%s%s**::\n\n%s\n\n'
190 else:
191 else:
191 format_string = '%s%s:\n%s\n'
192 format_string = '%s%s:\n%s\n'
192
193
193 return ''.join(
194 return ''.join(
194 [format_string % (magic_escapes['line'], fname,
195 [format_string % (magic_escapes['line'], fname,
195 indent(dedent(fndoc)))
196 indent(dedent(fndoc)))
196 for fname, fndoc in sorted(docs['line'].items())]
197 for fname, fndoc in sorted(docs['line'].items())]
197 +
198 +
198 [format_string % (magic_escapes['cell'], fname,
199 [format_string % (magic_escapes['cell'], fname,
199 indent(dedent(fndoc)))
200 indent(dedent(fndoc)))
200 for fname, fndoc in sorted(docs['cell'].items())]
201 for fname, fndoc in sorted(docs['cell'].items())]
201 )
202 )
202
203
203 @line_magic
204 @line_magic
204 def magic(self, parameter_s=''):
205 def magic(self, parameter_s=''):
205 """Print information about the magic function system.
206 """Print information about the magic function system.
206
207
207 Supported formats: -latex, -brief, -rest
208 Supported formats: -latex, -brief, -rest
208 """
209 """
209
210
210 mode = ''
211 mode = ''
211 try:
212 try:
212 mode = parameter_s.split()[0][1:]
213 mode = parameter_s.split()[0][1:]
213 except IndexError:
214 except IndexError:
214 pass
215 pass
215
216
216 brief = (mode == 'brief')
217 brief = (mode == 'brief')
217 rest = (mode == 'rest')
218 rest = (mode == 'rest')
218 magic_docs = self._magic_docs(brief, rest)
219 magic_docs = self._magic_docs(brief, rest)
219
220
220 if mode == 'latex':
221 if mode == 'latex':
221 print(self.format_latex(magic_docs))
222 print(self.format_latex(magic_docs))
222 return
223 return
223 else:
224 else:
224 magic_docs = format_screen(magic_docs)
225 magic_docs = format_screen(magic_docs)
225
226
226 out = ["""
227 out = ["""
227 IPython's 'magic' functions
228 IPython's 'magic' functions
228 ===========================
229 ===========================
229
230
230 The magic function system provides a series of functions which allow you to
231 The magic function system provides a series of functions which allow you to
231 control the behavior of IPython itself, plus a lot of system-type
232 control the behavior of IPython itself, plus a lot of system-type
232 features. There are two kinds of magics, line-oriented and cell-oriented.
233 features. There are two kinds of magics, line-oriented and cell-oriented.
233
234
234 Line magics are prefixed with the % character and work much like OS
235 Line magics are prefixed with the % character and work much like OS
235 command-line calls: they get as an argument the rest of the line, where
236 command-line calls: they get as an argument the rest of the line, where
236 arguments are passed without parentheses or quotes. For example, this will
237 arguments are passed without parentheses or quotes. For example, this will
237 time the given statement::
238 time the given statement::
238
239
239 %timeit range(1000)
240 %timeit range(1000)
240
241
241 Cell magics are prefixed with a double %%, and they are functions that get as
242 Cell magics are prefixed with a double %%, and they are functions that get as
242 an argument not only the rest of the line, but also the lines below it in a
243 an argument not only the rest of the line, but also the lines below it in a
243 separate argument. These magics are called with two arguments: the rest of the
244 separate argument. These magics are called with two arguments: the rest of the
244 call line and the body of the cell, consisting of the lines below the first.
245 call line and the body of the cell, consisting of the lines below the first.
245 For example::
246 For example::
246
247
247 %%timeit x = numpy.random.randn((100, 100))
248 %%timeit x = numpy.random.randn((100, 100))
248 numpy.linalg.svd(x)
249 numpy.linalg.svd(x)
249
250
250 will time the execution of the numpy svd routine, running the assignment of x
251 will time the execution of the numpy svd routine, running the assignment of x
251 as part of the setup phase, which is not timed.
252 as part of the setup phase, which is not timed.
252
253
253 In a line-oriented client (the terminal or Qt console IPython), starting a new
254 In a line-oriented client (the terminal or Qt console IPython), starting a new
254 input with %% will automatically enter cell mode, and IPython will continue
255 input with %% will automatically enter cell mode, and IPython will continue
255 reading input until a blank line is given. In the notebook, simply type the
256 reading input until a blank line is given. In the notebook, simply type the
256 whole cell as one entity, but keep in mind that the %% escape can only be at
257 whole cell as one entity, but keep in mind that the %% escape can only be at
257 the very start of the cell.
258 the very start of the cell.
258
259
259 NOTE: If you have 'automagic' enabled (via the command line option or with the
260 NOTE: If you have 'automagic' enabled (via the command line option or with the
260 %automagic function), you don't need to type in the % explicitly for line
261 %automagic function), you don't need to type in the % explicitly for line
261 magics; cell magics always require an explicit '%%' escape. By default,
262 magics; cell magics always require an explicit '%%' escape. By default,
262 IPython ships with automagic on, so you should only rarely need the % escape.
263 IPython ships with automagic on, so you should only rarely need the % escape.
263
264
264 Example: typing '%cd mydir' (without the quotes) changes your working directory
265 Example: typing '%cd mydir' (without the quotes) changes your working directory
265 to 'mydir', if it exists.
266 to 'mydir', if it exists.
266
267
267 For a list of the available magic functions, use %lsmagic. For a description
268 For a list of the available magic functions, use %lsmagic. For a description
268 of any of them, type %magic_name?, e.g. '%cd?'.
269 of any of them, type %magic_name?, e.g. '%cd?'.
269
270
270 Currently the magic system has the following functions:""",
271 Currently the magic system has the following functions:""",
271 magic_docs,
272 magic_docs,
272 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
273 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
273 str(self.lsmagic()),
274 str(self.lsmagic()),
274 ]
275 ]
275 page.page('\n'.join(out))
276 page.page('\n'.join(out))
276
277
277
278
278 @line_magic
279 @line_magic
279 def page(self, parameter_s=''):
280 def page(self, parameter_s=''):
280 """Pretty print the object and display it through a pager.
281 """Pretty print the object and display it through a pager.
281
282
282 %page [options] OBJECT
283 %page [options] OBJECT
283
284
284 If no object is given, use _ (last output).
285 If no object is given, use _ (last output).
285
286
286 Options:
287 Options:
287
288
288 -r: page str(object), don't pretty-print it."""
289 -r: page str(object), don't pretty-print it."""
289
290
290 # After a function contributed by Olivier Aubert, slightly modified.
291 # After a function contributed by Olivier Aubert, slightly modified.
291
292
292 # Process options/args
293 # Process options/args
293 opts, args = self.parse_options(parameter_s, 'r')
294 opts, args = self.parse_options(parameter_s, 'r')
294 raw = 'r' in opts
295 raw = 'r' in opts
295
296
296 oname = args and args or '_'
297 oname = args and args or '_'
297 info = self.shell._ofind(oname)
298 info = self.shell._ofind(oname)
298 if info['found']:
299 if info['found']:
299 txt = (raw and str or pformat)( info['obj'] )
300 txt = (raw and str or pformat)( info['obj'] )
300 page.page(txt)
301 page.page(txt)
301 else:
302 else:
302 print('Object `%s` not found' % oname)
303 print('Object `%s` not found' % oname)
303
304
304 @line_magic
305 @line_magic
305 def pprint(self, parameter_s=''):
306 def pprint(self, parameter_s=''):
306 """Toggle pretty printing on/off."""
307 """Toggle pretty printing on/off."""
307 ptformatter = self.shell.display_formatter.formatters['text/plain']
308 ptformatter = self.shell.display_formatter.formatters['text/plain']
308 ptformatter.pprint = bool(1 - ptformatter.pprint)
309 ptformatter.pprint = bool(1 - ptformatter.pprint)
309 print('Pretty printing has been turned',
310 print('Pretty printing has been turned',
310 ['OFF','ON'][ptformatter.pprint])
311 ['OFF','ON'][ptformatter.pprint])
311
312
312 @line_magic
313 @line_magic
313 def colors(self, parameter_s=''):
314 def colors(self, parameter_s=''):
314 """Switch color scheme for prompts, info system and exception handlers.
315 """Switch color scheme for prompts, info system and exception handlers.
315
316
316 Currently implemented schemes: NoColor, Linux, LightBG.
317 Currently implemented schemes: NoColor, Linux, LightBG.
317
318
318 Color scheme names are not case-sensitive.
319 Color scheme names are not case-sensitive.
319
320
320 Examples
321 Examples
321 --------
322 --------
322 To get a plain black and white terminal::
323 To get a plain black and white terminal::
323
324
324 %colors nocolor
325 %colors nocolor
325 """
326 """
326 def color_switch_err(name):
327 def color_switch_err(name):
327 warn('Error changing %s color schemes.\n%s' %
328 warn('Error changing %s color schemes.\n%s' %
328 (name, sys.exc_info()[1]), stacklevel=2)
329 (name, sys.exc_info()[1]), stacklevel=2)
329
330
330
331
331 new_scheme = parameter_s.strip()
332 new_scheme = parameter_s.strip()
332 if not new_scheme:
333 if not new_scheme:
333 raise UsageError(
334 raise UsageError(
334 "%colors: you must specify a color scheme. See '%colors?'")
335 "%colors: you must specify a color scheme. See '%colors?'")
335 # local shortcut
336 # local shortcut
336 shell = self.shell
337 shell = self.shell
337
338
338 # Set shell colour scheme
339 # Set shell colour scheme
339 try:
340 try:
340 shell.colors = new_scheme
341 shell.colors = new_scheme
341 shell.refresh_style()
342 shell.refresh_style()
342 except:
343 except:
343 color_switch_err('shell')
344 color_switch_err('shell')
344
345
345 # Set exception colors
346 # Set exception colors
346 try:
347 try:
347 shell.InteractiveTB.set_colors(scheme = new_scheme)
348 shell.InteractiveTB.set_colors(scheme = new_scheme)
348 shell.SyntaxTB.set_colors(scheme = new_scheme)
349 shell.SyntaxTB.set_colors(scheme = new_scheme)
349 except:
350 except:
350 color_switch_err('exception')
351 color_switch_err('exception')
351
352
352 # Set info (for 'object?') colors
353 # Set info (for 'object?') colors
353 if shell.color_info:
354 if shell.color_info:
354 try:
355 try:
355 shell.inspector.set_active_scheme(new_scheme)
356 shell.inspector.set_active_scheme(new_scheme)
356 except:
357 except:
357 color_switch_err('object inspector')
358 color_switch_err('object inspector')
358 else:
359 else:
359 shell.inspector.set_active_scheme('NoColor')
360 shell.inspector.set_active_scheme('NoColor')
360
361
361 @line_magic
362 @line_magic
362 def xmode(self, parameter_s=''):
363 def xmode(self, parameter_s=''):
363 """Switch modes for the exception handlers.
364 """Switch modes for the exception handlers.
364
365
365 Valid modes: Plain, Context and Verbose.
366 Valid modes: Plain, Context and Verbose.
366
367
367 If called without arguments, acts as a toggle."""
368 If called without arguments, acts as a toggle."""
368
369
369 def xmode_switch_err(name):
370 def xmode_switch_err(name):
370 warn('Error changing %s exception modes.\n%s' %
371 warn('Error changing %s exception modes.\n%s' %
371 (name,sys.exc_info()[1]))
372 (name,sys.exc_info()[1]))
372
373
373 shell = self.shell
374 shell = self.shell
374 new_mode = parameter_s.strip().capitalize()
375 new_mode = parameter_s.strip().capitalize()
375 try:
376 try:
376 shell.InteractiveTB.set_mode(mode=new_mode)
377 shell.InteractiveTB.set_mode(mode=new_mode)
377 print('Exception reporting mode:',shell.InteractiveTB.mode)
378 print('Exception reporting mode:',shell.InteractiveTB.mode)
378 except:
379 except:
379 xmode_switch_err('user')
380 xmode_switch_err('user')
380
381
381 @line_magic
382 @line_magic
383 def autoawait(self, parameter_s):
384 """
385 Allow to change the status of the autoawait option.
386
387 This allow you to set a specific asynchronous code runner.
388
389 If no value is passed, print the currently used asynchronous integration
390 and whether it is activated.
391
392 It can take a number of value evaluated in the following order:
393
394 - False/false/off deactivate autoawait integration
395 - True/true/on activate autoawait integration using configured default
396 loop
397 - asyncio/curio/trio activate autoawait integration and use integration
398 with said library.
399
400 If the passed parameter does not match any of the above and is a python
401 identifier, get said object from user namespace and set it as the
402 runner, and activate autoawait.
403
404 If the object is a fully qualified object name, attempt to import it and
405 set it as the runner, and activate autoawait."""
406
407 param = parameter_s.strip()
408 d = {True: "on", False: "off"}
409
410 if not param:
411 print("IPython autoawait is `{}`, and set to use `{}`".format(
412 d[self.shell.autoawait],
413 self.shell.loop_runner
414 ))
415 return None
416
417 if param.lower() in ('false', 'off'):
418 self.shell.autoawait = False
419 return None
420 if param.lower() in ('true', 'on'):
421 self.shell.autoawait = True
422 return None
423
424 if param in self.shell.loop_runner_map:
425 self.shell.loop_runner = param
426 self.shell.autoawait = True
427 return None
428
429 if param in self.shell.user_ns :
430 self.shell.loop_runner = self.shell.user_ns[param]
431 self.shell.autoawait = True
432 return None
433
434 runner = import_item(param)
435
436 self.shell.loop_runner = runner
437 self.shell.autoawait = True
438
439
440 @line_magic
382 def pip(self, args=''):
441 def pip(self, args=''):
383 """
442 """
384 Intercept usage of ``pip`` in IPython and direct user to run command outside of IPython.
443 Intercept usage of ``pip`` in IPython and direct user to run command outside of IPython.
385 """
444 """
386 print(textwrap.dedent('''
445 print(textwrap.dedent('''
387 The following command must be run outside of the IPython shell:
446 The following command must be run outside of the IPython shell:
388
447
389 $ pip {args}
448 $ pip {args}
390
449
391 The Python package manager (pip) can only be used from outside of IPython.
450 The Python package manager (pip) can only be used from outside of IPython.
392 Please reissue the `pip` command in a separate terminal or command prompt.
451 Please reissue the `pip` command in a separate terminal or command prompt.
393
452
394 See the Python documentation for more information on how to install packages:
453 See the Python documentation for more information on how to install packages:
395
454
396 https://docs.python.org/3/installing/'''.format(args=args)))
455 https://docs.python.org/3/installing/'''.format(args=args)))
397
456
398 @line_magic
457 @line_magic
399 def quickref(self, arg):
458 def quickref(self, arg):
400 """ Show a quick reference sheet """
459 """ Show a quick reference sheet """
401 from IPython.core.usage import quick_reference
460 from IPython.core.usage import quick_reference
402 qr = quick_reference + self._magic_docs(brief=True)
461 qr = quick_reference + self._magic_docs(brief=True)
403 page.page(qr)
462 page.page(qr)
404
463
405 @line_magic
464 @line_magic
406 def doctest_mode(self, parameter_s=''):
465 def doctest_mode(self, parameter_s=''):
407 """Toggle doctest mode on and off.
466 """Toggle doctest mode on and off.
408
467
409 This mode is intended to make IPython behave as much as possible like a
468 This mode is intended to make IPython behave as much as possible like a
410 plain Python shell, from the perspective of how its prompts, exceptions
469 plain Python shell, from the perspective of how its prompts, exceptions
411 and output look. This makes it easy to copy and paste parts of a
470 and output look. This makes it easy to copy and paste parts of a
412 session into doctests. It does so by:
471 session into doctests. It does so by:
413
472
414 - Changing the prompts to the classic ``>>>`` ones.
473 - Changing the prompts to the classic ``>>>`` ones.
415 - Changing the exception reporting mode to 'Plain'.
474 - Changing the exception reporting mode to 'Plain'.
416 - Disabling pretty-printing of output.
475 - Disabling pretty-printing of output.
417
476
418 Note that IPython also supports the pasting of code snippets that have
477 Note that IPython also supports the pasting of code snippets that have
419 leading '>>>' and '...' prompts in them. This means that you can paste
478 leading '>>>' and '...' prompts in them. This means that you can paste
420 doctests from files or docstrings (even if they have leading
479 doctests from files or docstrings (even if they have leading
421 whitespace), and the code will execute correctly. You can then use
480 whitespace), and the code will execute correctly. You can then use
422 '%history -t' to see the translated history; this will give you the
481 '%history -t' to see the translated history; this will give you the
423 input after removal of all the leading prompts and whitespace, which
482 input after removal of all the leading prompts and whitespace, which
424 can be pasted back into an editor.
483 can be pasted back into an editor.
425
484
426 With these features, you can switch into this mode easily whenever you
485 With these features, you can switch into this mode easily whenever you
427 need to do testing and changes to doctests, without having to leave
486 need to do testing and changes to doctests, without having to leave
428 your existing IPython session.
487 your existing IPython session.
429 """
488 """
430
489
431 # Shorthands
490 # Shorthands
432 shell = self.shell
491 shell = self.shell
433 meta = shell.meta
492 meta = shell.meta
434 disp_formatter = self.shell.display_formatter
493 disp_formatter = self.shell.display_formatter
435 ptformatter = disp_formatter.formatters['text/plain']
494 ptformatter = disp_formatter.formatters['text/plain']
436 # dstore is a data store kept in the instance metadata bag to track any
495 # dstore is a data store kept in the instance metadata bag to track any
437 # changes we make, so we can undo them later.
496 # changes we make, so we can undo them later.
438 dstore = meta.setdefault('doctest_mode',Struct())
497 dstore = meta.setdefault('doctest_mode',Struct())
439 save_dstore = dstore.setdefault
498 save_dstore = dstore.setdefault
440
499
441 # save a few values we'll need to recover later
500 # save a few values we'll need to recover later
442 mode = save_dstore('mode',False)
501 mode = save_dstore('mode',False)
443 save_dstore('rc_pprint',ptformatter.pprint)
502 save_dstore('rc_pprint',ptformatter.pprint)
444 save_dstore('xmode',shell.InteractiveTB.mode)
503 save_dstore('xmode',shell.InteractiveTB.mode)
445 save_dstore('rc_separate_out',shell.separate_out)
504 save_dstore('rc_separate_out',shell.separate_out)
446 save_dstore('rc_separate_out2',shell.separate_out2)
505 save_dstore('rc_separate_out2',shell.separate_out2)
447 save_dstore('rc_separate_in',shell.separate_in)
506 save_dstore('rc_separate_in',shell.separate_in)
448 save_dstore('rc_active_types',disp_formatter.active_types)
507 save_dstore('rc_active_types',disp_formatter.active_types)
449
508
450 if not mode:
509 if not mode:
451 # turn on
510 # turn on
452
511
453 # Prompt separators like plain python
512 # Prompt separators like plain python
454 shell.separate_in = ''
513 shell.separate_in = ''
455 shell.separate_out = ''
514 shell.separate_out = ''
456 shell.separate_out2 = ''
515 shell.separate_out2 = ''
457
516
458
517
459 ptformatter.pprint = False
518 ptformatter.pprint = False
460 disp_formatter.active_types = ['text/plain']
519 disp_formatter.active_types = ['text/plain']
461
520
462 shell.magic('xmode Plain')
521 shell.magic('xmode Plain')
463 else:
522 else:
464 # turn off
523 # turn off
465 shell.separate_in = dstore.rc_separate_in
524 shell.separate_in = dstore.rc_separate_in
466
525
467 shell.separate_out = dstore.rc_separate_out
526 shell.separate_out = dstore.rc_separate_out
468 shell.separate_out2 = dstore.rc_separate_out2
527 shell.separate_out2 = dstore.rc_separate_out2
469
528
470 ptformatter.pprint = dstore.rc_pprint
529 ptformatter.pprint = dstore.rc_pprint
471 disp_formatter.active_types = dstore.rc_active_types
530 disp_formatter.active_types = dstore.rc_active_types
472
531
473 shell.magic('xmode ' + dstore.xmode)
532 shell.magic('xmode ' + dstore.xmode)
474
533
475 # mode here is the state before we switch; switch_doctest_mode takes
534 # mode here is the state before we switch; switch_doctest_mode takes
476 # the mode we're switching to.
535 # the mode we're switching to.
477 shell.switch_doctest_mode(not mode)
536 shell.switch_doctest_mode(not mode)
478
537
479 # Store new mode and inform
538 # Store new mode and inform
480 dstore.mode = bool(not mode)
539 dstore.mode = bool(not mode)
481 mode_label = ['OFF','ON'][dstore.mode]
540 mode_label = ['OFF','ON'][dstore.mode]
482 print('Doctest mode is:', mode_label)
541 print('Doctest mode is:', mode_label)
483
542
484 @line_magic
543 @line_magic
485 def gui(self, parameter_s=''):
544 def gui(self, parameter_s=''):
486 """Enable or disable IPython GUI event loop integration.
545 """Enable or disable IPython GUI event loop integration.
487
546
488 %gui [GUINAME]
547 %gui [GUINAME]
489
548
490 This magic replaces IPython's threaded shells that were activated
549 This magic replaces IPython's threaded shells that were activated
491 using the (pylab/wthread/etc.) command line flags. GUI toolkits
550 using the (pylab/wthread/etc.) command line flags. GUI toolkits
492 can now be enabled at runtime and keyboard
551 can now be enabled at runtime and keyboard
493 interrupts should work without any problems. The following toolkits
552 interrupts should work without any problems. The following toolkits
494 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
553 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
495
554
496 %gui wx # enable wxPython event loop integration
555 %gui wx # enable wxPython event loop integration
497 %gui qt4|qt # enable PyQt4 event loop integration
556 %gui qt4|qt # enable PyQt4 event loop integration
498 %gui qt5 # enable PyQt5 event loop integration
557 %gui qt5 # enable PyQt5 event loop integration
499 %gui gtk # enable PyGTK event loop integration
558 %gui gtk # enable PyGTK event loop integration
500 %gui gtk3 # enable Gtk3 event loop integration
559 %gui gtk3 # enable Gtk3 event loop integration
501 %gui tk # enable Tk event loop integration
560 %gui tk # enable Tk event loop integration
502 %gui osx # enable Cocoa event loop integration
561 %gui osx # enable Cocoa event loop integration
503 # (requires %matplotlib 1.1)
562 # (requires %matplotlib 1.1)
504 %gui # disable all event loop integration
563 %gui # disable all event loop integration
505
564
506 WARNING: after any of these has been called you can simply create
565 WARNING: after any of these has been called you can simply create
507 an application object, but DO NOT start the event loop yourself, as
566 an application object, but DO NOT start the event loop yourself, as
508 we have already handled that.
567 we have already handled that.
509 """
568 """
510 opts, arg = self.parse_options(parameter_s, '')
569 opts, arg = self.parse_options(parameter_s, '')
511 if arg=='': arg = None
570 if arg=='': arg = None
512 try:
571 try:
513 return self.shell.enable_gui(arg)
572 return self.shell.enable_gui(arg)
514 except Exception as e:
573 except Exception as e:
515 # print simple error message, rather than traceback if we can't
574 # print simple error message, rather than traceback if we can't
516 # hook up the GUI
575 # hook up the GUI
517 error(str(e))
576 error(str(e))
518
577
519 @skip_doctest
578 @skip_doctest
520 @line_magic
579 @line_magic
521 def precision(self, s=''):
580 def precision(self, s=''):
522 """Set floating point precision for pretty printing.
581 """Set floating point precision for pretty printing.
523
582
524 Can set either integer precision or a format string.
583 Can set either integer precision or a format string.
525
584
526 If numpy has been imported and precision is an int,
585 If numpy has been imported and precision is an int,
527 numpy display precision will also be set, via ``numpy.set_printoptions``.
586 numpy display precision will also be set, via ``numpy.set_printoptions``.
528
587
529 If no argument is given, defaults will be restored.
588 If no argument is given, defaults will be restored.
530
589
531 Examples
590 Examples
532 --------
591 --------
533 ::
592 ::
534
593
535 In [1]: from math import pi
594 In [1]: from math import pi
536
595
537 In [2]: %precision 3
596 In [2]: %precision 3
538 Out[2]: u'%.3f'
597 Out[2]: u'%.3f'
539
598
540 In [3]: pi
599 In [3]: pi
541 Out[3]: 3.142
600 Out[3]: 3.142
542
601
543 In [4]: %precision %i
602 In [4]: %precision %i
544 Out[4]: u'%i'
603 Out[4]: u'%i'
545
604
546 In [5]: pi
605 In [5]: pi
547 Out[5]: 3
606 Out[5]: 3
548
607
549 In [6]: %precision %e
608 In [6]: %precision %e
550 Out[6]: u'%e'
609 Out[6]: u'%e'
551
610
552 In [7]: pi**10
611 In [7]: pi**10
553 Out[7]: 9.364805e+04
612 Out[7]: 9.364805e+04
554
613
555 In [8]: %precision
614 In [8]: %precision
556 Out[8]: u'%r'
615 Out[8]: u'%r'
557
616
558 In [9]: pi**10
617 In [9]: pi**10
559 Out[9]: 93648.047476082982
618 Out[9]: 93648.047476082982
560 """
619 """
561 ptformatter = self.shell.display_formatter.formatters['text/plain']
620 ptformatter = self.shell.display_formatter.formatters['text/plain']
562 ptformatter.float_precision = s
621 ptformatter.float_precision = s
563 return ptformatter.float_format
622 return ptformatter.float_format
564
623
565 @magic_arguments.magic_arguments()
624 @magic_arguments.magic_arguments()
566 @magic_arguments.argument(
625 @magic_arguments.argument(
567 '-e', '--export', action='store_true', default=False,
626 '-e', '--export', action='store_true', default=False,
568 help=argparse.SUPPRESS
627 help=argparse.SUPPRESS
569 )
628 )
570 @magic_arguments.argument(
629 @magic_arguments.argument(
571 'filename', type=str,
630 'filename', type=str,
572 help='Notebook name or filename'
631 help='Notebook name or filename'
573 )
632 )
574 @line_magic
633 @line_magic
575 def notebook(self, s):
634 def notebook(self, s):
576 """Export and convert IPython notebooks.
635 """Export and convert IPython notebooks.
577
636
578 This function can export the current IPython history to a notebook file.
637 This function can export the current IPython history to a notebook file.
579 For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb".
638 For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb".
580
639
581 The -e or --export flag is deprecated in IPython 5.2, and will be
640 The -e or --export flag is deprecated in IPython 5.2, and will be
582 removed in the future.
641 removed in the future.
583 """
642 """
584 args = magic_arguments.parse_argstring(self.notebook, s)
643 args = magic_arguments.parse_argstring(self.notebook, s)
585
644
586 from nbformat import write, v4
645 from nbformat import write, v4
587
646
588 cells = []
647 cells = []
589 hist = list(self.shell.history_manager.get_range())
648 hist = list(self.shell.history_manager.get_range())
590 if(len(hist)<=1):
649 if(len(hist)<=1):
591 raise ValueError('History is empty, cannot export')
650 raise ValueError('History is empty, cannot export')
592 for session, execution_count, source in hist[:-1]:
651 for session, execution_count, source in hist[:-1]:
593 cells.append(v4.new_code_cell(
652 cells.append(v4.new_code_cell(
594 execution_count=execution_count,
653 execution_count=execution_count,
595 source=source
654 source=source
596 ))
655 ))
597 nb = v4.new_notebook(cells=cells)
656 nb = v4.new_notebook(cells=cells)
598 with io.open(args.filename, 'w', encoding='utf-8') as f:
657 with io.open(args.filename, 'w', encoding='utf-8') as f:
599 write(nb, f, version=4)
658 write(nb, f, version=4)
@@ -1,396 +1,417 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 An embedded IPython shell.
3 An embedded IPython shell.
4 """
4 """
5 # Copyright (c) IPython Development Team.
5 # Copyright (c) IPython Development Team.
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7
7
8
8
9 import sys
9 import sys
10 import warnings
10 import warnings
11
11
12 from IPython.core import ultratb, compilerop
12 from IPython.core import ultratb, compilerop
13 from IPython.core import magic_arguments
13 from IPython.core import magic_arguments
14 from IPython.core.magic import Magics, magics_class, line_magic
14 from IPython.core.magic import Magics, magics_class, line_magic
15 from IPython.core.interactiveshell import DummyMod, InteractiveShell
15 from IPython.core.interactiveshell import DummyMod, InteractiveShell
16 from IPython.terminal.interactiveshell import TerminalInteractiveShell
16 from IPython.terminal.interactiveshell import TerminalInteractiveShell
17 from IPython.terminal.ipapp import load_default_config
17 from IPython.terminal.ipapp import load_default_config
18
18
19 from traitlets import Bool, CBool, Unicode
19 from traitlets import Bool, CBool, Unicode
20 from IPython.utils.io import ask_yes_no
20 from IPython.utils.io import ask_yes_no
21
21
22 from contextlib import contextmanager
23
24 _sentinel = object()
25 @contextmanager
26 def new_context():
27 import trio._core._run as tcr
28 old_runner = getattr(tcr.GLOBAL_RUN_CONTEXT, 'runner', _sentinel)
29 old_task = getattr(tcr.GLOBAL_RUN_CONTEXT, 'task', None)
30 if old_runner is not _sentinel:
31 del tcr.GLOBAL_RUN_CONTEXT.runner
32 tcr.GLOBAL_RUN_CONTEXT.task = None
33 yield
34 if old_runner is not _sentinel:
35 tcr.GLOBAL_RUN_CONTEXT.runner = old_runner
36 tcr.GLOBAL_RUN_CONTEXT.task = old_task
37
38
22 class KillEmbedded(Exception):pass
39 class KillEmbedded(Exception):pass
23
40
24 # kept for backward compatibility as IPython 6 was released with
41 # kept for backward compatibility as IPython 6 was released with
25 # the typo. See https://github.com/ipython/ipython/pull/10706
42 # the typo. See https://github.com/ipython/ipython/pull/10706
26 KillEmbeded = KillEmbedded
43 KillEmbeded = KillEmbedded
27
44
28 # This is an additional magic that is exposed in embedded shells.
45 # This is an additional magic that is exposed in embedded shells.
29 @magics_class
46 @magics_class
30 class EmbeddedMagics(Magics):
47 class EmbeddedMagics(Magics):
31
48
32 @line_magic
49 @line_magic
33 @magic_arguments.magic_arguments()
50 @magic_arguments.magic_arguments()
34 @magic_arguments.argument('-i', '--instance', action='store_true',
51 @magic_arguments.argument('-i', '--instance', action='store_true',
35 help='Kill instance instead of call location')
52 help='Kill instance instead of call location')
36 @magic_arguments.argument('-x', '--exit', action='store_true',
53 @magic_arguments.argument('-x', '--exit', action='store_true',
37 help='Also exit the current session')
54 help='Also exit the current session')
38 @magic_arguments.argument('-y', '--yes', action='store_true',
55 @magic_arguments.argument('-y', '--yes', action='store_true',
39 help='Do not ask confirmation')
56 help='Do not ask confirmation')
40 def kill_embedded(self, parameter_s=''):
57 def kill_embedded(self, parameter_s=''):
41 """%kill_embedded : deactivate for good the current embedded IPython
58 """%kill_embedded : deactivate for good the current embedded IPython
42
59
43 This function (after asking for confirmation) sets an internal flag so
60 This function (after asking for confirmation) sets an internal flag so
44 that an embedded IPython will never activate again for the given call
61 that an embedded IPython will never activate again for the given call
45 location. This is useful to permanently disable a shell that is being
62 location. This is useful to permanently disable a shell that is being
46 called inside a loop: once you've figured out what you needed from it,
63 called inside a loop: once you've figured out what you needed from it,
47 you may then kill it and the program will then continue to run without
64 you may then kill it and the program will then continue to run without
48 the interactive shell interfering again.
65 the interactive shell interfering again.
49
66
50
67
51 Kill Instance Option:
68 Kill Instance Option:
52
69
53 If for some reasons you need to kill the location where the instance
70 If for some reasons you need to kill the location where the instance
54 is created and not called, for example if you create a single
71 is created and not called, for example if you create a single
55 instance in one place and debug in many locations, you can use the
72 instance in one place and debug in many locations, you can use the
56 ``--instance`` option to kill this specific instance. Like for the
73 ``--instance`` option to kill this specific instance. Like for the
57 ``call location`` killing an "instance" should work even if it is
74 ``call location`` killing an "instance" should work even if it is
58 recreated within a loop.
75 recreated within a loop.
59
76
60 .. note::
77 .. note::
61
78
62 This was the default behavior before IPython 5.2
79 This was the default behavior before IPython 5.2
63
80
64 """
81 """
65
82
66 args = magic_arguments.parse_argstring(self.kill_embedded, parameter_s)
83 args = magic_arguments.parse_argstring(self.kill_embedded, parameter_s)
67 print(args)
84 print(args)
68 if args.instance:
85 if args.instance:
69 # let no ask
86 # let no ask
70 if not args.yes:
87 if not args.yes:
71 kill = ask_yes_no(
88 kill = ask_yes_no(
72 "Are you sure you want to kill this embedded instance? [y/N] ", 'n')
89 "Are you sure you want to kill this embedded instance? [y/N] ", 'n')
73 else:
90 else:
74 kill = True
91 kill = True
75 if kill:
92 if kill:
76 self.shell._disable_init_location()
93 self.shell._disable_init_location()
77 print("This embedded IPython instance will not reactivate anymore "
94 print("This embedded IPython instance will not reactivate anymore "
78 "once you exit.")
95 "once you exit.")
79 else:
96 else:
80 if not args.yes:
97 if not args.yes:
81 kill = ask_yes_no(
98 kill = ask_yes_no(
82 "Are you sure you want to kill this embedded call_location? [y/N] ", 'n')
99 "Are you sure you want to kill this embedded call_location? [y/N] ", 'n')
83 else:
100 else:
84 kill = True
101 kill = True
85 if kill:
102 if kill:
86 self.shell.embedded_active = False
103 self.shell.embedded_active = False
87 print("This embedded IPython call location will not reactivate anymore "
104 print("This embedded IPython call location will not reactivate anymore "
88 "once you exit.")
105 "once you exit.")
89
106
90 if args.exit:
107 if args.exit:
91 # Ask-exit does not really ask, it just set internals flags to exit
108 # Ask-exit does not really ask, it just set internals flags to exit
92 # on next loop.
109 # on next loop.
93 self.shell.ask_exit()
110 self.shell.ask_exit()
94
111
95
112
96 @line_magic
113 @line_magic
97 def exit_raise(self, parameter_s=''):
114 def exit_raise(self, parameter_s=''):
98 """%exit_raise Make the current embedded kernel exit and raise and exception.
115 """%exit_raise Make the current embedded kernel exit and raise and exception.
99
116
100 This function sets an internal flag so that an embedded IPython will
117 This function sets an internal flag so that an embedded IPython will
101 raise a `IPython.terminal.embed.KillEmbedded` Exception on exit, and then exit the current I. This is
118 raise a `IPython.terminal.embed.KillEmbedded` Exception on exit, and then exit the current I. This is
102 useful to permanently exit a loop that create IPython embed instance.
119 useful to permanently exit a loop that create IPython embed instance.
103 """
120 """
104
121
105 self.shell.should_raise = True
122 self.shell.should_raise = True
106 self.shell.ask_exit()
123 self.shell.ask_exit()
107
124
108
125
109
126
110 class InteractiveShellEmbed(TerminalInteractiveShell):
127 class InteractiveShellEmbed(TerminalInteractiveShell):
111
128
112 dummy_mode = Bool(False)
129 dummy_mode = Bool(False)
113 exit_msg = Unicode('')
130 exit_msg = Unicode('')
114 embedded = CBool(True)
131 embedded = CBool(True)
115 should_raise = CBool(False)
132 should_raise = CBool(False)
116 # Like the base class display_banner is not configurable, but here it
133 # Like the base class display_banner is not configurable, but here it
117 # is True by default.
134 # is True by default.
118 display_banner = CBool(True)
135 display_banner = CBool(True)
119 exit_msg = Unicode()
136 exit_msg = Unicode()
120
137
121 # When embedding, by default we don't change the terminal title
138 # When embedding, by default we don't change the terminal title
122 term_title = Bool(False,
139 term_title = Bool(False,
123 help="Automatically set the terminal title"
140 help="Automatically set the terminal title"
124 ).tag(config=True)
141 ).tag(config=True)
125
142
126 _inactive_locations = set()
143 _inactive_locations = set()
127
144
128 @property
145 @property
129 def embedded_active(self):
146 def embedded_active(self):
130 return (self._call_location_id not in InteractiveShellEmbed._inactive_locations)\
147 return (self._call_location_id not in InteractiveShellEmbed._inactive_locations)\
131 and (self._init_location_id not in InteractiveShellEmbed._inactive_locations)
148 and (self._init_location_id not in InteractiveShellEmbed._inactive_locations)
132
149
133 def _disable_init_location(self):
150 def _disable_init_location(self):
134 """Disable the current Instance creation location"""
151 """Disable the current Instance creation location"""
135 InteractiveShellEmbed._inactive_locations.add(self._init_location_id)
152 InteractiveShellEmbed._inactive_locations.add(self._init_location_id)
136
153
137 @embedded_active.setter
154 @embedded_active.setter
138 def embedded_active(self, value):
155 def embedded_active(self, value):
139 if value:
156 if value:
140 InteractiveShellEmbed._inactive_locations.discard(
157 InteractiveShellEmbed._inactive_locations.discard(
141 self._call_location_id)
158 self._call_location_id)
142 InteractiveShellEmbed._inactive_locations.discard(
159 InteractiveShellEmbed._inactive_locations.discard(
143 self._init_location_id)
160 self._init_location_id)
144 else:
161 else:
145 InteractiveShellEmbed._inactive_locations.add(
162 InteractiveShellEmbed._inactive_locations.add(
146 self._call_location_id)
163 self._call_location_id)
147
164
148 def __init__(self, **kw):
165 def __init__(self, **kw):
149 if kw.get('user_global_ns', None) is not None:
166 if kw.get('user_global_ns', None) is not None:
150 raise DeprecationWarning(
167 raise DeprecationWarning(
151 "Key word argument `user_global_ns` has been replaced by `user_module` since IPython 4.0.")
168 "Key word argument `user_global_ns` has been replaced by `user_module` since IPython 4.0.")
152
169
153 clid = kw.pop('_init_location_id', None)
170 clid = kw.pop('_init_location_id', None)
154 if not clid:
171 if not clid:
155 frame = sys._getframe(1)
172 frame = sys._getframe(1)
156 clid = '%s:%s' % (frame.f_code.co_filename, frame.f_lineno)
173 clid = '%s:%s' % (frame.f_code.co_filename, frame.f_lineno)
157 self._init_location_id = clid
174 self._init_location_id = clid
158
175
159 super(InteractiveShellEmbed,self).__init__(**kw)
176 super(InteractiveShellEmbed,self).__init__(**kw)
160
177
161 # don't use the ipython crash handler so that user exceptions aren't
178 # don't use the ipython crash handler so that user exceptions aren't
162 # trapped
179 # trapped
163 sys.excepthook = ultratb.FormattedTB(color_scheme=self.colors,
180 sys.excepthook = ultratb.FormattedTB(color_scheme=self.colors,
164 mode=self.xmode,
181 mode=self.xmode,
165 call_pdb=self.pdb)
182 call_pdb=self.pdb)
166
183
167 def init_sys_modules(self):
184 def init_sys_modules(self):
168 """
185 """
169 Explicitly overwrite :mod:`IPython.core.interactiveshell` to do nothing.
186 Explicitly overwrite :mod:`IPython.core.interactiveshell` to do nothing.
170 """
187 """
171 pass
188 pass
172
189
173 def init_magics(self):
190 def init_magics(self):
174 super(InteractiveShellEmbed, self).init_magics()
191 super(InteractiveShellEmbed, self).init_magics()
175 self.register_magics(EmbeddedMagics)
192 self.register_magics(EmbeddedMagics)
176
193
177 def __call__(self, header='', local_ns=None, module=None, dummy=None,
194 def __call__(self, header='', local_ns=None, module=None, dummy=None,
178 stack_depth=1, global_ns=None, compile_flags=None, **kw):
195 stack_depth=1, global_ns=None, compile_flags=None, **kw):
179 """Activate the interactive interpreter.
196 """Activate the interactive interpreter.
180
197
181 __call__(self,header='',local_ns=None,module=None,dummy=None) -> Start
198 __call__(self,header='',local_ns=None,module=None,dummy=None) -> Start
182 the interpreter shell with the given local and global namespaces, and
199 the interpreter shell with the given local and global namespaces, and
183 optionally print a header string at startup.
200 optionally print a header string at startup.
184
201
185 The shell can be globally activated/deactivated using the
202 The shell can be globally activated/deactivated using the
186 dummy_mode attribute. This allows you to turn off a shell used
203 dummy_mode attribute. This allows you to turn off a shell used
187 for debugging globally.
204 for debugging globally.
188
205
189 However, *each* time you call the shell you can override the current
206 However, *each* time you call the shell you can override the current
190 state of dummy_mode with the optional keyword parameter 'dummy'. For
207 state of dummy_mode with the optional keyword parameter 'dummy'. For
191 example, if you set dummy mode on with IPShell.dummy_mode = True, you
208 example, if you set dummy mode on with IPShell.dummy_mode = True, you
192 can still have a specific call work by making it as IPShell(dummy=False).
209 can still have a specific call work by making it as IPShell(dummy=False).
193 """
210 """
194
211
195 # we are called, set the underlying interactiveshell not to exit.
212 # we are called, set the underlying interactiveshell not to exit.
196 self.keep_running = True
213 self.keep_running = True
197
214
198 # If the user has turned it off, go away
215 # If the user has turned it off, go away
199 clid = kw.pop('_call_location_id', None)
216 clid = kw.pop('_call_location_id', None)
200 if not clid:
217 if not clid:
201 frame = sys._getframe(1)
218 frame = sys._getframe(1)
202 clid = '%s:%s' % (frame.f_code.co_filename, frame.f_lineno)
219 clid = '%s:%s' % (frame.f_code.co_filename, frame.f_lineno)
203 self._call_location_id = clid
220 self._call_location_id = clid
204
221
205 if not self.embedded_active:
222 if not self.embedded_active:
206 return
223 return
207
224
208 # Normal exits from interactive mode set this flag, so the shell can't
225 # Normal exits from interactive mode set this flag, so the shell can't
209 # re-enter (it checks this variable at the start of interactive mode).
226 # re-enter (it checks this variable at the start of interactive mode).
210 self.exit_now = False
227 self.exit_now = False
211
228
212 # Allow the dummy parameter to override the global __dummy_mode
229 # Allow the dummy parameter to override the global __dummy_mode
213 if dummy or (dummy != 0 and self.dummy_mode):
230 if dummy or (dummy != 0 and self.dummy_mode):
214 return
231 return
215
232
216 # self.banner is auto computed
233 # self.banner is auto computed
217 if header:
234 if header:
218 self.old_banner2 = self.banner2
235 self.old_banner2 = self.banner2
219 self.banner2 = self.banner2 + '\n' + header + '\n'
236 self.banner2 = self.banner2 + '\n' + header + '\n'
220 else:
237 else:
221 self.old_banner2 = ''
238 self.old_banner2 = ''
222
239
223 if self.display_banner:
240 if self.display_banner:
224 self.show_banner()
241 self.show_banner()
225
242
226 # Call the embedding code with a stack depth of 1 so it can skip over
243 # Call the embedding code with a stack depth of 1 so it can skip over
227 # our call and get the original caller's namespaces.
244 # our call and get the original caller's namespaces.
228 self.mainloop(local_ns, module, stack_depth=stack_depth,
245 self.mainloop(local_ns, module, stack_depth=stack_depth,
229 global_ns=global_ns, compile_flags=compile_flags)
246 global_ns=global_ns, compile_flags=compile_flags)
230
247
231 self.banner2 = self.old_banner2
248 self.banner2 = self.old_banner2
232
249
233 if self.exit_msg is not None:
250 if self.exit_msg is not None:
234 print(self.exit_msg)
251 print(self.exit_msg)
235
252
236 if self.should_raise:
253 if self.should_raise:
237 raise KillEmbedded('Embedded IPython raising error, as user requested.')
254 raise KillEmbedded('Embedded IPython raising error, as user requested.')
238
255
239
256
240 def mainloop(self, local_ns=None, module=None, stack_depth=0,
257 def mainloop(self, local_ns=None, module=None, stack_depth=0,
241 display_banner=None, global_ns=None, compile_flags=None):
258 display_banner=None, global_ns=None, compile_flags=None):
242 """Embeds IPython into a running python program.
259 """Embeds IPython into a running python program.
243
260
244 Parameters
261 Parameters
245 ----------
262 ----------
246
263
247 local_ns, module
264 local_ns, module
248 Working local namespace (a dict) and module (a module or similar
265 Working local namespace (a dict) and module (a module or similar
249 object). If given as None, they are automatically taken from the scope
266 object). If given as None, they are automatically taken from the scope
250 where the shell was called, so that program variables become visible.
267 where the shell was called, so that program variables become visible.
251
268
252 stack_depth : int
269 stack_depth : int
253 How many levels in the stack to go to looking for namespaces (when
270 How many levels in the stack to go to looking for namespaces (when
254 local_ns or module is None). This allows an intermediate caller to
271 local_ns or module is None). This allows an intermediate caller to
255 make sure that this function gets the namespace from the intended
272 make sure that this function gets the namespace from the intended
256 level in the stack. By default (0) it will get its locals and globals
273 level in the stack. By default (0) it will get its locals and globals
257 from the immediate caller.
274 from the immediate caller.
258
275
259 compile_flags
276 compile_flags
260 A bit field identifying the __future__ features
277 A bit field identifying the __future__ features
261 that are enabled, as passed to the builtin :func:`compile` function.
278 that are enabled, as passed to the builtin :func:`compile` function.
262 If given as None, they are automatically taken from the scope where
279 If given as None, they are automatically taken from the scope where
263 the shell was called.
280 the shell was called.
264
281
265 """
282 """
266
283
267 if (global_ns is not None) and (module is None):
284 if (global_ns is not None) and (module is None):
268 raise DeprecationWarning("'global_ns' keyword argument is deprecated, and has been removed in IPython 5.0 use `module` keyword argument instead.")
285 raise DeprecationWarning("'global_ns' keyword argument is deprecated, and has been removed in IPython 5.0 use `module` keyword argument instead.")
269
286
270 if (display_banner is not None):
287 if (display_banner is not None):
271 warnings.warn("The display_banner parameter is deprecated since IPython 4.0", DeprecationWarning)
288 warnings.warn("The display_banner parameter is deprecated since IPython 4.0", DeprecationWarning)
272
289
273 # Get locals and globals from caller
290 # Get locals and globals from caller
274 if ((local_ns is None or module is None or compile_flags is None)
291 if ((local_ns is None or module is None or compile_flags is None)
275 and self.default_user_namespaces):
292 and self.default_user_namespaces):
276 call_frame = sys._getframe(stack_depth).f_back
293 call_frame = sys._getframe(stack_depth).f_back
277
294
278 if local_ns is None:
295 if local_ns is None:
279 local_ns = call_frame.f_locals
296 local_ns = call_frame.f_locals
280 if module is None:
297 if module is None:
281 global_ns = call_frame.f_globals
298 global_ns = call_frame.f_globals
282 try:
299 try:
283 module = sys.modules[global_ns['__name__']]
300 module = sys.modules[global_ns['__name__']]
284 except KeyError:
301 except KeyError:
285 warnings.warn("Failed to get module %s" % \
302 warnings.warn("Failed to get module %s" % \
286 global_ns.get('__name__', 'unknown module')
303 global_ns.get('__name__', 'unknown module')
287 )
304 )
288 module = DummyMod()
305 module = DummyMod()
289 module.__dict__ = global_ns
306 module.__dict__ = global_ns
290 if compile_flags is None:
307 if compile_flags is None:
291 compile_flags = (call_frame.f_code.co_flags &
308 compile_flags = (call_frame.f_code.co_flags &
292 compilerop.PyCF_MASK)
309 compilerop.PyCF_MASK)
293
310
294 # Save original namespace and module so we can restore them after
311 # Save original namespace and module so we can restore them after
295 # embedding; otherwise the shell doesn't shut down correctly.
312 # embedding; otherwise the shell doesn't shut down correctly.
296 orig_user_module = self.user_module
313 orig_user_module = self.user_module
297 orig_user_ns = self.user_ns
314 orig_user_ns = self.user_ns
298 orig_compile_flags = self.compile.flags
315 orig_compile_flags = self.compile.flags
299
316
300 # Update namespaces and fire up interpreter
317 # Update namespaces and fire up interpreter
301
318
302 # The global one is easy, we can just throw it in
319 # The global one is easy, we can just throw it in
303 if module is not None:
320 if module is not None:
304 self.user_module = module
321 self.user_module = module
305
322
306 # But the user/local one is tricky: ipython needs it to store internal
323 # But the user/local one is tricky: ipython needs it to store internal
307 # data, but we also need the locals. We'll throw our hidden variables
324 # data, but we also need the locals. We'll throw our hidden variables
308 # like _ih and get_ipython() into the local namespace, but delete them
325 # like _ih and get_ipython() into the local namespace, but delete them
309 # later.
326 # later.
310 if local_ns is not None:
327 if local_ns is not None:
311 reentrant_local_ns = {k: v for (k, v) in local_ns.items() if k not in self.user_ns_hidden.keys()}
328 reentrant_local_ns = {k: v for (k, v) in local_ns.items() if k not in self.user_ns_hidden.keys()}
312 self.user_ns = reentrant_local_ns
329 self.user_ns = reentrant_local_ns
313 self.init_user_ns()
330 self.init_user_ns()
314
331
315 # Compiler flags
332 # Compiler flags
316 if compile_flags is not None:
333 if compile_flags is not None:
317 self.compile.flags = compile_flags
334 self.compile.flags = compile_flags
318
335
319 # make sure the tab-completer has the correct frame information, so it
336 # make sure the tab-completer has the correct frame information, so it
320 # actually completes using the frame's locals/globals
337 # actually completes using the frame's locals/globals
321 self.set_completer_frame()
338 self.set_completer_frame()
322
339
323 with self.builtin_trap, self.display_trap:
340 with self.builtin_trap, self.display_trap:
324 self.interact()
341 self.interact()
325
342
326 # now, purge out the local namespace of IPython's hidden variables.
343 # now, purge out the local namespace of IPython's hidden variables.
327 if local_ns is not None:
344 if local_ns is not None:
328 local_ns.update({k: v for (k, v) in self.user_ns.items() if k not in self.user_ns_hidden.keys()})
345 local_ns.update({k: v for (k, v) in self.user_ns.items() if k not in self.user_ns_hidden.keys()})
329
346
330
347
331 # Restore original namespace so shell can shut down when we exit.
348 # Restore original namespace so shell can shut down when we exit.
332 self.user_module = orig_user_module
349 self.user_module = orig_user_module
333 self.user_ns = orig_user_ns
350 self.user_ns = orig_user_ns
334 self.compile.flags = orig_compile_flags
351 self.compile.flags = orig_compile_flags
335
352
336
353
337 def embed(**kwargs):
354 def embed(**kwargs):
338 """Call this to embed IPython at the current point in your program.
355 """Call this to embed IPython at the current point in your program.
339
356
340 The first invocation of this will create an :class:`InteractiveShellEmbed`
357 The first invocation of this will create an :class:`InteractiveShellEmbed`
341 instance and then call it. Consecutive calls just call the already
358 instance and then call it. Consecutive calls just call the already
342 created instance.
359 created instance.
343
360
344 If you don't want the kernel to initialize the namespace
361 If you don't want the kernel to initialize the namespace
345 from the scope of the surrounding function,
362 from the scope of the surrounding function,
346 and/or you want to load full IPython configuration,
363 and/or you want to load full IPython configuration,
347 you probably want `IPython.start_ipython()` instead.
364 you probably want `IPython.start_ipython()` instead.
348
365
349 Here is a simple example::
366 Here is a simple example::
350
367
351 from IPython import embed
368 from IPython import embed
352 a = 10
369 a = 10
353 b = 20
370 b = 20
354 embed(header='First time')
371 embed(header='First time')
355 c = 30
372 c = 30
356 d = 40
373 d = 40
357 embed()
374 embed()
358
375
359 Full customization can be done by passing a :class:`Config` in as the
376 Full customization can be done by passing a :class:`Config` in as the
360 config argument.
377 config argument.
361 """
378 """
362 config = kwargs.get('config')
379 config = kwargs.get('config')
363 header = kwargs.pop('header', u'')
380 header = kwargs.pop('header', u'')
364 compile_flags = kwargs.pop('compile_flags', None)
381 compile_flags = kwargs.pop('compile_flags', None)
365 if config is None:
382 if config is None:
366 config = load_default_config()
383 config = load_default_config()
367 config.InteractiveShellEmbed = config.TerminalInteractiveShell
384 config.InteractiveShellEmbed = config.TerminalInteractiveShell
368 kwargs['config'] = config
385 kwargs['config'] = config
386 using = kwargs.get('using', 'trio')
387 if using :
388 kwargs['config'].update({'TerminalInteractiveShell':{'loop_runner':using, 'colors':'NoColor'}})
369 #save ps1/ps2 if defined
389 #save ps1/ps2 if defined
370 ps1 = None
390 ps1 = None
371 ps2 = None
391 ps2 = None
372 try:
392 try:
373 ps1 = sys.ps1
393 ps1 = sys.ps1
374 ps2 = sys.ps2
394 ps2 = sys.ps2
375 except AttributeError:
395 except AttributeError:
376 pass
396 pass
377 #save previous instance
397 #save previous instance
378 saved_shell_instance = InteractiveShell._instance
398 saved_shell_instance = InteractiveShell._instance
379 if saved_shell_instance is not None:
399 if saved_shell_instance is not None:
380 cls = type(saved_shell_instance)
400 cls = type(saved_shell_instance)
381 cls.clear_instance()
401 cls.clear_instance()
382 frame = sys._getframe(1)
402 frame = sys._getframe(1)
383 shell = InteractiveShellEmbed.instance(_init_location_id='%s:%s' % (
403 with new_context():
384 frame.f_code.co_filename, frame.f_lineno), **kwargs)
404 shell = InteractiveShellEmbed.instance(_init_location_id='%s:%s' % (
385 shell(header=header, stack_depth=2, compile_flags=compile_flags,
405 frame.f_code.co_filename, frame.f_lineno), **kwargs)
386 _call_location_id='%s:%s' % (frame.f_code.co_filename, frame.f_lineno))
406 shell(header=header, stack_depth=2, compile_flags=compile_flags,
387 InteractiveShellEmbed.clear_instance()
407 _call_location_id='%s:%s' % (frame.f_code.co_filename, frame.f_lineno))
408 InteractiveShellEmbed.clear_instance()
388 #restore previous instance
409 #restore previous instance
389 if saved_shell_instance is not None:
410 if saved_shell_instance is not None:
390 cls = type(saved_shell_instance)
411 cls = type(saved_shell_instance)
391 cls.clear_instance()
412 cls.clear_instance()
392 for subclass in cls._walk_mro():
413 for subclass in cls._walk_mro():
393 subclass._instance = saved_shell_instance
414 subclass._instance = saved_shell_instance
394 if ps1 is not None:
415 if ps1 is not None:
395 sys.ps1 = ps1
416 sys.ps1 = ps1
396 sys.ps2 = ps2
417 sys.ps2 = ps2
@@ -1,132 +1,135 b''
1 """Test embedding of IPython"""
1 """Test embedding of IPython"""
2
2
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (C) 2013 The IPython Development Team
4 # Copyright (C) 2013 The IPython Development Team
5 #
5 #
6 # Distributed under the terms of the BSD License. The full license is in
6 # Distributed under the terms of the BSD License. The full license is in
7 # the file COPYING, distributed as part of this software.
7 # the file COPYING, distributed as part of this software.
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Imports
11 # Imports
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 import os
14 import os
15 import subprocess
15 import subprocess
16 import sys
16 import sys
17 import nose.tools as nt
17 import nose.tools as nt
18 from IPython.utils.tempdir import NamedFileInTemporaryDirectory
18 from IPython.utils.tempdir import NamedFileInTemporaryDirectory
19 from IPython.testing.decorators import skip_win32
19 from IPython.testing.decorators import skip_win32
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Tests
22 # Tests
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25
25
26 _sample_embed = b"""
26 _sample_embed = b"""
27 import IPython
27 import IPython
28
28
29 a = 3
29 a = 3
30 b = 14
30 b = 14
31 print(a, '.', b)
31 print(a, '.', b)
32
32
33 IPython.embed()
33 IPython.embed()
34
34
35 print('bye!')
35 print('bye!')
36 """
36 """
37
37
38 _exit = b"exit\r"
38 _exit = b"exit\r"
39
39
40 def test_ipython_embed():
40 def test_ipython_embed():
41 """test that `IPython.embed()` works"""
41 """test that `IPython.embed()` works"""
42 with NamedFileInTemporaryDirectory('file_with_embed.py') as f:
42 with NamedFileInTemporaryDirectory('file_with_embed.py') as f:
43 f.write(_sample_embed)
43 f.write(_sample_embed)
44 f.flush()
44 f.flush()
45 f.close() # otherwise msft won't be able to read the file
45 f.close() # otherwise msft won't be able to read the file
46
46
47 # run `python file_with_embed.py`
47 # run `python file_with_embed.py`
48 cmd = [sys.executable, f.name]
48 cmd = [sys.executable, f.name]
49 env = os.environ.copy()
49 env = os.environ.copy()
50 env['IPY_TEST_SIMPLE_PROMPT'] = '1'
50 env['IPY_TEST_SIMPLE_PROMPT'] = '1'
51
51
52 p = subprocess.Popen(cmd, env=env, stdin=subprocess.PIPE,
52 p = subprocess.Popen(cmd, env=env, stdin=subprocess.PIPE,
53 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
53 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
54 out, err = p.communicate(_exit)
54 out, err = p.communicate(_exit)
55 std = out.decode('UTF-8')
55 std = out.decode('UTF-8')
56
56
57 nt.assert_equal(p.returncode, 0)
57 nt.assert_equal(p.returncode, 0)
58 nt.assert_in('3 . 14', std)
58 nt.assert_in('3 . 14', std)
59 if os.name != 'nt':
59 if os.name != 'nt':
60 # TODO: Fix up our different stdout references, see issue gh-14
60 # TODO: Fix up our different stdout references, see issue gh-14
61 nt.assert_in('IPython', std)
61 nt.assert_in('IPython', std)
62 nt.assert_in('bye!', std)
62 nt.assert_in('bye!', std)
63
63
64 @skip_win32
64 @skip_win32
65 def test_nest_embed():
65 def test_nest_embed():
66 """test that `IPython.embed()` is nestable"""
66 """test that `IPython.embed()` is nestable"""
67 import pexpect
67 import pexpect
68 ipy_prompt = r']:' #ansi color codes give problems matching beyond this
68 ipy_prompt = r']:' #ansi color codes give problems matching beyond this
69 env = os.environ.copy()
69 env = os.environ.copy()
70 env['IPY_TEST_SIMPLE_PROMPT'] = '1'
70 env['IPY_TEST_SIMPLE_PROMPT'] = '1'
71
71
72
72
73 child = pexpect.spawn(sys.executable, ['-m', 'IPython', '--colors=nocolor'],
73 child = pexpect.spawn(sys.executable, ['-m', 'IPython', '--colors=nocolor'],
74 env=env)
74 env=env)
75 child.timeout = 5
75 child.expect(ipy_prompt)
76 child.expect(ipy_prompt)
76 child.sendline("import IPython")
77 child.sendline("import IPython")
77 child.expect(ipy_prompt)
78 child.expect(ipy_prompt)
78 child.sendline("ip0 = get_ipython()")
79 child.sendline("ip0 = get_ipython()")
79 #enter first nested embed
80 #enter first nested embed
80 child.sendline("IPython.embed()")
81 child.sendline("IPython.embed()")
81 #skip the banner until we get to a prompt
82 #skip the banner until we get to a prompt
82 try:
83 try:
83 prompted = -1
84 prompted = -1
84 while prompted != 0:
85 while prompted != 0:
85 prompted = child.expect([ipy_prompt, '\r\n'])
86 prompted = child.expect([ipy_prompt, '\r\n'])
86 except pexpect.TIMEOUT as e:
87 except pexpect.TIMEOUT as e:
87 print(e)
88 print(e)
88 #child.interact()
89 #child.interact()
89 child.sendline("embed1 = get_ipython()"); child.expect(ipy_prompt)
90 child.sendline("embed1 = get_ipython()")
91 child.expect(ipy_prompt)
90 child.sendline("print('true' if embed1 is not ip0 else 'false')")
92 child.sendline("print('true' if embed1 is not ip0 else 'false')")
91 assert(child.expect(['true\r\n', 'false\r\n']) == 0)
93 assert(child.expect(['true\r\n', 'false\r\n']) == 0)
92 child.expect(ipy_prompt)
94 child.expect(ipy_prompt)
93 child.sendline("print('true' if IPython.get_ipython() is embed1 else 'false')")
95 child.sendline("print('true' if IPython.get_ipython() is embed1 else 'false')")
94 assert(child.expect(['true\r\n', 'false\r\n']) == 0)
96 assert(child.expect(['true\r\n', 'false\r\n']) == 0)
95 child.expect(ipy_prompt)
97 child.expect(ipy_prompt)
96 #enter second nested embed
98 #enter second nested embed
97 child.sendline("IPython.embed()")
99 child.sendline("IPython.embed()")
98 #skip the banner until we get to a prompt
100 #skip the banner until we get to a prompt
99 try:
101 try:
100 prompted = -1
102 prompted = -1
101 while prompted != 0:
103 while prompted != 0:
102 prompted = child.expect([ipy_prompt, '\r\n'])
104 prompted = child.expect([ipy_prompt, '\r\n'])
103 except pexpect.TIMEOUT as e:
105 except pexpect.TIMEOUT as e:
104 print(e)
106 print(e)
105 #child.interact()
107 #child.interact()
106 child.sendline("embed2 = get_ipython()"); child.expect(ipy_prompt)
108 child.sendline("embed2 = get_ipython()")
109 child.expect(ipy_prompt)
107 child.sendline("print('true' if embed2 is not embed1 else 'false')")
110 child.sendline("print('true' if embed2 is not embed1 else 'false')")
108 assert(child.expect(['true\r\n', 'false\r\n']) == 0)
111 assert(child.expect(['true\r\n', 'false\r\n']) == 0)
109 child.expect(ipy_prompt)
112 child.expect(ipy_prompt)
110 child.sendline("print('true' if embed2 is IPython.get_ipython() else 'false')")
113 child.sendline("print('true' if embed2 is IPython.get_ipython() else 'false')")
111 assert(child.expect(['true\r\n', 'false\r\n']) == 0)
114 assert(child.expect(['true\r\n', 'false\r\n']) == 0)
112 child.expect(ipy_prompt)
115 child.expect(ipy_prompt)
113 child.sendline('exit')
116 child.sendline('exit')
114 #back at first embed
117 #back at first embed
115 child.expect(ipy_prompt)
118 child.expect(ipy_prompt)
116 child.sendline("print('true' if get_ipython() is embed1 else 'false')")
119 child.sendline("print('true' if get_ipython() is embed1 else 'false')")
117 assert(child.expect(['true\r\n', 'false\r\n']) == 0)
120 assert(child.expect(['true\r\n', 'false\r\n']) == 0)
118 child.expect(ipy_prompt)
121 child.expect(ipy_prompt)
119 child.sendline("print('true' if IPython.get_ipython() is embed1 else 'false')")
122 child.sendline("print('true' if IPython.get_ipython() is embed1 else 'false')")
120 assert(child.expect(['true\r\n', 'false\r\n']) == 0)
123 assert(child.expect(['true\r\n', 'false\r\n']) == 0)
121 child.expect(ipy_prompt)
124 child.expect(ipy_prompt)
122 child.sendline('exit')
125 child.sendline('exit')
123 #back at launching scope
126 #back at launching scope
124 child.expect(ipy_prompt)
127 child.expect(ipy_prompt)
125 child.sendline("print('true' if get_ipython() is ip0 else 'false')")
128 child.sendline("print('true' if get_ipython() is ip0 else 'false')")
126 assert(child.expect(['true\r\n', 'false\r\n']) == 0)
129 assert(child.expect(['true\r\n', 'false\r\n']) == 0)
127 child.expect(ipy_prompt)
130 child.expect(ipy_prompt)
128 child.sendline("print('true' if IPython.get_ipython() is ip0 else 'false')")
131 child.sendline("print('true' if IPython.get_ipython() is ip0 else 'false')")
129 assert(child.expect(['true\r\n', 'false\r\n']) == 0)
132 assert(child.expect(['true\r\n', 'false\r\n']) == 0)
130 child.expect(ipy_prompt)
133 child.expect(ipy_prompt)
131 child.sendline('exit')
134 child.sendline('exit')
132 child.close()
135 child.close()
@@ -1,298 +1,299 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 #
2 #
3 # IPython documentation build configuration file.
3 # IPython documentation build configuration file.
4
4
5 # NOTE: This file has been edited manually from the auto-generated one from
5 # NOTE: This file has been edited manually from the auto-generated one from
6 # sphinx. Do NOT delete and re-generate. If any changes from sphinx are
6 # sphinx. Do NOT delete and re-generate. If any changes from sphinx are
7 # needed, generate a scratch one and merge by hand any new fields needed.
7 # needed, generate a scratch one and merge by hand any new fields needed.
8
8
9 #
9 #
10 # This file is execfile()d with the current directory set to its containing dir.
10 # This file is execfile()d with the current directory set to its containing dir.
11 #
11 #
12 # The contents of this file are pickled, so don't put values in the namespace
12 # The contents of this file are pickled, so don't put values in the namespace
13 # that aren't pickleable (module imports are okay, they're removed automatically).
13 # that aren't pickleable (module imports are okay, they're removed automatically).
14 #
14 #
15 # All configuration values have a default value; values that are commented out
15 # All configuration values have a default value; values that are commented out
16 # serve to show the default value.
16 # serve to show the default value.
17
17
18 import sys, os
18 import sys, os
19
19
20 # http://read-the-docs.readthedocs.io/en/latest/faq.html
20 # http://read-the-docs.readthedocs.io/en/latest/faq.html
21 ON_RTD = os.environ.get('READTHEDOCS', None) == 'True'
21 ON_RTD = os.environ.get('READTHEDOCS', None) == 'True'
22
22
23 if ON_RTD:
23 if ON_RTD:
24 tags.add('rtd')
24 tags.add('rtd')
25
25
26 # RTD doesn't use the Makefile, so re-run autogen_{things}.py here.
26 # RTD doesn't use the Makefile, so re-run autogen_{things}.py here.
27 for name in ('config', 'api', 'magics', 'shortcuts'):
27 for name in ('config', 'api', 'magics', 'shortcuts'):
28 fname = 'autogen_{}.py'.format(name)
28 fname = 'autogen_{}.py'.format(name)
29 fpath = os.path.abspath(os.path.join('..', fname))
29 fpath = os.path.abspath(os.path.join('..', fname))
30 with open(fpath) as f:
30 with open(fpath) as f:
31 exec(compile(f.read(), fname, 'exec'), {
31 exec(compile(f.read(), fname, 'exec'), {
32 '__file__': fpath,
32 '__file__': fpath,
33 '__name__': '__main__',
33 '__name__': '__main__',
34 })
34 })
35 else:
35 else:
36 import sphinx_rtd_theme
36 import sphinx_rtd_theme
37 html_theme = "sphinx_rtd_theme"
37 html_theme = "sphinx_rtd_theme"
38 html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
38 html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
39
39
40 # If your extensions are in another directory, add it here. If the directory
40 # If your extensions are in another directory, add it here. If the directory
41 # is relative to the documentation root, use os.path.abspath to make it
41 # is relative to the documentation root, use os.path.abspath to make it
42 # absolute, like shown here.
42 # absolute, like shown here.
43 sys.path.insert(0, os.path.abspath('../sphinxext'))
43 sys.path.insert(0, os.path.abspath('../sphinxext'))
44
44
45 # We load the ipython release info into a dict by explicit execution
45 # We load the ipython release info into a dict by explicit execution
46 iprelease = {}
46 iprelease = {}
47 exec(compile(open('../../IPython/core/release.py').read(), '../../IPython/core/release.py', 'exec'),iprelease)
47 exec(compile(open('../../IPython/core/release.py').read(), '../../IPython/core/release.py', 'exec'),iprelease)
48
48
49 # General configuration
49 # General configuration
50 # ---------------------
50 # ---------------------
51
51
52 # Add any Sphinx extension module names here, as strings. They can be extensions
52 # Add any Sphinx extension module names here, as strings. They can be extensions
53 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
53 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
54 extensions = [
54 extensions = [
55 'sphinx.ext.autodoc',
55 'sphinx.ext.autodoc',
56 'sphinx.ext.autosummary',
56 'sphinx.ext.autosummary',
57 'sphinx.ext.doctest',
57 'sphinx.ext.doctest',
58 'sphinx.ext.inheritance_diagram',
58 'sphinx.ext.inheritance_diagram',
59 'sphinx.ext.intersphinx',
59 'sphinx.ext.intersphinx',
60 'sphinx.ext.graphviz',
60 'sphinx.ext.graphviz',
61 'IPython.sphinxext.ipython_console_highlighting',
61 'IPython.sphinxext.ipython_console_highlighting',
62 'IPython.sphinxext.ipython_directive',
62 'IPython.sphinxext.ipython_directive',
63 'sphinx.ext.napoleon', # to preprocess docstrings
63 'sphinx.ext.napoleon', # to preprocess docstrings
64 'github', # for easy GitHub links
64 'github', # for easy GitHub links
65 'magics',
65 'magics',
66 'configtraits',
66 'configtraits',
67 ]
67 ]
68
68
69 if ON_RTD:
69 if ON_RTD:
70 # Remove extensions not currently supported on RTD
70 # Remove extensions not currently supported on RTD
71 extensions.remove('IPython.sphinxext.ipython_directive')
71 extensions.remove('IPython.sphinxext.ipython_directive')
72 extensions.remove('IPython.sphinxext.ipython_console_highlighting')
72 extensions.remove('IPython.sphinxext.ipython_console_highlighting')
73
73
74 # Add any paths that contain templates here, relative to this directory.
74 # Add any paths that contain templates here, relative to this directory.
75 templates_path = ['_templates']
75 templates_path = ['_templates']
76
76
77 # The suffix of source filenames.
77 # The suffix of source filenames.
78 source_suffix = '.rst'
78 source_suffix = '.rst'
79
79
80 rst_prolog = ''
80 rst_prolog = ''
81
81
82 def is_stable(extra):
82 def is_stable(extra):
83 for ext in {'dev', 'b', 'rc'}:
83 for ext in {'dev', 'b', 'rc'}:
84 if ext in extra:
84 if ext in extra:
85 return False
85 return False
86 return True
86 return True
87
87
88 if is_stable(iprelease['_version_extra']):
88 if is_stable(iprelease['_version_extra']):
89 tags.add('ipystable')
89 tags.add('ipystable')
90 else:
90 else:
91 tags.add('ipydev')
91 tags.add('ipydev')
92 rst_prolog += """
92 rst_prolog += """
93 .. warning::
93 .. warning::
94
94
95 This documentation covers a development version of IPython. The development
95 This documentation covers a development version of IPython. The development
96 version may differ significantly from the latest stable release.
96 version may differ significantly from the latest stable release.
97 """
97 """
98
98
99 rst_prolog += """
99 rst_prolog += """
100 .. important::
100 .. important::
101
101
102 This documentation covers IPython versions 6.0 and higher. Beginning with
102 This documentation covers IPython versions 6.0 and higher. Beginning with
103 version 6.0, IPython stopped supporting compatibility with Python versions
103 version 6.0, IPython stopped supporting compatibility with Python versions
104 lower than 3.3 including all versions of Python 2.7.
104 lower than 3.3 including all versions of Python 2.7.
105
105
106 If you are looking for an IPython version compatible with Python 2.7,
106 If you are looking for an IPython version compatible with Python 2.7,
107 please use the IPython 5.x LTS release and refer to its documentation (LTS
107 please use the IPython 5.x LTS release and refer to its documentation (LTS
108 is the long term support release).
108 is the long term support release).
109
109
110 """
110 """
111
111
112 # The master toctree document.
112 # The master toctree document.
113 master_doc = 'index'
113 master_doc = 'index'
114
114
115 # General substitutions.
115 # General substitutions.
116 project = 'IPython'
116 project = 'IPython'
117 copyright = 'The IPython Development Team'
117 copyright = 'The IPython Development Team'
118
118
119 # ghissue config
119 # ghissue config
120 github_project_url = "https://github.com/ipython/ipython"
120 github_project_url = "https://github.com/ipython/ipython"
121
121
122 # numpydoc config
122 # numpydoc config
123 numpydoc_show_class_members = False # Otherwise Sphinx emits thousands of warnings
123 numpydoc_show_class_members = False # Otherwise Sphinx emits thousands of warnings
124 numpydoc_class_members_toctree = False
124 numpydoc_class_members_toctree = False
125
125
126 # The default replacements for |version| and |release|, also used in various
126 # The default replacements for |version| and |release|, also used in various
127 # other places throughout the built documents.
127 # other places throughout the built documents.
128 #
128 #
129 # The full version, including alpha/beta/rc tags.
129 # The full version, including alpha/beta/rc tags.
130 release = "%s" % iprelease['version']
130 release = "%s" % iprelease['version']
131 # Just the X.Y.Z part, no '-dev'
131 # Just the X.Y.Z part, no '-dev'
132 version = iprelease['version'].split('-', 1)[0]
132 version = iprelease['version'].split('-', 1)[0]
133
133
134
134
135 # There are two options for replacing |today|: either, you set today to some
135 # There are two options for replacing |today|: either, you set today to some
136 # non-false value, then it is used:
136 # non-false value, then it is used:
137 #today = ''
137 #today = ''
138 # Else, today_fmt is used as the format for a strftime call.
138 # Else, today_fmt is used as the format for a strftime call.
139 today_fmt = '%B %d, %Y'
139 today_fmt = '%B %d, %Y'
140
140
141 # List of documents that shouldn't be included in the build.
141 # List of documents that shouldn't be included in the build.
142 #unused_docs = []
142 #unused_docs = []
143
143
144 # Exclude these glob-style patterns when looking for source files. They are
144 # Exclude these glob-style patterns when looking for source files. They are
145 # relative to the source/ directory.
145 # relative to the source/ directory.
146 exclude_patterns = ['whatsnew/pr']
146 exclude_patterns = ['whatsnew/pr/antigravity-feature.*',
147 'whatsnew/pr/incompat-switching-to-perl.*']
147
148
148
149
149 # If true, '()' will be appended to :func: etc. cross-reference text.
150 # If true, '()' will be appended to :func: etc. cross-reference text.
150 #add_function_parentheses = True
151 #add_function_parentheses = True
151
152
152 # If true, the current module name will be prepended to all description
153 # If true, the current module name will be prepended to all description
153 # unit titles (such as .. function::).
154 # unit titles (such as .. function::).
154 #add_module_names = True
155 #add_module_names = True
155
156
156 # If true, sectionauthor and moduleauthor directives will be shown in the
157 # If true, sectionauthor and moduleauthor directives will be shown in the
157 # output. They are ignored by default.
158 # output. They are ignored by default.
158 #show_authors = False
159 #show_authors = False
159
160
160 # The name of the Pygments (syntax highlighting) style to use.
161 # The name of the Pygments (syntax highlighting) style to use.
161 pygments_style = 'sphinx'
162 pygments_style = 'sphinx'
162
163
163 # Set the default role so we can use `foo` instead of ``foo``
164 # Set the default role so we can use `foo` instead of ``foo``
164 default_role = 'literal'
165 default_role = 'literal'
165
166
166 # Options for HTML output
167 # Options for HTML output
167 # -----------------------
168 # -----------------------
168
169
169 # The style sheet to use for HTML and HTML Help pages. A file of that name
170 # The style sheet to use for HTML and HTML Help pages. A file of that name
170 # must exist either in Sphinx' static/ path, or in one of the custom paths
171 # must exist either in Sphinx' static/ path, or in one of the custom paths
171 # given in html_static_path.
172 # given in html_static_path.
172 # html_style = 'default.css'
173 # html_style = 'default.css'
173
174
174
175
175 # The name for this set of Sphinx documents. If None, it defaults to
176 # The name for this set of Sphinx documents. If None, it defaults to
176 # "<project> v<release> documentation".
177 # "<project> v<release> documentation".
177 #html_title = None
178 #html_title = None
178
179
179 # The name of an image file (within the static path) to place at the top of
180 # The name of an image file (within the static path) to place at the top of
180 # the sidebar.
181 # the sidebar.
181 #html_logo = None
182 #html_logo = None
182
183
183 # Add any paths that contain custom static files (such as style sheets) here,
184 # Add any paths that contain custom static files (such as style sheets) here,
184 # relative to this directory. They are copied after the builtin static files,
185 # relative to this directory. They are copied after the builtin static files,
185 # so a file named "default.css" will overwrite the builtin "default.css".
186 # so a file named "default.css" will overwrite the builtin "default.css".
186 html_static_path = ['_static']
187 html_static_path = ['_static']
187
188
188 # Favicon needs the directory name
189 # Favicon needs the directory name
189 html_favicon = '_static/favicon.ico'
190 html_favicon = '_static/favicon.ico'
190 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
191 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
191 # using the given strftime format.
192 # using the given strftime format.
192 html_last_updated_fmt = '%b %d, %Y'
193 html_last_updated_fmt = '%b %d, %Y'
193
194
194 # If true, SmartyPants will be used to convert quotes and dashes to
195 # If true, SmartyPants will be used to convert quotes and dashes to
195 # typographically correct entities.
196 # typographically correct entities.
196 #html_use_smartypants = True
197 #html_use_smartypants = True
197
198
198 # Custom sidebar templates, maps document names to template names.
199 # Custom sidebar templates, maps document names to template names.
199 #html_sidebars = {}
200 #html_sidebars = {}
200
201
201 # Additional templates that should be rendered to pages, maps page names to
202 # Additional templates that should be rendered to pages, maps page names to
202 # template names.
203 # template names.
203 html_additional_pages = {
204 html_additional_pages = {
204 'interactive/htmlnotebook': 'notebook_redirect.html',
205 'interactive/htmlnotebook': 'notebook_redirect.html',
205 'interactive/notebook': 'notebook_redirect.html',
206 'interactive/notebook': 'notebook_redirect.html',
206 'interactive/nbconvert': 'notebook_redirect.html',
207 'interactive/nbconvert': 'notebook_redirect.html',
207 'interactive/public_server': 'notebook_redirect.html',
208 'interactive/public_server': 'notebook_redirect.html',
208 }
209 }
209
210
210 # If false, no module index is generated.
211 # If false, no module index is generated.
211 #html_use_modindex = True
212 #html_use_modindex = True
212
213
213 # If true, the reST sources are included in the HTML build as _sources/<name>.
214 # If true, the reST sources are included in the HTML build as _sources/<name>.
214 #html_copy_source = True
215 #html_copy_source = True
215
216
216 # If true, an OpenSearch description file will be output, and all pages will
217 # If true, an OpenSearch description file will be output, and all pages will
217 # contain a <link> tag referring to it. The value of this option must be the
218 # contain a <link> tag referring to it. The value of this option must be the
218 # base URL from which the finished HTML is served.
219 # base URL from which the finished HTML is served.
219 #html_use_opensearch = ''
220 #html_use_opensearch = ''
220
221
221 # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
222 # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
222 #html_file_suffix = ''
223 #html_file_suffix = ''
223
224
224 # Output file base name for HTML help builder.
225 # Output file base name for HTML help builder.
225 htmlhelp_basename = 'ipythondoc'
226 htmlhelp_basename = 'ipythondoc'
226
227
227 intersphinx_mapping = {'python': ('https://docs.python.org/3/', None),
228 intersphinx_mapping = {'python': ('https://docs.python.org/3/', None),
228 'rpy2': ('https://rpy2.readthedocs.io/en/version_2.8.x/', None),
229 'rpy2': ('https://rpy2.readthedocs.io/en/version_2.8.x/', None),
229 'traitlets': ('https://traitlets.readthedocs.io/en/latest/', None),
230 'traitlets': ('https://traitlets.readthedocs.io/en/latest/', None),
230 'jupyterclient': ('https://jupyter-client.readthedocs.io/en/latest/', None),
231 'jupyterclient': ('https://jupyter-client.readthedocs.io/en/latest/', None),
231 'ipyparallel': ('https://ipyparallel.readthedocs.io/en/latest/', None),
232 'ipyparallel': ('https://ipyparallel.readthedocs.io/en/latest/', None),
232 'jupyter': ('https://jupyter.readthedocs.io/en/latest/', None),
233 'jupyter': ('https://jupyter.readthedocs.io/en/latest/', None),
233 'jedi': ('https://jedi.readthedocs.io/en/latest/', None),
234 'jedi': ('https://jedi.readthedocs.io/en/latest/', None),
234 'traitlets': ('https://traitlets.readthedocs.io/en/latest/', None),
235 'traitlets': ('https://traitlets.readthedocs.io/en/latest/', None),
235 'ipykernel': ('https://ipykernel.readthedocs.io/en/latest/', None),
236 'ipykernel': ('https://ipykernel.readthedocs.io/en/latest/', None),
236 'prompt_toolkit' : ('https://python-prompt-toolkit.readthedocs.io/en/stable/', None),
237 'prompt_toolkit' : ('https://python-prompt-toolkit.readthedocs.io/en/stable/', None),
237 'ipywidgets': ('https://ipywidgets.readthedocs.io/en/stable/', None),
238 'ipywidgets': ('https://ipywidgets.readthedocs.io/en/stable/', None),
238 'ipyparallel': ('https://ipyparallel.readthedocs.io/en/stable/', None)
239 'ipyparallel': ('https://ipyparallel.readthedocs.io/en/stable/', None)
239 }
240 }
240
241
241 # Options for LaTeX output
242 # Options for LaTeX output
242 # ------------------------
243 # ------------------------
243
244
244 # The paper size ('letter' or 'a4').
245 # The paper size ('letter' or 'a4').
245 latex_paper_size = 'letter'
246 latex_paper_size = 'letter'
246
247
247 # The font size ('10pt', '11pt' or '12pt').
248 # The font size ('10pt', '11pt' or '12pt').
248 latex_font_size = '11pt'
249 latex_font_size = '11pt'
249
250
250 # Grouping the document tree into LaTeX files. List of tuples
251 # Grouping the document tree into LaTeX files. List of tuples
251 # (source start file, target name, title, author, document class [howto/manual]).
252 # (source start file, target name, title, author, document class [howto/manual]).
252
253
253 latex_documents = [
254 latex_documents = [
254 ('index', 'ipython.tex', 'IPython Documentation',
255 ('index', 'ipython.tex', 'IPython Documentation',
255 u"""The IPython Development Team""", 'manual', True),
256 u"""The IPython Development Team""", 'manual', True),
256 ('parallel/winhpc_index', 'winhpc_whitepaper.tex',
257 ('parallel/winhpc_index', 'winhpc_whitepaper.tex',
257 'Using IPython on Windows HPC Server 2008',
258 'Using IPython on Windows HPC Server 2008',
258 u"Brian E. Granger", 'manual', True)
259 u"Brian E. Granger", 'manual', True)
259 ]
260 ]
260
261
261 # The name of an image file (relative to this directory) to place at the top of
262 # The name of an image file (relative to this directory) to place at the top of
262 # the title page.
263 # the title page.
263 #latex_logo = None
264 #latex_logo = None
264
265
265 # For "manual" documents, if this is true, then toplevel headings are parts,
266 # For "manual" documents, if this is true, then toplevel headings are parts,
266 # not chapters.
267 # not chapters.
267 #latex_use_parts = False
268 #latex_use_parts = False
268
269
269 # Additional stuff for the LaTeX preamble.
270 # Additional stuff for the LaTeX preamble.
270 #latex_preamble = ''
271 #latex_preamble = ''
271
272
272 # Documents to append as an appendix to all manuals.
273 # Documents to append as an appendix to all manuals.
273 #latex_appendices = []
274 #latex_appendices = []
274
275
275 # If false, no module index is generated.
276 # If false, no module index is generated.
276 latex_use_modindex = True
277 latex_use_modindex = True
277
278
278
279
279 # Options for texinfo output
280 # Options for texinfo output
280 # --------------------------
281 # --------------------------
281
282
282 texinfo_documents = [
283 texinfo_documents = [
283 (master_doc, 'ipython', 'IPython Documentation',
284 (master_doc, 'ipython', 'IPython Documentation',
284 'The IPython Development Team',
285 'The IPython Development Team',
285 'IPython',
286 'IPython',
286 'IPython Documentation',
287 'IPython Documentation',
287 'Programming',
288 'Programming',
288 1),
289 1),
289 ]
290 ]
290
291
291 modindex_common_prefix = ['IPython.']
292 modindex_common_prefix = ['IPython.']
292
293
293
294
294 # Cleanup
295 # Cleanup
295 # -------
296 # -------
296 # delete release info to avoid pickling errors from sphinx
297 # delete release info to avoid pickling errors from sphinx
297
298
298 del iprelease
299 del iprelease
@@ -1,31 +1,32 b''
1 ========
1 ========
2 Tutorial
2 Tutorial
3 ========
3 ========
4
4
5 This section of IPython documentation will walk you through most of the IPython
5 This section of IPython documentation will walk you through most of the IPython
6 functionality. You do not need to have any deep knowledge of Python to read this
6 functionality. You do not need to have any deep knowledge of Python to read this
7 tutorial, though some sections might make slightly more sense if you have already
7 tutorial, though some sections might make slightly more sense if you have already
8 done some work in the classic Python REPL.
8 done some work in the classic Python REPL.
9
9
10 .. note::
10 .. note::
11
11
12 Some part of this documentation are more than a decade old so might be out
12 Some part of this documentation are more than a decade old so might be out
13 of date, we welcome any report of inaccuracy, and Pull Requests that make
13 of date, we welcome any report of inaccuracy, and Pull Requests that make
14 that up to date.
14 that up to date.
15
15
16 .. toctree::
16 .. toctree::
17 :maxdepth: 2
17 :maxdepth: 2
18 :hidden:
18 :hidden:
19
19
20 tutorial
20 tutorial
21 plotting
21 plotting
22 reference
22 reference
23 shell
23 shell
24 autoawait
24 tips
25 tips
25 python-ipython-diff
26 python-ipython-diff
26 magics
27 magics
27
28
28 .. seealso::
29 .. seealso::
29
30
30 `A Qt Console for Jupyter <https://jupyter.org/qtconsole/>`__
31 `A Qt Console for Jupyter <https://jupyter.org/qtconsole/>`__
31 `The Jupyter Notebook <http://jupyter-notebook.readthedocs.io/en/latest/>`__
32 `The Jupyter Notebook <http://jupyter-notebook.readthedocs.io/en/latest/>`__
@@ -1,21 +1,150 b''
1 =====================
1 =====================
2 Development version
2 Development version
3 =====================
3 =====================
4
4
5 This document describes in-flight development work.
5 This document describes in-flight development work.
6
6
7 .. warning::
7 .. warning::
8
8
9 Please do not edit this file by hand (doing so will likely cause merge
9 Please do not edit this file by hand (doing so will likely cause merge
10 conflicts for other Pull Requests). Instead, create a new file in the
10 conflicts for other Pull Requests). Instead, create a new file in the
11 `docs/source/whatsnew/pr` folder
11 `docs/source/whatsnew/pr` folder
12
12
13
13
14 Released .... ...., 2017
15
16
17 Need to be updated:
18
19 .. toctree::
20 :maxdepth: 2
21 :glob:
22
23 pr/*
24
25 IPython 6 feature a major improvement in the completion machinery which is now
26 capable of completing non-executed code. It is also the first version of IPython
27 to stop compatibility with Python 2, which is still supported on the bugfix only
28 5.x branch. Read below to have a non-exhaustive list of new features.
29
30 Make sure you have pip > 9.0 before upgrading.
31 You should be able to update by using:
32
33 .. code::
34
35 pip install ipython --upgrade
36
37 New completion API and Interface
38 --------------------------------
39
40 The completer Completion API has seen an overhaul, and the new completer have
41 plenty of improvement both from the end users of terminal IPython or for
42 consumers of the API.
43
44 This new API is capable of pulling completions from :any:`jedi`, thus allowing
45 type inference on non-executed code. If :any:`jedi` is installed completion like
46 the following are now becoming possible without code evaluation:
47
48 >>> data = ['Number of users', 123_456]
49 ... data[0].<tab>
50
51 That is to say, IPython is now capable of inferring that `data[0]` is a string,
52 and will suggest completions like `.capitalize`. The completion power of IPython
53 will increase with new Jedi releases, and a number of bugs and more completions
54 are already available on development version of :any:`jedi` if you are curious.
55
56 With the help of prompt toolkit, types of completions can be shown in the
57 completer interface:
58
59 .. image:: ../_images/jedi_type_inference_60.png
60 :alt: Jedi showing ability to do type inference
61 :align: center
62 :width: 400px
63 :target: ../_images/jedi_type_inference_60.png
64
65 The appearance of the completer is controlled by the
66 ``c.TerminalInteractiveShell.display_completions`` option that will show the
67 type differently depending on the value among ``'column'``, ``'multicolumn'``
68 and ``'readlinelike'``
69
70 The use of Jedi also full fill a number of request and fix a number of bugs
71 like case insensitive completion, completion after division operator: See
72 :ghpull:`10182`.
73
74 Extra patches and updates will be needed to the :mod:`ipykernel` package for
75 this feature to be available to other clients like jupyter Notebook, Lab,
76 Nteract, Hydrogen...
77
78 The use of Jedi can is barely noticeable on recent enough machines, but can be
79 feel on older ones, in cases were Jedi behavior need to be adjusted, the amount
80 of time given to Jedi to compute type inference can be adjusted with
81 ``c.IPCompleter.jedi_compute_type_timeout``, with object whose type were not
82 inferred will be shown as ``<unknown>``. Jedi can also be completely deactivated
83 by using the ``c.Completer.use_jedi=False`` option.
84
85
86 The old ``Completer.complete()`` API is waiting deprecation and should be
87 replaced replaced by ``Completer.completions()`` in a near future. Feedback on
88 the current state of the API and suggestions welcome.
89
90 Python 3 only codebase
91 ----------------------
92
93 One of the large challenges in IPython 6.0 has been the adoption of a pure
94 Python 3 code base, which lead us to great length to upstream patches in pip,
95 pypi and warehouse to make sure Python 2 system still upgrade to the latest
96 compatible Python version compatible.
97
98 We remind our Python 2 users that IPython 5 is still compatible with Python 2.7,
99 still maintained and get regular releases. Using pip 9+, upgrading IPython will
100 automatically upgrade to the latest version compatible with your system.
101
102 .. warning::
103
104 If you are on a system using an older verison of pip on Python 2, pip may
105 still install IPython 6.0 on your system, and IPython will refuse to start.
106 You can fix this by ugrading pip, and reinstalling ipython, or forcing pip to
107 install an earlier version: ``pip install 'ipython<6'``
108
109 The ability to use only Python 3 on the code base of IPython has bring a number
110 of advantage. Most of the newly written code make use of `optional function type
111 anotation <https://www.python.org/dev/peps/pep-0484/>`_ leading to clearer code
112 and better documentation.
113
114 The total size of the repository has also for a first time between releases
115 (excluding the big split for 4.0) decreased by about 1500 lines, potentially
116 quite a bit more codewide as some documents like this one are append only and
117 are about 300 lines long.
118
119 The removal as of Python2/Python3 shim layer has made the code quite clearer and
120 more idiomatic in a number of location, and much friendlier to work with and
121 understand. We hope to further embrace Python 3 capability in the next release
122 cycle and introduce more of the Python 3 only idioms (yield from, kwarg only,
123 general unpacking) in the code base of IPython, and see if we can take advantage
124 of these as well to improve user experience with better error messages and
125 hints.
126
127
128 Miscs improvements
129 ------------------
130
131
132 - The :cellmagic:`capture` magic can now capture the result of a cell (from an
133 expression on the last line), as well as printed and displayed output.
134 :ghpull:`9851`.
135
136 - Pressing Ctrl-Z in the terminal debugger now suspends IPython, as it already
137 does in the main terminal prompt.
138
139 - autoreload can now reload ``Enum``. See :ghissue:`10232` and :ghpull:`10316`
140
141 - IPython.display has gained a :any:`GeoJSON <IPython.display.GeoJSON>` object.
142 :ghpull:`10288` and :ghpull:`10253`
14
143
15 .. DO NOT EDIT THIS LINE BEFORE RELEASE. FEATURE INSERTION POINT.
144 .. DO NOT EDIT THIS LINE BEFORE RELEASE. FEATURE INSERTION POINT.
16
145
17
146
18 Backwards incompatible changes
147 Backwards incompatible changes
19 ------------------------------
148 ------------------------------
20
149
21 .. DO NOT EDIT THIS LINE BEFORE RELEASE. INCOMPAT INSERTION POINT.
150 .. DO NOT EDIT THIS LINE BEFORE RELEASE. INCOMPAT INSERTION POINT.
@@ -1,264 +1,265 b''
1 #!/usr/bin/env python3
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
5 Under Posix environments it works like a typical setup.py script.
5 Under Posix environments it works like a typical setup.py script.
6 Under Windows, the command sdist is not supported, since IPython
6 Under Windows, the command sdist is not supported, since IPython
7 requires utilities which are not available under Windows."""
7 requires utilities which are not available under Windows."""
8
8
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10 # Copyright (c) 2008-2011, IPython Development Team.
10 # Copyright (c) 2008-2011, IPython Development Team.
11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
14 #
14 #
15 # Distributed under the terms of the Modified BSD License.
15 # Distributed under the terms of the Modified BSD License.
16 #
16 #
17 # The full license is in the file COPYING.rst, distributed with this software.
17 # The full license is in the file COPYING.rst, distributed with this software.
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 from __future__ import print_function
20 from __future__ import print_function
21
21
22 import os
22 import os
23 import sys
23 import sys
24
24
25 # **Python version check**
25 # **Python version check**
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, 4):
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
33 pip_version = tuple([int(x) for x in pip.__version__.split('.')[:3]])
33 pip_version = tuple([int(x) for x in pip.__version__.split('.')[:3]])
34 if pip_version < (9, 0, 1) :
34 if pip_version < (9, 0, 1) :
35 pip_message = 'Your pip version is out of date, please install pip >= 9.0.1. '\
35 pip_message = 'Your pip version is out of date, please install pip >= 9.0.1. '\
36 'pip {} detected.'.format(pip.__version__)
36 'pip {} detected.'.format(pip.__version__)
37 else:
37 else:
38 # pip is new enough - it must be something else
38 # pip is new enough - it must be something else
39 pip_message = ''
39 pip_message = ''
40 except Exception:
40 except Exception:
41 pass
41 pass
42
42
43
43
44 error = """
44 error = """
45 IPython 7.0+ supports Python 3.4 and above.
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 Python 3.3 was supported up to IPython 6.x.
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
51 https://github.com/ipython/ipython/blob/master/README.rst
51 https://github.com/ipython/ipython/blob/master/README.rst
52
52
53 Python {py} detected.
53 Python {py} detected.
54 {pip}
54 {pip}
55 """.format(py=sys.version_info, pip=pip_message )
55 """.format(py=sys.version_info, pip=pip_message )
56
56
57 print(error, file=sys.stderr)
57 print(error, file=sys.stderr)
58 sys.exit(1)
58 sys.exit(1)
59
59
60 # At least we're on the python version we need, move on.
60 # At least we're on the python version we need, move on.
61
61
62 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
62 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
63 # update it when the contents of directories change.
63 # update it when the contents of directories change.
64 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
64 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
65
65
66 from distutils.core import setup
66 from distutils.core import setup
67
67
68 # Our own imports
68 # Our own imports
69 from setupbase import target_update
69 from setupbase import target_update
70
70
71 from setupbase import (
71 from setupbase import (
72 setup_args,
72 setup_args,
73 find_packages,
73 find_packages,
74 find_package_data,
74 find_package_data,
75 check_package_data_first,
75 check_package_data_first,
76 find_entry_points,
76 find_entry_points,
77 build_scripts_entrypt,
77 build_scripts_entrypt,
78 find_data_files,
78 find_data_files,
79 git_prebuild,
79 git_prebuild,
80 install_symlinked,
80 install_symlinked,
81 install_lib_symlink,
81 install_lib_symlink,
82 install_scripts_for_symlink,
82 install_scripts_for_symlink,
83 unsymlink,
83 unsymlink,
84 )
84 )
85
85
86 isfile = os.path.isfile
86 isfile = os.path.isfile
87 pjoin = os.path.join
87 pjoin = os.path.join
88
88
89 #-------------------------------------------------------------------------------
89 #-------------------------------------------------------------------------------
90 # Handle OS specific things
90 # Handle OS specific things
91 #-------------------------------------------------------------------------------
91 #-------------------------------------------------------------------------------
92
92
93 if os.name in ('nt','dos'):
93 if os.name in ('nt','dos'):
94 os_name = 'windows'
94 os_name = 'windows'
95 else:
95 else:
96 os_name = os.name
96 os_name = os.name
97
97
98 # Under Windows, 'sdist' has not been supported. Now that the docs build with
98 # Under Windows, 'sdist' has not been supported. Now that the docs build with
99 # Sphinx it might work, but let's not turn it on until someone confirms that it
99 # Sphinx it might work, but let's not turn it on until someone confirms that it
100 # actually works.
100 # actually works.
101 if os_name == 'windows' and 'sdist' in sys.argv:
101 if os_name == 'windows' and 'sdist' in sys.argv:
102 print('The sdist command is not available under Windows. Exiting.')
102 print('The sdist command is not available under Windows. Exiting.')
103 sys.exit(1)
103 sys.exit(1)
104
104
105
105
106 #-------------------------------------------------------------------------------
106 #-------------------------------------------------------------------------------
107 # Things related to the IPython documentation
107 # Things related to the IPython documentation
108 #-------------------------------------------------------------------------------
108 #-------------------------------------------------------------------------------
109
109
110 # update the manuals when building a source dist
110 # update the manuals when building a source dist
111 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
111 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
112
112
113 # List of things to be updated. Each entry is a triplet of args for
113 # List of things to be updated. Each entry is a triplet of args for
114 # target_update()
114 # target_update()
115 to_update = [
115 to_update = [
116 ('docs/man/ipython.1.gz',
116 ('docs/man/ipython.1.gz',
117 ['docs/man/ipython.1'],
117 ['docs/man/ipython.1'],
118 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
118 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
119 ]
119 ]
120
120
121
121
122 [ target_update(*t) for t in to_update ]
122 [ target_update(*t) for t in to_update ]
123
123
124 #---------------------------------------------------------------------------
124 #---------------------------------------------------------------------------
125 # Find all the packages, package data, and data_files
125 # Find all the packages, package data, and data_files
126 #---------------------------------------------------------------------------
126 #---------------------------------------------------------------------------
127
127
128 packages = find_packages()
128 packages = find_packages()
129 package_data = find_package_data()
129 package_data = find_package_data()
130
130
131 data_files = find_data_files()
131 data_files = find_data_files()
132
132
133 setup_args['packages'] = packages
133 setup_args['packages'] = packages
134 setup_args['package_data'] = package_data
134 setup_args['package_data'] = package_data
135 setup_args['data_files'] = data_files
135 setup_args['data_files'] = data_files
136
136
137 #---------------------------------------------------------------------------
137 #---------------------------------------------------------------------------
138 # custom distutils commands
138 # custom distutils commands
139 #---------------------------------------------------------------------------
139 #---------------------------------------------------------------------------
140 # imports here, so they are after setuptools import if there was one
140 # imports here, so they are after setuptools import if there was one
141 from distutils.command.sdist import sdist
141 from distutils.command.sdist import sdist
142
142
143 setup_args['cmdclass'] = {
143 setup_args['cmdclass'] = {
144 'build_py': \
144 'build_py': \
145 check_package_data_first(git_prebuild('IPython')),
145 check_package_data_first(git_prebuild('IPython')),
146 'sdist' : git_prebuild('IPython', sdist),
146 'sdist' : git_prebuild('IPython', sdist),
147 'symlink': install_symlinked,
147 'symlink': install_symlinked,
148 'install_lib_symlink': install_lib_symlink,
148 'install_lib_symlink': install_lib_symlink,
149 'install_scripts_sym': install_scripts_for_symlink,
149 'install_scripts_sym': install_scripts_for_symlink,
150 'unsymlink': unsymlink,
150 'unsymlink': unsymlink,
151 }
151 }
152
152
153
153
154 #---------------------------------------------------------------------------
154 #---------------------------------------------------------------------------
155 # Handle scripts, dependencies, and setuptools specific things
155 # Handle scripts, dependencies, and setuptools specific things
156 #---------------------------------------------------------------------------
156 #---------------------------------------------------------------------------
157
157
158 # For some commands, use setuptools. Note that we do NOT list install here!
158 # For some commands, use setuptools. Note that we do NOT list install here!
159 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
159 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
160 needs_setuptools = {'develop', 'release', 'bdist_egg', 'bdist_rpm',
160 needs_setuptools = {'develop', 'release', 'bdist_egg', 'bdist_rpm',
161 'bdist', 'bdist_dumb', 'bdist_wininst', 'bdist_wheel',
161 'bdist', 'bdist_dumb', 'bdist_wininst', 'bdist_wheel',
162 'egg_info', 'easy_install', 'upload', 'install_egg_info',
162 'egg_info', 'easy_install', 'upload', 'install_egg_info',
163 }
163 }
164
164
165 if len(needs_setuptools.intersection(sys.argv)) > 0:
165 if len(needs_setuptools.intersection(sys.argv)) > 0:
166 import setuptools
166 import setuptools
167
167
168 # This dict is used for passing extra arguments that are setuptools
168 # This dict is used for passing extra arguments that are setuptools
169 # specific to setup
169 # specific to setup
170 setuptools_extra_args = {}
170 setuptools_extra_args = {}
171
171
172 # setuptools requirements
172 # setuptools requirements
173
173
174 extras_require = dict(
174 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', 'numpy'],
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'],
182 notebook = ['notebook', 'ipywidgets'],
182 notebook = ['notebook', 'ipywidgets'],
183 nbconvert = ['nbconvert'],
183 nbconvert = ['nbconvert'],
184 )
184 )
185
185
186 install_requires = [
186 install_requires = [
187 'setuptools>=18.5',
187 'setuptools>=18.5',
188 'jedi>=0.10',
188 'jedi>=0.10',
189 'decorator',
189 'decorator',
190 'pickleshare',
190 'pickleshare',
191 'simplegeneric>0.8',
191 'simplegeneric>0.8',
192 'traitlets>=4.2',
192 'traitlets>=4.2',
193 'prompt_toolkit>=2.0.0,<2.1.0',
193 'prompt_toolkit>=2.0.0,<2.1.0',
194 'pygments',
194 'pygments',
195 'backcall',
195 'backcall',
196 ]
196 ]
197
197
198 # Platform-specific dependencies:
198 # Platform-specific dependencies:
199 # This is the correct way to specify these,
199 # This is the correct way to specify these,
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 ':python_version == "3.4"': ['typing'],
203 ':python_version == "3.4"': ['typing'],
204 ':python_version >= "3.5"': ['trio', 'curio'],
204 ':sys_platform != "win32"': ['pexpect'],
205 ':sys_platform != "win32"': ['pexpect'],
205 ':sys_platform == "darwin"': ['appnope'],
206 ':sys_platform == "darwin"': ['appnope'],
206 ':sys_platform == "win32"': ['colorama'],
207 ':sys_platform == "win32"': ['colorama'],
207 ':sys_platform == "win32" and python_version < "3.6"': ['win_unicode_console>=0.5'],
208 ':sys_platform == "win32" and python_version < "3.6"': ['win_unicode_console>=0.5'],
208 })
209 })
209 # FIXME: re-specify above platform dependencies for pip < 6
210 # FIXME: re-specify above platform dependencies for pip < 6
210 # These would result in non-portable bdists.
211 # These would result in non-portable bdists.
211 if not any(arg.startswith('bdist') for arg in sys.argv):
212 if not any(arg.startswith('bdist') for arg in sys.argv):
212 if sys.platform == 'darwin':
213 if sys.platform == 'darwin':
213 install_requires.extend(['appnope'])
214 install_requires.extend(['appnope'])
214
215
215 if not sys.platform.startswith('win'):
216 if not sys.platform.startswith('win'):
216 install_requires.append('pexpect')
217 install_requires.append('pexpect')
217
218
218 # workaround pypa/setuptools#147, where setuptools misspells
219 # workaround pypa/setuptools#147, where setuptools misspells
219 # platform_python_implementation as python_implementation
220 # platform_python_implementation as python_implementation
220 if 'setuptools' in sys.modules:
221 if 'setuptools' in sys.modules:
221 for key in list(extras_require):
222 for key in list(extras_require):
222 if 'platform_python_implementation' in key:
223 if 'platform_python_implementation' in key:
223 new_key = key.replace('platform_python_implementation', 'python_implementation')
224 new_key = key.replace('platform_python_implementation', 'python_implementation')
224 extras_require[new_key] = extras_require.pop(key)
225 extras_require[new_key] = extras_require.pop(key)
225
226
226 everything = set()
227 everything = set()
227 for key, deps in extras_require.items():
228 for key, deps in extras_require.items():
228 if ':' not in key:
229 if ':' not in key:
229 everything.update(deps)
230 everything.update(deps)
230 extras_require['all'] = everything
231 extras_require['all'] = everything
231
232
232 if 'setuptools' in sys.modules:
233 if 'setuptools' in sys.modules:
233 setuptools_extra_args['python_requires'] = '>=3.4'
234 setuptools_extra_args['python_requires'] = '>=3.4'
234 setuptools_extra_args['zip_safe'] = False
235 setuptools_extra_args['zip_safe'] = False
235 setuptools_extra_args['entry_points'] = {
236 setuptools_extra_args['entry_points'] = {
236 'console_scripts': find_entry_points(),
237 'console_scripts': find_entry_points(),
237 'pygments.lexers': [
238 'pygments.lexers': [
238 'ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer',
239 'ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer',
239 'ipython = IPython.lib.lexers:IPythonLexer',
240 'ipython = IPython.lib.lexers:IPythonLexer',
240 'ipython3 = IPython.lib.lexers:IPython3Lexer',
241 'ipython3 = IPython.lib.lexers:IPython3Lexer',
241 ],
242 ],
242 }
243 }
243 setup_args['extras_require'] = extras_require
244 setup_args['extras_require'] = extras_require
244 setup_args['install_requires'] = install_requires
245 setup_args['install_requires'] = install_requires
245
246
246 else:
247 else:
247 # scripts has to be a non-empty list, or install_scripts isn't called
248 # scripts has to be a non-empty list, or install_scripts isn't called
248 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
249 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
249
250
250 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
251 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
251
252
252 #---------------------------------------------------------------------------
253 #---------------------------------------------------------------------------
253 # Do the actual setup now
254 # Do the actual setup now
254 #---------------------------------------------------------------------------
255 #---------------------------------------------------------------------------
255
256
256 setup_args.update(setuptools_extra_args)
257 setup_args.update(setuptools_extra_args)
257
258
258
259
259
260
260 def main():
261 def main():
261 setup(**setup_args)
262 setup(**setup_args)
262
263
263 if __name__ == '__main__':
264 if __name__ == '__main__':
264 main()
265 main()
General Comments 0
You need to be logged in to leave comments. Login now