예제 #1
0
def object_build_methoddescriptor(
    node: nodes.Module | nodes.ClassDef,
    member: _FunctionTypes,
    localname: str,
) -> None:
    """create astroid for a living method descriptor object"""
    # FIXME get arguments ?
    func = build_function(getattr(member, "__name__", None) or localname,
                          doc=member.__doc__)
    node.add_local_node(func, localname)
    _add_dunder_class(func, member)
예제 #2
0
    def _check_docstring(
            self, node_type: str,
            node: nodes.Module | nodes.ClassDef | nodes.FunctionDef) -> None:
        docstring = node.doc_node.value if node.doc_node else None
        if docstring and docstring[0] == "\n":
            self.add_message(
                "docstring-first-line-empty",
                node=node,
                args=(node_type, ),
                confidence=HIGH,
            )

        # Use "linecache", instead of node.as_string(), because the latter
        # looses the original form of the docstrings.

        if docstring:
            lineno = node.fromlineno + 1
            line = linecache.getline(node.root().file, lineno).lstrip()
            if line and line.find('"""') == 0:
                return
            if line and "'''" in line:
                quotes = "'''"
            elif line and line[0] == '"':
                quotes = '"'
            elif line and line[0] == "'":
                quotes = "'"
            else:
                quotes = ""
            if quotes:
                self.add_message(
                    "bad-docstring-quotes",
                    node=node,
                    args=(node_type, quotes),
                    confidence=HIGH,
                )
예제 #3
0
def object_build_function(node: nodes.Module | nodes.ClassDef,
                          member: _FunctionTypes, localname: str) -> None:
    """create astroid for a living function object"""
    args, posonlyargs, defaults, kwonlyargs = _get_args_info_from_callable(
        member)

    func = build_function(
        getattr(member, "__name__", None) or localname,
        args,
        posonlyargs,
        defaults,
        member.__doc__,
        kwonlyargs=kwonlyargs,
    )

    node.add_local_node(func, localname)
예제 #4
0
def _base_class_object_build(
    node: nodes.Module | nodes.ClassDef,
    member: type,
    basenames: list[str],
    name: str | None = None,
    localname: str | None = None,
) -> nodes.ClassDef:
    """create astroid for a living class object, with a given set of base names
    (e.g. ancestors)
    """
    class_name = name or getattr(member, "__name__", None) or localname
    assert isinstance(class_name, str)
    klass = build_class(
        class_name,
        basenames,
        member.__doc__,
    )
    klass._newstyle = isinstance(member, type)
    node.add_local_node(klass, localname)
    try:
        # limit the instantiation trick since it's too dangerous
        # (such as infinite test execution...)
        # this at least resolves common case such as Exception.args,
        # OSError.errno
        if issubclass(member, Exception):
            instdict = member().__dict__
        else:
            raise TypeError
    except TypeError:
        pass
    else:
        for item_name, obj in instdict.items():
            valnode = nodes.EmptyNode()
            valnode.object = obj
            valnode.parent = klass
            valnode.lineno = 1
            klass.instance_attrs[item_name] = [valnode]
    return klass
예제 #5
0
 def object_build(self, node: nodes.Module | nodes.ClassDef,
                  obj: types.ModuleType | type) -> None:
     """recursive method which create a partial ast from real objects
     (only function, class, and method are handled)
     """
     if obj in self._done:
         return None
     self._done[obj] = node
     for name in dir(obj):
         # inspect.ismethod() and inspect.isbuiltin() in PyPy return
         # the opposite of what they do in CPython for __class_getitem__.
         pypy__class_getitem__ = IS_PYPY and name == "__class_getitem__"
         try:
             with warnings.catch_warnings():
                 warnings.simplefilter("ignore")
                 member = getattr(obj, name)
         except (AttributeError):
             # damned ExtensionClass.Base, I know you're there !
             attach_dummy_node(node, name)
             continue
         if inspect.ismethod(member) and not pypy__class_getitem__:
             member = member.__func__
         if inspect.isfunction(member):
             _build_from_function(node, name, member, self._module)
         elif inspect.isbuiltin(member) or pypy__class_getitem__:
             if self.imported_member(node, member, name):
                 continue
             object_build_methoddescriptor(node, member, name)
         elif inspect.isclass(member):
             if self.imported_member(node, member, name):
                 continue
             if member in self._done:
                 class_node = self._done[member]
                 assert isinstance(class_node, nodes.ClassDef)
                 if class_node not in node.locals.get(name, ()):
                     node.add_local_node(class_node, name)
             else:
                 class_node = object_build_class(node, member, name)
                 # recursion
                 self.object_build(class_node, member)
             if name == "__class__" and class_node.parent is None:
                 class_node.parent = self._done[self._module]
         elif inspect.ismethoddescriptor(member):
             object_build_methoddescriptor(node, member, name)
         elif inspect.isdatadescriptor(member):
             object_build_datadescriptor(node, member, name)
         elif isinstance(member, _CONSTANTS):
             attach_const_node(node, name, member)
         elif inspect.isroutine(member):
             # This should be called for Jython, where some builtin
             # methods aren't caught by isbuiltin branch.
             _build_from_function(node, name, member, self._module)
         elif _safe_has_attribute(member, "__all__"):
             module = build_module(name)
             _attach_local_node(node, module, name)
             # recursion
             self.object_build(module, member)
         else:
             # create an empty node so that the name is actually defined
             attach_dummy_node(node, name, member)
     return None