def register_builtin_transform(transform, builtin_name): """Register a new transform function for the given *builtin_name*. The transform function must accept two parameters, a node and an optional context. """ def _transform_wrapper(node, context=None): result = transform(node, context=context) if result: if not result.parent: # Let the transformation function determine # the parent for its result. Otherwise, # we set it to be the node we transformed from. result.parent = node if result.lineno is None: result.lineno = node.lineno # Can be a 'Module' see https://github.com/PyCQA/pylint/issues/4671 # We don't have a regression test on this one: tread carefully if hasattr(result, "col_offset") and result.col_offset is None: result.col_offset = node.col_offset return iter([result]) AstroidManager().register_transform( nodes.Call, inference_tip(_transform_wrapper), partial(_builtin_filter_predicate, builtin_name=builtin_name), )
def _initialize_node_visitors(cls, stats, rel_file_path): initialized_node_visitors = [] for ( node, node_visitor_function, predicate, inferences, ) in cls.node_visitor_registry: node_visitor_obj = NodeVisitor(stats, rel_file_path) if inferences is not None: for inference in inferences: node_visitor_obj.register_transform( inference.node, inference_tip(inference.fn), inference.predicate, ) node_visitor_obj.register_transform( node, node_visitor_function, predicate, ) initialized_node_visitors.append(node_visitor_obj) return initialized_node_visitors
def register_builtin_transform(transform, builtin_name): """Register a new transform function for the given *builtin_name*. The transform function must accept two parameters, a node and an optional context. """ def _transform_wrapper(node, context=None): result = transform(node, context=context) if result: if not result.parent: # Let the transformation function determine # the parent for its result. Otherwise, # we set it to be the node we transformed from. result.parent = node if result.lineno is None: result.lineno = node.lineno if result.col_offset is None: result.col_offset = node.col_offset return iter([result]) MANAGER.register_transform( nodes.Call, inference_tip(_transform_wrapper), partial(_builtin_filter_predicate, builtin_name=builtin_name), )
def use_inferences(*inference_tips): transform_args = [(cls.node_class, astroid.inference_tip(cls.infer), cls.filter) for cls in inference_tips] for args in transform_args: astroid.MANAGER.register_transform(*args) yield for args in transform_args: astroid.MANAGER.unregister_transform(*args)
def register_builtin_transform(transform, builtin_name): """Register a new transform function for the given *builtin_name*. The transform function must accept two parameters, a node and an optional context. """ def _transform_wrapper(node, context=None): result = transform(node, context=context) if result: result.parent = node result.lineno = node.lineno result.col_offset = node.col_offset return iter([result]) MANAGER.register_transform( nodes.CallFunc, inference_tip(_transform_wrapper), lambda n: (isinstance(n.func, nodes.Name) and n.func.name == builtin_name))
def register_builtin_transform(transform, builtin_name): """Register a new transform function for the given *builtin_name*. The transform function must accept two parameters, a node and an optional context. """ def _transform_wrapper(node, context=None): result = transform(node, context=context) if result: result.parent = node result.lineno = node.lineno result.col_offset = node.col_offset return iter([result]) MANAGER.register_transform(nodes.CallFunc, inference_tip(_transform_wrapper), lambda n: (isinstance(n.func, nodes.Name) and n.func.name == builtin_name))
def test_deprecated_no_qname_on_unexpected_nodes(self) -> None: """Test that we don't crash on nodes which don't have a qname method. While this test might seem weird since it uses a transform, it's actually testing a crash that happened in production, but there was no way to retrieve the code for which this occurred (how an AssignAttr got to be the result of a function inference beats me..)""" def infer_func( node: Name, context: Optional[Any] = None ) -> Iterator[Union[Iterator, Iterator[AssignAttr]]]: # pylint: disable=unused-argument new_node = nodes.AssignAttr(attrname="alpha", parent=node) yield new_node manager = astroid.MANAGER transform = astroid.inference_tip(infer_func) with _add_transform(manager, nodes.Name, transform): node = astroid.extract_node(""" call_something() """) with self.assertNoMessages(): self.checker.visit_call(node)
def test_deprecated_no_qname_on_unexpected_nodes(self): # Test that we don't crash on nodes which don't have # a qname method. While this test might seem weird since # it uses a transform, it's actually testing a crash that # happened in production, but there was no way to retrieve # the code for which this occurred (how an AssignAttr # got to be the result of a function inference # beats me..) def infer_func(node, context=None): # pylint: disable=unused-argument new_node = astroid.AssignAttr() new_node.parent = node yield new_node manager = astroid.MANAGER transform = astroid.inference_tip(infer_func) with _add_transform(manager, astroid.Name, transform): node = astroid.extract_node(""" call_something() """) with self.assertNoMessages(): self.checker.visit_call(node)
def test_deprecated_no_qname_on_unexpected_nodes(self): # Test that we don't crash on nodes which don't have # a qname method. While this test might seem weird since # it uses a transform, it's actually testing a crash that # happened in production, but there was no way to retrieve # the code for which this occurred (how an AssignAttr # got to be the result of a function inference # beats me..) def infer_func(node, context=None): new_node = astroid.AssignAttr() new_node.parent = node yield new_node manager = astroid.MANAGER transform = astroid.inference_tip(infer_func) with _add_transform(manager, astroid.Name, transform): node = astroid.extract_node(''' call_something() ''') with self.assertNoMessages(): self.checker.visit_call(node)
if _looks_like_functools_member(decorator, "lru_cache"): return True return False def _looks_like_functools_member(node, member): """Check if the given Call node is a functools.partial call""" if isinstance(node.func, astroid.Name): return node.func.name == member elif isinstance(node.func, astroid.Attribute): return ( node.func.attrname == member and isinstance(node.func.expr, astroid.Name) and node.func.expr.name == "functools" ) _looks_like_partial = partial(_looks_like_functools_member, member="partial") MANAGER.register_transform( astroid.FunctionDef, _transform_lru_cache, _looks_like_lru_cache ) MANAGER.register_transform( astroid.Call, astroid.inference_tip(_functools_partial_inference), _looks_like_partial, )
except InferenceError: raise UseInferenceDefault try: mro_type = next(node.args[1].infer(context=context)) except InferenceError: raise UseInferenceDefault if mro_pointer is YES or mro_type is YES: # No way we could understand this. raise UseInferenceDefault super_obj = objects.Super(mro_pointer=mro_pointer, mro_type=mro_type, self_class=cls, scope=scope) super_obj.parent = node return iter([super_obj]) # Builtins inference MANAGER.register_transform(nodes.Call, inference_tip(infer_super), lambda n: (isinstance(n.func, nodes.Name) and n.func.name == 'super')) register_builtin_transform(infer_tuple, 'tuple') register_builtin_transform(infer_set, 'set') register_builtin_transform(infer_list, 'list') register_builtin_transform(infer_dict, 'dict') register_builtin_transform(infer_frozenset, 'frozenset')
return _build_dict_with_elements([]) # Builtins inference register_builtin_transform(infer_bool, "bool") register_builtin_transform(infer_super, "super") register_builtin_transform(infer_callable, "callable") register_builtin_transform(infer_property, "property") register_builtin_transform(infer_getattr, "getattr") register_builtin_transform(infer_hasattr, "hasattr") register_builtin_transform(infer_tuple, "tuple") register_builtin_transform(infer_set, "set") register_builtin_transform(infer_list, "list") register_builtin_transform(infer_dict, "dict") register_builtin_transform(infer_frozenset, "frozenset") register_builtin_transform(infer_type, "type") register_builtin_transform(infer_slice, "slice") register_builtin_transform(infer_isinstance, "isinstance") register_builtin_transform(infer_issubclass, "issubclass") register_builtin_transform(infer_len, "len") register_builtin_transform(infer_str, "str") register_builtin_transform(infer_int, "int") register_builtin_transform(infer_dict_fromkeys, "dict.fromkeys") # Infer object.__new__ calls MANAGER.register_transform( nodes.ClassDef, inference_tip(_infer_object__new__decorator), _infer_object__new__decorator_check, )
return node.name == "type" return False def infer_type_sub(node, context=None): """ Infer a type[...] subscript :param node: node to infer :type node: astroid.node_classes.NodeNG :param context: inference context :type context: astroid.context.InferenceContext :return: the inferred node :rtype: nodes.NodeNG """ node_scope, _ = node.scope().lookup("type") if node_scope.qname() != "builtins": raise UseInferenceDefault() class_src = """ class type: def __class_getitem__(cls, key): return cls """ node = extract_node(class_src) return node.infer(context=context) if PY39: MANAGER.register_transform(nodes.Name, inference_tip(infer_type_sub), _looks_like_type_subscript)
def infer_arg(node, context=None): if not isinstance(node.parent, nodes.Arguments): raise UseInferenceDefault() if not isinstance(node.parent.parent, nodes.Function): raise UseInferenceDefault() func = node.parent.parent docstring = func.doc if docstring is None: raise UseInferenceDefault() doctree = etree.fromstring(publish_doctree(docstring).asdom().toxml()) field_lists = doctree.findall(".//field_list") fields = [f for field_list in field_lists for f in field_list.findall('field')] if fields: for field in fields: field_name = field.findall("field_name")[0].text field_body = field.findall("field_body")[0].findall("paragraph")[0].text if field_name == "type %s" % node.name: return parse_node(node, context, field_body) raise UseInferenceDefault() MANAGER.register_transform(nodes.CallFunc, inference_tip(infer_rtype)) MANAGER.register_transform(nodes.AssName, inference_tip(infer_arg))
# node is a CallFunc node, class name as first argument and generated class # attributes as second argument if len(node.args) != 2: # something weird here, go back to class implementation raise UseInferenceDefault() # namedtuple list of attributes can be a list of strings or a # whitespace-separate string try: name = node.args[0].value try: attributes = node.args[1].value.split() except AttributeError: attributes = [const.value for const in node.args[1].elts] except AttributeError: raise UseInferenceDefault() # we want to return a Class node instance with proper attributes set class_node = nodes.Class(name, 'docstring') # set base class=tuple class_node.bases.append(nodes.Tuple._proxied) # XXX add __init__(*attributes) method for attr in attributes: fake_node = nodes.EmptyNode() fake_node.parent = class_node class_node.instance_attrs[attr] = [fake_node] # we use UseInferenceDefault, we can't be a generator so return an iterator return iter([class_node]) MANAGER.register_transform(nodes.CallFunc, inference_tip(infer_named_tuple), AsStringRegexpPredicate('namedtuple', 'func'))
names = [] for elt in node.args[1].elts: if not isinstance(elt, (nodes.List, nodes.Tuple)): raise UseInferenceDefault if len(elt.elts) != 2: raise UseInferenceDefault names.append(elt.elts[0].as_string()) typename = node.args[0].as_string() node = extract_node('namedtuple(%(typename)s, (%(fields)s,)) ' % {'typename': typename, 'fields': ",".join(names)}) return infer_named_tuple(node, context) MANAGER.register_transform( nodes.Call, inference_tip(infer_named_tuple), _looks_like_namedtuple, ) MANAGER.register_transform( nodes.Call, inference_tip(infer_enum), _looks_like_enum, ) MANAGER.register_transform( nodes.ClassDef, infer_enum_class, predicate=lambda cls: any(basename for basename in cls.basenames if basename in ENUM_BASE_NAMES) ) MANAGER.register_transform( nodes.ClassDef, inference_tip(infer_typing_namedtuple_class), _has_namedtuple_base,
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"}) def infer_pattern_match(node: nodes.Call, ctx: Optional[context.InferenceContext] = None): """Infer re.Pattern and re.Match as classes. For PY39+ add `__class_getitem__`.""" class_def = nodes.ClassDef( name=node.parent.targets[0].name, lineno=node.lineno, col_offset=node.col_offset, parent=node.parent, ) if PY39_PLUS: func_to_add = extract_node(CLASS_GETITEM_TEMPLATE) class_def.locals["__class_getitem__"] = [func_to_add] return iter([class_def]) if PY37_PLUS: AstroidManager().register_transform(nodes.Call, inference_tip(infer_pattern_match), _looks_like_pattern_or_match)
# attributes as second argument if len(node.args) != 2: # something weird here, go back to class implementation raise UseInferenceDefault() # namedtuple list of attributes can be a list of strings or a # whitespace-separate string try: name = node.args[0].value try: attributes = node.args[1].value.split() except AttributeError: attributes = [const.value for const in node.args[1].elts] except AttributeError: raise UseInferenceDefault() # we want to return a Class node instance with proper attributes set class_node = nodes.Class(name, "docstring") # set base class=tuple class_node.bases.append(nodes.Tuple._proxied) # XXX add __init__(*attributes) method for attr in attributes: fake_node = nodes.EmptyNode() fake_node.parent = class_node class_node.instance_attrs[attr] = [fake_node] # we use UseInferenceDefault, we can't be a generator so return an iterator return iter([class_node]) MANAGER.register_transform( nodes.CallFunc, inference_tip(infer_named_tuple), AsStringRegexpPredicate("namedtuple", "func") )
raise astroid.UseInferenceDefault try: elts = random.sample(inferred_sequence.elts, length.value) except ValueError: raise astroid.UseInferenceDefault new_node = astroid.List(lineno=node.lineno, col_offset=node.col_offset, parent=node.scope()) new_elts = [ _clone_node_with_lineno(elt, parent=new_node, lineno=new_node.lineno) for elt in elts ] new_node.postinit(new_elts) return iter((new_node, )) def _looks_like_random_sample(node): func = node.func if isinstance(func, astroid.Attribute): return func.attrname == "sample" if isinstance(func, astroid.Name): return func.name == "sample" return False MANAGER.register_transform(astroid.Call, astroid.inference_tip(infer_random_sample), _looks_like_random_sample)
] code = textwrap.dedent(''' from collections import namedtuple namedtuple({typename!r}, {fields!r}) ''').format( typename=node.name, fields=",".join(annassigns_fields) ) node = extract_node(code) return node.infer(context=context) def looks_like_typing_namedtuple(node): func = node.func if isinstance(func, nodes.Attribute): return func.attrname == 'NamedTuple' if isinstance(func, nodes.Name): return func.name == 'NamedTuple' return False MANAGER.register_transform( nodes.Call, inference_tip(infer_typing_namedtuple), looks_like_typing_namedtuple ) MANAGER.register_transform( nodes.ClassDef, inference_tip(infer_typing_namedtuple_class) )
def infer_namespace(node, context=None): callsite = arguments.CallSite.from_call(node) if not callsite.keyword_arguments: # Cannot make sense of it. raise UseInferenceDefault() class_node = nodes.ClassDef("Namespace", "docstring") class_node.parent = node.parent for attr in set(callsite.keyword_arguments): fake_node = nodes.EmptyNode() fake_node.parent = class_node fake_node.attrname = attr class_node.instance_attrs[attr] = [fake_node] return iter((class_node.instantiate_class(),)) def _looks_like_namespace(node): func = node.func if isinstance(func, nodes.Attribute): return ( func.attrname == "Namespace" and isinstance(func.expr, nodes.Name) and func.expr.name == "argparse" ) return False MANAGER.register_transform( nodes.Call, inference_tip(infer_namespace), _looks_like_namespace )
if not isinstance(elt, (nodes.List, nodes.Tuple)): raise UseInferenceDefault if len(elt.elts) != 2: raise UseInferenceDefault names.append(elt.elts[0].as_string()) typename = node.args[0].as_string() node = extract_node( "namedtuple(%(typename)s, (%(fields)s,)) " % {"typename": typename, "fields": ",".join(names)} ) return infer_named_tuple(node, context) MANAGER.register_transform( nodes.Call, inference_tip(infer_named_tuple), _looks_like_namedtuple ) MANAGER.register_transform(nodes.Call, inference_tip(infer_enum), _looks_like_enum) MANAGER.register_transform( nodes.ClassDef, infer_enum_class, predicate=lambda cls: any( basename for basename in cls.basenames if basename in ENUM_BASE_NAMES ), ) MANAGER.register_transform( nodes.ClassDef, inference_tip(infer_typing_namedtuple_class), _has_namedtuple_base ) MANAGER.register_transform( nodes.Call, inference_tip(infer_typing_namedtuple), _looks_like_typing_namedtuple )
def infer_namespace(node, context=None): callsite = arguments.CallSite.from_call(node, context=context) if not callsite.keyword_arguments: # Cannot make sense of it. raise UseInferenceDefault() class_node = nodes.ClassDef("Namespace", "docstring") class_node.parent = node.parent for attr in set(callsite.keyword_arguments): fake_node = nodes.EmptyNode() fake_node.parent = class_node fake_node.attrname = attr class_node.instance_attrs[attr] = [fake_node] return iter((class_node.instantiate_class(),)) def _looks_like_namespace(node): func = node.func if isinstance(func, nodes.Attribute): return ( func.attrname == "Namespace" and isinstance(func.expr, nodes.Name) and func.expr.name == "argparse" ) return False MANAGER.register_transform( nodes.Call, inference_tip(infer_namespace), _looks_like_namespace )
func = next(node.func.infer(context=ctx)) except (InferenceError, StopIteration) as exc: raise UseInferenceDefault from exc if ( not isinstance(func, FunctionDef) or func.qname() != "typing.cast" or len(node.args) != 2 ): raise UseInferenceDefault return node.args[1].infer(context=ctx) AstroidManager().register_transform( Call, inference_tip(infer_typing_typevar_or_newtype), looks_like_typing_typevar_or_newtype, ) AstroidManager().register_transform( Subscript, inference_tip(infer_typing_attr), _looks_like_typing_subscript ) AstroidManager().register_transform( Call, inference_tip(infer_typing_cast), _looks_like_typing_cast ) if PY39_PLUS: AstroidManager().register_transform( FunctionDef, inference_tip(infer_typedDict), _looks_like_typedDict ) elif PY38_PLUS: AstroidManager().register_transform(
targets = [stmt.target] new_targets = [] for target in targets: # Replace all the assignments with our mocked class. classdef = dedent(''' class %(name)s(%(types)s): @property def value(self): # Not the best return. return None @property def name(self): return %(name)r ''' % {'name': target.name, 'types': ', '.join(node.basenames)}) fake = AstroidBuilder(MANAGER).string_build(classdef)[target.name] fake.parent = target.parent for method in node.mymethods(): fake.locals[method.name] = [method] new_targets.append(fake.instantiate_class()) node.locals[local] = new_targets break return node MANAGER.register_transform(nodes.Call, inference_tip(infer_named_tuple), _looks_like_namedtuple) MANAGER.register_transform(nodes.Call, inference_tip(infer_enum), _looks_like_enum) MANAGER.register_transform(nodes.ClassDef, infer_enum_class)
if not isinstance(node.args[1], (List, Tuple)): raise UseInferenceDefault names = [] for elt in node.args[1].elts: if not isinstance(elt, (List, Tuple)): raise UseInferenceDefault if len(elt.elts) != 2: raise UseInferenceDefault names.append(elt.elts[0].as_string()) typename = node.args[0].as_string() node = extract_node('namedtuple(%(typename)s, (%(fields)s,)) ' % { 'typename': typename, 'fields': ",".join(names) }) return node.infer(context=context) def looks_like_typing_namedtuple(node): func = node.func if isinstance(func, nodes.Attribute): return func.attrname == 'NamedTuple' if isinstance(func, nodes.Name): return func.name == 'NamedTuple' return False MANAGER.register_transform(nodes.Call, inference_tip(infer_typing_namedtuple), looks_like_typing_namedtuple)
return node.name in TYPING_MEMBERS elif isinstance(node, nodes.Attribute): return node.attrname in TYPING_MEMBERS elif isinstance(node, nodes.Subscript): return _looks_like_typing_subscript(node.value) return False def infer_typing_attr(node, context=None): """Infer a typing.X[...] subscript""" try: value = next(node.value.infer()) except InferenceError as exc: raise UseInferenceDefault from exc if not value.qname().startswith("typing."): raise UseInferenceDefault node = extract_node(TYPING_TYPE_TEMPLATE.format(value.qname().split(".")[-1])) return node.infer(context=context) MANAGER.register_transform( nodes.Call, inference_tip(infer_typing_typevar_or_newtype), looks_like_typing_typevar_or_newtype, ) MANAGER.register_transform( nodes.Subscript, inference_tip(infer_typing_attr), _looks_like_typing_subscript )
if "id" not in cls.locals: cls.locals["id"] = [nodes.ClassDef("id", None)] def is_model_field(cls: ClassDef) -> bool: """ Guard to apply this transform to Model Fields only """ type_name = "tortoise.fields.base.Field" return bool(cls.is_subtype_of(type_name)) and cls.qname() != type_name def apply_type_shim(cls: ClassDef, _context: Any = None) -> Iterator[ClassDef]: """ Morphs model fields to representative type """ base_nodes: List[ClassDef] = [cls] # Use the type inference standard try: base_nodes.extend(list(cls.getattr("field_type")[0].infer())) except AstroidError: pass return iter(base_nodes) MANAGER.register_transform(nodes.ClassDef, inference_tip(apply_type_shim), is_model_field) MANAGER.register_transform(nodes.ClassDef, transform_model, is_model)
from astroid import MANAGER, arguments, nodes, inference_tip, UseInferenceDefault def infer_namespace(node, context=None): callsite = arguments.CallSite.from_call(node, context=context) if not callsite.keyword_arguments: # Cannot make sense of it. raise UseInferenceDefault() class_node = nodes.ClassDef("Namespace", "docstring") class_node.parent = node.parent for attr in set(callsite.keyword_arguments): fake_node = nodes.EmptyNode() fake_node.parent = class_node fake_node.attrname = attr class_node.instance_attrs[attr] = [fake_node] return iter((class_node.instantiate_class(), )) def _looks_like_namespace(node): func = node.func if isinstance(func, nodes.Attribute): return (func.attrname == "Namespace" and isinstance(func.expr, nodes.Name) and func.expr.name == "argparse") return False MANAGER.register_transform(nodes.Call, inference_tip(infer_namespace), _looks_like_namespace)
return node.attrname in TYPING_MEMBERS elif isinstance(node, nodes.Subscript): return _looks_like_typing_subscript(node.value) return False def infer_typing_attr(node, context=None): """Infer a typing.X[...] subscript""" try: value = next(node.value.infer()) except InferenceError as exc: raise UseInferenceDefault from exc if not value.qname().startswith('typing.'): raise UseInferenceDefault node = extract_node(TYPING_TYPE_TEMPLATE.format(value.qname().split('.')[-1])) return node.infer(context=context) MANAGER.register_transform( nodes.Call, inference_tip(infer_typing_typevar_or_newtype), looks_like_typing_typevar_or_newtype ) MANAGER.register_transform( nodes.Subscript, inference_tip(infer_typing_attr), _looks_like_typing_subscript, )
from astroid import MANAGER, nodes, inference_tip, BRAIN_MODULES_DIR sys.path.append(BRAIN_MODULES_DIR) import py2stdlib logger = logging.getLogger(__name__) # pylint: disable=invalid-name def _looks_like_nt_with_defaults(node): func = node.func if type(func) == nodes.Getattr: # pylint: disable=unidiomatic-typecheck return func.attrname == 'namedtuple_with_defaults' elif type(func) == nodes.Name: # pylint: disable=unidiomatic-typecheck return func.name == 'namedtuple_with_defaults' return False def nt_with_defaults_transform(node, *args, **kwargs): node.args = node.args[:2] return py2stdlib.infer_named_tuple(node, *args, **kwargs) def register(_linter): pass MANAGER.register_transform(nodes.CallFunc, inference_tip(nt_with_defaults_transform), _looks_like_nt_with_defaults)
raise astroid.UseInferenceDefault try: elts = random.sample(inferred_sequence.elts, length.value) except ValueError: raise astroid.UseInferenceDefault new_node = astroid.List( lineno=node.lineno, col_offset=node.col_offset, parent=node.scope() ) new_elts = [ _clone_node_with_lineno(elt, parent=new_node, lineno=new_node.lineno) for elt in elts ] new_node.postinit(new_elts) return iter((new_node,)) def _looks_like_random_sample(node): func = node.func if isinstance(func, astroid.Attribute): return func.attrname == "sample" if isinstance(func, astroid.Name): return func.name == "sample" return False MANAGER.register_transform( astroid.Call, astroid.inference_tip(infer_random_sample), _looks_like_random_sample )
if not isinstance(decorator, astroid.Call): continue func = helpers.safe_infer(decorator.func) if func in (None, astroid.Uninferable): continue if isinstance(func, astroid.FunctionDef) and func.qname() == LRU_CACHE: return True return False def _looks_like_functools_partial(node): """Check if the given Call node is a functools.partial call""" if isinstance(node.func, astroid.Name): return node.func.name == "partial" elif isinstance(node.func, astroid.Attribute): return (node.func.attrname == "partial" and isinstance(node.func.expr, astroid.Name) and node.func.expr.name == "functools") MANAGER.register_transform(astroid.FunctionDef, _transform_lru_cache, _looks_like_lru_cache) MANAGER.register_transform( astroid.Call, astroid.inference_tip(_functools_partial_inference), _looks_like_functools_partial, )
if not isinstance(klass, ClassDef): yield Uninferable elif klass.root().name in { "typing", "_collections_abc", "", }: # "" because of synthetic nodes in brain_typing.py if klass.name in _INFERABLE_TYPING_TYPES: yield klass.instantiate_class() else: yield Uninferable else: yield klass.instantiate_class() if PY37_PLUS: AstroidManager().register_transform(ClassDef, dataclass_transform, is_decorated_with_dataclass) AstroidManager().register_transform( Call, inference_tip(infer_dataclass_field_call, raise_on_overwrite=True), _looks_like_dataclass_field_call, ) AstroidManager().register_transform( Unknown, inference_tip(infer_dataclass_attribute, raise_on_overwrite=True), _looks_like_dataclass_attribute, )
def add_transforms(manager): manager.register_transform(nodes.Class, inference_tip(apply_type_shim), is_model_or_form_field)
raise UseInferenceDefault try: func = next(node.func.infer(context=ctx)) except (InferenceError, StopIteration) as exc: raise UseInferenceDefault from exc if (not isinstance(func, FunctionDef) or func.qname() != "typing.cast" or len(node.args) != 2): raise UseInferenceDefault return node.args[1].infer(context=ctx) AstroidManager().register_transform( Call, inference_tip(infer_typing_typevar_or_newtype), looks_like_typing_typevar_or_newtype, ) AstroidManager().register_transform(Subscript, inference_tip(infer_typing_attr), _looks_like_typing_subscript) AstroidManager().register_transform(Call, inference_tip(infer_typing_cast), _looks_like_typing_cast) if PY39_PLUS: AstroidManager().register_transform(FunctionDef, inference_tip(infer_typedDict), _looks_like_typedDict) elif PY38_PLUS: AstroidManager().register_transform(ClassDef, inference_tip(infer_old_typedDict),
def add_transform(manager): manager.register_transform(nodes.Call, inference_tip(infer_key_classes), is_foreignkey_in_class)
lineno=node.lineno, col_offset=node.col_offset, parent=node.scope(), ) new_elts = [ _clone_node_with_lineno( elt, parent=new_node, lineno=new_node.lineno ) for elt in elts ] new_node.postinit(new_elts) return iter((new_node, )) def _looks_like_random_sample(node): func = node.func if isinstance(func, astroid.Attribute): return func.attrname == 'sample' if isinstance(func, astroid.Name): return func.name == 'sample' return False MANAGER.register_transform( astroid.Call, astroid.inference_tip(infer_random_sample), _looks_like_random_sample, )
def setfield(self, val, dtype, offset=0): return None def setflags(self, write=None, align=None, uic=None): return None def sort(self, axis=-1, kind='quicksort', order=None): return None def squeeze(self, axis=None): return np.ndarray([0, 0]) def std(self, axis=None, dtype=None, out=None, ddof=0, keepdims=False): return np.ndarray([0, 0]) def sum(self, axis=None, dtype=None, out=None, keepdims=False): return np.ndarray([0, 0]) def swapaxes(self, axis1, axis2): return np.ndarray([0, 0]) def take(self, indices, axis=None, out=None, mode='raise'): return np.ndarray([0, 0]) def tobytes(self, order='C'): return b'' def tofile(self, fid, sep="", format="%s"): return None def tolist(self, ): return [] def tostring(self, order='C'): return b'' def trace(self, offset=0, axis1=0, axis2=1, dtype=None, out=None): return np.ndarray([0, 0]) def transpose(self, *axes): return np.ndarray([0, 0]) def var(self, axis=None, dtype=None, out=None, ddof=0, keepdims=False): return np.ndarray([0, 0]) def view(self, dtype=None, type=None): return np.ndarray([0, 0]) """ node = astroid.extract_node(ndarray) return node.infer(context=context) def _looks_like_numpy_ndarray(node): return isinstance(node, astroid.Attribute) and node.attrname == "ndarray" astroid.MANAGER.register_transform( astroid.Attribute, astroid.inference_tip(infer_numpy_ndarray), _looks_like_numpy_ndarray, )
callsite = arguments.CallSite.from_call(node) if not callsite.keyword_arguments: # Cannot make sense of it. raise UseInferenceDefault() class_node = nodes.ClassDef('Namespace', 'docstring') class_node.parent = node.parent for attr in set(callsite.keyword_arguments): fake_node = nodes.EmptyNode() fake_node.parent = class_node fake_node.attrname = attr class_node.instance_attrs[attr] = [fake_node] return iter((class_node.instantiate_class(), )) def _looks_like_namespace(node): func = node.func if isinstance(func, nodes.Attribute): return ( func.attrname == 'Namespace' and isinstance(func.expr, nodes.Name) and func.expr.name == 'argparse' ) return False MANAGER.register_transform( nodes.Call, inference_tip(infer_namespace), _looks_like_namespace, )
"array": """def array(object, dtype=None, copy=True, order='K', subok=False, ndmin=0): return numpy.ndarray([0, 0])""", "dot": """def dot(a, b, out=None): return numpy.ndarray([0, 0])""", "empty_like": """def empty_like(a, dtype=None, order='K', subok=True): return numpy.ndarray((0, 0))""", "concatenate": """def concatenate(arrays, axis=None, out=None): return numpy.ndarray((0, 0))""", "where": """def where(condition, x=None, y=None): return numpy.ndarray([0, 0])""", "empty": """def empty(shape, dtype=float, order='C'): return numpy.ndarray([0, 0])""", "zeros": """def zeros(shape, dtype=float, order='C'): return numpy.ndarray([0, 0])""", } for method_name, function_src in METHODS_TO_BE_INFERRED.items(): inference_function = functools.partial(infer_numpy_member, function_src) astroid.MANAGER.register_transform( astroid.Attribute, astroid.inference_tip(inference_function), functools.partial(looks_like_numpy_member, method_name), )
def _infer_object__new__decorator(node, context=None): if not node.decorators: raise UseInferenceDefault for decorator in node.decorators.nodes: if isinstance(decorator, nodes.Attribute): if decorator.as_string() == OBJECT_DUNDER_NEW: return iter((node.instantiate_class(),)) raise UseInferenceDefault # Builtins inference register_builtin_transform(infer_bool, 'bool') register_builtin_transform(infer_super, 'super') register_builtin_transform(infer_callable, 'callable') register_builtin_transform(infer_getattr, 'getattr') register_builtin_transform(infer_hasattr, 'hasattr') register_builtin_transform(infer_tuple, 'tuple') register_builtin_transform(infer_set, 'set') register_builtin_transform(infer_list, 'list') register_builtin_transform(infer_dict, 'dict') register_builtin_transform(infer_frozenset, 'frozenset') register_builtin_transform(infer_type, 'type') register_builtin_transform(infer_slice, 'slice') # Infer object.__new__ calls MANAGER.register_transform( nodes.ClassDef, inference_tip(_infer_object__new__decorator) )
raise UseInferenceDefault if len(elt.elts) != 2: raise UseInferenceDefault names.append(elt.elts[0].as_string()) typename = node.args[0].as_string() if names: field_names = "({},)".format(",".join(names)) else: field_names = "''" node = extract_node("namedtuple({typename}, {fields})".format( typename=typename, fields=field_names)) return infer_named_tuple(node, context) MANAGER.register_transform(nodes.Call, inference_tip(infer_named_tuple), _looks_like_namedtuple) MANAGER.register_transform(nodes.Call, inference_tip(infer_enum), _looks_like_enum) MANAGER.register_transform( nodes.ClassDef, infer_enum_class, predicate=lambda cls: any(basename for basename in cls.basenames if basename in ENUM_BASE_NAMES), ) MANAGER.register_transform(nodes.ClassDef, inference_tip(infer_typing_namedtuple_class), _has_namedtuple_base) MANAGER.register_transform(nodes.Call, inference_tip(infer_typing_namedtuple), _looks_like_typing_namedtuple)
raise UseInferenceDefault names.append(elt.elts[0].as_string()) typename = node.args[0].as_string() if names: field_names = "({},)".format(",".join(names)) else: field_names = "''" node = extract_node( "namedtuple({typename}, {fields})".format(typename=typename, fields=field_names) ) return infer_named_tuple(node, context) MANAGER.register_transform( nodes.Call, inference_tip(infer_named_tuple), _looks_like_namedtuple ) MANAGER.register_transform(nodes.Call, inference_tip(infer_enum), _looks_like_enum) MANAGER.register_transform( nodes.ClassDef, infer_enum_class, predicate=lambda cls: any( basename for basename in cls.basenames if basename in ENUM_BASE_NAMES ), ) MANAGER.register_transform( nodes.ClassDef, inference_tip(infer_typing_namedtuple_class), _has_namedtuple_base ) MANAGER.register_transform( nodes.Call, inference_tip(infer_typing_namedtuple), _looks_like_typing_namedtuple )
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")) def infer_pattern_match(node: nodes.Call, ctx: context.InferenceContext = None): """Infer re.Pattern and re.Match as classes. For PY39+ add `__class_getitem__`.""" class_def = nodes.ClassDef( name=node.parent.targets[0].name, lineno=node.lineno, col_offset=node.col_offset, parent=node.parent, ) if PY39: func_to_add = astroid.extract_node(CLASS_GETITEM_TEMPLATE) class_def.locals["__class_getitem__"] = [func_to_add] return iter([class_def]) if PY37: MANAGER.register_transform(nodes.Call, inference_tip(infer_pattern_match), _looks_like_pattern_or_match)
def add_transform(manager): manager.register_transform(nodes.CallFunc, inference_tip(infer_key_classes), is_foreignkey_in_class)