Example #1
0
        def recurse(cls):
            cache.add(cls)

            nodename = self.class_name(cls, parts)
            fullname = self.class_name(cls, 0)

            # Use first line of docstring as tooltip, if available
            tooltip = None
            try:
                if cls.__doc__:
                    enc = ModuleAnalyzer.for_module(cls.__module__).encoding
                    doc = cls.__doc__.strip().split("\n")[0]
                    if not isinstance(doc, text_type):
                        doc = force_decode(doc, enc)
                    if doc:
                        tooltip = '"%s"' % doc.replace('"', '\\"')
            except Exception:  # might raise AttributeError for strange classes
                pass

            baselist = [self.class_name(base, parts) for base in cls.__bases__]

            graph.node_add\
                ( ClassInfo(cls, fullname, baselist, tooltip)
                , nodename, baselist
                )

            for base in cls.__bases__:
                if base not in cache:
                    recurse(base)
Example #2
0
        def recurse(cls):
            # type: (Any) -> None
            if not show_builtins and cls in py_builtins:
                return
            if not private_bases and cls.__name__.startswith('_'):
                return

            nodename = self.class_name(cls, parts)
            fullname = self.class_name(cls, 0)

            # Use first line of docstring as tooltip, if available
            tooltip = None
            try:
                if cls.__doc__:
                    enc = ModuleAnalyzer.for_module(cls.__module__).encoding
                    doc = cls.__doc__.strip().split("\n")[0]
                    if not isinstance(doc, text_type):
                        doc = force_decode(doc, enc)
                    if doc:
                        tooltip = '"%s"' % doc.replace('"', '\\"')
            except Exception:  # might raise AttributeError for strange classes
                pass

            baselist = []  # type: List[unicode]
            all_classes[cls] = (nodename, fullname, baselist, tooltip)
            for base in cls.__bases__:
                if not show_builtins and base in py_builtins:
                    continue
                if not private_bases and base.__name__.startswith('_'):
                    continue
                baselist.append(self.class_name(base, parts))
                if base not in all_classes:
                    recurse(base)
Example #3
0
    def has_tag(modname, fullname, docname, refname):
        entry = env._viewcode_modules.get(modname, None)  # type: ignore
        if entry is False:
            return

        code_tags = app.emit_firstresult('viewcode-find-source', modname)
        if code_tags is None:
            try:
                analyzer = ModuleAnalyzer.for_module(modname)
            except Exception:
                env._viewcode_modules[modname] = False  # type: ignore
                return

            analyzer.find_tags()
            code = analyzer.code
            tags = analyzer.tags
        else:
            code, tags = code_tags

        if entry is None or entry[0] != code:
            entry = code, tags, {}, refname
            env._viewcode_modules[modname] = entry  # type: ignore
        _, tags, used, _ = entry
        if fullname in tags:
            used[fullname] = docname
            return True
Example #4
0
    def make_rst(self, section_title_set):
        # print('importing falcon app %s...' % self.arguments[0])
        app = autohttp_import_object(self.arguments[0])
        for method, path, handler in get_routes(app):
            docstring = handler.__doc__
            if not isinstance(docstring, unicode):
                analyzer = ModuleAnalyzer.for_module(handler.__module__)
                docstring = force_decode(docstring, analyzer.encoding)
            if not docstring and 'include-empty-docstring' not in self.options:
                continue
            if not docstring:
                continue
            docstring = prepare_docstring(docstring)

            # generate section title if needed
            if path.startswith('/v'):
                section_title = '/'.join(path.split('/')[0:3])
            else:
                section_title = path
            if section_title not in section_title_set:
                section_title_set.add(section_title)
                yield section_title
                yield '_' * len(section_title)

            for line in autohttp_http_directive(method, path, docstring):
                yield line
Example #5
0
    def make_rst(self):
        app = import_object(self.arguments[0])
        if self.endpoints:
            routes = itertools.chain(
                *[get_routes(app, endpoint) for endpoint in self.endpoints])
        else:
            routes = get_routes(app)
        # sort by path then method
        for method, paths, endpoint in sorted(routes,
                                              key=operator.itemgetter(1, 0)):
            if endpoint in self.undoc_endpoints:
                continue
            view = app._endpoints[endpoint]
            docstring = view.__doc__ or ''
            if hasattr(view, 'view_class'):
                meth_func = getattr(view.view_class, method.lower(), None)
                if meth_func and meth_func.__doc__:
                    docstring = meth_func.__doc__
            if not isinstance(docstring, six.text_type):
                analyzer = ModuleAnalyzer.for_module(view.__module__)
                docstring = force_decode(docstring, analyzer.encoding)

            if not docstring and 'include-empty-docstring' not in self.options:
                continue
            docstring = self.fix_docstring(docstring)
            docstring = prepare_docstring(docstring)
            for line in http_directive(method, paths, docstring):
                yield line
Example #6
0
        def recurse(cls):
            if not show_builtins and cls in py_builtins:
                return
            if not private_bases and cls.__name__.startswith('_'):
                return

            nodename = self.class_name(cls, parts)
            fullname = self.class_name(cls, 0)

            # Use first line of docstring as tooltip, if available
            tooltip = None
            try:
                if cls.__doc__:
                    enc = ModuleAnalyzer.for_module(cls.__module__).encoding
                    doc = cls.__doc__.strip().split("\n")[0]
                    if not isinstance(doc, text_type):
                        doc = force_decode(doc, enc)
                    if doc:
                        tooltip = '"%s"' % doc.replace('"', '\\"')
            except Exception:  # might raise AttributeError for strange classes
                pass

            baselist = []
            all_classes[cls] = (nodename, fullname, baselist, tooltip)
            for base in cls.__bases__:
                if not show_builtins and base in py_builtins:
                    continue
                if not private_bases and base.__name__.startswith('_'):
                    continue
                baselist.append(self.class_name(base, parts))
                if base not in all_classes:
                    recurse(base)
Example #7
0
def import_ivar_by_name(
        name: str,
        prefixes: List[str] = [None],
        grouped_exception: bool = True) -> Tuple[str, Any, Any, str]:
    """Import an instance variable that has the given *name*, under one of the
    *prefixes*.  The first name that succeeds is used.
    """
    try:
        name, attr = name.rsplit(".", 1)
        real_name, obj, parent, modname = import_by_name(
            name, prefixes, grouped_exception)
        qualname = real_name.replace(modname + ".", "")
        analyzer = ModuleAnalyzer.for_module(
            getattr(obj, '__module__', modname))
        analyzer.analyze()
        # check for presence in `annotations` to include dataclass attributes
        if (qualname,
                attr) in analyzer.attr_docs or (qualname,
                                                attr) in analyzer.annotations:
            return real_name + "." + attr, INSTANCEATTR, obj, modname
    except (ImportError, ValueError, PycodeError) as exc:
        raise ImportError from exc
    except ImportExceptionGroup:
        raise  # pass through it as is

    raise ImportError
Example #8
0
    def make_rst(self):
        app = autohttp.import_object(self.arguments[0])
        for method, path, endpoint in get_routes(app):
            try:
                blueprint, endpoint_internal = endpoint.split('.')
                if blueprint in self.undoc_blueprints:
                    continue
            except ValueError:
                pass  # endpoint is not within a blueprint

            if self.endpoints and endpoint not in self.endpoints:
                continue
            if endpoint in self.undoc_endpoints:
                continue
            try:
                static_url_path = app.static_url_path  # Flask 0.7 or higher
            except AttributeError:
                static_url_path = app.static_path  # Flask 0.6 or under
            if ('undoc-static' in self.options and endpoint == 'static'
                    and path == static_url_path + '/(path:filename)'):
                continue
            view = app.view_functions[endpoint]
            docstring = view.__doc__ or ''
            if not isinstance(docstring, unicode):
                analyzer = ModuleAnalyzer.for_module(view.__module__)
                docstring = force_decode(docstring, analyzer.encoding)
            if not docstring and 'include-empty-docstring' not in self.options:
                continue
            docstring = prepare_docstring(docstring)
            for line in autohttp.http_directive(method, path, docstring):
                yield line
    def make_rst(self):
        app = import_object(self.arguments[0])
        for method, path, endpoint in get_routes(app):
            try:
                blueprint, endpoint_internal = endpoint.split('.')
                if blueprint in self.undoc_blueprints:
                    continue
            except ValueError:
                pass  # endpoint is not within a blueprint

            if self.endpoints and endpoint not in self.endpoints:
                continue
            if endpoint in self.undoc_endpoints:
                continue
            try:
                static_url_path = app.static_url_path # Flask 0.7 or higher
            except AttributeError:
                static_url_path = app.static_path # Flask 0.6 or under
            if ('undoc-static' in self.options and endpoint == 'static' and
                path == static_url_path + '/(path:filename)'):
                continue
            view = app.view_functions[endpoint]
            docstring = view.__doc__ or ''
            if hasattr(view, 'view_class'):
                meth_func = getattr(view.view_class, method.lower(), None)
                if meth_func and meth_func.__doc__:
                    docstring = meth_func.__doc__
            if not isinstance(docstring, unicode):
                analyzer = ModuleAnalyzer.for_module(view.__module__)
                docstring = force_decode(docstring, analyzer.encoding)
            if not docstring and 'include-empty-docstring' not in self.options:
                continue
            docstring = prepare_docstring(docstring)
            for line in http_directive(method, path, docstring):
                yield line
Example #10
0
    def has_tag(modname, fullname, docname, refname):
        entry = env._viewcode_modules.get(modname, None)  # type: ignore
        if entry is False:
            return

        code_tags = app.emit_firstresult('viewcode-find-source', modname)
        if code_tags is None:
            try:
                analyzer = ModuleAnalyzer.for_module(modname)
            except Exception:
                env._viewcode_modules[modname] = False  # type: ignore
                return

            if not isinstance(analyzer.code, text_type):
                code = analyzer.code.decode(analyzer.encoding)
            else:
                code = analyzer.code

            analyzer.find_tags()
            tags = analyzer.tags
        else:
            code, tags = code_tags

        if entry is None or entry[0] != code:
            entry = code, tags, {}, refname
            env._viewcode_modules[modname] = entry  # type: ignore
        _, tags, used, _ = entry
        if fullname in tags:
            used[fullname] = docname
            return True
Example #11
0
    def make_rst(self, qref=False):
        app = import_object(self.arguments[0])
        if self.endpoints:
            routes = itertools.chain(*[
                get_routes(app, endpoint, self.order)
                for endpoint in self.endpoints
            ])
        else:
            routes = get_routes(app, order=self.order)
        for method, paths, endpoint in routes:
            try:
                blueprint, _, endpoint_internal = endpoint.rpartition('.')
                if self.blueprints and blueprint not in self.blueprints:
                    continue
                if blueprint in self.undoc_blueprints:
                    continue
            except ValueError:
                pass  # endpoint is not within a blueprint

            if endpoint in self.undoc_endpoints:
                continue
            try:
                static_url_path = app.static_url_path  # Flask 0.7 or higher
            except AttributeError:
                static_url_path = app.static_path  # Flask 0.6 or under
            if ('undoc-static' in self.options and endpoint == 'static'
                    and static_url_path + '/(path:filename)' in paths):
                continue
            view = app.view_functions[endpoint]

            if self.modules and view.__module__ not in self.modules:
                continue

            if self.undoc_modules and view.__module__ in self.modules:
                continue

            docstring = view.__doc__ or ''
            if hasattr(view, 'view_class'):
                meth_func = getattr(view.view_class, method.lower(), None)
                if meth_func and meth_func.__doc__:
                    docstring = meth_func.__doc__
            if not isinstance(docstring, six.text_type):
                analyzer = ModuleAnalyzer.for_module(view.__module__)
                docstring = force_decode(docstring, analyzer.encoding)

            if not docstring and 'include-empty-docstring' not in self.options:
                continue
            docstring = prepare_docstring(docstring)
            if qref == True:
                for path in paths:
                    row = quickref_directive(method, path, docstring)
                    yield row
            else:
                lines = list(http_directive(method, paths, docstring))
                self.state.document.settings.env.app.emit(
                    'autodoc-process-docstring', 'function', None, view, {},
                    lines)
                for line in lines:
                    yield line
Example #12
0
    def inspect_routes(self, app):
        """Inspects the views of Flask.

        :param app: The Flask application.
        :returns: 4-tuple like ``(method, paths, view_func, view_doc)``
        """
        if self.endpoints:
            routes = itertools.chain(*[get_routes(app, endpoint, self.order)
                                       for endpoint in self.endpoints])
        else:
            routes = get_routes(app, order=self.order)

        for method, paths, endpoint in routes:
            try:
                blueprint, _, endpoint_internal = endpoint.rpartition('.')
                if self.blueprints and blueprint not in self.blueprints:
                    continue
                if blueprint in self.undoc_blueprints:
                    continue
            except ValueError:
                pass  # endpoint is not within a blueprint

            if endpoint in self.undoc_endpoints:
                continue

            try:
                static_url_path = app.static_url_path  # Flask 0.7 or higher
            except AttributeError:
                static_url_path = app.static_path      # Flask 0.6 or under
            if ('undoc-static' in self.options and endpoint == 'static' and
                    static_url_path + '/(path:filename)' in paths):
                continue
            view = app.view_functions[endpoint]

            if self.modules and view.__module__ not in self.modules:
                continue

            if self.undoc_modules and view.__module__ in self.modules:
                continue

            view_class = getattr(view, 'view_class', None)
            if view_class is None:
                view_func = view
            else:
                view_func = getattr(view_class, method.lower(), None)

            view_doc = view.__doc__ or ''
            if view_func and view_func.__doc__:
                view_doc = view_func.__doc__

            if not isinstance(view_doc, six.text_type):
                analyzer = ModuleAnalyzer.for_module(view.__module__)
                view_doc = force_decode(view_doc, analyzer.encoding)

            if not view_doc and 'include-empty-docstring' not in self.options:
                continue

            yield (method, paths, view_func, view_doc)
Example #13
0
def viewcode_find_source(app, modname):
    if modname == 'xml_state.XMLNode':
        modname = 'xml_state'
    analyzer = ModuleAnalyzer.for_module(modname)
    code = analyzer.code
    analyzer.find_tags()
    tags = analyzer.tags
    tags = {k.replace('XMLNode.', ''): v for k, v in tags.items()}
    return code, tags 
Example #14
0
def test_ModuleAnalyzer_for_module_in_egg(rootdir):
    try:
        path = rootdir / 'test-pycode-egg' / 'sample-0.0.0-py3.7.egg'
        sys.path.insert(0, path)

        analyzer = ModuleAnalyzer.for_module('sample')
        docs = analyzer.find_attr_docs()
        assert docs == {('', 'CONSTANT'): ['constant on sample.py', '']}
    finally:
        sys.path.pop(0)
Example #15
0
 def get_attr_docs(self, ty):
     # this reaches into some undocumented stuff in sphinx to
     # extract the attribute documentation.
     analyzer = ModuleAnalyzer.for_module(ty.__module__)
     module_attrs = analyzer.find_attr_docs()  # (scope is broken!)
     # Make sure we can split lines for type docs on long lines
     attrs_docs = {}
     for k, v in module_attrs.iteritems():
         attrs_docs[k[1]] = "\n".join(v).strip()
     return attrs_docs
 def get_attr_docs(self, ty):
     # this reaches into some undocumented stuff in sphinx to
     # extract the attribute documentation.
     analyzer = ModuleAnalyzer.for_module(ty.__module__)
     module_attrs = analyzer.find_attr_docs()  # (scope is broken!)
     # Make sure we can split lines for type docs on long lines
     attrs_docs = {}
     for k, v in module_attrs.iteritems():
         attrs_docs[k[1]] = "\n".join(v).strip()
     return attrs_docs
Example #17
0
def test_ModuleAnalyzer_for_module_in_egg(rootdir):
    try:
        path = rootdir / 'test-pycode-egg' / 'sample-0.0.0-py3.7.egg'
        sys.path.insert(0, path)

        analyzer = ModuleAnalyzer.for_module('sample')
        docs = analyzer.find_attr_docs()
        assert docs == {('', 'CONSTANT'): ['constant on sample.py', '']}
    finally:
        sys.path.pop(0)
    def _str_member_list(self):
        """
        Generate a member listing, autosummary:: table .

        """
        out = []

        
        
        for name in ['Attributes', 'Methods']:
            if not self[name]:
                continue
            
            out += ['.. rubric:: %s' % name, '']
            prefix = getattr(self, '_name', '')

            if prefix:
                prefix = '%s.' % prefix
            elif hasattr(self, 'name') and self.name:
                # This is a class: Use its name to make sure Sphinx can find
                # the methods and attributes
                prefix = '%s.' % (self.name)
            else:
                prefix = ''

            autosum = []
            for param, _, desc in self[name]:
                param = param.strip()
                if self._obj:
                    # Fake the attribute as a class property, but do not touch
                    # methods
                    if (hasattr(self._obj, '__module__') and not 
                        (hasattr(self._obj, param) and callable(getattr(self._obj, param)))):

                        # Do not override directly provided docstrings
                        if not len(''.join(desc).strip()):
                            analyzer = ModuleAnalyzer.for_module(self._obj.__module__)
                            desc = analyzer.find_attr_docs().get((self._obj.__name__, param), '')
                            
                        # Only fake a property if we got a docstring
                        if len(''.join(desc).strip()):
                            setattr(self._obj, param, property(lambda self: None,
                                                               doc='\n'.join(desc)))

                if len(prefix):
                    autosum += ["   ~%s%s" % (prefix, param)]
                else:
                    autosum += ["   %s" % param]

            if autosum:
                out += ['.. autosummary::', '']
                out += autosum
            
            out += ['']
        return out
Example #19
0
    def _str_member_list(self):
        """
        Generate a member listing, autosummary:: table .

        """
        out = []

        for name in ['Attributes', 'Methods']:
            if not self[name]:
                continue

            out += [f'.. rubric:: {name}', '']
            prefix = getattr(self, '_name', '')

            if prefix:
                prefix = f'{prefix}.'

            autosum = []
            for param, _, desc in self[name]:
                param = param.strip()
                if self._obj:
                    # Fake the attribute as a class property, but do not touch
                    # methods
                    if hasattr(self._obj, '__module__') and not (
                            hasattr(self._obj, param)
                            and callable(getattr(self._obj, param))):

                        # Do not override directly provided docstrings
                        if not len(''.join(desc).strip()):
                            analyzer = ModuleAnalyzer.for_module(
                                self._obj.__module__)
                            desc = analyzer.find_attr_docs().get(
                                (self._obj.__name__, param), '')

                        # Only fake a property if we got a docstring
                        if len(''.join(desc).strip()):
                            setattr(
                                self._obj,
                                param,
                                property(lambda self: None,
                                         doc='\n'.join(desc)),
                            )

                if len(prefix):
                    autosum += [f"   ~{prefix}{param}"]
                else:
                    autosum += [f"   {param}"]

            if autosum:
                out += ['.. autosummary::', '']
                out += autosum

            out += ['']
        return out
Example #20
0
 def parse_module(self, modname: str):
     if modname in self.cache:
         return self.cache[modname]
     logger.debug(f'Parsing "{modname}"')
     result = self.cache[modname] = {}
     analyzer = ModuleAnalyzer.for_module(modname)
     analyzer.analyze()
     tree = ast.parse(analyzer.code)
     for fullname, decorator_name in self.iter_find_slot_defs(tree):
         result[fullname] = decorator_name
     return result
Example #21
0
def parse_override_docs(namespace, version):
    import_namespace(namespace, version)

    try:
        ma = ModuleAnalyzer.for_module("pgi.overrides.%s" % namespace)
    except PycodeError:
        return {}
    docs = {}
    for key, value in ma.find_attr_docs().iteritems():
        docs[namespace + "." + ".".join(filter(None, key))] = "\n".join(value)
    return docs
Example #22
0
def parse_override_docs(namespace, version):
    import_namespace(namespace, version)

    try:
        ma = ModuleAnalyzer.for_module("pgi.overrides.%s" % namespace)
    except PycodeError:
        return {}
    docs = {}
    for key, value in ma.find_attr_docs().iteritems():
        docs[namespace + "." + ".".join(filter(None, key))] = "\n".join(value)
    return docs
Example #23
0
    def make_rst(self, qref=False):
        app = import_object(self.arguments[0])
        if self.endpoints:
            routes = itertools.chain(*[get_routes(app, endpoint, self.order)
                    for endpoint in self.endpoints])
        else:
            routes = get_routes(app, order=self.order)
        for method, paths, endpoint in routes:
            try:
                blueprint, _, endpoint_internal = endpoint.rpartition('.')
                if self.blueprints and blueprint not in self.blueprints:
                    continue
                if blueprint in self.undoc_blueprints:
                    continue
            except ValueError:
                pass  # endpoint is not within a blueprint

            if endpoint in self.undoc_endpoints:
                continue
            try:
                static_url_path = app.static_url_path # Flask 0.7 or higher
            except AttributeError:
                static_url_path = app.static_path # Flask 0.6 or under
            if ('undoc-static' in self.options and endpoint == 'static' and
                static_url_path + '/(path:filename)' in paths):
                continue
            view = app.view_functions[endpoint]

            if self.modules and view.__module__ not in self.modules:
                continue

            if self.undoc_modules and view.__module__ in self.modules:
                continue

            docstring = view.__doc__ or ''
            if hasattr(view, 'view_class'):
                meth_func = getattr(view.view_class, method.lower(), None)
                if meth_func and meth_func.__doc__:
                    docstring = meth_func.__doc__
            if not isinstance(docstring, six.text_type):
                analyzer = ModuleAnalyzer.for_module(view.__module__)
                docstring = force_decode(docstring, analyzer.encoding)

            if not docstring and 'include-empty-docstring' not in self.options:
                continue
            docstring = prepare_docstring(docstring)
            if qref == True:
                for path in paths:
                    row = quickref_directive(method, path, docstring)
                    yield row
            else:
                for line in http_directive(method, paths, docstring):
                    yield line
Example #24
0
    def properties(self):
        if self._cls is None:
            return []
        analyzer = ModuleAnalyzer.for_module(self._cls.__module__)
        instance_members = set([attr_name for (class_name, attr_name) in
                                analyzer.find_attr_docs().keys()
                                if class_name == self._cls.__name__])
        class_members = set([name for name, func in getattr(self._cls, '__dict__').iteritems()
                             if not name.startswith('_') and (func is None or
                                                              inspect.isdatadescriptor(func))])

        return instance_members | class_members
    def properties(self):
        if self._cls is None:
            return []
        analyzer = ModuleAnalyzer.for_module(self._cls.__module__)
        instance_members = {attr_name for (class_name, attr_name) in
                            analyzer.find_attr_docs().keys()
                            if class_name == self._cls.__name__}
        class_members = {name for name, func in getattr(self._cls, '__dict__').items()
                         if not name.startswith('_') and (func is None or
                                                          inspect.isdatadescriptor(func))}

        return instance_members | class_members
Example #26
0
def config_attrs(config):
    annotations, defaults = config.config.annotations_and_defaults()
    analyzer = ModuleAnalyzer.for_module(config.config.__module__)
    attr_docs = {
        attr: list(lines)
        for (classname, attr), lines in analyzer.find_attr_docs().items()
        if classname == config.name
    }
    return [
        Attribute(type, name, defaults.get(name, NO_DEFAULT), attr_docs.get(name, ""))
        for name, type in annotations.items()
    ]
Example #27
0
 def get_module_attrs(members: Any) -> Tuple[List[str], List[str]]:
     """Find module attributes with docstrings."""
     attrs, public = [], []
     try:
         analyzer = ModuleAnalyzer.for_module(name)
         attr_docs = analyzer.find_attr_docs()
         for namespace, attr_name in attr_docs:
             if namespace == '' and attr_name in members:
                 attrs.append(attr_name)
                 if not attr_name.startswith('_'):
                     public.append(attr_name)
     except PycodeError:
         pass  # give up if ModuleAnalyzer fails to parse code
     return public, attrs
Example #28
0
 def get_iattributes(obj):
     items = list()
     name = obj.__name__
     obj_attr = dir(obj)
     analyzer = ModuleAnalyzer.for_module(obj.__module__)
     attr_docs = analyzer.find_attr_docs()
     for pair, doc in attr_docs.items():
         if name != pair[0]:
             continue
         if not pair[1] in obj_attr:
             items.append({"name": pair[1],
                           "doc": '\n   '.join(doc)})
     items.sort(key=lambda d: d["name"])
     return items
Example #29
0
 def get_iattributes(obj):
     items = []
     name = obj.__name__
     obj_attr = dir(obj)
     analyzer = ModuleAnalyzer.for_module(obj.__module__)
     attr_docs = analyzer.find_attr_docs()
     for pair, doc in attr_docs.iteritems():
         if name!=pair[0]:
             continue
         if not pair[1] in obj_attr:
             items.append({"name":pair[1],
                           "doc":'\n   '.join(doc)})
     items.sort(key=lambda d: d["name"]) 
     return items
    def run(self):
        module_name = str(self.arguments[0])
        module = importlib.import_module(module_name)

        analyzer = ModuleAnalyzer.for_module(module_name)
        attr_docs = analyzer.find_attr_docs()

        with open(module.__file__) as module_file:
            symbols = symtable.symtable(module_file.read(), module.__file__, "exec")

        members = []

        for name in dir(module):
            member = getattr(module, name)

            # Ignore private members
            if name.startswith("_"):
                continue

            # Ignore imported modules
            if isinstance(member, types.ModuleType):
                continue

            # Ignore members imported from other modules
            member_module_name = getattr(member, "__module__", None)
            if member_module_name is None:
                try:
                    if symbols.lookup(name).is_imported():
                        continue
                except KeyError:
                    continue
            else:
                if member_module_name != module_name:
                    continue

            documenter = get_documenter(self.env.app, member, module)

            # Ignore data items that do not have docstrings
            if documenter.objtype == "data" and ("", name) not in attr_docs:
                continue

            members.append(name)

        # Sort members in the order they appear in source code
        tagorder = analyzer.tagorder
        members.sort(key=lambda name: tagorder.get(name, len(tagorder)))

        self.content = [f"{module_name}.{member}" for member in members]

        return super().run()
    def sort_members(
        self,
        documenters: List[Tuple[Documenter, bool]],
        order: str,
    ) -> List[Tuple[Documenter, bool]]:
        """
		Sort the TypedDict's members.

		:param documenters:
		:param order:
		"""

        # The documenters for the keys, in the desired order
        documenters = super().sort_members(documenters, order)

        # Mapping of key names to docstrings (as list of strings)
        docstrings = {
            k[1]: v
            for k, v in ModuleAnalyzer.for_module(
                self.object.__module__).find_attr_docs().items()
        }

        required_keys = []
        optional_keys = []
        types = get_type_hints(self.object)

        for d in documenters:
            name = d[0].name.split('.')[-1]
            if name in self.object.__required_keys__:
                required_keys.append(name)
            elif name in self.object.__optional_keys__:
                optional_keys.append(name)
            # else: warn user. This shouldn't ever happen, though.

        sourcename = self.get_sourcename()

        if required_keys:
            self.add_line('', sourcename)
            self.add_line(":Required Keys:", sourcename)
            self.document_keys(required_keys, types, docstrings)
            self.add_line('', sourcename)

        if optional_keys:
            self.add_line('', sourcename)
            self.add_line(":Optional Keys:", sourcename)
            self.document_keys(optional_keys, types, docstrings)
            self.add_line('', sourcename)

        return []
Example #32
0
 def resolve_arg_doc_and_index(
         self, name,
         dataclass: type) -> Optional[Tuple[Tuple[int, int], str]]:
     if self.settings.inherited_options:
         bases = dataclass.__mro__
     else:
         bases = [dataclass]
     for i, base in enumerate(bases):
         analyzer = ModuleAnalyzer.for_module(base.__module__)
         docs = analyzer.find_attr_docs()
         if (base.__qualname__, name) in docs:
             tag = analyzer.tagorder[f'{base.__qualname__}.{name}']
             return (-i, tag), self.canonize_docstring('\n'.join(
                 docs[base.__qualname__, name]))
     return None
Example #33
0
def import_ivar_by_name(name: str, prefixes: List[str] = [None]) -> Tuple[str, Any, Any, str]:
    """Import an instance variable that has the given *name*, under one of the
    *prefixes*.  The first name that succeeds is used.
    """
    try:
        name, attr = name.rsplit(".", 1)
        real_name, obj, parent, modname = import_by_name(name, prefixes)
        qualname = real_name.replace(modname + ".", "")
        analyzer = ModuleAnalyzer.for_module(modname)
        if (qualname, attr) in analyzer.find_attr_docs():
            return real_name + "." + attr, INSTANCEATTR, obj, modname
    except (ImportError, ValueError, PycodeError):
        pass

    raise ImportError
    def isinstanceattribute(self) -> bool:
        """
		Check the subject is an instance attribute.
		"""

        try:
            analyzer = ModuleAnalyzer.for_module(self.modname)
            attr_docs = analyzer.find_attr_docs()
            if self.objpath:
                key = ('.'.join(self.objpath[:-1]), self.objpath[-1])
                if key in attr_docs:
                    return True

            return False
        except PycodeError:
            return False
Example #35
0
    def generate(
        self,
        more_content=None,
        real_modname=None,
        check_module=False,
        all_members=False,
    ):
        """
        Generate reST for the object given by *self.name*, and possibly members.

        If *more_content* is given, include that content. If *real_modname* is
        given, use that module name to find attribute docs. If *check_module* is
        True, only generate if the object is defined in the module name it is
        imported from. If *all_members* is True, document all members.
        """
        if not self.parse_name():
            # need a module to import
            self.directive.warn(
                "don't know which module to import for autodocumenting "
                '%r (try placing a "module" or "currentmodule" directive '
                "in the document, or giving an explicit module name)" % self.name
            )
            return

        # now, import the module and get object to document
        if not self.import_object():
            return

        # If there is no real module defined, figure out which to use.
        # The real module is used in the module analyzer to look up the module
        # where the attribute documentation would actually be found in.
        # This is used for situations where you have a module that collects the
        # functions and classes of internal submodules.
        self.real_modname = real_modname or self.get_real_modname()

        # try to also get a source code analyzer for attribute docs
        try:
            self.analyzer = ModuleAnalyzer.for_module(self.real_modname)
            # parse right now, to get PycodeErrors on parsing (results will
            # be cached anyway)
            self.analyzer.find_attr_docs()
        except PycodeError, err:
            # no source file -- e.g. for builtin and C modules
            self.analyzer = None
            # at least add the module.__file__ as a dependency
            if hasattr(self.module, "__file__") and self.module.__file__:
                self.directive.filename_set.add(self.module.__file__)
Example #36
0
def register_source(app, env, modname):
    """
    Registers source code.

    :param app: application
    :param env: environment of the plugin
    :param modname: name of the module to load
    :return: True if the code is registered successfully, False otherwise
    """
    entry = env._viewcode_modules.get(modname, None)
    if entry is False:
        print(f"[{modname}] Entry is false for ")
        return False

    code_tags = app.emit_firstresult("viewcode-find-source", modname)
    if code_tags is None:
        try:
            analyzer = ModuleAnalyzer.for_module(modname)
        except Exception as ex:
            logger.info(
                "Module \"%s\" could not be loaded. Full source will not be available. \"%s\"",
                modname, ex)
            # We cannot use regular warnings or exception methods because those warnings are interpreted
            # by running python process and converted into "real" warnings, so we need to print the
            # traceback here at info level
            tb = traceback.format_exc()
            logger.info("%s", tb)
            env._viewcode_modules[modname] = False
            return False

        if not isinstance(analyzer.code, str):
            code = analyzer.code.decode(analyzer.encoding)
        else:
            code = analyzer.code

        analyzer.find_tags()
        tags = analyzer.tags

    else:
        code, tags = code_tags

    if entry is None or entry[0] != code:
        entry = code, tags, {}, ""
        env._viewcode_modules[modname] = entry

    return True
Example #37
0
 def has_tag(modname, fullname, docname):
     entry = env._viewcode_modules.get(modname, None)
     if entry is None:
         try:
             analyzer = ModuleAnalyzer.for_module(modname)
         except Exception:
             env._viewcode_modules[modname] = False
             return
         analyzer.find_tags()
         entry = analyzer.code.decode(analyzer.encoding), analyzer.tags, {}
         env._viewcode_modules[modname] = entry
     elif entry is False:
         return
     code, tags, used = entry
     if fullname in tags:
         used[fullname] = docname
         return True
Example #38
0
def handle_find_source(app, modname):
    try:
        module = importlib.import_module(modname)
    except Exception:
        return None
    if not getattr(module, '_isScenicModule', False):
        return None  # no special handling for Python modules

    # Run usual analysis on the translated source to get tag dictionary
    try:
        analyzer = ModuleAnalyzer.for_module(modname)
        analyzer.find_tags()
    except Exception:
        return None  # bail out; viewcode will try analyzing again but oh well

    # Return original Scenic source, plus tags (line numbers will correspond)
    return module._source, analyzer.tags
Example #39
0
 def has_tag(modname, fullname, docname):
     entry = env._viewcode_modules.get(modname, None)
     if entry is None:
         try:
             analyzer = ModuleAnalyzer.for_module(modname)
         except Exception:
             env._viewcode_modules[modname] = False
             return
         analyzer.find_tags()
         entry = analyzer.code.decode(analyzer.encoding), analyzer.tags, {}
         env._viewcode_modules[modname] = entry
     elif entry is False:
         return
     code, tags, used = entry
     if fullname in tags:
         used[fullname] = docname
         return True
    def make_rst(self):
        app = import_object(self.arguments[0])
        if self.endpoints:
            routes = itertools.chain(*[get_routes(app, endpoint)
                                     for endpoint in self.endpoints])
        else:
            routes = get_routes(app)

        for method, paths, endpoint in routes:
            if not self.check_regex_validate_path(paths):
                continue
            if self.check_regex_cancel_path(paths):
                continue
            try:
                blueprint, _, endpoint_internal = endpoint.rpartition('.')
                if self.blueprints and blueprint not in self.blueprints:
                    continue
                if blueprint in self.undoc_blueprints:
                    continue
            except ValueError:
                pass  # endpoint is not within a blueprint

            if endpoint in self.undoc_endpoints:
                continue
            try:
                static_url_path = app.static_url_path  # Flask 0.7 or higher
            except AttributeError:
                static_url_path = app.static_path  # Flask 0.6 or under
            if ('undoc-static' in self.options and endpoint == 'static' and
                    static_url_path + '/(path:filename)' in paths):
                continue
            view = app.view_functions[endpoint]
            docstring = view.__doc__ or ''
            if hasattr(view, 'view_class'):
                meth_func = getattr(view.view_class, method.lower(), None)
                if meth_func and meth_func.__doc__:
                    docstring = meth_func.__doc__
            if not isinstance(docstring, six.text_type):
                analyzer = ModuleAnalyzer.for_module(view.__module__)
                docstring = force_decode(docstring, analyzer.encoding)

            if not docstring and 'include-empty-docstring' not in self.options:
                continue
            docstring = prepare_docstring(docstring)
            for line in http_directive(method, paths, docstring):
                yield line
Example #41
0
 def make_rst(self):
     app = import_object(self.arguments[0])
     for method, path, target in get_routes(app):
         endpoint = target.name or target.callback.__name__
         if self.endpoints and endpoint not in self.endpoints:
             continue
         if endpoint in self.undoc_endpoints:
             continue
         view = target.callback
         docstring = view.__doc__ or ''
         if not isinstance(docstring, six.text_type):
             analyzer = ModuleAnalyzer.for_module(view.__module__)
             docstring = force_decode(docstring, analyzer.encoding)
         if not docstring and 'include-empty-docstring' not in self.options:
             continue
         docstring = prepare_docstring(docstring)
         for line in http_directive(method, path, docstring):
             yield line
 def make_rst(self):
     app = import_object(self.arguments[0])
     for method, path, target in get_routes(app):
         endpoint = target.name or target.callback.__name__
         if self.endpoints and endpoint not in self.endpoints:
             continue
         if endpoint in self.undoc_endpoints:
             continue
         view = target.callback
         docstring = view.__doc__ or ''
         if not isinstance(docstring, six.text_type):
             analyzer = ModuleAnalyzer.for_module(view.__module__)
             docstring = force_decode(docstring, analyzer.encoding)
         if not docstring and 'include-empty-docstring' not in self.options:
             continue
         docstring = prepare_docstring(docstring)
         for line in http_directive(method, path, docstring):
             yield line
Example #43
0
    def generate(self, more_content=None, real_modname=None,
                 check_module=False, all_members=False):
        """Generate reST for the object given by *self.name*, and possibly for
        its members.

        If *more_content* is given, include that content. If *real_modname* is
        given, use that module name to find attribute docs. If *check_module* is
        True, only generate if the object is defined in the module name it is
        imported from. If *all_members* is True, document all members.
        """
        if not self.parse_name():
            # need a module to import
            self.directive.warn(
                'don\'t know which module to import for autodocumenting '
                '%r (try placing a "module" or "currentmodule" directive '
                'in the document, or giving an explicit module name)'
                % self.name)
            return

        # now, import the module and get object to document
        if not self.import_object():
            return

        # If there is no real module defined, figure out which to use.
        # The real module is used in the module analyzer to look up the module
        # where the attribute documentation would actually be found in.
        # This is used for situations where you have a module that collects the
        # functions and classes of internal submodules.
        self.real_modname = real_modname or self.get_real_modname()

        # try to also get a source code analyzer for attribute docs
        try:
            self.analyzer = ModuleAnalyzer.for_module(self.real_modname)
            # parse right now, to get PycodeErrors on parsing (results will
            # be cached anyway)
            self.analyzer.find_attr_docs()
        except PycodeError, err:
            self.env.app.debug('[autodoc] module analyzer failed: %s', err)
            # no source file -- e.g. for builtin and C modules
            self.analyzer = None
            # at least add the module.__file__ as a dependency
            if hasattr(self.module, '__file__') and self.module.__file__:
                self.directive.filename_set.add(self.module.__file__)
Example #44
0
def register_source(app, env, modname):
    """
    Registers source code.

    :param app: application
    :param env: environment of the plugin
    :param modname: name of the module to load
    :return: True if the code is registered successfully, False otherwise
    """
    entry = env._viewcode_modules.get(modname, None)  # type: ignore
    if entry is False:
        print("[%s] Entry is false for " % modname)
        return False

    code_tags = app.emit_firstresult("viewcode-find-source", modname)
    if code_tags is None:
        # noinspection PyBroadException
        try:
            analyzer = ModuleAnalyzer.for_module(modname)
        except Exception as ex:  # pylint: disable=broad-except
            logger.info(
                "Module \"%s\" could not be loaded. Full source will not be available. \"%s\"",
                modname, ex)
            env._viewcode_modules[modname] = False  # type: ignore
            return False

        if not isinstance(analyzer.code, text_type):
            code = analyzer.code.decode(analyzer.encoding)
        else:
            code = analyzer.code

        analyzer.find_tags()
        tags = analyzer.tags

    else:
        code, tags = code_tags

    if entry is None or entry[0] != code:
        entry = code, tags, {}, ""
        env._viewcode_modules[modname] = entry  # type: ignore

    return True
Example #45
0
 def has_tag(modname, fullname, docname):
     entry = env._viewcode_modules.get(modname, None)
     try:
         analyzer = ModuleAnalyzer.for_module(modname)
     except Exception:
         env._viewcode_modules[modname] = False
         return
     if not isinstance(analyzer.code, str):
         code = analyzer.code.decode(analyzer.encoding)
     else:
         code = analyzer.code
     if entry is None or entry[0] != code:
         analyzer.find_tags()
         entry = code, analyzer.tags, {}
         env._viewcode_modules[modname] = entry
     elif entry is False:
         return
     code, tags, used = entry
     if fullname in tags:
         used[fullname] = docname
         return True
Example #46
0
 def has_tag(modname, fullname, docname, refname):
     entry = env._viewcode_modules.get(modname, None)
     if entry is None:
         try:
             analyzer = ModuleAnalyzer.for_module(modname)
         except Exception:
             env._viewcode_modules[modname] = False
             return
         analyzer.find_tags()
         if not isinstance(analyzer.code, text_type):
             code = analyzer.code.decode(analyzer.encoding)
         else:
             code = analyzer.code
         entry = code, analyzer.tags, {}, refname
         env._viewcode_modules[modname] = entry
     elif entry is False:
         return
     _, tags, used, _ = entry
     if fullname in tags:
         used[fullname] = docname
         return True
Example #47
0
def _update_tags(env, modname, fullname=None):
    # Analyze modname code and return True if fullname is present. Also caches
    # the analysis results in _viewcode_modules.
    entry = env._viewcode_modules.get(modname, None)
    if entry is None:
        try:
            analyzer = ModuleAnalyzer.for_module(modname)
        except Exception:
            env._viewcode_modules[modname] = False
            return
        analyzer.find_tags()
        if not isinstance(analyzer.code, str):
            code = analyzer.code.decode(analyzer.encoding)
        else:
            code = analyzer.code
        entry = code, analyzer.tags, {}
        env._viewcode_modules[modname] = entry
    elif entry is False:
        return
    code, tags, used = entry
    if fullname is not None and fullname in tags:
        used[fullname] = env.docname
        return True
Example #48
0
def doctree_read(app, doctree):
    env = app.builder.env
    if not hasattr(env, '_viewcode_modules'):
        env._viewcode_modules = {}

    def has_tag(modname, fullname, docname, refname):
        entry = env._viewcode_modules.get(modname, None)
        try:
            analyzer = ModuleAnalyzer.for_module(modname)
        except Exception:
            env._viewcode_modules[modname] = False
            return
        if not isinstance(analyzer.code, text_type):
            code = analyzer.code.decode(analyzer.encoding)
        else:
            code = analyzer.code
        if entry is None or entry[0] != code:
            analyzer.find_tags()
            entry = code, analyzer.tags, {}, refname
            env._viewcode_modules[modname] = entry
        elif entry is False:
            return
        _, tags, used, _ = entry
        if fullname in tags:
            used[fullname] = docname
            return True

    for objnode in doctree.traverse(addnodes.desc):
        if objnode.get('domain') != 'py':
            continue
        names = set()
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue
            modname = signode.get('module')
            fullname = signode.get('fullname')
            refname = modname
            if env.config.viewcode_import:
                modname = _get_full_modname(app, modname, fullname)
            if not modname:
                continue
            fullname = signode.get('fullname')
            if not has_tag(modname, fullname, env.docname, refname):
                continue
            if fullname in names:
                # only one link per name, please
                continue
            names.add(fullname)
            pagename = '_modules/' + modname.replace('.', '/')
            onlynode = addnodes.only(expr='html')
            onlynode += addnodes.pending_xref(
                '', reftype='viewcode', refdomain='std', refexplicit=False,
                reftarget=pagename, refid=fullname,
                refdoc=env.docname)
            onlynode[0] += nodes.inline('', _('[source]'),
                                        classes=['viewcode-link'])
            signode += onlynode

    for objnode in doctree.traverse(nodes.title):
        rawsource = objnode.rawsource
        if rawsource.endswith(' module'):
            # HACK: use rawsource string as source of module name.
            modname = rawsource[:-len(' module')]

            entry = env._viewcode_modules.get(modname, None)
            try:
                analyzer = ModuleAnalyzer.for_module(modname)
            except Exception:
                env._viewcode_modules[modname] = False
                return
            if not isinstance(analyzer.code, text_type):
                code = analyzer.code.decode(analyzer.encoding)
            else:
                code = analyzer.code
            if entry is None or entry[0] != code:
                analyzer.find_tags()
                entry = code, analyzer.tags, {}, modname
                env._viewcode_modules[modname] = entry

            pagename = '_modules/' + modname.replace('.', '/')
            onlynode = addnodes.only(expr='html')
            onlynode += addnodes.pending_xref(
                '', reftype='viewcode', refdomain='std', refexplicit=False,
                reftarget=pagename, refid='', refdoc=env.docname)
            onlynode[0] += nodes.inline('', _('[source]'),
                                        classes=['viewcode-link'])
            objnode += onlynode
Example #49
0
    def make_rst(self):
        app = import_object(self.arguments[0])
        yield "Services:\n"
        yield ""
        for x in self._make_toc(get_routes(app)):
            yield '- {}'.format(x)
            yield ""
        
        for method, path, endpoint in get_routes(app):
            try:
                blueprint, _, endpoint_internal = endpoint.rpartition('.')
                if self.blueprints and blueprint not in self.blueprints:
                    continue
                if blueprint in self.undoc_blueprints:
                    continue
            except ValueError:
                pass  # endpoint is not within a blueprint

            if self.endpoints and endpoint not in self.endpoints:
                continue
            if endpoint in self.undoc_endpoints:
                continue
            try:
                static_url_path = app.static_url_path # Flask 0.7 or higher
            except AttributeError:
                static_url_path = app.static_path # Flask 0.6 or under
            if ('undoc-static' in self.options and endpoint == 'static' and
                path == static_url_path + '/(path:filename)'):
                continue
            view = app.view_functions[endpoint]
            docstring = view.__doc__ or ''
            if hasattr(view, 'view_class'):
                meth_func = getattr(view.view_class, method.lower(), None)
                if meth_func and meth_func.__doc__:
                    docstring = meth_func.__doc__
            if not isinstance(docstring, six.text_type):
                analyzer = ModuleAnalyzer.for_module(view.__module__)
                docstring = force_decode(docstring, analyzer.encoding)

            if not docstring and 'include-empty-docstring' not in self.options:
                continue

            #Thanks flask-classy for this :D
            if len(endpoint.split(":")) == 2:
                view_cls, view_func = endpoint.split(":")
                if hasattr(app, 'view_classes') and view_cls in app.view_classes:
                    cls = app.view_classes[view_cls]
                    members = inspect.getmembers(cls,predicate=inspect.ismethod)
                    if hasattr(cls,'args_rules'):
                        rules = cls.args_rules
                        if view_func in rules:
                            for m in members:
                                if m[0] == view_func:
                                    docstring += m[1].__doc__.strip()
                            docstring += '\n\n'
                            for a in rules[view_func]:
                                t = str(a.type).replace('type','').replace("'","").replace('<','').replace('>','')
                                params = dict(
                                    type=t,
                                    name=str(a.name),
                                    description=str(a.description),
                                    default=str(a.default)
                                )
                                if a.required:
                                    docstring += '    :<json {type} {name}: {description}.\n'.format(**params)
                                else:
                                    docstring += '    :<json {type} {name}: *(optional)* {description}. *Default*={default}\n'.format(**params)
            docstring = prepare_docstring(docstring)
            for line in http_directive(method, path, docstring):
                yield line
Example #50
0
def test_ModuleAnalyzer_for_module():
    analyzer = ModuleAnalyzer.for_module('sphinx')
    assert analyzer.modname == 'sphinx'
    assert analyzer.srcname == SPHINX_MODULE_PATH
    assert analyzer.encoding == 'utf-8'
Example #51
0
    def get_items(self, names):
        """Try to import the given names, and return a list of
        ``[(name, signature, summary_string, real_name), ...]``.
        """
        env = self.state.document.settings.env

        prefixes = get_import_prefixes_from_env(env)

        items = []

        max_item_chars = 50

        for name in names:
            display_name = name
            if name.startswith('~'):
                name = name[1:]
                display_name = name.split('.')[-1]

            try:
                real_name, obj, parent, modname = import_by_name(name, prefixes=prefixes)
            except ImportError:
                self.warn('failed to import %s' % name)
                items.append((name, '', '', name))
                continue

            self.result = ViewList()  # initialize for each documenter
            full_name = real_name
            if not isinstance(obj, ModuleType):
                # give explicitly separated module name, so that members
                # of inner classes can be documented
                full_name = modname + '::' + full_name[len(modname)+1:]
            # NB. using full_name here is important, since Documenters
            #     handle module prefixes slightly differently
            documenter = get_documenter(obj, parent)(self, full_name)
            if not documenter.parse_name():
                self.warn('failed to parse name %s' % real_name)
                items.append((display_name, '', '', real_name))
                continue
            if not documenter.import_object():
                self.warn('failed to import object %s' % real_name)
                items.append((display_name, '', '', real_name))
                continue
            if documenter.options.members and not documenter.check_module():
                continue

            # try to also get a source code analyzer for attribute docs
            try:
                documenter.analyzer = ModuleAnalyzer.for_module(
                    documenter.get_real_modname())
                # parse right now, to get PycodeErrors on parsing (results will
                # be cached anyway)
                documenter.analyzer.find_attr_docs()
            except PycodeError as err:
                documenter.env.app.debug(
                    '[autodoc] module analyzer failed: %s', err)
                # no source file -- e.g. for builtin and C modules
                documenter.analyzer = None

            # -- Grab the signature

            sig = documenter.format_signature()
            if not sig:
                sig = ''
            else:
                max_chars = max(10, max_item_chars - len(display_name))
                sig = mangle_signature(sig, max_chars=max_chars)
                sig = sig.replace('*', r'\*')

            # -- Grab the summary

            documenter.add_content(None)
            doc = list(documenter.process_doc([self.result.data]))

            while doc and not doc[0].strip():
                doc.pop(0)

            # If there's a blank line, then we can assume the first sentence /
            # paragraph has ended, so anything after shouldn't be part of the
            # summary
            for i, piece in enumerate(doc):
                if not piece.strip():
                    doc = doc[:i]
                    break

            # Try to find the "first sentence", which may span multiple lines
            m = re.search(r"^([A-Z].*?\.)(?:\s|$)", " ".join(doc).strip())
            if m:
                summary = m.group(1).strip()
            elif doc:
                summary = doc[0].strip()
            else:
                summary = ''

            items.append((display_name, sig, summary, real_name))

        return items
Example #52
0
    def get_items(self, names):
        # type: (List[unicode]) -> List[Tuple[unicode, unicode, unicode, unicode]]
        """Try to import the given names, and return a list of
        ``[(name, signature, summary_string, real_name), ...]``.
        """
        prefixes = get_import_prefixes_from_env(self.env)

        items = []  # type: List[Tuple[unicode, unicode, unicode, unicode]]

        max_item_chars = 50

        for name in names:
            display_name = name
            if name.startswith('~'):
                name = name[1:]
                display_name = name.split('.')[-1]

            try:
                real_name, obj, parent, modname = import_by_name(name, prefixes=prefixes)
            except ImportError:
                self.warn('failed to import %s' % name)
                items.append((name, '', '', name))
                continue

            self.result = ViewList()  # initialize for each documenter
            full_name = real_name
            if not isinstance(obj, ModuleType):
                # give explicitly separated module name, so that members
                # of inner classes can be documented
                full_name = modname + '::' + full_name[len(modname) + 1:]
            # NB. using full_name here is important, since Documenters
            #     handle module prefixes slightly differently
            documenter = get_documenter(self.env.app, obj, parent)(self, full_name)
            if not documenter.parse_name():
                self.warn('failed to parse name %s' % real_name)
                items.append((display_name, '', '', real_name))
                continue
            if not documenter.import_object():
                self.warn('failed to import object %s' % real_name)
                items.append((display_name, '', '', real_name))
                continue
            if documenter.options.members and not documenter.check_module():
                continue

            # try to also get a source code analyzer for attribute docs
            try:
                documenter.analyzer = ModuleAnalyzer.for_module(
                    documenter.get_real_modname())
                # parse right now, to get PycodeErrors on parsing (results will
                # be cached anyway)
                documenter.analyzer.find_attr_docs()
            except PycodeError as err:
                logger.debug('[autodoc] module analyzer failed: %s', err)
                # no source file -- e.g. for builtin and C modules
                documenter.analyzer = None

            # -- Grab the signature

            sig = documenter.format_signature()
            if not sig:
                sig = ''
            else:
                max_chars = max(10, max_item_chars - len(display_name))
                sig = mangle_signature(sig, max_chars=max_chars)

            # -- Grab the summary

            documenter.add_content(None)
            summary = extract_summary(self.result.data[:], self.state.document)

            items.append((display_name, sig, summary, real_name))

        return items
Example #53
0
 def get_attr_docs(self, ty):
     # this reaches into some undocumented stuff in sphinx to
     # extract the attribute documentation.
     analyzer = ModuleAnalyzer.for_module(ty.__module__)
     module_attrs = analyzer.find_attr_docs()  # (scope is broken!)
     return {k[1]: v[0] for k, v in module_attrs.iteritems()}
Example #54
0
 def run(self):
     try:
         modfn = ModuleAnalyzer.for_module(self.arguments[0]).srcname
     except PycodeError, e:
         warnstr = "can't find module %s for todomodule: %s" % (self.arguments[0], e)
         return [self.state.document.reporter.warning(warnstr, lineno=self.lineno)]
Example #55
0
def test_ModuleAnalyzer_for_module():
    analyzer = ModuleAnalyzer.for_module('sphinx')
    assert analyzer.modname == 'sphinx'
    assert analyzer.srcname in (SPHINX_MODULE_PATH,
                                os.path.abspath(SPHINX_MODULE_PATH))
    assert analyzer.encoding == 'utf-8'
Example #56
0
  def generate(self, more_content=None, real_modname=None,
                                check_module=False, all_members=False):
    # type: (Any, str, bool, bool) -> None
    """Generate reST for the object given by *self.name*, and possibly for
    its members.

    If *more_content* is given, include that content. If *real_modname* is
    given, use that module name to find attribute docs. If *check_module* is
    True, only generate if the object is defined in the module name it is
    imported from. If *all_members* is True, document all members.
    """
    # print('generate', more_content, real_modname, check_module, all_members)
    # print(self.name)
    # print('---------------------')
    # > generate None fontbakery.profiles.post True True
    # > fontbakery.profiles.post::com_google_fonts_check_post_table_version
    # > ---------------------
    #
    # > generate None fontbakery.profiles.shared_conditions True True
    # > fontbakery.profiles.shared_conditions::glyph_metrics_stats
    # > ---------------------
    if not self.parse_name():
        # need a module to import
        logger.warning(
            __('don\'t know which module to import for autodocumenting '
               '%r (try placing a "module" or "currentmodule" directive '
               'in the document, or giving an explicit module name)') %
            self.name, type='autodoc')
        return


    # now, import the module and get object to document
    if not self.import_object():
        return

    # doesn't do anything!
    # if self.objtype == 'fontbakerycheck':
    #   self.name = self.object.id


    # If there is no real module defined, figure out which to use.
    # The real module is used in the module analyzer to look up the module
    # where the attribute documentation would actually be found in.
    # This is used for situations where you have a module that collects the
    # functions and classes of internal submodules.
    self.real_modname = real_modname or self.get_real_modname()  # type: str

    # try to also get a source code analyzer for attribute docs
    try:
        self.analyzer = ModuleAnalyzer.for_module(self.real_modname)
        # parse right now, to get PycodeErrors on parsing (results will
        # be cached anyway)
        self.analyzer.find_attr_docs()
    except PycodeError as err:
        logger.debug('[autodoc] module analyzer failed: %s', err)
        # no source file -- e.g. for builtin and C modules
        self.analyzer = None
        # at least add the module.__file__ as a dependency
        if hasattr(self.module, '__file__') and self.module.__file__:
            self.directive.filename_set.add(self.module.__file__)
    else:
        self.directive.filename_set.add(self.analyzer.srcname)


    # check __module__ of object (for members not given explicitly)
    if check_module:
        if not self.check_module():
            return


    sourcename = self.get_sourcename()


    # make sure that the result starts with an empty line.  This is
    # necessary for some situations where another directive preprocesses
    # reST and no starting newline is present
    self.add_line('', sourcename)


    # format the object's signature, if any
    sig = self.format_signature()

    # generate the directive header and options, if applicable
    self.add_directive_header(sig)
    self.add_line('', sourcename)


    # e.g. the module directive doesn't have content
    self.indent += self.content_indent


    # add all content (from docstrings, attribute docs etc.)
    self.add_content(more_content)


    # document members, if possible
    self.document_members(all_members)
Example #57
0
    def generate(self, more_content=None, real_modname=None,
                 check_module=False, all_members=False):
        """
        Generate reST for the object given by *self.name*, and possibly members.

        If *more_content* is given, include that content. If *real_modname* is
        given, use that module name to find attribute docs. If *check_module* is
        True, only generate if the object is defined in the module name it is
        imported from. If *all_members* is True, document all members.
        """
        if not self.parse_name():
            # need a module to import
            self.directive.warn(
                'don\'t know which module to import for autodocumenting '
                '%r (try placing a "module" or "currentmodule" directive '
                'in the document, or giving an explicit module name)'
                % self.name)
            return

        # now, import the module and get object to document
        if not self.import_object():
            return

        # If there is no real module defined, figure out which to use.
        # The real module is used in the module analyzer to look up the module
        # where the attribute documentation would actually be found in.
        # This is used for situations where you have a module that collects the
        # functions and classes of internal submodules.
        self.real_modname = real_modname or self.get_real_modname()

        # try to also get a source code analyzer for attribute docs
        try:
            self.analyzer = ModuleAnalyzer.for_module(self.real_modname)
            # parse right now, to get PycodeErrors on parsing (results will
            # be cached anyway)
            self.analyzer.find_attr_docs()
        except PycodeError:
            # no source file -- e.g. for builtin and C modules
            self.analyzer = None
            # at least add the module.__file__ as a dependency
            if hasattr(self.module, '__file__') and self.module.__file__:
                self.directive.filename_set.add(self.module.__file__)
        else:
            self.directive.filename_set.add(self.analyzer.srcname)

        # check __module__ of object (for members not given explicitly)
        if check_module:
            if not self.check_module():
                return

        # make sure that the result starts with an empty line.  This is
        # necessary for some situations where another directive preprocesses
        # reST and no starting newline is present
        self.add_line(u'', '<autodoc>')

        # format the object's signature, if any
        sig = self.format_signature()

        # generate the directive header and options, if applicable
        self.add_directive_header(sig)
        self.add_line(u'', '<autodoc>')

        # e.g. the module directive doesn't have content
        self.indent += self.content_indent

        # add all content (from docstrings, attribute docs etc.)
        self.add_content(more_content)

        # document members, if possible
        self.document_members(all_members)