Exemple #1
0
    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"
Exemple #2
0
    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 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__)
Exemple #5
0
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)
Exemple #9
0
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__)
Exemple #10
0
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__)
Exemple #11
0
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__)
Exemple #12
0
    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"
Exemple #13
0
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
Exemple #14
0
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__
Exemple #15
0
    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
Exemple #16
0
    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)
Exemple #17
0
    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)