Esempio n. 1
0
def infer_named_tuple(
        node: nodes.Call,
        context: InferenceContext | None = None) -> Iterator[nodes.ClassDef]:
    """Specific inference function for namedtuple Call node"""
    tuple_base_name: list[nodes.NodeNG] = [
        nodes.Name(name="tuple", parent=node.root())
    ]
    class_node, name, attributes = infer_func_form(node,
                                                   tuple_base_name,
                                                   context=context)
    call_site = arguments.CallSite.from_call(node, context=context)
    node = extract_node("import collections; collections.namedtuple")
    try:

        func = next(node.infer())
    except StopIteration as e:
        raise InferenceError(node=node) from e
    try:
        rename = next(call_site.infer_argument(func, "rename",
                                               context)).bool_value()
    except (InferenceError, StopIteration):
        rename = False

    try:
        attributes = _check_namedtuple_attributes(name, attributes, rename)
    except AstroidTypeError as exc:
        raise UseInferenceDefault("TypeError: " + str(exc)) from exc
    except AstroidValueError as exc:
        raise UseInferenceDefault("ValueError: " + str(exc)) from exc

    replace_args = ", ".join(f"{arg}=None" for arg in attributes)
    field_def = ("    {name} = property(lambda self: self[{index:d}], "
                 "doc='Alias for field number {index:d}')")
    field_defs = "\n".join(
        field_def.format(name=name, index=index)
        for index, name in enumerate(attributes))
    fake = AstroidBuilder(AstroidManager()).string_build(f"""
class {name}(tuple):
    __slots__ = ()
    _fields = {attributes!r}
    def _asdict(self):
        return self.__dict__
    @classmethod
    def _make(cls, iterable, new=tuple.__new__, len=len):
        return new(cls, iterable)
    def _replace(self, {replace_args}):
        return self
    def __getnewargs__(self):
        return tuple(self)
{field_defs}
    """)
    class_node.locals["_asdict"] = fake.body[0].locals["_asdict"]
    class_node.locals["_make"] = fake.body[0].locals["_make"]
    class_node.locals["_replace"] = fake.body[0].locals["_replace"]
    class_node.locals["_fields"] = fake.body[0].locals["_fields"]
    for attr in attributes:
        class_node.locals[attr] = fake.body[0].locals[attr]
    # we use UseInferenceDefault, we can't be a generator so return an iterator
    return iter([class_node])
Esempio n. 2
0
 def visit_call(self, node: nodes.Call) -> None:
     if isinstance(node.func, nodes.Name):
         name = node.func.name
         # ignore the name if it's not a builtin (i.e. not defined in the
         # locals nor globals scope)
         if not (name in node.frame(future=True) or name in node.root()):
             if name in self.linter.config.bad_functions:
                 hint = BUILTIN_HINTS.get(name)
                 args = f"{name!r}. {hint}" if hint else repr(name)
                 self.add_message("bad-builtin", node=node, args=args)
Esempio n. 3
0
def _looks_like_pattern_or_match(node: nodes.Call) -> bool:
    """Check for re.Pattern or re.Match call in stdlib.

    Match these patterns from stdlib/re.py
    ```py
    Pattern = type(...)
    Match = type(...)
    ```
    """
    return (node.root().name == "re" and isinstance(node.func, nodes.Name)
            and node.func.name == "type"
            and isinstance(node.parent, nodes.Assign)
            and len(node.parent.targets) == 1
            and isinstance(node.parent.targets[0], nodes.AssignName)
            and node.parent.targets[0].name in ("Pattern", "Match"))
Esempio n. 4
0
 def visit_call(self, node: nodes.Call) -> None:
     """Visit a Call node -> check if this is not a disallowed builtin
     call and check for * or ** use.
     """
     self._check_misplaced_format_function(node)
     if isinstance(node.func, nodes.Name):
         name = node.func.name
         # ignore the name if it's not a builtin (i.e. not defined in the
         # locals nor globals scope)
         if not (name in node.frame(future=True) or name in node.root()):
             if name == "exec":
                 self.add_message("exec-used", node=node)
             elif name == "reversed":
                 self._check_reversed(node)
             elif name == "eval":
                 self.add_message("eval-used", node=node)