Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
"""Get the duplicated types from the underlying isinstance calls.
:param astroid.BoolOp node: Node which should contain a bunch of isinstance calls.
:returns: Dictionary of the comparison objects from the isinstance calls,
to duplicate values from consecutive calls.
:rtype: dict
"""
duplicated_objects = set()
all_types = collections.defaultdict(set)
for call in node.values:
if not isinstance(call, astroid.Call) or len(call.args) != 2:
continue
inferred = utils.safe_infer(call.func)
if not inferred or not utils.is_builtin_object(inferred):
continue
if inferred.name != "isinstance":
continue
isinstance_object = call.args[0].as_string()
isinstance_types = call.args[1]
if isinstance_object in all_types:
duplicated_objects.add(isinstance_object)
if isinstance(isinstance_types, astroid.Tuple):
elems = [
class_type.as_string() for class_type in isinstance_types.itered()
]
else:
argument = safe_infer(get_argument_from_call(node, position=0))
except NoSuchArgumentError:
self.add_message('missing-reversed-argument', node=node)
else:
if argument is astroid.YES:
return
if argument is None:
# Nothing was infered.
# Try to see if we have iter().
if isinstance(node.args[0], astroid.CallFunc):
try:
func = next(node.args[0].func.infer())
except InferenceError:
return
if (getattr(func, 'name', None) == 'iter' and
is_builtin_object(func)):
self.add_message('bad-reversed-sequence', node=node)
return
if isinstance(argument, astroid.Instance):
if (argument._proxied.name == 'dict' and
is_builtin_object(argument._proxied)):
self.add_message('bad-reversed-sequence', node=node)
return
elif any(ancestor.name == 'dict' and is_builtin_object(ancestor)
for ancestor in argument._proxied.ancestors()):
# mappings aren't accepted by reversed()
self.add_message('bad-reversed-sequence', node=node)
return
for methods in REVERSED_METHODS:
for meth in methods:
# Klass
if not (callee == klass.name or callee in klass.basenames):
# Detect property assignments in the body of the class.
# This is acceptable:
#
# class A:
# b = property(lambda: self._b)
stmt = node.parent.statement()
try:
if (isinstance(stmt, astroid.Assign) and
(stmt in klass.body or klass.parent_of(stmt)) and
isinstance(stmt.value, astroid.CallFunc) and
isinstance(stmt.value.func, astroid.Name) and
stmt.value.func.name == 'property' and
is_builtin_object(next(stmt.value.func.infer(), None))):
return
except astroid.InferenceError:
pass
self.add_message('protected-access', node=node, args=attrname)
def _is_invalid_base_class(cls):
return cls.name in INVALID_BASE_CLASSES and is_builtin_object(cls)
if argument is None:
# Nothing was infered.
# Try to see if we have iter().
if isinstance(node.args[0], astroid.Call):
try:
func = next(node.args[0].func.infer())
except astroid.InferenceError:
return
if (getattr(func, 'name', None) == 'iter' and
utils.is_builtin_object(func)):
self.add_message('bad-reversed-sequence', node=node)
return
if isinstance(argument, astroid.Instance):
if (argument._proxied.name == 'dict' and
utils.is_builtin_object(argument._proxied)):
self.add_message('bad-reversed-sequence', node=node)
return
elif any(ancestor.name == 'dict' and utils.is_builtin_object(ancestor)
for ancestor in argument._proxied.ancestors()):
# Mappings aren't accepted by reversed(), unless
# they provide explicitly a __reversed__ method.
try:
argument.locals[REVERSED_PROTOCOL_METHOD]
except KeyError:
self.add_message('bad-reversed-sequence', node=node)
return
for methods in REVERSED_METHODS:
for meth in methods:
try:
argument.getattr(meth)
if argument is None:
# Nothing was infered.
# Try to see if we have iter().
if isinstance(node.args[0], astroid.CallFunc):
try:
func = next(node.args[0].func.infer())
except InferenceError:
return
if (getattr(func, 'name', None) == 'iter' and
is_builtin_object(func)):
self.add_message('bad-reversed-sequence', node=node)
return
if isinstance(argument, astroid.Instance):
if (argument._proxied.name == 'dict' and
is_builtin_object(argument._proxied)):
self.add_message('bad-reversed-sequence', node=node)
return
elif any(ancestor.name == 'dict' and is_builtin_object(ancestor)
for ancestor in argument._proxied.ancestors()):
# mappings aren't accepted by reversed()
self.add_message('bad-reversed-sequence', node=node)
return
for methods in REVERSED_METHODS:
for meth in methods:
try:
argument.getattr(meth)
except astroid.NotFoundError:
break
else:
break
def visit_call(self, node):
"""visit a CallFunc node, check if map or filter are called with a
lambda
"""
if not node.args:
return
if not isinstance(node.args[0], astroid.Lambda):
return
infered = utils.safe_infer(node.func)
if (utils.is_builtin_object(infered)
and infered.name in ['map', 'filter']):
self.add_message('deprecated-lambda', node=node)
def _has_locals_call_after_node(stmt, scope):
skip_nodes = (
astroid.FunctionDef,
astroid.ClassDef,
astroid.Import,
astroid.ImportFrom,
)
for call in scope.nodes_of_class(astroid.Call, skip_klass=skip_nodes):
inferred = utils.safe_infer(call.func)
if (
utils.is_builtin_object(inferred)
and getattr(inferred, "name", None) == "locals"
):
if stmt.lineno < call.lineno:
return True
return False
isinstance(expr.expr.func, astroid.Name) and \
expr.expr.func.name == 'super':
return
try:
klass = next(expr.expr.infer())
if klass is YES:
continue
# The infered klass can be super(), which was
# assigned to a variable and the `__init__` was called later.
#
# base = super()
# base.__init__(...)
if (isinstance(klass, astroid.Instance) and
isinstance(klass._proxied, astroid.Class) and
is_builtin_object(klass._proxied) and
klass._proxied.name == 'super'):
return
try:
del not_called_yet[klass]
except KeyError:
if klass not in to_call:
self.add_message('non-parent-init-called',
node=expr, args=klass.name)
except astroid.InferenceError:
continue
for klass, method in six.iteritems(not_called_yet):
if klass.name == 'object' or method.parent.name == 'object':
continue
self.add_message('super-init-not-called', args=klass.name, node=node)