##// END OF EJS Templates
even more types
Matthias Bussonnier -
Show More
@@ -1,374 +1,377 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Implementations for various useful completers.
2 """Implementations for various useful completers.
3
3
4 These are all loaded by default by IPython.
4 These are all loaded by default by IPython.
5 """
5 """
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2010-2011 The IPython Development Team.
7 # Copyright (C) 2010-2011 The IPython Development Team.
8 #
8 #
9 # Distributed under the terms of the BSD License.
9 # Distributed under the terms of the BSD License.
10 #
10 #
11 # The full license is in the file COPYING.txt, distributed with this software.
11 # The full license is in the file COPYING.txt, distributed with this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 # Stdlib imports
18 # Stdlib imports
19 import glob
19 import glob
20 import inspect
20 import inspect
21 import os
21 import os
22 import re
22 import re
23 import sys
23 import sys
24 from importlib import import_module
24 from importlib import import_module
25 from importlib.machinery import all_suffixes
25 from importlib.machinery import all_suffixes
26
26
27
27
28 # Third-party imports
28 # Third-party imports
29 from time import time
29 from time import time
30 from zipimport import zipimporter
30 from zipimport import zipimporter
31
31
32 # Our own imports
32 # Our own imports
33 from .completer import expand_user, compress_user
33 from .completer import expand_user, compress_user
34 from .error import TryNext
34 from .error import TryNext
35 from ..utils._process_common import arg_split
35 from ..utils._process_common import arg_split
36
36
37 # FIXME: this should be pulled in with the right call via the component system
37 # FIXME: this should be pulled in with the right call via the component system
38 from IPython import get_ipython
38 from IPython import get_ipython
39
39
40 from typing import List
40 from typing import List
41
41
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43 # Globals and constants
43 # Globals and constants
44 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
45 _suffixes = all_suffixes()
45 _suffixes = all_suffixes()
46
46
47 # Time in seconds after which the rootmodules will be stored permanently in the
47 # Time in seconds after which the rootmodules will be stored permanently in the
48 # ipython ip.db database (kept in the user's .ipython dir).
48 # ipython ip.db database (kept in the user's .ipython dir).
49 TIMEOUT_STORAGE = 2
49 TIMEOUT_STORAGE = 2
50
50
51 # Time in seconds after which we give up
51 # Time in seconds after which we give up
52 TIMEOUT_GIVEUP = 20
52 TIMEOUT_GIVEUP = 20
53
53
54 # Regular expression for the python import statement
54 # Regular expression for the python import statement
55 import_re = re.compile(r'(?P<name>[^\W\d]\w*?)'
55 import_re = re.compile(r'(?P<name>[^\W\d]\w*?)'
56 r'(?P<package>[/\\]__init__)?'
56 r'(?P<package>[/\\]__init__)?'
57 r'(?P<suffix>%s)$' %
57 r'(?P<suffix>%s)$' %
58 r'|'.join(re.escape(s) for s in _suffixes))
58 r'|'.join(re.escape(s) for s in _suffixes))
59
59
60 # RE for the ipython %run command (python + ipython scripts)
60 # RE for the ipython %run command (python + ipython scripts)
61 magic_run_re = re.compile(r'.*(\.ipy|\.ipynb|\.py[w]?)$')
61 magic_run_re = re.compile(r'.*(\.ipy|\.ipynb|\.py[w]?)$')
62
62
63 #-----------------------------------------------------------------------------
63 #-----------------------------------------------------------------------------
64 # Local utilities
64 # Local utilities
65 #-----------------------------------------------------------------------------
65 #-----------------------------------------------------------------------------
66
66
67 def module_list(path):
67
68 def module_list(path: str) -> List[str]:
68 """
69 """
69 Return the list containing the names of the modules available in the given
70 Return the list containing the names of the modules available in the given
70 folder.
71 folder.
71 """
72 """
72 # sys.path has the cwd as an empty string, but isdir/listdir need it as '.'
73 # sys.path has the cwd as an empty string, but isdir/listdir need it as '.'
73 if path == '':
74 if path == '':
74 path = '.'
75 path = '.'
75
76
76 # A few local constants to be used in loops below
77 # A few local constants to be used in loops below
77 pjoin = os.path.join
78 pjoin = os.path.join
78
79
79 if os.path.isdir(path):
80 if os.path.isdir(path):
80 # Build a list of all files in the directory and all files
81 # Build a list of all files in the directory and all files
81 # in its subdirectories. For performance reasons, do not
82 # in its subdirectories. For performance reasons, do not
82 # recurse more than one level into subdirectories.
83 # recurse more than one level into subdirectories.
83 files = []
84 files: List[str] = []
84 for root, dirs, nondirs in os.walk(path, followlinks=True):
85 for root, dirs, nondirs in os.walk(path, followlinks=True):
85 subdir = root[len(path)+1:]
86 subdir = root[len(path)+1:]
86 if subdir:
87 if subdir:
87 files.extend(pjoin(subdir, f) for f in nondirs)
88 files.extend(pjoin(subdir, f) for f in nondirs)
88 dirs[:] = [] # Do not recurse into additional subdirectories.
89 dirs[:] = [] # Do not recurse into additional subdirectories.
89 else:
90 else:
90 files.extend(nondirs)
91 files.extend(nondirs)
91
92
92 else:
93 else:
93 try:
94 try:
94 files = list(zipimporter(path)._files.keys())
95 files = list(zipimporter(path)._files.keys()) # type: ignore
95 except:
96 except Exception:
96 files = []
97 files = []
97
98
98 # Build a list of modules which match the import_re regex.
99 # Build a list of modules which match the import_re regex.
99 modules = []
100 modules = []
100 for f in files:
101 for f in files:
101 m = import_re.match(f)
102 m = import_re.match(f)
102 if m:
103 if m:
103 modules.append(m.group('name'))
104 modules.append(m.group('name'))
104 return list(set(modules))
105 return list(set(modules))
105
106
106
107
107 def get_root_modules():
108 def get_root_modules():
108 """
109 """
109 Returns a list containing the names of all the modules available in the
110 Returns a list containing the names of all the modules available in the
110 folders of the pythonpath.
111 folders of the pythonpath.
111
112
112 ip.db['rootmodules_cache'] maps sys.path entries to list of modules.
113 ip.db['rootmodules_cache'] maps sys.path entries to list of modules.
113 """
114 """
114 ip = get_ipython()
115 ip = get_ipython()
115 if ip is None:
116 if ip is None:
116 # No global shell instance to store cached list of modules.
117 # No global shell instance to store cached list of modules.
117 # Don't try to scan for modules every time.
118 # Don't try to scan for modules every time.
118 return list(sys.builtin_module_names)
119 return list(sys.builtin_module_names)
119
120
120 if getattr(ip.db, "_mock", False):
121 if getattr(ip.db, "_mock", False):
121 rootmodules_cache = {}
122 rootmodules_cache = {}
122 else:
123 else:
123 rootmodules_cache = ip.db.get("rootmodules_cache", {})
124 rootmodules_cache = ip.db.get("rootmodules_cache", {})
124 rootmodules = list(sys.builtin_module_names)
125 rootmodules = list(sys.builtin_module_names)
125 start_time = time()
126 start_time = time()
126 store = False
127 store = False
127 for path in sys.path:
128 for path in sys.path:
128 try:
129 try:
129 modules = rootmodules_cache[path]
130 modules = rootmodules_cache[path]
130 except KeyError:
131 except KeyError:
131 modules = module_list(path)
132 modules = module_list(path)
132 try:
133 try:
133 modules.remove('__init__')
134 modules.remove('__init__')
134 except ValueError:
135 except ValueError:
135 pass
136 pass
136 if path not in ('', '.'): # cwd modules should not be cached
137 if path not in ('', '.'): # cwd modules should not be cached
137 rootmodules_cache[path] = modules
138 rootmodules_cache[path] = modules
138 if time() - start_time > TIMEOUT_STORAGE and not store:
139 if time() - start_time > TIMEOUT_STORAGE and not store:
139 store = True
140 store = True
140 print("\nCaching the list of root modules, please wait!")
141 print("\nCaching the list of root modules, please wait!")
141 print("(This will only be done once - type '%rehashx' to "
142 print("(This will only be done once - type '%rehashx' to "
142 "reset cache!)\n")
143 "reset cache!)\n")
143 sys.stdout.flush()
144 sys.stdout.flush()
144 if time() - start_time > TIMEOUT_GIVEUP:
145 if time() - start_time > TIMEOUT_GIVEUP:
145 print("This is taking too long, we give up.\n")
146 print("This is taking too long, we give up.\n")
146 return []
147 return []
147 rootmodules.extend(modules)
148 rootmodules.extend(modules)
148 if store:
149 if store:
149 ip.db['rootmodules_cache'] = rootmodules_cache
150 ip.db['rootmodules_cache'] = rootmodules_cache
150 rootmodules = list(set(rootmodules))
151 rootmodules = list(set(rootmodules))
151 return rootmodules
152 return rootmodules
152
153
153
154
154 def is_importable(module, attr, only_modules):
155 def is_importable(module, attr, only_modules):
155 if only_modules:
156 if only_modules:
156 return inspect.ismodule(getattr(module, attr))
157 return inspect.ismodule(getattr(module, attr))
157 else:
158 else:
158 return not(attr[:2] == '__' and attr[-2:] == '__')
159 return not(attr[:2] == '__' and attr[-2:] == '__')
159
160
160 def is_possible_submodule(module, attr):
161 def is_possible_submodule(module, attr):
161 try:
162 try:
162 obj = getattr(module, attr)
163 obj = getattr(module, attr)
163 except AttributeError:
164 except AttributeError:
164 # Is possilby an unimported submodule
165 # Is possilby an unimported submodule
165 return True
166 return True
166 except TypeError:
167 except TypeError:
167 # https://github.com/ipython/ipython/issues/9678
168 # https://github.com/ipython/ipython/issues/9678
168 return False
169 return False
169 return inspect.ismodule(obj)
170 return inspect.ismodule(obj)
170
171
171
172
172 def try_import(mod: str, only_modules=False) -> List[str]:
173 def try_import(mod: str, only_modules=False) -> List[str]:
173 """
174 """
174 Try to import given module and return list of potential completions.
175 Try to import given module and return list of potential completions.
175 """
176 """
176 mod = mod.rstrip('.')
177 mod = mod.rstrip('.')
177 try:
178 try:
178 m = import_module(mod)
179 m = import_module(mod)
179 except:
180 except:
180 return []
181 return []
181
182
182 m_is_init = '__init__' in (getattr(m, '__file__', '') or '')
183 m_is_init = '__init__' in (getattr(m, '__file__', '') or '')
183
184
184 completions = []
185 completions = []
185 if (not hasattr(m, '__file__')) or (not only_modules) or m_is_init:
186 if (not hasattr(m, '__file__')) or (not only_modules) or m_is_init:
186 completions.extend( [attr for attr in dir(m) if
187 completions.extend( [attr for attr in dir(m) if
187 is_importable(m, attr, only_modules)])
188 is_importable(m, attr, only_modules)])
188
189
189 m_all = getattr(m, "__all__", [])
190 m_all = getattr(m, "__all__", [])
190 if only_modules:
191 if only_modules:
191 completions.extend(attr for attr in m_all if is_possible_submodule(m, attr))
192 completions.extend(attr for attr in m_all if is_possible_submodule(m, attr))
192 else:
193 else:
193 completions.extend(m_all)
194 completions.extend(m_all)
194
195
195 if m_is_init:
196 if m_is_init:
196 file_ = m.__file__
197 file_ = m.__file__
197 completions.extend(module_list(os.path.dirname(file_)))
198 file_path = os.path.dirname(file_) # type: ignore
199 if file_path is not None:
200 completions.extend(module_list(file_path))
198 completions_set = {c for c in completions if isinstance(c, str)}
201 completions_set = {c for c in completions if isinstance(c, str)}
199 completions_set.discard('__init__')
202 completions_set.discard('__init__')
200 return list(completions_set)
203 return list(completions_set)
201
204
202
205
203 #-----------------------------------------------------------------------------
206 #-----------------------------------------------------------------------------
204 # Completion-related functions.
207 # Completion-related functions.
205 #-----------------------------------------------------------------------------
208 #-----------------------------------------------------------------------------
206
209
207 def quick_completer(cmd, completions):
210 def quick_completer(cmd, completions):
208 r""" Easily create a trivial completer for a command.
211 r""" Easily create a trivial completer for a command.
209
212
210 Takes either a list of completions, or all completions in string (that will
213 Takes either a list of completions, or all completions in string (that will
211 be split on whitespace).
214 be split on whitespace).
212
215
213 Example::
216 Example::
214
217
215 [d:\ipython]|1> import ipy_completers
218 [d:\ipython]|1> import ipy_completers
216 [d:\ipython]|2> ipy_completers.quick_completer('foo', ['bar','baz'])
219 [d:\ipython]|2> ipy_completers.quick_completer('foo', ['bar','baz'])
217 [d:\ipython]|3> foo b<TAB>
220 [d:\ipython]|3> foo b<TAB>
218 bar baz
221 bar baz
219 [d:\ipython]|3> foo ba
222 [d:\ipython]|3> foo ba
220 """
223 """
221
224
222 if isinstance(completions, str):
225 if isinstance(completions, str):
223 completions = completions.split()
226 completions = completions.split()
224
227
225 def do_complete(self, event):
228 def do_complete(self, event):
226 return completions
229 return completions
227
230
228 get_ipython().set_hook('complete_command',do_complete, str_key = cmd)
231 get_ipython().set_hook('complete_command',do_complete, str_key = cmd)
229
232
230 def module_completion(line):
233 def module_completion(line):
231 """
234 """
232 Returns a list containing the completion possibilities for an import line.
235 Returns a list containing the completion possibilities for an import line.
233
236
234 The line looks like this :
237 The line looks like this :
235 'import xml.d'
238 'import xml.d'
236 'from xml.dom import'
239 'from xml.dom import'
237 """
240 """
238
241
239 words = line.split(' ')
242 words = line.split(' ')
240 nwords = len(words)
243 nwords = len(words)
241
244
242 # from whatever <tab> -> 'import '
245 # from whatever <tab> -> 'import '
243 if nwords == 3 and words[0] == 'from':
246 if nwords == 3 and words[0] == 'from':
244 return ['import ']
247 return ['import ']
245
248
246 # 'from xy<tab>' or 'import xy<tab>'
249 # 'from xy<tab>' or 'import xy<tab>'
247 if nwords < 3 and (words[0] in {'%aimport', 'import', 'from'}) :
250 if nwords < 3 and (words[0] in {'%aimport', 'import', 'from'}) :
248 if nwords == 1:
251 if nwords == 1:
249 return get_root_modules()
252 return get_root_modules()
250 mod = words[1].split('.')
253 mod = words[1].split('.')
251 if len(mod) < 2:
254 if len(mod) < 2:
252 return get_root_modules()
255 return get_root_modules()
253 completion_list = try_import('.'.join(mod[:-1]), True)
256 completion_list = try_import('.'.join(mod[:-1]), True)
254 return ['.'.join(mod[:-1] + [el]) for el in completion_list]
257 return ['.'.join(mod[:-1] + [el]) for el in completion_list]
255
258
256 # 'from xyz import abc<tab>'
259 # 'from xyz import abc<tab>'
257 if nwords >= 3 and words[0] == 'from':
260 if nwords >= 3 and words[0] == 'from':
258 mod = words[1]
261 mod = words[1]
259 return try_import(mod)
262 return try_import(mod)
260
263
261 #-----------------------------------------------------------------------------
264 #-----------------------------------------------------------------------------
262 # Completers
265 # Completers
263 #-----------------------------------------------------------------------------
266 #-----------------------------------------------------------------------------
264 # These all have the func(self, event) signature to be used as custom
267 # These all have the func(self, event) signature to be used as custom
265 # completers
268 # completers
266
269
267 def module_completer(self,event):
270 def module_completer(self,event):
268 """Give completions after user has typed 'import ...' or 'from ...'"""
271 """Give completions after user has typed 'import ...' or 'from ...'"""
269
272
270 # This works in all versions of python. While 2.5 has
273 # This works in all versions of python. While 2.5 has
271 # pkgutil.walk_packages(), that particular routine is fairly dangerous,
274 # pkgutil.walk_packages(), that particular routine is fairly dangerous,
272 # since it imports *EVERYTHING* on sys.path. That is: a) very slow b) full
275 # since it imports *EVERYTHING* on sys.path. That is: a) very slow b) full
273 # of possibly problematic side effects.
276 # of possibly problematic side effects.
274 # This search the folders in the sys.path for available modules.
277 # This search the folders in the sys.path for available modules.
275
278
276 return module_completion(event.line)
279 return module_completion(event.line)
277
280
278 # FIXME: there's a lot of logic common to the run, cd and builtin file
281 # FIXME: there's a lot of logic common to the run, cd and builtin file
279 # completers, that is currently reimplemented in each.
282 # completers, that is currently reimplemented in each.
280
283
281 def magic_run_completer(self, event):
284 def magic_run_completer(self, event):
282 """Complete files that end in .py or .ipy or .ipynb for the %run command.
285 """Complete files that end in .py or .ipy or .ipynb for the %run command.
283 """
286 """
284 comps = arg_split(event.line, strict=False)
287 comps = arg_split(event.line, strict=False)
285 # relpath should be the current token that we need to complete.
288 # relpath should be the current token that we need to complete.
286 if (len(comps) > 1) and (not event.line.endswith(' ')):
289 if (len(comps) > 1) and (not event.line.endswith(' ')):
287 relpath = comps[-1].strip("'\"")
290 relpath = comps[-1].strip("'\"")
288 else:
291 else:
289 relpath = ''
292 relpath = ''
290
293
291 #print("\nev=", event) # dbg
294 #print("\nev=", event) # dbg
292 #print("rp=", relpath) # dbg
295 #print("rp=", relpath) # dbg
293 #print('comps=', comps) # dbg
296 #print('comps=', comps) # dbg
294
297
295 lglob = glob.glob
298 lglob = glob.glob
296 isdir = os.path.isdir
299 isdir = os.path.isdir
297 relpath, tilde_expand, tilde_val = expand_user(relpath)
300 relpath, tilde_expand, tilde_val = expand_user(relpath)
298
301
299 # Find if the user has already typed the first filename, after which we
302 # Find if the user has already typed the first filename, after which we
300 # should complete on all files, since after the first one other files may
303 # should complete on all files, since after the first one other files may
301 # be arguments to the input script.
304 # be arguments to the input script.
302
305
303 if any(magic_run_re.match(c) for c in comps):
306 if any(magic_run_re.match(c) for c in comps):
304 matches = [f.replace('\\','/') + ('/' if isdir(f) else '')
307 matches = [f.replace('\\','/') + ('/' if isdir(f) else '')
305 for f in lglob(relpath+'*')]
308 for f in lglob(relpath+'*')]
306 else:
309 else:
307 dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*') if isdir(f)]
310 dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*') if isdir(f)]
308 pys = [f.replace('\\','/')
311 pys = [f.replace('\\','/')
309 for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') +
312 for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') +
310 lglob(relpath+'*.ipynb') + lglob(relpath + '*.pyw')]
313 lglob(relpath+'*.ipynb') + lglob(relpath + '*.pyw')]
311
314
312 matches = dirs + pys
315 matches = dirs + pys
313
316
314 #print('run comp:', dirs+pys) # dbg
317 #print('run comp:', dirs+pys) # dbg
315 return [compress_user(p, tilde_expand, tilde_val) for p in matches]
318 return [compress_user(p, tilde_expand, tilde_val) for p in matches]
316
319
317
320
318 def cd_completer(self, event):
321 def cd_completer(self, event):
319 """Completer function for cd, which only returns directories."""
322 """Completer function for cd, which only returns directories."""
320 ip = get_ipython()
323 ip = get_ipython()
321 relpath = event.symbol
324 relpath = event.symbol
322
325
323 #print(event) # dbg
326 #print(event) # dbg
324 if event.line.endswith('-b') or ' -b ' in event.line:
327 if event.line.endswith('-b') or ' -b ' in event.line:
325 # return only bookmark completions
328 # return only bookmark completions
326 bkms = self.db.get('bookmarks', None)
329 bkms = self.db.get('bookmarks', None)
327 if bkms:
330 if bkms:
328 return bkms.keys()
331 return bkms.keys()
329 else:
332 else:
330 return []
333 return []
331
334
332 if event.symbol == '-':
335 if event.symbol == '-':
333 width_dh = str(len(str(len(ip.user_ns['_dh']) + 1)))
336 width_dh = str(len(str(len(ip.user_ns['_dh']) + 1)))
334 # jump in directory history by number
337 # jump in directory history by number
335 fmt = '-%0' + width_dh +'d [%s]'
338 fmt = '-%0' + width_dh +'d [%s]'
336 ents = [ fmt % (i,s) for i,s in enumerate(ip.user_ns['_dh'])]
339 ents = [ fmt % (i,s) for i,s in enumerate(ip.user_ns['_dh'])]
337 if len(ents) > 1:
340 if len(ents) > 1:
338 return ents
341 return ents
339 return []
342 return []
340
343
341 if event.symbol.startswith('--'):
344 if event.symbol.startswith('--'):
342 return ["--" + os.path.basename(d) for d in ip.user_ns['_dh']]
345 return ["--" + os.path.basename(d) for d in ip.user_ns['_dh']]
343
346
344 # Expand ~ in path and normalize directory separators.
347 # Expand ~ in path and normalize directory separators.
345 relpath, tilde_expand, tilde_val = expand_user(relpath)
348 relpath, tilde_expand, tilde_val = expand_user(relpath)
346 relpath = relpath.replace('\\','/')
349 relpath = relpath.replace('\\','/')
347
350
348 found = []
351 found = []
349 for d in [f.replace('\\','/') + '/' for f in glob.glob(relpath+'*')
352 for d in [f.replace('\\','/') + '/' for f in glob.glob(relpath+'*')
350 if os.path.isdir(f)]:
353 if os.path.isdir(f)]:
351 if ' ' in d:
354 if ' ' in d:
352 # we don't want to deal with any of that, complex code
355 # we don't want to deal with any of that, complex code
353 # for this is elsewhere
356 # for this is elsewhere
354 raise TryNext
357 raise TryNext
355
358
356 found.append(d)
359 found.append(d)
357
360
358 if not found:
361 if not found:
359 if os.path.isdir(relpath):
362 if os.path.isdir(relpath):
360 return [compress_user(relpath, tilde_expand, tilde_val)]
363 return [compress_user(relpath, tilde_expand, tilde_val)]
361
364
362 # if no completions so far, try bookmarks
365 # if no completions so far, try bookmarks
363 bks = self.db.get('bookmarks',{})
366 bks = self.db.get('bookmarks',{})
364 bkmatches = [s for s in bks if s.startswith(event.symbol)]
367 bkmatches = [s for s in bks if s.startswith(event.symbol)]
365 if bkmatches:
368 if bkmatches:
366 return bkmatches
369 return bkmatches
367
370
368 raise TryNext
371 raise TryNext
369
372
370 return [compress_user(p, tilde_expand, tilde_val) for p in found]
373 return [compress_user(p, tilde_expand, tilde_val) for p in found]
371
374
372 def reset_completer(self, event):
375 def reset_completer(self, event):
373 "A completer for %reset magic"
376 "A completer for %reset magic"
374 return '-f -s in out array dhist'.split()
377 return '-f -s in out array dhist'.split()
@@ -1,138 +1,149 b''
1 """An interface for publishing rich data to frontends.
1 """An interface for publishing rich data to frontends.
2
2
3 There are two components of the display system:
3 There are two components of the display system:
4
4
5 * Display formatters, which take a Python object and compute the
5 * Display formatters, which take a Python object and compute the
6 representation of the object in various formats (text, HTML, SVG, etc.).
6 representation of the object in various formats (text, HTML, SVG, etc.).
7 * The display publisher that is used to send the representation data to the
7 * The display publisher that is used to send the representation data to the
8 various frontends.
8 various frontends.
9
9
10 This module defines the logic display publishing. The display publisher uses
10 This module defines the logic display publishing. The display publisher uses
11 the ``display_data`` message type that is defined in the IPython messaging
11 the ``display_data`` message type that is defined in the IPython messaging
12 spec.
12 spec.
13 """
13 """
14
14
15 # Copyright (c) IPython Development Team.
15 # Copyright (c) IPython Development Team.
16 # Distributed under the terms of the Modified BSD License.
16 # Distributed under the terms of the Modified BSD License.
17
17
18
18
19 import sys
19 import sys
20
20
21 from traitlets.config.configurable import Configurable
21 from traitlets.config.configurable import Configurable
22 from traitlets import List
22 from traitlets import List
23
23
24 # This used to be defined here - it is imported for backwards compatibility
24 # This used to be defined here - it is imported for backwards compatibility
25 from .display_functions import publish_display_data
25 from .display_functions import publish_display_data
26
26
27 #-----------------------------------------------------------------------------
27 import typing as t
28
29 # -----------------------------------------------------------------------------
28 # Main payload class
30 # Main payload class
29 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
30
32
31
33
32 class DisplayPublisher(Configurable):
34 class DisplayPublisher(Configurable):
33 """A traited class that publishes display data to frontends.
35 """A traited class that publishes display data to frontends.
34
36
35 Instances of this class are created by the main IPython object and should
37 Instances of this class are created by the main IPython object and should
36 be accessed there.
38 be accessed there.
37 """
39 """
38
40
39 def __init__(self, shell=None, *args, **kwargs):
41 def __init__(self, shell=None, *args, **kwargs):
40 self.shell = shell
42 self.shell = shell
41 super().__init__(*args, **kwargs)
43 super().__init__(*args, **kwargs)
42
44
43 def _validate_data(self, data, metadata=None):
45 def _validate_data(self, data, metadata=None):
44 """Validate the display data.
46 """Validate the display data.
45
47
46 Parameters
48 Parameters
47 ----------
49 ----------
48 data : dict
50 data : dict
49 The formata data dictionary.
51 The formata data dictionary.
50 metadata : dict
52 metadata : dict
51 Any metadata for the data.
53 Any metadata for the data.
52 """
54 """
53
55
54 if not isinstance(data, dict):
56 if not isinstance(data, dict):
55 raise TypeError('data must be a dict, got: %r' % data)
57 raise TypeError('data must be a dict, got: %r' % data)
56 if metadata is not None:
58 if metadata is not None:
57 if not isinstance(metadata, dict):
59 if not isinstance(metadata, dict):
58 raise TypeError('metadata must be a dict, got: %r' % data)
60 raise TypeError('metadata must be a dict, got: %r' % data)
59
61
60 # use * to indicate transient, update are keyword-only
62 # use * to indicate transient, update are keyword-only
61 def publish(self, data, metadata=None, source=None, *, transient=None, update=False, **kwargs) -> None:
63 def publish(self, data, metadata=None, source=None, *, transient=None, update=False, **kwargs) -> None:
62 """Publish data and metadata to all frontends.
64 """Publish data and metadata to all frontends.
63
65
64 See the ``display_data`` message in the messaging documentation for
66 See the ``display_data`` message in the messaging documentation for
65 more details about this message type.
67 more details about this message type.
66
68
67 The following MIME types are currently implemented:
69 The following MIME types are currently implemented:
68
70
69 * text/plain
71 * text/plain
70 * text/html
72 * text/html
71 * text/markdown
73 * text/markdown
72 * text/latex
74 * text/latex
73 * application/json
75 * application/json
74 * application/javascript
76 * application/javascript
75 * image/png
77 * image/png
76 * image/jpeg
78 * image/jpeg
77 * image/svg+xml
79 * image/svg+xml
78
80
79 Parameters
81 Parameters
80 ----------
82 ----------
81 data : dict
83 data : dict
82 A dictionary having keys that are valid MIME types (like
84 A dictionary having keys that are valid MIME types (like
83 'text/plain' or 'image/svg+xml') and values that are the data for
85 'text/plain' or 'image/svg+xml') and values that are the data for
84 that MIME type. The data itself must be a JSON'able data
86 that MIME type. The data itself must be a JSON'able data
85 structure. Minimally all data should have the 'text/plain' data,
87 structure. Minimally all data should have the 'text/plain' data,
86 which can be displayed by all frontends. If more than the plain
88 which can be displayed by all frontends. If more than the plain
87 text is given, it is up to the frontend to decide which
89 text is given, it is up to the frontend to decide which
88 representation to use.
90 representation to use.
89 metadata : dict
91 metadata : dict
90 A dictionary for metadata related to the data. This can contain
92 A dictionary for metadata related to the data. This can contain
91 arbitrary key, value pairs that frontends can use to interpret
93 arbitrary key, value pairs that frontends can use to interpret
92 the data. Metadata specific to each mime-type can be specified
94 the data. Metadata specific to each mime-type can be specified
93 in the metadata dict with the same mime-type keys as
95 in the metadata dict with the same mime-type keys as
94 the data itself.
96 the data itself.
95 source : str, deprecated
97 source : str, deprecated
96 Unused.
98 Unused.
97 transient : dict, keyword-only
99 transient : dict, keyword-only
98 A dictionary for transient data.
100 A dictionary for transient data.
99 Data in this dictionary should not be persisted as part of saving this output.
101 Data in this dictionary should not be persisted as part of saving this output.
100 Examples include 'display_id'.
102 Examples include 'display_id'.
101 update : bool, keyword-only, default: False
103 update : bool, keyword-only, default: False
102 If True, only update existing outputs with the same display_id,
104 If True, only update existing outputs with the same display_id,
103 rather than creating a new output.
105 rather than creating a new output.
104 """
106 """
105
107
106 handlers = {}
108 handlers: t.Dict = {}
107 if self.shell is not None:
109 if self.shell is not None:
108 handlers = getattr(self.shell, 'mime_renderers', {})
110 handlers = getattr(self.shell, "mime_renderers", {})
109
111
110 for mime, handler in handlers.items():
112 for mime, handler in handlers.items():
111 if mime in data:
113 if mime in data:
112 handler(data[mime], metadata.get(mime, None))
114 handler(data[mime], metadata.get(mime, None))
113 return
115 return
114
116
115 if 'text/plain' in data:
117 if 'text/plain' in data:
116 print(data['text/plain'])
118 print(data['text/plain'])
117
119
118 def clear_output(self, wait=False):
120 def clear_output(self, wait=False):
119 """Clear the output of the cell receiving output."""
121 """Clear the output of the cell receiving output."""
120 print('\033[2K\r', end='')
122 print('\033[2K\r', end='')
121 sys.stdout.flush()
123 sys.stdout.flush()
122 print('\033[2K\r', end='')
124 print('\033[2K\r', end='')
123 sys.stderr.flush()
125 sys.stderr.flush()
124
126
125
127
126 class CapturingDisplayPublisher(DisplayPublisher):
128 class CapturingDisplayPublisher(DisplayPublisher):
127 """A DisplayPublisher that stores"""
129 """A DisplayPublisher that stores"""
128 outputs = List()
129
130
130 def publish(self, data, metadata=None, source=None, *, transient=None, update=False):
131 outputs: List = List()
131 self.outputs.append({'data':data, 'metadata':metadata,
132
132 'transient':transient, 'update':update})
133 def publish(
134 self, data, metadata=None, source=None, *, transient=None, update=False
135 ):
136 self.outputs.append(
137 {
138 "data": data,
139 "metadata": metadata,
140 "transient": transient,
141 "update": update,
142 }
143 )
133
144
134 def clear_output(self, wait=False):
145 def clear_output(self, wait=False):
135 super(CapturingDisplayPublisher, self).clear_output(wait)
146 super(CapturingDisplayPublisher, self).clear_output(wait)
136
147
137 # empty the list, *do not* reassign a new list
148 # empty the list, *do not* reassign a new list
138 self.outputs.clear()
149 self.outputs.clear()
@@ -1,796 +1,797 b''
1 """DEPRECATED: Input handling and transformation machinery.
1 """DEPRECATED: Input handling and transformation machinery.
2
2
3 This module was deprecated in IPython 7.0, in favour of inputtransformer2.
3 This module was deprecated in IPython 7.0, in favour of inputtransformer2.
4
4
5 The first class in this module, :class:`InputSplitter`, is designed to tell when
5 The first class in this module, :class:`InputSplitter`, is designed to tell when
6 input from a line-oriented frontend is complete and should be executed, and when
6 input from a line-oriented frontend is complete and should be executed, and when
7 the user should be prompted for another line of code instead. The name 'input
7 the user should be prompted for another line of code instead. The name 'input
8 splitter' is largely for historical reasons.
8 splitter' is largely for historical reasons.
9
9
10 A companion, :class:`IPythonInputSplitter`, provides the same functionality but
10 A companion, :class:`IPythonInputSplitter`, provides the same functionality but
11 with full support for the extended IPython syntax (magics, system calls, etc).
11 with full support for the extended IPython syntax (magics, system calls, etc).
12 The code to actually do these transformations is in :mod:`IPython.core.inputtransformer`.
12 The code to actually do these transformations is in :mod:`IPython.core.inputtransformer`.
13 :class:`IPythonInputSplitter` feeds the raw code to the transformers in order
13 :class:`IPythonInputSplitter` feeds the raw code to the transformers in order
14 and stores the results.
14 and stores the results.
15
15
16 For more details, see the class docstrings below.
16 For more details, see the class docstrings below.
17 """
17 """
18
18
19 from warnings import warn
19 from warnings import warn
20
20
21 warn('IPython.core.inputsplitter is deprecated since IPython 7 in favor of `IPython.core.inputtransformer2`',
21 warn('IPython.core.inputsplitter is deprecated since IPython 7 in favor of `IPython.core.inputtransformer2`',
22 DeprecationWarning)
22 DeprecationWarning)
23
23
24 # Copyright (c) IPython Development Team.
24 # Copyright (c) IPython Development Team.
25 # Distributed under the terms of the Modified BSD License.
25 # Distributed under the terms of the Modified BSD License.
26 import ast
26 import ast
27 import codeop
27 import codeop
28 import io
28 import io
29 import re
29 import re
30 import sys
30 import sys
31 import tokenize
31 import tokenize
32 import warnings
32 import warnings
33
33
34 from typing import List, Tuple, Union, Optional
34 from typing import List, Tuple, Union, Optional, TYPE_CHECKING
35 from typing_extensions import Self
36 from types import CodeType
35 from types import CodeType
37
36
38 from IPython.core.inputtransformer import (leading_indent,
37 from IPython.core.inputtransformer import (leading_indent,
39 classic_prompt,
38 classic_prompt,
40 ipy_prompt,
39 ipy_prompt,
41 cellmagic,
40 cellmagic,
42 assemble_logical_lines,
41 assemble_logical_lines,
43 help_end,
42 help_end,
44 escaped_commands,
43 escaped_commands,
45 assign_from_magic,
44 assign_from_magic,
46 assign_from_system,
45 assign_from_system,
47 assemble_python_lines,
46 assemble_python_lines,
48 )
47 )
49 from IPython.utils import tokenutil
48 from IPython.utils import tokenutil
50
49
51 # These are available in this module for backwards compatibility.
50 # These are available in this module for backwards compatibility.
52 from IPython.core.inputtransformer import (ESC_SHELL, ESC_SH_CAP, ESC_HELP,
51 from IPython.core.inputtransformer import (ESC_SHELL, ESC_SH_CAP, ESC_HELP,
53 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,
52 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,
54 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN, ESC_SEQUENCES)
53 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN, ESC_SEQUENCES)
55
54
55 if TYPE_CHECKING:
56 from typing_extensions import Self
56 #-----------------------------------------------------------------------------
57 #-----------------------------------------------------------------------------
57 # Utilities
58 # Utilities
58 #-----------------------------------------------------------------------------
59 #-----------------------------------------------------------------------------
59
60
60 # FIXME: These are general-purpose utilities that later can be moved to the
61 # FIXME: These are general-purpose utilities that later can be moved to the
61 # general ward. Kept here for now because we're being very strict about test
62 # general ward. Kept here for now because we're being very strict about test
62 # coverage with this code, and this lets us ensure that we keep 100% coverage
63 # coverage with this code, and this lets us ensure that we keep 100% coverage
63 # while developing.
64 # while developing.
64
65
65 # compiled regexps for autoindent management
66 # compiled regexps for autoindent management
66 dedent_re = re.compile('|'.join([
67 dedent_re = re.compile('|'.join([
67 r'^\s+raise(\s.*)?$', # raise statement (+ space + other stuff, maybe)
68 r'^\s+raise(\s.*)?$', # raise statement (+ space + other stuff, maybe)
68 r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
69 r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
69 r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
70 r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
70 r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
71 r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
71 r'^\s+pass\s*$', # pass (optionally followed by trailing spaces)
72 r'^\s+pass\s*$', # pass (optionally followed by trailing spaces)
72 r'^\s+break\s*$', # break (optionally followed by trailing spaces)
73 r'^\s+break\s*$', # break (optionally followed by trailing spaces)
73 r'^\s+continue\s*$', # continue (optionally followed by trailing spaces)
74 r'^\s+continue\s*$', # continue (optionally followed by trailing spaces)
74 ]))
75 ]))
75 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
76 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
76
77
77 # regexp to match pure comment lines so we don't accidentally insert 'if 1:'
78 # regexp to match pure comment lines so we don't accidentally insert 'if 1:'
78 # before pure comments
79 # before pure comments
79 comment_line_re = re.compile(r'^\s*\#')
80 comment_line_re = re.compile(r'^\s*\#')
80
81
81
82
82 def num_ini_spaces(s):
83 def num_ini_spaces(s):
83 """Return the number of initial spaces in a string.
84 """Return the number of initial spaces in a string.
84
85
85 Note that tabs are counted as a single space. For now, we do *not* support
86 Note that tabs are counted as a single space. For now, we do *not* support
86 mixing of tabs and spaces in the user's input.
87 mixing of tabs and spaces in the user's input.
87
88
88 Parameters
89 Parameters
89 ----------
90 ----------
90 s : string
91 s : string
91
92
92 Returns
93 Returns
93 -------
94 -------
94 n : int
95 n : int
95 """
96 """
96 warnings.warn(
97 warnings.warn(
97 "`num_ini_spaces` is Pending Deprecation since IPython 8.17."
98 "`num_ini_spaces` is Pending Deprecation since IPython 8.17."
98 "It is considered fro removal in in future version. "
99 "It is considered fro removal in in future version. "
99 "Please open an issue if you believe it should be kept.",
100 "Please open an issue if you believe it should be kept.",
100 stacklevel=2,
101 stacklevel=2,
101 category=PendingDeprecationWarning,
102 category=PendingDeprecationWarning,
102 )
103 )
103 ini_spaces = ini_spaces_re.match(s)
104 ini_spaces = ini_spaces_re.match(s)
104 if ini_spaces:
105 if ini_spaces:
105 return ini_spaces.end()
106 return ini_spaces.end()
106 else:
107 else:
107 return 0
108 return 0
108
109
109 # Fake token types for partial_tokenize:
110 # Fake token types for partial_tokenize:
110 INCOMPLETE_STRING = tokenize.N_TOKENS
111 INCOMPLETE_STRING = tokenize.N_TOKENS
111 IN_MULTILINE_STATEMENT = tokenize.N_TOKENS + 1
112 IN_MULTILINE_STATEMENT = tokenize.N_TOKENS + 1
112
113
113 # The 2 classes below have the same API as TokenInfo, but don't try to look up
114 # The 2 classes below have the same API as TokenInfo, but don't try to look up
114 # a token type name that they won't find.
115 # a token type name that they won't find.
115 class IncompleteString:
116 class IncompleteString:
116 type = exact_type = INCOMPLETE_STRING
117 type = exact_type = INCOMPLETE_STRING
117 def __init__(self, s, start, end, line):
118 def __init__(self, s, start, end, line):
118 self.s = s
119 self.s = s
119 self.start = start
120 self.start = start
120 self.end = end
121 self.end = end
121 self.line = line
122 self.line = line
122
123
123 class InMultilineStatement:
124 class InMultilineStatement:
124 type = exact_type = IN_MULTILINE_STATEMENT
125 type = exact_type = IN_MULTILINE_STATEMENT
125 def __init__(self, pos, line):
126 def __init__(self, pos, line):
126 self.s = ''
127 self.s = ''
127 self.start = self.end = pos
128 self.start = self.end = pos
128 self.line = line
129 self.line = line
129
130
130 def partial_tokens(s):
131 def partial_tokens(s):
131 """Iterate over tokens from a possibly-incomplete string of code.
132 """Iterate over tokens from a possibly-incomplete string of code.
132
133
133 This adds two special token types: INCOMPLETE_STRING and
134 This adds two special token types: INCOMPLETE_STRING and
134 IN_MULTILINE_STATEMENT. These can only occur as the last token yielded, and
135 IN_MULTILINE_STATEMENT. These can only occur as the last token yielded, and
135 represent the two main ways for code to be incomplete.
136 represent the two main ways for code to be incomplete.
136 """
137 """
137 readline = io.StringIO(s).readline
138 readline = io.StringIO(s).readline
138 token = tokenize.TokenInfo(tokenize.NEWLINE, '', (1, 0), (1, 0), '')
139 token = tokenize.TokenInfo(tokenize.NEWLINE, '', (1, 0), (1, 0), '')
139 try:
140 try:
140 for token in tokenutil.generate_tokens_catch_errors(readline):
141 for token in tokenutil.generate_tokens_catch_errors(readline):
141 yield token
142 yield token
142 except tokenize.TokenError as e:
143 except tokenize.TokenError as e:
143 # catch EOF error
144 # catch EOF error
144 lines = s.splitlines(keepends=True)
145 lines = s.splitlines(keepends=True)
145 end = len(lines), len(lines[-1])
146 end = len(lines), len(lines[-1])
146 if 'multi-line string' in e.args[0]:
147 if 'multi-line string' in e.args[0]:
147 l, c = start = token.end
148 l, c = start = token.end
148 s = lines[l-1][c:] + ''.join(lines[l:])
149 s = lines[l-1][c:] + ''.join(lines[l:])
149 yield IncompleteString(s, start, end, lines[-1])
150 yield IncompleteString(s, start, end, lines[-1])
150 elif 'multi-line statement' in e.args[0]:
151 elif 'multi-line statement' in e.args[0]:
151 yield InMultilineStatement(end, lines[-1])
152 yield InMultilineStatement(end, lines[-1])
152 else:
153 else:
153 raise
154 raise
154
155
155 def find_next_indent(code) -> int:
156 def find_next_indent(code) -> int:
156 """Find the number of spaces for the next line of indentation"""
157 """Find the number of spaces for the next line of indentation"""
157 tokens = list(partial_tokens(code))
158 tokens = list(partial_tokens(code))
158 if tokens[-1].type == tokenize.ENDMARKER:
159 if tokens[-1].type == tokenize.ENDMARKER:
159 tokens.pop()
160 tokens.pop()
160 if not tokens:
161 if not tokens:
161 return 0
162 return 0
162
163
163 while tokens[-1].type in {
164 while tokens[-1].type in {
164 tokenize.DEDENT,
165 tokenize.DEDENT,
165 tokenize.NEWLINE,
166 tokenize.NEWLINE,
166 tokenize.COMMENT,
167 tokenize.COMMENT,
167 tokenize.ERRORTOKEN,
168 tokenize.ERRORTOKEN,
168 }:
169 }:
169 tokens.pop()
170 tokens.pop()
170
171
171 # Starting in Python 3.12, the tokenize module adds implicit newlines at the end
172 # Starting in Python 3.12, the tokenize module adds implicit newlines at the end
172 # of input. We need to remove those if we're in a multiline statement
173 # of input. We need to remove those if we're in a multiline statement
173 if tokens[-1].type == IN_MULTILINE_STATEMENT:
174 if tokens[-1].type == IN_MULTILINE_STATEMENT:
174 while tokens[-2].type in {tokenize.NL}:
175 while tokens[-2].type in {tokenize.NL}:
175 tokens.pop(-2)
176 tokens.pop(-2)
176
177
177
178
178 if tokens[-1].type == INCOMPLETE_STRING:
179 if tokens[-1].type == INCOMPLETE_STRING:
179 # Inside a multiline string
180 # Inside a multiline string
180 return 0
181 return 0
181
182
182 # Find the indents used before
183 # Find the indents used before
183 prev_indents = [0]
184 prev_indents = [0]
184 def _add_indent(n):
185 def _add_indent(n):
185 if n != prev_indents[-1]:
186 if n != prev_indents[-1]:
186 prev_indents.append(n)
187 prev_indents.append(n)
187
188
188 tokiter = iter(tokens)
189 tokiter = iter(tokens)
189 for tok in tokiter:
190 for tok in tokiter:
190 if tok.type in {tokenize.INDENT, tokenize.DEDENT}:
191 if tok.type in {tokenize.INDENT, tokenize.DEDENT}:
191 _add_indent(tok.end[1])
192 _add_indent(tok.end[1])
192 elif (tok.type == tokenize.NL):
193 elif (tok.type == tokenize.NL):
193 try:
194 try:
194 _add_indent(next(tokiter).start[1])
195 _add_indent(next(tokiter).start[1])
195 except StopIteration:
196 except StopIteration:
196 break
197 break
197
198
198 last_indent = prev_indents.pop()
199 last_indent = prev_indents.pop()
199
200
200 # If we've just opened a multiline statement (e.g. 'a = ['), indent more
201 # If we've just opened a multiline statement (e.g. 'a = ['), indent more
201 if tokens[-1].type == IN_MULTILINE_STATEMENT:
202 if tokens[-1].type == IN_MULTILINE_STATEMENT:
202 if tokens[-2].exact_type in {tokenize.LPAR, tokenize.LSQB, tokenize.LBRACE}:
203 if tokens[-2].exact_type in {tokenize.LPAR, tokenize.LSQB, tokenize.LBRACE}:
203 return last_indent + 4
204 return last_indent + 4
204 return last_indent
205 return last_indent
205
206
206 if tokens[-1].exact_type == tokenize.COLON:
207 if tokens[-1].exact_type == tokenize.COLON:
207 # Line ends with colon - indent
208 # Line ends with colon - indent
208 return last_indent + 4
209 return last_indent + 4
209
210
210 if last_indent:
211 if last_indent:
211 # Examine the last line for dedent cues - statements like return or
212 # Examine the last line for dedent cues - statements like return or
212 # raise which normally end a block of code.
213 # raise which normally end a block of code.
213 last_line_starts = 0
214 last_line_starts = 0
214 for i, tok in enumerate(tokens):
215 for i, tok in enumerate(tokens):
215 if tok.type == tokenize.NEWLINE:
216 if tok.type == tokenize.NEWLINE:
216 last_line_starts = i + 1
217 last_line_starts = i + 1
217
218
218 last_line_tokens = tokens[last_line_starts:]
219 last_line_tokens = tokens[last_line_starts:]
219 names = [t.string for t in last_line_tokens if t.type == tokenize.NAME]
220 names = [t.string for t in last_line_tokens if t.type == tokenize.NAME]
220 if names and names[0] in {'raise', 'return', 'pass', 'break', 'continue'}:
221 if names and names[0] in {'raise', 'return', 'pass', 'break', 'continue'}:
221 # Find the most recent indentation less than the current level
222 # Find the most recent indentation less than the current level
222 for indent in reversed(prev_indents):
223 for indent in reversed(prev_indents):
223 if indent < last_indent:
224 if indent < last_indent:
224 return indent
225 return indent
225
226
226 return last_indent
227 return last_indent
227
228
228
229
229 def last_blank(src):
230 def last_blank(src):
230 """Determine if the input source ends in a blank.
231 """Determine if the input source ends in a blank.
231
232
232 A blank is either a newline or a line consisting of whitespace.
233 A blank is either a newline or a line consisting of whitespace.
233
234
234 Parameters
235 Parameters
235 ----------
236 ----------
236 src : string
237 src : string
237 A single or multiline string.
238 A single or multiline string.
238 """
239 """
239 if not src: return False
240 if not src: return False
240 ll = src.splitlines()[-1]
241 ll = src.splitlines()[-1]
241 return (ll == '') or ll.isspace()
242 return (ll == '') or ll.isspace()
242
243
243
244
244 last_two_blanks_re = re.compile(r'\n\s*\n\s*$', re.MULTILINE)
245 last_two_blanks_re = re.compile(r'\n\s*\n\s*$', re.MULTILINE)
245 last_two_blanks_re2 = re.compile(r'.+\n\s*\n\s+$', re.MULTILINE)
246 last_two_blanks_re2 = re.compile(r'.+\n\s*\n\s+$', re.MULTILINE)
246
247
247 def last_two_blanks(src):
248 def last_two_blanks(src):
248 """Determine if the input source ends in two blanks.
249 """Determine if the input source ends in two blanks.
249
250
250 A blank is either a newline or a line consisting of whitespace.
251 A blank is either a newline or a line consisting of whitespace.
251
252
252 Parameters
253 Parameters
253 ----------
254 ----------
254 src : string
255 src : string
255 A single or multiline string.
256 A single or multiline string.
256 """
257 """
257 if not src: return False
258 if not src: return False
258 # The logic here is tricky: I couldn't get a regexp to work and pass all
259 # The logic here is tricky: I couldn't get a regexp to work and pass all
259 # the tests, so I took a different approach: split the source by lines,
260 # the tests, so I took a different approach: split the source by lines,
260 # grab the last two and prepend '###\n' as a stand-in for whatever was in
261 # grab the last two and prepend '###\n' as a stand-in for whatever was in
261 # the body before the last two lines. Then, with that structure, it's
262 # the body before the last two lines. Then, with that structure, it's
262 # possible to analyze with two regexps. Not the most elegant solution, but
263 # possible to analyze with two regexps. Not the most elegant solution, but
263 # it works. If anyone tries to change this logic, make sure to validate
264 # it works. If anyone tries to change this logic, make sure to validate
264 # the whole test suite first!
265 # the whole test suite first!
265 new_src = '\n'.join(['###\n'] + src.splitlines()[-2:])
266 new_src = '\n'.join(['###\n'] + src.splitlines()[-2:])
266 return (bool(last_two_blanks_re.match(new_src)) or
267 return (bool(last_two_blanks_re.match(new_src)) or
267 bool(last_two_blanks_re2.match(new_src)) )
268 bool(last_two_blanks_re2.match(new_src)) )
268
269
269
270
270 def remove_comments(src):
271 def remove_comments(src):
271 """Remove all comments from input source.
272 """Remove all comments from input source.
272
273
273 Note: comments are NOT recognized inside of strings!
274 Note: comments are NOT recognized inside of strings!
274
275
275 Parameters
276 Parameters
276 ----------
277 ----------
277 src : string
278 src : string
278 A single or multiline input string.
279 A single or multiline input string.
279
280
280 Returns
281 Returns
281 -------
282 -------
282 String with all Python comments removed.
283 String with all Python comments removed.
283 """
284 """
284
285
285 return re.sub('#.*', '', src)
286 return re.sub('#.*', '', src)
286
287
287
288
288 def get_input_encoding():
289 def get_input_encoding():
289 """Return the default standard input encoding.
290 """Return the default standard input encoding.
290
291
291 If sys.stdin has no encoding, 'ascii' is returned."""
292 If sys.stdin has no encoding, 'ascii' is returned."""
292 # There are strange environments for which sys.stdin.encoding is None. We
293 # There are strange environments for which sys.stdin.encoding is None. We
293 # ensure that a valid encoding is returned.
294 # ensure that a valid encoding is returned.
294 encoding = getattr(sys.stdin, 'encoding', None)
295 encoding = getattr(sys.stdin, 'encoding', None)
295 if encoding is None:
296 if encoding is None:
296 encoding = 'ascii'
297 encoding = 'ascii'
297 return encoding
298 return encoding
298
299
299 #-----------------------------------------------------------------------------
300 #-----------------------------------------------------------------------------
300 # Classes and functions for normal Python syntax handling
301 # Classes and functions for normal Python syntax handling
301 #-----------------------------------------------------------------------------
302 #-----------------------------------------------------------------------------
302
303
303 class InputSplitter(object):
304 class InputSplitter(object):
304 r"""An object that can accumulate lines of Python source before execution.
305 r"""An object that can accumulate lines of Python source before execution.
305
306
306 This object is designed to be fed python source line-by-line, using
307 This object is designed to be fed python source line-by-line, using
307 :meth:`push`. It will return on each push whether the currently pushed
308 :meth:`push`. It will return on each push whether the currently pushed
308 code could be executed already. In addition, it provides a method called
309 code could be executed already. In addition, it provides a method called
309 :meth:`push_accepts_more` that can be used to query whether more input
310 :meth:`push_accepts_more` that can be used to query whether more input
310 can be pushed into a single interactive block.
311 can be pushed into a single interactive block.
311
312
312 This is a simple example of how an interactive terminal-based client can use
313 This is a simple example of how an interactive terminal-based client can use
313 this tool::
314 this tool::
314
315
315 isp = InputSplitter()
316 isp = InputSplitter()
316 while isp.push_accepts_more():
317 while isp.push_accepts_more():
317 indent = ' '*isp.indent_spaces
318 indent = ' '*isp.indent_spaces
318 prompt = '>>> ' + indent
319 prompt = '>>> ' + indent
319 line = indent + raw_input(prompt)
320 line = indent + raw_input(prompt)
320 isp.push(line)
321 isp.push(line)
321 print 'Input source was:\n', isp.source_reset(),
322 print 'Input source was:\n', isp.source_reset(),
322 """
323 """
323 # A cache for storing the current indentation
324 # A cache for storing the current indentation
324 # The first value stores the most recently processed source input
325 # The first value stores the most recently processed source input
325 # The second value is the number of spaces for the current indentation
326 # The second value is the number of spaces for the current indentation
326 # If self.source matches the first value, the second value is a valid
327 # If self.source matches the first value, the second value is a valid
327 # current indentation. Otherwise, the cache is invalid and the indentation
328 # current indentation. Otherwise, the cache is invalid and the indentation
328 # must be recalculated.
329 # must be recalculated.
329 _indent_spaces_cache: Union[Tuple[None, None], Tuple[str, int]] = None, None
330 _indent_spaces_cache: Union[Tuple[None, None], Tuple[str, int]] = None, None
330 # String, indicating the default input encoding. It is computed by default
331 # String, indicating the default input encoding. It is computed by default
331 # at initialization time via get_input_encoding(), but it can be reset by a
332 # at initialization time via get_input_encoding(), but it can be reset by a
332 # client with specific knowledge of the encoding.
333 # client with specific knowledge of the encoding.
333 encoding = ''
334 encoding = ''
334 # String where the current full source input is stored, properly encoded.
335 # String where the current full source input is stored, properly encoded.
335 # Reading this attribute is the normal way of querying the currently pushed
336 # Reading this attribute is the normal way of querying the currently pushed
336 # source code, that has been properly encoded.
337 # source code, that has been properly encoded.
337 source: str = ""
338 source: str = ""
338 # Code object corresponding to the current source. It is automatically
339 # Code object corresponding to the current source. It is automatically
339 # synced to the source, so it can be queried at any time to obtain the code
340 # synced to the source, so it can be queried at any time to obtain the code
340 # object; it will be None if the source doesn't compile to valid Python.
341 # object; it will be None if the source doesn't compile to valid Python.
341 code: Optional[CodeType] = None
342 code: Optional[CodeType] = None
342
343
343 # Private attributes
344 # Private attributes
344
345
345 # List with lines of input accumulated so far
346 # List with lines of input accumulated so far
346 _buffer: List[str]
347 _buffer: List[str]
347 # Command compiler
348 # Command compiler
348 _compile: codeop.CommandCompiler
349 _compile: codeop.CommandCompiler
349 # Boolean indicating whether the current block is complete
350 # Boolean indicating whether the current block is complete
350 _is_complete: Optional[bool] = None
351 _is_complete: Optional[bool] = None
351 # Boolean indicating whether the current block has an unrecoverable syntax error
352 # Boolean indicating whether the current block has an unrecoverable syntax error
352 _is_invalid: bool = False
353 _is_invalid: bool = False
353
354
354 def __init__(self) -> None:
355 def __init__(self) -> None:
355 """Create a new InputSplitter instance."""
356 """Create a new InputSplitter instance."""
356 self._buffer = []
357 self._buffer = []
357 self._compile = codeop.CommandCompiler()
358 self._compile = codeop.CommandCompiler()
358 self.encoding = get_input_encoding()
359 self.encoding = get_input_encoding()
359
360
360 def reset(self):
361 def reset(self):
361 """Reset the input buffer and associated state."""
362 """Reset the input buffer and associated state."""
362 self._buffer[:] = []
363 self._buffer[:] = []
363 self.source = ''
364 self.source = ''
364 self.code = None
365 self.code = None
365 self._is_complete = False
366 self._is_complete = False
366 self._is_invalid = False
367 self._is_invalid = False
367
368
368 def source_reset(self):
369 def source_reset(self):
369 """Return the input source and perform a full reset.
370 """Return the input source and perform a full reset.
370 """
371 """
371 out = self.source
372 out = self.source
372 self.reset()
373 self.reset()
373 return out
374 return out
374
375
375 def check_complete(self, source):
376 def check_complete(self, source):
376 """Return whether a block of code is ready to execute, or should be continued
377 """Return whether a block of code is ready to execute, or should be continued
377
378
378 This is a non-stateful API, and will reset the state of this InputSplitter.
379 This is a non-stateful API, and will reset the state of this InputSplitter.
379
380
380 Parameters
381 Parameters
381 ----------
382 ----------
382 source : string
383 source : string
383 Python input code, which can be multiline.
384 Python input code, which can be multiline.
384
385
385 Returns
386 Returns
386 -------
387 -------
387 status : str
388 status : str
388 One of 'complete', 'incomplete', or 'invalid' if source is not a
389 One of 'complete', 'incomplete', or 'invalid' if source is not a
389 prefix of valid code.
390 prefix of valid code.
390 indent_spaces : int or None
391 indent_spaces : int or None
391 The number of spaces by which to indent the next line of code. If
392 The number of spaces by which to indent the next line of code. If
392 status is not 'incomplete', this is None.
393 status is not 'incomplete', this is None.
393 """
394 """
394 self.reset()
395 self.reset()
395 try:
396 try:
396 self.push(source)
397 self.push(source)
397 except SyntaxError:
398 except SyntaxError:
398 # Transformers in IPythonInputSplitter can raise SyntaxError,
399 # Transformers in IPythonInputSplitter can raise SyntaxError,
399 # which push() will not catch.
400 # which push() will not catch.
400 return 'invalid', None
401 return 'invalid', None
401 else:
402 else:
402 if self._is_invalid:
403 if self._is_invalid:
403 return 'invalid', None
404 return 'invalid', None
404 elif self.push_accepts_more():
405 elif self.push_accepts_more():
405 return 'incomplete', self.get_indent_spaces()
406 return 'incomplete', self.get_indent_spaces()
406 else:
407 else:
407 return 'complete', None
408 return 'complete', None
408 finally:
409 finally:
409 self.reset()
410 self.reset()
410
411
411 def push(self, lines:str) -> bool:
412 def push(self, lines:str) -> bool:
412 """Push one or more lines of input.
413 """Push one or more lines of input.
413
414
414 This stores the given lines and returns a status code indicating
415 This stores the given lines and returns a status code indicating
415 whether the code forms a complete Python block or not.
416 whether the code forms a complete Python block or not.
416
417
417 Any exceptions generated in compilation are swallowed, but if an
418 Any exceptions generated in compilation are swallowed, but if an
418 exception was produced, the method returns True.
419 exception was produced, the method returns True.
419
420
420 Parameters
421 Parameters
421 ----------
422 ----------
422 lines : string
423 lines : string
423 One or more lines of Python input.
424 One or more lines of Python input.
424
425
425 Returns
426 Returns
426 -------
427 -------
427 is_complete : boolean
428 is_complete : boolean
428 True if the current input source (the result of the current input
429 True if the current input source (the result of the current input
429 plus prior inputs) forms a complete Python execution block. Note that
430 plus prior inputs) forms a complete Python execution block. Note that
430 this value is also stored as a private attribute (``_is_complete``), so it
431 this value is also stored as a private attribute (``_is_complete``), so it
431 can be queried at any time.
432 can be queried at any time.
432 """
433 """
433 assert isinstance(lines, str)
434 assert isinstance(lines, str)
434 self._store(lines)
435 self._store(lines)
435 source = self.source
436 source = self.source
436
437
437 # Before calling _compile(), reset the code object to None so that if an
438 # Before calling _compile(), reset the code object to None so that if an
438 # exception is raised in compilation, we don't mislead by having
439 # exception is raised in compilation, we don't mislead by having
439 # inconsistent code/source attributes.
440 # inconsistent code/source attributes.
440 self.code, self._is_complete = None, None
441 self.code, self._is_complete = None, None
441 self._is_invalid = False
442 self._is_invalid = False
442
443
443 # Honor termination lines properly
444 # Honor termination lines properly
444 if source.endswith('\\\n'):
445 if source.endswith('\\\n'):
445 return False
446 return False
446
447
447 try:
448 try:
448 with warnings.catch_warnings():
449 with warnings.catch_warnings():
449 warnings.simplefilter('error', SyntaxWarning)
450 warnings.simplefilter('error', SyntaxWarning)
450 self.code = self._compile(source, symbol="exec")
451 self.code = self._compile(source, symbol="exec")
451 # Invalid syntax can produce any of a number of different errors from
452 # Invalid syntax can produce any of a number of different errors from
452 # inside the compiler, so we have to catch them all. Syntax errors
453 # inside the compiler, so we have to catch them all. Syntax errors
453 # immediately produce a 'ready' block, so the invalid Python can be
454 # immediately produce a 'ready' block, so the invalid Python can be
454 # sent to the kernel for evaluation with possible ipython
455 # sent to the kernel for evaluation with possible ipython
455 # special-syntax conversion.
456 # special-syntax conversion.
456 except (SyntaxError, OverflowError, ValueError, TypeError,
457 except (SyntaxError, OverflowError, ValueError, TypeError,
457 MemoryError, SyntaxWarning):
458 MemoryError, SyntaxWarning):
458 self._is_complete = True
459 self._is_complete = True
459 self._is_invalid = True
460 self._is_invalid = True
460 else:
461 else:
461 # Compilation didn't produce any exceptions (though it may not have
462 # Compilation didn't produce any exceptions (though it may not have
462 # given a complete code object)
463 # given a complete code object)
463 self._is_complete = self.code is not None
464 self._is_complete = self.code is not None
464
465
465 return self._is_complete
466 return self._is_complete
466
467
467 def push_accepts_more(self):
468 def push_accepts_more(self):
468 """Return whether a block of interactive input can accept more input.
469 """Return whether a block of interactive input can accept more input.
469
470
470 This method is meant to be used by line-oriented frontends, who need to
471 This method is meant to be used by line-oriented frontends, who need to
471 guess whether a block is complete or not based solely on prior and
472 guess whether a block is complete or not based solely on prior and
472 current input lines. The InputSplitter considers it has a complete
473 current input lines. The InputSplitter considers it has a complete
473 interactive block and will not accept more input when either:
474 interactive block and will not accept more input when either:
474
475
475 * A SyntaxError is raised
476 * A SyntaxError is raised
476
477
477 * The code is complete and consists of a single line or a single
478 * The code is complete and consists of a single line or a single
478 non-compound statement
479 non-compound statement
479
480
480 * The code is complete and has a blank line at the end
481 * The code is complete and has a blank line at the end
481
482
482 If the current input produces a syntax error, this method immediately
483 If the current input produces a syntax error, this method immediately
483 returns False but does *not* raise the syntax error exception, as
484 returns False but does *not* raise the syntax error exception, as
484 typically clients will want to send invalid syntax to an execution
485 typically clients will want to send invalid syntax to an execution
485 backend which might convert the invalid syntax into valid Python via
486 backend which might convert the invalid syntax into valid Python via
486 one of the dynamic IPython mechanisms.
487 one of the dynamic IPython mechanisms.
487 """
488 """
488
489
489 # With incomplete input, unconditionally accept more
490 # With incomplete input, unconditionally accept more
490 # A syntax error also sets _is_complete to True - see push()
491 # A syntax error also sets _is_complete to True - see push()
491 if not self._is_complete:
492 if not self._is_complete:
492 #print("Not complete") # debug
493 #print("Not complete") # debug
493 return True
494 return True
494
495
495 # The user can make any (complete) input execute by leaving a blank line
496 # The user can make any (complete) input execute by leaving a blank line
496 last_line = self.source.splitlines()[-1]
497 last_line = self.source.splitlines()[-1]
497 if (not last_line) or last_line.isspace():
498 if (not last_line) or last_line.isspace():
498 #print("Blank line") # debug
499 #print("Blank line") # debug
499 return False
500 return False
500
501
501 # If there's just a single line or AST node, and we're flush left, as is
502 # If there's just a single line or AST node, and we're flush left, as is
502 # the case after a simple statement such as 'a=1', we want to execute it
503 # the case after a simple statement such as 'a=1', we want to execute it
503 # straight away.
504 # straight away.
504 if self.get_indent_spaces() == 0:
505 if self.get_indent_spaces() == 0:
505 if len(self.source.splitlines()) <= 1:
506 if len(self.source.splitlines()) <= 1:
506 return False
507 return False
507
508
508 try:
509 try:
509 code_ast = ast.parse("".join(self._buffer))
510 code_ast = ast.parse("".join(self._buffer))
510 except Exception:
511 except Exception:
511 #print("Can't parse AST") # debug
512 #print("Can't parse AST") # debug
512 return False
513 return False
513 else:
514 else:
514 if len(code_ast.body) == 1 and \
515 if len(code_ast.body) == 1 and \
515 not hasattr(code_ast.body[0], 'body'):
516 not hasattr(code_ast.body[0], 'body'):
516 #print("Simple statement") # debug
517 #print("Simple statement") # debug
517 return False
518 return False
518
519
519 # General fallback - accept more code
520 # General fallback - accept more code
520 return True
521 return True
521
522
522 def get_indent_spaces(self) -> int:
523 def get_indent_spaces(self) -> int:
523 sourcefor, n = self._indent_spaces_cache
524 sourcefor, n = self._indent_spaces_cache
524 if sourcefor == self.source:
525 if sourcefor == self.source:
525 assert n is not None
526 assert n is not None
526 return n
527 return n
527
528
528 # self.source always has a trailing newline
529 # self.source always has a trailing newline
529 n = find_next_indent(self.source[:-1])
530 n = find_next_indent(self.source[:-1])
530 self._indent_spaces_cache = (self.source, n)
531 self._indent_spaces_cache = (self.source, n)
531 return n
532 return n
532
533
533 # Backwards compatibility. I think all code that used .indent_spaces was
534 # Backwards compatibility. I think all code that used .indent_spaces was
534 # inside IPython, but we can leave this here until IPython 7 in case any
535 # inside IPython, but we can leave this here until IPython 7 in case any
535 # other modules are using it. -TK, November 2017
536 # other modules are using it. -TK, November 2017
536 indent_spaces = property(get_indent_spaces)
537 indent_spaces = property(get_indent_spaces)
537
538
538 def _store(self, lines, buffer=None, store='source'):
539 def _store(self, lines, buffer=None, store='source'):
539 """Store one or more lines of input.
540 """Store one or more lines of input.
540
541
541 If input lines are not newline-terminated, a newline is automatically
542 If input lines are not newline-terminated, a newline is automatically
542 appended."""
543 appended."""
543
544
544 if buffer is None:
545 if buffer is None:
545 buffer = self._buffer
546 buffer = self._buffer
546
547
547 if lines.endswith('\n'):
548 if lines.endswith('\n'):
548 buffer.append(lines)
549 buffer.append(lines)
549 else:
550 else:
550 buffer.append(lines+'\n')
551 buffer.append(lines+'\n')
551 setattr(self, store, self._set_source(buffer))
552 setattr(self, store, self._set_source(buffer))
552
553
553 def _set_source(self, buffer):
554 def _set_source(self, buffer):
554 return u''.join(buffer)
555 return u''.join(buffer)
555
556
556
557
557 class IPythonInputSplitter(InputSplitter):
558 class IPythonInputSplitter(InputSplitter):
558 """An input splitter that recognizes all of IPython's special syntax."""
559 """An input splitter that recognizes all of IPython's special syntax."""
559
560
560 # String with raw, untransformed input.
561 # String with raw, untransformed input.
561 source_raw = ''
562 source_raw = ''
562
563
563 # Flag to track when a transformer has stored input that it hasn't given
564 # Flag to track when a transformer has stored input that it hasn't given
564 # back yet.
565 # back yet.
565 transformer_accumulating = False
566 transformer_accumulating = False
566
567
567 # Flag to track when assemble_python_lines has stored input that it hasn't
568 # Flag to track when assemble_python_lines has stored input that it hasn't
568 # given back yet.
569 # given back yet.
569 within_python_line = False
570 within_python_line = False
570
571
571 # Private attributes
572 # Private attributes
572
573
573 # List with lines of raw input accumulated so far.
574 # List with lines of raw input accumulated so far.
574 _buffer_raw: List[str]
575 _buffer_raw: List[str]
575
576
576 def __init__(self, line_input_checker=True, physical_line_transforms=None,
577 def __init__(self, line_input_checker=True, physical_line_transforms=None,
577 logical_line_transforms=None, python_line_transforms=None):
578 logical_line_transforms=None, python_line_transforms=None):
578 super(IPythonInputSplitter, self).__init__()
579 super(IPythonInputSplitter, self).__init__()
579 self._buffer_raw = []
580 self._buffer_raw = []
580 self._validate = True
581 self._validate = True
581
582
582 if physical_line_transforms is not None:
583 if physical_line_transforms is not None:
583 self.physical_line_transforms = physical_line_transforms
584 self.physical_line_transforms = physical_line_transforms
584 else:
585 else:
585 self.physical_line_transforms = [
586 self.physical_line_transforms = [
586 leading_indent(),
587 leading_indent(),
587 classic_prompt(),
588 classic_prompt(),
588 ipy_prompt(),
589 ipy_prompt(),
589 cellmagic(end_on_blank_line=line_input_checker),
590 cellmagic(end_on_blank_line=line_input_checker),
590 ]
591 ]
591
592
592 self.assemble_logical_lines = assemble_logical_lines()
593 self.assemble_logical_lines = assemble_logical_lines()
593 if logical_line_transforms is not None:
594 if logical_line_transforms is not None:
594 self.logical_line_transforms = logical_line_transforms
595 self.logical_line_transforms = logical_line_transforms
595 else:
596 else:
596 self.logical_line_transforms = [
597 self.logical_line_transforms = [
597 help_end(),
598 help_end(),
598 escaped_commands(),
599 escaped_commands(),
599 assign_from_magic(),
600 assign_from_magic(),
600 assign_from_system(),
601 assign_from_system(),
601 ]
602 ]
602
603
603 self.assemble_python_lines = assemble_python_lines()
604 self.assemble_python_lines = assemble_python_lines()
604 if python_line_transforms is not None:
605 if python_line_transforms is not None:
605 self.python_line_transforms = python_line_transforms
606 self.python_line_transforms = python_line_transforms
606 else:
607 else:
607 # We don't use any of these at present
608 # We don't use any of these at present
608 self.python_line_transforms = []
609 self.python_line_transforms = []
609
610
610 @property
611 @property
611 def transforms(self):
612 def transforms(self):
612 "Quick access to all transformers."
613 "Quick access to all transformers."
613 return self.physical_line_transforms + \
614 return self.physical_line_transforms + \
614 [self.assemble_logical_lines] + self.logical_line_transforms + \
615 [self.assemble_logical_lines] + self.logical_line_transforms + \
615 [self.assemble_python_lines] + self.python_line_transforms
616 [self.assemble_python_lines] + self.python_line_transforms
616
617
617 @property
618 @property
618 def transforms_in_use(self):
619 def transforms_in_use(self):
619 """Transformers, excluding logical line transformers if we're in a
620 """Transformers, excluding logical line transformers if we're in a
620 Python line."""
621 Python line."""
621 t = self.physical_line_transforms[:]
622 t = self.physical_line_transforms[:]
622 if not self.within_python_line:
623 if not self.within_python_line:
623 t += [self.assemble_logical_lines] + self.logical_line_transforms
624 t += [self.assemble_logical_lines] + self.logical_line_transforms
624 return t + [self.assemble_python_lines] + self.python_line_transforms
625 return t + [self.assemble_python_lines] + self.python_line_transforms
625
626
626 def reset(self):
627 def reset(self):
627 """Reset the input buffer and associated state."""
628 """Reset the input buffer and associated state."""
628 super(IPythonInputSplitter, self).reset()
629 super(IPythonInputSplitter, self).reset()
629 self._buffer_raw[:] = []
630 self._buffer_raw[:] = []
630 self.source_raw = ''
631 self.source_raw = ''
631 self.transformer_accumulating = False
632 self.transformer_accumulating = False
632 self.within_python_line = False
633 self.within_python_line = False
633
634
634 for t in self.transforms:
635 for t in self.transforms:
635 try:
636 try:
636 t.reset()
637 t.reset()
637 except SyntaxError:
638 except SyntaxError:
638 # Nothing that calls reset() expects to handle transformer
639 # Nothing that calls reset() expects to handle transformer
639 # errors
640 # errors
640 pass
641 pass
641
642
642 def flush_transformers(self: Self):
643 def flush_transformers(self: Self):
643 def _flush(transform, outs: List[str]):
644 def _flush(transform, outs: List[str]):
644 """yield transformed lines
645 """yield transformed lines
645
646
646 always strings, never None
647 always strings, never None
647
648
648 transform: the current transform
649 transform: the current transform
649 outs: an iterable of previously transformed inputs.
650 outs: an iterable of previously transformed inputs.
650 Each may be multiline, which will be passed
651 Each may be multiline, which will be passed
651 one line at a time to transform.
652 one line at a time to transform.
652 """
653 """
653 for out in outs:
654 for out in outs:
654 for line in out.splitlines():
655 for line in out.splitlines():
655 # push one line at a time
656 # push one line at a time
656 tmp = transform.push(line)
657 tmp = transform.push(line)
657 if tmp is not None:
658 if tmp is not None:
658 yield tmp
659 yield tmp
659
660
660 # reset the transform
661 # reset the transform
661 tmp = transform.reset()
662 tmp = transform.reset()
662 if tmp is not None:
663 if tmp is not None:
663 yield tmp
664 yield tmp
664
665
665 out: List[str] = []
666 out: List[str] = []
666 for t in self.transforms_in_use:
667 for t in self.transforms_in_use:
667 out = _flush(t, out)
668 out = _flush(t, out)
668
669
669 out = list(out)
670 out = list(out)
670 if out:
671 if out:
671 self._store('\n'.join(out))
672 self._store('\n'.join(out))
672
673
673 def raw_reset(self):
674 def raw_reset(self):
674 """Return raw input only and perform a full reset.
675 """Return raw input only and perform a full reset.
675 """
676 """
676 out = self.source_raw
677 out = self.source_raw
677 self.reset()
678 self.reset()
678 return out
679 return out
679
680
680 def source_reset(self):
681 def source_reset(self):
681 try:
682 try:
682 self.flush_transformers()
683 self.flush_transformers()
683 return self.source
684 return self.source
684 finally:
685 finally:
685 self.reset()
686 self.reset()
686
687
687 def push_accepts_more(self):
688 def push_accepts_more(self):
688 if self.transformer_accumulating:
689 if self.transformer_accumulating:
689 return True
690 return True
690 else:
691 else:
691 return super(IPythonInputSplitter, self).push_accepts_more()
692 return super(IPythonInputSplitter, self).push_accepts_more()
692
693
693 def transform_cell(self, cell):
694 def transform_cell(self, cell):
694 """Process and translate a cell of input.
695 """Process and translate a cell of input.
695 """
696 """
696 self.reset()
697 self.reset()
697 try:
698 try:
698 self.push(cell)
699 self.push(cell)
699 self.flush_transformers()
700 self.flush_transformers()
700 return self.source
701 return self.source
701 finally:
702 finally:
702 self.reset()
703 self.reset()
703
704
704 def push(self, lines:str) -> bool:
705 def push(self, lines:str) -> bool:
705 """Push one or more lines of IPython input.
706 """Push one or more lines of IPython input.
706
707
707 This stores the given lines and returns a status code indicating
708 This stores the given lines and returns a status code indicating
708 whether the code forms a complete Python block or not, after processing
709 whether the code forms a complete Python block or not, after processing
709 all input lines for special IPython syntax.
710 all input lines for special IPython syntax.
710
711
711 Any exceptions generated in compilation are swallowed, but if an
712 Any exceptions generated in compilation are swallowed, but if an
712 exception was produced, the method returns True.
713 exception was produced, the method returns True.
713
714
714 Parameters
715 Parameters
715 ----------
716 ----------
716 lines : string
717 lines : string
717 One or more lines of Python input.
718 One or more lines of Python input.
718
719
719 Returns
720 Returns
720 -------
721 -------
721 is_complete : boolean
722 is_complete : boolean
722 True if the current input source (the result of the current input
723 True if the current input source (the result of the current input
723 plus prior inputs) forms a complete Python execution block. Note that
724 plus prior inputs) forms a complete Python execution block. Note that
724 this value is also stored as a private attribute (_is_complete), so it
725 this value is also stored as a private attribute (_is_complete), so it
725 can be queried at any time.
726 can be queried at any time.
726 """
727 """
727 assert isinstance(lines, str)
728 assert isinstance(lines, str)
728 # We must ensure all input is pure unicode
729 # We must ensure all input is pure unicode
729 # ''.splitlines() --> [], but we need to push the empty line to transformers
730 # ''.splitlines() --> [], but we need to push the empty line to transformers
730 lines_list = lines.splitlines()
731 lines_list = lines.splitlines()
731 if not lines_list:
732 if not lines_list:
732 lines_list = ['']
733 lines_list = ['']
733
734
734 # Store raw source before applying any transformations to it. Note
735 # Store raw source before applying any transformations to it. Note
735 # that this must be done *after* the reset() call that would otherwise
736 # that this must be done *after* the reset() call that would otherwise
736 # flush the buffer.
737 # flush the buffer.
737 self._store(lines, self._buffer_raw, 'source_raw')
738 self._store(lines, self._buffer_raw, 'source_raw')
738
739
739 transformed_lines_list = []
740 transformed_lines_list = []
740 for line in lines_list:
741 for line in lines_list:
741 transformed = self._transform_line(line)
742 transformed = self._transform_line(line)
742 if transformed is not None:
743 if transformed is not None:
743 transformed_lines_list.append(transformed)
744 transformed_lines_list.append(transformed)
744
745
745 if transformed_lines_list:
746 if transformed_lines_list:
746 transformed_lines = '\n'.join(transformed_lines_list)
747 transformed_lines = '\n'.join(transformed_lines_list)
747 return super(IPythonInputSplitter, self).push(transformed_lines)
748 return super(IPythonInputSplitter, self).push(transformed_lines)
748 else:
749 else:
749 # Got nothing back from transformers - they must be waiting for
750 # Got nothing back from transformers - they must be waiting for
750 # more input.
751 # more input.
751 return False
752 return False
752
753
753 def _transform_line(self, line):
754 def _transform_line(self, line):
754 """Push a line of input code through the various transformers.
755 """Push a line of input code through the various transformers.
755
756
756 Returns any output from the transformers, or None if a transformer
757 Returns any output from the transformers, or None if a transformer
757 is accumulating lines.
758 is accumulating lines.
758
759
759 Sets self.transformer_accumulating as a side effect.
760 Sets self.transformer_accumulating as a side effect.
760 """
761 """
761 def _accumulating(dbg):
762 def _accumulating(dbg):
762 #print(dbg)
763 #print(dbg)
763 self.transformer_accumulating = True
764 self.transformer_accumulating = True
764 return None
765 return None
765
766
766 for transformer in self.physical_line_transforms:
767 for transformer in self.physical_line_transforms:
767 line = transformer.push(line)
768 line = transformer.push(line)
768 if line is None:
769 if line is None:
769 return _accumulating(transformer)
770 return _accumulating(transformer)
770
771
771 if not self.within_python_line:
772 if not self.within_python_line:
772 line = self.assemble_logical_lines.push(line)
773 line = self.assemble_logical_lines.push(line)
773 if line is None:
774 if line is None:
774 return _accumulating('acc logical line')
775 return _accumulating('acc logical line')
775
776
776 for transformer in self.logical_line_transforms:
777 for transformer in self.logical_line_transforms:
777 line = transformer.push(line)
778 line = transformer.push(line)
778 if line is None:
779 if line is None:
779 return _accumulating(transformer)
780 return _accumulating(transformer)
780
781
781 line = self.assemble_python_lines.push(line)
782 line = self.assemble_python_lines.push(line)
782 if line is None:
783 if line is None:
783 self.within_python_line = True
784 self.within_python_line = True
784 return _accumulating('acc python line')
785 return _accumulating('acc python line')
785 else:
786 else:
786 self.within_python_line = False
787 self.within_python_line = False
787
788
788 for transformer in self.python_line_transforms:
789 for transformer in self.python_line_transforms:
789 line = transformer.push(line)
790 line = transformer.push(line)
790 if line is None:
791 if line is None:
791 return _accumulating(transformer)
792 return _accumulating(transformer)
792
793
793 #print("transformers clear") #debug
794 #print("transformers clear") #debug
794 self.transformer_accumulating = False
795 self.transformer_accumulating = False
795 return line
796 return line
796
797
@@ -1,757 +1,759 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Magic functions for InteractiveShell.
2 """Magic functions for InteractiveShell.
3 """
3 """
4
4
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
7 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
7 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
8 # Copyright (C) 2008 The IPython Development Team
8 # Copyright (C) 2008 The IPython Development Team
9
9
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 import os
14 import os
15 import re
15 import re
16 import sys
16 import sys
17 from getopt import getopt, GetoptError
17 from getopt import getopt, GetoptError
18
18
19 from traitlets.config.configurable import Configurable
19 from traitlets.config.configurable import Configurable
20 from . import oinspect
20 from . import oinspect
21 from .error import UsageError
21 from .error import UsageError
22 from .inputtransformer2 import ESC_MAGIC, ESC_MAGIC2
22 from .inputtransformer2 import ESC_MAGIC, ESC_MAGIC2
23 from ..utils.ipstruct import Struct
23 from ..utils.ipstruct import Struct
24 from ..utils.process import arg_split
24 from ..utils.process import arg_split
25 from ..utils.text import dedent
25 from ..utils.text import dedent
26 from traitlets import Bool, Dict, Instance, observe
26 from traitlets import Bool, Dict, Instance, observe
27 from logging import error
27 from logging import error
28
28
29 import typing as t
30
29 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
30 # Globals
32 # Globals
31 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
32
34
33 # A dict we'll use for each class that has magics, used as temporary storage to
35 # A dict we'll use for each class that has magics, used as temporary storage to
34 # pass information between the @line/cell_magic method decorators and the
36 # pass information between the @line/cell_magic method decorators and the
35 # @magics_class class decorator, because the method decorators have no
37 # @magics_class class decorator, because the method decorators have no
36 # access to the class when they run. See for more details:
38 # access to the class when they run. See for more details:
37 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
39 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
38
40
39 magics = dict(line={}, cell={})
41 magics: t.Dict = dict(line={}, cell={})
40
42
41 magic_kinds = ('line', 'cell')
43 magic_kinds = ('line', 'cell')
42 magic_spec = ('line', 'cell', 'line_cell')
44 magic_spec = ('line', 'cell', 'line_cell')
43 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
45 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
44
46
45 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
46 # Utility classes and functions
48 # Utility classes and functions
47 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
48
50
49 class Bunch: pass
51 class Bunch: pass
50
52
51
53
52 def on_off(tag):
54 def on_off(tag):
53 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
55 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
54 return ['OFF','ON'][tag]
56 return ['OFF','ON'][tag]
55
57
56
58
57 def compress_dhist(dh):
59 def compress_dhist(dh):
58 """Compress a directory history into a new one with at most 20 entries.
60 """Compress a directory history into a new one with at most 20 entries.
59
61
60 Return a new list made from the first and last 10 elements of dhist after
62 Return a new list made from the first and last 10 elements of dhist after
61 removal of duplicates.
63 removal of duplicates.
62 """
64 """
63 head, tail = dh[:-10], dh[-10:]
65 head, tail = dh[:-10], dh[-10:]
64
66
65 newhead = []
67 newhead = []
66 done = set()
68 done = set()
67 for h in head:
69 for h in head:
68 if h in done:
70 if h in done:
69 continue
71 continue
70 newhead.append(h)
72 newhead.append(h)
71 done.add(h)
73 done.add(h)
72
74
73 return newhead + tail
75 return newhead + tail
74
76
75
77
76 def needs_local_scope(func):
78 def needs_local_scope(func):
77 """Decorator to mark magic functions which need to local scope to run."""
79 """Decorator to mark magic functions which need to local scope to run."""
78 func.needs_local_scope = True
80 func.needs_local_scope = True
79 return func
81 return func
80
82
81 #-----------------------------------------------------------------------------
83 #-----------------------------------------------------------------------------
82 # Class and method decorators for registering magics
84 # Class and method decorators for registering magics
83 #-----------------------------------------------------------------------------
85 #-----------------------------------------------------------------------------
84
86
85 def magics_class(cls):
87 def magics_class(cls):
86 """Class decorator for all subclasses of the main Magics class.
88 """Class decorator for all subclasses of the main Magics class.
87
89
88 Any class that subclasses Magics *must* also apply this decorator, to
90 Any class that subclasses Magics *must* also apply this decorator, to
89 ensure that all the methods that have been decorated as line/cell magics
91 ensure that all the methods that have been decorated as line/cell magics
90 get correctly registered in the class instance. This is necessary because
92 get correctly registered in the class instance. This is necessary because
91 when method decorators run, the class does not exist yet, so they
93 when method decorators run, the class does not exist yet, so they
92 temporarily store their information into a module global. Application of
94 temporarily store their information into a module global. Application of
93 this class decorator copies that global data to the class instance and
95 this class decorator copies that global data to the class instance and
94 clears the global.
96 clears the global.
95
97
96 Obviously, this mechanism is not thread-safe, which means that the
98 Obviously, this mechanism is not thread-safe, which means that the
97 *creation* of subclasses of Magic should only be done in a single-thread
99 *creation* of subclasses of Magic should only be done in a single-thread
98 context. Instantiation of the classes has no restrictions. Given that
100 context. Instantiation of the classes has no restrictions. Given that
99 these classes are typically created at IPython startup time and before user
101 these classes are typically created at IPython startup time and before user
100 application code becomes active, in practice this should not pose any
102 application code becomes active, in practice this should not pose any
101 problems.
103 problems.
102 """
104 """
103 cls.registered = True
105 cls.registered = True
104 cls.magics = dict(line = magics['line'],
106 cls.magics = dict(line = magics['line'],
105 cell = magics['cell'])
107 cell = magics['cell'])
106 magics['line'] = {}
108 magics['line'] = {}
107 magics['cell'] = {}
109 magics['cell'] = {}
108 return cls
110 return cls
109
111
110
112
111 def record_magic(dct, magic_kind, magic_name, func):
113 def record_magic(dct, magic_kind, magic_name, func):
112 """Utility function to store a function as a magic of a specific kind.
114 """Utility function to store a function as a magic of a specific kind.
113
115
114 Parameters
116 Parameters
115 ----------
117 ----------
116 dct : dict
118 dct : dict
117 A dictionary with 'line' and 'cell' subdicts.
119 A dictionary with 'line' and 'cell' subdicts.
118 magic_kind : str
120 magic_kind : str
119 Kind of magic to be stored.
121 Kind of magic to be stored.
120 magic_name : str
122 magic_name : str
121 Key to store the magic as.
123 Key to store the magic as.
122 func : function
124 func : function
123 Callable object to store.
125 Callable object to store.
124 """
126 """
125 if magic_kind == 'line_cell':
127 if magic_kind == 'line_cell':
126 dct['line'][magic_name] = dct['cell'][magic_name] = func
128 dct['line'][magic_name] = dct['cell'][magic_name] = func
127 else:
129 else:
128 dct[magic_kind][magic_name] = func
130 dct[magic_kind][magic_name] = func
129
131
130
132
131 def validate_type(magic_kind):
133 def validate_type(magic_kind):
132 """Ensure that the given magic_kind is valid.
134 """Ensure that the given magic_kind is valid.
133
135
134 Check that the given magic_kind is one of the accepted spec types (stored
136 Check that the given magic_kind is one of the accepted spec types (stored
135 in the global `magic_spec`), raise ValueError otherwise.
137 in the global `magic_spec`), raise ValueError otherwise.
136 """
138 """
137 if magic_kind not in magic_spec:
139 if magic_kind not in magic_spec:
138 raise ValueError('magic_kind must be one of %s, %s given' %
140 raise ValueError('magic_kind must be one of %s, %s given' %
139 magic_kinds, magic_kind)
141 magic_kinds, magic_kind)
140
142
141
143
142 # The docstrings for the decorator below will be fairly similar for the two
144 # The docstrings for the decorator below will be fairly similar for the two
143 # types (method and function), so we generate them here once and reuse the
145 # types (method and function), so we generate them here once and reuse the
144 # templates below.
146 # templates below.
145 _docstring_template = \
147 _docstring_template = \
146 """Decorate the given {0} as {1} magic.
148 """Decorate the given {0} as {1} magic.
147
149
148 The decorator can be used with or without arguments, as follows.
150 The decorator can be used with or without arguments, as follows.
149
151
150 i) without arguments: it will create a {1} magic named as the {0} being
152 i) without arguments: it will create a {1} magic named as the {0} being
151 decorated::
153 decorated::
152
154
153 @deco
155 @deco
154 def foo(...)
156 def foo(...)
155
157
156 will create a {1} magic named `foo`.
158 will create a {1} magic named `foo`.
157
159
158 ii) with one string argument: which will be used as the actual name of the
160 ii) with one string argument: which will be used as the actual name of the
159 resulting magic::
161 resulting magic::
160
162
161 @deco('bar')
163 @deco('bar')
162 def foo(...)
164 def foo(...)
163
165
164 will create a {1} magic named `bar`.
166 will create a {1} magic named `bar`.
165
167
166 To register a class magic use ``Interactiveshell.register_magic(class or instance)``.
168 To register a class magic use ``Interactiveshell.register_magic(class or instance)``.
167 """
169 """
168
170
169 # These two are decorator factories. While they are conceptually very similar,
171 # These two are decorator factories. While they are conceptually very similar,
170 # there are enough differences in the details that it's simpler to have them
172 # there are enough differences in the details that it's simpler to have them
171 # written as completely standalone functions rather than trying to share code
173 # written as completely standalone functions rather than trying to share code
172 # and make a single one with convoluted logic.
174 # and make a single one with convoluted logic.
173
175
174 def _method_magic_marker(magic_kind):
176 def _method_magic_marker(magic_kind):
175 """Decorator factory for methods in Magics subclasses.
177 """Decorator factory for methods in Magics subclasses.
176 """
178 """
177
179
178 validate_type(magic_kind)
180 validate_type(magic_kind)
179
181
180 # This is a closure to capture the magic_kind. We could also use a class,
182 # This is a closure to capture the magic_kind. We could also use a class,
181 # but it's overkill for just that one bit of state.
183 # but it's overkill for just that one bit of state.
182 def magic_deco(arg):
184 def magic_deco(arg):
183 if callable(arg):
185 if callable(arg):
184 # "Naked" decorator call (just @foo, no args)
186 # "Naked" decorator call (just @foo, no args)
185 func = arg
187 func = arg
186 name = func.__name__
188 name = func.__name__
187 retval = arg
189 retval = arg
188 record_magic(magics, magic_kind, name, name)
190 record_magic(magics, magic_kind, name, name)
189 elif isinstance(arg, str):
191 elif isinstance(arg, str):
190 # Decorator called with arguments (@foo('bar'))
192 # Decorator called with arguments (@foo('bar'))
191 name = arg
193 name = arg
192 def mark(func, *a, **kw):
194 def mark(func, *a, **kw):
193 record_magic(magics, magic_kind, name, func.__name__)
195 record_magic(magics, magic_kind, name, func.__name__)
194 return func
196 return func
195 retval = mark
197 retval = mark
196 else:
198 else:
197 raise TypeError("Decorator can only be called with "
199 raise TypeError("Decorator can only be called with "
198 "string or function")
200 "string or function")
199 return retval
201 return retval
200
202
201 # Ensure the resulting decorator has a usable docstring
203 # Ensure the resulting decorator has a usable docstring
202 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
204 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
203 return magic_deco
205 return magic_deco
204
206
205
207
206 def _function_magic_marker(magic_kind):
208 def _function_magic_marker(magic_kind):
207 """Decorator factory for standalone functions.
209 """Decorator factory for standalone functions.
208 """
210 """
209 validate_type(magic_kind)
211 validate_type(magic_kind)
210
212
211 # This is a closure to capture the magic_kind. We could also use a class,
213 # This is a closure to capture the magic_kind. We could also use a class,
212 # but it's overkill for just that one bit of state.
214 # but it's overkill for just that one bit of state.
213 def magic_deco(arg):
215 def magic_deco(arg):
214 # Find get_ipython() in the caller's namespace
216 # Find get_ipython() in the caller's namespace
215 caller = sys._getframe(1)
217 caller = sys._getframe(1)
216 for ns in ['f_locals', 'f_globals', 'f_builtins']:
218 for ns in ['f_locals', 'f_globals', 'f_builtins']:
217 get_ipython = getattr(caller, ns).get('get_ipython')
219 get_ipython = getattr(caller, ns).get('get_ipython')
218 if get_ipython is not None:
220 if get_ipython is not None:
219 break
221 break
220 else:
222 else:
221 raise NameError('Decorator can only run in context where '
223 raise NameError('Decorator can only run in context where '
222 '`get_ipython` exists')
224 '`get_ipython` exists')
223
225
224 ip = get_ipython()
226 ip = get_ipython()
225
227
226 if callable(arg):
228 if callable(arg):
227 # "Naked" decorator call (just @foo, no args)
229 # "Naked" decorator call (just @foo, no args)
228 func = arg
230 func = arg
229 name = func.__name__
231 name = func.__name__
230 ip.register_magic_function(func, magic_kind, name)
232 ip.register_magic_function(func, magic_kind, name)
231 retval = arg
233 retval = arg
232 elif isinstance(arg, str):
234 elif isinstance(arg, str):
233 # Decorator called with arguments (@foo('bar'))
235 # Decorator called with arguments (@foo('bar'))
234 name = arg
236 name = arg
235 def mark(func, *a, **kw):
237 def mark(func, *a, **kw):
236 ip.register_magic_function(func, magic_kind, name)
238 ip.register_magic_function(func, magic_kind, name)
237 return func
239 return func
238 retval = mark
240 retval = mark
239 else:
241 else:
240 raise TypeError("Decorator can only be called with "
242 raise TypeError("Decorator can only be called with "
241 "string or function")
243 "string or function")
242 return retval
244 return retval
243
245
244 # Ensure the resulting decorator has a usable docstring
246 # Ensure the resulting decorator has a usable docstring
245 ds = _docstring_template.format('function', magic_kind)
247 ds = _docstring_template.format('function', magic_kind)
246
248
247 ds += dedent("""
249 ds += dedent("""
248 Note: this decorator can only be used in a context where IPython is already
250 Note: this decorator can only be used in a context where IPython is already
249 active, so that the `get_ipython()` call succeeds. You can therefore use
251 active, so that the `get_ipython()` call succeeds. You can therefore use
250 it in your startup files loaded after IPython initializes, but *not* in the
252 it in your startup files loaded after IPython initializes, but *not* in the
251 IPython configuration file itself, which is executed before IPython is
253 IPython configuration file itself, which is executed before IPython is
252 fully up and running. Any file located in the `startup` subdirectory of
254 fully up and running. Any file located in the `startup` subdirectory of
253 your configuration profile will be OK in this sense.
255 your configuration profile will be OK in this sense.
254 """)
256 """)
255
257
256 magic_deco.__doc__ = ds
258 magic_deco.__doc__ = ds
257 return magic_deco
259 return magic_deco
258
260
259
261
260 MAGIC_NO_VAR_EXPAND_ATTR = "_ipython_magic_no_var_expand"
262 MAGIC_NO_VAR_EXPAND_ATTR = "_ipython_magic_no_var_expand"
261 MAGIC_OUTPUT_CAN_BE_SILENCED = "_ipython_magic_output_can_be_silenced"
263 MAGIC_OUTPUT_CAN_BE_SILENCED = "_ipython_magic_output_can_be_silenced"
262
264
263
265
264 def no_var_expand(magic_func):
266 def no_var_expand(magic_func):
265 """Mark a magic function as not needing variable expansion
267 """Mark a magic function as not needing variable expansion
266
268
267 By default, IPython interprets `{a}` or `$a` in the line passed to magics
269 By default, IPython interprets `{a}` or `$a` in the line passed to magics
268 as variables that should be interpolated from the interactive namespace
270 as variables that should be interpolated from the interactive namespace
269 before passing the line to the magic function.
271 before passing the line to the magic function.
270 This is not always desirable, e.g. when the magic executes Python code
272 This is not always desirable, e.g. when the magic executes Python code
271 (%timeit, %time, etc.).
273 (%timeit, %time, etc.).
272 Decorate magics with `@no_var_expand` to opt-out of variable expansion.
274 Decorate magics with `@no_var_expand` to opt-out of variable expansion.
273
275
274 .. versionadded:: 7.3
276 .. versionadded:: 7.3
275 """
277 """
276 setattr(magic_func, MAGIC_NO_VAR_EXPAND_ATTR, True)
278 setattr(magic_func, MAGIC_NO_VAR_EXPAND_ATTR, True)
277 return magic_func
279 return magic_func
278
280
279
281
280 def output_can_be_silenced(magic_func):
282 def output_can_be_silenced(magic_func):
281 """Mark a magic function so its output may be silenced.
283 """Mark a magic function so its output may be silenced.
282
284
283 The output is silenced if the Python code used as a parameter of
285 The output is silenced if the Python code used as a parameter of
284 the magic ends in a semicolon, not counting a Python comment that can
286 the magic ends in a semicolon, not counting a Python comment that can
285 follow it.
287 follow it.
286 """
288 """
287 setattr(magic_func, MAGIC_OUTPUT_CAN_BE_SILENCED, True)
289 setattr(magic_func, MAGIC_OUTPUT_CAN_BE_SILENCED, True)
288 return magic_func
290 return magic_func
289
291
290 # Create the actual decorators for public use
292 # Create the actual decorators for public use
291
293
292 # These three are used to decorate methods in class definitions
294 # These three are used to decorate methods in class definitions
293 line_magic = _method_magic_marker('line')
295 line_magic = _method_magic_marker('line')
294 cell_magic = _method_magic_marker('cell')
296 cell_magic = _method_magic_marker('cell')
295 line_cell_magic = _method_magic_marker('line_cell')
297 line_cell_magic = _method_magic_marker('line_cell')
296
298
297 # These three decorate standalone functions and perform the decoration
299 # These three decorate standalone functions and perform the decoration
298 # immediately. They can only run where get_ipython() works
300 # immediately. They can only run where get_ipython() works
299 register_line_magic = _function_magic_marker('line')
301 register_line_magic = _function_magic_marker('line')
300 register_cell_magic = _function_magic_marker('cell')
302 register_cell_magic = _function_magic_marker('cell')
301 register_line_cell_magic = _function_magic_marker('line_cell')
303 register_line_cell_magic = _function_magic_marker('line_cell')
302
304
303 #-----------------------------------------------------------------------------
305 #-----------------------------------------------------------------------------
304 # Core Magic classes
306 # Core Magic classes
305 #-----------------------------------------------------------------------------
307 #-----------------------------------------------------------------------------
306
308
307 class MagicsManager(Configurable):
309 class MagicsManager(Configurable):
308 """Object that handles all magic-related functionality for IPython.
310 """Object that handles all magic-related functionality for IPython.
309 """
311 """
310 # Non-configurable class attributes
312 # Non-configurable class attributes
311
313
312 # A two-level dict, first keyed by magic type, then by magic function, and
314 # A two-level dict, first keyed by magic type, then by magic function, and
313 # holding the actual callable object as value. This is the dict used for
315 # holding the actual callable object as value. This is the dict used for
314 # magic function dispatch
316 # magic function dispatch
315 magics = Dict()
317 magics = Dict()
316 lazy_magics = Dict(
318 lazy_magics = Dict(
317 help="""
319 help="""
318 Mapping from magic names to modules to load.
320 Mapping from magic names to modules to load.
319
321
320 This can be used in IPython/IPykernel configuration to declare lazy magics
322 This can be used in IPython/IPykernel configuration to declare lazy magics
321 that will only be imported/registered on first use.
323 that will only be imported/registered on first use.
322
324
323 For example::
325 For example::
324
326
325 c.MagicsManager.lazy_magics = {
327 c.MagicsManager.lazy_magics = {
326 "my_magic": "slow.to.import",
328 "my_magic": "slow.to.import",
327 "my_other_magic": "also.slow",
329 "my_other_magic": "also.slow",
328 }
330 }
329
331
330 On first invocation of `%my_magic`, `%%my_magic`, `%%my_other_magic` or
332 On first invocation of `%my_magic`, `%%my_magic`, `%%my_other_magic` or
331 `%%my_other_magic`, the corresponding module will be loaded as an ipython
333 `%%my_other_magic`, the corresponding module will be loaded as an ipython
332 extensions as if you had previously done `%load_ext ipython`.
334 extensions as if you had previously done `%load_ext ipython`.
333
335
334 Magics names should be without percent(s) as magics can be both cell
336 Magics names should be without percent(s) as magics can be both cell
335 and line magics.
337 and line magics.
336
338
337 Lazy loading happen relatively late in execution process, and
339 Lazy loading happen relatively late in execution process, and
338 complex extensions that manipulate Python/IPython internal state or global state
340 complex extensions that manipulate Python/IPython internal state or global state
339 might not support lazy loading.
341 might not support lazy loading.
340 """
342 """
341 ).tag(
343 ).tag(
342 config=True,
344 config=True,
343 )
345 )
344
346
345 # A registry of the original objects that we've been given holding magics.
347 # A registry of the original objects that we've been given holding magics.
346 registry = Dict()
348 registry = Dict()
347
349
348 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
350 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
349
351
350 auto_magic = Bool(True, help=
352 auto_magic = Bool(True, help=
351 "Automatically call line magics without requiring explicit % prefix"
353 "Automatically call line magics without requiring explicit % prefix"
352 ).tag(config=True)
354 ).tag(config=True)
353 @observe('auto_magic')
355 @observe('auto_magic')
354 def _auto_magic_changed(self, change):
356 def _auto_magic_changed(self, change):
355 self.shell.automagic = change['new']
357 self.shell.automagic = change['new']
356
358
357 _auto_status = [
359 _auto_status = [
358 'Automagic is OFF, % prefix IS needed for line magics.',
360 'Automagic is OFF, % prefix IS needed for line magics.',
359 'Automagic is ON, % prefix IS NOT needed for line magics.']
361 'Automagic is ON, % prefix IS NOT needed for line magics.']
360
362
361 user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
363 user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
362
364
363 def __init__(self, shell=None, config=None, user_magics=None, **traits):
365 def __init__(self, shell=None, config=None, user_magics=None, **traits):
364
366
365 super(MagicsManager, self).__init__(shell=shell, config=config,
367 super(MagicsManager, self).__init__(shell=shell, config=config,
366 user_magics=user_magics, **traits)
368 user_magics=user_magics, **traits)
367 self.magics = dict(line={}, cell={})
369 self.magics = dict(line={}, cell={})
368 # Let's add the user_magics to the registry for uniformity, so *all*
370 # Let's add the user_magics to the registry for uniformity, so *all*
369 # registered magic containers can be found there.
371 # registered magic containers can be found there.
370 self.registry[user_magics.__class__.__name__] = user_magics
372 self.registry[user_magics.__class__.__name__] = user_magics
371
373
372 def auto_status(self):
374 def auto_status(self):
373 """Return descriptive string with automagic status."""
375 """Return descriptive string with automagic status."""
374 return self._auto_status[self.auto_magic]
376 return self._auto_status[self.auto_magic]
375
377
376 def lsmagic(self):
378 def lsmagic(self):
377 """Return a dict of currently available magic functions.
379 """Return a dict of currently available magic functions.
378
380
379 The return dict has the keys 'line' and 'cell', corresponding to the
381 The return dict has the keys 'line' and 'cell', corresponding to the
380 two types of magics we support. Each value is a list of names.
382 two types of magics we support. Each value is a list of names.
381 """
383 """
382 return self.magics
384 return self.magics
383
385
384 def lsmagic_docs(self, brief=False, missing=''):
386 def lsmagic_docs(self, brief=False, missing=''):
385 """Return dict of documentation of magic functions.
387 """Return dict of documentation of magic functions.
386
388
387 The return dict has the keys 'line' and 'cell', corresponding to the
389 The return dict has the keys 'line' and 'cell', corresponding to the
388 two types of magics we support. Each value is a dict keyed by magic
390 two types of magics we support. Each value is a dict keyed by magic
389 name whose value is the function docstring. If a docstring is
391 name whose value is the function docstring. If a docstring is
390 unavailable, the value of `missing` is used instead.
392 unavailable, the value of `missing` is used instead.
391
393
392 If brief is True, only the first line of each docstring will be returned.
394 If brief is True, only the first line of each docstring will be returned.
393 """
395 """
394 docs = {}
396 docs = {}
395 for m_type in self.magics:
397 for m_type in self.magics:
396 m_docs = {}
398 m_docs = {}
397 for m_name, m_func in self.magics[m_type].items():
399 for m_name, m_func in self.magics[m_type].items():
398 if m_func.__doc__:
400 if m_func.__doc__:
399 if brief:
401 if brief:
400 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
402 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
401 else:
403 else:
402 m_docs[m_name] = m_func.__doc__.rstrip()
404 m_docs[m_name] = m_func.__doc__.rstrip()
403 else:
405 else:
404 m_docs[m_name] = missing
406 m_docs[m_name] = missing
405 docs[m_type] = m_docs
407 docs[m_type] = m_docs
406 return docs
408 return docs
407
409
408 def register_lazy(self, name: str, fully_qualified_name: str):
410 def register_lazy(self, name: str, fully_qualified_name: str):
409 """
411 """
410 Lazily register a magic via an extension.
412 Lazily register a magic via an extension.
411
413
412
414
413 Parameters
415 Parameters
414 ----------
416 ----------
415 name : str
417 name : str
416 Name of the magic you wish to register.
418 Name of the magic you wish to register.
417 fully_qualified_name :
419 fully_qualified_name :
418 Fully qualified name of the module/submodule that should be loaded
420 Fully qualified name of the module/submodule that should be loaded
419 as an extensions when the magic is first called.
421 as an extensions when the magic is first called.
420 It is assumed that loading this extensions will register the given
422 It is assumed that loading this extensions will register the given
421 magic.
423 magic.
422 """
424 """
423
425
424 self.lazy_magics[name] = fully_qualified_name
426 self.lazy_magics[name] = fully_qualified_name
425
427
426 def register(self, *magic_objects):
428 def register(self, *magic_objects):
427 """Register one or more instances of Magics.
429 """Register one or more instances of Magics.
428
430
429 Take one or more classes or instances of classes that subclass the main
431 Take one or more classes or instances of classes that subclass the main
430 `core.Magic` class, and register them with IPython to use the magic
432 `core.Magic` class, and register them with IPython to use the magic
431 functions they provide. The registration process will then ensure that
433 functions they provide. The registration process will then ensure that
432 any methods that have decorated to provide line and/or cell magics will
434 any methods that have decorated to provide line and/or cell magics will
433 be recognized with the `%x`/`%%x` syntax as a line/cell magic
435 be recognized with the `%x`/`%%x` syntax as a line/cell magic
434 respectively.
436 respectively.
435
437
436 If classes are given, they will be instantiated with the default
438 If classes are given, they will be instantiated with the default
437 constructor. If your classes need a custom constructor, you should
439 constructor. If your classes need a custom constructor, you should
438 instanitate them first and pass the instance.
440 instanitate them first and pass the instance.
439
441
440 The provided arguments can be an arbitrary mix of classes and instances.
442 The provided arguments can be an arbitrary mix of classes and instances.
441
443
442 Parameters
444 Parameters
443 ----------
445 ----------
444 *magic_objects : one or more classes or instances
446 *magic_objects : one or more classes or instances
445 """
447 """
446 # Start by validating them to ensure they have all had their magic
448 # Start by validating them to ensure they have all had their magic
447 # methods registered at the instance level
449 # methods registered at the instance level
448 for m in magic_objects:
450 for m in magic_objects:
449 if not m.registered:
451 if not m.registered:
450 raise ValueError("Class of magics %r was constructed without "
452 raise ValueError("Class of magics %r was constructed without "
451 "the @register_magics class decorator")
453 "the @register_magics class decorator")
452 if isinstance(m, type):
454 if isinstance(m, type):
453 # If we're given an uninstantiated class
455 # If we're given an uninstantiated class
454 m = m(shell=self.shell)
456 m = m(shell=self.shell)
455
457
456 # Now that we have an instance, we can register it and update the
458 # Now that we have an instance, we can register it and update the
457 # table of callables
459 # table of callables
458 self.registry[m.__class__.__name__] = m
460 self.registry[m.__class__.__name__] = m
459 for mtype in magic_kinds:
461 for mtype in magic_kinds:
460 self.magics[mtype].update(m.magics[mtype])
462 self.magics[mtype].update(m.magics[mtype])
461
463
462 def register_function(self, func, magic_kind='line', magic_name=None):
464 def register_function(self, func, magic_kind='line', magic_name=None):
463 """Expose a standalone function as magic function for IPython.
465 """Expose a standalone function as magic function for IPython.
464
466
465 This will create an IPython magic (line, cell or both) from a
467 This will create an IPython magic (line, cell or both) from a
466 standalone function. The functions should have the following
468 standalone function. The functions should have the following
467 signatures:
469 signatures:
468
470
469 * For line magics: `def f(line)`
471 * For line magics: `def f(line)`
470 * For cell magics: `def f(line, cell)`
472 * For cell magics: `def f(line, cell)`
471 * For a function that does both: `def f(line, cell=None)`
473 * For a function that does both: `def f(line, cell=None)`
472
474
473 In the latter case, the function will be called with `cell==None` when
475 In the latter case, the function will be called with `cell==None` when
474 invoked as `%f`, and with cell as a string when invoked as `%%f`.
476 invoked as `%f`, and with cell as a string when invoked as `%%f`.
475
477
476 Parameters
478 Parameters
477 ----------
479 ----------
478 func : callable
480 func : callable
479 Function to be registered as a magic.
481 Function to be registered as a magic.
480 magic_kind : str
482 magic_kind : str
481 Kind of magic, one of 'line', 'cell' or 'line_cell'
483 Kind of magic, one of 'line', 'cell' or 'line_cell'
482 magic_name : optional str
484 magic_name : optional str
483 If given, the name the magic will have in the IPython namespace. By
485 If given, the name the magic will have in the IPython namespace. By
484 default, the name of the function itself is used.
486 default, the name of the function itself is used.
485 """
487 """
486
488
487 # Create the new method in the user_magics and register it in the
489 # Create the new method in the user_magics and register it in the
488 # global table
490 # global table
489 validate_type(magic_kind)
491 validate_type(magic_kind)
490 magic_name = func.__name__ if magic_name is None else magic_name
492 magic_name = func.__name__ if magic_name is None else magic_name
491 setattr(self.user_magics, magic_name, func)
493 setattr(self.user_magics, magic_name, func)
492 record_magic(self.magics, magic_kind, magic_name, func)
494 record_magic(self.magics, magic_kind, magic_name, func)
493
495
494 def register_alias(self, alias_name, magic_name, magic_kind='line', magic_params=None):
496 def register_alias(self, alias_name, magic_name, magic_kind='line', magic_params=None):
495 """Register an alias to a magic function.
497 """Register an alias to a magic function.
496
498
497 The alias is an instance of :class:`MagicAlias`, which holds the
499 The alias is an instance of :class:`MagicAlias`, which holds the
498 name and kind of the magic it should call. Binding is done at
500 name and kind of the magic it should call. Binding is done at
499 call time, so if the underlying magic function is changed the alias
501 call time, so if the underlying magic function is changed the alias
500 will call the new function.
502 will call the new function.
501
503
502 Parameters
504 Parameters
503 ----------
505 ----------
504 alias_name : str
506 alias_name : str
505 The name of the magic to be registered.
507 The name of the magic to be registered.
506 magic_name : str
508 magic_name : str
507 The name of an existing magic.
509 The name of an existing magic.
508 magic_kind : str
510 magic_kind : str
509 Kind of magic, one of 'line' or 'cell'
511 Kind of magic, one of 'line' or 'cell'
510 """
512 """
511
513
512 # `validate_type` is too permissive, as it allows 'line_cell'
514 # `validate_type` is too permissive, as it allows 'line_cell'
513 # which we do not handle.
515 # which we do not handle.
514 if magic_kind not in magic_kinds:
516 if magic_kind not in magic_kinds:
515 raise ValueError('magic_kind must be one of %s, %s given' %
517 raise ValueError('magic_kind must be one of %s, %s given' %
516 magic_kinds, magic_kind)
518 magic_kinds, magic_kind)
517
519
518 alias = MagicAlias(self.shell, magic_name, magic_kind, magic_params)
520 alias = MagicAlias(self.shell, magic_name, magic_kind, magic_params)
519 setattr(self.user_magics, alias_name, alias)
521 setattr(self.user_magics, alias_name, alias)
520 record_magic(self.magics, magic_kind, alias_name, alias)
522 record_magic(self.magics, magic_kind, alias_name, alias)
521
523
522 # Key base class that provides the central functionality for magics.
524 # Key base class that provides the central functionality for magics.
523
525
524
526
525 class Magics(Configurable):
527 class Magics(Configurable):
526 """Base class for implementing magic functions.
528 """Base class for implementing magic functions.
527
529
528 Shell functions which can be reached as %function_name. All magic
530 Shell functions which can be reached as %function_name. All magic
529 functions should accept a string, which they can parse for their own
531 functions should accept a string, which they can parse for their own
530 needs. This can make some functions easier to type, eg `%cd ../`
532 needs. This can make some functions easier to type, eg `%cd ../`
531 vs. `%cd("../")`
533 vs. `%cd("../")`
532
534
533 Classes providing magic functions need to subclass this class, and they
535 Classes providing magic functions need to subclass this class, and they
534 MUST:
536 MUST:
535
537
536 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
538 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
537 individual methods as magic functions, AND
539 individual methods as magic functions, AND
538
540
539 - Use the class decorator `@magics_class` to ensure that the magic
541 - Use the class decorator `@magics_class` to ensure that the magic
540 methods are properly registered at the instance level upon instance
542 methods are properly registered at the instance level upon instance
541 initialization.
543 initialization.
542
544
543 See :mod:`magic_functions` for examples of actual implementation classes.
545 See :mod:`magic_functions` for examples of actual implementation classes.
544 """
546 """
545 # Dict holding all command-line options for each magic.
547 # Dict holding all command-line options for each magic.
546 options_table = None
548 options_table = None
547 # Dict for the mapping of magic names to methods, set by class decorator
549 # Dict for the mapping of magic names to methods, set by class decorator
548 magics = None
550 magics = None
549 # Flag to check that the class decorator was properly applied
551 # Flag to check that the class decorator was properly applied
550 registered = False
552 registered = False
551 # Instance of IPython shell
553 # Instance of IPython shell
552 shell = None
554 shell = None
553
555
554 def __init__(self, shell=None, **kwargs):
556 def __init__(self, shell=None, **kwargs):
555 if not(self.__class__.registered):
557 if not(self.__class__.registered):
556 raise ValueError('Magics subclass without registration - '
558 raise ValueError('Magics subclass without registration - '
557 'did you forget to apply @magics_class?')
559 'did you forget to apply @magics_class?')
558 if shell is not None:
560 if shell is not None:
559 if hasattr(shell, 'configurables'):
561 if hasattr(shell, 'configurables'):
560 shell.configurables.append(self)
562 shell.configurables.append(self)
561 if hasattr(shell, 'config'):
563 if hasattr(shell, 'config'):
562 kwargs.setdefault('parent', shell)
564 kwargs.setdefault('parent', shell)
563
565
564 self.shell = shell
566 self.shell = shell
565 self.options_table = {}
567 self.options_table = {}
566 # The method decorators are run when the instance doesn't exist yet, so
568 # The method decorators are run when the instance doesn't exist yet, so
567 # they can only record the names of the methods they are supposed to
569 # they can only record the names of the methods they are supposed to
568 # grab. Only now, that the instance exists, can we create the proper
570 # grab. Only now, that the instance exists, can we create the proper
569 # mapping to bound methods. So we read the info off the original names
571 # mapping to bound methods. So we read the info off the original names
570 # table and replace each method name by the actual bound method.
572 # table and replace each method name by the actual bound method.
571 # But we mustn't clobber the *class* mapping, in case of multiple instances.
573 # But we mustn't clobber the *class* mapping, in case of multiple instances.
572 class_magics = self.magics
574 class_magics = self.magics
573 self.magics = {}
575 self.magics = {}
574 for mtype in magic_kinds:
576 for mtype in magic_kinds:
575 tab = self.magics[mtype] = {}
577 tab = self.magics[mtype] = {}
576 cls_tab = class_magics[mtype]
578 cls_tab = class_magics[mtype]
577 for magic_name, meth_name in cls_tab.items():
579 for magic_name, meth_name in cls_tab.items():
578 if isinstance(meth_name, str):
580 if isinstance(meth_name, str):
579 # it's a method name, grab it
581 # it's a method name, grab it
580 tab[magic_name] = getattr(self, meth_name)
582 tab[magic_name] = getattr(self, meth_name)
581 else:
583 else:
582 # it's the real thing
584 # it's the real thing
583 tab[magic_name] = meth_name
585 tab[magic_name] = meth_name
584 # Configurable **needs** to be initiated at the end or the config
586 # Configurable **needs** to be initiated at the end or the config
585 # magics get screwed up.
587 # magics get screwed up.
586 super(Magics, self).__init__(**kwargs)
588 super(Magics, self).__init__(**kwargs)
587
589
588 def arg_err(self,func):
590 def arg_err(self,func):
589 """Print docstring if incorrect arguments were passed"""
591 """Print docstring if incorrect arguments were passed"""
590 print('Error in arguments:')
592 print('Error in arguments:')
591 print(oinspect.getdoc(func))
593 print(oinspect.getdoc(func))
592
594
593 def format_latex(self, strng):
595 def format_latex(self, strng):
594 """Format a string for latex inclusion."""
596 """Format a string for latex inclusion."""
595
597
596 # Characters that need to be escaped for latex:
598 # Characters that need to be escaped for latex:
597 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
599 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
598 # Magic command names as headers:
600 # Magic command names as headers:
599 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
601 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
600 re.MULTILINE)
602 re.MULTILINE)
601 # Magic commands
603 # Magic commands
602 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
604 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
603 re.MULTILINE)
605 re.MULTILINE)
604 # Paragraph continue
606 # Paragraph continue
605 par_re = re.compile(r'\\$',re.MULTILINE)
607 par_re = re.compile(r'\\$',re.MULTILINE)
606
608
607 # The "\n" symbol
609 # The "\n" symbol
608 newline_re = re.compile(r'\\n')
610 newline_re = re.compile(r'\\n')
609
611
610 # Now build the string for output:
612 # Now build the string for output:
611 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
613 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
612 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
614 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
613 strng)
615 strng)
614 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
616 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
615 strng = par_re.sub(r'\\\\',strng)
617 strng = par_re.sub(r'\\\\',strng)
616 strng = escape_re.sub(r'\\\1',strng)
618 strng = escape_re.sub(r'\\\1',strng)
617 strng = newline_re.sub(r'\\textbackslash{}n',strng)
619 strng = newline_re.sub(r'\\textbackslash{}n',strng)
618 return strng
620 return strng
619
621
620 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
622 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
621 """Parse options passed to an argument string.
623 """Parse options passed to an argument string.
622
624
623 The interface is similar to that of :func:`getopt.getopt`, but it
625 The interface is similar to that of :func:`getopt.getopt`, but it
624 returns a :class:`~IPython.utils.struct.Struct` with the options as keys
626 returns a :class:`~IPython.utils.struct.Struct` with the options as keys
625 and the stripped argument string still as a string.
627 and the stripped argument string still as a string.
626
628
627 arg_str is quoted as a true sys.argv vector by using shlex.split.
629 arg_str is quoted as a true sys.argv vector by using shlex.split.
628 This allows us to easily expand variables, glob files, quote
630 This allows us to easily expand variables, glob files, quote
629 arguments, etc.
631 arguments, etc.
630
632
631 Parameters
633 Parameters
632 ----------
634 ----------
633 arg_str : str
635 arg_str : str
634 The arguments to parse.
636 The arguments to parse.
635 opt_str : str
637 opt_str : str
636 The options specification.
638 The options specification.
637 mode : str, default 'string'
639 mode : str, default 'string'
638 If given as 'list', the argument string is returned as a list (split
640 If given as 'list', the argument string is returned as a list (split
639 on whitespace) instead of a string.
641 on whitespace) instead of a string.
640 list_all : bool, default False
642 list_all : bool, default False
641 Put all option values in lists. Normally only options
643 Put all option values in lists. Normally only options
642 appearing more than once are put in a list.
644 appearing more than once are put in a list.
643 posix : bool, default True
645 posix : bool, default True
644 Whether to split the input line in POSIX mode or not, as per the
646 Whether to split the input line in POSIX mode or not, as per the
645 conventions outlined in the :mod:`shlex` module from the standard
647 conventions outlined in the :mod:`shlex` module from the standard
646 library.
648 library.
647 """
649 """
648
650
649 # inject default options at the beginning of the input line
651 # inject default options at the beginning of the input line
650 caller = sys._getframe(1).f_code.co_name
652 caller = sys._getframe(1).f_code.co_name
651 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
653 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
652
654
653 mode = kw.get('mode','string')
655 mode = kw.get('mode','string')
654 if mode not in ['string','list']:
656 if mode not in ['string','list']:
655 raise ValueError('incorrect mode given: %s' % mode)
657 raise ValueError('incorrect mode given: %s' % mode)
656 # Get options
658 # Get options
657 list_all = kw.get('list_all',0)
659 list_all = kw.get('list_all',0)
658 posix = kw.get('posix', os.name == 'posix')
660 posix = kw.get('posix', os.name == 'posix')
659 strict = kw.get('strict', True)
661 strict = kw.get('strict', True)
660
662
661 preserve_non_opts = kw.get("preserve_non_opts", False)
663 preserve_non_opts = kw.get("preserve_non_opts", False)
662 remainder_arg_str = arg_str
664 remainder_arg_str = arg_str
663
665
664 # Check if we have more than one argument to warrant extra processing:
666 # Check if we have more than one argument to warrant extra processing:
665 odict = {} # Dictionary with options
667 odict = {} # Dictionary with options
666 args = arg_str.split()
668 args = arg_str.split()
667 if len(args) >= 1:
669 if len(args) >= 1:
668 # If the list of inputs only has 0 or 1 thing in it, there's no
670 # If the list of inputs only has 0 or 1 thing in it, there's no
669 # need to look for options
671 # need to look for options
670 argv = arg_split(arg_str, posix, strict)
672 argv = arg_split(arg_str, posix, strict)
671 # Do regular option processing
673 # Do regular option processing
672 try:
674 try:
673 opts,args = getopt(argv, opt_str, long_opts)
675 opts,args = getopt(argv, opt_str, long_opts)
674 except GetoptError as e:
676 except GetoptError as e:
675 raise UsageError(
677 raise UsageError(
676 '%s ( allowed: "%s" %s)' % (e.msg, opt_str, " ".join(long_opts))
678 '%s ( allowed: "%s" %s)' % (e.msg, opt_str, " ".join(long_opts))
677 ) from e
679 ) from e
678 for o, a in opts:
680 for o, a in opts:
679 if mode == "string" and preserve_non_opts:
681 if mode == "string" and preserve_non_opts:
680 # remove option-parts from the original args-string and preserve remaining-part.
682 # remove option-parts from the original args-string and preserve remaining-part.
681 # This relies on the arg_split(...) and getopt(...)'s impl spec, that the parsed options are
683 # This relies on the arg_split(...) and getopt(...)'s impl spec, that the parsed options are
682 # returned in the original order.
684 # returned in the original order.
683 remainder_arg_str = remainder_arg_str.replace(o, "", 1).replace(
685 remainder_arg_str = remainder_arg_str.replace(o, "", 1).replace(
684 a, "", 1
686 a, "", 1
685 )
687 )
686 if o.startswith("--"):
688 if o.startswith("--"):
687 o = o[2:]
689 o = o[2:]
688 else:
690 else:
689 o = o[1:]
691 o = o[1:]
690 try:
692 try:
691 odict[o].append(a)
693 odict[o].append(a)
692 except AttributeError:
694 except AttributeError:
693 odict[o] = [odict[o],a]
695 odict[o] = [odict[o],a]
694 except KeyError:
696 except KeyError:
695 if list_all:
697 if list_all:
696 odict[o] = [a]
698 odict[o] = [a]
697 else:
699 else:
698 odict[o] = a
700 odict[o] = a
699
701
700 # Prepare opts,args for return
702 # Prepare opts,args for return
701 opts = Struct(odict)
703 opts = Struct(odict)
702 if mode == 'string':
704 if mode == 'string':
703 if preserve_non_opts:
705 if preserve_non_opts:
704 args = remainder_arg_str.lstrip()
706 args = remainder_arg_str.lstrip()
705 else:
707 else:
706 args = " ".join(args)
708 args = " ".join(args)
707
709
708 return opts,args
710 return opts,args
709
711
710 def default_option(self, fn, optstr):
712 def default_option(self, fn, optstr):
711 """Make an entry in the options_table for fn, with value optstr"""
713 """Make an entry in the options_table for fn, with value optstr"""
712
714
713 if fn not in self.lsmagic():
715 if fn not in self.lsmagic():
714 error("%s is not a magic function" % fn)
716 error("%s is not a magic function" % fn)
715 self.options_table[fn] = optstr
717 self.options_table[fn] = optstr
716
718
717
719
718 class MagicAlias(object):
720 class MagicAlias(object):
719 """An alias to another magic function.
721 """An alias to another magic function.
720
722
721 An alias is determined by its magic name and magic kind. Lookup
723 An alias is determined by its magic name and magic kind. Lookup
722 is done at call time, so if the underlying magic changes the alias
724 is done at call time, so if the underlying magic changes the alias
723 will call the new function.
725 will call the new function.
724
726
725 Use the :meth:`MagicsManager.register_alias` method or the
727 Use the :meth:`MagicsManager.register_alias` method or the
726 `%alias_magic` magic function to create and register a new alias.
728 `%alias_magic` magic function to create and register a new alias.
727 """
729 """
728 def __init__(self, shell, magic_name, magic_kind, magic_params=None):
730 def __init__(self, shell, magic_name, magic_kind, magic_params=None):
729 self.shell = shell
731 self.shell = shell
730 self.magic_name = magic_name
732 self.magic_name = magic_name
731 self.magic_params = magic_params
733 self.magic_params = magic_params
732 self.magic_kind = magic_kind
734 self.magic_kind = magic_kind
733
735
734 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
736 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
735 self.__doc__ = "Alias for `%s`." % self.pretty_target
737 self.__doc__ = "Alias for `%s`." % self.pretty_target
736
738
737 self._in_call = False
739 self._in_call = False
738
740
739 def __call__(self, *args, **kwargs):
741 def __call__(self, *args, **kwargs):
740 """Call the magic alias."""
742 """Call the magic alias."""
741 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
743 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
742 if fn is None:
744 if fn is None:
743 raise UsageError("Magic `%s` not found." % self.pretty_target)
745 raise UsageError("Magic `%s` not found." % self.pretty_target)
744
746
745 # Protect against infinite recursion.
747 # Protect against infinite recursion.
746 if self._in_call:
748 if self._in_call:
747 raise UsageError("Infinite recursion detected; "
749 raise UsageError("Infinite recursion detected; "
748 "magic aliases cannot call themselves.")
750 "magic aliases cannot call themselves.")
749 self._in_call = True
751 self._in_call = True
750 try:
752 try:
751 if self.magic_params:
753 if self.magic_params:
752 args_list = list(args)
754 args_list = list(args)
753 args_list[0] = self.magic_params + " " + args[0]
755 args_list[0] = self.magic_params + " " + args[0]
754 args = tuple(args_list)
756 args = tuple(args_list)
755 return fn(*args, **kwargs)
757 return fn(*args, **kwargs)
756 finally:
758 finally:
757 self._in_call = False
759 self._in_call = False
@@ -1,944 +1,946 b''
1 # -*- coding: utf-8 -*-
2 """
1 """
3 Python advanced pretty printer. This pretty printer is intended to
2 Python advanced pretty printer. This pretty printer is intended to
4 replace the old `pprint` python module which does not allow developers
3 replace the old `pprint` python module which does not allow developers
5 to provide their own pretty print callbacks.
4 to provide their own pretty print callbacks.
6
5
7 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
6 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
8
7
9
8
10 Example Usage
9 Example Usage
11 -------------
10 -------------
12
11
13 To directly print the representation of an object use `pprint`::
12 To directly print the representation of an object use `pprint`::
14
13
15 from pretty import pprint
14 from pretty import pprint
16 pprint(complex_object)
15 pprint(complex_object)
17
16
18 To get a string of the output use `pretty`::
17 To get a string of the output use `pretty`::
19
18
20 from pretty import pretty
19 from pretty import pretty
21 string = pretty(complex_object)
20 string = pretty(complex_object)
22
21
23
22
24 Extending
23 Extending
25 ---------
24 ---------
26
25
27 The pretty library allows developers to add pretty printing rules for their
26 The pretty library allows developers to add pretty printing rules for their
28 own objects. This process is straightforward. All you have to do is to
27 own objects. This process is straightforward. All you have to do is to
29 add a `_repr_pretty_` method to your object and call the methods on the
28 add a `_repr_pretty_` method to your object and call the methods on the
30 pretty printer passed::
29 pretty printer passed::
31
30
32 class MyObject(object):
31 class MyObject(object):
33
32
34 def _repr_pretty_(self, p, cycle):
33 def _repr_pretty_(self, p, cycle):
35 ...
34 ...
36
35
37 Here's an example for a class with a simple constructor::
36 Here's an example for a class with a simple constructor::
38
37
39 class MySimpleObject:
38 class MySimpleObject:
40
39
41 def __init__(self, a, b, *, c=None):
40 def __init__(self, a, b, *, c=None):
42 self.a = a
41 self.a = a
43 self.b = b
42 self.b = b
44 self.c = c
43 self.c = c
45
44
46 def _repr_pretty_(self, p, cycle):
45 def _repr_pretty_(self, p, cycle):
47 ctor = CallExpression.factory(self.__class__.__name__)
46 ctor = CallExpression.factory(self.__class__.__name__)
48 if self.c is None:
47 if self.c is None:
49 p.pretty(ctor(a, b))
48 p.pretty(ctor(a, b))
50 else:
49 else:
51 p.pretty(ctor(a, b, c=c))
50 p.pretty(ctor(a, b, c=c))
52
51
53 Here is an example implementation of a `_repr_pretty_` method for a list
52 Here is an example implementation of a `_repr_pretty_` method for a list
54 subclass::
53 subclass::
55
54
56 class MyList(list):
55 class MyList(list):
57
56
58 def _repr_pretty_(self, p, cycle):
57 def _repr_pretty_(self, p, cycle):
59 if cycle:
58 if cycle:
60 p.text('MyList(...)')
59 p.text('MyList(...)')
61 else:
60 else:
62 with p.group(8, 'MyList([', '])'):
61 with p.group(8, 'MyList([', '])'):
63 for idx, item in enumerate(self):
62 for idx, item in enumerate(self):
64 if idx:
63 if idx:
65 p.text(',')
64 p.text(',')
66 p.breakable()
65 p.breakable()
67 p.pretty(item)
66 p.pretty(item)
68
67
69 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
68 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
70 react to that or the result is an infinite loop. `p.text()` just adds
69 react to that or the result is an infinite loop. `p.text()` just adds
71 non breaking text to the output, `p.breakable()` either adds a whitespace
70 non breaking text to the output, `p.breakable()` either adds a whitespace
72 or breaks here. If you pass it an argument it's used instead of the
71 or breaks here. If you pass it an argument it's used instead of the
73 default space. `p.pretty` prettyprints another object using the pretty print
72 default space. `p.pretty` prettyprints another object using the pretty print
74 method.
73 method.
75
74
76 The first parameter to the `group` function specifies the extra indentation
75 The first parameter to the `group` function specifies the extra indentation
77 of the next line. In this example the next item will either be on the same
76 of the next line. In this example the next item will either be on the same
78 line (if the items are short enough) or aligned with the right edge of the
77 line (if the items are short enough) or aligned with the right edge of the
79 opening bracket of `MyList`.
78 opening bracket of `MyList`.
80
79
81 If you just want to indent something you can use the group function
80 If you just want to indent something you can use the group function
82 without open / close parameters. You can also use this code::
81 without open / close parameters. You can also use this code::
83
82
84 with p.indent(2):
83 with p.indent(2):
85 ...
84 ...
86
85
87 Inheritance diagram:
86 Inheritance diagram:
88
87
89 .. inheritance-diagram:: IPython.lib.pretty
88 .. inheritance-diagram:: IPython.lib.pretty
90 :parts: 3
89 :parts: 3
91
90
92 :copyright: 2007 by Armin Ronacher.
91 :copyright: 2007 by Armin Ronacher.
93 Portions (c) 2009 by Robert Kern.
92 Portions (c) 2009 by Robert Kern.
94 :license: BSD License.
93 :license: BSD License.
95 """
94 """
96
95
97 from contextlib import contextmanager
96 from contextlib import contextmanager
98 import datetime
97 import datetime
99 import os
98 import os
100 import re
99 import re
101 import sys
100 import sys
102 import types
101 import types
103 from collections import deque
102 from collections import deque
104 from inspect import signature
103 from inspect import signature
105 from io import StringIO
104 from io import StringIO
106 from warnings import warn
105 from warnings import warn
107
106
108 from IPython.utils.decorators import undoc
107 from IPython.utils.decorators import undoc
109 from IPython.utils.py3compat import PYPY
108 from IPython.utils.py3compat import PYPY
110
109
110 from typing import Dict
111
111 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
112 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
112 'for_type', 'for_type_by_name', 'RawText', 'RawStringLiteral', 'CallExpression']
113 'for_type', 'for_type_by_name', 'RawText', 'RawStringLiteral', 'CallExpression']
113
114
114
115
115 MAX_SEQ_LENGTH = 1000
116 MAX_SEQ_LENGTH = 1000
116 _re_pattern_type = type(re.compile(''))
117 _re_pattern_type = type(re.compile(''))
117
118
118 def _safe_getattr(obj, attr, default=None):
119 def _safe_getattr(obj, attr, default=None):
119 """Safe version of getattr.
120 """Safe version of getattr.
120
121
121 Same as getattr, but will return ``default`` on any Exception,
122 Same as getattr, but will return ``default`` on any Exception,
122 rather than raising.
123 rather than raising.
123 """
124 """
124 try:
125 try:
125 return getattr(obj, attr, default)
126 return getattr(obj, attr, default)
126 except Exception:
127 except Exception:
127 return default
128 return default
128
129
129 @undoc
130 @undoc
130 class CUnicodeIO(StringIO):
131 class CUnicodeIO(StringIO):
131 def __init__(self, *args, **kwargs):
132 def __init__(self, *args, **kwargs):
132 super().__init__(*args, **kwargs)
133 super().__init__(*args, **kwargs)
133 warn(("CUnicodeIO is deprecated since IPython 6.0. "
134 warn(("CUnicodeIO is deprecated since IPython 6.0. "
134 "Please use io.StringIO instead."),
135 "Please use io.StringIO instead."),
135 DeprecationWarning, stacklevel=2)
136 DeprecationWarning, stacklevel=2)
136
137
137 def _sorted_for_pprint(items):
138 def _sorted_for_pprint(items):
138 """
139 """
139 Sort the given items for pretty printing. Since some predictable
140 Sort the given items for pretty printing. Since some predictable
140 sorting is better than no sorting at all, we sort on the string
141 sorting is better than no sorting at all, we sort on the string
141 representation if normal sorting fails.
142 representation if normal sorting fails.
142 """
143 """
143 items = list(items)
144 items = list(items)
144 try:
145 try:
145 return sorted(items)
146 return sorted(items)
146 except Exception:
147 except Exception:
147 try:
148 try:
148 return sorted(items, key=str)
149 return sorted(items, key=str)
149 except Exception:
150 except Exception:
150 return items
151 return items
151
152
152 def pretty(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
153 def pretty(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
153 """
154 """
154 Pretty print the object's representation.
155 Pretty print the object's representation.
155 """
156 """
156 stream = StringIO()
157 stream = StringIO()
157 printer = RepresentationPrinter(stream, verbose, max_width, newline, max_seq_length=max_seq_length)
158 printer = RepresentationPrinter(stream, verbose, max_width, newline, max_seq_length=max_seq_length)
158 printer.pretty(obj)
159 printer.pretty(obj)
159 printer.flush()
160 printer.flush()
160 return stream.getvalue()
161 return stream.getvalue()
161
162
162
163
163 def pprint(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
164 def pprint(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
164 """
165 """
165 Like `pretty` but print to stdout.
166 Like `pretty` but print to stdout.
166 """
167 """
167 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline, max_seq_length=max_seq_length)
168 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline, max_seq_length=max_seq_length)
168 printer.pretty(obj)
169 printer.pretty(obj)
169 printer.flush()
170 printer.flush()
170 sys.stdout.write(newline)
171 sys.stdout.write(newline)
171 sys.stdout.flush()
172 sys.stdout.flush()
172
173
173 class _PrettyPrinterBase(object):
174 class _PrettyPrinterBase(object):
174
175
175 @contextmanager
176 @contextmanager
176 def indent(self, indent):
177 def indent(self, indent):
177 """with statement support for indenting/dedenting."""
178 """with statement support for indenting/dedenting."""
178 self.indentation += indent
179 self.indentation += indent
179 try:
180 try:
180 yield
181 yield
181 finally:
182 finally:
182 self.indentation -= indent
183 self.indentation -= indent
183
184
184 @contextmanager
185 @contextmanager
185 def group(self, indent=0, open='', close=''):
186 def group(self, indent=0, open='', close=''):
186 """like begin_group / end_group but for the with statement."""
187 """like begin_group / end_group but for the with statement."""
187 self.begin_group(indent, open)
188 self.begin_group(indent, open)
188 try:
189 try:
189 yield
190 yield
190 finally:
191 finally:
191 self.end_group(indent, close)
192 self.end_group(indent, close)
192
193
193 class PrettyPrinter(_PrettyPrinterBase):
194 class PrettyPrinter(_PrettyPrinterBase):
194 """
195 """
195 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
196 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
196 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
197 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
197 this printer knows nothing about the default pprinters or the `_repr_pretty_`
198 this printer knows nothing about the default pprinters or the `_repr_pretty_`
198 callback method.
199 callback method.
199 """
200 """
200
201
201 def __init__(self, output, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
202 def __init__(self, output, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
202 self.output = output
203 self.output = output
203 self.max_width = max_width
204 self.max_width = max_width
204 self.newline = newline
205 self.newline = newline
205 self.max_seq_length = max_seq_length
206 self.max_seq_length = max_seq_length
206 self.output_width = 0
207 self.output_width = 0
207 self.buffer_width = 0
208 self.buffer_width = 0
208 self.buffer = deque()
209 self.buffer = deque()
209
210
210 root_group = Group(0)
211 root_group = Group(0)
211 self.group_stack = [root_group]
212 self.group_stack = [root_group]
212 self.group_queue = GroupQueue(root_group)
213 self.group_queue = GroupQueue(root_group)
213 self.indentation = 0
214 self.indentation = 0
214
215
215 def _break_one_group(self, group):
216 def _break_one_group(self, group):
216 while group.breakables:
217 while group.breakables:
217 x = self.buffer.popleft()
218 x = self.buffer.popleft()
218 self.output_width = x.output(self.output, self.output_width)
219 self.output_width = x.output(self.output, self.output_width)
219 self.buffer_width -= x.width
220 self.buffer_width -= x.width
220 while self.buffer and isinstance(self.buffer[0], Text):
221 while self.buffer and isinstance(self.buffer[0], Text):
221 x = self.buffer.popleft()
222 x = self.buffer.popleft()
222 self.output_width = x.output(self.output, self.output_width)
223 self.output_width = x.output(self.output, self.output_width)
223 self.buffer_width -= x.width
224 self.buffer_width -= x.width
224
225
225 def _break_outer_groups(self):
226 def _break_outer_groups(self):
226 while self.max_width < self.output_width + self.buffer_width:
227 while self.max_width < self.output_width + self.buffer_width:
227 group = self.group_queue.deq()
228 group = self.group_queue.deq()
228 if not group:
229 if not group:
229 return
230 return
230 self._break_one_group(group)
231 self._break_one_group(group)
231
232
232 def text(self, obj):
233 def text(self, obj):
233 """Add literal text to the output."""
234 """Add literal text to the output."""
234 width = len(obj)
235 width = len(obj)
235 if self.buffer:
236 if self.buffer:
236 text = self.buffer[-1]
237 text = self.buffer[-1]
237 if not isinstance(text, Text):
238 if not isinstance(text, Text):
238 text = Text()
239 text = Text()
239 self.buffer.append(text)
240 self.buffer.append(text)
240 text.add(obj, width)
241 text.add(obj, width)
241 self.buffer_width += width
242 self.buffer_width += width
242 self._break_outer_groups()
243 self._break_outer_groups()
243 else:
244 else:
244 self.output.write(obj)
245 self.output.write(obj)
245 self.output_width += width
246 self.output_width += width
246
247
247 def breakable(self, sep=' '):
248 def breakable(self, sep=' '):
248 """
249 """
249 Add a breakable separator to the output. This does not mean that it
250 Add a breakable separator to the output. This does not mean that it
250 will automatically break here. If no breaking on this position takes
251 will automatically break here. If no breaking on this position takes
251 place the `sep` is inserted which default to one space.
252 place the `sep` is inserted which default to one space.
252 """
253 """
253 width = len(sep)
254 width = len(sep)
254 group = self.group_stack[-1]
255 group = self.group_stack[-1]
255 if group.want_break:
256 if group.want_break:
256 self.flush()
257 self.flush()
257 self.output.write(self.newline)
258 self.output.write(self.newline)
258 self.output.write(' ' * self.indentation)
259 self.output.write(' ' * self.indentation)
259 self.output_width = self.indentation
260 self.output_width = self.indentation
260 self.buffer_width = 0
261 self.buffer_width = 0
261 else:
262 else:
262 self.buffer.append(Breakable(sep, width, self))
263 self.buffer.append(Breakable(sep, width, self))
263 self.buffer_width += width
264 self.buffer_width += width
264 self._break_outer_groups()
265 self._break_outer_groups()
265
266
266 def break_(self):
267 def break_(self):
267 """
268 """
268 Explicitly insert a newline into the output, maintaining correct indentation.
269 Explicitly insert a newline into the output, maintaining correct indentation.
269 """
270 """
270 group = self.group_queue.deq()
271 group = self.group_queue.deq()
271 if group:
272 if group:
272 self._break_one_group(group)
273 self._break_one_group(group)
273 self.flush()
274 self.flush()
274 self.output.write(self.newline)
275 self.output.write(self.newline)
275 self.output.write(' ' * self.indentation)
276 self.output.write(' ' * self.indentation)
276 self.output_width = self.indentation
277 self.output_width = self.indentation
277 self.buffer_width = 0
278 self.buffer_width = 0
278
279
279
280
280 def begin_group(self, indent=0, open=''):
281 def begin_group(self, indent=0, open=''):
281 """
282 """
282 Begin a group.
283 Begin a group.
283 The first parameter specifies the indentation for the next line (usually
284 The first parameter specifies the indentation for the next line (usually
284 the width of the opening text), the second the opening text. All
285 the width of the opening text), the second the opening text. All
285 parameters are optional.
286 parameters are optional.
286 """
287 """
287 if open:
288 if open:
288 self.text(open)
289 self.text(open)
289 group = Group(self.group_stack[-1].depth + 1)
290 group = Group(self.group_stack[-1].depth + 1)
290 self.group_stack.append(group)
291 self.group_stack.append(group)
291 self.group_queue.enq(group)
292 self.group_queue.enq(group)
292 self.indentation += indent
293 self.indentation += indent
293
294
294 def _enumerate(self, seq):
295 def _enumerate(self, seq):
295 """like enumerate, but with an upper limit on the number of items"""
296 """like enumerate, but with an upper limit on the number of items"""
296 for idx, x in enumerate(seq):
297 for idx, x in enumerate(seq):
297 if self.max_seq_length and idx >= self.max_seq_length:
298 if self.max_seq_length and idx >= self.max_seq_length:
298 self.text(',')
299 self.text(',')
299 self.breakable()
300 self.breakable()
300 self.text('...')
301 self.text('...')
301 return
302 return
302 yield idx, x
303 yield idx, x
303
304
304 def end_group(self, dedent=0, close=''):
305 def end_group(self, dedent=0, close=''):
305 """End a group. See `begin_group` for more details."""
306 """End a group. See `begin_group` for more details."""
306 self.indentation -= dedent
307 self.indentation -= dedent
307 group = self.group_stack.pop()
308 group = self.group_stack.pop()
308 if not group.breakables:
309 if not group.breakables:
309 self.group_queue.remove(group)
310 self.group_queue.remove(group)
310 if close:
311 if close:
311 self.text(close)
312 self.text(close)
312
313
313 def flush(self):
314 def flush(self):
314 """Flush data that is left in the buffer."""
315 """Flush data that is left in the buffer."""
315 for data in self.buffer:
316 for data in self.buffer:
316 self.output_width += data.output(self.output, self.output_width)
317 self.output_width += data.output(self.output, self.output_width)
317 self.buffer.clear()
318 self.buffer.clear()
318 self.buffer_width = 0
319 self.buffer_width = 0
319
320
320
321
321 def _get_mro(obj_class):
322 def _get_mro(obj_class):
322 """ Get a reasonable method resolution order of a class and its superclasses
323 """ Get a reasonable method resolution order of a class and its superclasses
323 for both old-style and new-style classes.
324 for both old-style and new-style classes.
324 """
325 """
325 if not hasattr(obj_class, '__mro__'):
326 if not hasattr(obj_class, '__mro__'):
326 # Old-style class. Mix in object to make a fake new-style class.
327 # Old-style class. Mix in object to make a fake new-style class.
327 try:
328 try:
328 obj_class = type(obj_class.__name__, (obj_class, object), {})
329 obj_class = type(obj_class.__name__, (obj_class, object), {})
329 except TypeError:
330 except TypeError:
330 # Old-style extension type that does not descend from object.
331 # Old-style extension type that does not descend from object.
331 # FIXME: try to construct a more thorough MRO.
332 # FIXME: try to construct a more thorough MRO.
332 mro = [obj_class]
333 mro = [obj_class]
333 else:
334 else:
334 mro = obj_class.__mro__[1:-1]
335 mro = obj_class.__mro__[1:-1]
335 else:
336 else:
336 mro = obj_class.__mro__
337 mro = obj_class.__mro__
337 return mro
338 return mro
338
339
339
340
340 class RepresentationPrinter(PrettyPrinter):
341 class RepresentationPrinter(PrettyPrinter):
341 """
342 """
342 Special pretty printer that has a `pretty` method that calls the pretty
343 Special pretty printer that has a `pretty` method that calls the pretty
343 printer for a python object.
344 printer for a python object.
344
345
345 This class stores processing data on `self` so you must *never* use
346 This class stores processing data on `self` so you must *never* use
346 this class in a threaded environment. Always lock it or reinstanciate
347 this class in a threaded environment. Always lock it or reinstanciate
347 it.
348 it.
348
349
349 Instances also have a verbose flag callbacks can access to control their
350 Instances also have a verbose flag callbacks can access to control their
350 output. For example the default instance repr prints all attributes and
351 output. For example the default instance repr prints all attributes and
351 methods that are not prefixed by an underscore if the printer is in
352 methods that are not prefixed by an underscore if the printer is in
352 verbose mode.
353 verbose mode.
353 """
354 """
354
355
355 def __init__(self, output, verbose=False, max_width=79, newline='\n',
356 def __init__(self, output, verbose=False, max_width=79, newline='\n',
356 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None,
357 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None,
357 max_seq_length=MAX_SEQ_LENGTH):
358 max_seq_length=MAX_SEQ_LENGTH):
358
359
359 PrettyPrinter.__init__(self, output, max_width, newline, max_seq_length=max_seq_length)
360 PrettyPrinter.__init__(self, output, max_width, newline, max_seq_length=max_seq_length)
360 self.verbose = verbose
361 self.verbose = verbose
361 self.stack = []
362 self.stack = []
362 if singleton_pprinters is None:
363 if singleton_pprinters is None:
363 singleton_pprinters = _singleton_pprinters.copy()
364 singleton_pprinters = _singleton_pprinters.copy()
364 self.singleton_pprinters = singleton_pprinters
365 self.singleton_pprinters = singleton_pprinters
365 if type_pprinters is None:
366 if type_pprinters is None:
366 type_pprinters = _type_pprinters.copy()
367 type_pprinters = _type_pprinters.copy()
367 self.type_pprinters = type_pprinters
368 self.type_pprinters = type_pprinters
368 if deferred_pprinters is None:
369 if deferred_pprinters is None:
369 deferred_pprinters = _deferred_type_pprinters.copy()
370 deferred_pprinters = _deferred_type_pprinters.copy()
370 self.deferred_pprinters = deferred_pprinters
371 self.deferred_pprinters = deferred_pprinters
371
372
372 def pretty(self, obj):
373 def pretty(self, obj):
373 """Pretty print the given object."""
374 """Pretty print the given object."""
374 obj_id = id(obj)
375 obj_id = id(obj)
375 cycle = obj_id in self.stack
376 cycle = obj_id in self.stack
376 self.stack.append(obj_id)
377 self.stack.append(obj_id)
377 self.begin_group()
378 self.begin_group()
378 try:
379 try:
379 obj_class = _safe_getattr(obj, '__class__', None) or type(obj)
380 obj_class = _safe_getattr(obj, '__class__', None) or type(obj)
380 # First try to find registered singleton printers for the type.
381 # First try to find registered singleton printers for the type.
381 try:
382 try:
382 printer = self.singleton_pprinters[obj_id]
383 printer = self.singleton_pprinters[obj_id]
383 except (TypeError, KeyError):
384 except (TypeError, KeyError):
384 pass
385 pass
385 else:
386 else:
386 return printer(obj, self, cycle)
387 return printer(obj, self, cycle)
387 # Next walk the mro and check for either:
388 # Next walk the mro and check for either:
388 # 1) a registered printer
389 # 1) a registered printer
389 # 2) a _repr_pretty_ method
390 # 2) a _repr_pretty_ method
390 for cls in _get_mro(obj_class):
391 for cls in _get_mro(obj_class):
391 if cls in self.type_pprinters:
392 if cls in self.type_pprinters:
392 # printer registered in self.type_pprinters
393 # printer registered in self.type_pprinters
393 return self.type_pprinters[cls](obj, self, cycle)
394 return self.type_pprinters[cls](obj, self, cycle)
394 else:
395 else:
395 # deferred printer
396 # deferred printer
396 printer = self._in_deferred_types(cls)
397 printer = self._in_deferred_types(cls)
397 if printer is not None:
398 if printer is not None:
398 return printer(obj, self, cycle)
399 return printer(obj, self, cycle)
399 else:
400 else:
400 # Finally look for special method names.
401 # Finally look for special method names.
401 # Some objects automatically create any requested
402 # Some objects automatically create any requested
402 # attribute. Try to ignore most of them by checking for
403 # attribute. Try to ignore most of them by checking for
403 # callability.
404 # callability.
404 if '_repr_pretty_' in cls.__dict__:
405 if '_repr_pretty_' in cls.__dict__:
405 meth = cls._repr_pretty_
406 meth = cls._repr_pretty_
406 if callable(meth):
407 if callable(meth):
407 return meth(obj, self, cycle)
408 return meth(obj, self, cycle)
408 if cls is not object \
409 if cls is not object \
409 and callable(cls.__dict__.get('__repr__')):
410 and callable(cls.__dict__.get('__repr__')):
410 return _repr_pprint(obj, self, cycle)
411 return _repr_pprint(obj, self, cycle)
411
412
412 return _default_pprint(obj, self, cycle)
413 return _default_pprint(obj, self, cycle)
413 finally:
414 finally:
414 self.end_group()
415 self.end_group()
415 self.stack.pop()
416 self.stack.pop()
416
417
417 def _in_deferred_types(self, cls):
418 def _in_deferred_types(self, cls):
418 """
419 """
419 Check if the given class is specified in the deferred type registry.
420 Check if the given class is specified in the deferred type registry.
420
421
421 Returns the printer from the registry if it exists, and None if the
422 Returns the printer from the registry if it exists, and None if the
422 class is not in the registry. Successful matches will be moved to the
423 class is not in the registry. Successful matches will be moved to the
423 regular type registry for future use.
424 regular type registry for future use.
424 """
425 """
425 mod = _safe_getattr(cls, '__module__', None)
426 mod = _safe_getattr(cls, '__module__', None)
426 name = _safe_getattr(cls, '__name__', None)
427 name = _safe_getattr(cls, '__name__', None)
427 key = (mod, name)
428 key = (mod, name)
428 printer = None
429 printer = None
429 if key in self.deferred_pprinters:
430 if key in self.deferred_pprinters:
430 # Move the printer over to the regular registry.
431 # Move the printer over to the regular registry.
431 printer = self.deferred_pprinters.pop(key)
432 printer = self.deferred_pprinters.pop(key)
432 self.type_pprinters[cls] = printer
433 self.type_pprinters[cls] = printer
433 return printer
434 return printer
434
435
435
436
436 class Printable(object):
437 class Printable(object):
437
438
438 def output(self, stream, output_width):
439 def output(self, stream, output_width):
439 return output_width
440 return output_width
440
441
441
442
442 class Text(Printable):
443 class Text(Printable):
443
444
444 def __init__(self):
445 def __init__(self):
445 self.objs = []
446 self.objs = []
446 self.width = 0
447 self.width = 0
447
448
448 def output(self, stream, output_width):
449 def output(self, stream, output_width):
449 for obj in self.objs:
450 for obj in self.objs:
450 stream.write(obj)
451 stream.write(obj)
451 return output_width + self.width
452 return output_width + self.width
452
453
453 def add(self, obj, width):
454 def add(self, obj, width):
454 self.objs.append(obj)
455 self.objs.append(obj)
455 self.width += width
456 self.width += width
456
457
457
458
458 class Breakable(Printable):
459 class Breakable(Printable):
459
460
460 def __init__(self, seq, width, pretty):
461 def __init__(self, seq, width, pretty):
461 self.obj = seq
462 self.obj = seq
462 self.width = width
463 self.width = width
463 self.pretty = pretty
464 self.pretty = pretty
464 self.indentation = pretty.indentation
465 self.indentation = pretty.indentation
465 self.group = pretty.group_stack[-1]
466 self.group = pretty.group_stack[-1]
466 self.group.breakables.append(self)
467 self.group.breakables.append(self)
467
468
468 def output(self, stream, output_width):
469 def output(self, stream, output_width):
469 self.group.breakables.popleft()
470 self.group.breakables.popleft()
470 if self.group.want_break:
471 if self.group.want_break:
471 stream.write(self.pretty.newline)
472 stream.write(self.pretty.newline)
472 stream.write(' ' * self.indentation)
473 stream.write(' ' * self.indentation)
473 return self.indentation
474 return self.indentation
474 if not self.group.breakables:
475 if not self.group.breakables:
475 self.pretty.group_queue.remove(self.group)
476 self.pretty.group_queue.remove(self.group)
476 stream.write(self.obj)
477 stream.write(self.obj)
477 return output_width + self.width
478 return output_width + self.width
478
479
479
480
480 class Group(Printable):
481 class Group(Printable):
481
482
482 def __init__(self, depth):
483 def __init__(self, depth):
483 self.depth = depth
484 self.depth = depth
484 self.breakables = deque()
485 self.breakables = deque()
485 self.want_break = False
486 self.want_break = False
486
487
487
488
488 class GroupQueue(object):
489 class GroupQueue(object):
489
490
490 def __init__(self, *groups):
491 def __init__(self, *groups):
491 self.queue = []
492 self.queue = []
492 for group in groups:
493 for group in groups:
493 self.enq(group)
494 self.enq(group)
494
495
495 def enq(self, group):
496 def enq(self, group):
496 depth = group.depth
497 depth = group.depth
497 while depth > len(self.queue) - 1:
498 while depth > len(self.queue) - 1:
498 self.queue.append([])
499 self.queue.append([])
499 self.queue[depth].append(group)
500 self.queue[depth].append(group)
500
501
501 def deq(self):
502 def deq(self):
502 for stack in self.queue:
503 for stack in self.queue:
503 for idx, group in enumerate(reversed(stack)):
504 for idx, group in enumerate(reversed(stack)):
504 if group.breakables:
505 if group.breakables:
505 del stack[idx]
506 del stack[idx]
506 group.want_break = True
507 group.want_break = True
507 return group
508 return group
508 for group in stack:
509 for group in stack:
509 group.want_break = True
510 group.want_break = True
510 del stack[:]
511 del stack[:]
511
512
512 def remove(self, group):
513 def remove(self, group):
513 try:
514 try:
514 self.queue[group.depth].remove(group)
515 self.queue[group.depth].remove(group)
515 except ValueError:
516 except ValueError:
516 pass
517 pass
517
518
518
519
519 class RawText:
520 class RawText:
520 """ Object such that ``p.pretty(RawText(value))`` is the same as ``p.text(value)``.
521 """ Object such that ``p.pretty(RawText(value))`` is the same as ``p.text(value)``.
521
522
522 An example usage of this would be to show a list as binary numbers, using
523 An example usage of this would be to show a list as binary numbers, using
523 ``p.pretty([RawText(bin(i)) for i in integers])``.
524 ``p.pretty([RawText(bin(i)) for i in integers])``.
524 """
525 """
525 def __init__(self, value):
526 def __init__(self, value):
526 self.value = value
527 self.value = value
527
528
528 def _repr_pretty_(self, p, cycle):
529 def _repr_pretty_(self, p, cycle):
529 p.text(self.value)
530 p.text(self.value)
530
531
531
532
532 class CallExpression:
533 class CallExpression:
533 """ Object which emits a line-wrapped call expression in the form `__name(*args, **kwargs)` """
534 """ Object which emits a line-wrapped call expression in the form `__name(*args, **kwargs)` """
534 def __init__(__self, __name, *args, **kwargs):
535 def __init__(__self, __name, *args, **kwargs):
535 # dunders are to avoid clashes with kwargs, as python's name manging
536 # dunders are to avoid clashes with kwargs, as python's name manging
536 # will kick in.
537 # will kick in.
537 self = __self
538 self = __self
538 self.name = __name
539 self.name = __name
539 self.args = args
540 self.args = args
540 self.kwargs = kwargs
541 self.kwargs = kwargs
541
542
542 @classmethod
543 @classmethod
543 def factory(cls, name):
544 def factory(cls, name):
544 def inner(*args, **kwargs):
545 def inner(*args, **kwargs):
545 return cls(name, *args, **kwargs)
546 return cls(name, *args, **kwargs)
546 return inner
547 return inner
547
548
548 def _repr_pretty_(self, p, cycle):
549 def _repr_pretty_(self, p, cycle):
549 # dunders are to avoid clashes with kwargs, as python's name manging
550 # dunders are to avoid clashes with kwargs, as python's name manging
550 # will kick in.
551 # will kick in.
551
552
552 started = False
553 started = False
553 def new_item():
554 def new_item():
554 nonlocal started
555 nonlocal started
555 if started:
556 if started:
556 p.text(",")
557 p.text(",")
557 p.breakable()
558 p.breakable()
558 started = True
559 started = True
559
560
560 prefix = self.name + "("
561 prefix = self.name + "("
561 with p.group(len(prefix), prefix, ")"):
562 with p.group(len(prefix), prefix, ")"):
562 for arg in self.args:
563 for arg in self.args:
563 new_item()
564 new_item()
564 p.pretty(arg)
565 p.pretty(arg)
565 for arg_name, arg in self.kwargs.items():
566 for arg_name, arg in self.kwargs.items():
566 new_item()
567 new_item()
567 arg_prefix = arg_name + "="
568 arg_prefix = arg_name + "="
568 with p.group(len(arg_prefix), arg_prefix):
569 with p.group(len(arg_prefix), arg_prefix):
569 p.pretty(arg)
570 p.pretty(arg)
570
571
571
572
572 class RawStringLiteral:
573 class RawStringLiteral:
573 """ Wrapper that shows a string with a `r` prefix """
574 """ Wrapper that shows a string with a `r` prefix """
574 def __init__(self, value):
575 def __init__(self, value):
575 self.value = value
576 self.value = value
576
577
577 def _repr_pretty_(self, p, cycle):
578 def _repr_pretty_(self, p, cycle):
578 base_repr = repr(self.value)
579 base_repr = repr(self.value)
579 if base_repr[:1] in 'uU':
580 if base_repr[:1] in 'uU':
580 base_repr = base_repr[1:]
581 base_repr = base_repr[1:]
581 prefix = 'ur'
582 prefix = 'ur'
582 else:
583 else:
583 prefix = 'r'
584 prefix = 'r'
584 base_repr = prefix + base_repr.replace('\\\\', '\\')
585 base_repr = prefix + base_repr.replace('\\\\', '\\')
585 p.text(base_repr)
586 p.text(base_repr)
586
587
587
588
588 def _default_pprint(obj, p, cycle):
589 def _default_pprint(obj, p, cycle):
589 """
590 """
590 The default print function. Used if an object does not provide one and
591 The default print function. Used if an object does not provide one and
591 it's none of the builtin objects.
592 it's none of the builtin objects.
592 """
593 """
593 klass = _safe_getattr(obj, '__class__', None) or type(obj)
594 klass = _safe_getattr(obj, '__class__', None) or type(obj)
594 if _safe_getattr(klass, '__repr__', None) is not object.__repr__:
595 if _safe_getattr(klass, '__repr__', None) is not object.__repr__:
595 # A user-provided repr. Find newlines and replace them with p.break_()
596 # A user-provided repr. Find newlines and replace them with p.break_()
596 _repr_pprint(obj, p, cycle)
597 _repr_pprint(obj, p, cycle)
597 return
598 return
598 p.begin_group(1, '<')
599 p.begin_group(1, '<')
599 p.pretty(klass)
600 p.pretty(klass)
600 p.text(' at 0x%x' % id(obj))
601 p.text(' at 0x%x' % id(obj))
601 if cycle:
602 if cycle:
602 p.text(' ...')
603 p.text(' ...')
603 elif p.verbose:
604 elif p.verbose:
604 first = True
605 first = True
605 for key in dir(obj):
606 for key in dir(obj):
606 if not key.startswith('_'):
607 if not key.startswith('_'):
607 try:
608 try:
608 value = getattr(obj, key)
609 value = getattr(obj, key)
609 except AttributeError:
610 except AttributeError:
610 continue
611 continue
611 if isinstance(value, types.MethodType):
612 if isinstance(value, types.MethodType):
612 continue
613 continue
613 if not first:
614 if not first:
614 p.text(',')
615 p.text(',')
615 p.breakable()
616 p.breakable()
616 p.text(key)
617 p.text(key)
617 p.text('=')
618 p.text('=')
618 step = len(key) + 1
619 step = len(key) + 1
619 p.indentation += step
620 p.indentation += step
620 p.pretty(value)
621 p.pretty(value)
621 p.indentation -= step
622 p.indentation -= step
622 first = False
623 first = False
623 p.end_group(1, '>')
624 p.end_group(1, '>')
624
625
625
626
626 def _seq_pprinter_factory(start, end):
627 def _seq_pprinter_factory(start, end):
627 """
628 """
628 Factory that returns a pprint function useful for sequences. Used by
629 Factory that returns a pprint function useful for sequences. Used by
629 the default pprint for tuples and lists.
630 the default pprint for tuples and lists.
630 """
631 """
631 def inner(obj, p, cycle):
632 def inner(obj, p, cycle):
632 if cycle:
633 if cycle:
633 return p.text(start + '...' + end)
634 return p.text(start + '...' + end)
634 step = len(start)
635 step = len(start)
635 p.begin_group(step, start)
636 p.begin_group(step, start)
636 for idx, x in p._enumerate(obj):
637 for idx, x in p._enumerate(obj):
637 if idx:
638 if idx:
638 p.text(',')
639 p.text(',')
639 p.breakable()
640 p.breakable()
640 p.pretty(x)
641 p.pretty(x)
641 if len(obj) == 1 and isinstance(obj, tuple):
642 if len(obj) == 1 and isinstance(obj, tuple):
642 # Special case for 1-item tuples.
643 # Special case for 1-item tuples.
643 p.text(',')
644 p.text(',')
644 p.end_group(step, end)
645 p.end_group(step, end)
645 return inner
646 return inner
646
647
647
648
648 def _set_pprinter_factory(start, end):
649 def _set_pprinter_factory(start, end):
649 """
650 """
650 Factory that returns a pprint function useful for sets and frozensets.
651 Factory that returns a pprint function useful for sets and frozensets.
651 """
652 """
652 def inner(obj, p, cycle):
653 def inner(obj, p, cycle):
653 if cycle:
654 if cycle:
654 return p.text(start + '...' + end)
655 return p.text(start + '...' + end)
655 if len(obj) == 0:
656 if len(obj) == 0:
656 # Special case.
657 # Special case.
657 p.text(type(obj).__name__ + '()')
658 p.text(type(obj).__name__ + '()')
658 else:
659 else:
659 step = len(start)
660 step = len(start)
660 p.begin_group(step, start)
661 p.begin_group(step, start)
661 # Like dictionary keys, we will try to sort the items if there aren't too many
662 # Like dictionary keys, we will try to sort the items if there aren't too many
662 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
663 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
663 items = _sorted_for_pprint(obj)
664 items = _sorted_for_pprint(obj)
664 else:
665 else:
665 items = obj
666 items = obj
666 for idx, x in p._enumerate(items):
667 for idx, x in p._enumerate(items):
667 if idx:
668 if idx:
668 p.text(',')
669 p.text(',')
669 p.breakable()
670 p.breakable()
670 p.pretty(x)
671 p.pretty(x)
671 p.end_group(step, end)
672 p.end_group(step, end)
672 return inner
673 return inner
673
674
674
675
675 def _dict_pprinter_factory(start, end):
676 def _dict_pprinter_factory(start, end):
676 """
677 """
677 Factory that returns a pprint function used by the default pprint of
678 Factory that returns a pprint function used by the default pprint of
678 dicts and dict proxies.
679 dicts and dict proxies.
679 """
680 """
680 def inner(obj, p, cycle):
681 def inner(obj, p, cycle):
681 if cycle:
682 if cycle:
682 return p.text('{...}')
683 return p.text('{...}')
683 step = len(start)
684 step = len(start)
684 p.begin_group(step, start)
685 p.begin_group(step, start)
685 keys = obj.keys()
686 keys = obj.keys()
686 for idx, key in p._enumerate(keys):
687 for idx, key in p._enumerate(keys):
687 if idx:
688 if idx:
688 p.text(',')
689 p.text(',')
689 p.breakable()
690 p.breakable()
690 p.pretty(key)
691 p.pretty(key)
691 p.text(': ')
692 p.text(': ')
692 p.pretty(obj[key])
693 p.pretty(obj[key])
693 p.end_group(step, end)
694 p.end_group(step, end)
694 return inner
695 return inner
695
696
696
697
697 def _super_pprint(obj, p, cycle):
698 def _super_pprint(obj, p, cycle):
698 """The pprint for the super type."""
699 """The pprint for the super type."""
699 p.begin_group(8, '<super: ')
700 p.begin_group(8, '<super: ')
700 p.pretty(obj.__thisclass__)
701 p.pretty(obj.__thisclass__)
701 p.text(',')
702 p.text(',')
702 p.breakable()
703 p.breakable()
703 if PYPY: # In PyPy, super() objects don't have __self__ attributes
704 if PYPY: # In PyPy, super() objects don't have __self__ attributes
704 dself = obj.__repr__.__self__
705 dself = obj.__repr__.__self__
705 p.pretty(None if dself is obj else dself)
706 p.pretty(None if dself is obj else dself)
706 else:
707 else:
707 p.pretty(obj.__self__)
708 p.pretty(obj.__self__)
708 p.end_group(8, '>')
709 p.end_group(8, '>')
709
710
710
711
711
712
712 class _ReFlags:
713 class _ReFlags:
713 def __init__(self, value):
714 def __init__(self, value):
714 self.value = value
715 self.value = value
715
716
716 def _repr_pretty_(self, p, cycle):
717 def _repr_pretty_(self, p, cycle):
717 done_one = False
718 done_one = False
718 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
719 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
719 'UNICODE', 'VERBOSE', 'DEBUG'):
720 'UNICODE', 'VERBOSE', 'DEBUG'):
720 if self.value & getattr(re, flag):
721 if self.value & getattr(re, flag):
721 if done_one:
722 if done_one:
722 p.text('|')
723 p.text('|')
723 p.text('re.' + flag)
724 p.text('re.' + flag)
724 done_one = True
725 done_one = True
725
726
726
727
727 def _re_pattern_pprint(obj, p, cycle):
728 def _re_pattern_pprint(obj, p, cycle):
728 """The pprint function for regular expression patterns."""
729 """The pprint function for regular expression patterns."""
729 re_compile = CallExpression.factory('re.compile')
730 re_compile = CallExpression.factory('re.compile')
730 if obj.flags:
731 if obj.flags:
731 p.pretty(re_compile(RawStringLiteral(obj.pattern), _ReFlags(obj.flags)))
732 p.pretty(re_compile(RawStringLiteral(obj.pattern), _ReFlags(obj.flags)))
732 else:
733 else:
733 p.pretty(re_compile(RawStringLiteral(obj.pattern)))
734 p.pretty(re_compile(RawStringLiteral(obj.pattern)))
734
735
735
736
736 def _types_simplenamespace_pprint(obj, p, cycle):
737 def _types_simplenamespace_pprint(obj, p, cycle):
737 """The pprint function for types.SimpleNamespace."""
738 """The pprint function for types.SimpleNamespace."""
738 namespace = CallExpression.factory('namespace')
739 namespace = CallExpression.factory('namespace')
739 if cycle:
740 if cycle:
740 p.pretty(namespace(RawText("...")))
741 p.pretty(namespace(RawText("...")))
741 else:
742 else:
742 p.pretty(namespace(**obj.__dict__))
743 p.pretty(namespace(**obj.__dict__))
743
744
744
745
745 def _type_pprint(obj, p, cycle):
746 def _type_pprint(obj, p, cycle):
746 """The pprint for classes and types."""
747 """The pprint for classes and types."""
747 # Heap allocated types might not have the module attribute,
748 # Heap allocated types might not have the module attribute,
748 # and others may set it to None.
749 # and others may set it to None.
749
750
750 # Checks for a __repr__ override in the metaclass. Can't compare the
751 # Checks for a __repr__ override in the metaclass. Can't compare the
751 # type(obj).__repr__ directly because in PyPy the representation function
752 # type(obj).__repr__ directly because in PyPy the representation function
752 # inherited from type isn't the same type.__repr__
753 # inherited from type isn't the same type.__repr__
753 if [m for m in _get_mro(type(obj)) if "__repr__" in vars(m)][:1] != [type]:
754 if [m for m in _get_mro(type(obj)) if "__repr__" in vars(m)][:1] != [type]:
754 _repr_pprint(obj, p, cycle)
755 _repr_pprint(obj, p, cycle)
755 return
756 return
756
757
757 mod = _safe_getattr(obj, '__module__', None)
758 mod = _safe_getattr(obj, '__module__', None)
758 try:
759 try:
759 name = obj.__qualname__
760 name = obj.__qualname__
760 if not isinstance(name, str):
761 if not isinstance(name, str):
761 # This can happen if the type implements __qualname__ as a property
762 # This can happen if the type implements __qualname__ as a property
762 # or other descriptor in Python 2.
763 # or other descriptor in Python 2.
763 raise Exception("Try __name__")
764 raise Exception("Try __name__")
764 except Exception:
765 except Exception:
765 name = obj.__name__
766 name = obj.__name__
766 if not isinstance(name, str):
767 if not isinstance(name, str):
767 name = '<unknown type>'
768 name = '<unknown type>'
768
769
769 if mod in (None, '__builtin__', 'builtins', 'exceptions'):
770 if mod in (None, '__builtin__', 'builtins', 'exceptions'):
770 p.text(name)
771 p.text(name)
771 else:
772 else:
772 p.text(mod + '.' + name)
773 p.text(mod + '.' + name)
773
774
774
775
775 def _repr_pprint(obj, p, cycle):
776 def _repr_pprint(obj, p, cycle):
776 """A pprint that just redirects to the normal repr function."""
777 """A pprint that just redirects to the normal repr function."""
777 # Find newlines and replace them with p.break_()
778 # Find newlines and replace them with p.break_()
778 output = repr(obj)
779 output = repr(obj)
779 lines = output.splitlines()
780 lines = output.splitlines()
780 with p.group():
781 with p.group():
781 for idx, output_line in enumerate(lines):
782 for idx, output_line in enumerate(lines):
782 if idx:
783 if idx:
783 p.break_()
784 p.break_()
784 p.text(output_line)
785 p.text(output_line)
785
786
786
787
787 def _function_pprint(obj, p, cycle):
788 def _function_pprint(obj, p, cycle):
788 """Base pprint for all functions and builtin functions."""
789 """Base pprint for all functions and builtin functions."""
789 name = _safe_getattr(obj, '__qualname__', obj.__name__)
790 name = _safe_getattr(obj, '__qualname__', obj.__name__)
790 mod = obj.__module__
791 mod = obj.__module__
791 if mod and mod not in ('__builtin__', 'builtins', 'exceptions'):
792 if mod and mod not in ('__builtin__', 'builtins', 'exceptions'):
792 name = mod + '.' + name
793 name = mod + '.' + name
793 try:
794 try:
794 func_def = name + str(signature(obj))
795 func_def = name + str(signature(obj))
795 except ValueError:
796 except ValueError:
796 func_def = name
797 func_def = name
797 p.text('<function %s>' % func_def)
798 p.text('<function %s>' % func_def)
798
799
799
800
800 def _exception_pprint(obj, p, cycle):
801 def _exception_pprint(obj, p, cycle):
801 """Base pprint for all exceptions."""
802 """Base pprint for all exceptions."""
802 name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__)
803 name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__)
803 if obj.__class__.__module__ not in ('exceptions', 'builtins'):
804 if obj.__class__.__module__ not in ('exceptions', 'builtins'):
804 name = '%s.%s' % (obj.__class__.__module__, name)
805 name = '%s.%s' % (obj.__class__.__module__, name)
805
806
806 p.pretty(CallExpression(name, *getattr(obj, 'args', ())))
807 p.pretty(CallExpression(name, *getattr(obj, 'args', ())))
807
808
808
809
809 #: the exception base
810 #: the exception base
811 _exception_base: type
810 try:
812 try:
811 _exception_base = BaseException
813 _exception_base = BaseException
812 except NameError:
814 except NameError:
813 _exception_base = Exception
815 _exception_base = Exception
814
816
815
817
816 #: printers for builtin types
818 #: printers for builtin types
817 _type_pprinters = {
819 _type_pprinters = {
818 int: _repr_pprint,
820 int: _repr_pprint,
819 float: _repr_pprint,
821 float: _repr_pprint,
820 str: _repr_pprint,
822 str: _repr_pprint,
821 tuple: _seq_pprinter_factory('(', ')'),
823 tuple: _seq_pprinter_factory('(', ')'),
822 list: _seq_pprinter_factory('[', ']'),
824 list: _seq_pprinter_factory('[', ']'),
823 dict: _dict_pprinter_factory('{', '}'),
825 dict: _dict_pprinter_factory('{', '}'),
824 set: _set_pprinter_factory('{', '}'),
826 set: _set_pprinter_factory('{', '}'),
825 frozenset: _set_pprinter_factory('frozenset({', '})'),
827 frozenset: _set_pprinter_factory('frozenset({', '})'),
826 super: _super_pprint,
828 super: _super_pprint,
827 _re_pattern_type: _re_pattern_pprint,
829 _re_pattern_type: _re_pattern_pprint,
828 type: _type_pprint,
830 type: _type_pprint,
829 types.FunctionType: _function_pprint,
831 types.FunctionType: _function_pprint,
830 types.BuiltinFunctionType: _function_pprint,
832 types.BuiltinFunctionType: _function_pprint,
831 types.MethodType: _repr_pprint,
833 types.MethodType: _repr_pprint,
832 types.SimpleNamespace: _types_simplenamespace_pprint,
834 types.SimpleNamespace: _types_simplenamespace_pprint,
833 datetime.datetime: _repr_pprint,
835 datetime.datetime: _repr_pprint,
834 datetime.timedelta: _repr_pprint,
836 datetime.timedelta: _repr_pprint,
835 _exception_base: _exception_pprint
837 _exception_base: _exception_pprint
836 }
838 }
837
839
838 # render os.environ like a dict
840 # render os.environ like a dict
839 _env_type = type(os.environ)
841 _env_type = type(os.environ)
840 # future-proof in case os.environ becomes a plain dict?
842 # future-proof in case os.environ becomes a plain dict?
841 if _env_type is not dict:
843 if _env_type is not dict:
842 _type_pprinters[_env_type] = _dict_pprinter_factory('environ{', '}')
844 _type_pprinters[_env_type] = _dict_pprinter_factory('environ{', '}')
843
845
844 _type_pprinters[types.MappingProxyType] = _dict_pprinter_factory("mappingproxy({", "})")
846 _type_pprinters[types.MappingProxyType] = _dict_pprinter_factory("mappingproxy({", "})")
845 _type_pprinters[slice] = _repr_pprint
847 _type_pprinters[slice] = _repr_pprint
846
848
847 _type_pprinters[range] = _repr_pprint
849 _type_pprinters[range] = _repr_pprint
848 _type_pprinters[bytes] = _repr_pprint
850 _type_pprinters[bytes] = _repr_pprint
849
851
850 #: printers for types specified by name
852 #: printers for types specified by name
851 _deferred_type_pprinters = {
853 _deferred_type_pprinters: Dict = {}
852 }
854
853
855
854 def for_type(typ, func):
856 def for_type(typ, func):
855 """
857 """
856 Add a pretty printer for a given type.
858 Add a pretty printer for a given type.
857 """
859 """
858 oldfunc = _type_pprinters.get(typ, None)
860 oldfunc = _type_pprinters.get(typ, None)
859 if func is not None:
861 if func is not None:
860 # To support easy restoration of old pprinters, we need to ignore Nones.
862 # To support easy restoration of old pprinters, we need to ignore Nones.
861 _type_pprinters[typ] = func
863 _type_pprinters[typ] = func
862 return oldfunc
864 return oldfunc
863
865
864 def for_type_by_name(type_module, type_name, func):
866 def for_type_by_name(type_module, type_name, func):
865 """
867 """
866 Add a pretty printer for a type specified by the module and name of a type
868 Add a pretty printer for a type specified by the module and name of a type
867 rather than the type object itself.
869 rather than the type object itself.
868 """
870 """
869 key = (type_module, type_name)
871 key = (type_module, type_name)
870 oldfunc = _deferred_type_pprinters.get(key, None)
872 oldfunc = _deferred_type_pprinters.get(key, None)
871 if func is not None:
873 if func is not None:
872 # To support easy restoration of old pprinters, we need to ignore Nones.
874 # To support easy restoration of old pprinters, we need to ignore Nones.
873 _deferred_type_pprinters[key] = func
875 _deferred_type_pprinters[key] = func
874 return oldfunc
876 return oldfunc
875
877
876
878
877 #: printers for the default singletons
879 #: printers for the default singletons
878 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
880 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
879 NotImplemented]), _repr_pprint)
881 NotImplemented]), _repr_pprint)
880
882
881
883
882 def _defaultdict_pprint(obj, p, cycle):
884 def _defaultdict_pprint(obj, p, cycle):
883 cls_ctor = CallExpression.factory(obj.__class__.__name__)
885 cls_ctor = CallExpression.factory(obj.__class__.__name__)
884 if cycle:
886 if cycle:
885 p.pretty(cls_ctor(RawText("...")))
887 p.pretty(cls_ctor(RawText("...")))
886 else:
888 else:
887 p.pretty(cls_ctor(obj.default_factory, dict(obj)))
889 p.pretty(cls_ctor(obj.default_factory, dict(obj)))
888
890
889 def _ordereddict_pprint(obj, p, cycle):
891 def _ordereddict_pprint(obj, p, cycle):
890 cls_ctor = CallExpression.factory(obj.__class__.__name__)
892 cls_ctor = CallExpression.factory(obj.__class__.__name__)
891 if cycle:
893 if cycle:
892 p.pretty(cls_ctor(RawText("...")))
894 p.pretty(cls_ctor(RawText("...")))
893 elif len(obj):
895 elif len(obj):
894 p.pretty(cls_ctor(list(obj.items())))
896 p.pretty(cls_ctor(list(obj.items())))
895 else:
897 else:
896 p.pretty(cls_ctor())
898 p.pretty(cls_ctor())
897
899
898 def _deque_pprint(obj, p, cycle):
900 def _deque_pprint(obj, p, cycle):
899 cls_ctor = CallExpression.factory(obj.__class__.__name__)
901 cls_ctor = CallExpression.factory(obj.__class__.__name__)
900 if cycle:
902 if cycle:
901 p.pretty(cls_ctor(RawText("...")))
903 p.pretty(cls_ctor(RawText("...")))
902 elif obj.maxlen is not None:
904 elif obj.maxlen is not None:
903 p.pretty(cls_ctor(list(obj), maxlen=obj.maxlen))
905 p.pretty(cls_ctor(list(obj), maxlen=obj.maxlen))
904 else:
906 else:
905 p.pretty(cls_ctor(list(obj)))
907 p.pretty(cls_ctor(list(obj)))
906
908
907 def _counter_pprint(obj, p, cycle):
909 def _counter_pprint(obj, p, cycle):
908 cls_ctor = CallExpression.factory(obj.__class__.__name__)
910 cls_ctor = CallExpression.factory(obj.__class__.__name__)
909 if cycle:
911 if cycle:
910 p.pretty(cls_ctor(RawText("...")))
912 p.pretty(cls_ctor(RawText("...")))
911 elif len(obj):
913 elif len(obj):
912 p.pretty(cls_ctor(dict(obj.most_common())))
914 p.pretty(cls_ctor(dict(obj.most_common())))
913 else:
915 else:
914 p.pretty(cls_ctor())
916 p.pretty(cls_ctor())
915
917
916
918
917 def _userlist_pprint(obj, p, cycle):
919 def _userlist_pprint(obj, p, cycle):
918 cls_ctor = CallExpression.factory(obj.__class__.__name__)
920 cls_ctor = CallExpression.factory(obj.__class__.__name__)
919 if cycle:
921 if cycle:
920 p.pretty(cls_ctor(RawText("...")))
922 p.pretty(cls_ctor(RawText("...")))
921 else:
923 else:
922 p.pretty(cls_ctor(obj.data))
924 p.pretty(cls_ctor(obj.data))
923
925
924
926
925 for_type_by_name('collections', 'defaultdict', _defaultdict_pprint)
927 for_type_by_name('collections', 'defaultdict', _defaultdict_pprint)
926 for_type_by_name('collections', 'OrderedDict', _ordereddict_pprint)
928 for_type_by_name('collections', 'OrderedDict', _ordereddict_pprint)
927 for_type_by_name('collections', 'deque', _deque_pprint)
929 for_type_by_name('collections', 'deque', _deque_pprint)
928 for_type_by_name('collections', 'Counter', _counter_pprint)
930 for_type_by_name('collections', 'Counter', _counter_pprint)
929 for_type_by_name("collections", "UserList", _userlist_pprint)
931 for_type_by_name("collections", "UserList", _userlist_pprint)
930
932
931 if __name__ == '__main__':
933 if __name__ == '__main__':
932 from random import randrange
934 from random import randrange
933 class Foo(object):
935 class Foo(object):
934 def __init__(self):
936 def __init__(self):
935 self.foo = 1
937 self.foo = 1
936 self.bar = re.compile(r'\s+')
938 self.bar = re.compile(r'\s+')
937 self.blub = dict.fromkeys(range(30), randrange(1, 40))
939 self.blub = dict.fromkeys(range(30), randrange(1, 40))
938 self.hehe = 23424.234234
940 self.hehe = 23424.234234
939 self.list = ["blub", "blah", self]
941 self.list = ["blub", "blah", self]
940
942
941 def get_foo(self):
943 def get_foo(self):
942 print("foo")
944 print("foo")
943
945
944 pprint(Foo(), verbose=True)
946 pprint(Foo(), verbose=True)
@@ -1,84 +1,78 b''
1 [build-system]
1 [build-system]
2 requires = ["setuptools >= 51.0.0"]
2 requires = ["setuptools >= 51.0.0"]
3 # We need access to the 'setupbase' module at build time.
3 # We need access to the 'setupbase' module at build time.
4 # Hence we declare a custom build backend.
4 # Hence we declare a custom build backend.
5 build-backend = "_build_meta" # just re-exports setuptools.build_meta definitions
5 build-backend = "_build_meta" # just re-exports setuptools.build_meta definitions
6 backend-path = ["."]
6 backend-path = ["."]
7
7
8 [tool.mypy]
8 [tool.mypy]
9 python_version = "3.10"
9 python_version = "3.10"
10 ignore_missing_imports = true
10 ignore_missing_imports = true
11 follow_imports = 'silent'
11 follow_imports = 'silent'
12 exclude = [
12 exclude = [
13 'test_\.+\.py',
13 'test_\.+\.py',
14 'IPython.utils.tests.test_wildcard',
14 'IPython.utils.tests.test_wildcard',
15 'testing',
15 'testing',
16 'tests',
16 'tests',
17 'PyColorize.py',
17 'PyColorize.py',
18 '_process_win32_controller.py',
18 '_process_win32_controller.py',
19 'IPython/core/application.py',
19 'IPython/core/application.py',
20 'IPython/core/completerlib.py',
21 'IPython/core/displaypub.py',
22 #'IPython/core/interactiveshell.py',
23 'IPython/core/magic.py',
24 'IPython/core/profileapp.py',
20 'IPython/core/profileapp.py',
25 # 'IPython/core/ultratb.py',
26 'IPython/lib/deepreload.py',
21 'IPython/lib/deepreload.py',
27 'IPython/lib/pretty.py',
28 'IPython/sphinxext/ipython_directive.py',
22 'IPython/sphinxext/ipython_directive.py',
29 'IPython/terminal/ipapp.py',
23 'IPython/terminal/ipapp.py',
30 'IPython/utils/_process_win32.py',
24 'IPython/utils/_process_win32.py',
31 'IPython/utils/path.py',
25 'IPython/utils/path.py',
32 ]
26 ]
33
27
34 [tool.pytest.ini_options]
28 [tool.pytest.ini_options]
35 addopts = [
29 addopts = [
36 "--durations=10",
30 "--durations=10",
37 "-pIPython.testing.plugin.pytest_ipdoctest",
31 "-pIPython.testing.plugin.pytest_ipdoctest",
38 "--ipdoctest-modules",
32 "--ipdoctest-modules",
39 "--ignore=docs",
33 "--ignore=docs",
40 "--ignore=examples",
34 "--ignore=examples",
41 "--ignore=htmlcov",
35 "--ignore=htmlcov",
42 "--ignore=ipython_kernel",
36 "--ignore=ipython_kernel",
43 "--ignore=ipython_parallel",
37 "--ignore=ipython_parallel",
44 "--ignore=results",
38 "--ignore=results",
45 "--ignore=tmp",
39 "--ignore=tmp",
46 "--ignore=tools",
40 "--ignore=tools",
47 "--ignore=traitlets",
41 "--ignore=traitlets",
48 "--ignore=IPython/core/tests/daft_extension",
42 "--ignore=IPython/core/tests/daft_extension",
49 "--ignore=IPython/sphinxext",
43 "--ignore=IPython/sphinxext",
50 "--ignore=IPython/terminal/pt_inputhooks",
44 "--ignore=IPython/terminal/pt_inputhooks",
51 "--ignore=IPython/__main__.py",
45 "--ignore=IPython/__main__.py",
52 "--ignore=IPython/external/qt_for_kernel.py",
46 "--ignore=IPython/external/qt_for_kernel.py",
53 "--ignore=IPython/html/widgets/widget_link.py",
47 "--ignore=IPython/html/widgets/widget_link.py",
54 "--ignore=IPython/html/widgets/widget_output.py",
48 "--ignore=IPython/html/widgets/widget_output.py",
55 "--ignore=IPython/terminal/console.py",
49 "--ignore=IPython/terminal/console.py",
56 "--ignore=IPython/utils/_process_cli.py",
50 "--ignore=IPython/utils/_process_cli.py",
57 "--ignore=IPython/utils/_process_posix.py",
51 "--ignore=IPython/utils/_process_posix.py",
58 "--ignore=IPython/utils/_process_win32.py",
52 "--ignore=IPython/utils/_process_win32.py",
59 "--ignore=IPython/utils/_process_win32_controller.py",
53 "--ignore=IPython/utils/_process_win32_controller.py",
60 "--ignore=IPython/utils/daemonize.py",
54 "--ignore=IPython/utils/daemonize.py",
61 "--ignore=IPython/utils/eventful.py",
55 "--ignore=IPython/utils/eventful.py",
62 "--ignore=IPython/kernel",
56 "--ignore=IPython/kernel",
63 "--ignore=IPython/consoleapp.py",
57 "--ignore=IPython/consoleapp.py",
64 "--ignore=IPython/core/inputsplitter.py",
58 "--ignore=IPython/core/inputsplitter.py",
65 "--ignore=IPython/lib/kernel.py",
59 "--ignore=IPython/lib/kernel.py",
66 "--ignore=IPython/utils/jsonutil.py",
60 "--ignore=IPython/utils/jsonutil.py",
67 "--ignore=IPython/utils/localinterfaces.py",
61 "--ignore=IPython/utils/localinterfaces.py",
68 "--ignore=IPython/utils/log.py",
62 "--ignore=IPython/utils/log.py",
69 "--ignore=IPython/utils/signatures.py",
63 "--ignore=IPython/utils/signatures.py",
70 "--ignore=IPython/utils/traitlets.py",
64 "--ignore=IPython/utils/traitlets.py",
71 "--ignore=IPython/utils/version.py"
65 "--ignore=IPython/utils/version.py"
72 ]
66 ]
73 doctest_optionflags = [
67 doctest_optionflags = [
74 "NORMALIZE_WHITESPACE",
68 "NORMALIZE_WHITESPACE",
75 "ELLIPSIS"
69 "ELLIPSIS"
76 ]
70 ]
77 ipdoctest_optionflags = [
71 ipdoctest_optionflags = [
78 "NORMALIZE_WHITESPACE",
72 "NORMALIZE_WHITESPACE",
79 "ELLIPSIS"
73 "ELLIPSIS"
80 ]
74 ]
81 asyncio_mode = "strict"
75 asyncio_mode = "strict"
82
76
83 [tool.pyright]
77 [tool.pyright]
84 pythonPlatform="All"
78 pythonPlatform="All"
General Comments 0
You need to be logged in to leave comments. Login now