Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/IPython/core/oinspect.py: 19%
496 statements
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-26 06:07 +0000
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-26 06:07 +0000
1# -*- coding: utf-8 -*-
2"""Tools for inspecting Python objects.
4Uses syntax highlighting for presenting the various information elements.
6Similar in spirit to the inspect module, but all calls take a name argument to
7reference the name under which an object is being read.
8"""
10# Copyright (c) IPython Development Team.
11# Distributed under the terms of the Modified BSD License.
13__all__ = ['Inspector','InspectColors']
15# stdlib modules
16import ast
17import inspect
18from inspect import signature
19import html
20import linecache
21import warnings
22import os
23from textwrap import dedent
24import types
25import io as stdlib_io
27from typing import Union
29# IPython's own
30from IPython.core import page
31from IPython.lib.pretty import pretty
32from IPython.testing.skipdoctest import skip_doctest
33from IPython.utils import PyColorize
34from IPython.utils import openpy
35from IPython.utils.dir2 import safe_hasattr
36from IPython.utils.path import compress_user
37from IPython.utils.text import indent
38from IPython.utils.wildcard import list_namespace
39from IPython.utils.wildcard import typestr2type
40from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable
41from IPython.utils.py3compat import cast_unicode
42from IPython.utils.colorable import Colorable
43from IPython.utils.decorators import undoc
45from pygments import highlight
46from pygments.lexers import PythonLexer
47from pygments.formatters import HtmlFormatter
49def pylight(code):
50 return highlight(code, PythonLexer(), HtmlFormatter(noclasses=True))
52# builtin docstrings to ignore
53_func_call_docstring = types.FunctionType.__call__.__doc__
54_object_init_docstring = object.__init__.__doc__
55_builtin_type_docstrings = {
56 inspect.getdoc(t) for t in (types.ModuleType, types.MethodType,
57 types.FunctionType, property)
58}
60_builtin_func_type = type(all)
61_builtin_meth_type = type(str.upper) # Bound methods have the same type as builtin functions
62#****************************************************************************
63# Builtin color schemes
65Colors = TermColors # just a shorthand
67InspectColors = PyColorize.ANSICodeColors
69#****************************************************************************
70# Auxiliary functions and objects
72# See the messaging spec for the definition of all these fields. This list
73# effectively defines the order of display
74info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
75 'length', 'file', 'definition', 'docstring', 'source',
76 'init_definition', 'class_docstring', 'init_docstring',
77 'call_def', 'call_docstring',
78 # These won't be printed but will be used to determine how to
79 # format the object
80 'ismagic', 'isalias', 'isclass', 'found', 'name'
81 ]
84def object_info(**kw):
85 """Make an object info dict with all fields present."""
86 infodict = {k:None for k in info_fields}
87 infodict.update(kw)
88 return infodict
91def get_encoding(obj):
92 """Get encoding for python source file defining obj
94 Returns None if obj is not defined in a sourcefile.
95 """
96 ofile = find_file(obj)
97 # run contents of file through pager starting at line where the object
98 # is defined, as long as the file isn't binary and is actually on the
99 # filesystem.
100 if ofile is None:
101 return None
102 elif ofile.endswith(('.so', '.dll', '.pyd')):
103 return None
104 elif not os.path.isfile(ofile):
105 return None
106 else:
107 # Print only text files, not extension binaries. Note that
108 # getsourcelines returns lineno with 1-offset and page() uses
109 # 0-offset, so we must adjust.
110 with stdlib_io.open(ofile, 'rb') as buffer: # Tweaked to use io.open for Python 2
111 encoding, lines = openpy.detect_encoding(buffer.readline)
112 return encoding
114def getdoc(obj) -> Union[str,None]:
115 """Stable wrapper around inspect.getdoc.
117 This can't crash because of attribute problems.
119 It also attempts to call a getdoc() method on the given object. This
120 allows objects which provide their docstrings via non-standard mechanisms
121 (like Pyro proxies) to still be inspected by ipython's ? system.
122 """
123 # Allow objects to offer customized documentation via a getdoc method:
124 try:
125 ds = obj.getdoc()
126 except Exception:
127 pass
128 else:
129 if isinstance(ds, str):
130 return inspect.cleandoc(ds)
131 docstr = inspect.getdoc(obj)
132 return docstr
135def getsource(obj, oname='') -> Union[str,None]:
136 """Wrapper around inspect.getsource.
138 This can be modified by other projects to provide customized source
139 extraction.
141 Parameters
142 ----------
143 obj : object
144 an object whose source code we will attempt to extract
145 oname : str
146 (optional) a name under which the object is known
148 Returns
149 -------
150 src : unicode or None
152 """
154 if isinstance(obj, property):
155 sources = []
156 for attrname in ['fget', 'fset', 'fdel']:
157 fn = getattr(obj, attrname)
158 if fn is not None:
159 encoding = get_encoding(fn)
160 oname_prefix = ('%s.' % oname) if oname else ''
161 sources.append(''.join(('# ', oname_prefix, attrname)))
162 if inspect.isfunction(fn):
163 sources.append(dedent(getsource(fn)))
164 else:
165 # Default str/repr only prints function name,
166 # pretty.pretty prints module name too.
167 sources.append(
168 '%s%s = %s\n' % (oname_prefix, attrname, pretty(fn))
169 )
170 if sources:
171 return '\n'.join(sources)
172 else:
173 return None
175 else:
176 # Get source for non-property objects.
178 obj = _get_wrapped(obj)
180 try:
181 src = inspect.getsource(obj)
182 except TypeError:
183 # The object itself provided no meaningful source, try looking for
184 # its class definition instead.
185 try:
186 src = inspect.getsource(obj.__class__)
187 except (OSError, TypeError):
188 return None
189 except OSError:
190 return None
192 return src
195def is_simple_callable(obj):
196 """True if obj is a function ()"""
197 return (inspect.isfunction(obj) or inspect.ismethod(obj) or \
198 isinstance(obj, _builtin_func_type) or isinstance(obj, _builtin_meth_type))
200@undoc
201def getargspec(obj):
202 """Wrapper around :func:`inspect.getfullargspec`
204 In addition to functions and methods, this can also handle objects with a
205 ``__call__`` attribute.
207 DEPRECATED: Deprecated since 7.10. Do not use, will be removed.
208 """
210 warnings.warn('`getargspec` function is deprecated as of IPython 7.10'
211 'and will be removed in future versions.', DeprecationWarning, stacklevel=2)
213 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
214 obj = obj.__call__
216 return inspect.getfullargspec(obj)
218@undoc
219def format_argspec(argspec):
220 """Format argspect, convenience wrapper around inspect's.
222 This takes a dict instead of ordered arguments and calls
223 inspect.format_argspec with the arguments in the necessary order.
225 DEPRECATED (since 7.10): Do not use; will be removed in future versions.
226 """
228 warnings.warn('`format_argspec` function is deprecated as of IPython 7.10'
229 'and will be removed in future versions.', DeprecationWarning, stacklevel=2)
232 return inspect.formatargspec(argspec['args'], argspec['varargs'],
233 argspec['varkw'], argspec['defaults'])
235@undoc
236def call_tip(oinfo, format_call=True):
237 """DEPRECATED since 6.0. Extract call tip data from an oinfo dict."""
238 warnings.warn(
239 "`call_tip` function is deprecated as of IPython 6.0"
240 "and will be removed in future versions.",
241 DeprecationWarning,
242 stacklevel=2,
243 )
244 # Get call definition
245 argspec = oinfo.get('argspec')
246 if argspec is None:
247 call_line = None
248 else:
249 # Callable objects will have 'self' as their first argument, prune
250 # it out if it's there for clarity (since users do *not* pass an
251 # extra first argument explicitly).
252 try:
253 has_self = argspec['args'][0] == 'self'
254 except (KeyError, IndexError):
255 pass
256 else:
257 if has_self:
258 argspec['args'] = argspec['args'][1:]
260 call_line = oinfo['name']+format_argspec(argspec)
262 # Now get docstring.
263 # The priority is: call docstring, constructor docstring, main one.
264 doc = oinfo.get('call_docstring')
265 if doc is None:
266 doc = oinfo.get('init_docstring')
267 if doc is None:
268 doc = oinfo.get('docstring','')
270 return call_line, doc
273def _get_wrapped(obj):
274 """Get the original object if wrapped in one or more @decorators
276 Some objects automatically construct similar objects on any unrecognised
277 attribute access (e.g. unittest.mock.call). To protect against infinite loops,
278 this will arbitrarily cut off after 100 levels of obj.__wrapped__
279 attribute access. --TK, Jan 2016
280 """
281 orig_obj = obj
282 i = 0
283 while safe_hasattr(obj, '__wrapped__'):
284 obj = obj.__wrapped__
285 i += 1
286 if i > 100:
287 # __wrapped__ is probably a lie, so return the thing we started with
288 return orig_obj
289 return obj
291def find_file(obj) -> str:
292 """Find the absolute path to the file where an object was defined.
294 This is essentially a robust wrapper around `inspect.getabsfile`.
296 Returns None if no file can be found.
298 Parameters
299 ----------
300 obj : any Python object
302 Returns
303 -------
304 fname : str
305 The absolute path to the file where the object was defined.
306 """
307 obj = _get_wrapped(obj)
309 fname = None
310 try:
311 fname = inspect.getabsfile(obj)
312 except TypeError:
313 # For an instance, the file that matters is where its class was
314 # declared.
315 try:
316 fname = inspect.getabsfile(obj.__class__)
317 except (OSError, TypeError):
318 # Can happen for builtins
319 pass
320 except OSError:
321 pass
323 return cast_unicode(fname)
326def find_source_lines(obj):
327 """Find the line number in a file where an object was defined.
329 This is essentially a robust wrapper around `inspect.getsourcelines`.
331 Returns None if no file can be found.
333 Parameters
334 ----------
335 obj : any Python object
337 Returns
338 -------
339 lineno : int
340 The line number where the object definition starts.
341 """
342 obj = _get_wrapped(obj)
344 try:
345 lineno = inspect.getsourcelines(obj)[1]
346 except TypeError:
347 # For instances, try the class object like getsource() does
348 try:
349 lineno = inspect.getsourcelines(obj.__class__)[1]
350 except (OSError, TypeError):
351 return None
352 except OSError:
353 return None
355 return lineno
357class Inspector(Colorable):
359 def __init__(self, color_table=InspectColors,
360 code_color_table=PyColorize.ANSICodeColors,
361 scheme=None,
362 str_detail_level=0,
363 parent=None, config=None):
364 super(Inspector, self).__init__(parent=parent, config=config)
365 self.color_table = color_table
366 self.parser = PyColorize.Parser(out='str', parent=self, style=scheme)
367 self.format = self.parser.format
368 self.str_detail_level = str_detail_level
369 self.set_active_scheme(scheme)
371 def _getdef(self,obj,oname='') -> Union[str,None]:
372 """Return the call signature for any callable object.
374 If any exception is generated, None is returned instead and the
375 exception is suppressed."""
376 try:
377 return _render_signature(signature(obj), oname)
378 except:
379 return None
381 def __head(self,h) -> str:
382 """Return a header string with proper colors."""
383 return '%s%s%s' % (self.color_table.active_colors.header,h,
384 self.color_table.active_colors.normal)
386 def set_active_scheme(self, scheme):
387 if scheme is not None:
388 self.color_table.set_active_scheme(scheme)
389 self.parser.color_table.set_active_scheme(scheme)
391 def noinfo(self, msg, oname):
392 """Generic message when no information is found."""
393 print('No %s found' % msg, end=' ')
394 if oname:
395 print('for %s' % oname)
396 else:
397 print()
399 def pdef(self, obj, oname=''):
400 """Print the call signature for any callable object.
402 If the object is a class, print the constructor information."""
404 if not callable(obj):
405 print('Object is not callable.')
406 return
408 header = ''
410 if inspect.isclass(obj):
411 header = self.__head('Class constructor information:\n')
414 output = self._getdef(obj,oname)
415 if output is None:
416 self.noinfo('definition header',oname)
417 else:
418 print(header,self.format(output), end=' ')
420 # In Python 3, all classes are new-style, so they all have __init__.
421 @skip_doctest
422 def pdoc(self, obj, oname='', formatter=None):
423 """Print the docstring for any object.
425 Optional:
426 -formatter: a function to run the docstring through for specially
427 formatted docstrings.
429 Examples
430 --------
431 In [1]: class NoInit:
432 ...: pass
434 In [2]: class NoDoc:
435 ...: def __init__(self):
436 ...: pass
438 In [3]: %pdoc NoDoc
439 No documentation found for NoDoc
441 In [4]: %pdoc NoInit
442 No documentation found for NoInit
444 In [5]: obj = NoInit()
446 In [6]: %pdoc obj
447 No documentation found for obj
449 In [5]: obj2 = NoDoc()
451 In [6]: %pdoc obj2
452 No documentation found for obj2
453 """
455 head = self.__head # For convenience
456 lines = []
457 ds = getdoc(obj)
458 if formatter:
459 ds = formatter(ds).get('plain/text', ds)
460 if ds:
461 lines.append(head("Class docstring:"))
462 lines.append(indent(ds))
463 if inspect.isclass(obj) and hasattr(obj, '__init__'):
464 init_ds = getdoc(obj.__init__)
465 if init_ds is not None:
466 lines.append(head("Init docstring:"))
467 lines.append(indent(init_ds))
468 elif hasattr(obj,'__call__'):
469 call_ds = getdoc(obj.__call__)
470 if call_ds:
471 lines.append(head("Call docstring:"))
472 lines.append(indent(call_ds))
474 if not lines:
475 self.noinfo('documentation',oname)
476 else:
477 page.page('\n'.join(lines))
479 def psource(self, obj, oname=''):
480 """Print the source code for an object."""
482 # Flush the source cache because inspect can return out-of-date source
483 linecache.checkcache()
484 try:
485 src = getsource(obj, oname=oname)
486 except Exception:
487 src = None
489 if src is None:
490 self.noinfo('source', oname)
491 else:
492 page.page(self.format(src))
494 def pfile(self, obj, oname=''):
495 """Show the whole file where an object was defined."""
497 lineno = find_source_lines(obj)
498 if lineno is None:
499 self.noinfo('file', oname)
500 return
502 ofile = find_file(obj)
503 # run contents of file through pager starting at line where the object
504 # is defined, as long as the file isn't binary and is actually on the
505 # filesystem.
506 if ofile.endswith(('.so', '.dll', '.pyd')):
507 print('File %r is binary, not printing.' % ofile)
508 elif not os.path.isfile(ofile):
509 print('File %r does not exist, not printing.' % ofile)
510 else:
511 # Print only text files, not extension binaries. Note that
512 # getsourcelines returns lineno with 1-offset and page() uses
513 # 0-offset, so we must adjust.
514 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
517 def _mime_format(self, text:str, formatter=None) -> dict:
518 """Return a mime bundle representation of the input text.
520 - if `formatter` is None, the returned mime bundle has
521 a ``text/plain`` field, with the input text.
522 a ``text/html`` field with a ``<pre>`` tag containing the input text.
524 - if ``formatter`` is not None, it must be a callable transforming the
525 input text into a mime bundle. Default values for ``text/plain`` and
526 ``text/html`` representations are the ones described above.
528 Note:
530 Formatters returning strings are supported but this behavior is deprecated.
532 """
533 defaults = {
534 "text/plain": text,
535 "text/html": f"<pre>{html.escape(text)}</pre>",
536 }
538 if formatter is None:
539 return defaults
540 else:
541 formatted = formatter(text)
543 if not isinstance(formatted, dict):
544 # Handle the deprecated behavior of a formatter returning
545 # a string instead of a mime bundle.
546 return {"text/plain": formatted, "text/html": f"<pre>{formatted}</pre>"}
548 else:
549 return dict(defaults, **formatted)
552 def format_mime(self, bundle):
553 """Format a mimebundle being created by _make_info_unformatted into a real mimebundle"""
554 # Format text/plain mimetype
555 if isinstance(bundle["text/plain"], (list, tuple)):
556 # bundle['text/plain'] is a list of (head, formatted body) pairs
557 lines = []
558 _len = max(len(h) for h, _ in bundle["text/plain"])
560 for head, body in bundle["text/plain"]:
561 body = body.strip("\n")
562 delim = "\n" if "\n" in body else " "
563 lines.append(
564 f"{self.__head(head+':')}{(_len - len(head))*' '}{delim}{body}"
565 )
567 bundle["text/plain"] = "\n".join(lines)
569 # Format the text/html mimetype
570 if isinstance(bundle["text/html"], (list, tuple)):
571 # bundle['text/html'] is a list of (head, formatted body) pairs
572 bundle["text/html"] = "\n".join(
573 (f"<h1>{head}</h1>\n{body}" for (head, body) in bundle["text/html"])
574 )
575 return bundle
577 def _append_info_field(
578 self, bundle, title: str, key: str, info, omit_sections, formatter
579 ):
580 """Append an info value to the unformatted mimebundle being constructed by _make_info_unformatted"""
581 if title in omit_sections or key in omit_sections:
582 return
583 field = info[key]
584 if field is not None:
585 formatted_field = self._mime_format(field, formatter)
586 bundle["text/plain"].append((title, formatted_field["text/plain"]))
587 bundle["text/html"].append((title, formatted_field["text/html"]))
589 def _make_info_unformatted(self, obj, info, formatter, detail_level, omit_sections):
590 """Assemble the mimebundle as unformatted lists of information"""
591 bundle = {
592 "text/plain": [],
593 "text/html": [],
594 }
596 # A convenience function to simplify calls below
597 def append_field(bundle, title: str, key: str, formatter=None):
598 self._append_info_field(
599 bundle,
600 title=title,
601 key=key,
602 info=info,
603 omit_sections=omit_sections,
604 formatter=formatter,
605 )
607 def code_formatter(text):
608 return {
609 'text/plain': self.format(text),
610 'text/html': pylight(text)
611 }
613 if info["isalias"]:
614 append_field(bundle, "Repr", "string_form")
616 elif info['ismagic']:
617 if detail_level > 0:
618 append_field(bundle, "Source", "source", code_formatter)
619 else:
620 append_field(bundle, "Docstring", "docstring", formatter)
621 append_field(bundle, "File", "file")
623 elif info['isclass'] or is_simple_callable(obj):
624 # Functions, methods, classes
625 append_field(bundle, "Signature", "definition", code_formatter)
626 append_field(bundle, "Init signature", "init_definition", code_formatter)
627 append_field(bundle, "Docstring", "docstring", formatter)
628 if detail_level > 0 and info["source"]:
629 append_field(bundle, "Source", "source", code_formatter)
630 else:
631 append_field(bundle, "Init docstring", "init_docstring", formatter)
633 append_field(bundle, "File", "file")
634 append_field(bundle, "Type", "type_name")
635 append_field(bundle, "Subclasses", "subclasses")
637 else:
638 # General Python objects
639 append_field(bundle, "Signature", "definition", code_formatter)
640 append_field(bundle, "Call signature", "call_def", code_formatter)
641 append_field(bundle, "Type", "type_name")
642 append_field(bundle, "String form", "string_form")
644 # Namespace
645 if info["namespace"] != "Interactive":
646 append_field(bundle, "Namespace", "namespace")
648 append_field(bundle, "Length", "length")
649 append_field(bundle, "File", "file")
651 # Source or docstring, depending on detail level and whether
652 # source found.
653 if detail_level > 0 and info["source"]:
654 append_field(bundle, "Source", "source", code_formatter)
655 else:
656 append_field(bundle, "Docstring", "docstring", formatter)
658 append_field(bundle, "Class docstring", "class_docstring", formatter)
659 append_field(bundle, "Init docstring", "init_docstring", formatter)
660 append_field(bundle, "Call docstring", "call_docstring", formatter)
661 return bundle
664 def _get_info(
665 self, obj, oname="", formatter=None, info=None, detail_level=0, omit_sections=()
666 ):
667 """Retrieve an info dict and format it.
669 Parameters
670 ----------
671 obj : any
672 Object to inspect and return info from
673 oname : str (default: ''):
674 Name of the variable pointing to `obj`.
675 formatter : callable
676 info
677 already computed information
678 detail_level : integer
679 Granularity of detail level, if set to 1, give more information.
680 omit_sections : container[str]
681 Titles or keys to omit from output (can be set, tuple, etc., anything supporting `in`)
682 """
684 info = self.info(obj, oname=oname, info=info, detail_level=detail_level)
685 bundle = self._make_info_unformatted(
686 obj, info, formatter, detail_level=detail_level, omit_sections=omit_sections
687 )
688 return self.format_mime(bundle)
690 def pinfo(
691 self,
692 obj,
693 oname="",
694 formatter=None,
695 info=None,
696 detail_level=0,
697 enable_html_pager=True,
698 omit_sections=(),
699 ):
700 """Show detailed information about an object.
702 Optional arguments:
704 - oname: name of the variable pointing to the object.
706 - formatter: callable (optional)
707 A special formatter for docstrings.
709 The formatter is a callable that takes a string as an input
710 and returns either a formatted string or a mime type bundle
711 in the form of a dictionary.
713 Although the support of custom formatter returning a string
714 instead of a mime type bundle is deprecated.
716 - info: a structure with some information fields which may have been
717 precomputed already.
719 - detail_level: if set to 1, more information is given.
721 - omit_sections: set of section keys and titles to omit
722 """
723 info = self._get_info(
724 obj, oname, formatter, info, detail_level, omit_sections=omit_sections
725 )
726 if not enable_html_pager:
727 del info['text/html']
728 page.page(info)
730 def _info(self, obj, oname="", info=None, detail_level=0):
731 """
732 Inspector.info() was likely improperly marked as deprecated
733 while only a parameter was deprecated. We "un-deprecate" it.
734 """
736 warnings.warn(
737 "The `Inspector.info()` method has been un-deprecated as of 8.0 "
738 "and the `formatter=` keyword removed. `Inspector._info` is now "
739 "an alias, and you can just call `.info()` directly.",
740 DeprecationWarning,
741 stacklevel=2,
742 )
743 return self.info(obj, oname=oname, info=info, detail_level=detail_level)
745 def info(self, obj, oname="", info=None, detail_level=0) -> dict:
746 """Compute a dict with detailed information about an object.
748 Parameters
749 ----------
750 obj : any
751 An object to find information about
752 oname : str (default: '')
753 Name of the variable pointing to `obj`.
754 info : (default: None)
755 A struct (dict like with attr access) with some information fields
756 which may have been precomputed already.
757 detail_level : int (default:0)
758 If set to 1, more information is given.
760 Returns
761 -------
762 An object info dict with known fields from `info_fields`. Keys are
763 strings, values are string or None.
764 """
766 if info is None:
767 ismagic = False
768 isalias = False
769 ospace = ''
770 else:
771 ismagic = info.ismagic
772 isalias = info.isalias
773 ospace = info.namespace
775 # Get docstring, special-casing aliases:
776 if isalias:
777 if not callable(obj):
778 try:
779 ds = "Alias to the system command:\n %s" % obj[1]
780 except:
781 ds = "Alias: " + str(obj)
782 else:
783 ds = "Alias to " + str(obj)
784 if obj.__doc__:
785 ds += "\nDocstring:\n" + obj.__doc__
786 else:
787 ds = getdoc(obj)
788 if ds is None:
789 ds = '<no docstring>'
791 # store output in a dict, we initialize it here and fill it as we go
792 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic, subclasses=None)
794 string_max = 200 # max size of strings to show (snipped if longer)
795 shalf = int((string_max - 5) / 2)
797 if ismagic:
798 out['type_name'] = 'Magic function'
799 elif isalias:
800 out['type_name'] = 'System alias'
801 else:
802 out['type_name'] = type(obj).__name__
804 try:
805 bclass = obj.__class__
806 out['base_class'] = str(bclass)
807 except:
808 pass
810 # String form, but snip if too long in ? form (full in ??)
811 if detail_level >= self.str_detail_level:
812 try:
813 ostr = str(obj)
814 str_head = 'string_form'
815 if not detail_level and len(ostr)>string_max:
816 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
817 ostr = ("\n" + " " * len(str_head.expandtabs())).\
818 join(q.strip() for q in ostr.split("\n"))
819 out[str_head] = ostr
820 except:
821 pass
823 if ospace:
824 out['namespace'] = ospace
826 # Length (for strings and lists)
827 try:
828 out['length'] = str(len(obj))
829 except Exception:
830 pass
832 # Filename where object was defined
833 binary_file = False
834 fname = find_file(obj)
835 if fname is None:
836 # if anything goes wrong, we don't want to show source, so it's as
837 # if the file was binary
838 binary_file = True
839 else:
840 if fname.endswith(('.so', '.dll', '.pyd')):
841 binary_file = True
842 elif fname.endswith('<string>'):
843 fname = 'Dynamically generated function. No source code available.'
844 out['file'] = compress_user(fname)
846 # Original source code for a callable, class or property.
847 if detail_level:
848 # Flush the source cache because inspect can return out-of-date
849 # source
850 linecache.checkcache()
851 try:
852 if isinstance(obj, property) or not binary_file:
853 src = getsource(obj, oname)
854 if src is not None:
855 src = src.rstrip()
856 out['source'] = src
858 except Exception:
859 pass
861 # Add docstring only if no source is to be shown (avoid repetitions).
862 if ds and not self._source_contains_docstring(out.get('source'), ds):
863 out['docstring'] = ds
865 # Constructor docstring for classes
866 if inspect.isclass(obj):
867 out['isclass'] = True
869 # get the init signature:
870 try:
871 init_def = self._getdef(obj, oname)
872 except AttributeError:
873 init_def = None
875 # get the __init__ docstring
876 try:
877 obj_init = obj.__init__
878 except AttributeError:
879 init_ds = None
880 else:
881 if init_def is None:
882 # Get signature from init if top-level sig failed.
883 # Can happen for built-in types (list, etc.).
884 try:
885 init_def = self._getdef(obj_init, oname)
886 except AttributeError:
887 pass
888 init_ds = getdoc(obj_init)
889 # Skip Python's auto-generated docstrings
890 if init_ds == _object_init_docstring:
891 init_ds = None
893 if init_def:
894 out['init_definition'] = init_def
896 if init_ds:
897 out['init_docstring'] = init_ds
899 names = [sub.__name__ for sub in type.__subclasses__(obj)]
900 if len(names) < 10:
901 all_names = ', '.join(names)
902 else:
903 all_names = ', '.join(names[:10]+['...'])
904 out['subclasses'] = all_names
905 # and class docstring for instances:
906 else:
907 # reconstruct the function definition and print it:
908 defln = self._getdef(obj, oname)
909 if defln:
910 out['definition'] = defln
912 # First, check whether the instance docstring is identical to the
913 # class one, and print it separately if they don't coincide. In
914 # most cases they will, but it's nice to print all the info for
915 # objects which use instance-customized docstrings.
916 if ds:
917 try:
918 cls = getattr(obj,'__class__')
919 except:
920 class_ds = None
921 else:
922 class_ds = getdoc(cls)
923 # Skip Python's auto-generated docstrings
924 if class_ds in _builtin_type_docstrings:
925 class_ds = None
926 if class_ds and ds != class_ds:
927 out['class_docstring'] = class_ds
929 # Next, try to show constructor docstrings
930 try:
931 init_ds = getdoc(obj.__init__)
932 # Skip Python's auto-generated docstrings
933 if init_ds == _object_init_docstring:
934 init_ds = None
935 except AttributeError:
936 init_ds = None
937 if init_ds:
938 out['init_docstring'] = init_ds
940 # Call form docstring for callable instances
941 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
942 call_def = self._getdef(obj.__call__, oname)
943 if call_def and (call_def != out.get('definition')):
944 # it may never be the case that call def and definition differ,
945 # but don't include the same signature twice
946 out['call_def'] = call_def
947 call_ds = getdoc(obj.__call__)
948 # Skip Python's auto-generated docstrings
949 if call_ds == _func_call_docstring:
950 call_ds = None
951 if call_ds:
952 out['call_docstring'] = call_ds
954 return object_info(**out)
956 @staticmethod
957 def _source_contains_docstring(src, doc):
958 """
959 Check whether the source *src* contains the docstring *doc*.
961 This is is helper function to skip displaying the docstring if the
962 source already contains it, avoiding repetition of information.
963 """
964 try:
965 def_node, = ast.parse(dedent(src)).body
966 return ast.get_docstring(def_node) == doc
967 except Exception:
968 # The source can become invalid or even non-existent (because it
969 # is re-fetched from the source file) so the above code fail in
970 # arbitrary ways.
971 return False
973 def psearch(self,pattern,ns_table,ns_search=[],
974 ignore_case=False,show_all=False, *, list_types=False):
975 """Search namespaces with wildcards for objects.
977 Arguments:
979 - pattern: string containing shell-like wildcards to use in namespace
980 searches and optionally a type specification to narrow the search to
981 objects of that type.
983 - ns_table: dict of name->namespaces for search.
985 Optional arguments:
987 - ns_search: list of namespace names to include in search.
989 - ignore_case(False): make the search case-insensitive.
991 - show_all(False): show all names, including those starting with
992 underscores.
994 - list_types(False): list all available object types for object matching.
995 """
996 #print 'ps pattern:<%r>' % pattern # dbg
998 # defaults
999 type_pattern = 'all'
1000 filter = ''
1002 # list all object types
1003 if list_types:
1004 page.page('\n'.join(sorted(typestr2type)))
1005 return
1007 cmds = pattern.split()
1008 len_cmds = len(cmds)
1009 if len_cmds == 1:
1010 # Only filter pattern given
1011 filter = cmds[0]
1012 elif len_cmds == 2:
1013 # Both filter and type specified
1014 filter,type_pattern = cmds
1015 else:
1016 raise ValueError('invalid argument string for psearch: <%s>' %
1017 pattern)
1019 # filter search namespaces
1020 for name in ns_search:
1021 if name not in ns_table:
1022 raise ValueError('invalid namespace <%s>. Valid names: %s' %
1023 (name,ns_table.keys()))
1025 #print 'type_pattern:',type_pattern # dbg
1026 search_result, namespaces_seen = set(), set()
1027 for ns_name in ns_search:
1028 ns = ns_table[ns_name]
1029 # Normally, locals and globals are the same, so we just check one.
1030 if id(ns) in namespaces_seen:
1031 continue
1032 namespaces_seen.add(id(ns))
1033 tmp_res = list_namespace(ns, type_pattern, filter,
1034 ignore_case=ignore_case, show_all=show_all)
1035 search_result.update(tmp_res)
1037 page.page('\n'.join(sorted(search_result)))
1040def _render_signature(obj_signature, obj_name) -> str:
1041 """
1042 This was mostly taken from inspect.Signature.__str__.
1043 Look there for the comments.
1044 The only change is to add linebreaks when this gets too long.
1045 """
1046 result = []
1047 pos_only = False
1048 kw_only = True
1049 for param in obj_signature.parameters.values():
1050 if param.kind == inspect._POSITIONAL_ONLY:
1051 pos_only = True
1052 elif pos_only:
1053 result.append('/')
1054 pos_only = False
1056 if param.kind == inspect._VAR_POSITIONAL:
1057 kw_only = False
1058 elif param.kind == inspect._KEYWORD_ONLY and kw_only:
1059 result.append('*')
1060 kw_only = False
1062 result.append(str(param))
1064 if pos_only:
1065 result.append('/')
1067 # add up name, parameters, braces (2), and commas
1068 if len(obj_name) + sum(len(r) + 2 for r in result) > 75:
1069 # This doesn’t fit behind “Signature: ” in an inspect window.
1070 rendered = '{}(\n{})'.format(obj_name, ''.join(
1071 ' {},\n'.format(r) for r in result)
1072 )
1073 else:
1074 rendered = '{}({})'.format(obj_name, ', '.join(result))
1076 if obj_signature.return_annotation is not inspect._empty:
1077 anno = inspect.formatannotation(obj_signature.return_annotation)
1078 rendered += ' -> {}'.format(anno)
1080 return rendered