##// END OF EJS Templates
Fix a couple of warnings/errors in doc builds.
Matthias Bussonnier -
Show More
@@ -1,393 +1,392 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 class KillEmbeded(Exception):pass
22 class KillEmbeded(Exception):pass
23
23
24 # This is an additional magic that is exposed in embedded shells.
24 # This is an additional magic that is exposed in embedded shells.
25 @magics_class
25 @magics_class
26 class EmbeddedMagics(Magics):
26 class EmbeddedMagics(Magics):
27
27
28 @line_magic
28 @line_magic
29 @magic_arguments.magic_arguments()
29 @magic_arguments.magic_arguments()
30 @magic_arguments.argument('-i', '--instance', action='store_true',
30 @magic_arguments.argument('-i', '--instance', action='store_true',
31 help='Kill instance instead of call location')
31 help='Kill instance instead of call location')
32 @magic_arguments.argument('-x', '--exit', action='store_true',
32 @magic_arguments.argument('-x', '--exit', action='store_true',
33 help='Also exit the current session')
33 help='Also exit the current session')
34 @magic_arguments.argument('-y', '--yes', action='store_true',
34 @magic_arguments.argument('-y', '--yes', action='store_true',
35 help='Do not ask confirmation')
35 help='Do not ask confirmation')
36 def kill_embedded(self, parameter_s=''):
36 def kill_embedded(self, parameter_s=''):
37 """%kill_embedded : deactivate for good the current embedded IPython
37 """%kill_embedded : deactivate for good the current embedded IPython
38
38
39 This function (after asking for confirmation) sets an internal flag so
39 This function (after asking for confirmation) sets an internal flag so
40 that an embedded IPython will never activate again for the given call
40 that an embedded IPython will never activate again for the given call
41 location. This is useful to permanently disable a shell that is being
41 location. This is useful to permanently disable a shell that is being
42 called inside a loop: once you've figured out what you needed from it,
42 called inside a loop: once you've figured out what you needed from it,
43 you may then kill it and the program will then continue to run without
43 you may then kill it and the program will then continue to run without
44 the interactive shell interfering again.
44 the interactive shell interfering again.
45
45
46
46
47 Kill Instance Option
47 Kill Instance Option:
48 --------------------
48
49
49 If for some reasons you need to kill the location where the instance
50 If for some reasons you need to kill the location where the instance is
50 is created and not called, for example if you create a single
51 created and not called, for example if you create a single instance in
51 instance in one place and debug in many locations, you can use the
52 one place and debug in many locations, you can use the ``--instance``
52 ``--instance`` option to kill this specific instance. Like for the
53 option to kill this specific instance. Like for the ``call location``
53 ``call location`` killing an "instance" should work even if it is
54 killing an "instance" should work even if it is recreated within a
54 recreated within a loop.
55 loop.
56
55
57 .. note::
56 .. note::
58
57
59 This was the default behavior before IPython 5.2
58 This was the default behavior before IPython 5.2
60
59
61 """
60 """
62
61
63 args = magic_arguments.parse_argstring(self.kill_embedded, parameter_s)
62 args = magic_arguments.parse_argstring(self.kill_embedded, parameter_s)
64 print(args)
63 print(args)
65 if args.instance:
64 if args.instance:
66 # let no ask
65 # let no ask
67 if not args.yes:
66 if not args.yes:
68 kill = ask_yes_no(
67 kill = ask_yes_no(
69 "Are you sure you want to kill this embedded instance? [y/N] ", 'n')
68 "Are you sure you want to kill this embedded instance? [y/N] ", 'n')
70 else:
69 else:
71 kill = True
70 kill = True
72 if kill:
71 if kill:
73 self.shell._disable_init_location()
72 self.shell._disable_init_location()
74 print("This embedded IPython instance will not reactivate anymore "
73 print("This embedded IPython instance will not reactivate anymore "
75 "once you exit.")
74 "once you exit.")
76 else:
75 else:
77 if not args.yes:
76 if not args.yes:
78 kill = ask_yes_no(
77 kill = ask_yes_no(
79 "Are you sure you want to kill this embedded call_location? [y/N] ", 'n')
78 "Are you sure you want to kill this embedded call_location? [y/N] ", 'n')
80 else:
79 else:
81 kill = True
80 kill = True
82 if kill:
81 if kill:
83 self.shell.embedded_active = False
82 self.shell.embedded_active = False
84 print("This embedded IPython call location will not reactivate anymore "
83 print("This embedded IPython call location will not reactivate anymore "
85 "once you exit.")
84 "once you exit.")
86
85
87 if args.exit:
86 if args.exit:
88 # Ask-exit does not really ask, it just set internals flags to exit
87 # Ask-exit does not really ask, it just set internals flags to exit
89 # on next loop.
88 # on next loop.
90 self.shell.ask_exit()
89 self.shell.ask_exit()
91
90
92
91
93 @line_magic
92 @line_magic
94 def exit_raise(self, parameter_s=''):
93 def exit_raise(self, parameter_s=''):
95 """%exit_raise Make the current embedded kernel exit and raise and exception.
94 """%exit_raise Make the current embedded kernel exit and raise and exception.
96
95
97 This function sets an internal flag so that an embedded IPython will
96 This function sets an internal flag so that an embedded IPython will
98 raise a `IPython.terminal.embed.KillEmbeded` Exception on exit, and then exit the current I. This is
97 raise a `IPython.terminal.embed.KillEmbeded` Exception on exit, and then exit the current I. This is
99 useful to permanently exit a loop that create IPython embed instance.
98 useful to permanently exit a loop that create IPython embed instance.
100 """
99 """
101
100
102 self.shell.should_raise = True
101 self.shell.should_raise = True
103 self.shell.ask_exit()
102 self.shell.ask_exit()
104
103
105
104
106
105
107 class InteractiveShellEmbed(TerminalInteractiveShell):
106 class InteractiveShellEmbed(TerminalInteractiveShell):
108
107
109 dummy_mode = Bool(False)
108 dummy_mode = Bool(False)
110 exit_msg = Unicode('')
109 exit_msg = Unicode('')
111 embedded = CBool(True)
110 embedded = CBool(True)
112 should_raise = CBool(False)
111 should_raise = CBool(False)
113 # Like the base class display_banner is not configurable, but here it
112 # Like the base class display_banner is not configurable, but here it
114 # is True by default.
113 # is True by default.
115 display_banner = CBool(True)
114 display_banner = CBool(True)
116 exit_msg = Unicode()
115 exit_msg = Unicode()
117
116
118 # When embedding, by default we don't change the terminal title
117 # When embedding, by default we don't change the terminal title
119 term_title = Bool(False,
118 term_title = Bool(False,
120 help="Automatically set the terminal title"
119 help="Automatically set the terminal title"
121 ).tag(config=True)
120 ).tag(config=True)
122
121
123 _inactive_locations = set()
122 _inactive_locations = set()
124
123
125 @property
124 @property
126 def embedded_active(self):
125 def embedded_active(self):
127 return (self._call_location_id not in InteractiveShellEmbed._inactive_locations)\
126 return (self._call_location_id not in InteractiveShellEmbed._inactive_locations)\
128 and (self._init_location_id not in InteractiveShellEmbed._inactive_locations)
127 and (self._init_location_id not in InteractiveShellEmbed._inactive_locations)
129
128
130 def _disable_init_location(self):
129 def _disable_init_location(self):
131 """Disable the current Instance creation location"""
130 """Disable the current Instance creation location"""
132 InteractiveShellEmbed._inactive_locations.add(self._init_location_id)
131 InteractiveShellEmbed._inactive_locations.add(self._init_location_id)
133
132
134 @embedded_active.setter
133 @embedded_active.setter
135 def embedded_active(self, value):
134 def embedded_active(self, value):
136 if value:
135 if value:
137 InteractiveShellEmbed._inactive_locations.discard(
136 InteractiveShellEmbed._inactive_locations.discard(
138 self._call_location_id)
137 self._call_location_id)
139 InteractiveShellEmbed._inactive_locations.discard(
138 InteractiveShellEmbed._inactive_locations.discard(
140 self._init_location_id)
139 self._init_location_id)
141 else:
140 else:
142 InteractiveShellEmbed._inactive_locations.add(
141 InteractiveShellEmbed._inactive_locations.add(
143 self._call_location_id)
142 self._call_location_id)
144
143
145 def __init__(self, **kw):
144 def __init__(self, **kw):
146 if kw.get('user_global_ns', None) is not None:
145 if kw.get('user_global_ns', None) is not None:
147 raise DeprecationWarning(
146 raise DeprecationWarning(
148 "Key word argument `user_global_ns` has been replaced by `user_module` since IPython 4.0.")
147 "Key word argument `user_global_ns` has been replaced by `user_module` since IPython 4.0.")
149
148
150 clid = kw.pop('_init_location_id', None)
149 clid = kw.pop('_init_location_id', None)
151 if not clid:
150 if not clid:
152 frame = sys._getframe(1)
151 frame = sys._getframe(1)
153 clid = '%s:%s' % (frame.f_code.co_filename, frame.f_lineno)
152 clid = '%s:%s' % (frame.f_code.co_filename, frame.f_lineno)
154 self._init_location_id = clid
153 self._init_location_id = clid
155
154
156 super(InteractiveShellEmbed,self).__init__(**kw)
155 super(InteractiveShellEmbed,self).__init__(**kw)
157
156
158 # don't use the ipython crash handler so that user exceptions aren't
157 # don't use the ipython crash handler so that user exceptions aren't
159 # trapped
158 # trapped
160 sys.excepthook = ultratb.FormattedTB(color_scheme=self.colors,
159 sys.excepthook = ultratb.FormattedTB(color_scheme=self.colors,
161 mode=self.xmode,
160 mode=self.xmode,
162 call_pdb=self.pdb)
161 call_pdb=self.pdb)
163
162
164 def init_sys_modules(self):
163 def init_sys_modules(self):
165 """
164 """
166 Explicitly overwrite :mod:`IPython.core.interactiveshell` to do nothing.
165 Explicitly overwrite :mod:`IPython.core.interactiveshell` to do nothing.
167 """
166 """
168 pass
167 pass
169
168
170 def init_magics(self):
169 def init_magics(self):
171 super(InteractiveShellEmbed, self).init_magics()
170 super(InteractiveShellEmbed, self).init_magics()
172 self.register_magics(EmbeddedMagics)
171 self.register_magics(EmbeddedMagics)
173
172
174 def __call__(self, header='', local_ns=None, module=None, dummy=None,
173 def __call__(self, header='', local_ns=None, module=None, dummy=None,
175 stack_depth=1, global_ns=None, compile_flags=None, **kw):
174 stack_depth=1, global_ns=None, compile_flags=None, **kw):
176 """Activate the interactive interpreter.
175 """Activate the interactive interpreter.
177
176
178 __call__(self,header='',local_ns=None,module=None,dummy=None) -> Start
177 __call__(self,header='',local_ns=None,module=None,dummy=None) -> Start
179 the interpreter shell with the given local and global namespaces, and
178 the interpreter shell with the given local and global namespaces, and
180 optionally print a header string at startup.
179 optionally print a header string at startup.
181
180
182 The shell can be globally activated/deactivated using the
181 The shell can be globally activated/deactivated using the
183 dummy_mode attribute. This allows you to turn off a shell used
182 dummy_mode attribute. This allows you to turn off a shell used
184 for debugging globally.
183 for debugging globally.
185
184
186 However, *each* time you call the shell you can override the current
185 However, *each* time you call the shell you can override the current
187 state of dummy_mode with the optional keyword parameter 'dummy'. For
186 state of dummy_mode with the optional keyword parameter 'dummy'. For
188 example, if you set dummy mode on with IPShell.dummy_mode = True, you
187 example, if you set dummy mode on with IPShell.dummy_mode = True, you
189 can still have a specific call work by making it as IPShell(dummy=False).
188 can still have a specific call work by making it as IPShell(dummy=False).
190 """
189 """
191
190
192 # we are called, set the underlying interactiveshell not to exit.
191 # we are called, set the underlying interactiveshell not to exit.
193 self.keep_running = True
192 self.keep_running = True
194
193
195 # If the user has turned it off, go away
194 # If the user has turned it off, go away
196 clid = kw.pop('_call_location_id', None)
195 clid = kw.pop('_call_location_id', None)
197 if not clid:
196 if not clid:
198 frame = sys._getframe(1)
197 frame = sys._getframe(1)
199 clid = '%s:%s' % (frame.f_code.co_filename, frame.f_lineno)
198 clid = '%s:%s' % (frame.f_code.co_filename, frame.f_lineno)
200 self._call_location_id = clid
199 self._call_location_id = clid
201
200
202 if not self.embedded_active:
201 if not self.embedded_active:
203 return
202 return
204
203
205 # Normal exits from interactive mode set this flag, so the shell can't
204 # Normal exits from interactive mode set this flag, so the shell can't
206 # re-enter (it checks this variable at the start of interactive mode).
205 # re-enter (it checks this variable at the start of interactive mode).
207 self.exit_now = False
206 self.exit_now = False
208
207
209 # Allow the dummy parameter to override the global __dummy_mode
208 # Allow the dummy parameter to override the global __dummy_mode
210 if dummy or (dummy != 0 and self.dummy_mode):
209 if dummy or (dummy != 0 and self.dummy_mode):
211 return
210 return
212
211
213 # self.banner is auto computed
212 # self.banner is auto computed
214 if header:
213 if header:
215 self.old_banner2 = self.banner2
214 self.old_banner2 = self.banner2
216 self.banner2 = self.banner2 + '\n' + header + '\n'
215 self.banner2 = self.banner2 + '\n' + header + '\n'
217 else:
216 else:
218 self.old_banner2 = ''
217 self.old_banner2 = ''
219
218
220 if self.display_banner:
219 if self.display_banner:
221 self.show_banner()
220 self.show_banner()
222
221
223 # Call the embedding code with a stack depth of 1 so it can skip over
222 # Call the embedding code with a stack depth of 1 so it can skip over
224 # our call and get the original caller's namespaces.
223 # our call and get the original caller's namespaces.
225 self.mainloop(local_ns, module, stack_depth=stack_depth,
224 self.mainloop(local_ns, module, stack_depth=stack_depth,
226 global_ns=global_ns, compile_flags=compile_flags)
225 global_ns=global_ns, compile_flags=compile_flags)
227
226
228 self.banner2 = self.old_banner2
227 self.banner2 = self.old_banner2
229
228
230 if self.exit_msg is not None:
229 if self.exit_msg is not None:
231 print(self.exit_msg)
230 print(self.exit_msg)
232
231
233 if self.should_raise:
232 if self.should_raise:
234 raise KillEmbeded('Embedded IPython raising error, as user requested.')
233 raise KillEmbeded('Embedded IPython raising error, as user requested.')
235
234
236
235
237 def mainloop(self, local_ns=None, module=None, stack_depth=0,
236 def mainloop(self, local_ns=None, module=None, stack_depth=0,
238 display_banner=None, global_ns=None, compile_flags=None):
237 display_banner=None, global_ns=None, compile_flags=None):
239 """Embeds IPython into a running python program.
238 """Embeds IPython into a running python program.
240
239
241 Parameters
240 Parameters
242 ----------
241 ----------
243
242
244 local_ns, module
243 local_ns, module
245 Working local namespace (a dict) and module (a module or similar
244 Working local namespace (a dict) and module (a module or similar
246 object). If given as None, they are automatically taken from the scope
245 object). If given as None, they are automatically taken from the scope
247 where the shell was called, so that program variables become visible.
246 where the shell was called, so that program variables become visible.
248
247
249 stack_depth : int
248 stack_depth : int
250 How many levels in the stack to go to looking for namespaces (when
249 How many levels in the stack to go to looking for namespaces (when
251 local_ns or module is None). This allows an intermediate caller to
250 local_ns or module is None). This allows an intermediate caller to
252 make sure that this function gets the namespace from the intended
251 make sure that this function gets the namespace from the intended
253 level in the stack. By default (0) it will get its locals and globals
252 level in the stack. By default (0) it will get its locals and globals
254 from the immediate caller.
253 from the immediate caller.
255
254
256 compile_flags
255 compile_flags
257 A bit field identifying the __future__ features
256 A bit field identifying the __future__ features
258 that are enabled, as passed to the builtin :func:`compile` function.
257 that are enabled, as passed to the builtin :func:`compile` function.
259 If given as None, they are automatically taken from the scope where
258 If given as None, they are automatically taken from the scope where
260 the shell was called.
259 the shell was called.
261
260
262 """
261 """
263
262
264 if (global_ns is not None) and (module is None):
263 if (global_ns is not None) and (module is None):
265 raise DeprecationWarning("'global_ns' keyword argument is deprecated, and has been removed in IPython 5.0 use `module` keyword argument instead.")
264 raise DeprecationWarning("'global_ns' keyword argument is deprecated, and has been removed in IPython 5.0 use `module` keyword argument instead.")
266
265
267 if (display_banner is not None):
266 if (display_banner is not None):
268 warnings.warn("The display_banner parameter is deprecated since IPython 4.0", DeprecationWarning)
267 warnings.warn("The display_banner parameter is deprecated since IPython 4.0", DeprecationWarning)
269
268
270 # Get locals and globals from caller
269 # Get locals and globals from caller
271 if ((local_ns is None or module is None or compile_flags is None)
270 if ((local_ns is None or module is None or compile_flags is None)
272 and self.default_user_namespaces):
271 and self.default_user_namespaces):
273 call_frame = sys._getframe(stack_depth).f_back
272 call_frame = sys._getframe(stack_depth).f_back
274
273
275 if local_ns is None:
274 if local_ns is None:
276 local_ns = call_frame.f_locals
275 local_ns = call_frame.f_locals
277 if module is None:
276 if module is None:
278 global_ns = call_frame.f_globals
277 global_ns = call_frame.f_globals
279 try:
278 try:
280 module = sys.modules[global_ns['__name__']]
279 module = sys.modules[global_ns['__name__']]
281 except KeyError:
280 except KeyError:
282 warnings.warn("Failed to get module %s" % \
281 warnings.warn("Failed to get module %s" % \
283 global_ns.get('__name__', 'unknown module')
282 global_ns.get('__name__', 'unknown module')
284 )
283 )
285 module = DummyMod()
284 module = DummyMod()
286 module.__dict__ = global_ns
285 module.__dict__ = global_ns
287 if compile_flags is None:
286 if compile_flags is None:
288 compile_flags = (call_frame.f_code.co_flags &
287 compile_flags = (call_frame.f_code.co_flags &
289 compilerop.PyCF_MASK)
288 compilerop.PyCF_MASK)
290
289
291 # Save original namespace and module so we can restore them after
290 # Save original namespace and module so we can restore them after
292 # embedding; otherwise the shell doesn't shut down correctly.
291 # embedding; otherwise the shell doesn't shut down correctly.
293 orig_user_module = self.user_module
292 orig_user_module = self.user_module
294 orig_user_ns = self.user_ns
293 orig_user_ns = self.user_ns
295 orig_compile_flags = self.compile.flags
294 orig_compile_flags = self.compile.flags
296
295
297 # Update namespaces and fire up interpreter
296 # Update namespaces and fire up interpreter
298
297
299 # The global one is easy, we can just throw it in
298 # The global one is easy, we can just throw it in
300 if module is not None:
299 if module is not None:
301 self.user_module = module
300 self.user_module = module
302
301
303 # But the user/local one is tricky: ipython needs it to store internal
302 # But the user/local one is tricky: ipython needs it to store internal
304 # data, but we also need the locals. We'll throw our hidden variables
303 # data, but we also need the locals. We'll throw our hidden variables
305 # like _ih and get_ipython() into the local namespace, but delete them
304 # like _ih and get_ipython() into the local namespace, but delete them
306 # later.
305 # later.
307 if local_ns is not None:
306 if local_ns is not None:
308 reentrant_local_ns = {k: v for (k, v) in local_ns.items() if k not in self.user_ns_hidden.keys()}
307 reentrant_local_ns = {k: v for (k, v) in local_ns.items() if k not in self.user_ns_hidden.keys()}
309 self.user_ns = reentrant_local_ns
308 self.user_ns = reentrant_local_ns
310 self.init_user_ns()
309 self.init_user_ns()
311
310
312 # Compiler flags
311 # Compiler flags
313 if compile_flags is not None:
312 if compile_flags is not None:
314 self.compile.flags = compile_flags
313 self.compile.flags = compile_flags
315
314
316 # make sure the tab-completer has the correct frame information, so it
315 # make sure the tab-completer has the correct frame information, so it
317 # actually completes using the frame's locals/globals
316 # actually completes using the frame's locals/globals
318 self.set_completer_frame()
317 self.set_completer_frame()
319
318
320 with self.builtin_trap, self.display_trap:
319 with self.builtin_trap, self.display_trap:
321 self.interact()
320 self.interact()
322
321
323 # now, purge out the local namespace of IPython's hidden variables.
322 # now, purge out the local namespace of IPython's hidden variables.
324 if local_ns is not None:
323 if local_ns is not None:
325 local_ns.update({k: v for (k, v) in self.user_ns.items() if k not in self.user_ns_hidden.keys()})
324 local_ns.update({k: v for (k, v) in self.user_ns.items() if k not in self.user_ns_hidden.keys()})
326
325
327
326
328 # Restore original namespace so shell can shut down when we exit.
327 # Restore original namespace so shell can shut down when we exit.
329 self.user_module = orig_user_module
328 self.user_module = orig_user_module
330 self.user_ns = orig_user_ns
329 self.user_ns = orig_user_ns
331 self.compile.flags = orig_compile_flags
330 self.compile.flags = orig_compile_flags
332
331
333
332
334 def embed(**kwargs):
333 def embed(**kwargs):
335 """Call this to embed IPython at the current point in your program.
334 """Call this to embed IPython at the current point in your program.
336
335
337 The first invocation of this will create an :class:`InteractiveShellEmbed`
336 The first invocation of this will create an :class:`InteractiveShellEmbed`
338 instance and then call it. Consecutive calls just call the already
337 instance and then call it. Consecutive calls just call the already
339 created instance.
338 created instance.
340
339
341 If you don't want the kernel to initialize the namespace
340 If you don't want the kernel to initialize the namespace
342 from the scope of the surrounding function,
341 from the scope of the surrounding function,
343 and/or you want to load full IPython configuration,
342 and/or you want to load full IPython configuration,
344 you probably want `IPython.start_ipython()` instead.
343 you probably want `IPython.start_ipython()` instead.
345
344
346 Here is a simple example::
345 Here is a simple example::
347
346
348 from IPython import embed
347 from IPython import embed
349 a = 10
348 a = 10
350 b = 20
349 b = 20
351 embed(header='First time')
350 embed(header='First time')
352 c = 30
351 c = 30
353 d = 40
352 d = 40
354 embed()
353 embed()
355
354
356 Full customization can be done by passing a :class:`Config` in as the
355 Full customization can be done by passing a :class:`Config` in as the
357 config argument.
356 config argument.
358 """
357 """
359 config = kwargs.get('config')
358 config = kwargs.get('config')
360 header = kwargs.pop('header', u'')
359 header = kwargs.pop('header', u'')
361 compile_flags = kwargs.pop('compile_flags', None)
360 compile_flags = kwargs.pop('compile_flags', None)
362 if config is None:
361 if config is None:
363 config = load_default_config()
362 config = load_default_config()
364 config.InteractiveShellEmbed = config.TerminalInteractiveShell
363 config.InteractiveShellEmbed = config.TerminalInteractiveShell
365 kwargs['config'] = config
364 kwargs['config'] = config
366 #save ps1/ps2 if defined
365 #save ps1/ps2 if defined
367 ps1 = None
366 ps1 = None
368 ps2 = None
367 ps2 = None
369 try:
368 try:
370 ps1 = sys.ps1
369 ps1 = sys.ps1
371 ps2 = sys.ps2
370 ps2 = sys.ps2
372 except AttributeError:
371 except AttributeError:
373 pass
372 pass
374 #save previous instance
373 #save previous instance
375 saved_shell_instance = InteractiveShell._instance
374 saved_shell_instance = InteractiveShell._instance
376 if saved_shell_instance is not None:
375 if saved_shell_instance is not None:
377 cls = type(saved_shell_instance)
376 cls = type(saved_shell_instance)
378 cls.clear_instance()
377 cls.clear_instance()
379 frame = sys._getframe(1)
378 frame = sys._getframe(1)
380 shell = InteractiveShellEmbed.instance(_init_location_id='%s:%s' % (
379 shell = InteractiveShellEmbed.instance(_init_location_id='%s:%s' % (
381 frame.f_code.co_filename, frame.f_lineno), **kwargs)
380 frame.f_code.co_filename, frame.f_lineno), **kwargs)
382 shell(header=header, stack_depth=2, compile_flags=compile_flags,
381 shell(header=header, stack_depth=2, compile_flags=compile_flags,
383 _call_location_id='%s:%s' % (frame.f_code.co_filename, frame.f_lineno))
382 _call_location_id='%s:%s' % (frame.f_code.co_filename, frame.f_lineno))
384 InteractiveShellEmbed.clear_instance()
383 InteractiveShellEmbed.clear_instance()
385 #restore previous instance
384 #restore previous instance
386 if saved_shell_instance is not None:
385 if saved_shell_instance is not None:
387 cls = type(saved_shell_instance)
386 cls = type(saved_shell_instance)
388 cls.clear_instance()
387 cls.clear_instance()
389 for subclass in cls._walk_mro():
388 for subclass in cls._walk_mro():
390 subclass._instance = saved_shell_instance
389 subclass._instance = saved_shell_instance
391 if ps1 is not None:
390 if ps1 is not None:
392 sys.ps1 = ps1
391 sys.ps1 = ps1
393 sys.ps2 = ps2
392 sys.ps2 = ps2
@@ -1,518 +1,516 b''
1 """IPython terminal interface using prompt_toolkit"""
1 """IPython terminal interface using prompt_toolkit"""
2
2
3 import os
3 import os
4 import sys
4 import sys
5 import warnings
5 import warnings
6 from warnings import warn
6 from warnings import warn
7
7
8 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
8 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
9 from IPython.utils import io
9 from IPython.utils import io
10 from IPython.utils.py3compat import cast_unicode_py2, input
10 from IPython.utils.py3compat import cast_unicode_py2, input
11 from IPython.utils.terminal import toggle_set_term_title, set_term_title
11 from IPython.utils.terminal import toggle_set_term_title, set_term_title
12 from IPython.utils.process import abbrev_cwd
12 from IPython.utils.process import abbrev_cwd
13 from traitlets import Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum, Union
13 from traitlets import Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum, Union
14
14
15 from prompt_toolkit.document import Document
15 from prompt_toolkit.document import Document
16 from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
16 from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
17 from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
17 from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
18 from prompt_toolkit.history import InMemoryHistory
18 from prompt_toolkit.history import InMemoryHistory
19 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output
19 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output
20 from prompt_toolkit.interface import CommandLineInterface
20 from prompt_toolkit.interface import CommandLineInterface
21 from prompt_toolkit.key_binding.manager import KeyBindingManager
21 from prompt_toolkit.key_binding.manager import KeyBindingManager
22 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
22 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
23 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
23 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
24
24
25 from pygments.styles import get_style_by_name, get_all_styles
25 from pygments.styles import get_style_by_name, get_all_styles
26 from pygments.style import Style
26 from pygments.style import Style
27 from pygments.token import Token
27 from pygments.token import Token
28
28
29 from .debugger import TerminalPdb, Pdb
29 from .debugger import TerminalPdb, Pdb
30 from .magics import TerminalMagics
30 from .magics import TerminalMagics
31 from .pt_inputhooks import get_inputhook_name_and_func
31 from .pt_inputhooks import get_inputhook_name_and_func
32 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
32 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
33 from .ptutils import IPythonPTCompleter, IPythonPTLexer
33 from .ptutils import IPythonPTCompleter, IPythonPTLexer
34 from .shortcuts import register_ipython_shortcuts
34 from .shortcuts import register_ipython_shortcuts
35
35
36 DISPLAY_BANNER_DEPRECATED = object()
36 DISPLAY_BANNER_DEPRECATED = object()
37
37
38
38
39 class _NoStyle(Style): pass
39 class _NoStyle(Style): pass
40
40
41
41
42
42
43 _style_overrides_light_bg = {
43 _style_overrides_light_bg = {
44 Token.Prompt: '#0000ff',
44 Token.Prompt: '#0000ff',
45 Token.PromptNum: '#0000ee bold',
45 Token.PromptNum: '#0000ee bold',
46 Token.OutPrompt: '#cc0000',
46 Token.OutPrompt: '#cc0000',
47 Token.OutPromptNum: '#bb0000 bold',
47 Token.OutPromptNum: '#bb0000 bold',
48 }
48 }
49
49
50 _style_overrides_linux = {
50 _style_overrides_linux = {
51 Token.Prompt: '#00cc00',
51 Token.Prompt: '#00cc00',
52 Token.PromptNum: '#00bb00 bold',
52 Token.PromptNum: '#00bb00 bold',
53 Token.OutPrompt: '#cc0000',
53 Token.OutPrompt: '#cc0000',
54 Token.OutPromptNum: '#bb0000 bold',
54 Token.OutPromptNum: '#bb0000 bold',
55 }
55 }
56
56
57
57
58
58
59 def get_default_editor():
59 def get_default_editor():
60 try:
60 try:
61 return os.environ['EDITOR']
61 return os.environ['EDITOR']
62 except KeyError:
62 except KeyError:
63 pass
63 pass
64 except UnicodeError:
64 except UnicodeError:
65 warn("$EDITOR environment variable is not pure ASCII. Using platform "
65 warn("$EDITOR environment variable is not pure ASCII. Using platform "
66 "default editor.")
66 "default editor.")
67
67
68 if os.name == 'posix':
68 if os.name == 'posix':
69 return 'vi' # the only one guaranteed to be there!
69 return 'vi' # the only one guaranteed to be there!
70 else:
70 else:
71 return 'notepad' # same in Windows!
71 return 'notepad' # same in Windows!
72
72
73 # conservatively check for tty
73 # conservatively check for tty
74 # overridden streams can result in things like:
74 # overridden streams can result in things like:
75 # - sys.stdin = None
75 # - sys.stdin = None
76 # - no isatty method
76 # - no isatty method
77 for _name in ('stdin', 'stdout', 'stderr'):
77 for _name in ('stdin', 'stdout', 'stderr'):
78 _stream = getattr(sys, _name)
78 _stream = getattr(sys, _name)
79 if not _stream or not hasattr(_stream, 'isatty') or not _stream.isatty():
79 if not _stream or not hasattr(_stream, 'isatty') or not _stream.isatty():
80 _is_tty = False
80 _is_tty = False
81 break
81 break
82 else:
82 else:
83 _is_tty = True
83 _is_tty = True
84
84
85
85
86 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
86 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
87
87
88 class TerminalInteractiveShell(InteractiveShell):
88 class TerminalInteractiveShell(InteractiveShell):
89 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
89 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
90 'to reserve for the completion menu'
90 'to reserve for the completion menu'
91 ).tag(config=True)
91 ).tag(config=True)
92
92
93 def _space_for_menu_changed(self, old, new):
93 def _space_for_menu_changed(self, old, new):
94 self._update_layout()
94 self._update_layout()
95
95
96 pt_cli = None
96 pt_cli = None
97 debugger_history = None
97 debugger_history = None
98 _pt_app = None
98 _pt_app = None
99
99
100 simple_prompt = Bool(_use_simple_prompt,
100 simple_prompt = Bool(_use_simple_prompt,
101 help="""Use `raw_input` for the REPL, without completion, multiline input, and prompt colors.
101 help="""Use `raw_input` for the REPL, without completion, multiline input, and prompt colors.
102
102
103 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
103 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
104 IPython own testing machinery, and emacs inferior-shell integration through elpy.
104 IPython own testing machinery, and emacs inferior-shell integration through elpy.
105
105
106 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
106 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
107 environment variable is set, or the current terminal is not a tty.
107 environment variable is set, or the current terminal is not a tty."""
108
109 """
110 ).tag(config=True)
108 ).tag(config=True)
111
109
112 @property
110 @property
113 def debugger_cls(self):
111 def debugger_cls(self):
114 return Pdb if self.simple_prompt else TerminalPdb
112 return Pdb if self.simple_prompt else TerminalPdb
115
113
116 confirm_exit = Bool(True,
114 confirm_exit = Bool(True,
117 help="""
115 help="""
118 Set to confirm when you try to exit IPython with an EOF (Control-D
116 Set to confirm when you try to exit IPython with an EOF (Control-D
119 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
117 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
120 you can force a direct exit without any confirmation.""",
118 you can force a direct exit without any confirmation.""",
121 ).tag(config=True)
119 ).tag(config=True)
122
120
123 editing_mode = Unicode('emacs',
121 editing_mode = Unicode('emacs',
124 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
122 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
125 ).tag(config=True)
123 ).tag(config=True)
126
124
127 mouse_support = Bool(False,
125 mouse_support = Bool(False,
128 help="Enable mouse support in the prompt"
126 help="Enable mouse support in the prompt"
129 ).tag(config=True)
127 ).tag(config=True)
130
128
131 highlighting_style = Union([Unicode('legacy'), Type(klass=Style)],
129 highlighting_style = Union([Unicode('legacy'), Type(klass=Style)],
132 help="""The name or class of a Pygments style to use for syntax
130 help="""The name or class of a Pygments style to use for syntax
133 highlighting: \n %s""" % ', '.join(get_all_styles())
131 highlighting: \n %s""" % ', '.join(get_all_styles())
134 ).tag(config=True)
132 ).tag(config=True)
135
133
136
134
137 @observe('highlighting_style')
135 @observe('highlighting_style')
138 @observe('colors')
136 @observe('colors')
139 def _highlighting_style_changed(self, change):
137 def _highlighting_style_changed(self, change):
140 self.refresh_style()
138 self.refresh_style()
141
139
142 def refresh_style(self):
140 def refresh_style(self):
143 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
141 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
144
142
145
143
146 highlighting_style_overrides = Dict(
144 highlighting_style_overrides = Dict(
147 help="Override highlighting format for specific tokens"
145 help="Override highlighting format for specific tokens"
148 ).tag(config=True)
146 ).tag(config=True)
149
147
150 true_color = Bool(False,
148 true_color = Bool(False,
151 help=("Use 24bit colors instead of 256 colors in prompt highlighting. "
149 help=("Use 24bit colors instead of 256 colors in prompt highlighting. "
152 "If your terminal supports true color, the following command "
150 "If your terminal supports true color, the following command "
153 "should print 'TRUECOLOR' in orange: "
151 "should print 'TRUECOLOR' in orange: "
154 "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"")
152 "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"")
155 ).tag(config=True)
153 ).tag(config=True)
156
154
157 editor = Unicode(get_default_editor(),
155 editor = Unicode(get_default_editor(),
158 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
156 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
159 ).tag(config=True)
157 ).tag(config=True)
160
158
161 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
159 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
162
160
163 prompts = Instance(Prompts)
161 prompts = Instance(Prompts)
164
162
165 @default('prompts')
163 @default('prompts')
166 def _prompts_default(self):
164 def _prompts_default(self):
167 return self.prompts_class(self)
165 return self.prompts_class(self)
168
166
169 @observe('prompts')
167 @observe('prompts')
170 def _(self, change):
168 def _(self, change):
171 self._update_layout()
169 self._update_layout()
172
170
173 @default('displayhook_class')
171 @default('displayhook_class')
174 def _displayhook_class_default(self):
172 def _displayhook_class_default(self):
175 return RichPromptDisplayHook
173 return RichPromptDisplayHook
176
174
177 term_title = Bool(True,
175 term_title = Bool(True,
178 help="Automatically set the terminal title"
176 help="Automatically set the terminal title"
179 ).tag(config=True)
177 ).tag(config=True)
180
178
181 display_completions = Enum(('column', 'multicolumn','readlinelike'),
179 display_completions = Enum(('column', 'multicolumn','readlinelike'),
182 help= ( "Options for displaying tab completions, 'column', 'multicolumn', and "
180 help= ( "Options for displaying tab completions, 'column', 'multicolumn', and "
183 "'readlinelike'. These options are for `prompt_toolkit`, see "
181 "'readlinelike'. These options are for `prompt_toolkit`, see "
184 "`prompt_toolkit` documentation for more information."
182 "`prompt_toolkit` documentation for more information."
185 ),
183 ),
186 default_value='multicolumn').tag(config=True)
184 default_value='multicolumn').tag(config=True)
187
185
188 highlight_matching_brackets = Bool(True,
186 highlight_matching_brackets = Bool(True,
189 help="Highlight matching brackets.",
187 help="Highlight matching brackets.",
190 ).tag(config=True)
188 ).tag(config=True)
191
189
192 extra_open_editor_shortcuts = Bool(False,
190 extra_open_editor_shortcuts = Bool(False,
193 help="Enable vi (v) or Emacs (C-X C-E) shortcuts to open an external editor. "
191 help="Enable vi (v) or Emacs (C-X C-E) shortcuts to open an external editor. "
194 "This is in addition to the F2 binding, which is always enabled."
192 "This is in addition to the F2 binding, which is always enabled."
195 ).tag(config=True)
193 ).tag(config=True)
196
194
197 @observe('term_title')
195 @observe('term_title')
198 def init_term_title(self, change=None):
196 def init_term_title(self, change=None):
199 # Enable or disable the terminal title.
197 # Enable or disable the terminal title.
200 if self.term_title:
198 if self.term_title:
201 toggle_set_term_title(True)
199 toggle_set_term_title(True)
202 set_term_title('IPython: ' + abbrev_cwd())
200 set_term_title('IPython: ' + abbrev_cwd())
203 else:
201 else:
204 toggle_set_term_title(False)
202 toggle_set_term_title(False)
205
203
206 def init_display_formatter(self):
204 def init_display_formatter(self):
207 super(TerminalInteractiveShell, self).init_display_formatter()
205 super(TerminalInteractiveShell, self).init_display_formatter()
208 # terminal only supports plain text
206 # terminal only supports plain text
209 self.display_formatter.active_types = ['text/plain']
207 self.display_formatter.active_types = ['text/plain']
210 # disable `_ipython_display_`
208 # disable `_ipython_display_`
211 self.display_formatter.ipython_display_formatter.enabled = False
209 self.display_formatter.ipython_display_formatter.enabled = False
212
210
213 def init_prompt_toolkit_cli(self):
211 def init_prompt_toolkit_cli(self):
214 if self.simple_prompt:
212 if self.simple_prompt:
215 # Fall back to plain non-interactive output for tests.
213 # Fall back to plain non-interactive output for tests.
216 # This is very limited, and only accepts a single line.
214 # This is very limited, and only accepts a single line.
217 def prompt():
215 def prompt():
218 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
216 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
219 self.prompt_for_code = prompt
217 self.prompt_for_code = prompt
220 return
218 return
221
219
222 # Set up keyboard shortcuts
220 # Set up keyboard shortcuts
223 kbmanager = KeyBindingManager.for_prompt(
221 kbmanager = KeyBindingManager.for_prompt(
224 enable_open_in_editor=self.extra_open_editor_shortcuts,
222 enable_open_in_editor=self.extra_open_editor_shortcuts,
225 )
223 )
226 register_ipython_shortcuts(kbmanager.registry, self)
224 register_ipython_shortcuts(kbmanager.registry, self)
227
225
228 # Pre-populate history from IPython's history database
226 # Pre-populate history from IPython's history database
229 history = InMemoryHistory()
227 history = InMemoryHistory()
230 last_cell = u""
228 last_cell = u""
231 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
229 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
232 include_latest=True):
230 include_latest=True):
233 # Ignore blank lines and consecutive duplicates
231 # Ignore blank lines and consecutive duplicates
234 cell = cell.rstrip()
232 cell = cell.rstrip()
235 if cell and (cell != last_cell):
233 if cell and (cell != last_cell):
236 history.append(cell)
234 history.append(cell)
237 last_cell = cell
235 last_cell = cell
238
236
239 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
237 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
240 style = DynamicStyle(lambda: self._style)
238 style = DynamicStyle(lambda: self._style)
241
239
242 editing_mode = getattr(EditingMode, self.editing_mode.upper())
240 editing_mode = getattr(EditingMode, self.editing_mode.upper())
243
241
244 def patch_stdout(**kwargs):
242 def patch_stdout(**kwargs):
245 return self.pt_cli.patch_stdout_context(**kwargs)
243 return self.pt_cli.patch_stdout_context(**kwargs)
246
244
247 self._pt_app = create_prompt_application(
245 self._pt_app = create_prompt_application(
248 editing_mode=editing_mode,
246 editing_mode=editing_mode,
249 key_bindings_registry=kbmanager.registry,
247 key_bindings_registry=kbmanager.registry,
250 history=history,
248 history=history,
251 completer=IPythonPTCompleter(shell=self,
249 completer=IPythonPTCompleter(shell=self,
252 patch_stdout=patch_stdout),
250 patch_stdout=patch_stdout),
253 enable_history_search=True,
251 enable_history_search=True,
254 style=style,
252 style=style,
255 mouse_support=self.mouse_support,
253 mouse_support=self.mouse_support,
256 **self._layout_options()
254 **self._layout_options()
257 )
255 )
258 self._eventloop = create_eventloop(self.inputhook)
256 self._eventloop = create_eventloop(self.inputhook)
259 self.pt_cli = CommandLineInterface(
257 self.pt_cli = CommandLineInterface(
260 self._pt_app, eventloop=self._eventloop,
258 self._pt_app, eventloop=self._eventloop,
261 output=create_output(true_color=self.true_color))
259 output=create_output(true_color=self.true_color))
262
260
263 def _make_style_from_name_or_cls(self, name_or_cls):
261 def _make_style_from_name_or_cls(self, name_or_cls):
264 """
262 """
265 Small wrapper that make an IPython compatible style from a style name
263 Small wrapper that make an IPython compatible style from a style name
266
264
267 We need that to add style for prompt ... etc.
265 We need that to add style for prompt ... etc.
268 """
266 """
269 style_overrides = {}
267 style_overrides = {}
270 if name_or_cls == 'legacy':
268 if name_or_cls == 'legacy':
271 legacy = self.colors.lower()
269 legacy = self.colors.lower()
272 if legacy == 'linux':
270 if legacy == 'linux':
273 style_cls = get_style_by_name('monokai')
271 style_cls = get_style_by_name('monokai')
274 style_overrides = _style_overrides_linux
272 style_overrides = _style_overrides_linux
275 elif legacy == 'lightbg':
273 elif legacy == 'lightbg':
276 style_overrides = _style_overrides_light_bg
274 style_overrides = _style_overrides_light_bg
277 style_cls = get_style_by_name('pastie')
275 style_cls = get_style_by_name('pastie')
278 elif legacy == 'neutral':
276 elif legacy == 'neutral':
279 # The default theme needs to be visible on both a dark background
277 # The default theme needs to be visible on both a dark background
280 # and a light background, because we can't tell what the terminal
278 # and a light background, because we can't tell what the terminal
281 # looks like. These tweaks to the default theme help with that.
279 # looks like. These tweaks to the default theme help with that.
282 style_cls = get_style_by_name('default')
280 style_cls = get_style_by_name('default')
283 style_overrides.update({
281 style_overrides.update({
284 Token.Number: '#007700',
282 Token.Number: '#007700',
285 Token.Operator: 'noinherit',
283 Token.Operator: 'noinherit',
286 Token.String: '#BB6622',
284 Token.String: '#BB6622',
287 Token.Name.Function: '#2080D0',
285 Token.Name.Function: '#2080D0',
288 Token.Name.Class: 'bold #2080D0',
286 Token.Name.Class: 'bold #2080D0',
289 Token.Name.Namespace: 'bold #2080D0',
287 Token.Name.Namespace: 'bold #2080D0',
290 Token.Prompt: '#009900',
288 Token.Prompt: '#009900',
291 Token.PromptNum: '#00ff00 bold',
289 Token.PromptNum: '#00ff00 bold',
292 Token.OutPrompt: '#990000',
290 Token.OutPrompt: '#990000',
293 Token.OutPromptNum: '#ff0000 bold',
291 Token.OutPromptNum: '#ff0000 bold',
294 })
292 })
295
293
296 # Hack: Due to limited color support on the Windows console
294 # Hack: Due to limited color support on the Windows console
297 # the prompt colors will be wrong without this
295 # the prompt colors will be wrong without this
298 if os.name == 'nt':
296 if os.name == 'nt':
299 style_overrides.update({
297 style_overrides.update({
300 Token.Prompt: '#ansidarkgreen',
298 Token.Prompt: '#ansidarkgreen',
301 Token.PromptNum: '#ansigreen bold',
299 Token.PromptNum: '#ansigreen bold',
302 Token.OutPrompt: '#ansidarkred',
300 Token.OutPrompt: '#ansidarkred',
303 Token.OutPromptNum: '#ansired bold',
301 Token.OutPromptNum: '#ansired bold',
304 })
302 })
305 elif legacy =='nocolor':
303 elif legacy =='nocolor':
306 style_cls=_NoStyle
304 style_cls=_NoStyle
307 style_overrides = {}
305 style_overrides = {}
308 else :
306 else :
309 raise ValueError('Got unknown colors: ', legacy)
307 raise ValueError('Got unknown colors: ', legacy)
310 else :
308 else :
311 if isinstance(name_or_cls, str):
309 if isinstance(name_or_cls, str):
312 style_cls = get_style_by_name(name_or_cls)
310 style_cls = get_style_by_name(name_or_cls)
313 else:
311 else:
314 style_cls = name_or_cls
312 style_cls = name_or_cls
315 style_overrides = {
313 style_overrides = {
316 Token.Prompt: '#009900',
314 Token.Prompt: '#009900',
317 Token.PromptNum: '#00ff00 bold',
315 Token.PromptNum: '#00ff00 bold',
318 Token.OutPrompt: '#990000',
316 Token.OutPrompt: '#990000',
319 Token.OutPromptNum: '#ff0000 bold',
317 Token.OutPromptNum: '#ff0000 bold',
320 }
318 }
321 style_overrides.update(self.highlighting_style_overrides)
319 style_overrides.update(self.highlighting_style_overrides)
322 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
320 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
323 style_dict=style_overrides)
321 style_dict=style_overrides)
324
322
325 return style
323 return style
326
324
327 def _layout_options(self):
325 def _layout_options(self):
328 """
326 """
329 Return the current layout option for the current Terminal InteractiveShell
327 Return the current layout option for the current Terminal InteractiveShell
330 """
328 """
331 return {
329 return {
332 'lexer':IPythonPTLexer(),
330 'lexer':IPythonPTLexer(),
333 'reserve_space_for_menu':self.space_for_menu,
331 'reserve_space_for_menu':self.space_for_menu,
334 'get_prompt_tokens':self.prompts.in_prompt_tokens,
332 'get_prompt_tokens':self.prompts.in_prompt_tokens,
335 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
333 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
336 'multiline':True,
334 'multiline':True,
337 'display_completions_in_columns': (self.display_completions == 'multicolumn'),
335 'display_completions_in_columns': (self.display_completions == 'multicolumn'),
338
336
339 # Highlight matching brackets, but only when this setting is
337 # Highlight matching brackets, but only when this setting is
340 # enabled, and only when the DEFAULT_BUFFER has the focus.
338 # enabled, and only when the DEFAULT_BUFFER has the focus.
341 'extra_input_processors': [ConditionalProcessor(
339 'extra_input_processors': [ConditionalProcessor(
342 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
340 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
343 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
341 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
344 Condition(lambda cli: self.highlight_matching_brackets))],
342 Condition(lambda cli: self.highlight_matching_brackets))],
345 }
343 }
346
344
347 def _update_layout(self):
345 def _update_layout(self):
348 """
346 """
349 Ask for a re computation of the application layout, if for example ,
347 Ask for a re computation of the application layout, if for example ,
350 some configuration options have changed.
348 some configuration options have changed.
351 """
349 """
352 if self._pt_app:
350 if self._pt_app:
353 self._pt_app.layout = create_prompt_layout(**self._layout_options())
351 self._pt_app.layout = create_prompt_layout(**self._layout_options())
354
352
355 def prompt_for_code(self):
353 def prompt_for_code(self):
356 document = self.pt_cli.run(
354 document = self.pt_cli.run(
357 pre_run=self.pre_prompt, reset_current_buffer=True)
355 pre_run=self.pre_prompt, reset_current_buffer=True)
358 return document.text
356 return document.text
359
357
360 def enable_win_unicode_console(self):
358 def enable_win_unicode_console(self):
361 if sys.version_info >= (3, 6):
359 if sys.version_info >= (3, 6):
362 # Since PEP 528, Python uses the unicode APIs for the Windows
360 # Since PEP 528, Python uses the unicode APIs for the Windows
363 # console by default, so WUC shouldn't be needed.
361 # console by default, so WUC shouldn't be needed.
364 return
362 return
365
363
366 import win_unicode_console
364 import win_unicode_console
367 win_unicode_console.enable()
365 win_unicode_console.enable()
368
366
369 def init_io(self):
367 def init_io(self):
370 if sys.platform not in {'win32', 'cli'}:
368 if sys.platform not in {'win32', 'cli'}:
371 return
369 return
372
370
373 self.enable_win_unicode_console()
371 self.enable_win_unicode_console()
374
372
375 import colorama
373 import colorama
376 colorama.init()
374 colorama.init()
377
375
378 # For some reason we make these wrappers around stdout/stderr.
376 # For some reason we make these wrappers around stdout/stderr.
379 # For now, we need to reset them so all output gets coloured.
377 # For now, we need to reset them so all output gets coloured.
380 # https://github.com/ipython/ipython/issues/8669
378 # https://github.com/ipython/ipython/issues/8669
381 # io.std* are deprecated, but don't show our own deprecation warnings
379 # io.std* are deprecated, but don't show our own deprecation warnings
382 # during initialization of the deprecated API.
380 # during initialization of the deprecated API.
383 with warnings.catch_warnings():
381 with warnings.catch_warnings():
384 warnings.simplefilter('ignore', DeprecationWarning)
382 warnings.simplefilter('ignore', DeprecationWarning)
385 io.stdout = io.IOStream(sys.stdout)
383 io.stdout = io.IOStream(sys.stdout)
386 io.stderr = io.IOStream(sys.stderr)
384 io.stderr = io.IOStream(sys.stderr)
387
385
388 def init_magics(self):
386 def init_magics(self):
389 super(TerminalInteractiveShell, self).init_magics()
387 super(TerminalInteractiveShell, self).init_magics()
390 self.register_magics(TerminalMagics)
388 self.register_magics(TerminalMagics)
391
389
392 def init_alias(self):
390 def init_alias(self):
393 # The parent class defines aliases that can be safely used with any
391 # The parent class defines aliases that can be safely used with any
394 # frontend.
392 # frontend.
395 super(TerminalInteractiveShell, self).init_alias()
393 super(TerminalInteractiveShell, self).init_alias()
396
394
397 # Now define aliases that only make sense on the terminal, because they
395 # Now define aliases that only make sense on the terminal, because they
398 # need direct access to the console in a way that we can't emulate in
396 # need direct access to the console in a way that we can't emulate in
399 # GUI or web frontend
397 # GUI or web frontend
400 if os.name == 'posix':
398 if os.name == 'posix':
401 for cmd in ['clear', 'more', 'less', 'man']:
399 for cmd in ['clear', 'more', 'less', 'man']:
402 self.alias_manager.soft_define_alias(cmd, cmd)
400 self.alias_manager.soft_define_alias(cmd, cmd)
403
401
404
402
405 def __init__(self, *args, **kwargs):
403 def __init__(self, *args, **kwargs):
406 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
404 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
407 self.init_prompt_toolkit_cli()
405 self.init_prompt_toolkit_cli()
408 self.init_term_title()
406 self.init_term_title()
409 self.keep_running = True
407 self.keep_running = True
410
408
411 self.debugger_history = InMemoryHistory()
409 self.debugger_history = InMemoryHistory()
412
410
413 def ask_exit(self):
411 def ask_exit(self):
414 self.keep_running = False
412 self.keep_running = False
415
413
416 rl_next_input = None
414 rl_next_input = None
417
415
418 def pre_prompt(self):
416 def pre_prompt(self):
419 if self.rl_next_input:
417 if self.rl_next_input:
420 # We can't set the buffer here, because it will be reset just after
418 # We can't set the buffer here, because it will be reset just after
421 # this. Adding a callable to pre_run_callables does what we need
419 # this. Adding a callable to pre_run_callables does what we need
422 # after the buffer is reset.
420 # after the buffer is reset.
423 s = cast_unicode_py2(self.rl_next_input)
421 s = cast_unicode_py2(self.rl_next_input)
424 def set_doc():
422 def set_doc():
425 self.pt_cli.application.buffer.document = Document(s)
423 self.pt_cli.application.buffer.document = Document(s)
426 if hasattr(self.pt_cli, 'pre_run_callables'):
424 if hasattr(self.pt_cli, 'pre_run_callables'):
427 self.pt_cli.pre_run_callables.append(set_doc)
425 self.pt_cli.pre_run_callables.append(set_doc)
428 else:
426 else:
429 # Older version of prompt_toolkit; it's OK to set the document
427 # Older version of prompt_toolkit; it's OK to set the document
430 # directly here.
428 # directly here.
431 set_doc()
429 set_doc()
432 self.rl_next_input = None
430 self.rl_next_input = None
433
431
434 def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
432 def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
435
433
436 if display_banner is not DISPLAY_BANNER_DEPRECATED:
434 if display_banner is not DISPLAY_BANNER_DEPRECATED:
437 warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
435 warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
438
436
439 self.keep_running = True
437 self.keep_running = True
440 while self.keep_running:
438 while self.keep_running:
441 print(self.separate_in, end='')
439 print(self.separate_in, end='')
442
440
443 try:
441 try:
444 code = self.prompt_for_code()
442 code = self.prompt_for_code()
445 except EOFError:
443 except EOFError:
446 if (not self.confirm_exit) \
444 if (not self.confirm_exit) \
447 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
445 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
448 self.ask_exit()
446 self.ask_exit()
449
447
450 else:
448 else:
451 if code:
449 if code:
452 self.run_cell(code, store_history=True)
450 self.run_cell(code, store_history=True)
453
451
454 def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED):
452 def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED):
455 # An extra layer of protection in case someone mashing Ctrl-C breaks
453 # An extra layer of protection in case someone mashing Ctrl-C breaks
456 # out of our internal code.
454 # out of our internal code.
457 if display_banner is not DISPLAY_BANNER_DEPRECATED:
455 if display_banner is not DISPLAY_BANNER_DEPRECATED:
458 warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
456 warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
459 while True:
457 while True:
460 try:
458 try:
461 self.interact()
459 self.interact()
462 break
460 break
463 except KeyboardInterrupt as e:
461 except KeyboardInterrupt as e:
464 print("\n%s escaped interact()\n" % type(e).__name__)
462 print("\n%s escaped interact()\n" % type(e).__name__)
465 finally:
463 finally:
466 # An interrupt during the eventloop will mess up the
464 # An interrupt during the eventloop will mess up the
467 # internal state of the prompt_toolkit library.
465 # internal state of the prompt_toolkit library.
468 # Stopping the eventloop fixes this, see
466 # Stopping the eventloop fixes this, see
469 # https://github.com/ipython/ipython/pull/9867
467 # https://github.com/ipython/ipython/pull/9867
470 if hasattr(self, '_eventloop'):
468 if hasattr(self, '_eventloop'):
471 self._eventloop.stop()
469 self._eventloop.stop()
472
470
473 _inputhook = None
471 _inputhook = None
474 def inputhook(self, context):
472 def inputhook(self, context):
475 if self._inputhook is not None:
473 if self._inputhook is not None:
476 self._inputhook(context)
474 self._inputhook(context)
477
475
478 active_eventloop = None
476 active_eventloop = None
479 def enable_gui(self, gui=None):
477 def enable_gui(self, gui=None):
480 if gui:
478 if gui:
481 self.active_eventloop, self._inputhook =\
479 self.active_eventloop, self._inputhook =\
482 get_inputhook_name_and_func(gui)
480 get_inputhook_name_and_func(gui)
483 else:
481 else:
484 self.active_eventloop = self._inputhook = None
482 self.active_eventloop = self._inputhook = None
485
483
486 # Run !system commands directly, not through pipes, so terminal programs
484 # Run !system commands directly, not through pipes, so terminal programs
487 # work correctly.
485 # work correctly.
488 system = InteractiveShell.system_raw
486 system = InteractiveShell.system_raw
489
487
490 def auto_rewrite_input(self, cmd):
488 def auto_rewrite_input(self, cmd):
491 """Overridden from the parent class to use fancy rewriting prompt"""
489 """Overridden from the parent class to use fancy rewriting prompt"""
492 if not self.show_rewritten_input:
490 if not self.show_rewritten_input:
493 return
491 return
494
492
495 tokens = self.prompts.rewrite_prompt_tokens()
493 tokens = self.prompts.rewrite_prompt_tokens()
496 if self.pt_cli:
494 if self.pt_cli:
497 self.pt_cli.print_tokens(tokens)
495 self.pt_cli.print_tokens(tokens)
498 print(cmd)
496 print(cmd)
499 else:
497 else:
500 prompt = ''.join(s for t, s in tokens)
498 prompt = ''.join(s for t, s in tokens)
501 print(prompt, cmd, sep='')
499 print(prompt, cmd, sep='')
502
500
503 _prompts_before = None
501 _prompts_before = None
504 def switch_doctest_mode(self, mode):
502 def switch_doctest_mode(self, mode):
505 """Switch prompts to classic for %doctest_mode"""
503 """Switch prompts to classic for %doctest_mode"""
506 if mode:
504 if mode:
507 self._prompts_before = self.prompts
505 self._prompts_before = self.prompts
508 self.prompts = ClassicPrompts(self)
506 self.prompts = ClassicPrompts(self)
509 elif self._prompts_before:
507 elif self._prompts_before:
510 self.prompts = self._prompts_before
508 self.prompts = self._prompts_before
511 self._prompts_before = None
509 self._prompts_before = None
512 self._update_layout()
510 self._update_layout()
513
511
514
512
515 InteractiveShellABC.register(TerminalInteractiveShell)
513 InteractiveShellABC.register(TerminalInteractiveShell)
516
514
517 if __name__ == '__main__':
515 if __name__ == '__main__':
518 TerminalInteractiveShell.instance().interact()
516 TerminalInteractiveShell.instance().interact()
@@ -1,594 +1,595 b''
1 """Patched version of standard library tokenize, to deal with various bugs.
1 """Patched version of standard library tokenize, to deal with various bugs.
2
2
3 Based on Python 3.2 code.
3 Based on Python 3.2 code.
4
4
5 Patches:
5 Patches:
6
6
7 - Gareth Rees' patch for Python issue #12691 (untokenizing)
7 - Gareth Rees' patch for Python issue #12691 (untokenizing)
8 - Except we don't encode the output of untokenize
8 - Except we don't encode the output of untokenize
9 - Python 2 compatible syntax, so that it can be byte-compiled at installation
9 - Python 2 compatible syntax, so that it can be byte-compiled at installation
10 - Newlines in comments and blank lines should be either NL or NEWLINE, depending
10 - Newlines in comments and blank lines should be either NL or NEWLINE, depending
11 on whether they are in a multi-line statement. Filed as Python issue #17061.
11 on whether they are in a multi-line statement. Filed as Python issue #17061.
12 - Export generate_tokens & TokenError
12 - Export generate_tokens & TokenError
13 - u and rb literals are allowed under Python 3.3 and above.
13 - u and rb literals are allowed under Python 3.3 and above.
14
14
15 ------------------------------------------------------------------------------
15 ------------------------------------------------------------------------------
16 Tokenization help for Python programs.
16 Tokenization help for Python programs.
17
17
18 tokenize(readline) is a generator that breaks a stream of bytes into
18 tokenize(readline) is a generator that breaks a stream of bytes into
19 Python tokens. It decodes the bytes according to PEP-0263 for
19 Python tokens. It decodes the bytes according to PEP-0263 for
20 determining source file encoding.
20 determining source file encoding.
21
21
22 It accepts a readline-like method which is called repeatedly to get the
22 It accepts a readline-like method which is called repeatedly to get the
23 next line of input (or b"" for EOF). It generates 5-tuples with these
23 next line of input (or b"" for EOF). It generates 5-tuples with these
24 members:
24 members:
25
25
26 the token type (see token.py)
26 the token type (see token.py)
27 the token (a string)
27 the token (a string)
28 the starting (row, column) indices of the token (a 2-tuple of ints)
28 the starting (row, column) indices of the token (a 2-tuple of ints)
29 the ending (row, column) indices of the token (a 2-tuple of ints)
29 the ending (row, column) indices of the token (a 2-tuple of ints)
30 the original line (string)
30 the original line (string)
31
31
32 It is designed to match the working of the Python tokenizer exactly, except
32 It is designed to match the working of the Python tokenizer exactly, except
33 that it produces COMMENT tokens for comments and gives type OP for all
33 that it produces COMMENT tokens for comments and gives type OP for all
34 operators. Additionally, all token lists start with an ENCODING token
34 operators. Additionally, all token lists start with an ENCODING token
35 which tells you which encoding was used to decode the bytes stream.
35 which tells you which encoding was used to decode the bytes stream.
36 """
36 """
37
37
38 __author__ = 'Ka-Ping Yee <ping@lfw.org>'
38 __author__ = 'Ka-Ping Yee <ping@lfw.org>'
39 __credits__ = ('GvR, ESR, Tim Peters, Thomas Wouters, Fred Drake, '
39 __credits__ = ('GvR, ESR, Tim Peters, Thomas Wouters, Fred Drake, '
40 'Skip Montanaro, Raymond Hettinger, Trent Nelson, '
40 'Skip Montanaro, Raymond Hettinger, Trent Nelson, '
41 'Michael Foord')
41 'Michael Foord')
42 import builtins
42 import builtins
43 import re
43 import re
44 import sys
44 import sys
45 from token import *
45 from token import *
46 from codecs import lookup, BOM_UTF8
46 from codecs import lookup, BOM_UTF8
47 import collections
47 import collections
48 from io import TextIOWrapper
48 from io import TextIOWrapper
49 cookie_re = re.compile("coding[:=]\s*([-\w.]+)")
49 cookie_re = re.compile("coding[:=]\s*([-\w.]+)")
50
50
51 import token
51 import token
52 __all__ = token.__all__ + ["COMMENT", "tokenize", "detect_encoding",
52 __all__ = token.__all__ + ["COMMENT", "tokenize", "detect_encoding",
53 "NL", "untokenize", "ENCODING", "TokenInfo"]
53 "NL", "untokenize", "ENCODING", "TokenInfo"]
54 del token
54 del token
55
55
56 __all__ += ["generate_tokens", "TokenError"]
56 __all__ += ["generate_tokens", "TokenError"]
57
57
58 COMMENT = N_TOKENS
58 COMMENT = N_TOKENS
59 tok_name[COMMENT] = 'COMMENT'
59 tok_name[COMMENT] = 'COMMENT'
60 NL = N_TOKENS + 1
60 NL = N_TOKENS + 1
61 tok_name[NL] = 'NL'
61 tok_name[NL] = 'NL'
62 ENCODING = N_TOKENS + 2
62 ENCODING = N_TOKENS + 2
63 tok_name[ENCODING] = 'ENCODING'
63 tok_name[ENCODING] = 'ENCODING'
64 N_TOKENS += 3
64 N_TOKENS += 3
65
65
66 class TokenInfo(collections.namedtuple('TokenInfo', 'type string start end line')):
66 class TokenInfo(collections.namedtuple('TokenInfo', 'type string start end line')):
67 def __repr__(self):
67 def __repr__(self):
68 annotated_type = '%d (%s)' % (self.type, tok_name[self.type])
68 annotated_type = '%d (%s)' % (self.type, tok_name[self.type])
69 return ('TokenInfo(type=%s, string=%r, start=%r, end=%r, line=%r)' %
69 return ('TokenInfo(type=%s, string=%r, start=%r, end=%r, line=%r)' %
70 self._replace(type=annotated_type))
70 self._replace(type=annotated_type))
71
71
72 def group(*choices): return '(' + '|'.join(choices) + ')'
72 def group(*choices): return '(' + '|'.join(choices) + ')'
73 def any(*choices): return group(*choices) + '*'
73 def any(*choices): return group(*choices) + '*'
74 def maybe(*choices): return group(*choices) + '?'
74 def maybe(*choices): return group(*choices) + '?'
75
75
76 # Note: we use unicode matching for names ("\w") but ascii matching for
76 # Note: we use unicode matching for names ("\w") but ascii matching for
77 # number literals.
77 # number literals.
78 Whitespace = r'[ \f\t]*'
78 Whitespace = r'[ \f\t]*'
79 Comment = r'#[^\r\n]*'
79 Comment = r'#[^\r\n]*'
80 Ignore = Whitespace + any(r'\\\r?\n' + Whitespace) + maybe(Comment)
80 Ignore = Whitespace + any(r'\\\r?\n' + Whitespace) + maybe(Comment)
81 Name = r'\w+'
81 Name = r'\w+'
82
82
83 Hexnumber = r'0[xX][0-9a-fA-F]+'
83 Hexnumber = r'0[xX][0-9a-fA-F]+'
84 Binnumber = r'0[bB][01]+'
84 Binnumber = r'0[bB][01]+'
85 Octnumber = r'0[oO][0-7]+'
85 Octnumber = r'0[oO][0-7]+'
86 Decnumber = r'(?:0+|[1-9][0-9]*)'
86 Decnumber = r'(?:0+|[1-9][0-9]*)'
87 Intnumber = group(Hexnumber, Binnumber, Octnumber, Decnumber)
87 Intnumber = group(Hexnumber, Binnumber, Octnumber, Decnumber)
88 Exponent = r'[eE][-+]?[0-9]+'
88 Exponent = r'[eE][-+]?[0-9]+'
89 Pointfloat = group(r'[0-9]+\.[0-9]*', r'\.[0-9]+') + maybe(Exponent)
89 Pointfloat = group(r'[0-9]+\.[0-9]*', r'\.[0-9]+') + maybe(Exponent)
90 Expfloat = r'[0-9]+' + Exponent
90 Expfloat = r'[0-9]+' + Exponent
91 Floatnumber = group(Pointfloat, Expfloat)
91 Floatnumber = group(Pointfloat, Expfloat)
92 Imagnumber = group(r'[0-9]+[jJ]', Floatnumber + r'[jJ]')
92 Imagnumber = group(r'[0-9]+[jJ]', Floatnumber + r'[jJ]')
93 Number = group(Imagnumber, Floatnumber, Intnumber)
93 Number = group(Imagnumber, Floatnumber, Intnumber)
94
94
95 if sys.version_info.minor >= 3:
95 if sys.version_info.minor >= 3:
96 StringPrefix = r'(?:[bB][rR]?|[rR][bB]?|[uU])?'
96 StringPrefix = r'(?:[bB][rR]?|[rR][bB]?|[uU])?'
97 else:
97 else:
98 StringPrefix = r'(?:[bB]?[rR]?)?'
98 StringPrefix = r'(?:[bB]?[rR]?)?'
99
99
100 # Tail end of ' string.
100 # Tail end of ' string.
101 Single = r"[^'\\]*(?:\\.[^'\\]*)*'"
101 Single = r"[^'\\]*(?:\\.[^'\\]*)*'"
102 # Tail end of " string.
102 # Tail end of " string.
103 Double = r'[^"\\]*(?:\\.[^"\\]*)*"'
103 Double = r'[^"\\]*(?:\\.[^"\\]*)*"'
104 # Tail end of ''' string.
104 # Tail end of ''' string.
105 Single3 = r"[^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*'''"
105 Single3 = r"[^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*'''"
106 # Tail end of """ string.
106 # Tail end of """ string.
107 Double3 = r'[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*"""'
107 Double3 = r'[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*"""'
108 Triple = group(StringPrefix + "'''", StringPrefix + '"""')
108 Triple = group(StringPrefix + "'''", StringPrefix + '"""')
109 # Single-line ' or " string.
109 # Single-line ' or " string.
110 String = group(StringPrefix + r"'[^\n'\\]*(?:\\.[^\n'\\]*)*'",
110 String = group(StringPrefix + r"'[^\n'\\]*(?:\\.[^\n'\\]*)*'",
111 StringPrefix + r'"[^\n"\\]*(?:\\.[^\n"\\]*)*"')
111 StringPrefix + r'"[^\n"\\]*(?:\\.[^\n"\\]*)*"')
112
112
113 # Because of leftmost-then-longest match semantics, be sure to put the
113 # Because of leftmost-then-longest match semantics, be sure to put the
114 # longest operators first (e.g., if = came before ==, == would get
114 # longest operators first (e.g., if = came before ==, == would get
115 # recognized as two instances of =).
115 # recognized as two instances of =).
116 Operator = group(r"\*\*=?", r">>=?", r"<<=?", r"!=",
116 Operator = group(r"\*\*=?", r">>=?", r"<<=?", r"!=",
117 r"//=?", r"->",
117 r"//=?", r"->",
118 r"[+\-*/%&|^=<>]=?",
118 r"[+\-*/%&|^=<>]=?",
119 r"~")
119 r"~")
120
120
121 Bracket = '[][(){}]'
121 Bracket = '[][(){}]'
122 Special = group(r'\r?\n', r'\.\.\.', r'[:;.,@]')
122 Special = group(r'\r?\n', r'\.\.\.', r'[:;.,@]')
123 Funny = group(Operator, Bracket, Special)
123 Funny = group(Operator, Bracket, Special)
124
124
125 PlainToken = group(Number, Funny, String, Name)
125 PlainToken = group(Number, Funny, String, Name)
126 Token = Ignore + PlainToken
126 Token = Ignore + PlainToken
127
127
128 # First (or only) line of ' or " string.
128 # First (or only) line of ' or " string.
129 ContStr = group(StringPrefix + r"'[^\n'\\]*(?:\\.[^\n'\\]*)*" +
129 ContStr = group(StringPrefix + r"'[^\n'\\]*(?:\\.[^\n'\\]*)*" +
130 group("'", r'\\\r?\n'),
130 group("'", r'\\\r?\n'),
131 StringPrefix + r'"[^\n"\\]*(?:\\.[^\n"\\]*)*' +
131 StringPrefix + r'"[^\n"\\]*(?:\\.[^\n"\\]*)*' +
132 group('"', r'\\\r?\n'))
132 group('"', r'\\\r?\n'))
133 PseudoExtras = group(r'\\\r?\n', Comment, Triple)
133 PseudoExtras = group(r'\\\r?\n', Comment, Triple)
134 PseudoToken = Whitespace + group(PseudoExtras, Number, Funny, ContStr, Name)
134 PseudoToken = Whitespace + group(PseudoExtras, Number, Funny, ContStr, Name)
135
135
136 def _compile(expr):
136 def _compile(expr):
137 return re.compile(expr, re.UNICODE)
137 return re.compile(expr, re.UNICODE)
138
138
139 tokenprog, pseudoprog, single3prog, double3prog = map(
139 tokenprog, pseudoprog, single3prog, double3prog = map(
140 _compile, (Token, PseudoToken, Single3, Double3))
140 _compile, (Token, PseudoToken, Single3, Double3))
141 endprogs = {"'": _compile(Single), '"': _compile(Double),
141 endprogs = {"'": _compile(Single), '"': _compile(Double),
142 "'''": single3prog, '"""': double3prog,
142 "'''": single3prog, '"""': double3prog,
143 "r'''": single3prog, 'r"""': double3prog,
143 "r'''": single3prog, 'r"""': double3prog,
144 "b'''": single3prog, 'b"""': double3prog,
144 "b'''": single3prog, 'b"""': double3prog,
145 "R'''": single3prog, 'R"""': double3prog,
145 "R'''": single3prog, 'R"""': double3prog,
146 "B'''": single3prog, 'B"""': double3prog,
146 "B'''": single3prog, 'B"""': double3prog,
147 "br'''": single3prog, 'br"""': double3prog,
147 "br'''": single3prog, 'br"""': double3prog,
148 "bR'''": single3prog, 'bR"""': double3prog,
148 "bR'''": single3prog, 'bR"""': double3prog,
149 "Br'''": single3prog, 'Br"""': double3prog,
149 "Br'''": single3prog, 'Br"""': double3prog,
150 "BR'''": single3prog, 'BR"""': double3prog,
150 "BR'''": single3prog, 'BR"""': double3prog,
151 'r': None, 'R': None, 'b': None, 'B': None}
151 'r': None, 'R': None, 'b': None, 'B': None}
152
152
153 triple_quoted = {}
153 triple_quoted = {}
154 for t in ("'''", '"""',
154 for t in ("'''", '"""',
155 "r'''", 'r"""', "R'''", 'R"""',
155 "r'''", 'r"""', "R'''", 'R"""',
156 "b'''", 'b"""', "B'''", 'B"""',
156 "b'''", 'b"""', "B'''", 'B"""',
157 "br'''", 'br"""', "Br'''", 'Br"""',
157 "br'''", 'br"""', "Br'''", 'Br"""',
158 "bR'''", 'bR"""', "BR'''", 'BR"""'):
158 "bR'''", 'bR"""', "BR'''", 'BR"""'):
159 triple_quoted[t] = t
159 triple_quoted[t] = t
160 single_quoted = {}
160 single_quoted = {}
161 for t in ("'", '"',
161 for t in ("'", '"',
162 "r'", 'r"', "R'", 'R"',
162 "r'", 'r"', "R'", 'R"',
163 "b'", 'b"', "B'", 'B"',
163 "b'", 'b"', "B'", 'B"',
164 "br'", 'br"', "Br'", 'Br"',
164 "br'", 'br"', "Br'", 'Br"',
165 "bR'", 'bR"', "BR'", 'BR"' ):
165 "bR'", 'bR"', "BR'", 'BR"' ):
166 single_quoted[t] = t
166 single_quoted[t] = t
167
167
168 if sys.version_info.minor >= 3:
168 if sys.version_info.minor >= 3:
169 # Python 3.3
169 # Python 3.3
170 for _prefix in ['rb', 'rB', 'Rb', 'RB', 'u', 'U']:
170 for _prefix in ['rb', 'rB', 'Rb', 'RB', 'u', 'U']:
171 _t2 = _prefix+'"""'
171 _t2 = _prefix+'"""'
172 endprogs[_t2] = double3prog
172 endprogs[_t2] = double3prog
173 triple_quoted[_t2] = _t2
173 triple_quoted[_t2] = _t2
174 _t1 = _prefix + "'''"
174 _t1 = _prefix + "'''"
175 endprogs[_t1] = single3prog
175 endprogs[_t1] = single3prog
176 triple_quoted[_t1] = _t1
176 triple_quoted[_t1] = _t1
177 single_quoted[_prefix+'"'] = _prefix+'"'
177 single_quoted[_prefix+'"'] = _prefix+'"'
178 single_quoted[_prefix+"'"] = _prefix+"'"
178 single_quoted[_prefix+"'"] = _prefix+"'"
179 del _prefix, _t2, _t1
179 del _prefix, _t2, _t1
180 endprogs['u'] = None
180 endprogs['u'] = None
181 endprogs['U'] = None
181 endprogs['U'] = None
182
182
183 del _compile
183 del _compile
184
184
185 tabsize = 8
185 tabsize = 8
186
186
187 class TokenError(Exception): pass
187 class TokenError(Exception): pass
188
188
189 class StopTokenizing(Exception): pass
189 class StopTokenizing(Exception): pass
190
190
191
191
192 class Untokenizer:
192 class Untokenizer:
193
193
194 def __init__(self):
194 def __init__(self):
195 self.tokens = []
195 self.tokens = []
196 self.prev_row = 1
196 self.prev_row = 1
197 self.prev_col = 0
197 self.prev_col = 0
198 self.encoding = 'utf-8'
198 self.encoding = 'utf-8'
199
199
200 def add_whitespace(self, tok_type, start):
200 def add_whitespace(self, tok_type, start):
201 row, col = start
201 row, col = start
202 assert row >= self.prev_row
202 assert row >= self.prev_row
203 col_offset = col - self.prev_col
203 col_offset = col - self.prev_col
204 if col_offset > 0:
204 if col_offset > 0:
205 self.tokens.append(" " * col_offset)
205 self.tokens.append(" " * col_offset)
206 elif row > self.prev_row and tok_type not in (NEWLINE, NL, ENDMARKER):
206 elif row > self.prev_row and tok_type not in (NEWLINE, NL, ENDMARKER):
207 # Line was backslash-continued.
207 # Line was backslash-continued.
208 self.tokens.append(" ")
208 self.tokens.append(" ")
209
209
210 def untokenize(self, tokens):
210 def untokenize(self, tokens):
211 iterable = iter(tokens)
211 iterable = iter(tokens)
212 for t in iterable:
212 for t in iterable:
213 if len(t) == 2:
213 if len(t) == 2:
214 self.compat(t, iterable)
214 self.compat(t, iterable)
215 break
215 break
216 tok_type, token, start, end = t[:4]
216 tok_type, token, start, end = t[:4]
217 if tok_type == ENCODING:
217 if tok_type == ENCODING:
218 self.encoding = token
218 self.encoding = token
219 continue
219 continue
220 self.add_whitespace(tok_type, start)
220 self.add_whitespace(tok_type, start)
221 self.tokens.append(token)
221 self.tokens.append(token)
222 self.prev_row, self.prev_col = end
222 self.prev_row, self.prev_col = end
223 if tok_type in (NEWLINE, NL):
223 if tok_type in (NEWLINE, NL):
224 self.prev_row += 1
224 self.prev_row += 1
225 self.prev_col = 0
225 self.prev_col = 0
226 return "".join(self.tokens)
226 return "".join(self.tokens)
227
227
228 def compat(self, token, iterable):
228 def compat(self, token, iterable):
229 # This import is here to avoid problems when the itertools
229 # This import is here to avoid problems when the itertools
230 # module is not built yet and tokenize is imported.
230 # module is not built yet and tokenize is imported.
231 from itertools import chain
231 from itertools import chain
232 startline = False
232 startline = False
233 prevstring = False
233 prevstring = False
234 indents = []
234 indents = []
235 toks_append = self.tokens.append
235 toks_append = self.tokens.append
236
236
237 for tok in chain([token], iterable):
237 for tok in chain([token], iterable):
238 toknum, tokval = tok[:2]
238 toknum, tokval = tok[:2]
239 if toknum == ENCODING:
239 if toknum == ENCODING:
240 self.encoding = tokval
240 self.encoding = tokval
241 continue
241 continue
242
242
243 if toknum in (NAME, NUMBER):
243 if toknum in (NAME, NUMBER):
244 tokval += ' '
244 tokval += ' '
245
245
246 # Insert a space between two consecutive strings
246 # Insert a space between two consecutive strings
247 if toknum == STRING:
247 if toknum == STRING:
248 if prevstring:
248 if prevstring:
249 tokval = ' ' + tokval
249 tokval = ' ' + tokval
250 prevstring = True
250 prevstring = True
251 else:
251 else:
252 prevstring = False
252 prevstring = False
253
253
254 if toknum == INDENT:
254 if toknum == INDENT:
255 indents.append(tokval)
255 indents.append(tokval)
256 continue
256 continue
257 elif toknum == DEDENT:
257 elif toknum == DEDENT:
258 indents.pop()
258 indents.pop()
259 continue
259 continue
260 elif toknum in (NEWLINE, NL):
260 elif toknum in (NEWLINE, NL):
261 startline = True
261 startline = True
262 elif startline and indents:
262 elif startline and indents:
263 toks_append(indents[-1])
263 toks_append(indents[-1])
264 startline = False
264 startline = False
265 toks_append(tokval)
265 toks_append(tokval)
266
266
267
267
268 def untokenize(tokens):
268 def untokenize(tokens):
269 """
269 """
270 Convert ``tokens`` (an iterable) back into Python source code. Return
270 Convert ``tokens`` (an iterable) back into Python source code. Return
271 a bytes object, encoded using the encoding specified by the last
271 a bytes object, encoded using the encoding specified by the last
272 ENCODING token in ``tokens``, or UTF-8 if no ENCODING token is found.
272 ENCODING token in ``tokens``, or UTF-8 if no ENCODING token is found.
273
273
274 The result is guaranteed to tokenize back to match the input so that
274 The result is guaranteed to tokenize back to match the input so that
275 the conversion is lossless and round-trips are assured. The
275 the conversion is lossless and round-trips are assured. The
276 guarantee applies only to the token type and token string as the
276 guarantee applies only to the token type and token string as the
277 spacing between tokens (column positions) may change.
277 spacing between tokens (column positions) may change.
278
278
279 :func:`untokenize` has two modes. If the input tokens are sequences
279 :func:`untokenize` has two modes. If the input tokens are sequences
280 of length 2 (``type``, ``string``) then spaces are added as necessary to
280 of length 2 (``type``, ``string``) then spaces are added as necessary to
281 preserve the round-trip property.
281 preserve the round-trip property.
282
282
283 If the input tokens are sequences of length 4 or more (``type``,
283 If the input tokens are sequences of length 4 or more (``type``,
284 ``string``, ``start``, ``end``), as returned by :func:`tokenize`, then
284 ``string``, ``start``, ``end``), as returned by :func:`tokenize`, then
285 spaces are added so that each token appears in the result at the
285 spaces are added so that each token appears in the result at the
286 position indicated by ``start`` and ``end``, if possible.
286 position indicated by ``start`` and ``end``, if possible.
287 """
287 """
288 return Untokenizer().untokenize(tokens)
288 return Untokenizer().untokenize(tokens)
289
289
290
290
291 def _get_normal_name(orig_enc):
291 def _get_normal_name(orig_enc):
292 """Imitates get_normal_name in tokenizer.c."""
292 """Imitates get_normal_name in tokenizer.c."""
293 # Only care about the first 12 characters.
293 # Only care about the first 12 characters.
294 enc = orig_enc[:12].lower().replace("_", "-")
294 enc = orig_enc[:12].lower().replace("_", "-")
295 if enc == "utf-8" or enc.startswith("utf-8-"):
295 if enc == "utf-8" or enc.startswith("utf-8-"):
296 return "utf-8"
296 return "utf-8"
297 if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \
297 if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \
298 enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")):
298 enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")):
299 return "iso-8859-1"
299 return "iso-8859-1"
300 return orig_enc
300 return orig_enc
301
301
302 def detect_encoding(readline):
302 def detect_encoding(readline):
303 """
303 """
304 The detect_encoding() function is used to detect the encoding that should
304 The detect_encoding() function is used to detect the encoding that should
305 be used to decode a Python source file. It requires one argment, readline,
305 be used to decode a Python source file. It requires one argment, readline,
306 in the same way as the tokenize() generator.
306 in the same way as the tokenize() generator.
307
307
308 It will call readline a maximum of twice, and return the encoding used
308 It will call readline a maximum of twice, and return the encoding used
309 (as a string) and a list of any lines (left as bytes) it has read in.
309 (as a string) and a list of any lines (left as bytes) it has read in.
310
310
311 It detects the encoding from the presence of a utf-8 bom or an encoding
311 It detects the encoding from the presence of a utf-8 bom or an encoding
312 cookie as specified in pep-0263. If both a bom and a cookie are present,
312 cookie as specified in pep-0263. If both a bom and a cookie are present,
313 but disagree, a SyntaxError will be raised. If the encoding cookie is an
313 but disagree, a SyntaxError will be raised. If the encoding cookie is an
314 invalid charset, raise a SyntaxError. Note that if a utf-8 bom is found,
314 invalid charset, raise a SyntaxError. Note that if a utf-8 bom is found,
315 'utf-8-sig' is returned.
315 'utf-8-sig' is returned.
316
316
317 If no encoding is specified, then the default of 'utf-8' will be returned.
317 If no encoding is specified, then the default of 'utf-8' will be returned.
318 """
318 """
319 bom_found = False
319 bom_found = False
320 encoding = None
320 encoding = None
321 default = 'utf-8'
321 default = 'utf-8'
322 def read_or_stop():
322 def read_or_stop():
323 try:
323 try:
324 return readline()
324 return readline()
325 except StopIteration:
325 except StopIteration:
326 return b''
326 return b''
327
327
328 def find_cookie(line):
328 def find_cookie(line):
329 try:
329 try:
330 # Decode as UTF-8. Either the line is an encoding declaration,
330 # Decode as UTF-8. Either the line is an encoding declaration,
331 # in which case it should be pure ASCII, or it must be UTF-8
331 # in which case it should be pure ASCII, or it must be UTF-8
332 # per default encoding.
332 # per default encoding.
333 line_string = line.decode('utf-8')
333 line_string = line.decode('utf-8')
334 except UnicodeDecodeError:
334 except UnicodeDecodeError:
335 raise SyntaxError("invalid or missing encoding declaration")
335 raise SyntaxError("invalid or missing encoding declaration")
336
336
337 matches = cookie_re.findall(line_string)
337 matches = cookie_re.findall(line_string)
338 if not matches:
338 if not matches:
339 return None
339 return None
340 encoding = _get_normal_name(matches[0])
340 encoding = _get_normal_name(matches[0])
341 try:
341 try:
342 codec = lookup(encoding)
342 codec = lookup(encoding)
343 except LookupError:
343 except LookupError:
344 # This behaviour mimics the Python interpreter
344 # This behaviour mimics the Python interpreter
345 raise SyntaxError("unknown encoding: " + encoding)
345 raise SyntaxError("unknown encoding: " + encoding)
346
346
347 if bom_found:
347 if bom_found:
348 if encoding != 'utf-8':
348 if encoding != 'utf-8':
349 # This behaviour mimics the Python interpreter
349 # This behaviour mimics the Python interpreter
350 raise SyntaxError('encoding problem: utf-8')
350 raise SyntaxError('encoding problem: utf-8')
351 encoding += '-sig'
351 encoding += '-sig'
352 return encoding
352 return encoding
353
353
354 first = read_or_stop()
354 first = read_or_stop()
355 if first.startswith(BOM_UTF8):
355 if first.startswith(BOM_UTF8):
356 bom_found = True
356 bom_found = True
357 first = first[3:]
357 first = first[3:]
358 default = 'utf-8-sig'
358 default = 'utf-8-sig'
359 if not first:
359 if not first:
360 return default, []
360 return default, []
361
361
362 encoding = find_cookie(first)
362 encoding = find_cookie(first)
363 if encoding:
363 if encoding:
364 return encoding, [first]
364 return encoding, [first]
365
365
366 second = read_or_stop()
366 second = read_or_stop()
367 if not second:
367 if not second:
368 return default, [first]
368 return default, [first]
369
369
370 encoding = find_cookie(second)
370 encoding = find_cookie(second)
371 if encoding:
371 if encoding:
372 return encoding, [first, second]
372 return encoding, [first, second]
373
373
374 return default, [first, second]
374 return default, [first, second]
375
375
376
376
377 def open(filename):
377 def open(filename):
378 """Open a file in read only mode using the encoding detected by
378 """Open a file in read only mode using the encoding detected by
379 detect_encoding().
379 detect_encoding().
380 """
380 """
381 buffer = builtins.open(filename, 'rb')
381 buffer = builtins.open(filename, 'rb')
382 encoding, lines = detect_encoding(buffer.readline)
382 encoding, lines = detect_encoding(buffer.readline)
383 buffer.seek(0)
383 buffer.seek(0)
384 text = TextIOWrapper(buffer, encoding, line_buffering=True)
384 text = TextIOWrapper(buffer, encoding, line_buffering=True)
385 text.mode = 'r'
385 text.mode = 'r'
386 return text
386 return text
387
387
388
388
389 def tokenize(readline):
389 def tokenize(readline):
390 """
390 """
391 The tokenize() generator requires one argment, readline, which
391 The tokenize() generator requires one argment, readline, which
392 must be a callable object which provides the same interface as the
392 must be a callable object which provides the same interface as the
393 readline() method of built-in file objects. Each call to the function
393 readline() method of built-in file objects. Each call to the function
394 should return one line of input as bytes. Alternately, readline
394 should return one line of input as bytes. Alternately, readline
395 can be a callable function terminating with StopIteration:
395 can be a callable function terminating with :class:`StopIteration`::
396
396 readline = open(myfile, 'rb').__next__ # Example of alternate readline
397 readline = open(myfile, 'rb').__next__ # Example of alternate readline
397
398
398 The generator produces 5-tuples with these members: the token type; the
399 The generator produces 5-tuples with these members: the token type; the
399 token string; a 2-tuple (srow, scol) of ints specifying the row and
400 token string; a 2-tuple (srow, scol) of ints specifying the row and
400 column where the token begins in the source; a 2-tuple (erow, ecol) of
401 column where the token begins in the source; a 2-tuple (erow, ecol) of
401 ints specifying the row and column where the token ends in the source;
402 ints specifying the row and column where the token ends in the source;
402 and the line on which the token was found. The line passed is the
403 and the line on which the token was found. The line passed is the
403 logical line; continuation lines are included.
404 logical line; continuation lines are included.
404
405
405 The first token sequence will always be an ENCODING token
406 The first token sequence will always be an ENCODING token
406 which tells you which encoding was used to decode the bytes stream.
407 which tells you which encoding was used to decode the bytes stream.
407 """
408 """
408 # This import is here to avoid problems when the itertools module is not
409 # This import is here to avoid problems when the itertools module is not
409 # built yet and tokenize is imported.
410 # built yet and tokenize is imported.
410 from itertools import chain, repeat
411 from itertools import chain, repeat
411 encoding, consumed = detect_encoding(readline)
412 encoding, consumed = detect_encoding(readline)
412 rl_gen = iter(readline, b"")
413 rl_gen = iter(readline, b"")
413 empty = repeat(b"")
414 empty = repeat(b"")
414 return _tokenize(chain(consumed, rl_gen, empty).__next__, encoding)
415 return _tokenize(chain(consumed, rl_gen, empty).__next__, encoding)
415
416
416
417
417 def _tokenize(readline, encoding):
418 def _tokenize(readline, encoding):
418 lnum = parenlev = continued = 0
419 lnum = parenlev = continued = 0
419 numchars = '0123456789'
420 numchars = '0123456789'
420 contstr, needcont = '', 0
421 contstr, needcont = '', 0
421 contline = None
422 contline = None
422 indents = [0]
423 indents = [0]
423
424
424 if encoding is not None:
425 if encoding is not None:
425 if encoding == "utf-8-sig":
426 if encoding == "utf-8-sig":
426 # BOM will already have been stripped.
427 # BOM will already have been stripped.
427 encoding = "utf-8"
428 encoding = "utf-8"
428 yield TokenInfo(ENCODING, encoding, (0, 0), (0, 0), '')
429 yield TokenInfo(ENCODING, encoding, (0, 0), (0, 0), '')
429 while True: # loop over lines in stream
430 while True: # loop over lines in stream
430 try:
431 try:
431 line = readline()
432 line = readline()
432 except StopIteration:
433 except StopIteration:
433 line = b''
434 line = b''
434
435
435 if encoding is not None:
436 if encoding is not None:
436 line = line.decode(encoding)
437 line = line.decode(encoding)
437 lnum += 1
438 lnum += 1
438 pos, max = 0, len(line)
439 pos, max = 0, len(line)
439
440
440 if contstr: # continued string
441 if contstr: # continued string
441 if not line:
442 if not line:
442 raise TokenError("EOF in multi-line string", strstart)
443 raise TokenError("EOF in multi-line string", strstart)
443 endmatch = endprog.match(line)
444 endmatch = endprog.match(line)
444 if endmatch:
445 if endmatch:
445 pos = end = endmatch.end(0)
446 pos = end = endmatch.end(0)
446 yield TokenInfo(STRING, contstr + line[:end],
447 yield TokenInfo(STRING, contstr + line[:end],
447 strstart, (lnum, end), contline + line)
448 strstart, (lnum, end), contline + line)
448 contstr, needcont = '', 0
449 contstr, needcont = '', 0
449 contline = None
450 contline = None
450 elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n':
451 elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n':
451 yield TokenInfo(ERRORTOKEN, contstr + line,
452 yield TokenInfo(ERRORTOKEN, contstr + line,
452 strstart, (lnum, len(line)), contline)
453 strstart, (lnum, len(line)), contline)
453 contstr = ''
454 contstr = ''
454 contline = None
455 contline = None
455 continue
456 continue
456 else:
457 else:
457 contstr = contstr + line
458 contstr = contstr + line
458 contline = contline + line
459 contline = contline + line
459 continue
460 continue
460
461
461 elif parenlev == 0 and not continued: # new statement
462 elif parenlev == 0 and not continued: # new statement
462 if not line: break
463 if not line: break
463 column = 0
464 column = 0
464 while pos < max: # measure leading whitespace
465 while pos < max: # measure leading whitespace
465 if line[pos] == ' ':
466 if line[pos] == ' ':
466 column += 1
467 column += 1
467 elif line[pos] == '\t':
468 elif line[pos] == '\t':
468 column = (column//tabsize + 1)*tabsize
469 column = (column//tabsize + 1)*tabsize
469 elif line[pos] == '\f':
470 elif line[pos] == '\f':
470 column = 0
471 column = 0
471 else:
472 else:
472 break
473 break
473 pos += 1
474 pos += 1
474 if pos == max:
475 if pos == max:
475 break
476 break
476
477
477 if line[pos] in '#\r\n': # skip comments or blank lines
478 if line[pos] in '#\r\n': # skip comments or blank lines
478 if line[pos] == '#':
479 if line[pos] == '#':
479 comment_token = line[pos:].rstrip('\r\n')
480 comment_token = line[pos:].rstrip('\r\n')
480 nl_pos = pos + len(comment_token)
481 nl_pos = pos + len(comment_token)
481 yield TokenInfo(COMMENT, comment_token,
482 yield TokenInfo(COMMENT, comment_token,
482 (lnum, pos), (lnum, pos + len(comment_token)), line)
483 (lnum, pos), (lnum, pos + len(comment_token)), line)
483 yield TokenInfo(NEWLINE, line[nl_pos:],
484 yield TokenInfo(NEWLINE, line[nl_pos:],
484 (lnum, nl_pos), (lnum, len(line)), line)
485 (lnum, nl_pos), (lnum, len(line)), line)
485 else:
486 else:
486 yield TokenInfo(NEWLINE, line[pos:],
487 yield TokenInfo(NEWLINE, line[pos:],
487 (lnum, pos), (lnum, len(line)), line)
488 (lnum, pos), (lnum, len(line)), line)
488 continue
489 continue
489
490
490 if column > indents[-1]: # count indents or dedents
491 if column > indents[-1]: # count indents or dedents
491 indents.append(column)
492 indents.append(column)
492 yield TokenInfo(INDENT, line[:pos], (lnum, 0), (lnum, pos), line)
493 yield TokenInfo(INDENT, line[:pos], (lnum, 0), (lnum, pos), line)
493 while column < indents[-1]:
494 while column < indents[-1]:
494 if column not in indents:
495 if column not in indents:
495 raise IndentationError(
496 raise IndentationError(
496 "unindent does not match any outer indentation level",
497 "unindent does not match any outer indentation level",
497 ("<tokenize>", lnum, pos, line))
498 ("<tokenize>", lnum, pos, line))
498 indents = indents[:-1]
499 indents = indents[:-1]
499 yield TokenInfo(DEDENT, '', (lnum, pos), (lnum, pos), line)
500 yield TokenInfo(DEDENT, '', (lnum, pos), (lnum, pos), line)
500
501
501 else: # continued statement
502 else: # continued statement
502 if not line:
503 if not line:
503 raise TokenError("EOF in multi-line statement", (lnum, 0))
504 raise TokenError("EOF in multi-line statement", (lnum, 0))
504 continued = 0
505 continued = 0
505
506
506 while pos < max:
507 while pos < max:
507 pseudomatch = pseudoprog.match(line, pos)
508 pseudomatch = pseudoprog.match(line, pos)
508 if pseudomatch: # scan for tokens
509 if pseudomatch: # scan for tokens
509 start, end = pseudomatch.span(1)
510 start, end = pseudomatch.span(1)
510 spos, epos, pos = (lnum, start), (lnum, end), end
511 spos, epos, pos = (lnum, start), (lnum, end), end
511 token, initial = line[start:end], line[start]
512 token, initial = line[start:end], line[start]
512
513
513 if (initial in numchars or # ordinary number
514 if (initial in numchars or # ordinary number
514 (initial == '.' and token != '.' and token != '...')):
515 (initial == '.' and token != '.' and token != '...')):
515 yield TokenInfo(NUMBER, token, spos, epos, line)
516 yield TokenInfo(NUMBER, token, spos, epos, line)
516 elif initial in '\r\n':
517 elif initial in '\r\n':
517 yield TokenInfo(NL if parenlev > 0 else NEWLINE,
518 yield TokenInfo(NL if parenlev > 0 else NEWLINE,
518 token, spos, epos, line)
519 token, spos, epos, line)
519 elif initial == '#':
520 elif initial == '#':
520 assert not token.endswith("\n")
521 assert not token.endswith("\n")
521 yield TokenInfo(COMMENT, token, spos, epos, line)
522 yield TokenInfo(COMMENT, token, spos, epos, line)
522 elif token in triple_quoted:
523 elif token in triple_quoted:
523 endprog = endprogs[token]
524 endprog = endprogs[token]
524 endmatch = endprog.match(line, pos)
525 endmatch = endprog.match(line, pos)
525 if endmatch: # all on one line
526 if endmatch: # all on one line
526 pos = endmatch.end(0)
527 pos = endmatch.end(0)
527 token = line[start:pos]
528 token = line[start:pos]
528 yield TokenInfo(STRING, token, spos, (lnum, pos), line)
529 yield TokenInfo(STRING, token, spos, (lnum, pos), line)
529 else:
530 else:
530 strstart = (lnum, start) # multiple lines
531 strstart = (lnum, start) # multiple lines
531 contstr = line[start:]
532 contstr = line[start:]
532 contline = line
533 contline = line
533 break
534 break
534 elif initial in single_quoted or \
535 elif initial in single_quoted or \
535 token[:2] in single_quoted or \
536 token[:2] in single_quoted or \
536 token[:3] in single_quoted:
537 token[:3] in single_quoted:
537 if token[-1] == '\n': # continued string
538 if token[-1] == '\n': # continued string
538 strstart = (lnum, start)
539 strstart = (lnum, start)
539 endprog = (endprogs[initial] or endprogs[token[1]] or
540 endprog = (endprogs[initial] or endprogs[token[1]] or
540 endprogs[token[2]])
541 endprogs[token[2]])
541 contstr, needcont = line[start:], 1
542 contstr, needcont = line[start:], 1
542 contline = line
543 contline = line
543 break
544 break
544 else: # ordinary string
545 else: # ordinary string
545 yield TokenInfo(STRING, token, spos, epos, line)
546 yield TokenInfo(STRING, token, spos, epos, line)
546 elif initial.isidentifier(): # ordinary name
547 elif initial.isidentifier(): # ordinary name
547 yield TokenInfo(NAME, token, spos, epos, line)
548 yield TokenInfo(NAME, token, spos, epos, line)
548 elif initial == '\\': # continued stmt
549 elif initial == '\\': # continued stmt
549 continued = 1
550 continued = 1
550 else:
551 else:
551 if initial in '([{':
552 if initial in '([{':
552 parenlev += 1
553 parenlev += 1
553 elif initial in ')]}':
554 elif initial in ')]}':
554 parenlev -= 1
555 parenlev -= 1
555 yield TokenInfo(OP, token, spos, epos, line)
556 yield TokenInfo(OP, token, spos, epos, line)
556 else:
557 else:
557 yield TokenInfo(ERRORTOKEN, line[pos],
558 yield TokenInfo(ERRORTOKEN, line[pos],
558 (lnum, pos), (lnum, pos+1), line)
559 (lnum, pos), (lnum, pos+1), line)
559 pos += 1
560 pos += 1
560
561
561 for indent in indents[1:]: # pop remaining indent levels
562 for indent in indents[1:]: # pop remaining indent levels
562 yield TokenInfo(DEDENT, '', (lnum, 0), (lnum, 0), '')
563 yield TokenInfo(DEDENT, '', (lnum, 0), (lnum, 0), '')
563 yield TokenInfo(ENDMARKER, '', (lnum, 0), (lnum, 0), '')
564 yield TokenInfo(ENDMARKER, '', (lnum, 0), (lnum, 0), '')
564
565
565
566
566 # An undocumented, backwards compatible, API for all the places in the standard
567 # An undocumented, backwards compatible, API for all the places in the standard
567 # library that expect to be able to use tokenize with strings
568 # library that expect to be able to use tokenize with strings
568 def generate_tokens(readline):
569 def generate_tokens(readline):
569 return _tokenize(readline, None)
570 return _tokenize(readline, None)
570
571
571 if __name__ == "__main__":
572 if __name__ == "__main__":
572 # Quick sanity check
573 # Quick sanity check
573 s = b'''def parseline(self, line):
574 s = b'''def parseline(self, line):
574 """Parse the line into a command name and a string containing
575 """Parse the line into a command name and a string containing
575 the arguments. Returns a tuple containing (command, args, line).
576 the arguments. Returns a tuple containing (command, args, line).
576 'command' and 'args' may be None if the line couldn't be parsed.
577 'command' and 'args' may be None if the line couldn't be parsed.
577 """
578 """
578 line = line.strip()
579 line = line.strip()
579 if not line:
580 if not line:
580 return None, None, line
581 return None, None, line
581 elif line[0] == '?':
582 elif line[0] == '?':
582 line = 'help ' + line[1:]
583 line = 'help ' + line[1:]
583 elif line[0] == '!':
584 elif line[0] == '!':
584 if hasattr(self, 'do_shell'):
585 if hasattr(self, 'do_shell'):
585 line = 'shell ' + line[1:]
586 line = 'shell ' + line[1:]
586 else:
587 else:
587 return None, None, line
588 return None, None, line
588 i, n = 0, len(line)
589 i, n = 0, len(line)
589 while i < n and line[i] in self.identchars: i = i+1
590 while i < n and line[i] in self.identchars: i = i+1
590 cmd, arg = line[:i], line[i:].strip()
591 cmd, arg = line[:i], line[i:].strip()
591 return cmd, arg, line
592 return cmd, arg, line
592 '''
593 '''
593 for tok in tokenize(iter(s.splitlines()).__next__):
594 for tok in tokenize(iter(s.splitlines()).__next__):
594 print(tok)
595 print(tok)
@@ -1,127 +1,127 b''
1 """Token-related utilities"""
1 """Token-related utilities"""
2
2
3 # Copyright (c) IPython Development Team.
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
4 # Distributed under the terms of the Modified BSD License.
5
5
6
6
7 from collections import namedtuple
7 from collections import namedtuple
8 from io import StringIO
8 from io import StringIO
9 from keyword import iskeyword
9 from keyword import iskeyword
10
10
11 from . import tokenize2
11 from . import tokenize2
12 from .py3compat import cast_unicode_py2
12 from .py3compat import cast_unicode_py2
13
13
14 Token = namedtuple('Token', ['token', 'text', 'start', 'end', 'line'])
14 Token = namedtuple('Token', ['token', 'text', 'start', 'end', 'line'])
15
15
16 def generate_tokens(readline):
16 def generate_tokens(readline):
17 """wrap generate_tokens to catch EOF errors"""
17 """wrap generate_tokens to catch EOF errors"""
18 try:
18 try:
19 for token in tokenize2.generate_tokens(readline):
19 for token in tokenize2.generate_tokens(readline):
20 yield token
20 yield token
21 except tokenize2.TokenError:
21 except tokenize2.TokenError:
22 # catch EOF error
22 # catch EOF error
23 return
23 return
24
24
25 def line_at_cursor(cell, cursor_pos=0):
25 def line_at_cursor(cell, cursor_pos=0):
26 """Return the line in a cell at a given cursor position
26 """Return the line in a cell at a given cursor position
27
27
28 Used for calling line-based APIs that don't support multi-line input, yet.
28 Used for calling line-based APIs that don't support multi-line input, yet.
29
29
30 Parameters
30 Parameters
31 ----------
31 ----------
32
32
33 cell: str
33 cell: str
34 multiline block of text
34 multiline block of text
35 cursor_pos: integer
35 cursor_pos: integer
36 the cursor position
36 the cursor position
37
37
38 Returns
38 Returns
39 -------
39 -------
40
40
41 (line, offset): (text, integer)
41 (line, offset): (string, integer)
42 The line with the current cursor, and the character offset of the start of the line.
42 The line with the current cursor, and the character offset of the start of the line.
43 """
43 """
44 offset = 0
44 offset = 0
45 lines = cell.splitlines(True)
45 lines = cell.splitlines(True)
46 for line in lines:
46 for line in lines:
47 next_offset = offset + len(line)
47 next_offset = offset + len(line)
48 if next_offset >= cursor_pos:
48 if next_offset >= cursor_pos:
49 break
49 break
50 offset = next_offset
50 offset = next_offset
51 else:
51 else:
52 line = ""
52 line = ""
53 return (line, offset)
53 return (line, offset)
54
54
55 def token_at_cursor(cell, cursor_pos=0):
55 def token_at_cursor(cell, cursor_pos=0):
56 """Get the token at a given cursor
56 """Get the token at a given cursor
57
57
58 Used for introspection.
58 Used for introspection.
59
59
60 Function calls are prioritized, so the token for the callable will be returned
60 Function calls are prioritized, so the token for the callable will be returned
61 if the cursor is anywhere inside the call.
61 if the cursor is anywhere inside the call.
62
62
63 Parameters
63 Parameters
64 ----------
64 ----------
65
65
66 cell : unicode
66 cell : unicode
67 A block of Python code
67 A block of Python code
68 cursor_pos : int
68 cursor_pos : int
69 The location of the cursor in the block where the token should be found
69 The location of the cursor in the block where the token should be found
70 """
70 """
71 cell = cast_unicode_py2(cell)
71 cell = cast_unicode_py2(cell)
72 names = []
72 names = []
73 tokens = []
73 tokens = []
74 call_names = []
74 call_names = []
75
75
76 offsets = {1: 0} # lines start at 1
76 offsets = {1: 0} # lines start at 1
77 for tup in generate_tokens(StringIO(cell).readline):
77 for tup in generate_tokens(StringIO(cell).readline):
78
78
79 tok = Token(*tup)
79 tok = Token(*tup)
80
80
81 # token, text, start, end, line = tup
81 # token, text, start, end, line = tup
82 start_line, start_col = tok.start
82 start_line, start_col = tok.start
83 end_line, end_col = tok.end
83 end_line, end_col = tok.end
84 if end_line + 1 not in offsets:
84 if end_line + 1 not in offsets:
85 # keep track of offsets for each line
85 # keep track of offsets for each line
86 lines = tok.line.splitlines(True)
86 lines = tok.line.splitlines(True)
87 for lineno, line in enumerate(lines, start_line + 1):
87 for lineno, line in enumerate(lines, start_line + 1):
88 if lineno not in offsets:
88 if lineno not in offsets:
89 offsets[lineno] = offsets[lineno-1] + len(line)
89 offsets[lineno] = offsets[lineno-1] + len(line)
90
90
91 offset = offsets[start_line]
91 offset = offsets[start_line]
92 # allow '|foo' to find 'foo' at the beginning of a line
92 # allow '|foo' to find 'foo' at the beginning of a line
93 boundary = cursor_pos + 1 if start_col == 0 else cursor_pos
93 boundary = cursor_pos + 1 if start_col == 0 else cursor_pos
94 if offset + start_col >= boundary:
94 if offset + start_col >= boundary:
95 # current token starts after the cursor,
95 # current token starts after the cursor,
96 # don't consume it
96 # don't consume it
97 break
97 break
98
98
99 if tok.token == tokenize2.NAME and not iskeyword(tok.text):
99 if tok.token == tokenize2.NAME and not iskeyword(tok.text):
100 if names and tokens and tokens[-1].token == tokenize2.OP and tokens[-1].text == '.':
100 if names and tokens and tokens[-1].token == tokenize2.OP and tokens[-1].text == '.':
101 names[-1] = "%s.%s" % (names[-1], tok.text)
101 names[-1] = "%s.%s" % (names[-1], tok.text)
102 else:
102 else:
103 names.append(tok.text)
103 names.append(tok.text)
104 elif tok.token == tokenize2.OP:
104 elif tok.token == tokenize2.OP:
105 if tok.text == '=' and names:
105 if tok.text == '=' and names:
106 # don't inspect the lhs of an assignment
106 # don't inspect the lhs of an assignment
107 names.pop(-1)
107 names.pop(-1)
108 if tok.text == '(' and names:
108 if tok.text == '(' and names:
109 # if we are inside a function call, inspect the function
109 # if we are inside a function call, inspect the function
110 call_names.append(names[-1])
110 call_names.append(names[-1])
111 elif tok.text == ')' and call_names:
111 elif tok.text == ')' and call_names:
112 call_names.pop(-1)
112 call_names.pop(-1)
113
113
114 tokens.append(tok)
114 tokens.append(tok)
115
115
116 if offsets[end_line] + end_col > cursor_pos:
116 if offsets[end_line] + end_col > cursor_pos:
117 # we found the cursor, stop reading
117 # we found the cursor, stop reading
118 break
118 break
119
119
120 if call_names:
120 if call_names:
121 return call_names[-1]
121 return call_names[-1]
122 elif names:
122 elif names:
123 return names[-1]
123 return names[-1]
124 else:
124 else:
125 return ''
125 return ''
126
126
127
127
@@ -1,230 +1,230 b''
1 =======================
1 =======================
2 Specific config details
2 Specific config details
3 =======================
3 =======================
4
4
5 .. _custom_prompts:
5 .. _custom_prompts:
6
6
7 Custom Prompts
7 Custom Prompts
8 ==============
8 ==============
9
9
10 .. versionchanged:: 5.0
10 .. versionchanged:: 5.0
11
11
12 From IPython 5, prompts are produced as a list of Pygments tokens, which are
12 From IPython 5, prompts are produced as a list of Pygments tokens, which are
13 tuples of (token_type, text). You can customise prompts by writing a method
13 tuples of (token_type, text). You can customise prompts by writing a method
14 which generates a list of tokens.
14 which generates a list of tokens.
15
15
16 There are four kinds of prompt:
16 There are four kinds of prompt:
17
17
18 * The **in** prompt is shown before the first line of input
18 * The **in** prompt is shown before the first line of input
19 (default like ``In [1]:``).
19 (default like ``In [1]:``).
20 * The **continuation** prompt is shown before further lines of input
20 * The **continuation** prompt is shown before further lines of input
21 (default like ``...:``).
21 (default like ``...:``).
22 * The **rewrite** prompt is shown to highlight how special syntax has been
22 * The **rewrite** prompt is shown to highlight how special syntax has been
23 interpreted (default like ``----->``).
23 interpreted (default like ``----->``).
24 * The **out** prompt is shown before the result from evaluating the input
24 * The **out** prompt is shown before the result from evaluating the input
25 (default like ``Out[1]:``).
25 (default like ``Out[1]:``).
26
26
27 Custom prompts are supplied together as a class. If you want to customise only
27 Custom prompts are supplied together as a class. If you want to customise only
28 some of the prompts, inherit from :class:`IPython.terminal.prompts.Prompts`,
28 some of the prompts, inherit from :class:`IPython.terminal.prompts.Prompts`,
29 which defines the defaults. The required interface is like this:
29 which defines the defaults. The required interface is like this:
30
30
31 .. class:: MyPrompts(shell)
31 .. class:: MyPrompts(shell)
32
32
33 Prompt style definition. *shell* is a reference to the
33 Prompt style definition. *shell* is a reference to the
34 :class:`~.TerminalInteractiveShell` instance.
34 :class:`~.TerminalInteractiveShell` instance.
35
35
36 .. method:: in_prompt_tokens(cli=None)
36 .. method:: in_prompt_tokens(cli=None)
37 continuation_prompt_tokens(self, cli=None, width=None)
37 continuation_prompt_tokens(self, cli=None, width=None)
38 rewrite_prompt_tokens()
38 rewrite_prompt_tokens()
39 out_prompt_tokens()
39 out_prompt_tokens()
40
40
41 Return the respective prompts as lists of ``(token_type, text)`` tuples.
41 Return the respective prompts as lists of ``(token_type, text)`` tuples.
42
42
43 For continuation prompts, *width* is an integer representing the width of
43 For continuation prompts, *width* is an integer representing the width of
44 the prompt area in terminal columns.
44 the prompt area in terminal columns.
45
45
46 *cli*, where used, is the prompt_toolkit ``CommandLineInterface`` instance.
46 *cli*, where used, is the prompt_toolkit ``CommandLineInterface`` instance.
47 This is mainly for compatibility with the API prompt_toolkit expects.
47 This is mainly for compatibility with the API prompt_toolkit expects.
48
48
49 Here is an example Prompt class that will show the current working directory
49 Here is an example Prompt class that will show the current working directory
50 in the input prompt:
50 in the input prompt:
51
51
52 .. code-block:: python
52 .. code-block:: python
53
53
54 from IPython.terminal.prompts import Prompts, Token
54 from IPython.terminal.prompts import Prompts, Token
55 import os
55 import os
56
56
57 class MyPrompt(Prompts):
57 class MyPrompt(Prompts):
58 def in_prompt_tokens(self, cli=None):
58 def in_prompt_tokens(self, cli=None):
59 return [(Token, os.getcwd()),
59 return [(Token, os.getcwd()),
60 (Token.Prompt, ' >>>')]
60 (Token.Prompt, ' >>>')]
61
61
62 To set the new prompt, assign it to the ``prompts`` attribute of the IPython
62 To set the new prompt, assign it to the ``prompts`` attribute of the IPython
63 shell:
63 shell:
64
64
65 .. code-block:: python
65 .. code-block:: python
66
66
67 In [2]: ip = get_ipython()
67 In [2]: ip = get_ipython()
68 ...: ip.prompts = MyPrompt(ip)
68 ...: ip.prompts = MyPrompt(ip)
69
69
70 /home/bob >>> # it works
70 /home/bob >>> # it works
71
71
72 See ``IPython/example/utils/cwd_prompt.py`` for an example of how to write an
72 See ``IPython/example/utils/cwd_prompt.py`` for an example of how to write an
73 extensions to customise prompts.
73 extensions to customise prompts.
74
74
75 Inside IPython or in a startup script, you can use a custom prompts class
75 Inside IPython or in a startup script, you can use a custom prompts class
76 by setting ``get_ipython().prompts`` to an *instance* of the class.
76 by setting ``get_ipython().prompts`` to an *instance* of the class.
77 In configuration, ``TerminalInteractiveShell.prompts_class`` may be set to
77 In configuration, ``TerminalInteractiveShell.prompts_class`` may be set to
78 either the class object, or a string of its full importable name.
78 either the class object, or a string of its full importable name.
79
79
80 To include invisible terminal control sequences in a prompt, use
80 To include invisible terminal control sequences in a prompt, use
81 ``Token.ZeroWidthEscape`` as the token type. Tokens with this type are ignored
81 ``Token.ZeroWidthEscape`` as the token type. Tokens with this type are ignored
82 when calculating the width.
82 when calculating the width.
83
83
84 Colours in the prompt are determined by the token types and the highlighting
84 Colours in the prompt are determined by the token types and the highlighting
85 style; see below for more details. The tokens used in the default prompts are
85 style; see below for more details. The tokens used in the default prompts are
86 ``Prompt``, ``PromptNum``, ``OutPrompt`` and ``OutPromptNum``.
86 ``Prompt``, ``PromptNum``, ``OutPrompt`` and ``OutPromptNum``.
87
87
88 .. _termcolour:
88 .. _termcolour:
89
89
90 Terminal Colors
90 Terminal Colors
91 ===============
91 ===============
92
92
93 .. versionchanged:: 5.0
93 .. versionchanged:: 5.0
94
94
95 There are two main configuration options controlling colours.
95 There are two main configuration options controlling colours.
96
96
97 ``InteractiveShell.colors`` sets the colour of tracebacks and object info (the
97 ``InteractiveShell.colors`` sets the colour of tracebacks and object info (the
98 output from e.g. ``zip?``). It may also affect other things if the option below
98 output from e.g. ``zip?``). It may also affect other things if the option below
99 is set to ``'legacy'``. It has four case-insensitive values:
99 is set to ``'legacy'``. It has four case-insensitive values:
100 ``'nocolor', 'neutral', 'linux', 'lightbg'``. The default is *neutral*, which
100 ``'nocolor', 'neutral', 'linux', 'lightbg'``. The default is *neutral*, which
101 should be legible on either dark or light terminal backgrounds. *linux* is
101 should be legible on either dark or light terminal backgrounds. *linux* is
102 optimised for dark backgrounds and *lightbg* for light ones.
102 optimised for dark backgrounds and *lightbg* for light ones.
103
103
104 ``TerminalInteractiveShell.highlighting_style`` determines prompt colours and
104 ``TerminalInteractiveShell.highlighting_style`` determines prompt colours and
105 syntax highlighting. It takes the name (as a string) or class (as a subclass of
105 syntax highlighting. It takes the name (as a string) or class (as a subclass of
106 ``pygments.style.Style``) of a Pygments style, or the special value ``'legacy'``
106 ``pygments.style.Style``) of a Pygments style, or the special value ``'legacy'``
107 to pick a style in accordance with ``InteractiveShell.colors``.
107 to pick a style in accordance with ``InteractiveShell.colors``.
108
108
109 You can see the Pygments styles available on your system by running::
109 You can see the Pygments styles available on your system by running::
110
110
111 import pygments
111 import pygments
112 list(pygments.styles.get_all_styles())
112 list(pygments.styles.get_all_styles())
113
113
114 Additionally, ``TerminalInteractiveShell.highlighting_style_overrides`` can override
114 Additionally, ``TerminalInteractiveShell.highlighting_style_overrides`` can override
115 specific styles in the highlighting. It should be a dictionary mapping Pygments
115 specific styles in the highlighting. It should be a dictionary mapping Pygments
116 token types to strings defining the style. See `Pygments' documentation
116 token types to strings defining the style. See `Pygments' documentation
117 <http://pygments.org/docs/styles/#creating-own-styles>`__ for the language used
117 <http://pygments.org/docs/styles/#creating-own-styles>`__ for the language used
118 to define styles.
118 to define styles.
119
119
120 Colors in the pager
120 Colors in the pager
121 -------------------
121 -------------------
122
122
123 On some systems, the default pager has problems with ANSI colour codes.
123 On some systems, the default pager has problems with ANSI colour codes.
124 To configure your default pager to allow these:
124 To configure your default pager to allow these:
125
125
126 1. Set the environment PAGER variable to ``less``.
126 1. Set the environment PAGER variable to ``less``.
127 2. Set the environment LESS variable to ``-r`` (plus any other options
127 2. Set the environment LESS variable to ``-r`` (plus any other options
128 you always want to pass to less by default). This tells less to
128 you always want to pass to less by default). This tells less to
129 properly interpret control sequences, which is how color
129 properly interpret control sequences, which is how color
130 information is given to your terminal.
130 information is given to your terminal.
131
131
132 .. _editors:
132 .. _editors:
133
133
134 Editor configuration
134 Editor configuration
135 ====================
135 ====================
136
136
137 IPython can integrate with text editors in a number of different ways:
137 IPython can integrate with text editors in a number of different ways:
138
138
139 * Editors (such as `(X)Emacs`_, vim_ and TextMate_) can
139 * Editors (such as `(X)Emacs`_, vim_ and TextMate_) can
140 send code to IPython for execution.
140 send code to IPython for execution.
141
141
142 * IPython's ``%edit`` magic command can open an editor of choice to edit
142 * IPython's ``%edit`` magic command can open an editor of choice to edit
143 a code block.
143 a code block.
144
144
145 The %edit command (and its alias %ed) will invoke the editor set in your
145 The %edit command (and its alias %ed) will invoke the editor set in your
146 environment as :envvar:`EDITOR`. If this variable is not set, it will default
146 environment as :envvar:`EDITOR`. If this variable is not set, it will default
147 to vi under Linux/Unix and to notepad under Windows. You may want to set this
147 to vi under Linux/Unix and to notepad under Windows. You may want to set this
148 variable properly and to a lightweight editor which doesn't take too long to
148 variable properly and to a lightweight editor which doesn't take too long to
149 start (that is, something other than a new instance of Emacs). This way you
149 start (that is, something other than a new instance of Emacs). This way you
150 can edit multi-line code quickly and with the power of a real editor right
150 can edit multi-line code quickly and with the power of a real editor right
151 inside IPython.
151 inside IPython.
152
152
153 You can also control the editor by setting :attr:`TerminalInteractiveShell.editor`
153 You can also control the editor by setting :attr:`TerminalInteractiveShell.editor`
154 in :file:`ipython_config.py`.
154 in :file:`ipython_config.py`.
155
155
156 Vim
156 Vim
157 ---
157 ---
158
158
159 Paul Ivanov's `vim-ipython <https://github.com/ivanov/vim-ipython>`_ provides
159 Paul Ivanov's `vim-ipython <https://github.com/ivanov/vim-ipython>`_ provides
160 powerful IPython integration for vim.
160 powerful IPython integration for vim.
161
161
162 .. _emacs:
162 .. _emacs:
163
163
164 (X)Emacs
164 (X)Emacs
165 --------
165 --------
166
166
167 If you are a dedicated Emacs user, and want to use Emacs when IPython's
167 If you are a dedicated Emacs user, and want to use Emacs when IPython's
168 ``%edit`` magic command is called you should set up the Emacs server so that
168 ``%edit`` magic command is called you should set up the Emacs server so that
169 new requests are handled by the original process. This means that almost no
169 new requests are handled by the original process. This means that almost no
170 time is spent in handling the request (assuming an Emacs process is already
170 time is spent in handling the request (assuming an Emacs process is already
171 running). For this to work, you need to set your EDITOR environment variable
171 running). For this to work, you need to set your EDITOR environment variable
172 to 'emacsclient'. The code below, supplied by Francois Pinard, can then be
172 to 'emacsclient'. The code below, supplied by Francois Pinard, can then be
173 used in your :file:`.emacs` file to enable the server:
173 used in your :file:`.emacs` file to enable the server:
174
174
175 .. code-block:: common-lisp
175 .. code-block:: common-lisp
176
176
177 (defvar server-buffer-clients)
177 (defvar server-buffer-clients)
178 (when (and (fboundp 'server-start) (string-equal (getenv "TERM") 'xterm))
178 (when (and (fboundp 'server-start) (string-equal (getenv "TERM") 'xterm))
179 (server-start)
179 (server-start)
180 (defun fp-kill-server-with-buffer-routine ()
180 (defun fp-kill-server-with-buffer-routine ()
181 (and server-buffer-clients (server-done)))
181 (and server-buffer-clients (server-done)))
182 (add-hook 'kill-buffer-hook 'fp-kill-server-with-buffer-routine))
182 (add-hook 'kill-buffer-hook 'fp-kill-server-with-buffer-routine))
183
183
184 Thanks to the work of Alexander Schmolck and Prabhu Ramachandran,
184 Thanks to the work of Alexander Schmolck and Prabhu Ramachandran,
185 currently (X)Emacs and IPython get along very well in other ways.
185 currently (X)Emacs and IPython get along very well in other ways.
186
186
187 With (X)EMacs >= 24, You can enable IPython in python-mode with:
187 With (X)EMacs >= 24, You can enable IPython in python-mode with:
188
188
189 .. code-block:: common-lisp
189 .. code-block:: common-lisp
190
190
191 (require 'python)
191 (require 'python)
192 (setq python-shell-interpreter "ipython")
192 (setq python-shell-interpreter "ipython")
193
193
194 .. _`(X)Emacs`: http://www.gnu.org/software/emacs/
194 .. _`(X)Emacs`: http://www.gnu.org/software/emacs/
195 .. _TextMate: http://macromates.com/
195 .. _TextMate: http://macromates.com/
196 .. _vim: http://www.vim.org/
196 .. _vim: http://www.vim.org/
197
197
198 .. _custom_keyboard_shortcuts
198 .. _custom_keyboard_shortcuts:
199
199
200 Keyboard Shortcuts
200 Keyboard Shortcuts
201 ==================
201 ==================
202
202
203 .. versionchanged:: 5.0
203 .. versionchanged:: 5.0
204
204
205 You can customise keyboard shortcuts for terminal IPython. Put code like this in
205 You can customise keyboard shortcuts for terminal IPython. Put code like this in
206 a :ref:`startup file <startup_files>`::
206 a :ref:`startup file <startup_files>`::
207
207
208 from IPython import get_ipython
208 from IPython import get_ipython
209 from prompt_toolkit.enums import DEFAULT_BUFFER
209 from prompt_toolkit.enums import DEFAULT_BUFFER
210 from prompt_toolkit.keys import Keys
210 from prompt_toolkit.keys import Keys
211 from prompt_toolkit.filters import HasFocus, HasSelection, ViInsertMode, EmacsInsertMode
211 from prompt_toolkit.filters import HasFocus, HasSelection, ViInsertMode, EmacsInsertMode
212
212
213 ip = get_ipython()
213 ip = get_ipython()
214 insert_mode = ViInsertMode() | EmacsInsertMode()
214 insert_mode = ViInsertMode() | EmacsInsertMode()
215
215
216 def insert_unexpected(event):
216 def insert_unexpected(event):
217 buf = event.current_buffer
217 buf = event.current_buffer
218 buf.insert_text('The Spanish Inquisition')
218 buf.insert_text('The Spanish Inquisition')
219
219
220 # Register the shortcut if IPython is using prompt_toolkit
220 # Register the shortcut if IPython is using prompt_toolkit
221 if getattr(ip, 'pt_cli'):
221 if getattr(ip, 'pt_cli'):
222 registry = ip.pt_cli.application.key_bindings_registry
222 registry = ip.pt_cli.application.key_bindings_registry
223 registry.add_binding(Keys.ControlN,
223 registry.add_binding(Keys.ControlN,
224 filter=(HasFocus(DEFAULT_BUFFER)
224 filter=(HasFocus(DEFAULT_BUFFER)
225 & ~HasSelection()
225 & ~HasSelection()
226 & insert_mode))(insert_unexpected)
226 & insert_mode))(insert_unexpected)
227
227
228 For more information on filters and what you can do with the ``event`` object,
228 For more information on filters and what you can do with the ``event`` object,
229 `see the prompt_toolkit docs
229 `see the prompt_toolkit docs
230 <http://python-prompt-toolkit.readthedocs.io/en/latest/pages/building_prompts.html#adding-custom-key-bindings>`__.
230 <http://python-prompt-toolkit.readthedocs.io/en/latest/pages/building_prompts.html#adding-custom-key-bindings>`__.
@@ -1,175 +1,176 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 IPython 6.0
13 IPython 6.0
14 ===========
14 ===========
15
15
16 Released .... ...., 2017
16 Released .... ...., 2017
17
17
18 IPython 6 feature a major improvement in the completion machinery which is now
18 IPython 6 feature a major improvement in the completion machinery which is now
19 capable of completing non-executed code. It is also the first version of IPython
19 capable of completing non-executed code. It is also the first version of IPython
20 to stop compatibility with Python 2, which is still supported on the bugfix only
20 to stop compatibility with Python 2, which is still supported on the bugfix only
21 5.x branch. Read below to have a non-exhaustive list of new features.
21 5.x branch. Read below to have a non-exhaustive list of new features.
22
22
23 Make sure you have pip > 9.0 before upgrading.
23 Make sure you have pip > 9.0 before upgrading.
24 You should be able to update by using:
24 You should be able to update by using:
25
25
26 .. code::
26 .. code::
27
27
28 pip install ipython --upgrade
28 pip install ipython --upgrade
29
29
30 New completion API and Interface
30 New completion API and Interface
31 --------------------------------
31 --------------------------------
32
32
33 The completer Completion API has seen an overhaul, and the new completer have
33 The completer Completion API has seen an overhaul, and the new completer have
34 plenty of improvement both from the end users of terminal IPython or for
34 plenty of improvement both from the end users of terminal IPython or for
35 consumers of the API.
35 consumers of the API.
36
36
37 This new API is capable of pulling completions from :any:`jedi`, thus allowing
37 This new API is capable of pulling completions from :any:`jedi`, thus allowing
38 type inference on non-executed code. If :any:`jedi` is installed completion like
38 type inference on non-executed code. If :any:`jedi` is installed completion like
39 the following are now becoming possible without code evaluation:
39 the following are now becoming possible without code evaluation:
40
40
41 >>> data = ['Number of users', 123_456]
41 >>> data = ['Number of users', 123_456]
42 ... data[0].<tab>
42 ... data[0].<tab>
43
43
44 That is to say, IPython is now capable of inferring that `data[0]` is a string,
44 That is to say, IPython is now capable of inferring that `data[0]` is a string,
45 and will suggest completions like `.capitalize`. The completion power of IPython
45 and will suggest completions like `.capitalize`. The completion power of IPython
46 will increase with new Jedi releases, and a number of bugs and more completions
46 will increase with new Jedi releases, and a number of bugs and more completions
47 are already available on development version of :any:`jedi` if you are curious.
47 are already available on development version of :any:`jedi` if you are curious.
48
48
49 With the help of prompt toolkit, types of completions can be shown in the
49 With the help of prompt toolkit, types of completions can be shown in the
50 completer interface:
50 completer interface:
51
51
52 .. image:: ../_images/jedi_type_inference_60.png
52 .. image:: ../_images/jedi_type_inference_60.png
53 :alt: Jedi showing ability to do type inference
53 :alt: Jedi showing ability to do type inference
54 :align: center
54 :align: center
55 :width: 400px
55 :target: ../_images/jedi_type_inference_60.png
56 :target: ../_images/jedi_type_inference_60.png
56
57
57 The appearance of the completer is controlled by the
58 The appearance of the completer is controlled by the
58 ``c.TerminalInteractiveShell.display_completions`` option that will show the
59 ``c.TerminalInteractiveShell.display_completions`` option that will show the
59 type differently depending on the value among ``'column'``, ``'multicolumn'``
60 type differently depending on the value among ``'column'``, ``'multicolumn'``
60 and ``'readlinelike'``
61 and ``'readlinelike'``
61
62
62 The use of Jedi also full fill a number of request and fix a number of bugs
63 The use of Jedi also full fill a number of request and fix a number of bugs
63 like case insensitive completion, completion after division operator: See
64 like case insensitive completion, completion after division operator: See
64 :ghpull:`10182`.
65 :ghpull:`10182`.
65
66
66 Extra patches and updates will be needed to the :any:`ipykernel` package for
67 Extra patches and updates will be needed to the :mod:`ipykernel` package for
67 this feature to be available to other clients like jupyter Notebook, Lab,
68 this feature to be available to other clients like jupyter Notebook, Lab,
68 Nteract, Hydrogen...
69 Nteract, Hydrogen...
69
70
70 The use of Jedi can is barely noticeable on recent enough machines, but can be
71 The use of Jedi can is barely noticeable on recent enough machines, but can be
71 feel on older ones, in cases were Jedi behavior need to be adjusted, the amount
72 feel on older ones, in cases were Jedi behavior need to be adjusted, the amount
72 of time given to Jedi to compute type inference can be adjusted with
73 of time given to Jedi to compute type inference can be adjusted with
73 ``c.IPCompleter.jedi_compute_type_timeout``, with object whose type were not
74 ``c.IPCompleter.jedi_compute_type_timeout``, with object whose type were not
74 inferred will be shown as ``<unknown>``. Jedi can also be completely deactivated
75 inferred will be shown as ``<unknown>``. Jedi can also be completely deactivated
75 by using the ``c.Completer.use_jedi=False`` option.
76 by using the ``c.Completer.use_jedi=False`` option.
76
77
77
78
78 The old ``Completer.complete()`` API is waiting deprecation and should be
79 The old ``Completer.complete()`` API is waiting deprecation and should be
79 replaced replaced by ``Completer.completions()`` in a near future. Feedback on
80 replaced replaced by ``Completer.completions()`` in a near future. Feedback on
80 the current state of the API and suggestions welcome.
81 the current state of the API and suggestions welcome.
81
82
82 Python 3 only codebase
83 Python 3 only codebase
83 ----------------------
84 ----------------------
84
85
85 One of the large challenges in IPython 6.0 has been the adoption of a pure
86 One of the large challenges in IPython 6.0 has been the adoption of a pure
86 Python 3 code base, which lead us to great length to upstream patches in pip,
87 Python 3 code base, which lead us to great length to upstream patches in pip,
87 pypi and warehouse to make sure Python 2 system still upgrade to the latest
88 pypi and warehouse to make sure Python 2 system still upgrade to the latest
88 compatible Python version compatible.
89 compatible Python version compatible.
89
90
90 We remind our Python 2 users that IPython 5 is still compatible with Python 2.7,
91 We remind our Python 2 users that IPython 5 is still compatible with Python 2.7,
91 still maintained and get regular releases. Using pip 9+, upgrading IPython will
92 still maintained and get regular releases. Using pip 9+, upgrading IPython will
92 automatically upgrade to the latest version compatible with your system.
93 automatically upgrade to the latest version compatible with your system.
93
94
94 .. warning::
95 .. warning::
95
96
96 If you are on a system using an older verison of pip on Python 2, pip may
97 If you are on a system using an older verison of pip on Python 2, pip may
97 still install IPython 6.0 on your system, and IPython will refuse to start.
98 still install IPython 6.0 on your system, and IPython will refuse to start.
98 You can fix this by ugrading pip, and reinstalling ipython, or forcing pip to
99 You can fix this by ugrading pip, and reinstalling ipython, or forcing pip to
99 install an earlier version: ``pip install 'ipython<6'``
100 install an earlier version: ``pip install 'ipython<6'``
100
101
101 The ability to use only Python 3 on the code base of IPython has bring a number
102 The ability to use only Python 3 on the code base of IPython has bring a number
102 of advantage. Most of the newly written code make use of `optional function type
103 of advantage. Most of the newly written code make use of `optional function type
103 anotation <https://www.python.org/dev/peps/pep-0484/>`_ leading to clearer code
104 anotation <https://www.python.org/dev/peps/pep-0484/>`_ leading to clearer code
104 and better documentation.
105 and better documentation.
105
106
106 The total size of the repository has also for a first time between releases
107 The total size of the repository has also for a first time between releases
107 (excluding the big split for 4.0) decreased by about 1500 lines, potentially
108 (excluding the big split for 4.0) decreased by about 1500 lines, potentially
108 quite a bit more codewide as some documents like this one are append only and
109 quite a bit more codewide as some documents like this one are append only and
109 are about 300 lines long.
110 are about 300 lines long.
110
111
111 The removal as of Python2/Python3 shim layer has made the code quite clearer and
112 The removal as of Python2/Python3 shim layer has made the code quite clearer and
112 more idiomatic in a number of location, and much friendlier to work with and
113 more idiomatic in a number of location, and much friendlier to work with and
113 understand. We hope to further embrace Python 3 capability in the next release
114 understand. We hope to further embrace Python 3 capability in the next release
114 cycle and introduce more of the Python 3 only idioms (yield from, kwarg only,
115 cycle and introduce more of the Python 3 only idioms (yield from, kwarg only,
115 general unpacking) in the code base of IPython, and see if we can take advantage
116 general unpacking) in the code base of IPython, and see if we can take advantage
116 of these as well to improve user experience with better error messages and
117 of these as well to improve user experience with better error messages and
117 hints.
118 hints.
118
119
119
120
120 Miscs improvements
121 Miscs improvements
121 ------------------
122 ------------------
122
123
123
124
124 - The :cellmagic:`capture` magic can now capture the result of a cell (from an
125 - The :cellmagic:`capture` magic can now capture the result of a cell (from an
125 expression on the last line), as well as printed and displayed output.
126 expression on the last line), as well as printed and displayed output.
126 :ghpull:`9851`.
127 :ghpull:`9851`.
127
128
128 - Pressing Ctrl-Z in the terminal debugger now suspends IPython, as it already
129 - Pressing Ctrl-Z in the terminal debugger now suspends IPython, as it already
129 does in the main terminal prompt.
130 does in the main terminal prompt.
130
131
131 - autoreload can now reload ``Enum``. See :ghissue:`10232` and :ghpull:`10316`
132 - autoreload can now reload ``Enum``. See :ghissue:`10232` and :ghpull:`10316`
132
133
133 - IPython.display has gained a :any:`GeoJSON <IPython.display.GeoJSON>` object.
134 - IPython.display has gained a :any:`GeoJSON <IPython.display.GeoJSON>` object.
134 :ghpull:`10288` and :ghpull:`10253`
135 :ghpull:`10288` and :ghpull:`10253`
135
136
136 .. DO NOT EDIT THIS LINE BEFORE RELEASE. FEATURE INSERTION POINT.
137 .. DO NOT EDIT THIS LINE BEFORE RELEASE. FEATURE INSERTION POINT.
137
138
138
139
139 Functions Deprecated in 6.x Development cycle
140 Functions Deprecated in 6.x Development cycle
140 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
141 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
141
142
142 - Loading extensions from ``ipython_extension_dir`` print a warning that this
143 - Loading extensions from ``ipython_extension_dir`` print a warning that this
143 location is pending deprecation. This should only affect users still having
144 location is pending deprecation. This should only affect users still having
144 extensions installed with ``%install_ext`` which has been deprecated since
145 extensions installed with ``%install_ext`` which has been deprecated since
145 IPython 4.0, and removed in 5.0. Extensions still present in
146 IPython 4.0, and removed in 5.0. Extensions still present in
146 ``ipython_extension_dir`` may shadow more recently installed versions using
147 ``ipython_extension_dir`` may shadow more recently installed versions using
147 pip. It is thus recommended to clean ``ipython_extension_dir`` of any
148 pip. It is thus recommended to clean ``ipython_extension_dir`` of any
148 extension now available as a package.
149 extension now available as a package.
149
150
150
151
151 - ``IPython.utils.warn`` was deprecated in IPython 4.0, and has now been removed.
152 - ``IPython.utils.warn`` was deprecated in IPython 4.0, and has now been removed.
152 instead of ``IPython.utils.warn`` inbuilt :any:`warnings` module is used.
153 instead of ``IPython.utils.warn`` inbuilt :any:`warnings` module is used.
153
154
154
155
155 - The function `IPython.core.oinspect.py:call_tip` is unused, was marked as
156 - The function `IPython.core.oinspect.py:call_tip` is unused, was marked as
156 Deprecated (raising a Deprecation Warning) and marked for later removal
157 Deprecated (raising a Deprecation Warning) and marked for later removal
157 :ghpull:`10104`
158 :ghpull:`10104`
158
159
159 Backwards incompatible changes
160 Backwards incompatible changes
160 ------------------------------
161 ------------------------------
161
162
162 Functions Removed in 6.x Development cycle
163 Functions Removed in 6.x Development cycle
163 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
164 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
164
165
165 The following functions have been removed in the
166 The following functions have been removed in the
166 development cycle marked for Milestone 6.0.
167 development cycle marked for Milestone 6.0.
167
168
168 - ``IPython/utils/process.py`` - ``is_cmd_found``
169 - ``IPython/utils/process.py`` - ``is_cmd_found``
169 - ``IPython/utils/process.py`` - ``pycmd2argv``
170 - ``IPython/utils/process.py`` - ``pycmd2argv``
170
171
171 - The `--deep-reload` flag and the corresponding options to inject `dreload` or
172 - The `--deep-reload` flag and the corresponding options to inject `dreload` or
172 `reload` into the interactive namespace have been removed. You have to
173 `reload` into the interactive namespace have been removed. You have to
173 explicitly import `reload` from `IPython.lib.deepreload` to use it.
174 explicitly import `reload` from `IPython.lib.deepreload` to use it.
174
175
175 .. DO NOT EDIT THIS LINE BEFORE RELEASE. INCOMPAT INSERTION POINT.
176 .. DO NOT EDIT THIS LINE BEFORE RELEASE. INCOMPAT INSERTION POINT.
General Comments 0
You need to be logged in to leave comments. Login now