##// END OF EJS Templates
docstring fixes
Matthias Bussonnier -
Show More
@@ -1,535 +1,538 b''
1 1 """DEPRECATED: Input transformer classes to support IPython special syntax.
2 2
3 3 This module was deprecated in IPython 7.0, in favour of inputtransformer2.
4 4
5 5 This includes the machinery to recognise and transform ``%magic`` commands,
6 6 ``!system`` commands, ``help?`` querying, prompt stripping, and so forth.
7 7 """
8 8 import abc
9 9 import functools
10 10 import re
11 11 import tokenize
12 12 from tokenize import generate_tokens, untokenize, TokenError
13 13 from io import StringIO
14 14
15 15 from IPython.core.splitinput import LineInfo
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Globals
19 19 #-----------------------------------------------------------------------------
20 20
21 21 # The escape sequences that define the syntax transformations IPython will
22 22 # apply to user input. These can NOT be just changed here: many regular
23 23 # expressions and other parts of the code may use their hardcoded values, and
24 24 # for all intents and purposes they constitute the 'IPython syntax', so they
25 25 # should be considered fixed.
26 26
27 27 ESC_SHELL = '!' # Send line to underlying system shell
28 28 ESC_SH_CAP = '!!' # Send line to system shell and capture output
29 29 ESC_HELP = '?' # Find information about object
30 30 ESC_HELP2 = '??' # Find extra-detailed information about object
31 31 ESC_MAGIC = '%' # Call magic function
32 32 ESC_MAGIC2 = '%%' # Call cell-magic function
33 33 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
34 34 ESC_QUOTE2 = ';' # Quote all args as a single string, call
35 35 ESC_PAREN = '/' # Call first argument with rest of line as arguments
36 36
37 37 ESC_SEQUENCES = [ESC_SHELL, ESC_SH_CAP, ESC_HELP ,\
38 38 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,\
39 39 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN ]
40 40
41 41
42 42 class InputTransformer(metaclass=abc.ABCMeta):
43 43 """Abstract base class for line-based input transformers."""
44 44
45 45 @abc.abstractmethod
46 46 def push(self, line):
47 47 """Send a line of input to the transformer, returning the transformed
48 48 input or None if the transformer is waiting for more input.
49 49
50 50 Must be overridden by subclasses.
51 51
52 52 Implementations may raise ``SyntaxError`` if the input is invalid. No
53 53 other exceptions may be raised.
54 54 """
55 55 pass
56 56
57 57 @abc.abstractmethod
58 58 def reset(self):
59 59 """Return, transformed any lines that the transformer has accumulated,
60 60 and reset its internal state.
61 61
62 62 Must be overridden by subclasses.
63 63 """
64 64 pass
65 65
66 66 @classmethod
67 67 def wrap(cls, func):
68 68 """Can be used by subclasses as a decorator, to return a factory that
69 69 will allow instantiation with the decorated object.
70 70 """
71 71 @functools.wraps(func)
72 72 def transformer_factory(**kwargs):
73 73 return cls(func, **kwargs)
74 74
75 75 return transformer_factory
76 76
77 77 class StatelessInputTransformer(InputTransformer):
78 78 """Wrapper for a stateless input transformer implemented as a function."""
79 79 def __init__(self, func):
80 80 self.func = func
81 81
82 82 def __repr__(self):
83 83 return "StatelessInputTransformer(func={0!r})".format(self.func)
84 84
85 85 def push(self, line):
86 86 """Send a line of input to the transformer, returning the
87 87 transformed input."""
88 88 return self.func(line)
89 89
90 90 def reset(self):
91 91 """No-op - exists for compatibility."""
92 92 pass
93 93
94 94 class CoroutineInputTransformer(InputTransformer):
95 95 """Wrapper for an input transformer implemented as a coroutine."""
96 96 def __init__(self, coro, **kwargs):
97 97 # Prime it
98 98 self.coro = coro(**kwargs)
99 99 next(self.coro)
100 100
101 101 def __repr__(self):
102 102 return "CoroutineInputTransformer(coro={0!r})".format(self.coro)
103 103
104 104 def push(self, line):
105 105 """Send a line of input to the transformer, returning the
106 106 transformed input or None if the transformer is waiting for more
107 107 input.
108 108 """
109 109 return self.coro.send(line)
110 110
111 111 def reset(self):
112 112 """Return, transformed any lines that the transformer has
113 113 accumulated, and reset its internal state.
114 114 """
115 115 return self.coro.send(None)
116 116
117 117 class TokenInputTransformer(InputTransformer):
118 118 """Wrapper for a token-based input transformer.
119 119
120 120 func should accept a list of tokens (5-tuples, see tokenize docs), and
121 121 return an iterable which can be passed to tokenize.untokenize().
122 122 """
123 123 def __init__(self, func):
124 124 self.func = func
125 125 self.buf = []
126 126 self.reset_tokenizer()
127 127
128 128 def reset_tokenizer(self):
129 129 it = iter(self.buf)
130 130 self.tokenizer = generate_tokens(it.__next__)
131 131
132 132 def push(self, line):
133 133 self.buf.append(line + '\n')
134 134 if all(l.isspace() for l in self.buf):
135 135 return self.reset()
136 136
137 137 tokens = []
138 138 stop_at_NL = False
139 139 try:
140 140 for intok in self.tokenizer:
141 141 tokens.append(intok)
142 142 t = intok[0]
143 143 if t == tokenize.NEWLINE or (stop_at_NL and t == tokenize.NL):
144 144 # Stop before we try to pull a line we don't have yet
145 145 break
146 146 elif t == tokenize.ERRORTOKEN:
147 147 stop_at_NL = True
148 148 except TokenError:
149 149 # Multi-line statement - stop and try again with the next line
150 150 self.reset_tokenizer()
151 151 return None
152 152
153 153 return self.output(tokens)
154 154
155 155 def output(self, tokens):
156 156 self.buf.clear()
157 157 self.reset_tokenizer()
158 158 return untokenize(self.func(tokens)).rstrip('\n')
159 159
160 160 def reset(self):
161 161 l = ''.join(self.buf)
162 162 self.buf.clear()
163 163 self.reset_tokenizer()
164 164 if l:
165 165 return l.rstrip('\n')
166 166
167 167 class assemble_python_lines(TokenInputTransformer):
168 168 def __init__(self):
169 169 super(assemble_python_lines, self).__init__(None)
170 170
171 171 def output(self, tokens):
172 172 return self.reset()
173 173
174 174 @CoroutineInputTransformer.wrap
175 175 def assemble_logical_lines():
176 176 r"""Join lines following explicit line continuations (\)"""
177 177 line = ''
178 178 while True:
179 179 line = (yield line)
180 180 if not line or line.isspace():
181 181 continue
182 182
183 183 parts = []
184 184 while line is not None:
185 185 if line.endswith('\\') and (not has_comment(line)):
186 186 parts.append(line[:-1])
187 187 line = (yield None) # Get another line
188 188 else:
189 189 parts.append(line)
190 190 break
191 191
192 192 # Output
193 193 line = ''.join(parts)
194 194
195 195 # Utilities
196 196 def _make_help_call(target, esc, lspace, next_input=None):
197 197 """Prepares a pinfo(2)/psearch call from a target name and the escape
198 198 (i.e. ? or ??)"""
199 199 method = 'pinfo2' if esc == '??' \
200 200 else 'psearch' if '*' in target \
201 201 else 'pinfo'
202 202 arg = " ".join([method, target])
203 203 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
204 204 t_magic_name, _, t_magic_arg_s = arg.partition(' ')
205 205 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
206 206 if next_input is None:
207 207 return '%sget_ipython().run_line_magic(%r, %r)' % (lspace, t_magic_name, t_magic_arg_s)
208 208 else:
209 209 return '%sget_ipython().set_next_input(%r);get_ipython().run_line_magic(%r, %r)' % \
210 210 (lspace, next_input, t_magic_name, t_magic_arg_s)
211 211
212 212 # These define the transformations for the different escape characters.
213 213 def _tr_system(line_info):
214 214 "Translate lines escaped with: !"
215 215 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
216 216 return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
217 217
218 218 def _tr_system2(line_info):
219 219 "Translate lines escaped with: !!"
220 220 cmd = line_info.line.lstrip()[2:]
221 221 return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
222 222
223 223 def _tr_help(line_info):
224 224 "Translate lines escaped with: ?/??"
225 225 # A naked help line should just fire the intro help screen
226 226 if not line_info.line[1:]:
227 227 return 'get_ipython().show_usage()'
228 228
229 229 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
230 230
231 231 def _tr_magic(line_info):
232 232 "Translate lines escaped with: %"
233 233 tpl = '%sget_ipython().run_line_magic(%r, %r)'
234 234 if line_info.line.startswith(ESC_MAGIC2):
235 235 return line_info.line
236 236 cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
237 237 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
238 238 t_magic_name, _, t_magic_arg_s = cmd.partition(' ')
239 239 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
240 240 return tpl % (line_info.pre, t_magic_name, t_magic_arg_s)
241 241
242 242 def _tr_quote(line_info):
243 243 "Translate lines escaped with: ,"
244 244 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
245 245 '", "'.join(line_info.the_rest.split()) )
246 246
247 247 def _tr_quote2(line_info):
248 248 "Translate lines escaped with: ;"
249 249 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
250 250 line_info.the_rest)
251 251
252 252 def _tr_paren(line_info):
253 253 "Translate lines escaped with: /"
254 254 return '%s%s(%s)' % (line_info.pre, line_info.ifun,
255 255 ", ".join(line_info.the_rest.split()))
256 256
257 257 tr = { ESC_SHELL : _tr_system,
258 258 ESC_SH_CAP : _tr_system2,
259 259 ESC_HELP : _tr_help,
260 260 ESC_HELP2 : _tr_help,
261 261 ESC_MAGIC : _tr_magic,
262 262 ESC_QUOTE : _tr_quote,
263 263 ESC_QUOTE2 : _tr_quote2,
264 264 ESC_PAREN : _tr_paren }
265 265
266 266 @StatelessInputTransformer.wrap
267 267 def escaped_commands(line):
268 268 """Transform escaped commands - %magic, !system, ?help + various autocalls.
269 269 """
270 270 if not line or line.isspace():
271 271 return line
272 272 lineinf = LineInfo(line)
273 273 if lineinf.esc not in tr:
274 274 return line
275 275
276 276 return tr[lineinf.esc](lineinf)
277 277
278 278 _initial_space_re = re.compile(r'\s*')
279 279
280 280 _help_end_re = re.compile(r"""(%{0,2}
281 281 (?!\d)[\w*]+ # Variable name
282 282 (\.(?!\d)[\w*]+)* # .etc.etc
283 283 )
284 284 (\?\??)$ # ? or ??
285 285 """,
286 286 re.VERBOSE)
287 287
288 288 # Extra pseudotokens for multiline strings and data structures
289 289 _MULTILINE_STRING = object()
290 290 _MULTILINE_STRUCTURE = object()
291 291
292 292 def _line_tokens(line):
293 293 """Helper for has_comment and ends_in_comment_or_string."""
294 294 readline = StringIO(line).readline
295 295 toktypes = set()
296 296 try:
297 297 for t in generate_tokens(readline):
298 298 toktypes.add(t[0])
299 299 except TokenError as e:
300 300 # There are only two cases where a TokenError is raised.
301 301 if 'multi-line string' in e.args[0]:
302 302 toktypes.add(_MULTILINE_STRING)
303 303 else:
304 304 toktypes.add(_MULTILINE_STRUCTURE)
305 305 return toktypes
306 306
307 307 def has_comment(src):
308 308 """Indicate whether an input line has (i.e. ends in, or is) a comment.
309 309
310 310 This uses tokenize, so it can distinguish comments from # inside strings.
311 311
312 312 Parameters
313 313 ----------
314 314 src : string
315 315 A single line input string.
316 316
317 317 Returns
318 318 -------
319 319 comment : bool
320 320 True if source has a comment.
321 321 """
322 322 return (tokenize.COMMENT in _line_tokens(src))
323 323
324 324 def ends_in_comment_or_string(src):
325 325 """Indicates whether or not an input line ends in a comment or within
326 326 a multiline string.
327 327
328 328 Parameters
329 329 ----------
330 330 src : string
331 331 A single line input string.
332 332
333 333 Returns
334 334 -------
335 335 comment : bool
336 336 True if source ends in a comment or multiline string.
337 337 """
338 338 toktypes = _line_tokens(src)
339 339 return (tokenize.COMMENT in toktypes) or (_MULTILINE_STRING in toktypes)
340 340
341 341
342 342 @StatelessInputTransformer.wrap
343 343 def help_end(line):
344 344 """Translate lines with ?/?? at the end"""
345 345 m = _help_end_re.search(line)
346 346 if m is None or ends_in_comment_or_string(line):
347 347 return line
348 348 target = m.group(1)
349 349 esc = m.group(3)
350 350 lspace = _initial_space_re.match(line).group(0)
351 351
352 352 # If we're mid-command, put it back on the next prompt for the user.
353 353 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
354 354
355 355 return _make_help_call(target, esc, lspace, next_input)
356 356
357 357
358 358 @CoroutineInputTransformer.wrap
359 359 def cellmagic(end_on_blank_line=False):
360 360 """Captures & transforms cell magics.
361 361
362 362 After a cell magic is started, this stores up any lines it gets until it is
363 363 reset (sent None).
364 364 """
365 365 tpl = 'get_ipython().run_cell_magic(%r, %r, %r)'
366 366 cellmagic_help_re = re.compile(r'%%\w+\?')
367 367 line = ''
368 368 while True:
369 369 line = (yield line)
370 370 # consume leading empty lines
371 371 while not line:
372 372 line = (yield line)
373 373
374 374 if not line.startswith(ESC_MAGIC2):
375 375 # This isn't a cell magic, idle waiting for reset then start over
376 376 while line is not None:
377 377 line = (yield line)
378 378 continue
379 379
380 380 if cellmagic_help_re.match(line):
381 381 # This case will be handled by help_end
382 382 continue
383 383
384 384 first = line
385 385 body = []
386 386 line = (yield None)
387 387 while (line is not None) and \
388 388 ((line.strip() != '') or not end_on_blank_line):
389 389 body.append(line)
390 390 line = (yield None)
391 391
392 392 # Output
393 393 magic_name, _, first = first.partition(' ')
394 394 magic_name = magic_name.lstrip(ESC_MAGIC2)
395 395 line = tpl % (magic_name, first, u'\n'.join(body))
396 396
397 397
398 398 def _strip_prompts(prompt_re, initial_re=None, turnoff_re=None):
399 399 """Remove matching input prompts from a block of input.
400 400
401 401 Parameters
402 402 ----------
403 403 prompt_re : regular expression
404 404 A regular expression matching any input prompt (including continuation)
405 405 initial_re : regular expression, optional
406 406 A regular expression matching only the initial prompt, but not continuation.
407 407 If no initial expression is given, prompt_re will be used everywhere.
408 408 Used mainly for plain Python prompts, where the continuation prompt
409 409 ``...`` is a valid Python expression in Python 3, so shouldn't be stripped.
410 If initial_re and prompt_re differ,
411 only initial_re will be tested against the first line.
410
411 Notes
412 -----
413 If `initial_re` and `prompt_re differ`,
414 only `initial_re` will be tested against the first line.
412 415 If any prompt is found on the first two lines,
413 416 prompts will be stripped from the rest of the block.
414 417 """
415 418 if initial_re is None:
416 419 initial_re = prompt_re
417 420 line = ''
418 421 while True:
419 422 line = (yield line)
420 423
421 424 # First line of cell
422 425 if line is None:
423 426 continue
424 427 out, n1 = initial_re.subn('', line, count=1)
425 428 if turnoff_re and not n1:
426 429 if turnoff_re.match(line):
427 430 # We're in e.g. a cell magic; disable this transformer for
428 431 # the rest of the cell.
429 432 while line is not None:
430 433 line = (yield line)
431 434 continue
432 435
433 436 line = (yield out)
434 437
435 438 if line is None:
436 439 continue
437 440 # check for any prompt on the second line of the cell,
438 441 # because people often copy from just after the first prompt,
439 442 # so we might not see it in the first line.
440 443 out, n2 = prompt_re.subn('', line, count=1)
441 444 line = (yield out)
442 445
443 446 if n1 or n2:
444 447 # Found a prompt in the first two lines - check for it in
445 448 # the rest of the cell as well.
446 449 while line is not None:
447 450 line = (yield prompt_re.sub('', line, count=1))
448 451
449 452 else:
450 453 # Prompts not in input - wait for reset
451 454 while line is not None:
452 455 line = (yield line)
453 456
454 457 @CoroutineInputTransformer.wrap
455 458 def classic_prompt():
456 459 """Strip the >>>/... prompts of the Python interactive shell."""
457 460 # FIXME: non-capturing version (?:...) usable?
458 461 prompt_re = re.compile(r'^(>>>|\.\.\.)( |$)')
459 462 initial_re = re.compile(r'^>>>( |$)')
460 463 # Any %magic/!system is IPython syntax, so we needn't look for >>> prompts
461 464 turnoff_re = re.compile(r'^[%!]')
462 465 return _strip_prompts(prompt_re, initial_re, turnoff_re)
463 466
464 467 @CoroutineInputTransformer.wrap
465 468 def ipy_prompt():
466 469 """Strip IPython's In [1]:/...: prompts."""
467 470 # FIXME: non-capturing version (?:...) usable?
468 471 prompt_re = re.compile(r'^(In \[\d+\]: |\s*\.{3,}: ?)')
469 472 # Disable prompt stripping inside cell magics
470 473 turnoff_re = re.compile(r'^%%')
471 474 return _strip_prompts(prompt_re, turnoff_re=turnoff_re)
472 475
473 476
474 477 @CoroutineInputTransformer.wrap
475 478 def leading_indent():
476 479 """Remove leading indentation.
477 480
478 481 If the first line starts with a spaces or tabs, the same whitespace will be
479 482 removed from each following line until it is reset.
480 483 """
481 484 space_re = re.compile(r'^[ \t]+')
482 485 line = ''
483 486 while True:
484 487 line = (yield line)
485 488
486 489 if line is None:
487 490 continue
488 491
489 492 m = space_re.match(line)
490 493 if m:
491 494 space = m.group(0)
492 495 while line is not None:
493 496 if line.startswith(space):
494 497 line = line[len(space):]
495 498 line = (yield line)
496 499 else:
497 500 # No leading spaces - wait for reset
498 501 while line is not None:
499 502 line = (yield line)
500 503
501 504
502 505 _assign_pat = \
503 506 r'''(?P<lhs>(\s*)
504 507 ([\w\.]+) # Initial identifier
505 508 (\s*,\s*
506 509 \*?[\w\.]+)* # Further identifiers for unpacking
507 510 \s*?,? # Trailing comma
508 511 )
509 512 \s*=\s*
510 513 '''
511 514
512 515 assign_system_re = re.compile(r'{}!\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
513 516 assign_system_template = '%s = get_ipython().getoutput(%r)'
514 517 @StatelessInputTransformer.wrap
515 518 def assign_from_system(line):
516 519 """Transform assignment from system commands (e.g. files = !ls)"""
517 520 m = assign_system_re.match(line)
518 521 if m is None:
519 522 return line
520 523
521 524 return assign_system_template % m.group('lhs', 'cmd')
522 525
523 526 assign_magic_re = re.compile(r'{}%\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
524 527 assign_magic_template = '%s = get_ipython().run_line_magic(%r, %r)'
525 528 @StatelessInputTransformer.wrap
526 529 def assign_from_magic(line):
527 530 """Transform assignment from magic commands (e.g. a = %who_ls)"""
528 531 m = assign_magic_re.match(line)
529 532 if m is None:
530 533 return line
531 534 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
532 535 m_lhs, m_cmd = m.group('lhs', 'cmd')
533 536 t_magic_name, _, t_magic_arg_s = m_cmd.partition(' ')
534 537 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
535 538 return assign_magic_template % (m_lhs, t_magic_name, t_magic_arg_s)
@@ -1,707 +1,711 b''
1 1 """Implementation of namespace-related magic functions.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (c) 2012 The IPython Development Team.
5 5 #
6 6 # Distributed under the terms of the Modified BSD License.
7 7 #
8 8 # The full license is in the file COPYING.txt, distributed with this software.
9 9 #-----------------------------------------------------------------------------
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14
15 15 # Stdlib
16 16 import gc
17 17 import re
18 18 import sys
19 19
20 20 # Our own packages
21 21 from IPython.core import page
22 22 from IPython.core.error import StdinNotImplementedError, UsageError
23 23 from IPython.core.magic import Magics, magics_class, line_magic
24 24 from IPython.testing.skipdoctest import skip_doctest
25 25 from IPython.utils.encoding import DEFAULT_ENCODING
26 26 from IPython.utils.openpy import read_py_file
27 27 from IPython.utils.path import get_py_filename
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Magic implementation classes
31 31 #-----------------------------------------------------------------------------
32 32
33 33 @magics_class
34 34 class NamespaceMagics(Magics):
35 35 """Magics to manage various aspects of the user's namespace.
36 36
37 37 These include listing variables, introspecting into them, etc.
38 38 """
39 39
40 40 @line_magic
41 41 def pinfo(self, parameter_s='', namespaces=None):
42 42 """Provide detailed information about an object.
43 43
44 44 '%pinfo object' is just a synonym for object? or ?object."""
45 45
46 46 #print 'pinfo par: <%s>' % parameter_s # dbg
47 47 # detail_level: 0 -> obj? , 1 -> obj??
48 48 detail_level = 0
49 49 # We need to detect if we got called as 'pinfo pinfo foo', which can
50 50 # happen if the user types 'pinfo foo?' at the cmd line.
51 51 pinfo,qmark1,oname,qmark2 = \
52 52 re.match(r'(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups()
53 53 if pinfo or qmark1 or qmark2:
54 54 detail_level = 1
55 55 if "*" in oname:
56 56 self.psearch(oname)
57 57 else:
58 58 self.shell._inspect('pinfo', oname, detail_level=detail_level,
59 59 namespaces=namespaces)
60 60
61 61 @line_magic
62 62 def pinfo2(self, parameter_s='', namespaces=None):
63 63 """Provide extra detailed information about an object.
64 64
65 65 '%pinfo2 object' is just a synonym for object?? or ??object."""
66 66 self.shell._inspect('pinfo', parameter_s, detail_level=1,
67 67 namespaces=namespaces)
68 68
69 69 @skip_doctest
70 70 @line_magic
71 71 def pdef(self, parameter_s='', namespaces=None):
72 72 """Print the call signature for any callable object.
73 73
74 74 If the object is a class, print the constructor information.
75 75
76 76 Examples
77 77 --------
78 78 ::
79 79
80 80 In [3]: %pdef urllib.urlopen
81 81 urllib.urlopen(url, data=None, proxies=None)
82 82 """
83 83 self.shell._inspect('pdef',parameter_s, namespaces)
84 84
85 85 @line_magic
86 86 def pdoc(self, parameter_s='', namespaces=None):
87 87 """Print the docstring for an object.
88 88
89 89 If the given object is a class, it will print both the class and the
90 90 constructor docstrings."""
91 91 self.shell._inspect('pdoc',parameter_s, namespaces)
92 92
93 93 @line_magic
94 94 def psource(self, parameter_s='', namespaces=None):
95 95 """Print (or run through pager) the source code for an object."""
96 96 if not parameter_s:
97 97 raise UsageError('Missing object name.')
98 98 self.shell._inspect('psource',parameter_s, namespaces)
99 99
100 100 @line_magic
101 101 def pfile(self, parameter_s='', namespaces=None):
102 102 """Print (or run through pager) the file where an object is defined.
103 103
104 104 The file opens at the line where the object definition begins. IPython
105 105 will honor the environment variable PAGER if set, and otherwise will
106 106 do its best to print the file in a convenient form.
107 107
108 108 If the given argument is not an object currently defined, IPython will
109 109 try to interpret it as a filename (automatically adding a .py extension
110 110 if needed). You can thus use %pfile as a syntax highlighting code
111 111 viewer."""
112 112
113 113 # first interpret argument as an object name
114 114 out = self.shell._inspect('pfile',parameter_s, namespaces)
115 115 # if not, try the input as a filename
116 116 if out == 'not found':
117 117 try:
118 118 filename = get_py_filename(parameter_s)
119 119 except IOError as msg:
120 120 print(msg)
121 121 return
122 122 page.page(self.shell.pycolorize(read_py_file(filename, skip_encoding_cookie=False)))
123 123
124 124 @line_magic
125 125 def psearch(self, parameter_s=''):
126 126 """Search for object in namespaces by wildcard.
127 127
128 128 %psearch [options] PATTERN [OBJECT TYPE]
129 129
130 130 Note: ? can be used as a synonym for %psearch, at the beginning or at
131 131 the end: both a*? and ?a* are equivalent to '%psearch a*'. Still, the
132 132 rest of the command line must be unchanged (options come first), so
133 133 for example the following forms are equivalent
134 134
135 135 %psearch -i a* function
136 136 -i a* function?
137 137 ?-i a* function
138 138
139 139 Arguments:
140 140
141 141 PATTERN
142 142
143 143 where PATTERN is a string containing * as a wildcard similar to its
144 144 use in a shell. The pattern is matched in all namespaces on the
145 145 search path. By default objects starting with a single _ are not
146 146 matched, many IPython generated objects have a single
147 147 underscore. The default is case insensitive matching. Matching is
148 148 also done on the attributes of objects and not only on the objects
149 149 in a module.
150 150
151 151 [OBJECT TYPE]
152 152
153 153 Is the name of a python type from the types module. The name is
154 154 given in lowercase without the ending type, ex. StringType is
155 155 written string. By adding a type here only objects matching the
156 156 given type are matched. Using all here makes the pattern match all
157 157 types (this is the default).
158 158
159 159 Options:
160 160
161 161 -a: makes the pattern match even objects whose names start with a
162 162 single underscore. These names are normally omitted from the
163 163 search.
164 164
165 165 -i/-c: make the pattern case insensitive/sensitive. If neither of
166 166 these options are given, the default is read from your configuration
167 167 file, with the option ``InteractiveShell.wildcards_case_sensitive``.
168 168 If this option is not specified in your configuration file, IPython's
169 169 internal default is to do a case sensitive search.
170 170
171 171 -e/-s NAMESPACE: exclude/search a given namespace. The pattern you
172 172 specify can be searched in any of the following namespaces:
173 173 'builtin', 'user', 'user_global','internal', 'alias', where
174 174 'builtin' and 'user' are the search defaults. Note that you should
175 175 not use quotes when specifying namespaces.
176 176
177 177 -l: List all available object types for object matching. This function
178 178 can be used without arguments.
179 179
180 180 'Builtin' contains the python module builtin, 'user' contains all
181 181 user data, 'alias' only contain the shell aliases and no python
182 182 objects, 'internal' contains objects used by IPython. The
183 183 'user_global' namespace is only used by embedded IPython instances,
184 184 and it contains module-level globals. You can add namespaces to the
185 185 search with -s or exclude them with -e (these options can be given
186 186 more than once).
187 187
188 188 Examples
189 189 --------
190 190 ::
191 191
192 192 %psearch a* -> objects beginning with an a
193 193 %psearch -e builtin a* -> objects NOT in the builtin space starting in a
194 194 %psearch a* function -> all functions beginning with an a
195 195 %psearch re.e* -> objects beginning with an e in module re
196 196 %psearch r*.e* -> objects that start with e in modules starting in r
197 197 %psearch r*.* string -> all strings in modules beginning with r
198 198
199 199 Case sensitive search::
200 200
201 201 %psearch -c a* list all object beginning with lower case a
202 202
203 203 Show objects beginning with a single _::
204 204
205 205 %psearch -a _* list objects beginning with a single underscore
206 206
207 207 List available objects::
208 208
209 209 %psearch -l list all available object types
210 210 """
211 211 # default namespaces to be searched
212 212 def_search = ['user_local', 'user_global', 'builtin']
213 213
214 214 # Process options/args
215 215 opts,args = self.parse_options(parameter_s,'cias:e:l',list_all=True)
216 216 opt = opts.get
217 217 shell = self.shell
218 218 psearch = shell.inspector.psearch
219 219
220 220 # select list object types
221 221 list_types = False
222 222 if 'l' in opts:
223 223 list_types = True
224 224
225 225 # select case options
226 226 if 'i' in opts:
227 227 ignore_case = True
228 228 elif 'c' in opts:
229 229 ignore_case = False
230 230 else:
231 231 ignore_case = not shell.wildcards_case_sensitive
232 232
233 233 # Build list of namespaces to search from user options
234 234 def_search.extend(opt('s',[]))
235 235 ns_exclude = ns_exclude=opt('e',[])
236 236 ns_search = [nm for nm in def_search if nm not in ns_exclude]
237 237
238 238 # Call the actual search
239 239 try:
240 240 psearch(args,shell.ns_table,ns_search,
241 241 show_all=opt('a'),ignore_case=ignore_case, list_types=list_types)
242 242 except:
243 243 shell.showtraceback()
244 244
245 245 @skip_doctest
246 246 @line_magic
247 247 def who_ls(self, parameter_s=''):
248 248 """Return a sorted list of all interactive variables.
249 249
250 250 If arguments are given, only variables of types matching these
251 251 arguments are returned.
252 252
253 253 Examples
254 254 --------
255 255 Define two variables and list them with who_ls::
256 256
257 257 In [1]: alpha = 123
258 258
259 259 In [2]: beta = 'test'
260 260
261 261 In [3]: %who_ls
262 262 Out[3]: ['alpha', 'beta']
263 263
264 264 In [4]: %who_ls int
265 265 Out[4]: ['alpha']
266 266
267 267 In [5]: %who_ls str
268 268 Out[5]: ['beta']
269 269 """
270 270
271 271 user_ns = self.shell.user_ns
272 272 user_ns_hidden = self.shell.user_ns_hidden
273 273 nonmatching = object() # This can never be in user_ns
274 274 out = [ i for i in user_ns
275 275 if not i.startswith('_') \
276 276 and (user_ns[i] is not user_ns_hidden.get(i, nonmatching)) ]
277 277
278 278 typelist = parameter_s.split()
279 279 if typelist:
280 280 typeset = set(typelist)
281 281 out = [i for i in out if type(user_ns[i]).__name__ in typeset]
282 282
283 283 out.sort()
284 284 return out
285 285
286 286 @skip_doctest
287 287 @line_magic
288 288 def who(self, parameter_s=''):
289 289 """Print all interactive variables, with some minimal formatting.
290 290
291 291 If any arguments are given, only variables whose type matches one of
292 292 these are printed. For example::
293 293
294 294 %who function str
295 295
296 296 will only list functions and strings, excluding all other types of
297 297 variables. To find the proper type names, simply use type(var) at a
298 298 command line to see how python prints type names. For example:
299 299
300 300 ::
301 301
302 302 In [1]: type('hello')\\
303 303 Out[1]: <type 'str'>
304 304
305 305 indicates that the type name for strings is 'str'.
306 306
307 307 ``%who`` always excludes executed names loaded through your configuration
308 308 file and things which are internal to IPython.
309 309
310 310 This is deliberate, as typically you may load many modules and the
311 311 purpose of %who is to show you only what you've manually defined.
312 312
313 313 Examples
314 314 --------
315 315
316 316 Define two variables and list them with who::
317 317
318 318 In [1]: alpha = 123
319 319
320 320 In [2]: beta = 'test'
321 321
322 322 In [3]: %who
323 323 alpha beta
324 324
325 325 In [4]: %who int
326 326 alpha
327 327
328 328 In [5]: %who str
329 329 beta
330 330 """
331 331
332 332 varlist = self.who_ls(parameter_s)
333 333 if not varlist:
334 334 if parameter_s:
335 335 print('No variables match your requested type.')
336 336 else:
337 337 print('Interactive namespace is empty.')
338 338 return
339 339
340 340 # if we have variables, move on...
341 341 count = 0
342 342 for i in varlist:
343 343 print(i+'\t', end=' ')
344 344 count += 1
345 345 if count > 8:
346 346 count = 0
347 347 print()
348 348 print()
349 349
350 350 @skip_doctest
351 351 @line_magic
352 352 def whos(self, parameter_s=''):
353 353 """Like %who, but gives some extra information about each variable.
354 354
355 355 The same type filtering of %who can be applied here.
356 356
357 357 For all variables, the type is printed. Additionally it prints:
358 358
359 359 - For {},[],(): their length.
360 360
361 361 - For numpy arrays, a summary with shape, number of
362 362 elements, typecode and size in memory.
363 363
364 364 - Everything else: a string representation, snipping their middle if
365 365 too long.
366 366
367 367 Examples
368 368 --------
369 369 Define two variables and list them with whos::
370 370
371 371 In [1]: alpha = 123
372 372
373 373 In [2]: beta = 'test'
374 374
375 375 In [3]: %whos
376 376 Variable Type Data/Info
377 377 --------------------------------
378 378 alpha int 123
379 379 beta str test
380 380 """
381 381
382 382 varnames = self.who_ls(parameter_s)
383 383 if not varnames:
384 384 if parameter_s:
385 385 print('No variables match your requested type.')
386 386 else:
387 387 print('Interactive namespace is empty.')
388 388 return
389 389
390 390 # if we have variables, move on...
391 391
392 392 # for these types, show len() instead of data:
393 393 seq_types = ['dict', 'list', 'tuple']
394 394
395 395 # for numpy arrays, display summary info
396 396 ndarray_type = None
397 397 if 'numpy' in sys.modules:
398 398 try:
399 399 from numpy import ndarray
400 400 except ImportError:
401 401 pass
402 402 else:
403 403 ndarray_type = ndarray.__name__
404 404
405 405 # Find all variable names and types so we can figure out column sizes
406 406
407 407 # some types are well known and can be shorter
408 408 abbrevs = {'IPython.core.macro.Macro' : 'Macro'}
409 409 def type_name(v):
410 410 tn = type(v).__name__
411 411 return abbrevs.get(tn,tn)
412 412
413 413 varlist = [self.shell.user_ns[n] for n in varnames]
414 414
415 415 typelist = []
416 416 for vv in varlist:
417 417 tt = type_name(vv)
418 418
419 419 if tt=='instance':
420 420 typelist.append( abbrevs.get(str(vv.__class__),
421 421 str(vv.__class__)))
422 422 else:
423 423 typelist.append(tt)
424 424
425 425 # column labels and # of spaces as separator
426 426 varlabel = 'Variable'
427 427 typelabel = 'Type'
428 428 datalabel = 'Data/Info'
429 429 colsep = 3
430 430 # variable format strings
431 431 vformat = "{0:<{varwidth}}{1:<{typewidth}}"
432 432 aformat = "%s: %s elems, type `%s`, %s bytes"
433 433 # find the size of the columns to format the output nicely
434 434 varwidth = max(max(map(len,varnames)), len(varlabel)) + colsep
435 435 typewidth = max(max(map(len,typelist)), len(typelabel)) + colsep
436 436 # table header
437 437 print(varlabel.ljust(varwidth) + typelabel.ljust(typewidth) + \
438 438 ' '+datalabel+'\n' + '-'*(varwidth+typewidth+len(datalabel)+1))
439 439 # and the table itself
440 440 kb = 1024
441 441 Mb = 1048576 # kb**2
442 442 for vname,var,vtype in zip(varnames,varlist,typelist):
443 443 print(vformat.format(vname, vtype, varwidth=varwidth, typewidth=typewidth), end=' ')
444 444 if vtype in seq_types:
445 445 print("n="+str(len(var)))
446 446 elif vtype == ndarray_type:
447 447 vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1]
448 448 if vtype==ndarray_type:
449 449 # numpy
450 450 vsize = var.size
451 451 vbytes = vsize*var.itemsize
452 452 vdtype = var.dtype
453 453
454 454 if vbytes < 100000:
455 455 print(aformat % (vshape, vsize, vdtype, vbytes))
456 456 else:
457 457 print(aformat % (vshape, vsize, vdtype, vbytes), end=' ')
458 458 if vbytes < Mb:
459 459 print('(%s kb)' % (vbytes/kb,))
460 460 else:
461 461 print('(%s Mb)' % (vbytes/Mb,))
462 462 else:
463 463 try:
464 464 vstr = str(var)
465 465 except UnicodeEncodeError:
466 466 vstr = var.encode(DEFAULT_ENCODING,
467 467 'backslashreplace')
468 468 except:
469 469 vstr = "<object with id %d (str() failed)>" % id(var)
470 470 vstr = vstr.replace('\n', '\\n')
471 471 if len(vstr) < 50:
472 472 print(vstr)
473 473 else:
474 474 print(vstr[:25] + "<...>" + vstr[-25:])
475 475
476 476 @line_magic
477 477 def reset(self, parameter_s=''):
478 478 """Resets the namespace by removing all names defined by the user, if
479 479 called without arguments, or by removing some types of objects, such
480 480 as everything currently in IPython's In[] and Out[] containers (see
481 481 the parameters for details).
482 482
483 483 Parameters
484 484 ----------
485 485 -f
486 force reset without asking for confirmation.
486 force reset without asking for confirmation.
487 487 -s
488 'Soft' reset: Only clears your namespace, leaving history intact.
488 'Soft' reset: Only clears your namespace, leaving history intact.
489 489 References to objects may be kept. By default (without this option),
490 490 we do a 'hard' reset, giving you a new session and removing all
491 491 references to objects from the current session.
492 492 --aggressive
493 493 Try to aggressively remove modules from sys.modules ; this
494 494 may allow you to reimport Python modules that have been updated and
495 495 pick up changes, but can have unattended consequences.
496 496
497 in : reset input history
498 out : reset output history
499 dhist : reset directory history
500 array : reset only variables that are NumPy arrays
497 in
498 reset input history
499 out
500 reset output history
501 dhist
502 reset directory history
503 array
504 reset only variables that are NumPy arrays
501 505
502 506 See Also
503 507 --------
504 508 reset_selective : invoked as ``%reset_selective``
505 509
506 510 Examples
507 511 --------
508 512 ::
509 513
510 514 In [6]: a = 1
511 515
512 516 In [7]: a
513 517 Out[7]: 1
514 518
515 519 In [8]: 'a' in get_ipython().user_ns
516 520 Out[8]: True
517 521
518 522 In [9]: %reset -f
519 523
520 524 In [1]: 'a' in get_ipython().user_ns
521 525 Out[1]: False
522 526
523 527 In [2]: %reset -f in
524 528 Flushing input history
525 529
526 530 In [3]: %reset -f dhist in
527 531 Flushing directory history
528 532 Flushing input history
529 533
530 534 Notes
531 535 -----
532 536 Calling this magic from clients that do not implement standard input,
533 537 such as the ipython notebook interface, will reset the namespace
534 538 without confirmation.
535 539 """
536 540 opts, args = self.parse_options(parameter_s, "sf", "aggressive", mode="list")
537 541 if "f" in opts:
538 542 ans = True
539 543 else:
540 544 try:
541 545 ans = self.shell.ask_yes_no(
542 546 "Once deleted, variables cannot be recovered. Proceed (y/[n])?",
543 547 default='n')
544 548 except StdinNotImplementedError:
545 549 ans = True
546 550 if not ans:
547 551 print('Nothing done.')
548 552 return
549 553
550 554 if 's' in opts: # Soft reset
551 555 user_ns = self.shell.user_ns
552 556 for i in self.who_ls():
553 557 del(user_ns[i])
554 558 elif len(args) == 0: # Hard reset
555 559 self.shell.reset(new_session=False, aggressive=("aggressive" in opts))
556 560
557 561 # reset in/out/dhist/array: previously extensinions/clearcmd.py
558 562 ip = self.shell
559 563 user_ns = self.shell.user_ns # local lookup, heavily used
560 564
561 565 for target in args:
562 566 target = target.lower() # make matches case insensitive
563 567 if target == 'out':
564 568 print("Flushing output cache (%d entries)" % len(user_ns['_oh']))
565 569 self.shell.displayhook.flush()
566 570
567 571 elif target == 'in':
568 572 print("Flushing input history")
569 573 pc = self.shell.displayhook.prompt_count + 1
570 574 for n in range(1, pc):
571 575 key = '_i'+repr(n)
572 576 user_ns.pop(key,None)
573 577 user_ns.update(dict(_i=u'',_ii=u'',_iii=u''))
574 578 hm = ip.history_manager
575 579 # don't delete these, as %save and %macro depending on the
576 580 # length of these lists to be preserved
577 581 hm.input_hist_parsed[:] = [''] * pc
578 582 hm.input_hist_raw[:] = [''] * pc
579 583 # hm has internal machinery for _i,_ii,_iii, clear it out
580 584 hm._i = hm._ii = hm._iii = hm._i00 = u''
581 585
582 586 elif target == 'array':
583 587 # Support cleaning up numpy arrays
584 588 try:
585 589 from numpy import ndarray
586 590 # This must be done with items and not iteritems because
587 591 # we're going to modify the dict in-place.
588 592 for x,val in list(user_ns.items()):
589 593 if isinstance(val,ndarray):
590 594 del user_ns[x]
591 595 except ImportError:
592 596 print("reset array only works if Numpy is available.")
593 597
594 598 elif target == 'dhist':
595 599 print("Flushing directory history")
596 600 del user_ns['_dh'][:]
597 601
598 602 else:
599 603 print("Don't know how to reset ", end=' ')
600 604 print(target + ", please run `%reset?` for details")
601 605
602 606 gc.collect()
603 607
604 608 @line_magic
605 609 def reset_selective(self, parameter_s=''):
606 610 """Resets the namespace by removing names defined by the user.
607 611
608 612 Input/Output history are left around in case you need them.
609 613
610 614 %reset_selective [-f] regex
611 615
612 616 No action is taken if regex is not included
613 617
614 618 Options
615 619 -f : force reset without asking for confirmation.
616 620
617 621 See Also
618 622 --------
619 623 reset : invoked as ``%reset``
620 624
621 625 Examples
622 626 --------
623 627 We first fully reset the namespace so your output looks identical to
624 628 this example for pedagogical reasons; in practice you do not need a
625 629 full reset::
626 630
627 631 In [1]: %reset -f
628 632
629 633 Now, with a clean namespace we can make a few variables and use
630 634 ``%reset_selective`` to only delete names that match our regexp::
631 635
632 636 In [2]: a=1; b=2; c=3; b1m=4; b2m=5; b3m=6; b4m=7; b2s=8
633 637
634 638 In [3]: who_ls
635 639 Out[3]: ['a', 'b', 'b1m', 'b2m', 'b2s', 'b3m', 'b4m', 'c']
636 640
637 641 In [4]: %reset_selective -f b[2-3]m
638 642
639 643 In [5]: who_ls
640 644 Out[5]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c']
641 645
642 646 In [6]: %reset_selective -f d
643 647
644 648 In [7]: who_ls
645 649 Out[7]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c']
646 650
647 651 In [8]: %reset_selective -f c
648 652
649 653 In [9]: who_ls
650 654 Out[9]: ['a', 'b', 'b1m', 'b2s', 'b4m']
651 655
652 656 In [10]: %reset_selective -f b
653 657
654 658 In [11]: who_ls
655 659 Out[11]: ['a']
656 660
657 661 Notes
658 662 -----
659 663 Calling this magic from clients that do not implement standard input,
660 664 such as the ipython notebook interface, will reset the namespace
661 665 without confirmation.
662 666 """
663 667
664 668 opts, regex = self.parse_options(parameter_s,'f')
665 669
666 670 if 'f' in opts:
667 671 ans = True
668 672 else:
669 673 try:
670 674 ans = self.shell.ask_yes_no(
671 675 "Once deleted, variables cannot be recovered. Proceed (y/[n])? ",
672 676 default='n')
673 677 except StdinNotImplementedError:
674 678 ans = True
675 679 if not ans:
676 680 print('Nothing done.')
677 681 return
678 682 user_ns = self.shell.user_ns
679 683 if not regex:
680 684 print('No regex pattern specified. Nothing done.')
681 685 return
682 686 else:
683 687 try:
684 688 m = re.compile(regex)
685 689 except TypeError as e:
686 690 raise TypeError('regex must be a string or compiled pattern') from e
687 691 for i in self.who_ls():
688 692 if m.search(i):
689 693 del(user_ns[i])
690 694
691 695 @line_magic
692 696 def xdel(self, parameter_s=''):
693 697 """Delete a variable, trying to clear it from anywhere that
694 698 IPython's machinery has references to it. By default, this uses
695 699 the identity of the named object in the user namespace to remove
696 700 references held under other names. The object is also removed
697 701 from the output history.
698 702
699 703 Options
700 704 -n : Delete the specified name from all namespaces, without
701 705 checking their identity.
702 706 """
703 707 opts, varname = self.parse_options(parameter_s,'n')
704 708 try:
705 709 self.shell.del_var(varname, ('n' in opts))
706 710 except (NameError, ValueError) as e:
707 711 print(type(e).__name__ +": "+ str(e))
@@ -1,1055 +1,1055 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tools for inspecting Python objects.
3 3
4 4 Uses syntax highlighting for presenting the various information elements.
5 5
6 6 Similar in spirit to the inspect module, but all calls take a name argument to
7 7 reference the name under which an object is being read.
8 8 """
9 9
10 10 # Copyright (c) IPython Development Team.
11 11 # Distributed under the terms of the Modified BSD License.
12 12
13 13 __all__ = ['Inspector','InspectColors']
14 14
15 15 # stdlib modules
16 16 import ast
17 17 import inspect
18 18 from inspect import signature
19 19 import linecache
20 20 import warnings
21 21 import os
22 22 from textwrap import dedent
23 23 import types
24 24 import io as stdlib_io
25 25
26 26 from typing import Union
27 27
28 28 # IPython's own
29 29 from IPython.core import page
30 30 from IPython.lib.pretty import pretty
31 31 from IPython.testing.skipdoctest import skip_doctest
32 32 from IPython.utils import PyColorize
33 33 from IPython.utils import openpy
34 34 from IPython.utils import py3compat
35 35 from IPython.utils.dir2 import safe_hasattr
36 36 from IPython.utils.path import compress_user
37 37 from IPython.utils.text import indent
38 38 from IPython.utils.wildcard import list_namespace
39 39 from IPython.utils.wildcard import typestr2type
40 40 from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable
41 41 from IPython.utils.py3compat import cast_unicode
42 42 from IPython.utils.colorable import Colorable
43 43 from IPython.utils.decorators import undoc
44 44
45 45 from pygments import highlight
46 46 from pygments.lexers import PythonLexer
47 47 from pygments.formatters import HtmlFormatter
48 48
49 49 def pylight(code):
50 50 return highlight(code, PythonLexer(), HtmlFormatter(noclasses=True))
51 51
52 52 # builtin docstrings to ignore
53 53 _func_call_docstring = types.FunctionType.__call__.__doc__
54 54 _object_init_docstring = object.__init__.__doc__
55 55 _builtin_type_docstrings = {
56 56 inspect.getdoc(t) for t in (types.ModuleType, types.MethodType,
57 57 types.FunctionType, property)
58 58 }
59 59
60 60 _builtin_func_type = type(all)
61 61 _builtin_meth_type = type(str.upper) # Bound methods have the same type as builtin functions
62 62 #****************************************************************************
63 63 # Builtin color schemes
64 64
65 65 Colors = TermColors # just a shorthand
66 66
67 67 InspectColors = PyColorize.ANSICodeColors
68 68
69 69 #****************************************************************************
70 70 # Auxiliary functions and objects
71 71
72 72 # See the messaging spec for the definition of all these fields. This list
73 73 # effectively defines the order of display
74 74 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
75 75 'length', 'file', 'definition', 'docstring', 'source',
76 76 'init_definition', 'class_docstring', 'init_docstring',
77 77 'call_def', 'call_docstring',
78 78 # These won't be printed but will be used to determine how to
79 79 # format the object
80 80 'ismagic', 'isalias', 'isclass', 'found', 'name'
81 81 ]
82 82
83 83
84 84 def object_info(**kw):
85 85 """Make an object info dict with all fields present."""
86 86 infodict = {k:None for k in info_fields}
87 87 infodict.update(kw)
88 88 return infodict
89 89
90 90
91 91 def get_encoding(obj):
92 92 """Get encoding for python source file defining obj
93 93
94 94 Returns None if obj is not defined in a sourcefile.
95 95 """
96 96 ofile = find_file(obj)
97 97 # run contents of file through pager starting at line where the object
98 98 # is defined, as long as the file isn't binary and is actually on the
99 99 # filesystem.
100 100 if ofile is None:
101 101 return None
102 102 elif ofile.endswith(('.so', '.dll', '.pyd')):
103 103 return None
104 104 elif not os.path.isfile(ofile):
105 105 return None
106 106 else:
107 107 # Print only text files, not extension binaries. Note that
108 108 # getsourcelines returns lineno with 1-offset and page() uses
109 109 # 0-offset, so we must adjust.
110 110 with stdlib_io.open(ofile, 'rb') as buffer: # Tweaked to use io.open for Python 2
111 111 encoding, lines = openpy.detect_encoding(buffer.readline)
112 112 return encoding
113 113
114 114 def getdoc(obj) -> Union[str,None]:
115 115 """Stable wrapper around inspect.getdoc.
116 116
117 117 This can't crash because of attribute problems.
118 118
119 119 It also attempts to call a getdoc() method on the given object. This
120 120 allows objects which provide their docstrings via non-standard mechanisms
121 121 (like Pyro proxies) to still be inspected by ipython's ? system.
122 122 """
123 123 # Allow objects to offer customized documentation via a getdoc method:
124 124 try:
125 125 ds = obj.getdoc()
126 126 except Exception:
127 127 pass
128 128 else:
129 129 if isinstance(ds, str):
130 130 return inspect.cleandoc(ds)
131 131 docstr = inspect.getdoc(obj)
132 132 return docstr
133 133
134 134
135 135 def getsource(obj, oname='') -> Union[str,None]:
136 136 """Wrapper around inspect.getsource.
137 137
138 138 This can be modified by other projects to provide customized source
139 139 extraction.
140 140
141 141 Parameters
142 142 ----------
143 143 obj : object
144 144 an object whose source code we will attempt to extract
145 145 oname : str
146 146 (optional) a name under which the object is known
147 147
148 148 Returns
149 149 -------
150 150 src : unicode or None
151 151
152 152 """
153 153
154 154 if isinstance(obj, property):
155 155 sources = []
156 156 for attrname in ['fget', 'fset', 'fdel']:
157 157 fn = getattr(obj, attrname)
158 158 if fn is not None:
159 159 encoding = get_encoding(fn)
160 160 oname_prefix = ('%s.' % oname) if oname else ''
161 161 sources.append(''.join(('# ', oname_prefix, attrname)))
162 162 if inspect.isfunction(fn):
163 163 sources.append(dedent(getsource(fn)))
164 164 else:
165 165 # Default str/repr only prints function name,
166 166 # pretty.pretty prints module name too.
167 167 sources.append(
168 168 '%s%s = %s\n' % (oname_prefix, attrname, pretty(fn))
169 169 )
170 170 if sources:
171 171 return '\n'.join(sources)
172 172 else:
173 173 return None
174 174
175 175 else:
176 176 # Get source for non-property objects.
177 177
178 178 obj = _get_wrapped(obj)
179 179
180 180 try:
181 181 src = inspect.getsource(obj)
182 182 except TypeError:
183 183 # The object itself provided no meaningful source, try looking for
184 184 # its class definition instead.
185 185 try:
186 186 src = inspect.getsource(obj.__class__)
187 187 except (OSError, TypeError):
188 188 return None
189 189 except OSError:
190 190 return None
191 191
192 192 return src
193 193
194 194
195 195 def is_simple_callable(obj):
196 196 """True if obj is a function ()"""
197 197 return (inspect.isfunction(obj) or inspect.ismethod(obj) or \
198 198 isinstance(obj, _builtin_func_type) or isinstance(obj, _builtin_meth_type))
199 199
200 200 @undoc
201 201 def getargspec(obj):
202 202 """Wrapper around :func:`inspect.getfullargspec`
203 203
204 204 In addition to functions and methods, this can also handle objects with a
205 205 ``__call__`` attribute.
206 206
207 207 DEPRECATED: Deprecated since 7.10. Do not use, will be removed.
208 208 """
209 209
210 210 warnings.warn('`getargspec` function is deprecated as of IPython 7.10'
211 211 'and will be removed in future versions.', DeprecationWarning, stacklevel=2)
212 212
213 213 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
214 214 obj = obj.__call__
215 215
216 216 return inspect.getfullargspec(obj)
217 217
218 218 @undoc
219 219 def format_argspec(argspec):
220 220 """Format argspect, convenience wrapper around inspect's.
221 221
222 222 This takes a dict instead of ordered arguments and calls
223 223 inspect.format_argspec with the arguments in the necessary order.
224 224
225 225 DEPRECATED (since 7.10): Do not use; will be removed in future versions.
226 226 """
227 227
228 228 warnings.warn('`format_argspec` function is deprecated as of IPython 7.10'
229 229 'and will be removed in future versions.', DeprecationWarning, stacklevel=2)
230 230
231 231
232 232 return inspect.formatargspec(argspec['args'], argspec['varargs'],
233 233 argspec['varkw'], argspec['defaults'])
234 234
235 235 @undoc
236 236 def call_tip(oinfo, format_call=True):
237 237 """DEPRECATED since 6.0. Extract call tip data from an oinfo dict."""
238 238 warnings.warn(
239 239 "`call_tip` function is deprecated as of IPython 6.0"
240 240 "and will be removed in future versions.",
241 241 DeprecationWarning,
242 242 stacklevel=2,
243 243 )
244 244 # Get call definition
245 245 argspec = oinfo.get('argspec')
246 246 if argspec is None:
247 247 call_line = None
248 248 else:
249 249 # Callable objects will have 'self' as their first argument, prune
250 250 # it out if it's there for clarity (since users do *not* pass an
251 251 # extra first argument explicitly).
252 252 try:
253 253 has_self = argspec['args'][0] == 'self'
254 254 except (KeyError, IndexError):
255 255 pass
256 256 else:
257 257 if has_self:
258 258 argspec['args'] = argspec['args'][1:]
259 259
260 260 call_line = oinfo['name']+format_argspec(argspec)
261 261
262 262 # Now get docstring.
263 263 # The priority is: call docstring, constructor docstring, main one.
264 264 doc = oinfo.get('call_docstring')
265 265 if doc is None:
266 266 doc = oinfo.get('init_docstring')
267 267 if doc is None:
268 268 doc = oinfo.get('docstring','')
269 269
270 270 return call_line, doc
271 271
272 272
273 273 def _get_wrapped(obj):
274 274 """Get the original object if wrapped in one or more @decorators
275 275
276 276 Some objects automatically construct similar objects on any unrecognised
277 277 attribute access (e.g. unittest.mock.call). To protect against infinite loops,
278 278 this will arbitrarily cut off after 100 levels of obj.__wrapped__
279 279 attribute access. --TK, Jan 2016
280 280 """
281 281 orig_obj = obj
282 282 i = 0
283 283 while safe_hasattr(obj, '__wrapped__'):
284 284 obj = obj.__wrapped__
285 285 i += 1
286 286 if i > 100:
287 287 # __wrapped__ is probably a lie, so return the thing we started with
288 288 return orig_obj
289 289 return obj
290 290
291 291 def find_file(obj) -> str:
292 292 """Find the absolute path to the file where an object was defined.
293 293
294 294 This is essentially a robust wrapper around `inspect.getabsfile`.
295 295
296 296 Returns None if no file can be found.
297 297
298 298 Parameters
299 299 ----------
300 300 obj : any Python object
301 301
302 302 Returns
303 303 -------
304 304 fname : str
305 305 The absolute path to the file where the object was defined.
306 306 """
307 307 obj = _get_wrapped(obj)
308 308
309 309 fname = None
310 310 try:
311 311 fname = inspect.getabsfile(obj)
312 312 except TypeError:
313 313 # For an instance, the file that matters is where its class was
314 314 # declared.
315 315 try:
316 316 fname = inspect.getabsfile(obj.__class__)
317 317 except (OSError, TypeError):
318 318 # Can happen for builtins
319 319 pass
320 320 except OSError:
321 321 pass
322 322
323 323 return cast_unicode(fname)
324 324
325 325
326 326 def find_source_lines(obj):
327 327 """Find the line number in a file where an object was defined.
328 328
329 329 This is essentially a robust wrapper around `inspect.getsourcelines`.
330 330
331 331 Returns None if no file can be found.
332 332
333 333 Parameters
334 334 ----------
335 335 obj : any Python object
336 336
337 337 Returns
338 338 -------
339 339 lineno : int
340 340 The line number where the object definition starts.
341 341 """
342 342 obj = _get_wrapped(obj)
343 343
344 344 try:
345 345 lineno = inspect.getsourcelines(obj)[1]
346 346 except TypeError:
347 347 # For instances, try the class object like getsource() does
348 348 try:
349 349 lineno = inspect.getsourcelines(obj.__class__)[1]
350 350 except (OSError, TypeError):
351 351 return None
352 352 except OSError:
353 353 return None
354 354
355 355 return lineno
356 356
357 357 class Inspector(Colorable):
358 358
359 359 def __init__(self, color_table=InspectColors,
360 360 code_color_table=PyColorize.ANSICodeColors,
361 361 scheme=None,
362 362 str_detail_level=0,
363 363 parent=None, config=None):
364 364 super(Inspector, self).__init__(parent=parent, config=config)
365 365 self.color_table = color_table
366 366 self.parser = PyColorize.Parser(out='str', parent=self, style=scheme)
367 367 self.format = self.parser.format
368 368 self.str_detail_level = str_detail_level
369 369 self.set_active_scheme(scheme)
370 370
371 371 def _getdef(self,obj,oname='') -> Union[str,None]:
372 372 """Return the call signature for any callable object.
373 373
374 374 If any exception is generated, None is returned instead and the
375 375 exception is suppressed."""
376 376 try:
377 377 return _render_signature(signature(obj), oname)
378 378 except:
379 379 return None
380 380
381 381 def __head(self,h) -> str:
382 382 """Return a header string with proper colors."""
383 383 return '%s%s%s' % (self.color_table.active_colors.header,h,
384 384 self.color_table.active_colors.normal)
385 385
386 386 def set_active_scheme(self, scheme):
387 387 if scheme is not None:
388 388 self.color_table.set_active_scheme(scheme)
389 389 self.parser.color_table.set_active_scheme(scheme)
390 390
391 391 def noinfo(self, msg, oname):
392 392 """Generic message when no information is found."""
393 393 print('No %s found' % msg, end=' ')
394 394 if oname:
395 395 print('for %s' % oname)
396 396 else:
397 397 print()
398 398
399 399 def pdef(self, obj, oname=''):
400 400 """Print the call signature for any callable object.
401 401
402 402 If the object is a class, print the constructor information."""
403 403
404 404 if not callable(obj):
405 405 print('Object is not callable.')
406 406 return
407 407
408 408 header = ''
409 409
410 410 if inspect.isclass(obj):
411 411 header = self.__head('Class constructor information:\n')
412 412
413 413
414 414 output = self._getdef(obj,oname)
415 415 if output is None:
416 416 self.noinfo('definition header',oname)
417 417 else:
418 418 print(header,self.format(output), end=' ')
419 419
420 420 # In Python 3, all classes are new-style, so they all have __init__.
421 421 @skip_doctest
422 422 def pdoc(self, obj, oname='', formatter=None):
423 423 """Print the docstring for any object.
424 424
425 425 Optional:
426 426 -formatter: a function to run the docstring through for specially
427 427 formatted docstrings.
428 428
429 429 Examples
430 430 --------
431 431 In [1]: class NoInit:
432 432 ...: pass
433 433
434 434 In [2]: class NoDoc:
435 435 ...: def __init__(self):
436 436 ...: pass
437 437
438 438 In [3]: %pdoc NoDoc
439 439 No documentation found for NoDoc
440 440
441 441 In [4]: %pdoc NoInit
442 442 No documentation found for NoInit
443 443
444 444 In [5]: obj = NoInit()
445 445
446 446 In [6]: %pdoc obj
447 447 No documentation found for obj
448 448
449 449 In [5]: obj2 = NoDoc()
450 450
451 451 In [6]: %pdoc obj2
452 452 No documentation found for obj2
453 453 """
454 454
455 455 head = self.__head # For convenience
456 456 lines = []
457 457 ds = getdoc(obj)
458 458 if formatter:
459 459 ds = formatter(ds).get('plain/text', ds)
460 460 if ds:
461 461 lines.append(head("Class docstring:"))
462 462 lines.append(indent(ds))
463 463 if inspect.isclass(obj) and hasattr(obj, '__init__'):
464 464 init_ds = getdoc(obj.__init__)
465 465 if init_ds is not None:
466 466 lines.append(head("Init docstring:"))
467 467 lines.append(indent(init_ds))
468 468 elif hasattr(obj,'__call__'):
469 469 call_ds = getdoc(obj.__call__)
470 470 if call_ds:
471 471 lines.append(head("Call docstring:"))
472 472 lines.append(indent(call_ds))
473 473
474 474 if not lines:
475 475 self.noinfo('documentation',oname)
476 476 else:
477 477 page.page('\n'.join(lines))
478 478
479 479 def psource(self, obj, oname=''):
480 480 """Print the source code for an object."""
481 481
482 482 # Flush the source cache because inspect can return out-of-date source
483 483 linecache.checkcache()
484 484 try:
485 485 src = getsource(obj, oname=oname)
486 486 except Exception:
487 487 src = None
488 488
489 489 if src is None:
490 490 self.noinfo('source', oname)
491 491 else:
492 492 page.page(self.format(src))
493 493
494 494 def pfile(self, obj, oname=''):
495 495 """Show the whole file where an object was defined."""
496 496
497 497 lineno = find_source_lines(obj)
498 498 if lineno is None:
499 499 self.noinfo('file', oname)
500 500 return
501 501
502 502 ofile = find_file(obj)
503 503 # run contents of file through pager starting at line where the object
504 504 # is defined, as long as the file isn't binary and is actually on the
505 505 # filesystem.
506 506 if ofile.endswith(('.so', '.dll', '.pyd')):
507 507 print('File %r is binary, not printing.' % ofile)
508 508 elif not os.path.isfile(ofile):
509 509 print('File %r does not exist, not printing.' % ofile)
510 510 else:
511 511 # Print only text files, not extension binaries. Note that
512 512 # getsourcelines returns lineno with 1-offset and page() uses
513 513 # 0-offset, so we must adjust.
514 514 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
515 515
516 516
517 517 def _mime_format(self, text:str, formatter=None) -> dict:
518 518 """Return a mime bundle representation of the input text.
519 519
520 520 - if `formatter` is None, the returned mime bundle has
521 521 a `text/plain` field, with the input text.
522 522 a `text/html` field with a `<pre>` tag containing the input text.
523 523
524 524 - if `formatter` is not None, it must be a callable transforming the
525 525 input text into a mime bundle. Default values for `text/plain` and
526 526 `text/html` representations are the ones described above.
527 527
528 528 Note:
529 529
530 530 Formatters returning strings are supported but this behavior is deprecated.
531 531
532 532 """
533 533 defaults = {
534 534 'text/plain': text,
535 535 'text/html': '<pre>' + text + '</pre>'
536 536 }
537 537
538 538 if formatter is None:
539 539 return defaults
540 540 else:
541 541 formatted = formatter(text)
542 542
543 543 if not isinstance(formatted, dict):
544 544 # Handle the deprecated behavior of a formatter returning
545 545 # a string instead of a mime bundle.
546 546 return {
547 547 'text/plain': formatted,
548 548 'text/html': '<pre>' + formatted + '</pre>'
549 549 }
550 550
551 551 else:
552 552 return dict(defaults, **formatted)
553 553
554 554
555 555 def format_mime(self, bundle):
556 556
557 557 text_plain = bundle['text/plain']
558 558
559 559 text = ''
560 560 heads, bodies = list(zip(*text_plain))
561 561 _len = max(len(h) for h in heads)
562 562
563 563 for head, body in zip(heads, bodies):
564 564 body = body.strip('\n')
565 565 delim = '\n' if '\n' in body else ' '
566 566 text += self.__head(head+':') + (_len - len(head))*' ' +delim + body +'\n'
567 567
568 568 bundle['text/plain'] = text
569 569 return bundle
570 570
571 571 def _get_info(
572 572 self, obj, oname="", formatter=None, info=None, detail_level=0, omit_sections=()
573 573 ):
574 574 """Retrieve an info dict and format it.
575 575
576 576 Parameters
577 577 ----------
578 578 obj : any
579 579 Object to inspect and return info from
580 oname: str (default: ''):
580 oname : str (default: ''):
581 581 Name of the variable pointing to `obj`.
582 582 formatter : callable
583 info:
583 info
584 584 already computed information
585 585 detail_level : integer
586 586 Granularity of detail level, if set to 1, give more information.
587 587 omit_sections : container[str]
588 588 Titles or keys to omit from output (can be set, tuple, etc., anything supporting `in`)
589 589 """
590 590
591 591 info = self.info(obj, oname=oname, info=info, detail_level=detail_level)
592 592
593 593 _mime = {
594 594 'text/plain': [],
595 595 'text/html': '',
596 596 }
597 597
598 598 def append_field(bundle, title:str, key:str, formatter=None):
599 599 if title in omit_sections or key in omit_sections:
600 600 return
601 601 field = info[key]
602 602 if field is not None:
603 603 formatted_field = self._mime_format(field, formatter)
604 604 bundle['text/plain'].append((title, formatted_field['text/plain']))
605 605 bundle['text/html'] += '<h1>' + title + '</h1>\n' + formatted_field['text/html'] + '\n'
606 606
607 607 def code_formatter(text):
608 608 return {
609 609 'text/plain': self.format(text),
610 610 'text/html': pylight(text)
611 611 }
612 612
613 613 if info['isalias']:
614 614 append_field(_mime, 'Repr', 'string_form')
615 615
616 616 elif info['ismagic']:
617 617 if detail_level > 0:
618 618 append_field(_mime, 'Source', 'source', code_formatter)
619 619 else:
620 620 append_field(_mime, 'Docstring', 'docstring', formatter)
621 621 append_field(_mime, 'File', 'file')
622 622
623 623 elif info['isclass'] or is_simple_callable(obj):
624 624 # Functions, methods, classes
625 625 append_field(_mime, 'Signature', 'definition', code_formatter)
626 626 append_field(_mime, 'Init signature', 'init_definition', code_formatter)
627 627 append_field(_mime, 'Docstring', 'docstring', formatter)
628 628 if detail_level > 0 and info['source']:
629 629 append_field(_mime, 'Source', 'source', code_formatter)
630 630 else:
631 631 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
632 632
633 633 append_field(_mime, 'File', 'file')
634 634 append_field(_mime, 'Type', 'type_name')
635 635 append_field(_mime, 'Subclasses', 'subclasses')
636 636
637 637 else:
638 638 # General Python objects
639 639 append_field(_mime, 'Signature', 'definition', code_formatter)
640 640 append_field(_mime, 'Call signature', 'call_def', code_formatter)
641 641 append_field(_mime, 'Type', 'type_name')
642 642 append_field(_mime, 'String form', 'string_form')
643 643
644 644 # Namespace
645 645 if info['namespace'] != 'Interactive':
646 646 append_field(_mime, 'Namespace', 'namespace')
647 647
648 648 append_field(_mime, 'Length', 'length')
649 649 append_field(_mime, 'File', 'file')
650 650
651 651 # Source or docstring, depending on detail level and whether
652 652 # source found.
653 653 if detail_level > 0 and info['source']:
654 654 append_field(_mime, 'Source', 'source', code_formatter)
655 655 else:
656 656 append_field(_mime, 'Docstring', 'docstring', formatter)
657 657
658 658 append_field(_mime, 'Class docstring', 'class_docstring', formatter)
659 659 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
660 660 append_field(_mime, 'Call docstring', 'call_docstring', formatter)
661 661
662 662
663 663 return self.format_mime(_mime)
664 664
665 665 def pinfo(
666 666 self,
667 667 obj,
668 668 oname="",
669 669 formatter=None,
670 670 info=None,
671 671 detail_level=0,
672 672 enable_html_pager=True,
673 673 omit_sections=(),
674 674 ):
675 675 """Show detailed information about an object.
676 676
677 677 Optional arguments:
678 678
679 679 - oname: name of the variable pointing to the object.
680 680
681 681 - formatter: callable (optional)
682 682 A special formatter for docstrings.
683 683
684 684 The formatter is a callable that takes a string as an input
685 685 and returns either a formatted string or a mime type bundle
686 686 in the form of a dictionary.
687 687
688 688 Although the support of custom formatter returning a string
689 689 instead of a mime type bundle is deprecated.
690 690
691 691 - info: a structure with some information fields which may have been
692 692 precomputed already.
693 693
694 694 - detail_level: if set to 1, more information is given.
695 695
696 696 - omit_sections: set of section keys and titles to omit
697 697 """
698 698 info = self._get_info(
699 699 obj, oname, formatter, info, detail_level, omit_sections=omit_sections
700 700 )
701 701 if not enable_html_pager:
702 702 del info['text/html']
703 703 page.page(info)
704 704
705 705 def _info(self, obj, oname="", info=None, detail_level=0):
706 706 """
707 707 Inspector.info() was likely improperly marked as deprecated
708 708 while only a parameter was deprecated. We "un-deprecate" it.
709 709 """
710 710
711 711 warnings.warn(
712 712 "The `Inspector.info()` method has been un-deprecated as of 8.0 "
713 713 "and the `formatter=` keyword removed. `Inspector._info` is now "
714 714 "an alias, and you can just call `.info()` directly.",
715 715 DeprecationWarning,
716 716 stacklevel=2,
717 717 )
718 718 return self.info(obj, oname=oname, info=info, detail_level=detail_level)
719 719
720 720 def info(self, obj, oname="", info=None, detail_level=0) -> dict:
721 721 """Compute a dict with detailed information about an object.
722 722
723 723 Parameters
724 724 ----------
725 725 obj : any
726 726 An object to find information about
727 727 oname : str (default: '')
728 728 Name of the variable pointing to `obj`.
729 729 info : (default: None)
730 730 A struct (dict like with attr access) with some information fields
731 731 which may have been precomputed already.
732 732 detail_level : int (default:0)
733 733 If set to 1, more information is given.
734 734
735 735 Returns
736 736 -------
737 737 An object info dict with known fields from `info_fields`. Keys are
738 738 strings, values are string or None.
739 739 """
740 740
741 741 if info is None:
742 742 ismagic = False
743 743 isalias = False
744 744 ospace = ''
745 745 else:
746 746 ismagic = info.ismagic
747 747 isalias = info.isalias
748 748 ospace = info.namespace
749 749
750 750 # Get docstring, special-casing aliases:
751 751 if isalias:
752 752 if not callable(obj):
753 753 try:
754 754 ds = "Alias to the system command:\n %s" % obj[1]
755 755 except:
756 756 ds = "Alias: " + str(obj)
757 757 else:
758 758 ds = "Alias to " + str(obj)
759 759 if obj.__doc__:
760 760 ds += "\nDocstring:\n" + obj.__doc__
761 761 else:
762 762 ds = getdoc(obj)
763 763 if ds is None:
764 764 ds = '<no docstring>'
765 765
766 766 # store output in a dict, we initialize it here and fill it as we go
767 767 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic, subclasses=None)
768 768
769 769 string_max = 200 # max size of strings to show (snipped if longer)
770 770 shalf = int((string_max - 5) / 2)
771 771
772 772 if ismagic:
773 773 out['type_name'] = 'Magic function'
774 774 elif isalias:
775 775 out['type_name'] = 'System alias'
776 776 else:
777 777 out['type_name'] = type(obj).__name__
778 778
779 779 try:
780 780 bclass = obj.__class__
781 781 out['base_class'] = str(bclass)
782 782 except:
783 783 pass
784 784
785 785 # String form, but snip if too long in ? form (full in ??)
786 786 if detail_level >= self.str_detail_level:
787 787 try:
788 788 ostr = str(obj)
789 789 str_head = 'string_form'
790 790 if not detail_level and len(ostr)>string_max:
791 791 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
792 792 ostr = ("\n" + " " * len(str_head.expandtabs())).\
793 793 join(q.strip() for q in ostr.split("\n"))
794 794 out[str_head] = ostr
795 795 except:
796 796 pass
797 797
798 798 if ospace:
799 799 out['namespace'] = ospace
800 800
801 801 # Length (for strings and lists)
802 802 try:
803 803 out['length'] = str(len(obj))
804 804 except Exception:
805 805 pass
806 806
807 807 # Filename where object was defined
808 808 binary_file = False
809 809 fname = find_file(obj)
810 810 if fname is None:
811 811 # if anything goes wrong, we don't want to show source, so it's as
812 812 # if the file was binary
813 813 binary_file = True
814 814 else:
815 815 if fname.endswith(('.so', '.dll', '.pyd')):
816 816 binary_file = True
817 817 elif fname.endswith('<string>'):
818 818 fname = 'Dynamically generated function. No source code available.'
819 819 out['file'] = compress_user(fname)
820 820
821 821 # Original source code for a callable, class or property.
822 822 if detail_level:
823 823 # Flush the source cache because inspect can return out-of-date
824 824 # source
825 825 linecache.checkcache()
826 826 try:
827 827 if isinstance(obj, property) or not binary_file:
828 828 src = getsource(obj, oname)
829 829 if src is not None:
830 830 src = src.rstrip()
831 831 out['source'] = src
832 832
833 833 except Exception:
834 834 pass
835 835
836 836 # Add docstring only if no source is to be shown (avoid repetitions).
837 837 if ds and not self._source_contains_docstring(out.get('source'), ds):
838 838 out['docstring'] = ds
839 839
840 840 # Constructor docstring for classes
841 841 if inspect.isclass(obj):
842 842 out['isclass'] = True
843 843
844 844 # get the init signature:
845 845 try:
846 846 init_def = self._getdef(obj, oname)
847 847 except AttributeError:
848 848 init_def = None
849 849
850 850 # get the __init__ docstring
851 851 try:
852 852 obj_init = obj.__init__
853 853 except AttributeError:
854 854 init_ds = None
855 855 else:
856 856 if init_def is None:
857 857 # Get signature from init if top-level sig failed.
858 858 # Can happen for built-in types (list, etc.).
859 859 try:
860 860 init_def = self._getdef(obj_init, oname)
861 861 except AttributeError:
862 862 pass
863 863 init_ds = getdoc(obj_init)
864 864 # Skip Python's auto-generated docstrings
865 865 if init_ds == _object_init_docstring:
866 866 init_ds = None
867 867
868 868 if init_def:
869 869 out['init_definition'] = init_def
870 870
871 871 if init_ds:
872 872 out['init_docstring'] = init_ds
873 873
874 874 names = [sub.__name__ for sub in type.__subclasses__(obj)]
875 875 if len(names) < 10:
876 876 all_names = ', '.join(names)
877 877 else:
878 878 all_names = ', '.join(names[:10]+['...'])
879 879 out['subclasses'] = all_names
880 880 # and class docstring for instances:
881 881 else:
882 882 # reconstruct the function definition and print it:
883 883 defln = self._getdef(obj, oname)
884 884 if defln:
885 885 out['definition'] = defln
886 886
887 887 # First, check whether the instance docstring is identical to the
888 888 # class one, and print it separately if they don't coincide. In
889 889 # most cases they will, but it's nice to print all the info for
890 890 # objects which use instance-customized docstrings.
891 891 if ds:
892 892 try:
893 893 cls = getattr(obj,'__class__')
894 894 except:
895 895 class_ds = None
896 896 else:
897 897 class_ds = getdoc(cls)
898 898 # Skip Python's auto-generated docstrings
899 899 if class_ds in _builtin_type_docstrings:
900 900 class_ds = None
901 901 if class_ds and ds != class_ds:
902 902 out['class_docstring'] = class_ds
903 903
904 904 # Next, try to show constructor docstrings
905 905 try:
906 906 init_ds = getdoc(obj.__init__)
907 907 # Skip Python's auto-generated docstrings
908 908 if init_ds == _object_init_docstring:
909 909 init_ds = None
910 910 except AttributeError:
911 911 init_ds = None
912 912 if init_ds:
913 913 out['init_docstring'] = init_ds
914 914
915 915 # Call form docstring for callable instances
916 916 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
917 917 call_def = self._getdef(obj.__call__, oname)
918 918 if call_def and (call_def != out.get('definition')):
919 919 # it may never be the case that call def and definition differ,
920 920 # but don't include the same signature twice
921 921 out['call_def'] = call_def
922 922 call_ds = getdoc(obj.__call__)
923 923 # Skip Python's auto-generated docstrings
924 924 if call_ds == _func_call_docstring:
925 925 call_ds = None
926 926 if call_ds:
927 927 out['call_docstring'] = call_ds
928 928
929 929 return object_info(**out)
930 930
931 931 @staticmethod
932 932 def _source_contains_docstring(src, doc):
933 933 """
934 934 Check whether the source *src* contains the docstring *doc*.
935 935
936 936 This is is helper function to skip displaying the docstring if the
937 937 source already contains it, avoiding repetition of information.
938 938 """
939 939 try:
940 940 def_node, = ast.parse(dedent(src)).body
941 941 return ast.get_docstring(def_node) == doc
942 942 except Exception:
943 943 # The source can become invalid or even non-existent (because it
944 944 # is re-fetched from the source file) so the above code fail in
945 945 # arbitrary ways.
946 946 return False
947 947
948 948 def psearch(self,pattern,ns_table,ns_search=[],
949 949 ignore_case=False,show_all=False, *, list_types=False):
950 950 """Search namespaces with wildcards for objects.
951 951
952 952 Arguments:
953 953
954 954 - pattern: string containing shell-like wildcards to use in namespace
955 955 searches and optionally a type specification to narrow the search to
956 956 objects of that type.
957 957
958 958 - ns_table: dict of name->namespaces for search.
959 959
960 960 Optional arguments:
961 961
962 962 - ns_search: list of namespace names to include in search.
963 963
964 964 - ignore_case(False): make the search case-insensitive.
965 965
966 966 - show_all(False): show all names, including those starting with
967 967 underscores.
968 968
969 969 - list_types(False): list all available object types for object matching.
970 970 """
971 971 #print 'ps pattern:<%r>' % pattern # dbg
972 972
973 973 # defaults
974 974 type_pattern = 'all'
975 975 filter = ''
976 976
977 977 # list all object types
978 978 if list_types:
979 979 page.page('\n'.join(sorted(typestr2type)))
980 980 return
981 981
982 982 cmds = pattern.split()
983 983 len_cmds = len(cmds)
984 984 if len_cmds == 1:
985 985 # Only filter pattern given
986 986 filter = cmds[0]
987 987 elif len_cmds == 2:
988 988 # Both filter and type specified
989 989 filter,type_pattern = cmds
990 990 else:
991 991 raise ValueError('invalid argument string for psearch: <%s>' %
992 992 pattern)
993 993
994 994 # filter search namespaces
995 995 for name in ns_search:
996 996 if name not in ns_table:
997 997 raise ValueError('invalid namespace <%s>. Valid names: %s' %
998 998 (name,ns_table.keys()))
999 999
1000 1000 #print 'type_pattern:',type_pattern # dbg
1001 1001 search_result, namespaces_seen = set(), set()
1002 1002 for ns_name in ns_search:
1003 1003 ns = ns_table[ns_name]
1004 1004 # Normally, locals and globals are the same, so we just check one.
1005 1005 if id(ns) in namespaces_seen:
1006 1006 continue
1007 1007 namespaces_seen.add(id(ns))
1008 1008 tmp_res = list_namespace(ns, type_pattern, filter,
1009 1009 ignore_case=ignore_case, show_all=show_all)
1010 1010 search_result.update(tmp_res)
1011 1011
1012 1012 page.page('\n'.join(sorted(search_result)))
1013 1013
1014 1014
1015 1015 def _render_signature(obj_signature, obj_name) -> str:
1016 1016 """
1017 1017 This was mostly taken from inspect.Signature.__str__.
1018 1018 Look there for the comments.
1019 1019 The only change is to add linebreaks when this gets too long.
1020 1020 """
1021 1021 result = []
1022 1022 pos_only = False
1023 1023 kw_only = True
1024 1024 for param in obj_signature.parameters.values():
1025 1025 if param.kind == inspect._POSITIONAL_ONLY:
1026 1026 pos_only = True
1027 1027 elif pos_only:
1028 1028 result.append('/')
1029 1029 pos_only = False
1030 1030
1031 1031 if param.kind == inspect._VAR_POSITIONAL:
1032 1032 kw_only = False
1033 1033 elif param.kind == inspect._KEYWORD_ONLY and kw_only:
1034 1034 result.append('*')
1035 1035 kw_only = False
1036 1036
1037 1037 result.append(str(param))
1038 1038
1039 1039 if pos_only:
1040 1040 result.append('/')
1041 1041
1042 1042 # add up name, parameters, braces (2), and commas
1043 1043 if len(obj_name) + sum(len(r) + 2 for r in result) > 75:
1044 1044 # This doesn’t fit behind “Signature: ” in an inspect window.
1045 1045 rendered = '{}(\n{})'.format(obj_name, ''.join(
1046 1046 ' {},\n'.format(r) for r in result)
1047 1047 )
1048 1048 else:
1049 1049 rendered = '{}({})'.format(obj_name, ', '.join(result))
1050 1050
1051 1051 if obj_signature.return_annotation is not inspect._empty:
1052 1052 anno = inspect.formatannotation(obj_signature.return_annotation)
1053 1053 rendered += ' -> {}'.format(anno)
1054 1054
1055 1055 return rendered
General Comments 0
You need to be logged in to leave comments. Login now