diff options
3 files changed, 82 insertions, 27 deletions
diff --git a/pylint/checkers/utils.py b/pylint/checkers/utils.py index 68b103b53..27042653b 100644 --- a/pylint/checkers/utils.py +++ b/pylint/checkers/utils.py @@ -51,6 +51,7 @@ ABC_METHODS = { TYPING_PROTOCOLS = frozenset( {"typing.Protocol", "typing_extensions.Protocol", ".Protocol"} ) +COMMUTATIVE_OPERATORS = frozenset({"*", "+", "^", "&", "|"}) ITER_METHOD = "__iter__" AITER_METHOD = "__aiter__" NEXT_METHOD = "__next__" @@ -2120,7 +2121,11 @@ def is_augmented_assign(node: nodes.Assign) -> tuple[bool, str]: if _is_target_name_in_binop_side(target, binop.left): return True, binop.op - if _is_target_name_in_binop_side(target, binop.right): + if ( + # Unless an operator is commutative, we should not raise (i.e. x = 3/x) + binop.op in COMMUTATIVE_OPERATORS + and _is_target_name_in_binop_side(target, binop.right) + ): inferred_left = safe_infer(binop.left) if isinstance(inferred_left, nodes.Const) and isinstance( inferred_left.value, int diff --git a/tests/functional/ext/code_style/cs_consider_using_augmented_assign.py b/tests/functional/ext/code_style/cs_consider_using_augmented_assign.py index e4af95686..806ca3f23 100644 --- a/tests/functional/ext/code_style/cs_consider_using_augmented_assign.py +++ b/tests/functional/ext/code_style/cs_consider_using_augmented_assign.py @@ -5,12 +5,16 @@ from unknown import Unknown x = 1 -x = x + 1 # [consider-using-augmented-assign] -x = 1 + x # [consider-using-augmented-assign] + +# summation is commutative (for integer and float, but not for string) +x = x + 3 # [consider-using-augmented-assign] +x = 3 + x # [consider-using-augmented-assign] +x = x + "3" # [consider-using-augmented-assign] +x = "3" + x + +# We don't warn on intricate expressions as we lack knowledge of simplifying such +# expressions which is necessary to see if they can become augmented x, y = 1 + x, 2 + x -# We don't warn on intricate expressions as we lack knowledge -# of simplifying such expressions which is necessary to see -# if they can become augmented x = 1 + x - 2 x = 1 + x + 2 @@ -52,7 +56,6 @@ def return_str() -> str: # Currently we disregard all calls my_str = return_str() + my_str - my_str = my_str % return_str() my_str = my_str % 1 # [consider-using-augmented-assign] my_str = my_str % (1, 2) # [consider-using-augmented-assign] @@ -61,17 +64,58 @@ my_str = return_str() % my_str my_str = Unknown % my_str my_str = my_str % Unknown # [consider-using-augmented-assign] +# subtraction is anti-commutative x = x - 3 # [consider-using-augmented-assign] +x = 3 - x + +# multiplication is commutative x = x * 3 # [consider-using-augmented-assign] +x = 3 * x # [consider-using-augmented-assign] + +# division is not commutative x = x / 3 # [consider-using-augmented-assign] +x = 3 / x + +# integer division is not commutative x = x // 3 # [consider-using-augmented-assign] +x = 3 // x + +# Left shift operator is not commutative x = x << 3 # [consider-using-augmented-assign] +x = 3 << x + +# Right shift operator is not commutative x = x >> 3 # [consider-using-augmented-assign] +x = 3 >> x + +# modulo is not commutative x = x % 3 # [consider-using-augmented-assign] +x = 3 % x + +# exponential is not commutative x = x**3 # [consider-using-augmented-assign] +x = 3**x + +# XOR is commutative x = x ^ 3 # [consider-using-augmented-assign] +x = 3 ^ x # [consider-using-augmented-assign] + +# Bitwise AND operator is commutative x = x & 3 # [consider-using-augmented-assign] +x = 3 & x # [consider-using-augmented-assign] + +# Bitwise OR operator is commutative +x = x | 3 # [consider-using-augmented-assign] +x = 3 | x # [consider-using-augmented-assign] + x = x > 3 +x = 3 > x + x = x < 3 +x = 3 < x + x = x >= 3 +x = 3 >= x + x = x <= 3 +x = 3 <= x diff --git a/tests/functional/ext/code_style/cs_consider_using_augmented_assign.txt b/tests/functional/ext/code_style/cs_consider_using_augmented_assign.txt index 1684953e9..5bcbb6b34 100644 --- a/tests/functional/ext/code_style/cs_consider_using_augmented_assign.txt +++ b/tests/functional/ext/code_style/cs_consider_using_augmented_assign.txt @@ -1,20 +1,26 @@ -consider-using-augmented-assign:8:0:8:9::Use '+=' to do an augmented assign directly:INFERENCE -consider-using-augmented-assign:9:0:9:9::Use '+=' to do an augmented assign directly:INFERENCE -consider-using-augmented-assign:28:8:28:27:MyClass.__init__:Use '+=' to do an augmented assign directly:INFERENCE -consider-using-augmented-assign:29:8:29:27:MyClass.__init__:Use '+=' to do an augmented assign directly:INFERENCE -redefined-outer-name:31:8:31:9:MyClass.__init__:Redefining name 'x' from outer scope (line 7):UNDEFINED -consider-using-augmented-assign:40:0:40:23::Use '+=' to do an augmented assign directly:INFERENCE -consider-using-augmented-assign:44:0:44:28::Use '+=' to do an augmented assign directly:INFERENCE -consider-using-augmented-assign:57:0:57:19::Use '%=' to do an augmented assign directly:INFERENCE -consider-using-augmented-assign:58:0:58:24::Use '%=' to do an augmented assign directly:INFERENCE -consider-using-augmented-assign:62:0:62:25::Use '%=' to do an augmented assign directly:INFERENCE -consider-using-augmented-assign:64:0:64:9::Use '-=' to do an augmented assign directly:INFERENCE -consider-using-augmented-assign:65:0:65:9::Use '*=' to do an augmented assign directly:INFERENCE -consider-using-augmented-assign:66:0:66:9::Use '/=' to do an augmented assign directly:INFERENCE -consider-using-augmented-assign:67:0:67:10::Use '//=' to do an augmented assign directly:INFERENCE -consider-using-augmented-assign:68:0:68:10::Use '<<=' to do an augmented assign directly:INFERENCE -consider-using-augmented-assign:69:0:69:10::Use '>>=' to do an augmented assign directly:INFERENCE -consider-using-augmented-assign:70:0:70:9::Use '%=' to do an augmented assign directly:INFERENCE -consider-using-augmented-assign:71:0:71:8::Use '**=' to do an augmented assign directly:INFERENCE -consider-using-augmented-assign:72:0:72:9::Use '^=' to do an augmented assign directly:INFERENCE -consider-using-augmented-assign:73:0:73:9::Use '&=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:10:0:10:9::Use '+=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:11:0:11:9::Use '+=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:12:0:12:11::Use '+=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:32:8:32:27:MyClass.__init__:Use '+=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:33:8:33:27:MyClass.__init__:Use '+=' to do an augmented assign directly:INFERENCE +redefined-outer-name:35:8:35:9:MyClass.__init__:Redefining name 'x' from outer scope (line 7):UNDEFINED +consider-using-augmented-assign:44:0:44:23::Use '+=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:48:0:48:28::Use '+=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:60:0:60:19::Use '%=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:61:0:61:24::Use '%=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:65:0:65:25::Use '%=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:68:0:68:9::Use '-=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:72:0:72:9::Use '*=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:73:0:73:9::Use '*=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:76:0:76:9::Use '/=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:80:0:80:10::Use '//=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:84:0:84:10::Use '<<=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:88:0:88:10::Use '>>=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:92:0:92:9::Use '%=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:96:0:96:8::Use '**=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:100:0:100:9::Use '^=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:101:0:101:9::Use '^=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:104:0:104:9::Use '&=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:105:0:105:9::Use '&=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:108:0:108:9::Use '|=' to do an augmented assign directly:INFERENCE +consider-using-augmented-assign:109:0:109:9::Use '|=' to do an augmented assign directly:INFERENCE |