Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
cdce8p committed Apr 28, 2021
1 parent 28c093c commit 559d778
Show file tree
Hide file tree
Showing 26 changed files with 443 additions and 281 deletions.
8 changes: 6 additions & 2 deletions pylint/checkers/async.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,12 @@ def open(self):
@checker_utils.check_messages("yield-inside-async-function")
def visit_asyncfunctiondef(self, node):
for child in node.nodes_of_class(astroid.Yield):
if child.scope() is node and (
sys.version_info[:2] == (3, 5) or isinstance(child, astroid.YieldFrom)
if (
child.scope() is node
and (
sys.version_info[:2] == (3, 5)
or isinstance(child, astroid.YieldFrom)
)
):
self.add_message("yield-inside-async-function", node=child)

Expand Down
94 changes: 57 additions & 37 deletions pylint/checkers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,9 @@ def _get_break_loop_node(break_node):
"""
loop_nodes = (astroid.For, astroid.While)
parent = break_node.parent
while not isinstance(parent, loop_nodes) or break_node in getattr(
parent, "orelse", []
while (
not isinstance(parent, loop_nodes)
or break_node in getattr(parent, "orelse", [])
):
break_node = parent
parent = parent.parent
Expand Down Expand Up @@ -363,9 +364,12 @@ def _determine_function_name_type(node: astroid.FunctionDef, config=None):
for decorator in decorators:
# If the function is a property (decorated with @property
# or @abc.abstractproperty), the name type is 'attr'.
if isinstance(decorator, astroid.Name) or (
isinstance(decorator, astroid.Attribute)
and decorator.attrname in property_names
if (
isinstance(decorator, astroid.Name)
or (
isinstance(decorator, astroid.Attribute)
and decorator.attrname in property_names
)
):
inferred = utils.safe_infer(decorator)
if (
Expand Down Expand Up @@ -623,9 +627,10 @@ def visit_starred(self, node):
def visit_functiondef(self, node):
self._check_nonlocal_and_global(node)
self._check_name_used_prior_global(node)
if not redefined_by_decorator(
node
) and not utils.is_registered_in_singledispatch_function(node):
if (
not redefined_by_decorator(node)
and not utils.is_registered_in_singledispatch_function(node)
):
self._check_redefinition(node.is_method() and "method" or "function", node)
# checks for max returns, branch, return in __init__
returns = node.nodes_of_class(
Expand Down Expand Up @@ -1266,8 +1271,9 @@ def visit_lambda(self, node):
# The body of the lambda must be a function call expression
# for the lambda to be unnecessary.
return
if isinstance(node.body.func, astroid.Attribute) and isinstance(
node.body.func.expr, astroid.Call
if (
isinstance(node.body.func, astroid.Attribute)
and isinstance(node.body.func.expr, astroid.Call)
):
# Chained call, the intermediate call might
# return something else (but we don't check that, yet).
Expand Down Expand Up @@ -1518,9 +1524,10 @@ def _check_reversed(self, node):
func = next(node.args[0].func.infer())
except astroid.InferenceError:
return
if getattr(
func, "name", None
) == "iter" and utils.is_builtin_object(func):
if (
getattr(func, "name", None) == "iter"
and utils.is_builtin_object(func)
):
self.add_message("bad-reversed-sequence", node=node)
return

Expand Down Expand Up @@ -1564,8 +1571,9 @@ def visit_with(self, node):
pairs = node.items
if pairs:
for prev_pair, pair in zip(pairs, pairs[1:]):
if isinstance(prev_pair[1], astroid.AssignName) and (
pair[1] is None and not isinstance(pair[0], astroid.Call)
if (
isinstance(prev_pair[1], astroid.AssignName)
and (pair[1] is None and not isinstance(pair[0], astroid.Call))
):
# Don't emit a message if the second is a function call
# there's no way that can be mistaken for a name assignment.
Expand Down Expand Up @@ -1983,15 +1991,17 @@ def visit_assignname(self, node):
self._check_name("class", node.name, node)
# Don't emit if the name redefines an import
# in an ImportError except handler.
elif not _redefines_import(node) and isinstance(
utils.safe_infer(assign_type.value), astroid.Const
elif (
not _redefines_import(node)
and isinstance(utils.safe_infer(assign_type.value), astroid.Const)
):
self._check_name("const", node.name, node)
elif isinstance(assign_type, astroid.ExceptHandler):
self._check_name("variable", node.name, node)
elif isinstance(
assign_type, astroid.AnnAssign
) and utils.is_assign_name_annotated_with(node, "Final"):
elif (
isinstance(assign_type, astroid.AnnAssign)
and utils.is_assign_name_annotated_with(node, "Final")
):
self._check_name("const", node.name, node)
elif isinstance(frame, astroid.FunctionDef):
# global introduced variable aren't in the function locals
Expand Down Expand Up @@ -2039,13 +2049,15 @@ def _raise_name_warning(
self.stats["badname_" + node_type] += 1

def _name_allowed_by_regex(self, name: str) -> bool:
return name in self.config.good_names or any(
pattern.match(name) for pattern in self._good_names_rgxs_compiled
return (
name in self.config.good_names
or any(pattern.match(name) for pattern in self._good_names_rgxs_compiled)
)

def _name_disallowed_by_regex(self, name: str) -> bool:
return name in self.config.bad_names or any(
pattern.match(name) for pattern in self._bad_names_rgxs_compiled
return (
name in self.config.bad_names
or any(pattern.match(name) for pattern in self._bad_names_rgxs_compiled)
)

def _check_name(self, node_type, name, node, confidence=interfaces.HIGH):
Expand Down Expand Up @@ -2202,8 +2214,9 @@ def visit_functiondef(self, node):
)
# check if node is from a method overridden by its ancestor
for ancestor in node.parent.frame().ancestors():
if node.name in ancestor and isinstance(
ancestor[node.name], astroid.FunctionDef
if (
node.name in ancestor
and isinstance(ancestor[node.name], astroid.FunctionDef)
):
overridden = True
break
Expand Down Expand Up @@ -2246,8 +2259,9 @@ def _check_docstring(
):
# Most likely a string with a format call. Let's see.
func = utils.safe_infer(node.body[0].value.func)
if isinstance(func, astroid.BoundMethod) and isinstance(
func.bound, astroid.Instance
if (
isinstance(func, astroid.BoundMethod)
and isinstance(func.bound, astroid.Instance)
):
# Strings.
if func.bound.name in ("str", "unicode", "bytes"):
Expand Down Expand Up @@ -2279,9 +2293,12 @@ class PassChecker(_BasicChecker):

@utils.check_messages("unnecessary-pass")
def visit_pass(self, node):
if len(node.parent.child_sequence(node)) > 1 or (
isinstance(node.parent, (astroid.ClassDef, astroid.FunctionDef))
and (node.parent.doc is not None)
if (
len(node.parent.child_sequence(node)) > 1
or (
isinstance(node.parent, (astroid.ClassDef, astroid.FunctionDef))
and (node.parent.doc is not None)
)
):
self.add_message("unnecessary-pass", node=node)

Expand Down Expand Up @@ -2374,8 +2391,9 @@ def _check_singleton_comparison(
singleton_values = (True, False, None)

def _is_singleton_const(node) -> bool:
return isinstance(node, astroid.Const) and any(
node.value is value for value in singleton_values
return (
isinstance(node, astroid.Const)
and any(node.value is value for value in singleton_values)
)

if _is_singleton_const(left_value):
Expand Down Expand Up @@ -2499,13 +2517,15 @@ def _check_logical_tautology(self, node):
left_operand = node.left
right_operand = node.ops[0][1]
operator = node.ops[0][0]
if isinstance(left_operand, astroid.Const) and isinstance(
right_operand, astroid.Const
if (
isinstance(left_operand, astroid.Const)
and isinstance(right_operand, astroid.Const)
):
left_operand = left_operand.value
right_operand = right_operand.value
elif isinstance(left_operand, astroid.Name) and isinstance(
right_operand, astroid.Name
elif (
isinstance(left_operand, astroid.Name)
and isinstance(right_operand, astroid.Name)
):
left_operand = left_operand.name
right_operand = right_operand.name
Expand Down
90 changes: 55 additions & 35 deletions pylint/checkers/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,9 @@ def _is_attribute_property(name, klass):
inferred = next(attr.infer())
except astroid.InferenceError:
continue
if isinstance(inferred, astroid.FunctionDef) and decorated_with_property(
inferred
if (
isinstance(inferred, astroid.FunctionDef)
and decorated_with_property(inferred)
):
return True
if inferred.pytype() != property_name:
Expand Down Expand Up @@ -825,13 +826,15 @@ def _check_proper_bases(self, node):
ancestor = safe_infer(base)
if not ancestor:
continue
if isinstance(ancestor, astroid.Instance) and ancestor.is_subtype_of(
f"{astroid.bases.BUILTINS}.type"
if (
isinstance(ancestor, astroid.Instance)
and ancestor.is_subtype_of(f"{astroid.bases.BUILTINS}.type")
):
continue

if not isinstance(ancestor, astroid.ClassDef) or _is_invalid_base_class(
ancestor
if (
not isinstance(ancestor, astroid.ClassDef)
or _is_invalid_base_class(ancestor)
):
self.add_message("inherit-non-class", args=base.as_string(), node=node)

Expand Down Expand Up @@ -947,10 +950,14 @@ def visit_functiondef(self, node):

if node.decorators:
for decorator in node.decorators.nodes:
if isinstance(decorator, astroid.Attribute) and decorator.attrname in (
"getter",
"setter",
"deleter",
if (
isinstance(decorator, astroid.Attribute)
and decorator.attrname
in (
"getter",
"setter",
"deleter",
)
):
# attribute affectation will call this method, not hiding it
return
Expand Down Expand Up @@ -1126,12 +1133,14 @@ def _check_property_with_parameters(self, node):
self.add_message("property-with-parameters", node=node)

def _check_invalid_overridden_method(self, function_node, parent_function_node):
parent_is_property = decorated_with_property(
parent_function_node
) or is_property_setter_or_deleter(parent_function_node)
current_is_property = decorated_with_property(
function_node
) or is_property_setter_or_deleter(function_node)
parent_is_property = (
decorated_with_property(parent_function_node)
or is_property_setter_or_deleter(parent_function_node)
)
current_is_property = (
decorated_with_property(function_node)
or is_property_setter_or_deleter(function_node)
)
if parent_is_property and not current_is_property:
self.add_message(
"invalid-overridden-method",
Expand Down Expand Up @@ -1197,8 +1206,9 @@ def _check_slots_elt(self, elt, node):
for inferred in elt.infer():
if inferred is astroid.Uninferable:
continue
if not isinstance(inferred, astroid.Const) or not isinstance(
inferred.value, str
if (
not isinstance(inferred, astroid.Const)
or not isinstance(inferred.value, str)
):
self.add_message(
"invalid-slots-object", args=inferred.as_string(), node=elt
Expand Down Expand Up @@ -1264,9 +1274,10 @@ class member from outside its class (but ignore __special__
self._check_protected_attribute_access(node)

def visit_assignattr(self, node):
if isinstance(
node.assign_type(), astroid.AugAssign
) and self._uses_mandatory_method_param(node):
if (
isinstance(node.assign_type(), astroid.AugAssign)
and self._uses_mandatory_method_param(node)
):
self._accessed.set_accessed(node)
self._check_in_slots(node)

Expand Down Expand Up @@ -1303,13 +1314,15 @@ def _check_in_slots(self, node):
# Properties circumvent the slots mechanism,
# so we should not emit a warning for them.
return
if node.attrname in klass.locals and _has_data_descriptor(
klass, node.attrname
if (
node.attrname in klass.locals
and _has_data_descriptor(klass, node.attrname)
):
# Descriptors circumvent the slots mechanism as well.
return
if node.attrname == "__class__" and _has_same_layout_slots(
slots, node.parent.value
if (
node.attrname == "__class__"
and _has_same_layout_slots(slots, node.parent.value)
):
return
self.add_message("assigning-non-slot", args=(node.attrname,), node=node)
Expand Down Expand Up @@ -1341,9 +1354,13 @@ def _check_classmethod_declaration(self, node):

# check the function called is "classmethod" or "staticmethod"
func = node.value.func
if not isinstance(func, astroid.Name) or func.name not in (
"classmethod",
"staticmethod",
if (
not isinstance(func, astroid.Name)
or func.name
not in (
"classmethod",
"staticmethod",
)
):
return

Expand Down Expand Up @@ -1466,8 +1483,9 @@ def _is_type_self_call(self, expr):
def _is_classmethod(func):
"""Check if the given *func* node is a class method."""

return isinstance(func, astroid.FunctionDef) and (
func.type == "classmethod" or func.name == "__class_getitem__"
return (
isinstance(func, astroid.FunctionDef)
and (func.type == "classmethod" or func.name == "__class_getitem__")
)

@staticmethod
Expand Down Expand Up @@ -1504,8 +1522,9 @@ def visit_name(self, node):
"""check if the name handle an access to a class member
if so, register it
"""
if self._first_attrs and (
node.name == self._first_attrs[-1] or not self._first_attrs[-1]
if (
self._first_attrs
and (node.name == self._first_attrs[-1] or not self._first_attrs[-1])
):
self._meth_could_be_func = False

Expand Down Expand Up @@ -1678,9 +1697,10 @@ def _check_init(self, node):
"""check that the __init__ method call super or ancestors'__init__
method (unless it is used for type hinting with `typing.overload`)
"""
if not self.linter.is_message_enabled(
"super-init-not-called"
) and not self.linter.is_message_enabled("non-parent-init-called"):
if (
not self.linter.is_message_enabled("super-init-not-called")
and not self.linter.is_message_enabled("non-parent-init-called")
):
return
klass_node = node.parent.frame()
to_call = _ancestors_to_call(klass_node)
Expand Down
Loading

0 comments on commit 559d778

Please sign in to comment.