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