def load_extension(self, module_str): """Load an IPython extension by its module name. Returns the string "already loaded" if the extension is already loaded, "no load function" if the module doesn't have a load_ipython_extension function, or None if it succeeded. """ if module_str in self.loaded: return "already loaded" from IPython.utils.syspathcontext import prepended_to_syspath with self.shell.builtin_trap: if module_str not in sys.modules: with prepended_to_syspath(self.ipython_extension_dir): mod = import_module(module_str) if mod.__file__.startswith(self.ipython_extension_dir): print(("Loading extensions from {dir} is deprecated. " "We recommend managing extensions like any " "other Python packages, in site-packages.").format( dir=compress_user(self.ipython_extension_dir))) mod = sys.modules[module_str] if self._call_load_ipython_extension(mod): self.loaded.add(module_str) else: return "no load function"
def load_extension(self, module_str): """Load an IPython extension by its module name. Returns the string "already loaded" if the extension is already loaded, "no load function" if the module doesn't have a load_ipython_extension function, or None if it succeeded. """ if module_str in self.loaded: return "already loaded" with self.shell.builtin_trap: if module_str not in sys.modules: try: sys.modules[module_str] = __import__('IPython.extensions.' + module_str) except ImportError: mod = import_module(module_str) if mod.__file__.startswith(self.ipython_extension_dir): print(("Loading extensions from {dir} is deprecated. " "We recommend managing extensions like any " "other Python packages, in site-packages.").format( dir=compress_user(self.ipython_extension_dir))) mod = sys.modules[module_str] if self._call_load_ipython_extension(mod): self.loaded.add(module_str) else: return "no load function"
def test_info(): "Check that Inspector.info fills out various fields as expected." i = inspector.info(Call, oname='Call') nt.assert_equal(i['type_name'], 'type') expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'> nt.assert_equal(i['base_class'], expted_class) nt.assert_regex(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'( at 0x[0-9a-f]{1,9})?>") fname = __file__ if fname.endswith(".pyc"): fname = fname[:-1] # case-insensitive comparison needed on some filesystems # e.g. Windows: nt.assert_equal(i['file'].lower(), compress_user(fname).lower()) nt.assert_equal(i['definition'], None) nt.assert_equal(i['docstring'], Call.__doc__) nt.assert_equal(i['source'], None) nt.assert_true(i['isclass']) nt.assert_equal(i['init_definition'], "Call(x, y=1)") nt.assert_equal(i['init_docstring'], Call.__init__.__doc__) i = inspector.info(Call, detail_level=1) nt.assert_not_equal(i['source'], None) nt.assert_equal(i['docstring'], None) c = Call(1) c.__doc__ = "Modified instance docstring" i = inspector.info(c) nt.assert_equal(i['type_name'], 'Call') nt.assert_equal(i['docstring'], "Modified instance docstring") nt.assert_equal(i['class_docstring'], Call.__doc__) nt.assert_equal(i['init_docstring'], Call.__init__.__doc__) nt.assert_equal(i['call_docstring'], Call.__call__.__doc__)
def _format_filename(file, ColorFilename, ColorNormal, *, lineno=None): """ Format filename lines with `In [n]` if it's the nth code cell or `File *.py` if it's a module. Parameters ---------- file : str ColorFilename ColorScheme's filename coloring to be used. ColorNormal ColorScheme's normal coloring to be used. """ ipinst = get_ipython() if ipinst is not None and file in ipinst.compile._filename_map: file = "[%s]" % ipinst.compile._filename_map[file] tpl_link = f"Input {ColorFilename}In {{file}}{ColorNormal}" else: file = util_path.compress_user( py3compat.cast_unicode(file, util_path.fs_encoding)) if lineno is None: tpl_link = f"File {ColorFilename}{{file}}{ColorNormal}" else: tpl_link = f"File {ColorFilename}{{file}}:{{lineno}}{ColorNormal}" return tpl_link.format(file=file, lineno=lineno)
def report(): """Return a string with a summary report of test-related variables.""" inf = get_sys_info() out = [] def _add(name, value): out.append((name, value)) _add('IPython version', inf['ipython_version']) _add('IPython commit', "{} ({})".format( inf['commit_hash'], inf['commit_source'])) _add('IPython package', compress_user(inf['ipython_path'])) _add('Python version', inf['sys_version'].replace('\n', '')) _add('sys.executable', compress_user(inf['sys_executable'])) _add('Platform', inf['platform']) width = max(len(n) for (n, v) in out) out = ["{:<{width}}: {}\n".format(n, v, width=width) for (n, v) in out] avail = [] not_avail = [] for k, is_avail in have.items(): if is_avail: avail.append(k) else: not_avail.append(k) if avail: out.append('\nTools and libraries available at test time:\n') avail.sort() out.append(' ' + ' '.join(avail) + '\n') if not_avail: out.append('\nTools and libraries NOT available at test time:\n') not_avail.sort() out.append(' ' + ' '.join(not_avail) + '\n') return ''.join(out)
def report(): """Return a string with a summary report of test-related variables.""" inf = get_sys_info() out = [] def _add(name, value): out.append((name, value)) _add('IPython version', inf['ipython_version']) _add('IPython commit', "{} ({})".format(inf['commit_hash'], inf['commit_source'])) _add('IPython package', compress_user(inf['ipython_path'])) _add('Python version', inf['sys_version'].replace('\n', '')) _add('sys.executable', compress_user(inf['sys_executable'])) _add('Platform', inf['platform']) width = max(len(n) for (n, v) in out) out = ["{:<{width}}: {}\n".format(n, v, width=width) for (n, v) in out] avail = [] not_avail = [] for k, is_avail in have.items(): if is_avail: avail.append(k) else: not_avail.append(k) if avail: out.append('\nTools and libraries available at test time:\n') avail.sort() out.append(' ' + ' '.join(avail) + '\n') if not_avail: out.append('\nTools and libraries NOT available at test time:\n') not_avail.sort() out.append(' ' + ' '.join(not_avail) + '\n') return ''.join(out)
def report(): """Return a string with a summary report of test-related variables.""" inf = get_sys_info() out = [] def _add(name, value): out.append((name, value)) _add("IPython version", inf["ipython_version"]) _add("IPython commit", "{} ({})".format(inf["commit_hash"], inf["commit_source"])) _add("IPython package", compress_user(inf["ipython_path"])) _add("Python version", inf["sys_version"].replace("\n", "")) _add("sys.executable", compress_user(inf["sys_executable"])) _add("Platform", inf["platform"]) width = max(len(n) for (n, v) in out) out = ["{:<{width}}: {}\n".format(n, v, width=width) for (n, v) in out] avail = [] not_avail = [] for k, is_avail in have.items(): if is_avail: avail.append(k) else: not_avail.append(k) if avail: out.append("\nTools and libraries available at test time:\n") avail.sort() out.append(" " + " ".join(avail) + "\n") if not_avail: out.append("\nTools and libraries NOT available at test time:\n") not_avail.sort() out.append(" " + " ".join(not_avail) + "\n") return "".join(out)
def test_info(): "Check that Inspector.info fills out various fields as expected." i = inspector.info(Call, oname='Call') nt.assert_equal(i['type_name'], 'type') expted_class = str( type(type)) # <class 'type'> (Python 3) or <type 'type'> nt.assert_equal(i['base_class'], expted_class) if sys.version_info > (3, ): nt.assert_regex( i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'( at 0x[0-9a-f]{1,9})?>" ) fname = __file__ if fname.endswith(".pyc"): fname = fname[:-1] # case-insensitive comparison needed on some filesystems # e.g. Windows: nt.assert_equal(i['file'].lower(), compress_user(fname).lower()) nt.assert_equal(i['definition'], None) nt.assert_equal(i['docstring'], Call.__doc__) nt.assert_equal(i['source'], None) nt.assert_true(i['isclass']) _self_py2 = '' if py3compat.PY3 else 'self, ' nt.assert_equal(i['init_definition'], "Call(%sx, y=1)\n" % _self_py2) nt.assert_equal(i['init_docstring'], Call.__init__.__doc__) i = inspector.info(Call, detail_level=1) nt.assert_not_equal(i['source'], None) nt.assert_equal(i['docstring'], None) c = Call(1) c.__doc__ = "Modified instance docstring" i = inspector.info(c) nt.assert_equal(i['type_name'], 'Call') nt.assert_equal(i['docstring'], "Modified instance docstring") nt.assert_equal(i['class_docstring'], Call.__doc__) nt.assert_equal(i['init_docstring'], Call.__init__.__doc__) nt.assert_equal(i['call_docstring'], Call.__call__.__doc__) # Test old-style classes, which for example may not have an __init__ method. if not py3compat.PY3: i = inspector.info(OldStyle) nt.assert_equal(i['type_name'], 'classobj') i = inspector.info(OldStyle()) nt.assert_equal(i['type_name'], 'instance') nt.assert_equal(i['docstring'], OldStyle.__doc__)
def test_info(): "Check that Inspector.info fills out various fields as expected." i = inspector.info(Call, oname='Call') nt.assert_equal(i['type_name'], 'type') expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'> nt.assert_equal(i['base_class'], expted_class) if sys.version_info > (3,): nt.assert_regex(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'( at 0x[0-9a-f]{1,9})?>") fname = __file__ if fname.endswith(".pyc"): fname = fname[:-1] # case-insensitive comparison needed on some filesystems # e.g. Windows: nt.assert_equal(i['file'].lower(), compress_user(fname).lower()) nt.assert_equal(i['definition'], None) nt.assert_equal(i['docstring'], Call.__doc__) nt.assert_equal(i['source'], None) nt.assert_true(i['isclass']) _self_py2 = '' if py3compat.PY3 else 'self, ' nt.assert_equal(i['init_definition'], "Call(%sx, y=1)" % _self_py2) nt.assert_equal(i['init_docstring'], Call.__init__.__doc__) i = inspector.info(Call, detail_level=1) nt.assert_not_equal(i['source'], None) nt.assert_equal(i['docstring'], None) c = Call(1) c.__doc__ = "Modified instance docstring" i = inspector.info(c) nt.assert_equal(i['type_name'], 'Call') nt.assert_equal(i['docstring'], "Modified instance docstring") nt.assert_equal(i['class_docstring'], Call.__doc__) nt.assert_equal(i['init_docstring'], Call.__init__.__doc__) nt.assert_equal(i['call_docstring'], Call.__call__.__doc__) # Test old-style classes, which for example may not have an __init__ method. if not py3compat.PY3: i = inspector.info(OldStyle) nt.assert_equal(i['type_name'], 'classobj') i = inspector.info(OldStyle()) nt.assert_equal(i['type_name'], 'instance') nt.assert_equal(i['docstring'], OldStyle.__doc__)
def test_info(): "Check that Inspector.info fills out various fields as expected." i = inspector.info(Call, oname="Call") nt.assert_equal(i["type_name"], "type") expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'> nt.assert_equal(i["base_class"], expted_class) nt.assert_equal(i["string_form"], "<class 'IPython.core.tests.test_oinspect.Call'>") fname = __file__ if fname.endswith(".pyc"): fname = fname[:-1] # case-insensitive comparison needed on some filesystems # e.g. Windows: nt.assert_equal(i["file"].lower(), compress_user(fname).lower()) nt.assert_equal(i["definition"], None) nt.assert_equal(i["docstring"], Call.__doc__) nt.assert_equal(i["source"], None) nt.assert_true(i["isclass"]) _self_py2 = "" if py3compat.PY3 else "self, " nt.assert_equal(i["init_definition"], "Call(%sx, y=1)\n" % _self_py2) nt.assert_equal(i["init_docstring"], Call.__init__.__doc__) i = inspector.info(Call, detail_level=1) nt.assert_not_equal(i["source"], None) nt.assert_equal(i["docstring"], None) c = Call(1) c.__doc__ = "Modified instance docstring" i = inspector.info(c) nt.assert_equal(i["type_name"], "Call") nt.assert_equal(i["docstring"], "Modified instance docstring") nt.assert_equal(i["class_docstring"], Call.__doc__) nt.assert_equal(i["init_docstring"], Call.__init__.__doc__) nt.assert_equal(i["call_docstring"], Call.__call__.__doc__) # Test old-style classes, which for example may not have an __init__ method. if not py3compat.PY3: i = inspector.info(OldStyle) nt.assert_equal(i["type_name"], "classobj") i = inspector.info(OldStyle()) nt.assert_equal(i["type_name"], "instance") nt.assert_equal(i["docstring"], OldStyle.__doc__)
def _load_extension(self, module_str: str): if module_str in self.loaded: return "already loaded" from IPython.utils.syspathcontext import prepended_to_syspath with self.shell.builtin_trap: if module_str not in sys.modules: with prepended_to_syspath(self.ipython_extension_dir): mod = import_module(module_str) if mod.__file__.startswith(self.ipython_extension_dir): print(( "Loading extensions from {dir} is deprecated. " "We recommend managing extensions like any " "other Python packages, in site-packages.").format( dir=compress_user(self.ipython_extension_dir))) mod = sys.modules[module_str] if self._call_load_ipython_extension(mod): self.loaded.add(module_str) else: return "no load function"
def _format_filename(file, ColorFilename, ColorNormal): """ Format filename lines with `In [n]` if it's the nth code cell or `File *.py` if it's a module. Parameters ---------- file : str ColorFilename ColorScheme's filename coloring to be used. ColorNormal ColorScheme's normal coloring to be used. """ ipinst = get_ipython() if ipinst is not None and file in ipinst.compile._filename_map: file = "[%s]" % ipinst.compile._filename_map[file] tpl_link = "In %s%%s%s" % (ColorFilename, ColorNormal) else: file = util_path.compress_user( py3compat.cast_unicode(file, util_path.fs_encoding)) tpl_link = "File %s%%s%s" % (ColorFilename, ColorNormal) return tpl_link % file
def test_info(): "Check that Inspector.info fills out various fields as expected." i = inspector.info(Call, oname="Call") assert i["type_name"] == "type" expted_class = str( type(type)) # <class 'type'> (Python 3) or <type 'type'> assert i["base_class"] == expted_class nt.assert_regex( i["string_form"], "<class 'IPython.core.tests.test_oinspect.Call'( at 0x[0-9a-f]{1,9})?>", ) fname = __file__ if fname.endswith(".pyc"): fname = fname[:-1] # case-insensitive comparison needed on some filesystems # e.g. Windows: assert i["file"].lower() == compress_user(fname).lower() assert i["definition"] == None assert i["docstring"] == Call.__doc__ assert i["source"] == None nt.assert_true(i["isclass"]) assert i["init_definition"] == "Call(x, y=1)" assert i["init_docstring"] == Call.__init__.__doc__ i = inspector.info(Call, detail_level=1) nt.assert_not_equal(i["source"], None) assert i["docstring"] == None c = Call(1) c.__doc__ = "Modified instance docstring" i = inspector.info(c) assert i["type_name"] == "Call" assert i["docstring"] == "Modified instance docstring" assert i["class_docstring"] == Call.__doc__ assert i["init_docstring"] == Call.__init__.__doc__ assert i["call_docstring"] == Call.__call__.__doc__
def format_record(self, frame_info): """Format a single stack frame""" Colors = self.Colors # just a shorthand + quicker name lookup ColorsNormal = Colors.Normal # used a lot if isinstance(frame_info, stack_data.RepeatedFrames): return ' %s[... skipping similar frames: %s]%s\n' % ( Colors.excName, frame_info.description, ColorsNormal) indent = ' ' * INDENT_SIZE em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal) tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal) tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal) tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \ (Colors.vName, Colors.valEm, ColorsNormal) tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal) tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal) file = frame_info.filename file = py3compat.cast_unicode(file, util_path.fs_encoding) link = tpl_link % util_path.compress_user(file) args, varargs, varkw, locals_ = inspect.getargvalues(frame_info.frame) func = frame_info.executing.code_qualname() if func == '<module>': call = tpl_call % (func, '') else: # Decide whether to include variable details or not var_repr = eqrepr if self.include_vars else nullrepr try: call = tpl_call % (func, inspect.formatargvalues(args, varargs, varkw, locals_, formatvalue=var_repr)) except KeyError: # This happens in situations like errors inside generator # expressions, where local variables are listed in the # line, but can't be extracted from the frame. I'm not # 100% sure this isn't actually a bug in inspect itself, # but since there's no info for us to compute with, the # best we can do is report the failure and move on. Here # we must *not* call any traceback construction again, # because that would mess up use of %debug later on. So we # simply report the failure and move on. The only # limitation will be that this frame won't have locals # listed in the call signature. Quite subtle problem... # I can't think of a good way to validate this in a unit # test, but running a script consisting of: # dict( (k,v.strip()) for (k,v) in range(10) ) # will illustrate the error, if this exception catch is # disabled. call = tpl_call_fail % func lvals = '' lvals_list = [] if self.include_vars: for var in frame_info.variables_in_executing_piece: lvals_list.append(tpl_name_val % (var.name, repr(var.value))) if lvals_list: lvals = '%s%s' % (indent, em_normal.join(lvals_list)) result = '%s %s\n' % (link, call) result += ''.join(_format_traceback_lines(frame_info.lines, Colors, self.has_colors, lvals)) return result
def _info(self, obj, oname='', info=None, detail_level=0): """Compute a dict with detailed information about an object. Optional arguments: - oname: name of the variable pointing to the object. - info: a structure with some information fields which may have been precomputed already. - detail_level: if set to 1, more information is given. """ obj_type = type(obj) if info is None: ismagic = 0 isalias = 0 ospace = '' else: ismagic = info.ismagic isalias = info.isalias ospace = info.namespace # Get docstring, special-casing aliases: if isalias: if not callable(obj): try: ds = "Alias to the system command:\n %s" % obj[1] except: ds = "Alias: " + str(obj) else: ds = "Alias to " + str(obj) if obj.__doc__: ds += "\nDocstring:\n" + obj.__doc__ else: ds = getdoc(obj) if ds is None: ds = '<no docstring>' # store output in a dict, we initialize it here and fill it as we go out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic) string_max = 200 # max size of strings to show (snipped if longer) shalf = int((string_max - 5) / 2) if ismagic: obj_type_name = 'Magic function' elif isalias: obj_type_name = 'System alias' else: obj_type_name = obj_type.__name__ out['type_name'] = obj_type_name try: bclass = obj.__class__ out['base_class'] = str(bclass) except: pass # String form, but snip if too long in ? form (full in ??) if detail_level >= self.str_detail_level: try: ostr = str(obj) str_head = 'string_form' if not detail_level and len(ostr)>string_max: ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:] ostr = ("\n" + " " * len(str_head.expandtabs())).\ join(q.strip() for q in ostr.split("\n")) out[str_head] = ostr except: pass if ospace: out['namespace'] = ospace # Length (for strings and lists) try: out['length'] = str(len(obj)) except: pass # Filename where object was defined binary_file = False fname = find_file(obj) if fname is None: # if anything goes wrong, we don't want to show source, so it's as # if the file was binary binary_file = True else: if fname.endswith(('.so', '.dll', '.pyd')): binary_file = True elif fname.endswith('<string>'): fname = 'Dynamically generated function. No source code available.' out['file'] = compress_user(fname) # Original source code for a callable, class or property. if detail_level: # Flush the source cache because inspect can return out-of-date # source linecache.checkcache() try: if isinstance(obj, property) or not binary_file: src = getsource(obj, oname) if src is not None: src = src.rstrip() out['source'] = src except Exception: pass # Add docstring only if no source is to be shown (avoid repetitions). if ds and out.get('source', None) is None: out['docstring'] = ds # Constructor docstring for classes if inspect.isclass(obj): out['isclass'] = True # get the init signature: try: init_def = self._getdef(obj, oname) except AttributeError: init_def = None if init_def: out['init_definition'] = self.format(init_def) # get the __init__ docstring try: obj_init = obj.__init__ except AttributeError: init_ds = None else: init_ds = getdoc(obj_init) # Skip Python's auto-generated docstrings if init_ds == _object_init_docstring: init_ds = None if init_ds: out['init_docstring'] = init_ds # and class docstring for instances: else: # reconstruct the function definition and print it: defln = self._getdef(obj, oname) if defln: out['definition'] = defln # First, check whether the instance docstring is identical to the # class one, and print it separately if they don't coincide. In # most cases they will, but it's nice to print all the info for # objects which use instance-customized docstrings. if ds: try: cls = getattr(obj,'__class__') except: class_ds = None else: class_ds = getdoc(cls) # Skip Python's auto-generated docstrings if class_ds in _builtin_type_docstrings: class_ds = None if class_ds and ds != class_ds: out['class_docstring'] = class_ds # Next, try to show constructor docstrings try: init_ds = getdoc(obj.__init__) # Skip Python's auto-generated docstrings if init_ds == _object_init_docstring: init_ds = None except AttributeError: init_ds = None if init_ds: out['init_docstring'] = init_ds # Call form docstring for callable instances if safe_hasattr(obj, '__call__') and not is_simple_callable(obj): call_def = self._getdef(obj.__call__, oname) if call_def and (call_def != out.get('definition')): # it may never be the case that call def and definition differ, # but don't include the same signature twice out['call_def'] = call_def call_ds = getdoc(obj.__call__) # Skip Python's auto-generated docstrings if call_ds == _func_call_docstring: call_ds = None if call_ds: out['call_docstring'] = call_ds # Compute the object's argspec as a callable. The key is to decide # whether to pull it from the object itself, from its __init__ or # from its __call__ method. if inspect.isclass(obj): # Old-style classes need not have an __init__ callable_obj = getattr(obj, "__init__", None) elif callable(obj): callable_obj = obj else: callable_obj = None if callable_obj is not None: try: argspec = getargspec(callable_obj) except (TypeError, AttributeError): # For extensions/builtins we can't retrieve the argspec pass else: # named tuples' _asdict() method returns an OrderedDict, but we # we want a normal out['argspec'] = argspec_dict = dict(argspec._asdict()) # We called this varkw before argspec became a named tuple. # With getfullargspec it's also called varkw. if 'varkw' not in argspec_dict: argspec_dict['varkw'] = argspec_dict.pop('keywords') return object_info(**out)
def _info(self, obj, oname='', info=None, detail_level=0) -> dict: """Compute a dict with detailed information about an object. Parameters ========== obj: any An object to find information about oname: str (default: ''): Name of the variable pointing to `obj`. info: (default: None) A struct (dict like with attr access) with some information fields which may have been precomputed already. detail_level: int (default:0) If set to 1, more information is given. Returns ======= An object info dict with known fields from `info_fields`. """ if info is None: ismagic = False isalias = False ospace = '' else: ismagic = info.ismagic isalias = info.isalias ospace = info.namespace # Get docstring, special-casing aliases: if isalias: if not callable(obj): try: ds = "Alias to the system command:\n %s" % obj[1] except: ds = "Alias: " + str(obj) else: ds = "Alias to " + str(obj) if obj.__doc__: ds += "\nDocstring:\n" + obj.__doc__ else: ds = getdoc(obj) if ds is None: ds = '<no docstring>' # store output in a dict, we initialize it here and fill it as we go out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic, subclasses=None) string_max = 200 # max size of strings to show (snipped if longer) shalf = int((string_max - 5) / 2) if ismagic: out['type_name'] = 'Magic function' elif isalias: out['type_name'] = 'System alias' else: out['type_name'] = type(obj).__name__ try: bclass = obj.__class__ out['base_class'] = str(bclass) except: pass # String form, but snip if too long in ? form (full in ??) if detail_level >= self.str_detail_level: try: ostr = str(obj) str_head = 'string_form' if not detail_level and len(ostr) > string_max: ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:] ostr = ("\n" + " " * len(str_head.expandtabs())).\ join(q.strip() for q in ostr.split("\n")) out[str_head] = ostr except: pass if ospace: out['namespace'] = ospace # Length (for strings and lists) try: out['length'] = str(len(obj)) except Exception: pass # Filename where object was defined binary_file = False fname = find_file(obj) if fname is None: # if anything goes wrong, we don't want to show source, so it's as # if the file was binary binary_file = True else: if fname.endswith(('.so', '.dll', '.pyd')): binary_file = True elif fname.endswith('<string>'): fname = 'Dynamically generated function. No source code available.' out['file'] = compress_user(fname) # Original source code for a callable, class or property. if detail_level: # Flush the source cache because inspect can return out-of-date # source linecache.checkcache() try: if isinstance(obj, property) or not binary_file: src = getsource(obj, oname) if src is not None: src = src.rstrip() out['source'] = src except Exception: pass # Add docstring only if no source is to be shown (avoid repetitions). if ds and not self._source_contains_docstring(out.get('source'), ds): out['docstring'] = ds # Constructor docstring for classes if inspect.isclass(obj): out['isclass'] = True # get the init signature: try: init_def = self._getdef(obj, oname) except AttributeError: init_def = None # get the __init__ docstring try: obj_init = obj.__init__ except AttributeError: init_ds = None else: if init_def is None: # Get signature from init if top-level sig failed. # Can happen for built-in types (list, etc.). try: init_def = self._getdef(obj_init, oname) except AttributeError: pass init_ds = getdoc(obj_init) # Skip Python's auto-generated docstrings if init_ds == _object_init_docstring: init_ds = None if init_def: out['init_definition'] = init_def if init_ds: out['init_docstring'] = init_ds names = [sub.__name__ for sub in type.__subclasses__(obj)] if len(names) < 10: all_names = ', '.join(names) else: all_names = ', '.join(names[:10] + ['...']) out['subclasses'] = all_names # and class docstring for instances: else: # reconstruct the function definition and print it: defln = self._getdef(obj, oname) if defln: out['definition'] = defln # First, check whether the instance docstring is identical to the # class one, and print it separately if they don't coincide. In # most cases they will, but it's nice to print all the info for # objects which use instance-customized docstrings. if ds: try: cls = getattr(obj, '__class__') except: class_ds = None else: class_ds = getdoc(cls) # Skip Python's auto-generated docstrings if class_ds in _builtin_type_docstrings: class_ds = None if class_ds and ds != class_ds: out['class_docstring'] = class_ds # Next, try to show constructor docstrings try: init_ds = getdoc(obj.__init__) # Skip Python's auto-generated docstrings if init_ds == _object_init_docstring: init_ds = None except AttributeError: init_ds = None if init_ds: out['init_docstring'] = init_ds # Call form docstring for callable instances if safe_hasattr(obj, '__call__') and not is_simple_callable(obj): call_def = self._getdef(obj.__call__, oname) if call_def and (call_def != out.get('definition')): # it may never be the case that call def and definition differ, # but don't include the same signature twice out['call_def'] = call_def call_ds = getdoc(obj.__call__) # Skip Python's auto-generated docstrings if call_ds == _func_call_docstring: call_ds = None if call_ds: out['call_docstring'] = call_ds # Compute the object's argspec as a callable. The key is to decide # whether to pull it from the object itself, from its __init__ or # from its __call__ method. if inspect.isclass(obj): # Old-style classes need not have an __init__ callable_obj = getattr(obj, "__init__", None) elif callable(obj): callable_obj = obj else: callable_obj = None if callable_obj is not None: try: argspec = getargspec(callable_obj) except Exception: # For extensions/builtins we can't retrieve the argspec pass else: # named tuples' _asdict() method returns an OrderedDict, but we # we want a normal out['argspec'] = argspec_dict = dict(argspec._asdict()) # We called this varkw before argspec became a named tuple. # With getfullargspec it's also called varkw. if 'varkw' not in argspec_dict: argspec_dict['varkw'] = argspec_dict.pop('keywords') return object_info(**out)