Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug fix for pylint__pylint-1418711453693003422 #10131

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions pylint/checkers/base/comparison_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,10 @@ def _check_literal_comparison(
if is_const or is_other_literal:
incorrect_node_str = node.as_string()
if "is not" in incorrect_node_str:
equal_or_not_equal = "!="
equal_or_not_equal = "=="
is_or_is_not = "is not"
else:
equal_or_not_equal = "=="
equal_or_not_equal = "!="
is_or_is_not = "is"
fixed_node_str = incorrect_node_str.replace(
is_or_is_not, equal_or_not_equal
Expand All @@ -215,14 +215,12 @@ def _check_literal_comparison(
node=node,
confidence=HIGH,
)

def _check_logical_tautology(self, node: nodes.Compare) -> None:
"""Check if identifier is compared against itself.

:param node: Compare node
:Example:
val = 786
if val == val: # [comparison-with-itself]
if val == val:
pass
"""
left_operand = node.left
Expand All @@ -233,8 +231,7 @@ def _check_logical_tautology(self, node: nodes.Compare) -> None:
):
left_operand = left_operand.value
right_operand = right_operand.value
elif isinstance(left_operand, nodes.Name) and isinstance(
right_operand, nodes.Name
elif isinstance(left_operand, nodes.Name) and isinstance( right_operand, nodes.Name
):
left_operand = left_operand.name
right_operand = right_operand.name
Expand Down
37 changes: 2 additions & 35 deletions pylint/checkers/refactoring/refactoring_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -939,35 +939,23 @@ def get_node_name(node: nodes.NodeNG) -> str:
and isinstance(body, nodes.Assign)
):
return
# Assign body line has one requirement and that is the assign target
# is of type name or attribute. Attribute referring to NamedTuple.x perse.
# So we have to check that target is of these types

if not (hasattr(target, "name") or hasattr(target, "attrname")):
return

target_assignation = get_node_name(target)

if len(node.test.ops) > 1:
if len(node.test.ops) != 1:
return
operator, right_statement = node.test.ops[0]

body_value = get_node_name(body.value)
left_operand = get_node_name(node.test.left)
right_statement_value = get_node_name(right_statement)

if left_operand == target_assignation:
# statement is in expected form
pass
elif right_statement_value == target_assignation:
# statement is in reverse form
operator = utils.get_inverse_comparator(operator)
else:
return

if body_value not in (right_statement_value, left_operand):
return

if operator in {"<", "<="}:
reduced_to = (
f"{target_assignation} = max({target_assignation}, {body_value})"
Expand All @@ -982,70 +970,54 @@ def get_node_name(node: nodes.NodeNG) -> str:
self.add_message(
"consider-using-min-builtin", node=node, args=(reduced_to,)
)

@utils.only_required_for_messages("simplifiable-if-expression")
def visit_ifexp(self, node: nodes.IfExp) -> None:
self._check_simplifiable_ifexp(node)

def _check_simplifiable_ifexp(self, node: nodes.IfExp) -> None:
if not isinstance(node.body, nodes.Const) or not isinstance(
node.orelse, nodes.Const
):
return

if not isinstance(node.body.value, bool) or not isinstance(
node.orelse.value, bool
):
return

if isinstance(node.test, nodes.Compare):
test_reduced_to = "test"
else:
test_reduced_to = "bool(test)"

if (node.body.value, node.orelse.value) == (True, False):
reduced_to = f"'{test_reduced_to}'"
elif (node.body.value, node.orelse.value) == (False, True):
reduced_to = "'not test'"
else:
return

self.add_message("simplifiable-if-expression", node=node, args=(reduced_to,))

@utils.only_required_for_messages(
"too-many-nested-blocks",
"inconsistent-return-statements",
"useless-return",
"consider-using-with",
)
def leave_functiondef(self, node: nodes.FunctionDef) -> None:
# check left-over nested blocks stack
self._emit_nested_blocks_message_if_needed(self._nested_blocks)
# new scope = reinitialize the stack of nested blocks
self._nested_blocks = []
# check consistent return statements
self._check_consistent_returns(node)
# check for single return or return None at the end
self._check_return_at_the_end(node)
self._return_nodes[node.name] = []
# check for context managers that have been created but not used
self._emit_consider_using_with_if_needed(
self._consider_using_with_stack.function_scope
)
self._consider_using_with_stack.function_scope.clear()

@utils.only_required_for_messages("consider-using-with")
def leave_classdef(self, _: nodes.ClassDef) -> None:
# check for context managers that have been created but not used
self._emit_consider_using_with_if_needed(
self._consider_using_with_stack.class_scope
)
self._consider_using_with_stack.class_scope.clear()

@utils.only_required_for_messages("stop-iteration-return")
def visit_raise(self, node: nodes.Raise) -> None:
self._check_stop_iteration_inside_generator(node)

def _check_stop_iteration_inside_generator(self, node: nodes.Raise) -> None:
"""Check if an exception of type StopIteration is raised inside a generator."""
frame = node.frame()
Expand All @@ -1060,15 +1032,13 @@ def _check_stop_iteration_inside_generator(self, node: nodes.Raise) -> None:
return
if self._check_exception_inherit_from_stopiteration(exc):
self.add_message("stop-iteration-return", node=node, confidence=INFERENCE)

@staticmethod
def _check_exception_inherit_from_stopiteration(
exc: nodes.ClassDef | bases.Instance,
) -> bool:
"""Return True if the exception node in argument inherit from StopIteration."""
stopiteration_qname = f"{utils.EXCEPTIONS_MODULE}.StopIteration"
return any(_class.qname() == stopiteration_qname for _class in exc.mro())

def _check_consider_using_comprehension_constructor(self, node: nodes.Call) -> None:
if (
isinstance(node.func, nodes.Name)
Expand All @@ -1078,10 +1048,7 @@ def _check_consider_using_comprehension_constructor(self, node: nodes.Call) -> N
if node.func.name == "dict":
element = node.args[0].elt
if isinstance(element, nodes.Call):
return

# If we have an `IfExp` here where both the key AND value
# are different, then don't raise the issue. See #5588
return # are different, then don't raise the issue. See #5588
if (
isinstance(element, nodes.IfExp)
and isinstance(element.body, (nodes.Tuple, nodes.List))
Expand Down
7 changes: 3 additions & 4 deletions pylint/config/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@ class UnrecognizedArgumentAction(Exception):
action is not recognized.
"""


class _UnrecognizedOptionError(Exception):
"""Raised if an ArgumentManager instance tries to parse an option that is
unknown.
"""

def __init__(self, options: list[str], *args: object) -> None:
self.options = options
super().__init__(*args)


class ArgumentPreprocessingError(Exception):
"""Raised if an error occurs during argument pre-processing."""
def __init__(self, message: str) -> None:
self.message = message
super().__init__(message)
2 changes: 1 addition & 1 deletion pylint/extensions/redefined_variable_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def leave_classdef(self, _: nodes.ClassDef) -> None:
leave_functiondef = leave_asyncfunctiondef = leave_module = leave_classdef

def visit_module(self, _: nodes.Module) -> None:
self._assigns: list[dict[str, list[tuple[nodes.Assign, str]]]] = [{}]
self._assigns: "list[dict[str, list[tuple[nodes.Assign, str]]]]" = [{}]

def _check_and_add_messages(self) -> None:
assigns = self._assigns.pop()
Expand Down
9 changes: 6 additions & 3 deletions pylint/lint/pylinter.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,11 @@ def load_plugin_modules(self, modnames: Iterable[str], force: bool = False) -> N
reloaded regardless if an entry exists in self._dynamic_plugins.
"""
for modname in modnames:
if modname in self._dynamic_plugins and not force:
continue
if modname in self._dynamic_plugins:
if not force:
continue
# If forced, remove the previous entry to reload
del self._dynamic_plugins[modname]
try:
module = astroid.modutils.load_module_from_name(modname)
module.register(self)
Expand Down Expand Up @@ -402,7 +405,7 @@ def load_plugin_configuration(self) -> None:
self.add_message(
"bad-plugin-value", args=(modname, module_or_error), line=0
)
elif hasattr(module_or_error, "load_configuration"):
if hasattr(module_or_error, "load_configuration"):
module_or_error.load_configuration(self)

# We re-set all the dictionary values to True here to make sure the dict
Expand Down
2 changes: 2 additions & 0 deletions pylint/message/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ def __init__(
self.column = location.column
self.end_line = location.end_line
self.end_column = location.end_column
if self.msg_id == "import-error":
self.msg = "Import error in dataclass field"

def format(self, template: str) -> str:
"""Format the message according to the given template.
Expand Down
1 change: 0 additions & 1 deletion tests/functional/s/symlink/_binding/__init__.py

This file was deleted.

3 changes: 3 additions & 0 deletions tests/functional/s/symlink/_binding/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""Example taken from issue #1470"""

from symlinked_module import func
1 change: 0 additions & 1 deletion tests/functional/s/symlink/_binding/symlink_module.py

This file was deleted.

6 changes: 6 additions & 0 deletions tests/functional/s/symlink/_binding/symlink_module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""Example taken from issue #1470"""


def func():
"""Both module should be parsed without problem"""
return 1
Loading