From cbda7304ea2baf4ab491777866ee7247a741f910 Mon Sep 17 00:00:00 2001 From: David Kunzmann Date: Wed, 1 Nov 2023 13:57:17 +0100 Subject: [PATCH] Updated rules metadata (#1629) --- .../org/sonar/l10n/py/rules/python/S1066.html | 30 ++++- .../org/sonar/l10n/py/rules/python/S1066.json | 2 +- .../org/sonar/l10n/py/rules/python/S1110.html | 8 +- .../org/sonar/l10n/py/rules/python/S112.html | 104 ++++----------- .../org/sonar/l10n/py/rules/python/S1128.json | 2 +- .../org/sonar/l10n/py/rules/python/S113.json | 2 +- .../org/sonar/l10n/py/rules/python/S1131.html | 7 +- .../org/sonar/l10n/py/rules/python/S1135.html | 2 +- .../org/sonar/l10n/py/rules/python/S1144.html | 11 +- .../org/sonar/l10n/py/rules/python/S1144.json | 2 +- .../org/sonar/l10n/py/rules/python/S116.html | 21 ++- .../org/sonar/l10n/py/rules/python/S117.html | 65 ++++++++- .../org/sonar/l10n/py/rules/python/S1172.html | 35 +++-- .../org/sonar/l10n/py/rules/python/S1186.html | 70 +++++----- .../org/sonar/l10n/py/rules/python/S1192.html | 45 ++++--- .../org/sonar/l10n/py/rules/python/S125.html | 5 +- .../org/sonar/l10n/py/rules/python/S134.html | 48 +++++-- .../org/sonar/l10n/py/rules/python/S1481.html | 51 ++++--- .../org/sonar/l10n/py/rules/python/S1854.html | 34 +++-- .../org/sonar/l10n/py/rules/python/S1854.json | 2 +- .../org/sonar/l10n/py/rules/python/S1871.html | 23 +++- .../org/sonar/l10n/py/rules/python/S2068.html | 1 - .../org/sonar/l10n/py/rules/python/S2077.html | 1 - .../org/sonar/l10n/py/rules/python/S2092.html | 1 - .../org/sonar/l10n/py/rules/python/S2208.html | 30 +++-- .../org/sonar/l10n/py/rules/python/S2257.html | 1 - .../org/sonar/l10n/py/rules/python/S2612.html | 1 - .../org/sonar/l10n/py/rules/python/S3330.html | 1 - .../org/sonar/l10n/py/rules/python/S3457.html | 34 +++-- .../org/sonar/l10n/py/rules/python/S3457.json | 2 +- .../org/sonar/l10n/py/rules/python/S3752.html | 1 - .../org/sonar/l10n/py/rules/python/S3776.html | 126 +++++++++++++++++- .../org/sonar/l10n/py/rules/python/S3776.json | 2 +- .../org/sonar/l10n/py/rules/python/S4423.html | 1 - .../org/sonar/l10n/py/rules/python/S4502.html | 1 - .../org/sonar/l10n/py/rules/python/S4721.html | 1 - .../org/sonar/l10n/py/rules/python/S4787.html | 1 - .../org/sonar/l10n/py/rules/python/S4790.html | 1 - .../org/sonar/l10n/py/rules/python/S4792.html | 1 - .../org/sonar/l10n/py/rules/python/S4823.html | 1 - .../org/sonar/l10n/py/rules/python/S4830.html | 61 +++++++++ .../org/sonar/l10n/py/rules/python/S5122.html | 1 - .../org/sonar/l10n/py/rules/python/S5300.html | 1 - .../org/sonar/l10n/py/rules/python/S5439.html | 1 - .../org/sonar/l10n/py/rules/python/S5542.html | 1 - .../org/sonar/l10n/py/rules/python/S5547.html | 1 - .../org/sonar/l10n/py/rules/python/S6353.html | 28 ++-- .../org/sonar/l10n/py/rules/python/S6554.html | 12 +- .../org/sonar/l10n/py/rules/python/S6559.html | 10 +- .../org/sonar/l10n/py/rules/python/S6660.html | 4 +- .../org/sonar/l10n/py/rules/python/S6660.json | 8 +- .../org/sonar/l10n/py/rules/python/S6799.html | 20 +-- .../org/sonar/l10n/py/rules/python/S6799.json | 2 +- .../org/sonar/l10n/py/rules/python/S905.html | 55 ++++++-- sonarpedia.json | 2 +- 55 files changed, 654 insertions(+), 330 deletions(-) diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1066.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1066.html index c74ce7bf70..2f56c6021f 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1066.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1066.html @@ -1,14 +1,34 @@

Why is this an issue?

-

Merging collapsible if statements increases the code’s readability.

-

Noncompliant code example

+

Nested code - blocks of code inside blocks of code - is eventually necessary, but increases complexity. This is why keeping the code as flat as +possible, by avoiding unnecessary nesting, is considered a good practice.

+

Merging if statements when possible will decrease the nesting of the code and improve its readability.

+

Code like

 if condition1:
-    if condition2:
+    if condition2:             # Noncompliant
         # ...
 
-

Compliant solution

+

Will be more readable as

-if condition1 and condition2:
+if condition1 and condition2:  # Compliant
     # ...
 
+

How to fix it

+

If merging the conditions seems to result in a more complex code, extracting the condition or part of it in a named function or variable is a +better approach to fix readability.

+

Code examples

+

Noncompliant code example

+
+if file.isValid():
+  if file.isfile() or file.isdir():     # Noncompliant
+    # ...
+
+

Compliant solution

+
+def isFileOrDirectory(File file):
+  return file.isFile() or file.isDirectory()
+
+if file.isValid() and isFileOrDirectory(file): # Compliant
+  # ...
+
diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1066.json b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1066.json index f6857be37a..732a6ea96f 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1066.json +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1066.json @@ -1,5 +1,5 @@ { - "title": "Collapsible \"if\" statements should be merged", + "title": "Mergeable \"if\" statements should be combined", "type": "CODE_SMELL", "code": { "impacts": { diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1110.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1110.html index 64880ce03a..30ee967061 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1110.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1110.html @@ -1,6 +1,10 @@

Why is this an issue?

-

The use of parentheses, even those not required to enforce a desired order of operations, can clarify the intent behind a piece of code. But -redundant pairs of parentheses could be misleading, and should be removed.

+

Parentheses can disambiguate the order of operations in complex expressions and make the code easier to understand.

+
+a = (b * c) + (d * e) # Compliant: the intent is clear.
+
+

Redundant parentheses are parenthesis that do not change the behavior of the code, and do not clarify the intent. They can mislead and complexify +the code. They should be removed.

Noncompliant code example

 return ((3))        # Noncompliant
diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S112.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S112.html
index 74a133d401..3238a11f21 100644
--- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S112.html
+++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S112.html
@@ -1,92 +1,40 @@
+

This rule raises an issue when a generic exception (such as Exception or BaseException) is raised.

Why is this an issue?

Raising instances of Exception and BaseException will have a negative impact on any code trying to catch these exceptions.

-

First, the only way to handle differently multiple Exceptions is to check their message, which is error-prone and difficult to maintain.

-

What’s more, it becomes difficult to catch only your exception. The best practice is to catch only exceptions which require a specific handling. -When you raise Exception or BaseException in a function the caller will have to add an except Exception or -except BaseException and re-raise all exceptions which were unintentionally caught. This can create tricky bugs when the caller forgets -to re-raise exceptions such as SystemExit and the software cannot be stopped.

-

It is recommended to either:

+

From a consumer perspective, it is generally a best practice to only catch exceptions you intend to handle. Other exceptions should ideally not be +caught and let to propagate up the stack trace so that they can be dealt with appropriately. When a generic exception is thrown, it forces consumers +to catch exceptions they do not intend to handle, which they then have to re-raise.

+

Besides, when working with a generic type of exception, the only way to distinguish between multiple exceptions is to check their message, which is +error-prone and difficult to maintain. Legitimate exceptions may be unintentionally silenced and errors may be hidden.

+

For instance, if an exception such as SystemExit is caught and not re-raised, it will prevent the program from stopping.

+

When raising an exception, it is therefore recommended to raising the most specific exception possible so that it can be handled intentionally by +consumers.

+

How to fix it

+

To fix this issue, make sure to throw specific exceptions that are relevant to the context in which they arise. It is recommended to either:

-

This rule raises an issue when Exception or BaseException are raised.

-

Noncompliant code example

-
-def process1():
-    raise BaseException("Wrong user input for field X")  # Noncompliant
-
-def process2():
-    raise BaseException("Wrong configuration")  # Noncompliant
-
-def process3(param):
-    if not isinstance(param, int):
-        raise Exception("param should be an integer")  # Noncompliant
-
-def caller():
-    try:
-         process1()
-         process2()
-         process3()
-    except BaseException as e:
-        if e.args[0] == "Wrong user input for field X":
-            # process error
-            pass
-        elif e.args[0] == "Wrong configuration":
-            # process error
-            pass
-        else:
-            # re-raise other exceptions
-            raise
+

Code examples

+

Noncompliant code example

+
+def check_value(value):
+    if value < 0:
+        raise BaseException("Value cannot be negative") # Noncompliant: this will be difficult for consumers to handle
 
-

Compliant solution

-
-class MyProjectError(Exception):
-    """Exception class from which every exception in this library will derive.
-         It enables other projects using this library to catch all errors coming
-         from the library with a single "except" statement
-    """
-    pass
-
-class BadUserInputError(MyProjectError):
-    """A specific error"""
-    pass
-
-class ConfigurationError(MyProjectError):
-    """A specific error"""
-    pass
-
-def process1():
-    raise BadUserInputError("Wrong user input for field X")
-
-def process2():
-    raise ConfigurationError("Wrong configuration")
-
-def process3(param):
-    if not isinstance(param, int):
-        raise TypeError("param should be an integer")
-
-def caller():
-    try:
-         process1()
-         process2()
-         process3()
-    except BadUserInputError as e:
-        # process error
-        pass
-    except ConfigurationError as e:
-        # process error
-        pass
+

Compliant solution

+
+def check_value(value):
+    if value < 0:
+        raise ValueError("Value cannot be negative") # Compliant
 

Resources

+

Documentation

diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1128.json b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1128.json index d3ad8e74ad..1b4b7b19be 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1128.json +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1128.json @@ -10,7 +10,7 @@ "status": "ready", "remediation": { "func": "Constant\/Issue", - "constantCost": "2min" + "constantCost": "1min" }, "tags": [ "unused" diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S113.json b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S113.json index b5acb1513c..1d0fcfdd81 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S113.json +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S113.json @@ -1,5 +1,5 @@ { - "title": "Files should contain an empty newline at the end", + "title": "Files should end with a newline", "type": "CODE_SMELL", "code": { "impacts": { diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1131.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1131.html index a5cab54ce8..625feb7197 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1131.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1131.html @@ -1,6 +1,5 @@

Why is this an issue?

-

Trailing whitespaces are simply useless and should not stay in code. They may generate noise when comparing different versions of the same -file.

-

If you encounter issues from this rule, this probably means that you are not using an automated code formatter - which you should if you have the -opportunity to do so.

+

Trailing whitespaces bring no information, they may generate noise when comparing different versions of the same file, and they can create bugs +when they appear after a \ marking a line continuation. They should be systematically removed.

+

An automated code formatter allows to completely avoid this family of issues and should be used wherever possible.

diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1135.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1135.html index a1e46710a4..ac5c06060a 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1135.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1135.html @@ -1,5 +1,5 @@

Why is this an issue?

-

Developers often use TOOO tags to mark areas in the code where additional work or improvements are needed but are not implemented +

Developers often use TODO tags to mark areas in the code where additional work or improvements are needed but are not implemented immediately. However, these TODO tags sometimes get overlooked or forgotten, leading to incomplete or unfinished code. This code smell class aims to identify and address such unattended TODO tags to ensure a clean and maintainable codebase. This description will explore why this is a problem and how it can be fixed to improve the overall code quality.

diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1144.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1144.html index fe68bc77a0..5f77d996a3 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1144.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1144.html @@ -1,7 +1,7 @@ +

This rule raises an issue when a "class-private" method is never called inside the class where it was declared.

Why is this an issue?

-

"Class-Private" methods that are never executed inside their enclosing class are dead code: unnecessary, inoperative code that should be removed. -Cleaning out dead code decreases the size of the maintained codebase, making it easier to understand the program and preventing bugs from being -introduced.

+

A method that is never called is dead code, and should be removed. Cleaning out dead code decreases the size of the maintained codebase, making it +easier to understand the program and preventing bugs from being introduced.

Python has no real private methods. Every method is accessible. There are however two conventions indicating that a method is not meant to be "public":

    @@ -15,7 +15,8 @@

    Why is this an issue?

This rule raises an issue when a class-private method (two leading underscores, max one underscore at the end) is never called inside the class. Class methods, static methods and instance methods will all raise an issue.

-

Noncompliant code example

+

Code examples

+

Noncompliant code example

 class Noncompliant:
 
@@ -30,7 +31,7 @@ 

Noncompliant code example

def __mangled_instance_method(self): # Noncompliant print("__mangled_instance_method")
-

Compliant solution

+

Compliant solution

 class Compliant:
 
diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1144.json b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1144.json
index 410bf119ad..cb1030c681 100644
--- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1144.json
+++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1144.json
@@ -10,7 +10,7 @@
   "status": "ready",
   "remediation": {
     "func": "Constant\/Issue",
-    "constantCost": "5min"
+    "constantCost": "2min"
   },
   "tags": [
     "unused"
diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S116.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S116.html
index 0ceccb315d..887bf086cf 100644
--- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S116.html
+++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S116.html
@@ -1,15 +1,22 @@
 

Why is this an issue?

-

Sharing some naming conventions is a key point to make it possible for a team to efficiently collaborate. This rule allows to check that field -names match a provided regular expression.

-

Noncompliant code example

-

With the default regular expression ^[_a-z][_a-z0-9]*$:

-
+

A naming convention in software development is a set of guidelines for naming code elements like variables, functions, and classes.

+

The goal of a naming convention is to make the code more readable and understandable, which makes it easier to maintain and debug. It also ensures +consistency in the code, especially when multiple developers are working on the same project.

+

This rule checks that field names match a provided regular expression.

+

Using the regular expression ^[_a-z][_a-z0-9]*$, the noncompliant code below:

+
 class MyClass:
   myField = 1
 
-

Compliant solution

-
+

Should be replaced with:

+
 class MyClass:
   my_field = 1
 
+

Resources

+

Documentation

+ diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S117.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S117.html index 980292a638..fa242cf94b 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S117.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S117.html @@ -1,10 +1,69 @@ +

Local variables and function parameters should be named consistently to communicate intent and improve maintainability. Rename your local variable +or function parameter to follow your project’s naming convention to address this issue.

Why is this an issue?

-

Shared naming conventions allow teams to collaborate effectively. This rule raises an issue when a local variable or function parameter name does -not match the provided regular expression.

+

A naming convention in software development is a set of guidelines for naming code elements like variables, functions, and classes.
Local +variables and function parameters hold the meaning of the written code. Their names should be meaningful and follow a consistent and easily +recognizable pattern.
Adhering to a consistent naming convention helps to make the code more readable and understandable, which makes it easier to +maintain and debug. It also ensures consistency in the code, especially when multiple developers are working on the same project.

+

This rule checks that local variable and function parameter names match a provided regular expression.

+

What is the potential impact?

+

Inconsistent naming of local variables and function parameters can lead to several issues in your code:

+
    +
  • Reduced Readability: inconsistent local variable and function parameter names make the code harder to read and understand; consequently, it is + more difficult to identify the purpose of each variable, spot errors, or comprehend the logic.
  • +
  • Difficulty in Identifying Variables: local variables and function parameters that don’t adhere to a standard naming convention are challenging + to identify; thus, the coding process slows down, especially when dealing with a large codebase.
  • +
  • Increased Risk of Errors: inconsistent or unclear local variable and function parameter names lead to misunderstandings about what the variable + represents. This ambiguity leads to incorrect assumptions and, consequently, bugs in the code.
  • +
  • Collaboration Difficulties: in a team setting, inconsistent naming conventions lead to confusion and miscommunication among team members.
  • +
  • Difficulty in Code Maintenance: inconsistent naming leads to an inconsistent codebase. The code is difficult to understand, and making changes + feels like refactoring constantly, as you face different naming methods. Ultimately, it makes the codebase harder to maintain.
  • +
+

In summary, not adhering to a naming convention for local variables and function parameters can lead to confusion, errors, and inefficiencies, +making the code harder to read, understand, and maintain.

Exceptions

-

Loop counters are ignored by this rule.

+

Loop counters of one letter are ignored by this rule.

 for i in range(limit):  # Compliant
     print(i)
 
+

Local variables matching regular expression ^[_A-Z][A-Z0-9_]*$ are considered as constant and ignored by this rule.
Function +parameters are not concerned by this exception.

+
+def print_something(important_param):
+    LOCAL_VARIABLE = "" # Compliant
+    print(important_param + LOCAL_VARIABLE)
+
+

How to fix it

+

First, familiarize yourself with the particular naming convention of the project in question. Then, update the name to match the convention, as +well as all usages of the name. For many IDEs, you can use built-in renaming and refactoring features to update all usages at once.

+

Code examples

+

Noncompliant code example

+

With the default regular expression ^[_a-z][a-z0-9_]*$:

+
+def print_something(IMPORTANT_PARAM): # Noncompliant
+    localVariable = "" # Noncompliant
+    print(IMPORTANT_PARAM + localVariable)
+
+

Compliant solution

+
+def print_something(important_param):
+    local_variable = ""
+    print(important_param + local_variable)
+
+

Resources

+

Documentation

+ +

Related rules

+
    +
  • {rule:python:S100} - Method names should comply with a naming convention
  • +
  • {rule:python:S101} - Class names should comply with a naming convention
  • +
  • {rule:python:S116} - Field names should comply with a naming convention
  • +
  • {rule:python:S1542} - Function names should comply with a naming convention
  • +
  • {rule:python:S1578} - Module names should comply with a naming convention
  • +
  • {rule:python:S2710} - The first argument to class methods should follow the naming convention
  • +
diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1172.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1172.html index a856614221..b4d799df66 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1172.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1172.html @@ -1,26 +1,33 @@

Why is this an issue?

-

Unused parameters are misleading. Whatever the value passed to such parameters is, the behavior will be the same.

-

Noncompliant code example

-
-def do_something(a, b): # "b" is unused
-  return compute(a)
-
-

Compliant solution

-
-def do_something(a):
-  return compute(a)
-
+

A typical code smell known as unused function parameters refers to parameters declared in a function but not used anywhere within the function’s +body. While this might seem harmless at first glance, it can lead to confusion and potential errors in your code. Disregarding the values passed to +such parameters, the function’s behavior will be the same, but the programmer’s intention won’t be clearly expressed anymore. Therefore, removing +function parameters that are not being utilized is considered best practice.

Exceptions

-

Overriding methods are ignored.

+

This rule ignores overriding methods.

 class C(B):
   def do_something(self, a, b): # no issue reported on b
     return self.compute(a)
-}
 
-

Throwaway variables _.

+

This rule also ignores variables named with a single underscore _. Such naming is a common practice for indicating that the variable +is insignificant.

 def do_something(a, _): # no issue reported on _
   return compute(a)
 
+

How to fix it

+

Having unused function parameters in your code can lead to confusion and misunderstanding of a developer’s intention. They reduce code readability +and introduce the potential for errors. To avoid these problems, developers should remove unused parameters from function declarations.

+

Code examples

+

Noncompliant code example

+
+def do_something(a, b): # "b" is unused
+  return compute(a)
+
+

Compliant solution

+
+def do_something(a):
+  return compute(a)
+
diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1186.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1186.html index 2eec141fe3..a15334ba69 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1186.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1186.html @@ -1,47 +1,14 @@

Why is this an issue?

-

There are several reasons for a function or a method not to have a body:

+

An empty method is generally considered bad practice and can lead to confusion, readability, and maintenance issues. Empty methods bring no +functionality and are misleading to others as they might think the method implementation fulfills a specific and identified requirement.

+

There are several reasons for a method not to have a body:

  • It is an unintentional omission, and should be fixed to prevent an unexpected behavior in production.
  • It is not yet, or never will be, supported. In this case an exception should be thrown.
  • The method is an intentionally-blank override. In this case a nested comment should explain the reason for the blank override.
-

Noncompliant code example

-
-def myfunc1(foo="Noncompliant"):
-    pass
-
-class MyClass:
-    def mymethod1(self, foo="Noncompliant"):
-        pass
-
-

Compliant solution

-
-def myfunc1():
-    pass  # comment explaining why this function is empty
-
-def myfunc2():
-    raise NotImplementedError()
-
-def myfunc3():
-    """
-    Docstring explaining why this function is empty.
-    """
-
-class MyClass:
-    def mymethod1(self):
-        pass  # comment explaining why this function is empty
-
-    def mymethod2(self):
-        raise NotImplementedError()
-
-    def mymethod3(self):
-        """
-        Docstring explaining why this method is empty. Note that this is not recommended for classes
-        which are meant to be subclassed.
-        """
-

Exceptions

-

No issue will be raised when the empty method is abstract and meant to be overriden in a subclass, i.e. it is decorated with +

No issue will be raised when the empty method is abstract and meant to be overridden in a subclass, i.e. it is decorated with abc.abstractmethod, abc.abstractstaticmethod, abc.abstractclassmethod or abc.abstractproperty. Note however that these methods should normally have a docstring explaining how subclasses should implement these methods.

@@ -64,4 +31,33 @@ 

Exceptions

def mystaticmethod(): pass
+

How to fix it

+

Code examples

+

Noncompliant code example

+
+def shouldNotBeEmpty():  # Noncompliant - method is empty
+    pass
+
+def notImplemented():  # Noncompliant - method is empty
+    pass
+
+def emptyOnPurpose():  # Noncompliant - method is empty
+    pass
+
+

Compliant solution

+
+def shouldNotBeEmpty():
+    doSomething()
+
+def notImplemented():
+    raise NotImplementedError("notImplemented() cannot be performed because ...")
+
+def emptyOnPurpose():
+    pass  # comment explaining why the method is empty
+
+def emptyOnPurposeBis():
+    """
+    Docstring explaining why this function is empty.
+    """
+
diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1192.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1192.html index 40cc968e87..082f477fae 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1192.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1192.html @@ -1,23 +1,6 @@

Why is this an issue?

-

Duplicated string literals make the process of refactoring error-prone, since you must be sure to update all occurrences.

-

On the other hand, constants can be referenced from many places, but only need to be updated in a single place.

-

Noncompliant code example

-

With the default threshold of 3:

-
-def run():
-    prepare("this is a duplicate")  # Noncompliant - "this is a duplicate" is duplicated 3 times
-    execute("this is a duplicate")
-    release("this is a duplicate")
-
-

Compliant solution

-
-ACTION_1 = "action1"
-
-def run():
-    prepare(ACTION_1)
-    execute(ACTION_1)
-    release(ACTION_1)
-
+

Duplicated string literals make the process of refactoring complex and error-prone, as any change would need to be propagated on all +occurrences.

Exceptions

No issue will be raised on:

    @@ -25,13 +8,33 @@

    Exceptions

  • strings with less than 5 characters
  • strings with only letters, numbers and underscores
-
+

How to fix it

+

Instead, use constants to replace the duplicated string literals. Constants can be referenced from many places, but only need to be updated in a +single place.

+

Code examples

+

Noncompliant code example

+

With the default threshold of 3:

+
+def run():
+    prepare("action1")  # Noncompliant - "action1" is duplicated 3 times
+    execute("action1")
+    release("action1")
+
 @app.route("/api/users/", methods=['GET', 'POST', 'PUT'])
 def users():
     pass
 
-@app.route("/api/projects/", methods=['GET', 'POST', 'PUT'])  # Compliant
+@app.route("/api/projects/", methods=['GET', 'POST', 'PUT'])  # Compliant - strings inside decorators are ignored
 def projects():
     pass
 
+

Compliant solution

+
+ACTION_1 = "action1"
+
+def run():
+    prepare(ACTION_1)
+    execute(ACTION_1)
+    release(ACTION_1)
+
diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S125.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S125.html index 86475f084c..0d83de02ce 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S125.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S125.html @@ -1,4 +1,5 @@

Why is this an issue?

-

Programmers should not comment out code as it bloats programs and reduces readability.

-

Unused code should be deleted and can be retrieved from source control history if required.

+

Commented-out code distracts the focus from the actual executed code. It creates a noise that increases maintenance code. And because it is never +executed, it quickly becomes out of date and invalid.

+

Commented-out code should be deleted and can be retrieved from source control history if required.

diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S134.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S134.html index 4bd6913ef1..d1b75a1869 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S134.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S134.html @@ -1,17 +1,43 @@

Why is this an issue?

-

Nested if, for, while, try, and with statements are key ingredients for making -what’s known as "Spaghetti code". Such code is hard to read, refactor and therefore maintain.

-

Noncompliant code example

-

The following code snippet illustrates this rule with the default threshold of 3.

-
-  if condition1:           # Compliant - depth = 1
+

Nested control flow statements if, for, while, try, and with are often key +ingredients in creating what’s known as "Spaghetti code". This code smell can make your program difficult to understand and maintain.

+

When numerous control structures are placed inside one another, the code becomes a tangled, complex web. This significantly reduces the code’s +readability and maintainability, and it also complicates the testing process.

+

How to fix it

+

Code examples

+

The following example demonstrates the behavior of the rule with the default threshold of 4 levels of nesting and one of the potential ways to fix +the code smell by introducing guard clauses:

+

Noncompliant code example

+
+if condition1:           # Compliant - depth = 1
+  # ...
+  if condition2:         # Compliant - depth = 2
     # ...
-    if condition2:         # Compliant - depth = 2
+    for i in range(10):  # Compliant - depth = 3
       # ...
-      for i in range(10):  # Compliant - depth = 3, not exceeding the limit
-        # ...
-        if condition4:     # Non-Compliant - depth = 4
-          if condition5:   # Depth = 5, exceeding the limit, but issues are only reported on depth = 4
+      if condition3:     # Compliant - depth = 4
+        if condition4:     # Non-Compliant - depth = 5, which exceeds the limit
+          if condition5:   # Depth = 6, exceeding the limit, but issues are only reported on depth = 5
             # ...
 
+

Compliant solution

+
+if not condition1:
+  return
+# ...
+if not condition2:
+  return
+  # ...
+  for i in range(10):
+    # ...
+    if condition3:
+      if condition4:
+        if condition5:
+          # ...
+
+

Resources

+ diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1481.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1481.html index 0b280f70b8..18c588541b 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1481.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1481.html @@ -1,28 +1,49 @@

Why is this an issue?

-

If a local variable is declared but not used, it is dead code and should be removed. Doing so will improve maintainability because developers will -not wonder what the variable is used for.

-

Noncompliant code example

+

An unused local variable is a variable that has been declared but is not used anywhere in the block of code where it is defined. It is dead code, +contributing to unnecessary complexity and leading to confusion when reading the code. Therefore, it should be removed from your code to maintain +clarity and efficiency.

+

What is the potential impact?

+

Having unused local variables in your code can lead to several issues:

+
    +
  • Decreased Readability: Unused variables can make your code more difficult to read. They add extra lines and complexity, which can distract from + the main logic of the code.
  • +
  • Misunderstanding: When other developers read your code, they may wonder why a variable is declared but not used. This can lead to confusion and + misinterpretation of the code’s intent.
  • +
  • Potential for Bugs: If a variable is declared but not used, it might indicate a bug or incomplete code. For example, if you declared a variable + intending to use it in a calculation, but then forgot to do so, your program might not work as expected.
  • +
  • Maintenance Issues: Unused variables can make code maintenance more difficult. If a programmer sees an unused variable, they might think it is + a mistake and try to 'fix' the code, potentially introducing new bugs.
  • +
  • Memory Usage: Although modern compilers are smart enough to ignore unused variables, not all compilers do this. In such cases, unused variables + take up memory space, leading to inefficient use of resources.
  • +
+

In summary, unused local variables can make your code less readable, more confusing, and harder to maintain, and they can potentially lead to bugs +or inefficient memory use. Therefore, it is best to remove them.

+

Exceptions

+

_ will not raise an issue for this rule. The following examples are compliant:

+for _ in range(10):
+    do_something()
+username, login, _ = auth
+do_something_else(username, login)
+
+

How to fix it

+

The fix for this issue is straightforward. Once you ensure the unused variable is not part of an incomplete implementation leading to bugs, you +just need to remove it.

+

Code examples

+

Noncompliant code example

+
 def hello(name):
-    message = "Hello " + name # Noncompliant
+    message = "Hello " + name # Noncompliant - message is unused
     print(name)
-for i in range(10):
+for i in range(10): # Noncompliant - i is unused
     foo()
 
-

Compliant solution

-
+

Compliant solution

+
 def hello(name):
     message = "Hello " + name
     print(message)
 for _ in range(10):
     foo()
 
-

Exceptions

-

_ will not raise an issue for this rule. The following examples are compliant:

-
-for _ in range(10):
-    do_something()
-username, login, _ = auth
-do_something_else(username, login)
-
diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1854.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1854.html index 944342a33c..3bf9889ebf 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1854.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1854.html @@ -1,26 +1,38 @@

Why is this an issue?

-

A dead store happens when a local variable is assigned a value that is not read by any subsequent instruction. Calculating or retrieving a value -only to then overwrite it or throw it away, could indicate a serious error in the code. Even if it’s not an error, it is at best a waste of resources. -Therefore all calculated values should be used.

-

Noncompliant code example

-
+

Dead stores refer to assignments made to local variables that are subsequently never used or immediately overwritten. Such assignments are +unnecessary and don’t contribute to the functionality or clarity of the code. They may even negatively impact performance. Removing them enhances code +cleanliness and readability. Even if the unnecessary operations do not do any harm in terms of the program’s correctness, they are - at best - a waste +of computing resources.

+

Exceptions

+

This rule ignores initializations to -1, 0, 1, None, True, False and +"". No issue will be raised on unpacked variables.

+

How to fix it

+

Remove the unnecesarry assignment, then test the code to make sure that the right-hand side of a given assignment had no side effects (e.g. a +method that writes certain data to a file and returns the number of written bytes).

+

Code examples

+

Noncompliant code example

+
 def func(a, b, compute):
     i = a + b  # Noncompliant; calculation result not used before value is overwritten
     i = compute()
     return i
 
-

Compliant solution

-
+

Compliant solution

+
 def func(a, b, compute):
     i = a + b
     i += compute()
     return i
 
-

Exceptions

-

This rule ignores initializations to -1, 0, 1, None, True, False and "".

-

No issue will be raised on unpacked variables.

Resources

+

Standards

+ +

Related rules

    -
  • MITRE, CWE-563 - Assignment to Variable without Use ('Unused Variable')
  • +
  • {rule:python:S1763} - All code should be reachable
  • +
  • {rule:python:S3516} - Functions returns should not be invariant
  • +
  • {rule:python:S3626} - Jump statements should not be redundant
diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1854.json b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1854.json index 0344bd02d2..1b1e0545e6 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1854.json +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1854.json @@ -10,7 +10,7 @@ "status": "ready", "remediation": { "func": "Constant\/Issue", - "constantCost": "15min" + "constantCost": "1min" }, "tags": [ "cwe", diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1871.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1871.html index d256b7955b..9a0f3dfc11 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1871.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S1871.html @@ -1,8 +1,8 @@

Why is this an issue?

-

Having two branches in the same if structure with the same implementation is at best duplicate code, and at worst a coding error. If -the same logic is truly needed for both instances, then they should be combined.

-

Noncompliant code example

-
+

When the same code is duplicated in two or more separate branches of a conditional, it can make the code harder to understand, maintain, and can +potentially introduce bugs if one instance of the code is changed but others are not.

+

Having two branches in the same if structure with the same implementation is at best duplicate code, and at worst a coding error.

+
 if 0 <= a < 10:
     do_first()
     do_second()
@@ -12,6 +12,14 @@ 

Noncompliant code example

do_first() # Noncompliant; duplicates first condition do_second()
+

If the same logic is needed for both instances, then the conditions should be combined.

+
+if (0 <= a < 10) or (20 <= a < 50):
+    do_first()
+    do_second()
+elif 10 <= a < 20:
+    do_the_other_thing()
+

Exceptions

Blocks in an if chain that contain a single line of code are ignored.

@@ -22,7 +30,7 @@ 

Exceptions

elif 20 <= a < 50: do_first() # no issue, usually this is done on purpose to increase the readability
-

But this exception does not apply to if chains without else-s when all branches have the same single line of code. In +

But this exception does not apply to if chains without else-s when all branches have the same single line of code. In the case of if chains with else-s rule {rule:python:S3923} raises a bug.

 if 0 <= a < 10:
@@ -30,4 +38,9 @@ 

Exceptions

elif 20 <= a < 50: do_first() # Noncompliant, this might have been done on purpose but probably not
+

Resources

+

Related rules

+
    +
  • {rule:python:S3923} - All branches in a conditional structure should not have exactly the same implementation
  • +
diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2068.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2068.html index 51a539649b..e69f430f3e 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2068.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2068.html @@ -45,7 +45,6 @@

See

  • MITRE, CWE-798 - Use of Hard-coded Credentials
  • MITRE, CWE-259 - Use of Hard-coded Password
  • -
  • SANS Top 25 - Porous Defenses
  • Derived from FindSecBugs rule Hard Coded Password
  • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2077.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2077.html index 52941270ba..b062aaee4c 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2077.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2077.html @@ -62,7 +62,6 @@

    See

  • MITRE, CWE-20 - Improper Input Validation
  • MITRE, CWE-89 - Improper Neutralization of Special Elements used in an SQL Command
  • -
  • SANS Top 25 - Insecure Interaction Between Components
  • Derived from FindSecBugs rules Potential SQL/JPQL Injection (JPA), Potential SQL/JDOQL Injection (JDO), Potential SQL/HQL Injection (Hibernate)
  • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2092.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2092.html index bdeeb96045..55a11adf0d 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2092.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2092.html @@ -44,6 +44,5 @@

    See

  • MITRE, CWE-311 - Missing Encryption of Sensitive Data
  • MITRE, CWE-315 - Cleartext Storage of Sensitive Information in a Cookie
  • MITRE, CWE-614 - Sensitive Cookie in HTTPS Session Without 'Secure' Attribute
  • -
  • SANS Top 25 - Porous Defenses
  • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2208.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2208.html index 17f1cd985d..62f1496946 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2208.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2208.html @@ -5,7 +5,19 @@

    Why is this an issue?

  • It reduces code readability as developers will have a hard time knowing where names come from.
  • It clutters the local namespace, which makes debugging more difficult.
  • -

    Remember that imported names can change when you update your dependencies. A wildcard import which works today might be broken tomorrow.

    +

    Remember that imported names can change when you update your dependencies. A wildcard import that works today might be broken tomorrow.

    +

    Exceptions

    +

    No issue will be raised in __init__.py files. Wildcard imports are a common way of populating these modules.

    +

    No issue will be raised in modules doing only imports. Local modules are sometimes created as a proxy for third-party modules.

    +
    +# file: mylibrary/pyplot.py
    +try:
    +    from guiqwt.pyplot import *  # Ok
    +except Exception:
    +    from matplotlib.pyplot import *  # Ok
    +
    +

    Just keep in mind that wildcard imports might still create issues in these cases. It’s always better to import only what you need.

    +

    How to fix it

    There are two ways to avoid a wildcard import:

    • Replace it with import mymodule and access module members as mymodule.myfunction. If the module name is too long, @@ -13,14 +25,15 @@

      Why is this an issue?

    • List every imported name. If necessary import statements can be split on multiple lines using parentheses (preferred solution) or backslashes.
    -

    Noncompliant code example

    +

    Code examples

    +

    Noncompliant code example

     from math import *  # Noncompliant
     def exp(x):
         pass
     print(exp(0))   # "None" will be printed
     
    -

    Compliant solution

    +

    Compliant solution

     import math
     def exp(x):
    @@ -34,17 +47,6 @@ 

    Compliant solution

    pass print(m_exp(0)) # "1.0" will be printed
    -

    Exceptions

    -

    No issue will be raised in __init__.py files. Wildcard imports are a common way of populating these modules.

    -

    No issue will be raised in modules doing only imports. Local modules are sometimes created as a proxy for third-party modules.

    -
    -# file: mylibrary/pyplot.py
    -try:
    -    from guiqwt.pyplot import *  # Ok
    -except Exception:
    -    from matplotlib.pyplot import *  # Ok
    -
    -

    Just keep in mind that wildcard imports might still create issues in these cases. It’s always better to import only what you need.

    Resources

    • Python documentation - The import statement
    • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2257.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2257.html index 22ea3987c4..76668d6650 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2257.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2257.html @@ -16,6 +16,5 @@

      See

    • OWASP Top 10 2017 Category A3 - Sensitive Data Exposure
    • MITRE, CWE-327 - Use of a Broken or Risky Cryptographic Algorithm
    • -
    • SANS Top 25 - Porous Defenses
    diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2612.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2612.html index 5d45fb28eb..d0fcd246f1 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2612.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S2612.html @@ -46,6 +46,5 @@

    See

    href="https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/02-Configuration_and_Deployment_Management_Testing/09-Test_File_Permission">OWASP File Permission
  • MITRE, CWE-732 - Incorrect Permission Assignment for Critical Resource
  • MITRE, CWE-266 - Incorrect Privilege Assignment
  • -
  • SANS Top 25 - Porous Defenses
  • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3330.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3330.html index 31c074c16c..a39eb8695d 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3330.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3330.html @@ -44,7 +44,6 @@

    See

  • OWASP Top 10 2017 Category A7 - Cross-Site Scripting (XSS)
  • MITRE, CWE-1004 - Sensitive Cookie Without 'HttpOnly' Flag
  • -
  • SANS Top 25 - Insecure Interaction Between Components
  • Derived from FindSecBugs rule HTTPONLY_COOKIE
  • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3457.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3457.html index 6d63de2845..e453f4774a 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3457.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3457.html @@ -1,20 +1,28 @@

    Why is this an issue?

    -

    Formatting strings, either with the % operator or str.format method, requires a valid string and arguments matching this -string’s replacement fields.

    -

    This also applies to loggers from the logging module. Internally they use %-formatting. The only difference is that they -will log an error instead of raising an exception when provided arguments are invalid.

    -

    Formatted string literals, also called "f-strings", are generally simpler to use, and any syntax mistake will fail at compile time. However it is -easy to forget curly braces and it won’t raise any error.

    +

    A format string is a string that contains placeholders, usually represented by special characters such as "%s" or "{}", depending on the technology +in use. These placeholders are replaced by values when the string is printed or logged. Thus, it is required that a string is valid and arguments +match replacement fields in this string.

    +

    This applies to the % operator, the str.format method, and loggers from the logging module. Internally, the latter use the %-formatting. The only +difference is that they will log an error instead of raising an exception when the provided arguments are invalid.

    +

    Formatted string literals (also called "f-strings"; available since Python 3.6) are generally simpler to use, and any syntax mistake will cause a +failure at compile time. However, it is easy to forget curly braces, which will not lead to any detectable errors.

    This rule raises an issue when:

      -
    • A string formatted with % will not return the expected string because some arguments are not used.
    • -
    • A string formatted with str.format will not return the expected string because some arguments are not used.
    • -
    • An "f-string" doesn’t contain any replacement field, which probably means that some curly braces are missing.
    • +
    • A string formatted with % will not return the expected text because some arguments are unused.
    • +
    • A string formatted with str.format will not return the expected string because some arguments are unused.
    • +
    • An "f-string" doesn’t contain any replacement field, which probably means some curly braces are missing.
    • Loggers will log an error because their message is not formatted properly.

    Rule {rule:python:S2275} covers cases where formatting a string will raise an exception.

    -

    Noncompliant code example

    -
    +

    How to fix it

    +

    A printf--style format string is a string that contains placeholders, which are replaced by values when the string is printed or +logged. Mismatch in the format specifiers and the arguments provided can lead to incorrect strings being created.

    +

    To avoid issues, a developer should ensure that the provided arguments match format specifiers.

    +

    Code examples

    +

    Noncompliant code example

    +
     "Error %(message)s" % {"message": "something failed", "extra": "some dead code"}  # Noncompliant. Remove the unused argument "extra" or add a replacement field.
     
     "Error: User {} has not been able to access []".format("Alice", "MyFile")  # Noncompliant. Remove 1 unexpected argument or add a replacement field.
    @@ -26,8 +34,8 @@ 

    Noncompliant code example

    import logging logging.error("Error: User %s has not been able to access %s", "Alice") # Noncompliant. Add 1 missing argument.
    -

    Compliant solution

    -
    +

    Compliant solution

    +
     "Error %(message)s" % {"message": "something failed"}
     
     "Error: User {} has not been able to access {}".format("Alice", "MyFile")
    diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3457.json b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3457.json
    index a2396f08fb..6a2e82ce1d 100644
    --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3457.json
    +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3457.json
    @@ -10,7 +10,7 @@
       "status": "ready",
       "remediation": {
         "func": "Constant\/Issue",
    -    "constantCost": "10min"
    +    "constantCost": "1min"
       },
       "tags": [
         "confusing"
    diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3752.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3752.html
    index 1185a0599d..d360a5ff1c 100644
    --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3752.html
    +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3752.html
    @@ -72,7 +72,6 @@ 

    See

    Broken Access Control
  • MITRE, CWE-352 - Cross-Site Request Forgery (CSRF)
  • OWASP: Cross-Site Request Forgery
  • -
  • SANS Top 25 - Insecure Interaction Between Components
  • Django - Allowed HTTP Methods
  • Flask - HTTP Methods
  • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3776.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3776.html index 554d55e3fe..c3fd9a7968 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3776.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3776.html @@ -1,14 +1,130 @@ +

    This rule raises an issue when the code cognitive complexity of a function is above a certain threshold.

    Why is this an issue?

    -

    Cognitive Complexity is a measure of how hard the control flow of a function -is to understand. Functions with high Cognitive Complexity will be difficult to maintain.

    +

    Cognitive Complexity is a measure of how hard it is to understand the control flow of a unit of code. Code with high cognitive complexity is hard +to read, understand, test, and modify.

    +

    As a rule of thumb, high cognitive complexity is a sign that the code should be refactored into smaller, easier-to-manage pieces.

    +

    Which syntax in code does impact cognitive complexity score?

    +

    Here are the core concepts:

    +
      +
    • Cognitive complexity is incremented each time the code breaks the normal linear reading flow.
      This concerns, for example: + Loop structures, Conditionals, Catches, Switches, Jumps to label and mixed operators in condition.
    • +
    • Each nesting level adds a malus to the breaking call.
      During code reading, the deeper you go through nested layers, the + harder it becomes to keep the context in mind.
    • +
    • Method calls are free
      A well-picked method name is a summary of multiple lines of code. A reader can first explore a + high-level view of what the code is performing then go deeper and deeper by looking at called functions content.
      Note: This does not + apply to recursive calls, those will increment cognitive score.
    • +
    +

    The method of computation is fully detailed in the pdf linked in the resources.

    +

    What is the potential impact?

    +

    Developers spend more time reading and understanding code than writing it. High cognitive complexity slows down changes and increases the cost of +maintenance.

    +

    How to fix it

    +

    Reducing cognitive complexity can be challenging.
    Here are a few suggestions:

    +
      +
    • Extract complex conditions in a new function.
      Mixed operators in condition will increase complexity. Extracting the + condition in a new function with an appropriate name will reduce cognitive load.
    • +
    • Break down large functions.
      Large functions can be hard to understand and maintain. If a function is doing too many + things, consider breaking it down into smaller, more manageable functions. Each function should have a single responsibility.
    • +
    • Avoid deep nesting by returning early.
      To avoid the nesting of conditions, process exceptional cases first and return + early.
    • +
    +

    Code examples

    +

    Extraction of a complex condition in a new function.

    +

    Noncompliant code example

    +

    The code is using a complex condition and has a cognitive cost of 5.

    +
    +def process_eligible_users(users):
    +    for user in users:             # +1 (for)
    +        if ((user.is_active and    # +1 (if) +1 (nested) +1 (multiple conditions)
    +            user.has_profile) or   # +1 (mixed operator)
    +            user.age > 18 ):
    +            user.process()
    +
    +

    Compliant solution

    +

    Even if the cognitive complexity of the whole program did not change, it is easier for a reader to understand the code of the +process_eligible_users function, which now only has a cognitive cost of 3.

    +
    +def process_eligible_users(users):
    +    for user in users:             # +1 (for)
    +        if is_eligible_user(user): # +1 (if) +1 (nested)
    +            user.process()
    +
    +def is_eligible_user(user):
    +    return ((user.is_active and user.has_profile) or user.age > 18) # +1 (multiple conditions) +1 (mixed operators)
    +
    +

    Break down large functions.

    +

    Noncompliant code example

    +

    Note: The code is simplified here, to illustrate the purpose. Please imagine there is more happening in the process.

    +

    The bellow code has a cognitive complexity score of 8.

    +
    +def process_user(user):
    +    if user.is_active():             # +1 (if)
    +        if user.has_profile():       # +1 (if) +1 (nested)
    +            ... # process active user with profile
    +        else:                        # +1 (else)
    +            ... # process active user without profile
    +    else:                            # +1 (else)
    +        if user.has_profile():       # +1 (if) +1 (nested)
    +            ... # process inactive user with profile
    +        else:                        # +1 (else)
    +            ... # process inactive user without profile
    +
    +

    This function could be refactored into smaller functions: The complexity is spread over multiple functions and the breaks in flow are no more +nested.
    The process_user has now a complexity score of two.

    +

    Compliant solution

    +
    +def process_user(user):
    +    if user.is_active():             # +1 (if)
    +        process_active_user(user)
    +    else:                            # +1 (else)
    +        process_inactive_user(user)
    +
    +def process_active_user(user):
    +    if user.has_profile():           # +1 (if) +1 (nested)
    +        ... # process active user with profile
    +    else:                            # +1 (else)
    +        ... # process active user without profile
    +
    +def process_inactive_user(user):
    +    if user.has_profile():           # +1 (if) +1 (nested)
    +        ... # process inactive user with profile
    +    else:                            # +1 (else)
    +        ... # process inactive user without profile
    +
    +

    Avoid deep nesting by returning early.

    +

    Noncompliant code example

    +

    The below code has a cognitive complexity of 6.

    +
    +def calculate(data):
    +    if data is not None:  # +1 (if)
    +        total = 0
    +        for item in data: # +1 (for) +1 (nested)
    +            if item > 0:  # +1 (if)  +2 (nested)
    +                total += item * 2
    +        return total
    +
    +

    Compliant solution

    +

    Checking for the edge case first flattens the if statements and reduces the cognitive complexity to 4.

    +
    +def calculate(data):
    +    if data is None:      # +1 (if)
    +        return None
    +    total = 0
    +    for item in data:     # +1 (for)
    +        if item > 0:      # +1 (if) +1 (nested)
    +            total += item * 2
    +    return total
    +
    +

    Pitfalls

    +

    As this code is complex, ensure that you have unit tests that cover the code before refactoring.

    Resources

    Documentation

    Articles & blog posts

    diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3776.json b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3776.json index f18253c544..d00a267ddb 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3776.json +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S3776.json @@ -21,5 +21,5 @@ "ruleSpecification": "RSPEC-3776", "sqKey": "S3776", "scope": "All", - "quickfix": "unknown" + "quickfix": "infeasible" } diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4423.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4423.html index 3ccd7bdd22..781971dd8a 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4423.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4423.html @@ -173,6 +173,5 @@

    Standards

  • OWASP Top 10 2017 Category A6 - Security Misconfiguration
  • MITRE, CWE-327 - Use of a Broken or Risky Cryptographic Algorithm
  • -
  • SANS Top 25 - Porous Defenses
  • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4502.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4502.html index a8fd4eb076..23934d83bd 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4502.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4502.html @@ -143,6 +143,5 @@

    See

  • OWASP Top 10 2017 Category A6 - Security Misconfiguration
  • OWASP: Cross-Site Request Forgery
  • -
  • SANS Top 25 - Insecure Interaction Between Components
  • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4721.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4721.html index 2b05b88e69..6e054b80c3 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4721.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4721.html @@ -80,6 +80,5 @@

    See

  • OWASP Top 10 2021 Category A3 - Injection
  • OWASP Top 10 2017 Category A1 - Injection
  • MITRE, CWE-78 - Improper Neutralization of Special Elements used in an OS Command
  • -
  • SANS Top 25 - Insecure Interaction Between Components
  • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4787.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4787.html index 2595bb492e..16f2766229 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4787.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4787.html @@ -99,6 +99,5 @@

    See

  • MITRE, CWE-325 - Missing Required Cryptographic Step
  • MITRE, CWE-326 - Inadequate Encryption Strength
  • MITRE, CWE-327 - Use of a Broken or Risky Cryptographic Algorithm
  • -
  • SANS Top 25 - Porous Defenses
  • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4790.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4790.html index 1f8deb830f..32dfd7d7e1 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4790.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4790.html @@ -47,6 +47,5 @@

    See

  • OWASP Mobile Top 10 2016 Category M5 - Insufficient Cryptography
  • MITRE, CWE-1240 - Use of a Risky Cryptographic Primitive
  • -
  • SANS Top 25 - Porous Defenses
  • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4792.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4792.html index a17ad97624..1c010ea03b 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4792.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4792.html @@ -96,6 +96,5 @@

    See

    Insufficient Logging & Monitoring
  • MITRE, CWE-117 - Improper Output Neutralization for Logs
  • MITRE, CWE-532 - Information Exposure Through Log Files
  • -
  • SANS Top 25 - Porous Defenses
  • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4823.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4823.html index 7e69b804df..8fd6c3d7a3 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4823.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4823.html @@ -26,6 +26,5 @@

    See

  • OWASP Top 10 2017 Category A1 - Injection
  • MITRE, CWE-88 - Argument Injection or Modification
  • MITRE, CWE-214 - Information Exposure Through Process Environment
  • -
  • SANS Top 25 - Insecure Interaction Between Components
  • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4830.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4830.html index 70d059030f..47803f82d2 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4830.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S4830.html @@ -113,6 +113,67 @@

    Using trusted certificates

    Working with self-signed certificates or non-standard CAs

    In some cases, you might need to work with a server using a self-signed certificate, or a certificate issued by a CA not included in your trusted roots. Rather than disabling certificate validation in your code, you can add the necessary certificates to your trust store.

    +

    How to fix it in HTTPX

    +

    Code examples

    +

    The following code contains examples of disabled certificate validation.

    +

    The certificate validation gets disabled by setting verify to False. To enable validation set the value to +True or do not set verify at all to use the secure default value.

    +

    Noncompliant code example

    +
    +import httpx
    +
    +httpx.get('https://example.com', verify=False)  # Noncompliant
    +
    +

    Compliant solution

    +
    +import httpx
    +
    +# By default, certificate validation is enabled
    +httpx.get('https://example.com')
    +
    +

    How does this work?

    +

    Addressing the vulnerability of disabled TLS certificate validation primarily involves re-enabling the default validation.

    +

    To avoid running into problems with invalid certificates, consider the following sections.

    +

    Using trusted certificates

    +

    If possible, always use a certificate issued by a well-known, trusted CA for your server. Most programming environments come with a predefined list +of trusted root CAs, and certificates issued by these authorities are validated automatically. This is the best practice, and it requires no +additional code or configuration.

    +

    Working with self-signed certificates or non-standard CAs

    +

    In some cases, you might need to work with a server using a self-signed certificate, or a certificate issued by a CA not included in your trusted +roots. Rather than disabling certificate validation in your code, you can add the necessary certificates to your trust store.

    +

    How to fix it in aiohttp

    +

    Code examples

    +

    The following code contains examples of disabled certificate validation.

    +

    The certificate validation gets disabled by setting verify_ssl to False. To enable validation set the value to +True or do not set verify_ssl at all to use the secure default value.

    +

    Noncompliant code example

    +
    +import aiohttp
    +
    +async def example():
    +  async with aiohttp.ClientSession() as session:
    +    session.get("https://example.com", verify_ssl=False) # Noncompliant
    +
    +

    Compliant solution

    +
    +import aiohttp
    +
    +# By default, certificate validation is enabled
    +
    +async def example():
    +  async with aiohttp.ClientSession() as session:
    +    session.get("https://example.com")
    +
    +

    How does this work?

    +

    Addressing the vulnerability of disabled TLS certificate validation primarily involves re-enabling the default validation.

    +

    To avoid running into problems with invalid certificates, consider the following sections.

    +

    Using trusted certificates

    +

    If possible, always use a certificate issued by a well-known, trusted CA for your server. Most programming environments come with a predefined list +of trusted root CAs, and certificates issued by these authorities are validated automatically. This is the best practice, and it requires no +additional code or configuration.

    +

    Working with self-signed certificates or non-standard CAs

    +

    In some cases, you might need to work with a server using a self-signed certificate, or a certificate issued by a CA not included in your trusted +roots. Rather than disabling certificate validation in your code, you can add the necessary certificates to your trust store.

    Resources

    Standards

      diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5122.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5122.html index 423fe9a5da..c0e726beb4 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5122.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5122.html @@ -74,6 +74,5 @@

      See

      Cheat Sheet - Cross Origin Resource Sharing
    • MITRE, CWE-346 - Origin Validation Error
    • MITRE, CWE-942 - Overly Permissive Cross-domain Whitelist
    • -
    • SANS Top 25 - Porous Defenses
    diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5300.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5300.html index cd33cdff40..3f34f9aee2 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5300.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5300.html @@ -67,6 +67,5 @@

    See

  • MITRE, CWE-93 - Improper Neutralization of CRLF Sequences ('CRLF Injection')
  • MITRE, CWE-80 - Improper Neutralization of Script-Related HTML Tags in a Web Page (Basic XSS)
  • -
  • SANS Top 25 - Insecure Interaction Between Components
  • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5439.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5439.html index 619d162a42..f5aeb2f672 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5439.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5439.html @@ -52,6 +52,5 @@

    Resources

  • MITRE, CWE-86 - Improper Neutralization of Invalid Characters in Identifiers in Web Pages
  • MITRE, CWE-87 - Improper Neutralization of Alternate XSS Syntax
  • -
  • SANS Top 25 - Insecure Interaction Between Components
  • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5542.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5542.html index 890db491c2..8f85bf00d0 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5542.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5542.html @@ -271,6 +271,5 @@

    Standards

  • OWASP Top 10 2017 Category A6 - Security Misconfiguration
  • MITRE, CWE-327 - Use of a Broken or Risky Cryptographic Algorithm
  • -
  • SANS Top 25 - Porous Defenses
  • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5547.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5547.html index 6324c1eeb5..201bf6b8c6 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5547.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S5547.html @@ -118,6 +118,5 @@

    Standards

  • OWASP Top 10 2017 Category A3 - Sensitive Data Exposure
  • MITRE, CWE-327 - Use of a Broken or Risky Cryptographic Algorithm
  • -
  • SANS Top 25 - Porous Defenses
  • diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6353.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6353.html index 70bdce9180..cb5d24a2e8 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6353.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6353.html @@ -1,7 +1,14 @@

    Why is this an issue?

    -

    With regular expressions syntax, it’s possible to express the same thing in many ways. For example, to match a two-digit number, one could write -[0-9]{2,2} or \d{2}. Latter is not only shorter in terms of expression length, but also easier to read and thus to maintain. -This rule recommends to replace some bulky quantifiers and character classes with more concise equivalents:

    +

    A regular expression is a sequence of characters that specifies a match pattern in text. Among the most important concepts are:

    +
      +
    • Character classes: defines a set of characters, any one of which can occur in an input string for a match to succeed.
    • +
    • Quantifiers: used to specify how many instances of a character, group, or character class must be present in the input for a match.
    • +
    • Wildcard (.): matches all characters except line terminators (also matches them if the s flag is set).
    • +
    +

    Many of these features include shortcuts of widely used expressions, so there is more than one way to construct a regular expression to achieve the +same results. For example, to match a two-digit number, one could write [0-9]{2,2} or \d{2}. The latter is not only shorter +but easier to read and thus to maintain.

    +

    This rule recommends replacing some quantifiers and character classes with more concise equivalents:

    • \d for [0-9] and \D for [^0-9]
    • \w for [A-Za-z0-9_] and \W for [^A-Za-z0-9_]
    • @@ -10,16 +17,15 @@

      Why is this an issue?

    • x? for x{0,1}, x* for x{0,}, x+ for x{1,}, x{N} for x{N,N}
    -

    Noncompliant code example

    -
    -r"[0-9]" # Noncompliant - same as r"\d"
    -r"[^0-9]" # Noncompliant - same as r"\D"
    +
    +r"[0-9]"        # Noncompliant - same as r"\d"
    +r"[^0-9]"       # Noncompliant - same as r"\D"
     r"[A-Za-z0-9_]" # Noncompliant - same as r"\w"
    -r"[\w\W]" # Noncompliant - same as r"."
    -r"a{0,}" # Noncompliant - same as r"a*"
    +r"[\w\W]"       # Noncompliant - same as r"."
    +r"a{0,}"        # Noncompliant - same as r"a*"
     
    -

    Compliant solution

    -
    +

    Use the more concise version to make the regex expression more readable.

    +
     r"\d"
     r"\D"
     r"\w"
    diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6554.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6554.html
    index 565495b768..584bc1a503 100644
    --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6554.html
    +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6554.html
    @@ -1,11 +1,11 @@
    -

    This rule ensures that Django models have a str method defined.

    +

    This rule ensures that Django models have a __str__ method defined.

    Why is this an issue?

    -

    The str method in Django models is used to represent the model instance as a string. For example, the return value of this -method will be inserted in a template when displaying an object in the Django admin site. Without this method, the model instance will be represented -by its object identifier, which is not meaningful to end-users. This can result in confusion and make debugging more difficult.

    +

    The __str__ method in Django models is used to represent the model instance as a string. For example, the return value of this method +will be inserted in a template when displaying an object in the Django admin site. Without this method, the model instance will be represented by its +object identifier, which is not meaningful to end-users. This can result in confusion and make debugging more difficult.

    How to fix it

    -

    To fix this issue, the Django model must define a str method that returns a string representation of the instance. This -string should be meaningful to end-users and provide information about the model instance.

    +

    To fix this issue, the Django model must define a __str__ method that returns a string representation of the instance. This string +should be meaningful to end-users and provide information about the model instance.

    Code examples

    Noncompliant code example

    diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6559.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6559.html
    index e10654984b..86936ea35a 100644
    --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6559.html
    +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6559.html
    @@ -1,10 +1,10 @@
    -

    This rule discourages the use of exclude or all with ModelForm in Django and suggests using fields instead.

    +

    This rule discourages the use of exclude or __all__ with ModelForm in Django and suggests using fields instead.

    Why is this an issue?

    In Django, when creating a ModelForm, it is common to use exclude to remove fields from the form. It is also possible to -set the fields value to all to conveniently indicate that all the model fields should be included in the form. -However, this can lead to security issues when new fields are added to the model, as they will automatically be included in the form, which may not be -intended. Additionally, exclude or all can make it harder to maintain the codebase by hiding the dependencies -between the model and the form.

    +set the fields value to __all__ to conveniently indicate that all the model fields should be included in the form. However, +this can lead to security issues when new fields are added to the model, as they will automatically be included in the form, which may not be +intended. Additionally, exclude or __all__ can make it harder to maintain the codebase by hiding the dependencies between +the model and the form.

    How to fix it

    Developers should use the "fields" attribute instead of "exclude" or "all" when creating ModelForms in Django. This ensures that all fields are explicitly listed and makes it clear what fields are included in the form.

    diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6660.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6660.html index 3d16341f87..51e5161584 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6660.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6660.html @@ -31,7 +31,7 @@

    Noncompliant code example

    class MyClass: ... -def foo(a) +def foo(a): if type(a) == MyClass: # Noncompliant ...
    @@ -40,7 +40,7 @@

    Compliant solution

    class MyClass: ... -def foo(a) +def foo(a): if isinstance(a, MyClass): ...
    diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6660.json b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6660.json index 3087ef3485..bc685467e3 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6660.json +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6660.json @@ -1,6 +1,12 @@ { - "title": "\u0027isinstance()\u0027 should be preferred to direct type comparisons", + "title": "\"isinstance()\" should be preferred to direct type comparisons", "type": "CODE_SMELL", + "code": { + "impacts": { + "MAINTAINABILITY": "MEDIUM" + }, + "attribute": "CONVENTIONAL" + }, "status": "ready", "remediation": { "func": "Constant\/Issue", diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6799.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6799.html index b71f54c7c2..ed5048cfd1 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6799.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6799.html @@ -1,25 +1,25 @@ -

    This rule raises an issue f-strings are deeply nested.

    +

    This rule raises an issue when "f-strings" are deeply nested.

    Why is this an issue?

    -

    Through PEP 701, Python 3.12 lifts restrictions on how to construct f-strings.

    -

    Prior to Python 3.12, it was not possible to reuse string quotes when nesting f-strings. Therefore, the maximum level of nesting was:

    +

    Through PEP 701, Python 3.12 lifts restrictions on how to construct "f-strings".

    +

    Prior to Python 3.12, it was not possible to reuse string quotes when nesting "f-strings". Therefore, the maximum level of nesting was:

     f"""{f'''{f'{f"{1+1}"}'}'''}"""
     
    -

    It is now possible to arbitrarily nest f-strings by reusing string quotes. The following snippet is therefore valid:

    +

    It is now possible to arbitrarily nest "f-strings" by reusing string quotes. The following snippet is therefore valid:

     f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}"
     
    -

    It is, however, not recommended to nest f-strings too deeply as this would make the code confusing and hard to maintain.

    -

    This rule will raise an issue if f-strings literals are nested more than 3 times.

    +

    It is, however, not recommended to nest "f-strings" too deeply as this would make the code confusing and hard to maintain.

    +

    This rule will raise an issue when "f-string" literals are nested 3 times or more.

    How to fix it

    -

    To fix this issue, refactor the code to avoid nesting f-string literals too deeply. This may be done by introducing new variables to store +

    To fix this issue, refactor the code to avoid nesting "f-string" literals too deeply. This may be done by introducing new variables to store intermediate results.

    Code examples

    Noncompliant code example

     hello = "Hello"
     name = "John"
    -my_string = f"{f"{f"{hello}"},"} {name}!" # Noncompliant: deep nesting of f-strings is confusing
    +my_string = f"{f"{f"{hello}"},"} {name}!" # Noncompliant: deep nesting of "f-strings" is confusing
     

    Compliant solution

    @@ -31,7 +31,7 @@ 

    Compliant solution

    Resources

    Documentation

    diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6799.json b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6799.json index 33948088c5..408bfedfc4 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6799.json +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S6799.json @@ -1,5 +1,5 @@ { - "title": "f-strings should not be nested too deeply", + "title": "\"f-strings\" should not be nested too deeply", "type": "CODE_SMELL", "status": "ready", "remediation": { diff --git a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S905.html b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S905.html index 8d1aadfdef..fc50ebf254 100644 --- a/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S905.html +++ b/python-checks/src/main/resources/org/sonar/l10n/py/rules/python/S905.html @@ -1,23 +1,29 @@ +

    Statements with no side effects and no change of control flow do not contribute to the functionality of the code and can indicate a programming +error.

    Why is this an issue?

    -

    Any statement, other than a pass, ... (ellipsis) or an empty statement (i.e. a single semicolon ";"), which -has no side effect and does not result in a change of control flow will normally indicate a programming error, and therefore should be refactored.

    -

    Noncompliant code example

    -
    -a == 1 # Noncompliant; was assignment intended?
    -a < b # Noncompliant; have we forgotten to assign the result to a variable?
    -
    +

    When writing code, it is important to ensure that each statement serves a purpose and contributes to the overall functionality of the program. When +they have no side effects or do not change the control flow, they can either indicate a programming error or be redundant:

    +
      +
    1. The code does not behave as intended: The statements are expected to have an effect but they do not. This can be caused by mistyping, + copy-and-paste errors, etc.
    2. +
    3. The statements are residual after a refactoring.
    4. +

    Exceptions

    +

    Intentionally empty statement

    +

    Statements such as pass or ... (ellipsis) are clearly meant to have no effect and may be used to indicate an +implementation is missing. No issue will be raised in this case.

    Strings

    Some projects use string literals as comments. By default, this rule will not raise an issue on these strings. Reporting on string literals can be -enabled by setting the rule parameter "reportOnStrings" to "true".

    +enabled by setting the rule parameter reportOnStrings to true.

    -class MyClass:
    -    myattr = 42
    -    """This is an attribute"""  # Noncompliant by default. Set "reportOnStrings" to "false"
    +def foo():
    +    bar()
    +    """Some comment"""  # Compliant by default. Noncompliant with "reportOnStrings" set to "true"
    +    qix()
     

    Operators

    -

    By default, this rule considers that no arithmetic operator has a side effect. Some rare projects redefine operators and add a side effect. You can -list such operators in the rule parameter "ignoredOperators".

    +

    By default, this rule considers that no arithmetic operator has a side effect. Some projects may redefine operators and add a side effect. You can +list such operators in the rule parameter ignoredOperators.

     def process(p, beam):
         """
    @@ -26,8 +32,29 @@ 

    Exceptions

    """ p | "create" >> beam.Create() # Noncompliant by default
    +

    How to fix it

    +

    Identify statements that do not contribute to the functionality of the code and verify if they are intended to be part of the logic. If they are, +there is a bug to be fixed. If they are not, then they are redundant and should be removed.

    +

    Code examples

    +

    Noncompliant code example

    +
    +def get_result():
    +    result = 42
    +    if should_be_zero():
    +        result == 0 # Noncompliant: no side effect, was an assignment intended?
    +    return result
    +
    +

    Compliant solution

    +
    +def get_result():
    +    result = 42
    +    if should_be_zero():
    +        result = 0 # Compliant
    +    return result
    +

    Resources

    +

    Standards

    diff --git a/sonarpedia.json b/sonarpedia.json index 8f5e5b926d..f4a3a97a7e 100644 --- a/sonarpedia.json +++ b/sonarpedia.json @@ -3,7 +3,7 @@ "languages": [ "PY" ], - "latest-update": "2023-10-09T13:33:42.838821515Z", + "latest-update": "2023-11-01T11:03:52.033339700Z", "options": { "no-language-in-filenames": true, "preserve-filenames": true