Remove conditional statements that never execute
Remove conditional statements that never execute
Fix raise statements to include missing 'from'
Fix raise statements to include missing 'from'
Move statements outside of loops where possible
Move statements outside of loops where possible
Remove functions and classes that are never used
Remove functions and classes that are never used
Optimize singleton equality comparisons
Optimize singleton equality comparisons
Break out common code from if-else blocks
Break out common code from if-else blocks
Simplify control flow within if statements
Simplify control flow within if statements
Swap if-else branches where beneficial
Swap if-else branches where beneficial
Apply early return pattern to simplify function
Apply early return pattern to simplify function
Use continue statement early in loops to reduce nesting
Use continue statement early in loops to reduce nesting
Remove unnecessary enumerate calls
Remove unnecessary enumerate calls
Remove unused arguments in zip
Remove unused arguments in zip
Replace map and lambda with list comprehensions
Replace map and lambda with list comprehensions
Replace filter and lambda with list comprehensions
Replace filter and lambda with list comprehensions
Remove unnecessary else statements
Remove unnecessary else statements
Replace complex filtering logic with filter function
Replace complex filtering logic with filter function
Merge chained comparisons into a single expression
Merge chained comparisons into a single expression
Remove unnecessary casts of comprehensions
Remove unnecessary casts of comprehensions
Remove redundant casts in chained calls
Remove redundant casts in chained calls
Fix if statements with unnecessary return
Fix if statements with unnecessary return
Refactor if statements that unnecessarily assign values
Refactor if statements that unnecessarily assign values
Replace function calls with simpler literals where possible
Replace function calls with simpler literals where possible
Use collection literals for adding or updating collections
Use collection literals for adding or updating collections
Simplify the unpacking of collections
Simplify the unpacking of collections
Remove duplicate elements from sets
Remove duplicate elements from sets
Break out starred arguments into separate variables
Break out starred arguments into separate variables
Replace .loc and .at with .iloc and .iat for performance
Replace .loc and .at with .iloc and .iat for performance
Replace .iterrows with direct indexing for performance
Replace .iterrows with direct indexing for performance
Replace .iterrows with .itertuples for better performance
Replace .iterrows with .itertuples for better performance
Replace for loops with set or list comprehensions
Replace for loops with set or list comprehensions
Replace set comprehensions with union operations
Replace set comprehensions with union operations
Replace list append in a loop with concatenation
Replace list append in a loop with concatenation
Replace for loops with dictionary comprehensions
Replace for loops with dictionary comprehensions
Use implicit dictionary keys, values, and items
Use implicit dictionary keys, values, and items
Replace dictionary assignments with literals
Replace dictionary assignments with literals
Replace dictionary update with literal merge
Replace dictionary update with literal merge
Replace dict comp assignments with literals
Replace dict comp assignments with literals
Replace dict comp updates with literal merge
Replace dict comp updates with literal merge
Simplify the unpacking of dictionaries
Simplify the unpacking of dictionaries
Remove duplicate keys from dictionaries
Remove duplicate keys from dictionaries
Replace implicit matrix multiplication for clarity and performance
Replace implicit matrix multiplication for clarity and performance
Replace subscript looping with more efficient methods
Replace subscript looping with more efficient methods
Replace implicit dot products with explicit calls
Replace implicit dot products with explicit calls
Simplify unnecessary transposes in arrays
Simplify unnecessary transposes in arrays
Optimize matrix multiplications with transpose operations
Optimize matrix multiplications with transpose operations
Use defaultdict for cleaner default value handling
Use defaultdict for cleaner default value handling
Remove redundant lambdas and use direct function calls
Remove redundant lambdas and use direct function calls
Remove unnecessary comprehensions
Remove unnecessary comprehensions
Simplify complex boolean expressions
Simplify complex boolean expressions
Simplify constrained range expressions
Simplify constrained range expressions
Simplify boolean expressions using symbolic math
Simplify boolean expressions using symbolic math
Inline comprehensions in mathematical expressions
Inline comprehensions in mathematical expressions
Simplify iterators in mathematical expressions
Simplify iterators in mathematical expressions
Replace negated numeric comparisons with direct comparisons
Replace negated numeric comparisons with direct comparisons
<= b. This makes the intended comparison more explicit and can improve both the readability of the code and its execution speed by using simpler operations.Optimize type checks within 'in' and 'not in' expressions
Optimize type checks within 'in' and 'not in' expressions
Remove redundant chained method calls
Remove redundant chained method calls
Remove unnecessary calls to iter()
Remove unnecessary calls to iter()
Replace sorted calls with heapq for performance in large collections
Replace sorted calls with heapq for performance in large collections
Add missing context managers for file and resource handling
Add missing context managers for file and resource handling
Remove functions that are duplicated in the codebase
Remove functions that are duplicated in the codebase
Remove duplicate import statements
Remove duplicate import statements
Remove unused import statements
Remove unused import statements
Transforms keys in the source to items
Transforms keys in the source to items
Transforms items in the source to keys
Transforms items in the source to keys
Transforms items in the source to values
Transforms items in the source to values
Applies a transformation for keys to items in the source
Applies a transformation for keys to items in the source
Applies a transformation for items to keys in the source
Applies a transformation for items to keys in the source
Applies a transformation for items to values in the source
Applies a transformation for items to values in the source
Simplify assignments that are immediately returned
Simplify assignments that are immediately returned
Swap explicit if-else branches where beneficial
Swap explicit if-else branches where beneficial
Simplify assignments that are immediately returned
Simplify assignments that are immediately returned
Swaps explicit if-else branches where beneficial
Swaps explicit if-else branches where beneficial
replace string concatenation with f-strings
replace string concatenation with f-strings
Abstract class %r with abstract methods instantiated
Abstract class %r with abstract methods instantiated
Access to member %r before its definition line %s
Access to member %r before its definition line %s
Assigning to attribute %r not defined in class slots
Assigning to attribute %r not defined in class slots
Assigning result of a function call, where the function has no return
Assigning result of a function call, where the function has no return
Assigning result of a function call, where the function returns None
Assigning result of a function call, where the function returns None
step 1
'await' should be used within an async function
'await' should be used within an async function
Misconfigured section detected
Misconfigured section detected
Bad except clauses order (%s)
Bad except clauses order (%s)
Exception cause set to something which is not an exception, nor None
Exception cause set to something which is not an exception, nor None
Unsupported format character %r (%#02x) at index %d
Unsupported format character %r (%#02x) at index %d
Invalid value for plugin
Invalid value for plugin
The first reversed() argument is not a sequence
The first reversed() argument is not a sequence
Suspicious argument in %s.%s call
Suspicious argument in %s.%s call
Argument %r does not match format type %r
Argument %r does not match format type %r
Bad first argument %r given to super()
Bad first argument %r given to super()
Contains control characters that can permit obfuscated code executed differently than displayed
Contains control characters that can permit obfuscated code executed differently than displayed
Broken callable in collections
Broken callable in collections
Non-returning function returns
Non-returning function returns
Catching an exception which doesn't inherit from Exception: %s
Catching an exception which doesn't inherit from Exception: %s
Value %r in slots conflicts with class variable
Value %r in slots conflicts with class variable
'continue' not supported inside 'finally' clause
'continue' not supported inside 'finally' clause
Unpacking a dictionary in iteration without calling .items()
Unpacking a dictionary in iteration without calling .items()
Duplicate argument name %s in function definition
Duplicate argument name %s in function definition
Duplicate bases for class %r
Duplicate bases for class %r
Expected mapping for format string, not %s
Expected mapping for format string, not %s
%s already defined line %s
%s already defined line %s
Unable to import %s
Unable to import %s
Inconsistent method resolution order for class %r
Inconsistent method resolution order for class %r
Inheriting %r, which is not a class.
Inheriting %r, which is not a class.
init method is a generator
init method is a generator
Invalid format for all, must be tuple or list
Invalid format for all, must be tuple or list
Invalid object %r in all, must contain only strings
Invalid object %r in all, must contain only strings
bool does not return bool
bool does not return bool
bytes does not return bytes
bytes does not return bytes
Invalid unescaped character backspace, use '\b' instead.
Invalid unescaped character backspace, use '\b' instead.
Invalid unescaped character carriage-return, use '\r' instead.
Invalid unescaped character carriage-return, use '\r' instead.
Invalid unescaped character esc, use '\x1B' instead.
Invalid unescaped character esc, use '\x1B' instead.
Invalid unescaped character nul, use '\0' instead.
Invalid unescaped character nul, use '\0' instead.
Invalid unescaped character sub, use '\x1A' instead.
Invalid unescaped character sub, use '\x1A' instead.
Invalid unescaped character zero-width-space, use '\u200B' instead.
Invalid unescaped character zero-width-space, use '\u200B' instead.
Invalid assignment to 'class'. Should be a class definition but got a '%s'
Invalid assignment to 'class'. Should be a class definition but got a '%s'
Extending inherited Enum class '%s'
Extending inherited Enum class '%s'
%s does not support %s type argument
%s does not support %s type argument
Invalid usage of field(), %s
Invalid usage of field(), %s
format does not return str
format does not return str
getnewargs_ex does not return a tuple containing (tuple, dict)
getnewargs_ex does not return a tuple containing (tuple, dict)
getnewargs does not return a tuple
getnewargs does not return a tuple
hash does not return int
hash does not return int
index does not return int
index does not return int
length_hint does not return non-negative integer
length_hint does not return non-negative integer
len does not return non-negative integer
len does not return non-negative integer
Invalid metaclass %r used
Invalid metaclass %r used
repr does not return str
repr does not return str
Sequence index is not an int, slice, or instance with index
Sequence index is not an int, slice, or instance with index
Slice index is not an int, None, or instance with index
Slice index is not an int, None, or instance with index
Slice step cannot be 0
Slice step cannot be 0
Invalid slots object
Invalid slots object
Invalid object %r in slots, must contain only non empty strings
Invalid object %r in slots, must contain only non empty strings
Starred assignment target must be in a list or tuple
Starred assignment target must be in a list or tuple
str does not return str
str does not return str
Invalid unary operand type
Invalid unary operand type
UTF-16 and UTF-32 aren't backward compatible. Use UTF-8 instead
UTF-16 and UTF-32 aren't backward compatible. Use UTF-8 instead
Logging format string ends in middle of conversion specifier
Logging format string ends in middle of conversion specifier
Not enough arguments for logging format string
Not enough arguments for logging format string
Too many arguments for logging format string
Too many arguments for logging format string
Unsupported logging format character %r (%#02x) at index %d
Unsupported logging format character %r (%#02x) at index %d
An attribute defined in %s line %s hides this method
An attribute defined in %s line %s hides this method
The raise statement is not inside an except clause
The raise statement is not inside an except clause
format function is not called on str
format function is not called on str
Missing key %r in format string dictionary
Missing key %r in format string dictionary
Missing mandatory keyword argument %r in %s call
Missing mandatory keyword argument %r in %s call
Mixing named and unnamed conversion specifiers in format string
Mixing named and unnamed conversion specifiers in format string
Iterated dict '%s' is being modified inside for loop body, iterate through a copy of it instead.
Iterated dict '%s' is being modified inside for loop body, iterate through a copy of it instead.
Iterated set '%s' is being modified inside for loop body, iterate through a copy of it instead.
Iterated set '%s' is being modified inside for loop body, iterate through a copy of it instead.
%s %r has no %r member%s
%s %r has no %r member%s
Method %r has no argument
Method %r has no argument
No name %r in module %r
No name %r in module %r
Method %r should have 'self' as first argument
Method %r should have 'self' as first argument
No value for argument %s in %s call
No value for argument %s in %s call
iter returns non-iterator
iter returns non-iterator
Use of the non-existent %s operator
Use of the non-existent %s operator
Name %r is nonlocal and global
Name %r is nonlocal and global
nonlocal name %s found without binding
nonlocal name %s found without binding
Non-mapping value %s is used in a mapping context
Non-mapping value %s is used in a mapping context
Non-iterable value %s is used in an iterating context
Non-iterable value %s is used in an iterating context
Async context manager '%s' doesn't implement aenter and aexit.
Async context manager '%s' doesn't implement aenter and aexit.
Step 2
%s is not callable
%s is not callable
Context manager '%s' doesn't implement enter and exit.
Context manager '%s' doesn't implement enter and exit.
%r not properly in loop
%r not properly in loop
NotImplemented raised - should raise NotImplementedError
NotImplemented raised - should raise NotImplementedError
%s() got some positional-only arguments passed as keyword arguments: %s
%s() got some positional-only arguments passed as keyword arguments: %s
Invalid index for iterable length
Invalid index for iterable length
Raising %s while only classes or instances are allowed
Raising %s while only classes or instances are allowed
Raising a new style class which doesn't inherit from BaseException
Raising a new style class which doesn't inherit from BaseException
Argument %r passed by position and keyword in %s call
Argument %r passed by position and keyword in %s call
Attempted relative import beyond top-level package
Attempted relative import beyond top-level package
Got multiple values for keyword argument %r in function call
Got multiple values for keyword argument %r in function call
Return with argument inside generator
Return with argument inside generator
Explicit return in init
Explicit return in init
Return outside function
Return outside function
singledispatch decorator should not be used with methods, use singledispatchmethod instead.
singledispatch decorator should not be used with methods, use singledispatchmethod instead.
singledispatchmethod decorator should not be used with functions, use singledispatch instead.
singledispatchmethod decorator should not be used with functions, use singledispatch instead.
Can use starred expression only in assignment target
Can use starred expression only in assignment target
Syntax error detected
Syntax error detected
Not enough arguments for format string
Not enough arguments for format string
Too many arguments for format string
Too many arguments for format string
Too many positional arguments for %s call
Too many positional arguments for %s call
More than one starred expression in assignment
More than one starred expression in assignment
Format string ends in middle of conversion specifier
Format string ends in middle of conversion specifier
Undefined variable name %r in all
Undefined variable name %r in all
Undefined variable %r
Undefined variable %r
Unexpected keyword argument %r in %s call
Unexpected keyword argument %r in %s call
The special method %r expects %s param(s), %d %s given
The special method %r expects %s param(s), %d %s given
'%s' is unhashable and can't be used as a %s in a %s
'%s' is unhashable and can't be used as a %s in a %s
Attempting to unpack a non-sequence%s
Attempting to unpack a non-sequence%s
Unrecognized inline option
Unrecognized inline option
Unrecognized option in configuration file
Unrecognized option in configuration file
Value '%s' is unsubscriptable
Value '%s' is unsubscriptable
%r does not support item assignment
%r does not support item assignment
Unsupported binary operation
Unsupported binary operation
%r does not support item deletion
%r does not support item deletion
Value '%s' doesn't support membership test
Value '%s' doesn't support membership test
Using variable %r before assignment
Using variable %r before assignment
Name %r is used prior to global declaration
Name %r is used prior to global declaration
Yield inside async function
Yield inside async function
Yield outside function
Yield outside function
Improper context manager
Improper context manager
Incorrect exception context
Incorrect exception context
Bad value in option
Bad value in option
Possible missing member
Possible missing member
Non-iterator returned in old style
Non-iterator returned in old style
Unbalanced tuple unpacking
Unbalanced tuple unpacking
Unhashable key in dict
Unhashable key in dict
Method %r is abstract in class %r but is not overridden in child class %r
Method %r is abstract in class %r but is not overridden in child class %r
Anomalous backslash in string: '%s'. String constant might be missing an r prefix.
Anomalous backslash in string: '%s'. String constant might be missing an r prefix.
Anomalous Unicode escape in byte string: '%s'. String constant might be missing an r or u prefix.
Anomalous Unicode escape in byte string: '%s'. String constant might be missing an r or u prefix.
%s %s %r method
%s %s %r method
Positional arguments appear to be out of order
Positional arguments appear to be out of order
%s %s %r method
%s %s %r method
Assert statement has a string literal as its first argument. The assert will %s fail.
Assert statement has a string literal as its first argument. The assert will %s fail.
Assert called on a populated tuple. Did you mean 'assert x,y'?
Assert called on a populated tuple. Did you mean 'assert x,y'?
Attribute %r defined outside init
Attribute %r defined outside init
Bad usage of builtin function
Bad usage of builtin function
Suspicious %s-part chained comparison using semantically incompatible operators (%s)
Suspicious %s-part chained comparison using semantically incompatible operators (%s)
Bad magic method name
Bad magic method name
Invalid format string
Invalid format string
Format string dictionary key should be a string, not %s
Format string dictionary key should be a string, not %s
Bad indentation. Found %s %s, expected %s
Bad indentation. Found %s %s, expected %s
'%s' is not a valid mode for open.
'%s' is not a valid mode for open.
Static method with %r as first argument
Static method with %r as first argument
threading.Thread needs the target function
threading.Thread needs the target function
No exception type(s) specified
No exception type(s) specified
Exception to catch is the result of a binary '%s' operation
Exception to catch is the result of a binary '%s' operation
Using datetime.time in a boolean context.
Using datetime.time in a boolean context.
Catching too general exception %s
Catching too general exception %s
Raising too general exception: %s
Raising too general exception: %s
Cell variable %s defined in loop
Cell variable %s defined in loop
Comparing against a callable, did you omit the parenthesis?
Comparing against a callable, did you omit the parenthesis?
Following 'as' with another context manager looks like a tuple.
Following 'as' with another context manager looks like a tuple.
Consider using ternary expression
Consider using ternary expression
Dangerous default value %s as argument
Dangerous default value %s as argument
Using deprecated argument %s of method %s()
Using deprecated argument %s of method %s()
Using deprecated class %s of module %s
Using deprecated class %s of module %s
Using deprecated decorator %s()
Using deprecated decorator %s()
Using deprecated method %s()
Using deprecated method %s()
Deprecated module %r
Deprecated module %r
Deprecated typing alias used
Deprecated typing alias used
Parameter documentation differs
Parameter documentation differs
Type documentation differs
Type documentation differs
Catching previously caught exception type %s
Catching previously caught exception type %s
Duplicate key %r in dictionary
Duplicate key %r in dictionary
Duplicate string formatting argument %r, consider passing as named argument
Duplicate string formatting argument %r, consider passing as named argument
Duplicate value %r in set
Duplicate value %r in set
eq implemented without hash
eq implemented without hash
Use of eval
Use of eval
Use of exec
Use of exec
Expression '%s' is assigned to nothing
Expression '%s' is assigned to nothing
Using an f-string that does not have any interpolated variables
Using an f-string that does not have any interpolated variables
FIXME comment detected
FIXME comment detected
Leaving functions creating breakpoints in production code is not recommended
Leaving functions creating breakpoints in production code is not recommended
Step 3
Format string contains both automatic field numbering and manual field specification
Format string contains both automatic field numbering and manual field specification
Using formatting for a string that does not have any interpolated variables
Using formatting for a string that does not have any interpolated variables
Using the global statement at the module level
Using the global statement at the module level
Using the global statement
Using the global statement
Using global for %r but no assignment is done
Using global for %r but no assignment is done
Global variable %r undefined at the module level
Global variable %r undefined at the module level
Implicit string concatenation found in %s
Implicit string concatenation found in %s
Module import itself
Module import itself
Quote delimiter %s is inconsistent with the rest of the file
Quote delimiter %s is inconsistent with the rest of the file
%s default type is %s. Expected str or None.
%s default type is %s. Expected str or None.
Using invalid lookup key %r in format specifier %r
Using invalid lookup key %r in format specifier %r
Method %r was expected to be %r, found it instead as %r
Method %r was expected to be %r, found it instead as %r
Second argument of isinstance is not a type
Second argument of isinstance is not a type
Keyword argument before variable positional arguments list in the definition of %s function
Keyword argument before variable positional arguments list in the definition of %s function
%r will be included in %r since a positional-only parameter with this name already exists
%r will be included in %r since a positional-only parameter with this name already exists
Use %s formatting in logging functions
Use %s formatting in logging functions
Use %s formatting in logging functions
Use %s formatting in logging functions
Use %s formatting in logging functions
Use %s formatting in logging functions
%s statement in finally block may swallow exception
%s statement in finally block may swallow exception
'lru_cache(maxsize=None)' or 'cache' will keep all method args alive indefinitely, including 'self'
'lru_cache(maxsize=None)' or 'cache' will keep all method args alive indefinitely, including 'self'
future import is not the first non docstring statement
future import is not the first non docstring statement
Missing documentation for some parameters
Missing documentation for some parameters
Missing keyword argument %r for format string
Missing keyword argument %r for format string
Missing format attribute %r in format specifier %r
Missing format attribute %r in format specifier %r
Missing parameter documentation
Missing parameter documentation
Using a conditional statement with potentially wrong function or method call due to missing parentheses
Using a conditional statement with potentially wrong function or method call due to missing parentheses
Missing documentation about raises
Missing documentation about raises
Missing return documentation
Missing return documentation
Missing return type documentation
Missing return type documentation
Missing timeout argument for method '%s' can cause your program to hang indefinitely
Missing timeout argument for method '%s' can cause your program to hang indefinitely
Missing type documentation
Missing type documentation
Missing yield documentation
Missing yield documentation
Missing yield type documentation
Missing yield type documentation
Iterated list '%s' is being modified inside for loop body, consider iterating through a copy of it instead.
Iterated list '%s' is being modified inside for loop body, consider iterating through a copy of it instead.
Multiple constructor documentation
Multiple constructor documentation
Named expression used without context
Named expression used without context
Comparison %s should be %s
Comparison %s should be %s
Do not use nested call of '%s'; it's possible to do '%s' instead
Do not use nested call of '%s'; it's possible to do '%s' instead
%s name '%s' contains a non-ASCII character.
%s name '%s' contains a non-ASCII character.
init method from a non direct base class %r is called
init method from a non direct base class %r is called
Non-string value assigned to name
Non-string value assigned to name
Overlapping exception clauses
Overlapping exception clauses
Method %r overrides a method decorated with typing.final which is defined in class %r
Method %r overrides a method decorated with typing.final which is defined in class %r
Exception statement has no effect
Exception statement has no effect
Statement seems to have no effect
Statement seems to have no effect
String statement has no effect
String statement has no effect
Possibly unused variable %r
Possibly unused variable %r
Prefer importing %r instead of %r
Prefer importing %r instead of %r
Access to a protected member %s of a client class
Access to a protected member %s of a client class
Consider explicitly re-raising using %s'%s from %s'
Consider explicitly re-raising using %s'%s from %s'
Exception arguments suggest string formatting might be intended
Exception arguments suggest string formatting might be intended
Redeclared variable %r in assignment
Redeclared variable %r in assignment
Redefining built-in %r
Redefining built-in %r
Redefinition of loop variable
Redefinition of loop variable
Redefining name %r from outer scope (line %s)
Redefining name %r from outer scope (line %s)
Redefined slots %r in subclass
Redefined slots %r in subclass
Redundant returns documentation
Redundant returns documentation
The u prefix for strings is no longer necessary in Python >=3.0
The u prefix for strings is no longer necessary in Python >=3.0
Redundant use of %s with constant value %r
Redundant use of %s with constant value %r
Redundant yields documentation
Redundant yields documentation
Reimport %r (imported line %s)
Reimport %r (imported line %s)
'return' shadowed by the 'finally' clause.
'return' shadowed by the 'finally' clause.
Assigning the same variable %r to itself
Assigning the same variable %r to itself
Invalid assignment to %s in method
Invalid assignment to %s in method
Shadowed %r (imported line %s)
Shadowed %r (imported line %s)
Using copy.copy(os.environ). Use os.environ.copy() instead.
Using copy.copy(os.environ). Use os.environ.copy() instead.
Signature differs from %s %r method
Signature differs from %s %r method
Class %r is a subclass of a class decorated with typing.final: %r
Class %r is a subclass of a class decorated with typing.final: %r
Using preexec_fn keyword which may be unsafe in the presence of threads
Using preexec_fn keyword which may be unsafe in the presence of threads
'subprocess.run' used without explicitly defining the value for 'check'.
'subprocess.run' used without explicitly defining the value for 'check'.
init method from base class %r is not called
init method from base class %r is not called
Super call without brackets
Super call without brackets
Too many try statements
Too many try statements
The except handler raises immediately
The except handler raises immediately
Possible unbalanced dict unpacking with %s: left side has %d label%s, right side has %d value%s
Possible unbalanced dict unpacking with %s: left side has %d label%s, right side has %d value%s
Possible unbalanced tuple unpacking with sequence %s: left side has %d label%s, right side has %d value%s
Possible unbalanced tuple unpacking with sequence %s: left side has %d label%s, right side has %d value%s
Using possibly undefined loop variable %r
Using possibly undefined loop variable %r
Unknown option value in configuration
Unknown option value in configuration
step 4
Unnecessary ellipsis constant
Unnecessary ellipsis constant
Lambda may not be necessary
Lambda may not be necessary
Unnecessary pass statement
Unnecessary pass statement
Unnecessary semicolon
Unnecessary semicolon
Unreachable code
Unreachable code
Using open without explicitly specifying an encoding
Using open without explicitly specifying an encoding
Unused argument %r
Unused argument %r
Unused format argument %r
Unused format argument %r
Unused key %r in format string dictionary
Unused key %r in format string dictionary
Unused %s
Unused %s
Unused private member %s.%s
Unused private member %s.%s
Unused variable %r
Unused variable %r
Unused import(s) %s from wildcard import of %s
Unused import(s) %s from wildcard import of %s
Else clause on loop without a break statement, remove the else and de-indent all the code inside it
Else clause on loop without a break statement, remove the else and de-indent all the code inside it
Useless parameter documentation
Useless parameter documentation
Useless parent or super() delegation in method %r
Useless parent or super() delegation in method %r
Useless type documentation
Useless type documentation
'%s()' directly created in 'with' has no effect
'%s()' directly created in 'with' has no effect
Using a conditional statement with a constant value
Using a conditional statement with a constant value
F-strings are not supported by all versions included in the py-version setting
F-strings are not supported by all versions included in the py-version setting
typing.final is not supported by all versions included in the py-version setting
typing.final is not supported by all versions included in the py-version setting
While used unnecessarily
While used unnecessarily
Wildcard import %s
Wildcard import %s
Invalid exception operation. %s
Invalid exception operation. %s
Broad except clause used
Broad except clause used
Cache with max size None
Cache with max size None
Implicit string concatenation in sequence
Implicit string concatenation in sequence
LRU cache decorating method
LRU cache decorating method
Assignment from None in old Python version
Assignment from None in old Python version
Deprecated argument in old Python version
Deprecated argument in old Python version
Deprecated class in old Python version
Deprecated class in old Python version
Deprecated decorator in old Python version
Deprecated decorator in old Python version
Deprecated method in old Python version
Deprecated method in old Python version
Deprecated module in old Python version
Deprecated module in old Python version
Empty docstring in old Python version
Empty docstring in old Python version
Missing parameter documentation in old Python version
Missing parameter documentation in old Python version
Missing returns documentation in old Python version
Missing returns documentation in old Python version
Missing type documentation in old Python version
Missing type documentation in old Python version
Missing yields documentation in old Python version
Missing yields documentation in old Python version
Non-iterator returned in old Python version
Non-iterator returned in old Python version
Type check is unidiomatic in old Python version
Type check is unidiomatic in old Python version
Unpacking a non-sequence in old Python version
Unpacking a non-sequence in old Python version
Useless delegation to super method
Useless delegation to super method
Class method %s should have %s as first argument
Class method %s should have %s as first argument
Inconsistent docstring quotes
Inconsistent docstring quotes
PEP8 recommends UTF-8 as encoding for Python files
PEP8 recommends UTF-8 as encoding for Python files
Metaclass class method %s should have %s as first argument
Metaclass class method %s should have %s as first argument
Metaclass method %s should have %s as first argument
Metaclass method %s should have %s as first argument
Consider iterating the dictionary directly instead of calling .keys()
Consider iterating the dictionary directly instead of calling .keys()
Consider using 'any' or 'all'
Consider using 'any' or 'all'
Consider iterating with .items()
Consider iterating with .items()
Consider using enumerate instead of iterating with range and len
Consider using enumerate instead of iterating with range and len
Formatting a regular string which could be an f-string
Formatting a regular string which could be an f-string
Mutation during dictionary initialization
Mutation during dictionary initialization
Disallowed name '%s'
Disallowed name '%s'
First line of docstring is empty
First line of docstring is empty
Empty %s docstring
Empty %s docstring
Import outside toplevel (%s)
Import outside toplevel (%s)
Private name imported
Private name imported
Invalid characters %r in a docstring
Invalid characters %r in a docstring
%s name '%s' doesn't conform to %s
%s name '%s' doesn't conform to %s
Line too long (%s/%s)
Line too long (%s/%s)
Comparison constant misplaced
Comparison constant misplaced
Missing class docstring
Missing class docstring
Final newline missing
Final newline missing
Missing function or method docstring
Missing function or method docstring
Missing module docstring
Missing module docstring
Mixed line endings LF and CRLF
Mixed line endings LF and CRLF
Multiple imports on one line (%s)
Multiple imports on one line (%s)
More than one statement on a single line
More than one statement on a single line
%s name '%s' contains a non-ASCII character, use an ASCII-only alias for import.
%s name '%s' contains a non-ASCII character, use an ASCII-only alias for import.
%s name '%s' contains a non-ASCII character, consider renaming it.
%s name '%s' contains a non-ASCII character, consider renaming it.
Class slots should be a non-string iterable
Class slots should be a non-string iterable
Comparison %s should be %s
Comparison %s should be %s
Unnecessary parens after %r keyword
Unnecessary parens after %r keyword
Too many lines in module (%s/%s)
Too many lines in module (%s/%s)
Trailing newlines
Trailing newlines
Trailing whitespace
Trailing whitespace
TypeVar cannot be both covariant and contravariant
TypeVar cannot be both covariant and contravariant
Type variable name does not reflect variance%s
Type variable name does not reflect variance%s
TypeVar name '%s' does not match assigned variable name '%s'
TypeVar name '%s' does not match assigned variable name '%s'
Unexpected line ending format. There is '%s' while it should be '%s'.
Unexpected line ending format. There is '%s' while it should be '%s'.
Imports from package %s are not grouped
Imports from package %s are not grouped
Use isinstance() rather than type() for a typecheck.
Use isinstance() rather than type() for a typecheck.
Lambda expression called directly. Execute the expression inline instead.
Lambda expression called directly. Execute the expression inline instead.
Unnecessarily calls dunder method %s. %s.
Unnecessarily calls dunder method %s. %s.
Lambda expression assigned to a variable. Define a function using the 'def' keyword instead.
Lambda expression assigned to a variable. Define a function using the 'def' keyword instead.
Consider changing '%s' to '%s'
Consider changing '%s' to '%s'
'%s' can be simplified to '%s', if it is strictly a sequence, as an empty %s is falsey
'%s' can be simplified to '%s', if it is strictly a sequence, as an empty %s is falsey
'%s' can be simplified to '%s', if it is striclty a string, as an empty string is falsey
'%s' can be simplified to '%s', if it is striclty a string, as an empty string is falsey
'%s' can be simplified to '%s', if it is strictly an int, as 0 is falsey
'%s' can be simplified to '%s', if it is strictly an int, as 0 is falsey
Do not use len(SEQUENCE) without comparison to determine if a sequence is empty
Do not use len(SEQUENCE) without comparison to determine if a sequence is empty
Use %s instead
Use %s instead
Use a sequence type when iterating over values
Use a sequence type when iterating over values
Import alias does not rename original package
Import alias does not rename original package
%s should be placed before %s
%s should be placed before %s
Import '%s' should be placed at the top of the module
Import '%s' should be placed at the top of the module
Wrong spelling of a word '%s' in a comment:
Wrong spelling of a word '%s' in a comment:
Wrong spelling of a word '%s' in a docstring:
Wrong spelling of a word '%s' in a docstring:
Blacklisted name used
Blacklisted name used
Comparison to empty string
Comparison to empty string
Comparison to zero
Comparison to zero
Using len as condition
Using len as condition
Missing docstring in public module/function/class
Missing docstring in public module/function/class
Misplaced comparison constant in old Python version
Misplaced comparison constant in old Python version
Non-ASCII name in old Python version
Non-ASCII name in old Python version
Unneeded not operator
Unneeded not operator
Simplify chained comparison between the operands
Simplify chained comparison between the operands
Comparison between constants: '%s %s %s' has a constant value
Comparison between constants: '%s %s %s' has a constant value
Redundant comparison - %s
Redundant comparison - %s
Boolean condition '%s' will always evaluate to '%s'
Boolean condition '%s' will always evaluate to '%s'
Consecutive elif with same condition
Consecutive elif with same condition
Consider alternative union syntax
Consider alternative union syntax
Consider merging these isinstance calls to isinstance(%s, (%s))
Consider merging these isinstance calls to isinstance(%s, (%s))
Consider refactoring into while condition
Consider refactoring into while condition
Consider using tuple unpacking for swapping variables
Consider using tuple unpacking for swapping variables
Consider using alias
Consider using alias
Consider using assignment expression
Consider using assignment expression
Consider using augmented assignment
Consider using augmented assignment
step 6
Consider using a dictionary comprehension
Consider using a dictionary comprehension
Use 'from %s import %s' instead
Use 'from %s import %s' instead
Consider using a generator instead '%s(%s)'
Consider using a generator instead '%s(%s)'
Consider using dict.get for getting values from a dict if a key is present or a default if not
Consider using dict.get for getting values from a dict if a key is present or a default if not
Consider merging these comparisons with 'in' by using '%s %sin (%s)'. Use a set instead if elements are hashable.
Consider merging these comparisons with 'in' by using '%s %sin (%s)'. Use a set instead if elements are hashable.
Consider using str.join(sequence) for concatenating strings from an iterable
Consider using str.join(sequence) for concatenating strings from an iterable
Consider using '%s' instead of unnecessary if block
Consider using '%s' instead of unnecessary if block
Consider using '%s' instead of unnecessary if block
Consider using '%s' instead of unnecessary if block
Consider using namedtuple or dataclass
Consider using namedtuple or dataclass
Consider using a set comprehension
Consider using a set comprehension
Consider using 'sys.exit' instead
Consider using 'sys.exit' instead
Consider using ternary (%s)
Consider using ternary (%s)
Consider using tuple
Consider using tuple
Consider using 'with' for resource-allocating operations
Consider using 'with' for resource-allocating operations
Cyclic import (%s)
Cyclic import (%s)
Similar lines in %s files
Similar lines in %s files
Else if used instead of elif
Else if used instead of elif
Empty comment detected
Empty comment detected
Either all return statements in a function should return an expression, or none of them should.
Either all return statements in a function should return an expression, or none of them should.
In '%s', use '%s' when comparing constant literals not '%s' ('%s')
In '%s', use '%s' when comparing constant literals not '%s' ('%s')
Magic value comparison
Magic value comparison
Consider using a decorator instead of calling classmethod
Consider using a decorator instead of calling classmethod
Unnecessary '%s' after 'break', %s
Unnecessary '%s' after 'break', %s
Unnecessary '%s' after 'continue', %s
Unnecessary '%s' after 'continue', %s
Unnecessary '%s' after 'raise', %s
Unnecessary '%s' after 'raise', %s
Unnecessary '%s' after 'return', %s
Unnecessary '%s' after 'return', %s
Method could be a function (no self-use)
Method could be a function (no self-use)
Consider using a decorator instead of calling staticmethod
Consider using a decorator instead of calling staticmethod
Prefer typing.NamedTuple
Prefer typing.NamedTuple
Cannot have defined parameters for properties
Cannot have defined parameters for properties
Redefining argument with the local name %r
Redefining argument with the local name %r
Redefined variable type
Redefined variable type
Redundant type hint for argument
Redundant type hint for argument
Boolean condition '%s' may be simplified to '%s'
Boolean condition '%s' may be simplified to '%s'
The if expression can be replaced with %s
The if expression can be replaced with %s
The if statement can be replaced with %s
The if statement can be replaced with %s
Boolean expression may be simplified to %s
Boolean expression may be simplified to %s
Do not raise StopIteration in generator, use return statement instead
Do not raise StopIteration in generator, use return statement instead
Consider using Python 3 style super() without arguments
Consider using Python 3 style super() without arguments
Code too complex
Code too complex
Too few public methods (%s/%s)
Too few public methods (%s/%s)
Too many ancestors (%s/%s)
Too many ancestors (%s/%s)
Too many arguments (%s/%s)
Too many arguments (%s/%s)
Too many boolean expressions in if statement (%s/%s)
Too many boolean expressions in if statement (%s/%s)
Too many branches (%s/%s)
Too many branches (%s/%s)
Too many instance attributes (%s/%s)
Too many instance attributes (%s/%s)
Too many local variables (%s/%s)
Too many local variables (%s/%s)
Too many nested blocks (%s/%s)
Too many nested blocks (%s/%s)
Too many public methods (%s/%s)
Too many public methods (%s/%s)
Too many return statements (%s/%s)
Too many return statements (%s/%s)
Too many statements (%s/%s)
Too many statements (%s/%s)
Disallow trailing comma tuple
Disallow trailing comma tuple
Unnecessary use of a comprehension, use %s instead.
Unnecessary use of a comprehension, use %s instead.
Unnecessary dictionary index lookup, use '%s' instead
Unnecessary dictionary index lookup, use '%s' instead
Unnecessary list index lookup, use '%s' instead
Unnecessary list index lookup, use '%s' instead
Use a generator instead '%s(%s)'
Use a generator instead '%s(%s)'
Consider using '%s' instead of a call to 'dict'.
Consider using '%s' instead of a call to 'dict'.
Consider using [] instead of list()
Consider using [] instead of list()
Use set for membership test
Use set for membership test
Class %r inherits from object, can be safely removed from bases in python3
Class %r inherits from object, can be safely removed from bases in python3
Useless option value
Useless option value
Useless return at end of function or method
Useless return at end of function or method
Old style no self use
Old style no self use
Old style simplifiable if statement
Old style simplifiable if statement
Old style too many nested blocks
Old style too many nested blocks
Replace bare except statements with explicit exceptions
Replace bare except statements with explicit exceptions
Simplify repeated if statements into one
Simplify repeated if statements into one
step 7
Insert default get statements with explicit default values
Insert default get statements with explicit default values
Replace any() with in for membership checks
Replace any() with in for membership checks
Invert negative any() and all() for better readability
Invert negative any() and all() for better readability
Merge except handlers with same body for better readability
Merge except handlers with same body for better readability
autofix/no-unused-vars
autofix/no-unused-vars
autofix/eqeqeq
autofix/eqeqeq
autofix/no-var
autofix/no-var
autofix/no-useless-catch
autofix/no-useless-catch
autofix/no-useless-concat
autofix/no-useless-concat
autofix/prefer-const
autofix/prefer-const
autofix/prefer-arrow-callback
autofix/prefer-arrow-callback
autofix/sort-imports
autofix/sort-imports
autofix/no-unneeded-ternary
autofix/no-unneeded-ternary
react/react-in-jsx-scope
react/react-in-jsx-scope
array-callback-return
array-callback-return
logical-assignment-operators
logical-assignment-operators
no-floating-decimal
no-floating-decimal
no-promise-executor-return
no-promise-executor-return
no-return-await
no-return-await
no-undef-init
no-undef-init
no-useless-rename
no-useless-rename
react/hook-use-state
react/hook-use-state
react/jsx-no-leaked-render
react/jsx-no-leaked-render
Regular expressions should not be too complicated
Regular expressions should not be too complicated
Overly complicated regular expressions are hard to read and to maintain and can easily cause hard-to-find bugs. If a regex is too complicated, you should consider replacing it or parts of it with regular code or splitting it apart into multiple patterns at least.
The complexity of a regular expression is determined as follows:
Each of the following operators increases the complexity by an amount equal to the current nesting level and also increases the current nesting level by one for its arguments:
`| - when multiple | operators are used together, the subsequent ones only increase the complexity by 1
Quantifiers (*, +, ?, etc.)
Non-capturing groups that set flags (such as (?i:some_pattern) or (?i)some_pattern`)
Lookahead and lookbehind assertions
Additionally, each use of the following features increase the complexity by 1 regardless of nesting:
character classes
back references
Jump statements should not be redundant
Jump statements should not be redundant
Jump statements, such as return, break and continue let you change the default flow of program execution, but jump statements that direct the control flow to the original direction are just a waste of keystrokes.
Test methods should be discoverable
Test methods should be discoverable
Classes subclassing only `unittest.TestCase are considered test cases, otherwise they might be mixins.
As classes subclassing unittest.TestCase will be executed as tests, they should define test methods and not be used as “abstract” parent helper. Methods within the class will be discovered by the test runner if their name starts with test. If a method intended to be a test does not respect this convention, it will not be executed.
This rule raises an issue when a method is not discoverable as a test and is never used within its test case class.
This rule will not raise if:
The method is called directly from another method.
The method overrides an existing one in unittest.TestCase (example: a tearDown` method).
return and yield should not be used in the same function
return and yield should not be used in the same function
Functions that use yield are known as “generators”. Before Python 3.3, generators cannot return values. Similarly, functions that use return cannot use yield. Doing so will cause a SyntaxError.
Either upgrade your version of Python to a version >= 3.3, or don’t use both return and yield in a function.
Built-in generic types should be preferred over the typing module in type hints
Built-in generic types should be preferred over the typing module in type hints
Python 3.9 introduced built-in generic types such as list[T], dict[T], set[T] to make type hints more concise and easier to read. These built-in types have the same functionality as their counterparts in the typing module, but are more readable and idiomatic.
Using types such as typing.List is confusing in the presence of the already existing built-in types. This can also create inconsistencies when different parts of the codebase use different syntaxes for the same type.
len should always return an integer greater than or equal to zero
len should always return an integer greater than or equal to zero
The `len special method enables to define the length of an object. As such it should always return an integer greater than or equal to 0. When the len(…) builtin is called on an object, any other return type will raise a TypeError and a negative integer will raise a ValueError.
This rule raises an issue when a len` method returns an expression which is not an integer greater than or equal to 0.
Server-side templates should not be vulnerable to injection attacks
Server-side templates should not be vulnerable to injection attacks
Server-side template injections occur in an application when the application retrieves data from a user or a third-party service and inserts it into a template, without sanitizing it first.
If an application contains a template that is vulnerable to injections, it is exposed to attacks that target the underlying rendering server.
A user with malicious intent can create requests that will cause the template to change its logic into unwanted behavior.
After creating the malicious request, the attacker can attack the servers affected by this vulnerability without relying on any prerequisites.
Results that depend on random number generation should be reproducible
Results that depend on random number generation should be reproducible
Data science and machine learning tasks make extensive use of random number generation. It may, for example, be used for:
Model initialization
Randomness is used to initialize the parameters of machine learning models. Initializing parameters with random values helps to break symmetry and prevents models from getting stuck in local optima during training. By providing a random starting point, the model can explore different regions of the parameter space and potentially find better solutions.
Regularization techniques
Randomness is used to introduce noise into the learning process. Techniques like dropout and data augmentation use random numbers to randomly drop or modify features or samples during training. This helps to regularize the model, reduce overfitting, and improve generalization performance.
Cross-validation and bootstrapping
Randomness is often used in techniques like cross-validation, where data is split into multiple subsets. By using a predictable seed, the same data splits can be generated, allowing for fair and consistent model evaluation.
Hyperparameter tuning
Many machine learning algorithms have hyperparameters that need to be tuned for optimal performance. Randomness is often used in techniques like random search or Bayesian optimization to explore the hyperparameter space. By using a fixed seed, the same set of hyperparameters can be explored, making the tuning process more controlled and reproducible.
Simulation and synthetic data generation
Randomness is often used in techniques such as data augmentation and synthetic data generation to generate diverse and realistic datasets.
To ensure that results are reproducible, it is important to use a predictable seed in this context.
The preferred way to do this in numpy is by instantiating a Generator object, typically through numpy.random.default_rng, which should be provided with a seed parameter.
Note that a global seed for RandomState can be set using numpy.random.seed or numpy.seed, this will set the seed for RandomState methods such as numpy.random.randn. This approach is, however, deprecated and Generator should be used instead. This is reported by rule S6711.
pandas.pipe method should be preferred over long chains of instructions
pandas.pipe method should be preferred over long chains of instructions
The pandas library provides many ways to filter, select, reshape and modify a data frame.
Pandas supports as well method chaining, which means that many DataFrame methods return a modified DataFrame.
This allows the user to chain multiple operations together, making it effortless perform several of them in one line of code:
Only defined names should be listed in all
Only defined names should be listed in all
The all property of a module is used to define the list of names that will be imported when performing a wildcard import of this module, i.e. when from mymodule import * is used.
In the following example:
Generic type statements should not use TypeVars
Generic type statements should not use TypeVars
Prior to Python 3.12, generic type aliases were defined as follows:
Python side effects should not be used inside a tf.function
Python side effects should not be used inside a tf.function
Python sides effects such as printing, mutating a list or a global variable, inside of a tensorflow.function may not behave as expected. Because of the Rules of tracing, the execution of side effects will depend on the input values of the function and will execute only once per tracing.
Static methods should not have self or cls arguments
Static methods should not have self or cls arguments
Unlike class and instance methods, static methods don’t receive an implicit first argument. Nonetheless naming the first argument self or clz guarantees confusion - either on the part of the original author, who may never understand why the arguments don’t hold the values he expected, or on that of future maintainers.
Iterable unpacking, for-in loops and yield from should use an Iterable object
Iterable unpacking, for-in loops and yield from should use an Iterable object
for-in loops, yield from and iterable unpacking only work with iterable objects. In order to be iterable, an object should have either an `iter method or a getitem method implementing the Sequence protocol.
When trying to iterate over an object which does not implement the required methods, a TypeError will be raised.
Below is an example of a basic implementation of a iterator with iter`:
Variables named as constants should not be reassigned
Variables named as constants should not be reassigned
There are no constants in Python, but when a variable is named with all uppercase letters, the convention is to treat it as a constant. I.e. to use it as a read-only variable, and not reassign its value.
Ignore this convention, and you run the risk of confusing other developers, particularly those with experience in other languages. This rule raises an issue each time a variable named with all uppercase letters is reassigned.
Sequence indexes must have an index method
Sequence indexes must have an index method
Objects can be used as sequence indexes to access a specific element from the sequence, through the following syntax:
Variables, classes and functions should be either defined or imported
Variables, classes and functions should be either defined or imported
Variables, Classes and functions should not be undefined, otherwise the code will fail with a NameError.
Assertions comparing incompatible types should not be made
Assertions comparing incompatible types should not be made
Calling `unittest methods assertEqual, assertNotEqual, assertIs or assertIsNot on objects of incompatible types will always fail or always succeed.
For methods assertEqual and assertNotEqual, arguments’ types are incompatible if:
they are unrelated builtin types such as string and integer.
they are instances of unrelated classes which do not implement ++eq++ or ++ne++ (if a class implements one of these methods it could compare to any other type it wants).
As for methods assertIs and assertIsNot, if arguments’ types are different it is not possible for them to point to the same object, thus assertIs will always fail and assertIsNot` will always succeed.
Dictionary unpacking should only be done with mapping objects
Dictionary unpacking should only be done with mapping objects
Dictionary unpacking allows you to pass the key-value pairs of a dictionary as keyword arguments to a function or merge dictionaries:
<> should not be used to test inequality
<> should not be used to test inequality
The operators <> and != are equivalent.
However, the <> operator is considered obsolete in Python 2.7 and
has been removed from Python 3. Therefore, it is recommended to use != instead.
f-strings should not be nested too deeply
f-strings should not be nested too deeply
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:
tf.function should not depend on global or free Python variables
tf.function should not depend on global or free Python variables
When calling a tensorflow.function behind the scenes a ConcreteFunction is created everytime a new value is passed as argument. This is not the case with Python global variables, closure or nonlocal variables.
This means the state and the result of the tensorflow.function may not be what is expected.
The new raise form should be used
The new raise form should be used
The raise a, b syntax is deprecated in Python 3, and should no longer be used.
Raised Exceptions must derive from BaseException
Raised Exceptions must derive from BaseException
Attempting to raise an object which does not derive from BaseException will raise a `TypeError.
If you are about to create a custom exception class, note that custom exceptions should inherit from Exception, rather than BaseException.
BaseException is the base class for all built-in exceptions in Python, including system-exiting exceptions like SystemExit or KeyboardInterrupt, which are typically not meant to be caught. On the other hand, Exception is intended for exceptions that are expected to be caught, which is generally the case for user-defined exceptions. See PEP 352 for more information.
To fix this issue, make sure that the object you’re attempting to raise inherits from BaseException`.
Assignments of lambdas to variables should be replaced by function definitions
Assignments of lambdas to variables should be replaced by function definitions
Assigning a lambda to a variable is not inherently wrong or discouraged in Python. Lambdas are anonymous functions that can be useful for short and simple expressions or as function arguments. However, there are a few reasons why you might consider alternatives to assigning a lambda to a variable:
Readability and clarity: Lambdas can be concise, but they may become less readable as the expression or logic becomes more complex. For more complex or longer functions, using a regular named function defined with def can make the code more readable and self-explanatory.
Reusability: Lambdas are often used for one-off or small, isolated tasks. If you find that you need to reuse a piece of functionality in multiple places within your code or across modules, it is better to define a named function using def. This promotes code modularity and maintainability.
Documentation: Lambdas do not support docstrings, which are important for providing clear and comprehensive documentation for your functions. If you need to document the purpose, parameters, or behavior of a function, it is best to define a named function using def and include a docstring.
Debugging and error handling: Lambdas are anonymous functions, which means that when an error occurs during execution, the traceback will not provide a specific name associated with the lambda function. This can make it more challenging to identify and troubleshoot errors. Named functions defined with def provide more meaningful tracebacks.
Using a def statements rather than assigning lambdas to variable is also recommended by PEP8.
in and not in operators should be used on objects supporting them
in and not in operators should be used on objects supporting them
Operators `in and not in, also called “membership test operators”, require that the right operand supports the membership protocol.
In order to support the membership protocol, a user-defined class should implement at least one of the following methods: contains, iter, getitem.
If none of these methods is implemented, a TypeError` will be raised when performing a membership test.
Deprecated NumPy aliases of built-in types should not be used
Deprecated NumPy aliases of built-in types should not be used
In NumPy, some built-in types such as int have aliases in the form of numpy.int. However, these aliases have been deprecated and should not be used anymore.
The following deprecated aliases should be replaced with their built-in alternatives:
| Deprecated name | Equivalent built-in type |
|---|---|
numpy.bool | bool |
numpy.int | int |
numpy.float | float |
numpy.complex | complex |
numpy.object | object |
numpy.str | str |
numpy.long | int |
numpy.unicode | str |
pytz.timezone should not be passed to the datetime.datetime constructor
pytz.timezone should not be passed to the datetime.datetime constructor
When working with timezones in Python, it’s important to understand that the datetime.datetime constructor and pytz timezone objects handle timezones differently. This difference can lead to unexpected results if a pytz object is used as the tzinfo argument in the datetime.datetime constructor.
The datetime.datetime constructor expects a tzinfo object that is a subclass of the datetime.tzinfo base class. pytz timezone objects do provide this interface, but they implement it in a way that’s not fully compatible with datetime.datetime.
One key difference is how they handle historical changes in timezone offsets. The datetime module uses the IANA time zone database, which includes historical changes.
When you create a datetime object with a pytz timezone object as the tzinfo argument, it uses the earliest known offset for that timezone. This can lead to unexpected offsets, as the earliest known offset may not match the current or most commonly used offset for that timezone.
For example, if you were to use ‘US/Eastern’ as your timezone, you might expect the offset to be either -5 hours (Eastern Standard Time) or -4 hours (Eastern Daylight Time), depending on the time of the year. However, due to historical changes, the actual offset might be something different, like -4 hours and 56 minutes. This can lead to subtle bugs in your code, especially if you’re doing calculations with datetime objects.
Note that, when using Python 3.9 and later, it is recommended to use the zoneinfo package from the standard library over pytz.
Special method exit should not re-raise the provided exception
Special method exit should not re-raise the provided exception
Methods enter and exit make it possible to implement objects which can be used as the expression of a with statement:
The pandas.DataFrame.to_numpy() method should be preferred to the pandas.DataFrame.values attribute
The pandas.DataFrame.to_numpy() method should be preferred to the pandas.DataFrame.values attribute
The `values attribute and the to_numpy() method in pandas both provide a way to return a NumPy representation of the DataFrame. However, there are some reasons why the to_numpy() method is recommended over the values attribute:
Future Compatibility: The values attribute is considered a legacy feature, while the to_numpy() is the recommended method to extract data and is considered more future-proof.
Data type consistency: If the DataFrame has columns with different data types, NumPy will choose a common data type that can hold all the data. This may lead to loss of information, unexpected type conversions, or increased memory usage. The to_numpy() allows you to select the common type manually, passing the dtype argument.
View vs Copy: The values attribute can return a view or a copy of the data depending on whether the data needs to be transposed. This can lead to confusion when modifying the extracted data. On the other hand, to_numpy() has copy argument allowing to force it always to return a new NumPy array, ensuring that any changes you make won’t affect the original DataFrame.
Missing values control: The to_numpy() allows to specify the default value used for missing values in the DataFrame, while the values will always use numpy.nan` for missing values.
Operators should be used on compatible types
Operators should be used on compatible types
For a specific operator, two types are considered incompatible if no built-in operations between those types exist and none of the operands has implemented the operator’s corresponding special methods. Performing such an operation on incompatible types will raise a TypeError.
Calling an operator in Python is equivalent to calling a special method (except for the identity operator is). Python provides a set of built-in operations. For example, to add two integers: 1 + 2, calling the built-in operator + is equivalent to calling the special method `add on the type int.
Python allows developers to define how an operator will behave with a custom class by implementing the corresponding special method. When defining such methods for symmetrical binary operators, developers need to define two methods so that the order of operands doesn’t matter, ex: add and radd`.
For a complete list of operators and their methods see the Python documentation: arithmetic and bitwise operators, comparison operators.
Exceptions cause should be either an Exception or None
Exceptions cause should be either an Exception or None
Exception chaining enables users to see if an exception is the direct consequence of another exception (see PEP-3134). This is useful to propagate the original context of the error.
Exceptions are chained using either of the following syntax:
With the from keyword
Loops with at most one iteration should be refactored
Loops with at most one iteration should be refactored
A loop with at most one iteration is equivalent to the use of an `if statement to conditionally execute one piece of code. No developer expects to find such a use of a loop statement. If the initial intention of the author was really to conditionally execute one piece of code, an if statement should be used instead.
At worst that was not the initial intention of the author and so the body of the loop should be fixed to use the nested return, break or raise` statements in a more appropriate way.
Generic classes should be defined using the type parameter syntax
Generic classes should be defined using the type parameter syntax
Through PEP 695, Python 3.12 introduces the type parameter syntax to allow for a more compact and explicit way to define generic classes and functions.
Prior to Python 3.12, defining a generic class would be done through the following syntax:
Some special methods should return NotImplemented instead of raising NotImplementedError
Some special methods should return NotImplemented instead of raising NotImplementedError
In Python, special methods corresponding to numeric operators and rich comparison operators should return `NotImplemented when the operation is not supported.
For example A + B is equivalent to calling A.add(B). If this binary operation is not supported by class A, A.add(B) should return NotImplemented. The interpreter will then try the reverse operation, i.e. B.radd(A). If these special methods were to raise NotImplementedError, the callers would not catch the exception and the reverse operation would not be called.
Below is the list of special methods this rule applies to:
lt(self, other)
le(self, other)
eq(self, other)
ne(self, other)
gt(self, other)
ge(self, other)
add(self, other)
sub(self, other)
mul(self, other)
matmul(self, other)
truediv(self, other)
floordiv(self, other)
mod(self, other)
divmod(self, other)
pow(self, other[, modulo])
lshift(self, other)
rshift(self, other)
and(self, other)
xor(self, other)
or(self, other)
radd(self, other)
rsub(self, other)
rmul(self, other)
rmatmul(self, other)
rtruediv(self, other)
rfloordiv(self, other)
rmod(self, other)
rdivmod(self, other)
rpow(self, other[, modulo])
rlshift(self, other)
rrshift(self, other)
rand(self, other)
rxor(self, other)
ror(self, other)
iadd(self, other)
isub(self, other)
imul(self, other)
imatmul(self, other)
itruediv(self, other)
ifloordiv(self, other)
imod(self, other)
ipow(self, other[, modulo])
ilshift(self, other)
irshift(self, other)
iand(self, other)
ixor(self, other)
ior(self, other)
length_hint(self)`
Identity operators should not be used with dissimilar types
Identity operators should not be used with dissimilar types
Tests should be skipped explicitly
Tests should be skipped explicitly
Test frameworks provide a mechanism to skip tests if their prerequisites are not met, by either calling dedicated methods (e.g: `unittest.TestCase.skipTest, pytest.skip, …) or using decorators (e.g: unittest.skip, pytest.mark.skip, …)
Using a return statement instead will make the test succeed, even though no assertion has been performed. It is therefore better to flag the test as skipped in such situation.
This rule raises an issue when a return is performed conditionally at the beginning of a test method.
No issue will be raised if the return is unconditional as S1763 already raises an issue in such case.
The supported frameworks are Pytest and Unittest`.
The first argument to class methods should follow the naming convention
The first argument to class methods should follow the naming convention
By convention, the first argument in a class method, i.e. methods decorated with `@classmethod, is named cls as a representation and a reminder that the argument is the class itself. If you were to name the argument something else, you would stand a good chance of confusing both users and maintainers of the code. It might also indicate that the cls parameter was forgotten, in which case calling the method will most probably fail. This rule also applies to methods init_subclass, class_getitem and new as their first argument is always the class instead of “self”.
By default this rule accepts cls and mcs, which is sometime used in metaclasses, as valid names for class parameters. You can set your own list of accepted names via the parameter classParameterNames`.
Union type expressions should be preferred over typing.Union in type hints
Union type expressions should be preferred over typing.Union in type hints
Python 3.10 introduced a specific syntax using the “or” operator (X | Y) to represent a union of types. This syntax has the same functionality as typing.Union, but it is more concise and easier to read.
Using typing.Union is more verbose and less convenient. It can also create inconsistencies when different parts of the codebase use different syntaxes for the same type.
Dictionarys setdefault should be used instead of checking key existence
Dictionarys setdefault should be used instead of checking key existence
A common anti-pattern is to check that a key does not exist in a dictionary before adding it with a corresponding value. This pattern works but is less readable than the equivalent call to the built-in dictionary method “setdefault()”.
Note that if a default value is set for every key of the dictionary it is possible to use python’s defaultdict instead.
This rule raises an issue when a key presence is checked before being set. It only raises an issue when the value is a hard-coded string, number, list, dictionary or tuple. Computed values will not raise an issue as they can have side-effects.
Functions and lambdas should not reference variables defined in enclosing loops
Functions and lambdas should not reference variables defined in enclosing loops
Nested functions and lambdas can reference variables defined in enclosing scopes. This can create tricky bugs when the variable and the function are defined in a loop. If the function is called in another iteration or after the loop finishes, it will see the variables’ last value instead of seeing the values corresponding to the iteration where the function was defined.
Capturing loop variables might work for some time but:
it makes the code difficult to understand.
it increases the risk of introducing a bug when the code is refactored or when dependencies are updated. See an example with the builtin “map” below.
One solution is to add a parameter to the function/lambda and use the previously captured variable as its default value. Default values are only executed once, when the function is defined, which means that the parameter’s value will remain the same even when the variable is reassigned in following iterations.
Another solution is to pass the variable as an argument to the function/lambda when it is called.
This rule raises an issue when a function or lambda references a variable defined in an enclosing loop.
Type hints of generic types should specify their type parameters
Type hints of generic types should specify their type parameters
Generic types, such as list or dict accept type arguments to specify the type of elements contained in the list or the keys and values in the dictionary.
If a generic type is used without a type argument, the type arguments will implicitly assumed to be Any. This makes the type hint less informative and makes the contract of the function or variable annotated with the type hint more difficult to understand.
Furthermore, incomplete type hints can hinder IDE autocompletion and code insight capabilities of static analyis tools.
Set members and dictionary keys should be hashable
Set members and dictionary keys should be hashable
The hash value of an object is an integer returned by its `hash method. Objects that are considered equal to each other (as per the eq method) should have the same hash value.
Whenever using an object as a dictionary key or inserting it into a set, the hash value of that object will be used to derive a bucket in which the object will be inserted.
When attempting to insert an unhashable object into a set, a TypeError will be raised instead.
If an object defines a hash method derived from mutable properties, no TypeError` will be raised. However, having a mutable hash value should never be done as this would prevent dictionaries and set from retrieving the object.
np.nonzero should be preferred over np.where when only the condition parameter is set
np.nonzero should be preferred over np.where when only the condition parameter is set
The NumPy function np.where provides a way to execute operations on an array under a certain condition:
Methods and field names should not differ only by capitalization
Methods and field names should not differ only by capitalization
Looking at the set of methods and fields in a class and finding two that differ only by capitalization is confusing to users of the class.
This situation may simply indicate poor naming. Method names should be action-oriented, and thus contain a verb, which is unlikely in the case where both a method and a field have the same name (with or without capitalization differences). However, renaming a public method could be disruptive to callers. Therefore renaming the member is the recommended action.
await should be used on awaitable objects
await should be used on awaitable objects
The await keyword can only be used on “Awaitable” objects. Python has three types of awaitables: Future, Task and Coroutines. Calling await on any other object will raise a TypeError.
Dates should be formatted correctly when using pandas.to_datetime with dayfirst or yearfirst arguments
Dates should be formatted correctly when using pandas.to_datetime with dayfirst or yearfirst arguments
The pandas.to_datetime function transforms a string to a date object. The string representation of the date can take multiple formats. To correctly parse these strings, pandas.to_datetime provides several arguments to setup the parsing, such as dayfirst or yearfirst. For example setting dayfirst to True indicates to pandas.to_datetime that the date and time will be represented as a string with the shape day month year time. Similarly with yearfirst, the string should have the following shape year month day time.
These two arguments are not strict, meaning if the shape of the string is not the one expected by pandas.to_datetime, the function will not fail and try to figure out which part of the string is the day, month or year.
In the following example the dayfirst argument is set to True but we can clearly see that the month part of the date would be incorrect. In this case pandas.to_datetime will ignore the dayfirst argument, and parse the date as the 22nd of January.
Static methods should not have self or cls arguments
Static methods should not have self or cls arguments
Unlike class and instance methods, static methods don’t receive an implicit first argument. Nonetheless naming the first argument self or clz guarantees confusion - either on the part of the original author, who may never understand why the arguments don’t hold the values he expected, or on that of future maintainers.
Exceptions should not be created without being raised
Exceptions should not be created without being raised
Creating a new Exception without actually raising it has no effect and is probably due to a mistake.
isinstance() should be preferred to direct type comparisons
isinstance() should be preferred to direct type comparisons
In Python, using the isinstance() function is generally preferred over direct type comparison for several reasons:
Compatibility with inheritance: isinstance() considers inheritance hierarchy, whereas direct type comparison does not. This means that isinstance() can handle cases where an object belongs to a subclass of the specified type, making your code more flexible and robust. It allows you to write code that can work with objects of different but related types.
Support for duck typing: Python follows the principle of “duck typing,” which focuses on an object’s behavior rather than its actual type. isinstance() enables you to check if an object has certain behavior (by checking if it belongs to a particular class or subclass) rather than strictly requiring a specific type. This promotes code reusability and enhances the flexibility of your programs.
Code maintainability and extensibility: By using isinstance(), your code becomes more maintainable and extensible. If you directly compare types, you would need to modify your code whenever a new subtype is introduced or the inheritance hierarchy is changed. On the other hand, isinstance() allows your code to accommodate new types without requiring any modifications, as long as they exhibit the desired behavior.
Polymorphism and interface-based programming: isinstance() supports polymorphism, which is the ability of different objects to respond to the same method calls. It allows you to design code that interacts with objects based on their shared interface rather than their specific types. This promotes code reuse and modularity, as you can write functions and methods that operate on a range of compatible objects.
Third-party library compatibility: Many third-party libraries and frameworks in Python rely on isinstance() for type checking and handling different types of objects. By using isinstance(), your code becomes more compatible with these libraries and frameworks, making it easier to integrate your code into larger projects or collaborate with other developers.
In summary, using isinstance() over direct type comparison in Python promotes flexibility, code reusability, maintainability, extensibility, and compatibility with the wider Python ecosystem. It aligns with the principles of object-oriented programming and supports the dynamic nature of Python. It is also recommended by the PEP8 style guide.
Boolean expressions of exceptions should not be used in except statements
Boolean expressions of exceptions should not be used in except statements
The only two possible types for an `except’s expression are a class deriving from BaseException, or a tuple composed of such classes.
Trying to catch multiple exception in the same except with a boolean expression of exceptions may not work as intended. The result of a boolean expression of exceptions is a single exception class, thus using a boolean expression in an except` block will result in catching only one kind of exception.
Identity comparisons should not be used with cached types
Identity comparisons should not be used with cached types
The identity operators is and is not check if the same object is on both sides,
i.e. a is b returns True if ++id(a)
self should be the first argument to instance methods
self should be the first argument to instance methods
Instance methods, i.e. methods not annotated with `@classmethod or @staticmethod, are expected to have at least one parameter. This parameter will reference the object instance on which the method is called. By convention, this first parameter is named “self”.
Naming the first parameter something different from “self” is not recommended as it could lead to confusion. It might indicate that the “self” parameter was forgotten, in which case calling the method will most probably fail.
Note also that creating methods which are used as static methods without the @staticmethod decorator is a bad practice. Calling these methods on an instance will raise a TypeError. Either move the method out of the class or decorate it with @staticmethod`.
New objects should not be created only to check their identity
New objects should not be created only to check their identity
Identity operators is and is not check if the same object is on both sides, i.e. a is b returns True if ++id(a)
startswith or endswith methods should be used instead of string slicing in condition expressions
startswith or endswith methods should be used instead of string slicing in condition expressions
Using the startswith and endswith methods in Python instead of string slicing offers several advantages:
Readability and Intent: Using startswith and endswith methods provides code that is more readable and self-explanatory. It clearly communicates your intention to check if a string starts or ends with a specific pattern. This makes the code more maintainable and easier to understand for other developers.
Flexibility: The startswith and endswith methods allow you to check for patterns of varying lengths. With string slicing, you would need to specify the exact length of the substring to compare. However, with the methods, you can pass in a pattern of any length, making your code more flexible and adaptable.
Error Handling: The methods handle edge cases automatically. If you pass a substring length that exceeds the length of the original string, slicing would raise an IndexError exception. On the other hand, the methods gracefully handle such cases and return False, avoiding any potential errors.
Performance Optimization: In some cases, using startswith and endswith methods can provide better performance. These methods are optimized and implemented in C, which can make them faster than manually slicing the string in Python. Although the performance gain might be negligible for small strings, it can be significant when working with large strings or processing them in a loop.
Overall, using startswith and endswith methods provides a cleaner, more readable, and error-resistant approach for checking if a string starts or ends with a specific pattern. It promotes code clarity, flexibility, and can potentially improve performance. This is also recommended by the PEP8 style guide.
Increment and decrement operators should not be used
Increment and decrement operators should not be used
Python has no pre/post increment/decrement operator. For instance, x++ and x— will fail to parse. More importantly, ++x and —x will do nothing. To increment a number, simply write x += 1.
Bare raise statements should not be used in finally blocks
Bare raise statements should not be used in finally blocks
A bare `raise statement, i.e. a raise with no exception provided, will re-raise the last active exception in the current scope. If no exception is active a RuntimeError is raised instead.
If the bare “raise” statement is in a finally block, it will only have an active exception to re-raise when an exception from the try block is not caught or when an exception is raised by an except or else block. Thus bare raise statements should not be relied upon in finally` blocks. It is simpler to let the exception raise automatically.
init should not return a value
init should not return a value
By contract, every Python function returns something, even if it is the `None value, which can be returned implicitly by omitting the return statement, or explicitly.
The init method is required to return None. A TypeError will be raised if the init method either yields or returns any expression other than None. While explicitly returning an expression that evaluates to None will not raise an error, it is considered bad practice.
To fix this issue, make sure that the init` method does not contain any return statement.
Redundant pairs of parentheses should be removed
Redundant pairs of parentheses should be removed
Parentheses can disambiguate the order of operations in complex expressions and make the code easier to understand.
str.replace should be preferred to re.sub
str.replace should be preferred to re.sub
An re.sub call always performs an evaluation of the first argument as a regular expression, even if no regular expression features were used. This has a significant performance cost and therefore should be used with care.
When re.sub is used, the first argument should be a real regular expression. If it’s not the case, str.replace does exactly the same thing as re.sub without the performance drawback of the regex.
This rule raises an issue for each re.sub used with a simple string as first argument which doesn’t contains special regex character or pattern.
Function return types should be consistent with their type hint
Function return types should be consistent with their type hint
Developers can use type hints to specify which type a function is expected to return. Doing so improves maintainability since it clarifies the contract of the function, making it easier to use and understand.
When annotating a function with a specific type hint, it is expected that the returned value matches the type specified in the hint.
If the type hint specifies a class or a named type, then the value returned should be an instance of that class or type. If the type hint specifies a structural type, then the value returned should have the same structure as the type hint.
In the following example, while Bucket does not directly inherit from Iterable, it does implement the Iterable protocol thanks to its iter method and can therefore be used as a valid Iterable return type.
The abs_tol parameter should be provided when using math.isclose to compare values to 0
The abs_tol parameter should be provided when using math.isclose to compare values to 0
Comparing float values for equality directly is not reliable and should be avoided, due to the inherent imprecision in the binary representation of floating point numbers. Such comparison is reported by S1244.
One common solution to this problem is to use the math.isclose function to perform the comparison. Behind the scenes, the math.isclose function uses a tolerance value (also called epsilon) to define an acceptable range of difference between two floats. A tolerance value may be relative (based on the magnitude of the numbers being compared) or absolute.
Using a relative tolerance would be equivalent to:
Identical expressions should not be used on both sides of a binary operator
Identical expressions should not be used on both sides of a binary operator
Using the same value on either side of a binary operator is almost always a mistake. In the case of logical operators, it is either a copy/paste error and therefore a bug, or it is simply wasted code, and should be simplified. In the case of bitwise operators and most binary mathematical operators, having the same value on both sides of an operator yields predictable results, and should be simplified.
Note that this rule will raise issues on “++a
Floating point numbers should not be tested for equality
Floating point numbers should not be tested for equality
Floating point math is imprecise because of the challenges of storing such values in a binary representation.
In base 10, the fraction 1/3 is represented as 0.333… which, for a given number of significant digit, will never exactly be 1/3. The same problem happens when trying to represent 1/10 in base 2, with leads to the infinitely repeating fraction 0.0001100110011…. This makes floating point representations inherently imprecise.
Even worse, floating point math is not associative; push a `float through a series of simple mathematical operations and the answer will be different based on the order of those operation because of the rounding that takes place at each step.
Even simple floating point assignments are not simple, as can be vizualized using the format` function to check for significant digits:
Only existing object members should be accessed
Only existing object members should be accessed
Accessing a non-existing member on an object will raise in most case an AttributeError exception.
This rule raises an issue when a non-existing member is accessed on a class instance and nothing indicates that this was expected.
Recursion should not be infinite
Recursion should not be infinite
Recursion happens when control enters a loop that has no exit. This can happen when a method invokes itself or when a pair of methods invoke each other. It can be a useful tool, but unless the method includes a provision to break out of the recursion and return, the recursion will continue until the stack overflows and the program crashes.
Custom Exception classes should inherit from Exception or one of its subclasses
Custom Exception classes should inherit from Exception or one of its subclasses
`SystemExit is raised when sys.exit() is called. KeyboardInterrupt is raised when the user asks the program to stop by pressing interrupt keys. Both exceptions are expected to propagate up until the application stops.
In order to avoid catching SystemExit and KeyboardInterrupt by mistake, PEP-352 created the root class BaseException from which SystemExit, KeyboardInterrupt and Exception derive. Thus developers can use except Exception: without preventing the software from stopping.
The GeneratorExit class also derives from BaseException as it is not really an error and is not supposed to be caught by user code.
As said in Python’s documentation, user-defined exceptions are not supposed to inherit directly from BaseException. They should instead inherit from Exception` or one of its subclasses.
Comparison to None should not be constant
Comparison to None should not be constant
Checking if a variable or parameter is None should only be done when you expect that it can be None. Doing so when the variable is always None or never None is confusing at best. At worse, there is a bug and the variable is not updated properly.
This rule raises an issue when expressions X is None, X is not None, `X
Iterator classes should have a valid iter method
Iterator classes should have a valid iter method
The iterator protocol specifies that an iterator object should have
a `next method retrieving the next value or raising StopIteration when there are no more values left.
an iter method which should always return self. This enables iterators to be used as sequences in for-loops and other places.
This rule raises an issue when a class has a next method and either:
it doesn’t have an iter method.
or its iter` method does not return “self”.
Dictionarys get(..., default) should be used instead of checking key existence
Dictionarys get(..., default) should be used instead of checking key existence
A common anti-pattern is to check that a key exists in a dictionary before retrieving its corresponding value and providing a default value otherwise. This pattern works but is less readable than the equivalent call to the built-in dictionary method “get()” with a default value.
Note that if a default value is set for every key of the dictionary it is possible to use python’s defaultdict instead.
This rule raises an issue when a key presence is checked before retrieving its value or providing a default value. It only raises an issue when the default value is a hard-coded string, number, list, dictionary or tuple. Computed values will not raise an issue as they can have side-effects.
Equality checks should not be made against numpy.nan
Equality checks should not be made against numpy.nan
The `numpy.nan is a floating point representation of Not a Number (NaN) used as a placeholder for undefined or missing values in numerical computations.
Equality checks of variables against numpy.nan in NumPy will always be False due to the special nature of numpy.nan. This can lead to unexpected and incorrect results.
Instead of standard comparison the numpy.isnan()` function should be used.
NotImplemented should not be raised
NotImplemented should not be raised
NotImplemented is a constant which is intended to be used only by comparison methods such as lt. Use it instead of NotImplementedError, which is an exception, and callers will have a hard time using your code.
Back references in regular expressions should only refer to capturing groups that are matched before the reference
Back references in regular expressions should only refer to capturing groups that are matched before the reference
When a back reference in a regex refers to a capturing group that hasn’t been defined yet (or at all), it can never be matched and will fail with an re.error exception
Non-existent operators like =+ should not be used
Non-existent operators like =+ should not be used
Using operator pairs (=+ or =-) that look like reversed single operators (+= or -=) is confusing. They compile and run but do not produce the same result as their mirrored counterpart.
Unused private nested classes should be removed
Unused private nested classes should be removed
”Private” nested classes that are never used inside the enclosing class are usually 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.
Python has no real private classes. Every class is accessible. There are however two conventions indicating that a class is not meant to be “public”:
classes with a name starting with a single underscore (ex: `_MyClass) should be seen as non-public and might change without prior notice. They should not be used by third-party libraries or software. It is ok to use those classes inside the library defining them but it should be done with caution.
”class-private” classes are defined inside another class, and have a name starting with at least two underscores and ending with at most one underscore. These classes’ names will be automatically mangled to avoid collision with subclasses’ nested classes. For example __MyClass will be renamed as _classname__MyClass, where classname` is the enclosing class’s name without its leading underscore(s). Class-Private classes shouldn’t be used outside of their enclosing class.
This rule raises an issue when a private nested class (either with one or two leading underscores) is never used inside its parent class.
When using pandas.merge or pandas.join, the parameters on, how and validate should be provided
When using pandas.merge or pandas.join, the parameters on, how and validate should be provided
The Pandas library provides a user-friendly API to concatenate two data frames together with the methods `merge and join.
When using these methods, it is possible to specify how the merge will be performed:
The parameter how specifies the type of merge (left, inner, outer, etc..).
The parameter on specifies the column(s) on which the merge will be performed.
The parameter validate` specifies a way to verify if the merge result is what was expected.
Numpy weekmask should have a valid value
Numpy weekmask should have a valid value
To allow a datetime to be used in contexts where only certain days of the week are valid, NumPy includes a set of business day functions. Weekmask is used to customize valid business days.
Weekmask can be specified in several formats:
As an array of 7 1 or 0 values, e.g. [1, 1, 1, 1, 1, 0, 0]
As a string of 7 1 or 0 characters, e.g. “1111100”
As a string with abbreviations of valid days from this list: Mon Tue Wed Thu Fri Sat Sun, e.g. “Mon Tue Wed Thu Fri”
Setting an incorrect weekmask leads to ValueError.
ExceptionGroup and BaseExceptionGroup should not be caught with except*
ExceptionGroup and BaseExceptionGroup should not be caught with except*
Python 3.11 introduced `except* and ExceptionGroup, making it possible to handle and raise multiple unrelated exceptions simultaneously.
In the example below, we gather multiple exceptions in an ExceptionGroup. This ExceptionGroup` is then caught by a single except block:
All code should be reachable
All code should be reachable
Jump statements (return, break, continue, and raise) move control flow out of the current code block. So any statements that come after a jump are dead code.
Fields of a Django ModelFom should be defined explicitly
Fields of a Django ModelFom should be defined explicitly
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.
Conditionally executed code should be reachable
Conditionally executed code should be reachable
Unreachable code is never executed, so it has no effect on the behaviour of the program. If it is not executed because it no longer serves a purpose, then it adds unnecessary complexity. Otherwise, it indicates that there is a logical error in the condition.
Functions, methods and lambdas should not have too many mandatory parameters
Functions, methods and lambdas should not have too many mandatory parameters
Function, methods and lambdas should not have too many mandatory parameters, i.e. parameters with no default value. Calling them will require code difficult to read and maintain. To solve this problem you could wrap some parameters in an object, split the function into simpler functions with less parameters or provide default values for some parameters.
List comprehensions should be used
List comprehensions should be used
There are several ways to create a new list based on the elements of some other collection, but the use of a list comprehension has multiple benefits. First, it is both concise and readable, and second, it yields a fully-formed object without requiring a mutable object as input that must be updated multiple times in the course of the list creation.
zoneinfo should be preferred to pytz when using Python 3.9 and later
zoneinfo should be preferred to pytz when using Python 3.9 and later
In Python 3.9 and later, the zoneinfo module is the recommended tool for handling timezones, replacing the pytz library. This recommendation is based on several key advantages.
First, zoneinfo is part of Python’s standard library, making it readily available without needing additional installation, unlike pytz.
Second, zoneinfo integrates seamlessly with Python’s datetime module. You can directly use zoneinfo timezone objects when creating datetime objects, making it more intuitive and less error-prone than pytz, which requires a separate localize method for this purpose.
Third, zoneinfo handles historical timezone changes more accurately than pytz. When a pytz timezone object is used, it defaults to the earliest known offset, which can lead to unexpected results. zoneinfo does not have this issue.
Lastly, zoneinfo uses the system’s IANA time zone database when available, ensuring it works with the most up-to-date timezone data. In contrast, pytz includes its own copy of the IANA database, which may not be as current.
In summary, zoneinfo offers a more modern, intuitive, and reliable approach to handling timezones in Python 3.9 and later, making it the preferred choice over pytz.
Collection sizes and array length comparisons should make sense
Collection sizes and array length comparisons should make sense
The length of a collection is always greater than or equal to zero. Testing it doesn’t make sense, since the result is always true.
SystemExit should be re-raised
SystemExit should be re-raised
A `SystemExit exception is raised when sys.exit() is called. This exception is used to signal the interpreter to exit. The exception is expected to propagate up until the program stops. It is possible to catch this exception in order to perform, for example, clean-up tasks. It should, however, be raised again to allow the interpreter to exit as expected. Not re-raising such exception could lead to undesired behaviour.
A bare except: statement, i.e. an except block without any exception class, is equivalent to except BaseException. Both statements will catch every exceptions, including SystemExit. It is recommended to catch instead a more specific exception. If it is not possible, the exception should be raised again.
It is also a good idea to re-raise the KeyboardInterrupt exception. Similarly to SystemExit,KeyboardInterrupt` is used to signal the interpreter to exit. Not re-raising such exception could also lead to undesired behaviour.
inplace=True should not be used when modifying a Pandas DataFrame
inplace=True should not be used when modifying a Pandas DataFrame
Using inplace=True when modifying a Pandas DataFrame means that the method will modify the DataFrame in place, rather than returning a new object:
Silly equality checks should not be made
Silly equality checks should not be made
In some cases a comparison with operators `==, or != will always return True or always return False. When this happens, the comparison and all its dependent code can simply be removed. This includes:
comparing unrelated builtin types such as string and integer.
comparing class instances which do not implement eq or ne to an object of a different type (builtin or from an unrelated class which also doesn’t implement eq or ne`).
Assertions should not fail or succeed unconditionally
Assertions should not fail or succeed unconditionally
Assertions are meant to detect when code behaves as expected. An assertion which fails or succeeds all the time does not achieve this. Either it is redundant and should be removed to improve readabity or it is a mistake and the assertion should be corrected.
This rule raises an issue when an assertion method is given parameters which will make it succeed or fail all the time. It covers three cases:
an `assert statement or a unittest’s assertTrue or assertFalse method is called with a value which will be always True or always False.
a unittest’s assertIsNotNone or assertIsNone method is called with a value which will always be None or never be None.
a unittest’s assertIsNot or assertIs method is called with a literal expression creating a new object every time (ex: [1, 2, 3]`).
Function parameters initial values should not be ignored
Function parameters initial values should not be ignored
While it is technically correct to assign to parameters from within function bodies, doing so before the parameter value is read is likely a bug. Instead, initial values of parameters should be, if not treated as read-only, then at least read before reassignment.
The method ne should not be implemented without also implementing eq
The method ne should not be implemented without also implementing eq
Implementing the special method `ne is not equivalent to implementing the special method eq. By default ne will call eq, but the default implementation of eq does not call ne.
This rule raises an issue when the special method ne is implemented but not the eq` method.
iter should return an iterator
iter should return an iterator
An iterable object is an object capable of returning its members one at a time. To do so, it must define an `iter method that returns an iterator.
The iterator protocol specifies that, in order to be a valid iterator, an object must define a next and an iter method (because iterators are also iterable).
Defining an iter method that returns anything else than an iterator will raise a TypeError as soon as the iteration begins.
Note that generators and generator expressions have both next and iter` methods generated automatically.
\ should only be used as an escape character outside of raw strings
\ should only be used as an escape character outside of raw strings
Typically, backslashes are seen only as part of escape sequences. Therefore, the use of a backslash outside of a raw string or escape sequence looks suspiciously like a broken escape sequence.
Characters recognized as escape-able are: abfnrtvox‘“
Unread private attributes should be removed
Unread private attributes should be removed
Python has no real private attribute. Every attribute is accessible. There are however two conventions indicating that an attribute is not meant to be “public”:
attributes with a name starting with a single underscore (ex: `_myattribute) should be seen as non-public and might change without prior notice. They should not be used by third-party libraries or software. It is ok to use those methods inside the library defining them but it should be done with caution.
”class-private” attributes have a name starting with at least two underscores and ending with at most one underscore. These attributes’ names will be automatically mangled to avoid collision with subclasses’ attributes. For example __myattribute will be renamed as _classname__myattribute, where classname` is the attribute’s class name without its leading underscore(s). They shouldn’t be used outside of the class defining the attribute.
This rule raises an issue when a class-private attribute (two leading underscores, max one underscore at the end) is never read inside the class. It optionally raises an issue on unread attributes prefixed with a single underscore. Both class attributes and instance attributes will raise an issue.
Unpacking should be done with the same number of elements of the iterable.
Unpacking should be done with the same number of elements of the iterable.
In Python, the unpacking assignment is a powerful feature that allows you to assign multiple values to multiple variables in a single statement.
The basic rule for the unpacking assignment is that the number of variables on the left-hand side must be equal to the number of elements in the iterable. If this is not respected, a ValueError will be produced at runtime.
The axis argument should be specified when using TensorFlows reduction operations
The axis argument should be specified when using TensorFlows reduction operations
The result of TensorFlow’s reduction operations (i.e. tf.math.reduce_sum, tf.math.reduce_std),
highly depends on the shape of the Tensor provided.
Caught Exceptions must derive from BaseException
Caught Exceptions must derive from BaseException
In Python 3’s except statement, attempting to catch an object that does not derive from BaseException will raise a TypeError.
In order to catch multiple exceptions in an except statement, a tuple of exception classes should be provided. Trying to catch multiple exceptions with a list or a set will raise a TypeError.
If you are about to create a custom exception class, note that custom exceptions should inherit from `Exception, rather than BaseException.
BaseException is the base class for all built-in exceptions in Python, including system-exiting exceptions like SystemExit or KeyboardInterrupt, which are typically not meant to be caught. On the other hand, Exception is intended for exceptions that are expected to be caught, which is generally the case for user-defined exceptions. See PEP 352 for more information.
To fix this issue, make sure the expression used in an except statement is an exception which derives from BaseException/Exception` or a tuple of such exceptions.
Only strings should be listed in all
Only strings should be listed in all
The all property of a module is used to define the list of names that will be imported when performing a wildcard import of this module, i.e. when from mymodule import * is used.
In the following example:
slots should not be used in old-style classes
slots should not be used in old-style classes
A class without an explicit extension of object (class ClassName(object)) is considered an old-style class, and slots declarations are ignored in old-style classes. Having such a declaration in an old-style class could be confusing for maintainers and lead them to make false assumptions about the class.
Function returns should have type hints
Function returns should have type hints
Being a dynamically typed language, the Python interpreter only does type checking during runtime. Getting the typing right is important as certain operations may result in a TypeError.
Type hints can be used to clarify the expected return type of a function, enabling developers to better document its contract. Applying them consistently makes the code easier to read and understand.
In addition, type hints allow some development environments to offer better autocompletion and improve the precision of static analysis tools.
Method names should comply with a naming convention
Method names should comply with a naming convention
Shared naming conventions allow teams to collaborate efficiently.
This rule raises an issue when a method name does not match a provided regular expression.
For example, with the default provided regular expression ^[a-z_][a-z0-9_]*$, the method:
Django models should define a str method
Django models should define a str method
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.
Doubled prefix operators not and ~ should not be used
Doubled prefix operators not and ~ should not be used
The repetition of a prefix operator (not or ~) is usually a typo. The second operator invalidates the first one:
Type checks shouldnt be confusing
Type checks shouldnt be confusing
Checking that variable X has type T with type annotations implies that X’s value is of type T or a subtype of T. After such a check, it is a good practice to limit actions on X to those allowed by type T, even if a subclass of T allows different actions. Doing otherwise will confuse your fellow developers.
Just to be clear, it is common in python to perform an action without checking first if it is possible (see “Easier to ask for forgiveness than permission.”). However when type checks are performed, they should not contradict the following actions.
This rule raises an issue when an action performed on a variable might be possible, but it contradicts a previous type check. The list of checked actions corresponds to rules S2159, S3403, S5607, S5756, S5644, S3862, S5797, S5795 and S5632. These other rules only detect cases where the type of a variable is certain, i.e. it cannot be a subclass.
Names of regular expressions named groups should be used
Names of regular expressions named groups should be used
Why use named groups only to never use any of them later on in the code?
This rule raises issues every time named groups are:
referenced while not defined;
defined but called elsewhere in the code by their number instead.
Control flow statements if, for, while, try and with should not be nested too deeply
Control flow statements if, for, while, try and with should not be nested too deeply
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.
Conditional expressions should not be nested
Conditional expressions should not be nested
Nested conditionals are hard to read and can make the order of operations complex to understand.
A subclass should not be in the same except statement as a parent class
A subclass should not be in the same except statement as a parent class
In Python it is possible to catch multiple types of exception in a single except statement using a tuple of the exceptions.
Repeating an exception class in a single except statement will not fail but it does not have any effect. Either the exception class is not the one which should be caught, or it is duplicated code which should be removed.
Having a subclass and a parent class in the same except statement does not provide any benefit either. It is enough to keep only the parent class.
tf.Variable objects should be singletons when created inside of a tf.function
tf.Variable objects should be singletons when created inside of a tf.function
tensorflow.functions only supports singleton tensorflow.Variables. This means the variable will be created on the first call
of the tensorflow.function and will be reused across the subsequent calls. Creating a tensorflow.Variable that is not a singleton
will raise a ValueError.
future imports should be the first statements in a module
future imports should be the first statements in a module
Importing a feature from the future module turns on that feature from a future version of Python in your module. The purpose is to allow you to gradually transition to the new features or incompatible changes in future language versions, rather than having to make the entire jump at once.
Because such changes must be applied to the entirety of a module to work, putting such imports anywhere but in the beginning of the module doesn’t make sense. It would mean applying those restrictions to only part of your code. Because that would lead to inconsistencies and massive confusion, it’s not allowed.
except clauses should do more than raise the same issue
except clauses should do more than raise the same issue
An except clause that only rethrows the caught exception has the same effect as omitting the except altogether and letting it bubble up automatically.
numpy.random.Generator should be preferred to numpy.random.RandomState
numpy.random.Generator should be preferred to numpy.random.RandomState
Using a predictable seed is a common best practice when using NumPy to create reproducible results. To that end, using np.random.seed(number) to set the seed of the global numpy.random.RandomState has been the privileged solution for a long time.
numpy.random.RandomState and its associated methods rely on a global state, which may be problematic when threads or other forms of concurrency are involved. The global state may be altered and the global seed may be reset at various points in the program (for instance, through an imported package or script), which would lead to irreproducible results.
Instead, the preferred best practice to generate reproducible pseudorandom numbers is to instantiate a numpy.random.Generator object with a seed and reuse it in different parts of the code. This avoids the reliance on a global state. Whenever a new seed is needed, a new generator may be created instead of mutating a global state.
Below is the list of legacy functions and their alternatives:
Legacy function name | numpy.random.Generator alternative |
numpy.random.RandomState.seed | numpy.random.default_rng |
numpy.random.RandomState.rand | numpy.random.Generator.random |
numpy.random.RandomState.randn | numpy.random.Generator.standard_normal |
numpy.random.RandomState.randint | numpy.random.Generator.integers |
numpy.random.RandomState.random_integers | numpy.random.Generator.integers |
numpy.random.RandomState.random_sample | numpy.random.Generator.random |
numpy.random.RandomState.choice | numpy.random.Generator.choice |
numpy.random.RandomState.bytes | numpy.random.Generator.bytes |
numpy.random.RandomState.shuffle | numpy.random.Generator.shuffle |
numpy.random.RandomState.permutation | numpy.random.Generator.permutation |
numpy.random.RandomState.beta | numpy.random.Generator.beta |
numpy.random.RandomState.binomial | numpy.random.Generator.binomial |
numpy.random.RandomState.chisquare | numpy.random.Generator.chisquare |
numpy.random.RandomState.dirichlet | numpy.random.Generator.dirichlet |
numpy.random.RandomState.exponential | numpy.random.Generator.exponential |
numpy.random.RandomState.f | numpy.random.Generator.f |
numpy.random.RandomState.gamma | numpy.random.Generator.gamma |
numpy.random.RandomState.geometric | numpy.random.Generator.geometric |
numpy.random.RandomState.gumbel | numpy.random.Generator.gumbel |
numpy.random.RandomState.hypergeometric | numpy.random.Generator.hypergeometric |
numpy.random.RandomState.laplace | numpy.random.Generator.laplace |
numpy.random.RandomState.logistic | numpy.random.Generator.logistic |
numpy.random.RandomState.lognormal | numpy.random.Generator.lognormal |
numpy.random.RandomState.logseries | numpy.random.Generator.logseries |
numpy.random.RandomState.multinomial | numpy.random.Generator.multinomial |
numpy.random.RandomState.multivariate_normal | numpy.random.Generator.multivariate_normal |
numpy.random.RandomState.negative_binomial | numpy.random.Generator.negative_binomial |
numpy.random.RandomState.noncentral_chisquare | numpy.random.Generator.noncentral_chisquare |
numpy.random.RandomState.noncentral_f | numpy.random.Generator.noncentral_f |
numpy.random.RandomState.normal | numpy.random.Generator.normal |
numpy.random.RandomState.pareto | numpy.random.Generator.pareto |
numpy.random.RandomState.poisson | numpy.random.Generator.poisson |
numpy.random.RandomState.power | numpy.random.Generator.power |
numpy.random.RandomState.rayleigh | numpy.random.Generator.rayleigh |
numpy.random.RandomState.standard_cauchy | numpy.random.Generator.standard_cauchy |
numpy.random.RandomState.standard_exponential | numpy.random.Generator.standard_exponential |
numpy.random.RandomState.standard_gamma | numpy.random.Generator.standard_gamma |
numpy.random.RandomState.standard_normal | numpy.random.Generator.standard_normal |
numpy.random.RandomState.standard_t | numpy.random.Generator.standard_t |
numpy.random.RandomState.triangular | numpy.random.Generator.triangular |
numpy.random.RandomState.uniform | numpy.random.Generator.uniform |
numpy.random.RandomState.vonmises | numpy.random.Generator.vonmises |
numpy.random.RandomState.wald | numpy.random.Generator.wald |
numpy.random.RandomState.weibull | numpy.random.Generator.weibull |
numpy.random.RandomState.zipf | numpy.random.Generator.zipf |
numpy.random.beta | numpy.random.Generator.beta |
numpy.random.binomial | numpy.random.Generator.binomial |
numpy.random.bytes | numpy.random.Generator.bytes |
numpy.random.chisquare | numpy.random.Generator.chisquare |
numpy.random.choice | numpy.random.Generator.choice |
numpy.random.dirichlet | numpy.random.Generator.dirichlet |
numpy.random.exponential | numpy.random.Generator.exponential |
numpy.random.f | numpy.random.Generator.f |
numpy.random.gamma | numpy.random.Generator.gamma |
numpy.random.geometric | numpy.random.Generator.geometric |
numpy.random.gumbel | numpy.random.Generator.gumbel |
numpy.random.hypergeometric | numpy.random.Generator.hypergeometric |
numpy.random.laplace | numpy.random.Generator.laplace |
numpy.random.logistic | numpy.random.Generator.logistic |
numpy.random.lognormal | numpy.random.Generator.lognormal |
numpy.random.logseries | numpy.random.Generator.logseries |
numpy.random.multinomial | numpy.random.Generator.multinomial |
numpy.random.multivariate_normal | numpy.random.Generator.multivariate_normal |
numpy.random.negative_binomial | numpy.random.Generator.negative_binomial |
numpy.random.noncentral_chisquare | numpy.random.Generator.noncentral_chisquare |
numpy.random.noncentral_f | numpy.random.Generator.noncentral_f |
numpy.random.normal | numpy.random.Generator.normal |
numpy.random.pareto | numpy.random.Generator.pareto |
numpy.random.permutation | numpy.random.Generator.permutation |
numpy.random.poisson | numpy.random.Generator.poisson |
numpy.random.power | numpy.random.Generator.power |
numpy.random.rand | numpy.random.Generator.random |
numpy.random.randint | numpy.random.Generator.integers |
numpy.random.randn | numpy.random.Generator.standard_normal |
numpy.random.random | numpy.random.Generator.random |
numpy.random.random_integers | numpy.random.Generator.integers |
numpy.random.random_sample | numpy.random.Generator.random |
numpy.random.ranf | numpy.random.Generator.random |
numpy.random.rayleigh | numpy.random.Generator.rayleigh |
numpy.random.sample | numpy.random.Generator.random |
numpy.random.seed | numpy.random.default_rng |
numpy.random.shuffle | numpy.random.Generator.shuffle |
numpy.random.standard_cauchy | numpy.random.Generator.standard_cauchy |
numpy.random.standard_exponential | numpy.random.Generator.standard_exponential |
numpy.random.standard_gamma | numpy.random.Generator.standard_gamma |
numpy.random.standard_normal | numpy.random.Generator.standard_normal |
numpy.random.standard_t | numpy.random.Generator.standard_t |
numpy.random.triangular | numpy.random.Generator.triangular |
numpy.random.uniform | numpy.random.Generator.uniform |
numpy.random.vonmises | numpy.random.Generator.vonmises |
numpy.random.wald | numpy.random.Generator.wald |
numpy.random.weibull | numpy.random.Generator.weibull |
numpy.random.zipf | numpy.random.Generator.zipf |
Docstrings should be defined
Docstrings should be defined
A string literal that is the first statement in a module, function, class, or method is a docstring. A docstring should document what a caller needs to know about the code. Information about what it does, what it returns, and what it requires are all valid candidates for documentation. Well written docstrings allow callers to use your code without having to first read it and understand its logic.
By convention, docstrings are enclosed in three sets of double-quotes.
tensorflow.function should not be recursive
tensorflow.function should not be recursive
When defining a tensorflow.function it is generally a bad practice to make this function recursive. TensorFlow does not support recursive tensorflow.function and will in the majority of cases throw an exception. However it is possible as well that the execution of such function succeeds, but with multiple tracings which has strong performance implications. When executing tensorflow.function, the code is split into two distinct stages. The first stage call tracing creates a new tensorflow.Graph, runs the Python code normally, but defers the execution of TensorFlow operations (i.e. adding two Tensors). These operations are added to the graph without being ran. The second stage which is much faster than the first, runs everything that was deferred previously. Depending on the input of the tensorflow.function the first stage may not be needed, see: Rules of tracing. Skipping this first stage is what provides the user with TensorFlow’s high performance.
Having a recursive tensorflow.function prevents the user from benefiting of TensorFlow’s capabilities.
Default parameter values should be immutable
Default parameter values should be immutable
While the assignment of default parameter values is typically a good thing, it can go very wrong very quickly when mutable objects are used. That’s because a new instance of the object is not created for each function invocation. Instead, all invocations share the same instance, and the changes made for one caller are made for all!
Functions returns should not be invariant
Functions returns should not be invariant
When a function is designed to return an invariant value, it may be poor design, but it shouldn’t adversely affect the outcome of your program. However, when it happens on all paths through the logic, it is surely a bug.
This rule raises an issue when a function contains several return statements that all return the same value.
Exception and BaseException should not be raised
Exception and BaseException should not be raised
Raising instances of `Exception and BaseException will have a negative impact on any code trying to catch these exceptions.
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.
The input_shape parameter should not be specified for tf.keras.Model subclasses
The input_shape parameter should not be specified for tf.keras.Model subclasses
Keras provides a full-featured model class called tensorflow.keras.Model. It inherits from tensorflow.keras.layers.Layer, so a Keras model can be used and nested in the same way as Keras layers. Keras models come with extra functionality that makes them easy to train, evaluate, load, save, and even train on multiple machines.
As the tensorflow.keras.Model class inherits from the ‘tensorflow.keras.layers’ you do not need to specify input_shape in a subclassed model; this argument will be ignored.
Function parameters should have type hints
Function parameters should have type hints
Being a dynamically typed language, the Python interpreter only does type checking during runtime. Getting the typing right is important as certain operations may result in a TypeError.
Type hints can be used to clarify the expected parameters of a function, enabling developers to better document its contract. Applying them consistently makes the code easier to read and understand.
In addition, type hints allow some development environments to offer better autocompletion and improve the precision of static analysis tools.
Generic functions should be defined using the type parameter syntax
Generic functions should be defined using the type parameter syntax
Prior to Python 3.12 functions using generic types were created as follows:
Function parameters default values should not be modified or assigned
Function parameters default values should not be modified or assigned
In Python, function parameters can have default values.
These default values are expressions which are evalutated when the function is defined, i.e. only once. The same default value will be used every time the function is called. Therefore, modifying it will have an effect on every subsequent call. This can lead to confusing bugs.
New-style classes should be used
New-style classes should be used
The new style of class creation, with the declaration of a parent class, created a unified object model in Python, so that the type of an instantiated class is equal to its class. In Python 2.2-2.7, this is not the case for old-style classes. In Python 3+ all classes are new-style classes. However, since the behavior can differ from 2.2+ to 3+, explicitly inheriting from object (if there is no better candidate) is recommended.
String formatting should not lead to runtime errors
String formatting should not lead to runtime errors
Formatting strings, either with the % operator or str.format method, requires a valid string and arguments matching this string’s replacement fields.
This rule raises an issue when formatting a string will raise an exception because the input string or arguments are invalid. Rule S3457 covers cases where no exception is raised and the resulting string is simply not formatted properly.
Using timezone-aware datetime objects should be preferred over using datetime.datetime.utcnow and datetime.datetime.utcfromtimestamp
Using timezone-aware datetime objects should be preferred over using datetime.datetime.utcnow and datetime.datetime.utcfromtimestamp
Python’s datetime API provide several different ways to create datetime objects. One possibility is the to use datetime.datetime.utcnow or datetime.datetime.utcfromtimestamp functions. The issue with these two functions is they are not time zone aware, even if their name would suggest otherwise.
Using these functions could cause issue as they may not behave as expected, for example:
The exec statement should not be used
The exec statement should not be used
Use of the `exec statement could be dangerous, and should be avoided. Moreover, the exec statement was removed in Python 3.0. Instead, the built-in exec() function can be used.
Use of the exec statement is strongly discouraged for several reasons such as:
Security Risks: Executing code from a string opens up the possibility of code injection attacks.
Readability and Maintainability: Code executed with exec statement is often harder to read and understand since it is not explicitly written in the source code.
Performance Implications: The use of exec statement can have performance implications since the code is compiled and executed at runtime.
Limited Static Analysis: Since the code executed with exec` statement is only known at runtime, static code analysis tools may not be able to catch certain errors or issues, leading to potential bugs.
Collections should not be modified while they are iterated
Collections should not be modified while they are iterated
Iterating over a collection using a for loop in Python relies on iterators.
An iterator is an object that allows you to traverse a collection of elements, such as a list or a dictionary. Iterators are used in for loops to iterate over the elements of a collection one at a time.
When you create an iterator, it keeps track of the current position in the collection and provides a way to access the next element. The next() function is used to retrieve the next element from the iterator. When there are no more elements to iterate over, the next() function raises a StopIteration exception and the iteration stops.
It is important to note that iterators are designed to be read-only. Modifying a collection while iterating over it can cause unexpected behavior, as the iterator may skip over or repeat elements. A RuntimeError may also be raised in this situation, with the message changed size during iteration. Therefore, it is important to avoid modifying a collection while iterating over it to ensure that your code behaves as expected.
If you still want to modify the collection, it is best to use a second collection or to iterate over a copy of the original collection instead.
Parentheses should not be used after certain keywords
Parentheses should not be used after certain keywords
Parentheses are not required after the assert, del, elif, except, for, if, in, not, raise, return, while, and yield keywords, and using them unnecessarily impairs readability. They should therefore be omitted.
Static methods should not have self or cls arguments
Static methods should not have self or cls arguments
Unlike class and instance methods, static methods don’t receive an implicit first argument. Nonetheless naming the first argument self or cls guarantees confusion - either on the part of the original author, who may never understand why the arguments don’t hold the values he expected, or on that of future maintainers.
Return values from functions without side effects should not be ignored
Return values from functions without side effects should not be ignored
When the call to a function doesn’t have any side effects, what is the point of making the call if the results are ignored? In such case, either the function call is useless and should be dropped or the source code doesn’t behave as expected.
This rule raises an issue when a builtin function or methods which has no side effects is called and its result is not used.
The yield keyword should only be used in generators
The yield keyword should only be used in generators
As soon as the `yield keyword is used the enclosing method or function becomes a generator. Thus yield should never be used in a function or method which is not intended to be a generator.
This rule raises an issue when yield or yield from are used in a function or method which is not a generator because:
the function/method’s return type annotation is not [typing.Generator[…]|https://docs.python.org/3/library/typing.html#typing.Generator]
it is a special method which can never be a generator (ex: init`).
Builtins should not be shadowed by local variables
Builtins should not be shadowed by local variables
Defining a variable with the same name as a built-in symbol will “shadow” it. That means that the builtin will no longer be accessible through its original name, having locally been replaced by the variable.
Shadowing a builtin makes the code more difficult to read and maintain. It may also be a source of bugs as you can reference the builtin by mistake.
It is sometimes acceptable to shadow a builtin to improve the readability of a public API or to support multiple versions of a library. In these cases, benefits are greater than the maintainability cost. This should, however, be done with care.
It is generally not a good practice to shadow builtins with variables which are local to a function or method. These variables are not public and can easily be renamed, thus reducing the confusion and making the code less error-prone.
Calls should not be made to non-callable values
Calls should not be made to non-callable values
In order to be callable, a Python class should implement the `call method. Thanks to this method, an instance of this class will be callable as a function.
However, when making a call to a non-callable object, a TypeError will be raised.
In order to fix this issue, make sure that the object you are trying to call has a call` method.
Asserts should not be used to check the parameters of a public method
Asserts should not be used to check the parameters of a public method
An assert is inappropriate for parameter validation because assertions are disabled globally at the interpreter level when the application runs as optimize bytecode (-O and -OO command line switches). It means that the optimize version of the application would completely eliminate the intended checks.
This rule raises an issue when a public method uses one or more of its parameters with asserts.
Function arguments should be passed only once
Function arguments should be passed only once
When a function is called, it accepts only one value per parameter. The Python interpreter will raise a SyntaxError when the same parameter is provided more than once, i.e. myfunction(a=1, a=2).
Other less obvious cases will also fail at runtime by raising a TypeError, when:
An argument is provided by value and position at the same time.
An argument is provided twice, once via unpacking and once by value or position.
with statements should be used with context managers
with statements should be used with context managers
The with statement is used to wrap the execution of a block with methods defined by a context manager. The context manager handles the entry into, and the exit from, the desired runtime context for the execution of the block of code. To do so, a context manager should have an enter and an exit method.
Executing the following block of code:
Wildcard imports should not be used
Wildcard imports should not be used
Importing every public name from a module using a wildcard (from mymodule import *) is a bad idea because:
It could lead to conflicts between names defined locally and the ones imported.
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 that works today might be broken tomorrow.
exit should accept type, value, and traceback arguments
exit should accept type, value, and traceback arguments
The exit method is invoked with four arguments: self, type, value and traceback. Leave one of these out of the method declaration and the result will be a TypeError at runtime.
The number and name of arguments passed to a function should match its parameters
The number and name of arguments passed to a function should match its parameters
Calling a function or a method with fewer or more arguments than expected will raise a TypeError. This is usually a bug and should be fixed.
break and continue should not be used outside a loop
break and continue should not be used outside a loop
break and continue are control flow statements used inside of loops. break is used to break out of its innermost enclosing loop and continue will continue with the next iteration.
The example below illustrates the use of break in a while loop:
Functions and methods should only return expected values
Functions and methods should only return expected values
Python allows developers to customize how code is interpreted by defining special methods (also called magic methods). For example, it is possible to define the objects own truthiness or falsiness by iverriding `bool method. It is invoked when the built-in bool() function is called on an object. The bool() function returns True or False based on the truth value of the object.
The Python interpreter will call these methods when performing the operation they’re associated with. Each special method expects a specific return type. Calls to a special method will throw a TypeError if its return type is incorrect.
An issue will be raised when one of the following methods doesn’t return the indicated type:
bool method should return bool
index method should return integer
repr method should return string
str method should return string
bytes method should return bytes
hash method should return integer
format method should return string
getnewargs method should return tuple
getnewargs_ex` method should return something which is of the form tuple(tuple, dict)
Item operations should be done on objects supporting them
Item operations should be done on objects supporting them
Getting, setting and deleting items using square brackets requires the accessed object to have special methods:
Getting items such as `my_variable[key] requires my_variable to have the getitem method, or the class_getitem method if my_variable is a class.
Setting items such as my_variable[key] = 42 requires my_variable to have the setitem method.
Deleting items such as del my_variable[key] requires my_variable to have the delitem method.
Performing these operations on an object that doesn’t have the corresponding method will result in a TypeError`.
To fix this issue, make sure that the class for which you are trying to perform item operations implements the required methods.
Replacement strings should reference existing regular expression groups
Replacement strings should reference existing regular expression groups
The regex function re.sub can be used to perform a search and replace based on regular expression matches. The repl parameter can contain references to capturing groups used in the pattern parameter. This can be achieved with \n to reference the n’th group.
When referencing a nonexistent group an error will be thrown for Python < 3.5 or replaced by an empty string for Python >= 3.5.
The first argument to a super call should be the name of the calling class
The first argument to a super call should be the name of the calling class
The first argument to super must be the name of the class making the call. If it’s not, the result will be a runtime error.
null=True should not be used on string-based fields in Django models
null=True should not be used on string-based fields in Django models
Using “null=True” on string-based fields can lead to inconsistent and unexpected behavior. In Django, “null=True” allows the field to have a NULL value in the database. However, the Django convention to represent the absence of data for a string is an empty string. Having two ways to represent the absence of data can cause problems when querying and filtering on the field. For example, if a CharField with “null=True” has a value of NULL in the database, querying for an empty string will not return that object.
GraphQL introspection should be disabled in production
GraphQL introspection should be disabled in production
GraphQL introspection is a feature that allows client applications to query the schema of a GraphQL API at runtime. It provides a way for developers to explore and understand the available data and operations supported by the API.
This feature is a diagnostic tool that should only be used in the development phase as its presence also creates risks.
Clear documentation and API references should be considered better discoverability tools for a public GraphQL API.
Functions, methods and lambdas should not have too many parameters
Functions, methods and lambdas should not have too many parameters
Functions, methods, or lambdas with a long parameter list are difficult to use, as maintainers must figure out the role of each parameter and keep track of their position.
The safe flag should be set to False when serializing non-dictionary objects in Django JSON-encoded responses.
The safe flag should be set to False when serializing non-dictionary objects in Django JSON-encoded responses.
By default, only dictionary objects can be serialized in Django JSON-encoded response. Before ECMASCript 5, serializing non-dictionary objects could lead to security vulnerabilities. Since most modern browsers implement ECMAScript 5, this vector of attack is no longer a threat and it is possible to serialize non-dictionary objects by setting the safe flag to False. However, if this flag is not set, a TypeError will be thrown by the serializer.
Despite this possibility, it is still recommended to serialize dictionary objects, as an API based on dict is generally more extensible and easier to maintain.
Walrus operator should not make code confusing
Walrus operator should not make code confusing
The walrus operator := (also known as “assignment expression”) should be used with caution as it can easily make code more difficult to understand and thus maintain. In such case it is advised to refactor the code and use an assignment statement (i.e. =) instead.
Reasons why it is better to avoid using the walrus operator in Python:
Readability: The walrus operator can lead to more complex and nested expressions, which might reduce the readability of the code, especially for developers who are not familiar with this feature.
Compatibility: If you are working on projects that need to be compatible with older versions of Python (before 3.8), you should avoid using the walrus operator, as it won’t be available in those versions.
Loops without break should not have else clauses
Loops without break should not have else clauses
The else clause of a loop is skipped when a break is executed in this loop. In other words, a loop with an else but no break statement will always execute the else part (unless of course an exception is raised or return is used). If this is what the developer intended, it would be much simpler to have the else statement removed and its body unindented. Thus having a loop with an else and no break is most likely an error.
Methods and properties that dont access instance data should be static
Methods and properties that dont access instance data should be static
Class methods that don’t access instance data can and should be static because they yield more performant code.
To implement a static method in Python one should use either @classmethod or @staticmethod. A class method receives the class as implicit first argument, just like an instance method receives the instance. A static method does not receive an implicit first argument.
Method overrides should not change contracts
Method overrides should not change contracts
Because a subclass instance may be used as an instance of the superclass, overriding methods should uphold the aspects of the superclass contract that relate to the Liskov Substitution Principle. Specifically, an overriding method should be callable with the same parameters as the overriden one.
The following modifications are OK:
Adding an optional parameter, i.e. with a default value, as long as they don’t change the order of positional parameters.
Renaming a positional-only parameter.
Reordering keyword-only parameters.
Adding a default value to an existing parameter.
Changing the default value of an existing parameter.
Extend the ways a parameter can be provided, i.e. change a keyword-only or positional-only parameter to a keyword-or-positional parameter. This is only true if the order of positional parameters doesn’t change. New positional parameters should be placed at the end.
Adding a vararg parameter (`*args).
Adding a keywords parameter (**kwargs).
The following modifications are not OK:
Removing parameters, even when they have default values.
Adding mandatory parameters, i.e. without a default value.
Removing the default value of a parameter.
Reordering parameters, except when they are keyword-only parameters.
Removing some ways of providing a parameter. If a parameter could be passed as keyword it should still be possible to pass it as keyword, and the same is true for positional parameters.
Removing a vararg parameter (*args).
Removing a keywords parameter (**kwargs`).
This rule raises an issue when the signature of an overriding method does not accept the same parameters as the overriden one. Only instance methods are considered, class methods and static methods are ignored.
All branches in a conditional structure should not have exactly the same implementation
All branches in a conditional structure should not have exactly the same implementation
Having all branches of an if chain with the same implementation indicates a problem.
In the following code:
Instance and class methods should have at least one positional parameter
Instance and class methods should have at least one positional parameter
Every instance method is expected to have at least one positional parameter. This parameter will reference the object instance on which the method is called. Calling an instance method which doesn’t have at least one parameter will raise a TypeError. By convention, this first parameter is usually named self.
Class methods, i.e. methods annotated with @classmethod, also require at least one parameter. The only differences is that they will receive the class itself instead of a class instance. By convention, this first parameter is usually named cls.
Assert should not be called on a tuple literal
Assert should not be called on a tuple literal
When tested for truthiness, a sequence or collection will evaluate to False if it is empty (its `len method returns 0) and to True if it contains at least one element.
Using the assert statement on a tuple literal will therefore always fail if the tuple is empty, and always succeed otherwise.
The assert statement does not take parentheses around its parameters. Calling assert(x, y) will test if the tuple (x, y) is True, which is always the case.
There are two possible fixes:
If your intention is to test the first value of the tuple and use the second value as a message, simply remove the parentheses.
If your intention is to check that every element of the tuple is True`, test each value separately.
Long suffix L should be upper case
Long suffix L should be upper case
The long suffix should always be written in uppercase, i.e. ‘L’, as the lowercase ‘l’ can easily be confused with the digit one ‘1’.
The validate_indices argument should not be set for tf.gather function call
The validate_indices argument should not be set for tf.gather function call
The tf.gather function allows you to gather slices from a tensor along a specified axis according to the indices provided. The validate_indices argument is deprecated and setting its value has no effect. Indices are always validated on CPU and never validated on GPU.
Special methods should have an expected number of parameters
Special methods should have an expected number of parameters
Python allows developers to customize how code is interpreted by defining special methods (also called magic methods). For example, it is possible to override how the multiplication operator (`a * b) will apply to instances of a class by defining in this class the mul and rmul methods. Whenever a multiplication operation is performed with this class, the Python interpreter will call one of these methods instead of performing the default multiplication.
Each special method expects a specific number of parameters. The Python interpreter will call these methods with those parameters. Calls to a special method will throw a TypeError` if it is defined with an incorrect number of parameters.
Octal escape sequences should not be used in regular expressions
Octal escape sequences should not be used in regular expressions
Using octal escapes in regular expressions can create confusion with backreferences. Octal escapes are sequences of digits that represent a character in the ASCII table, and they are sometimes used to represent special characters in regular expressions. However, they can be easily mistaken for backreferences, which are also sequences of digits that represent previously captured groups. This confusion can lead to unexpected results or errors in the regular expression.
Unused class-private methods should be removed
Unused class-private methods should be removed
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”:
methods with a name starting with a single underscore (ex: `_mymethod) should be seen as non-public and might change without prior notice. They should not be used by third-party libraries or software. It is ok to use those methods inside the library defining them but it should be done with caution.
”class-private” methods have a name which starts with at least two underscores and ends with at most one underscore. These methods’ names will be automatically mangled to avoid collision with subclasses’ methods. For example __mymethod will be renamed as _classname__mymethod, where classname` is the method’s class name without its leading underscore(s). These methods shouldn’t be used outside of their enclosing class.
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.
Passing a list to np.array should be preferred over passing a generator
Passing a list to np.array should be preferred over passing a generator
The creation of a NumPy array can be done in several ways, for example by passing a Python list to the np.array function.
Another way would be to pass a generator to the np.array function, but doing so creates a 0-dimensional array of objects and may not be the intended goal.
This NumPy array will have a have a data type (dtype) of object and could hold any Python objects.
One of the characteristics of NumPy arrays is homogeneity, meaning all its elements are of the same type. Creating an array of objects allows the user to create heterogeneous array without raising any errors and creating such an array can lead to bugs further in the program.
* and ** should not be used in function calls
* and ** should not be used in function calls
* and **, conventionally known as *args and **kwargs (although any names can be used), can be used in either a function definition or in a function call. In a function definition, they allow a variable number of arguments to be passed. In a function call, they simply obscure the actual values being used in the call.
Character classes should be preferred over reluctant quantifiers in regular expressions
Character classes should be preferred over reluctant quantifiers in regular expressions
Using reluctant quantifiers (also known as lazy or non-greedy quantifiers) in patterns can often lead to needless backtracking, making the regex needlessly inefficient and potentially vulnerable to catastrophic backtracking. Particularly when using .? or .+? to match anything up to some terminating character, it is usually a better idea to instead use a greedily or quantified negated character class containing the terminating character. For example <.+?> should be replaced with <[^>]> or <[^>]+>.
The open builtin function should be called with a valid mode
The open builtin function should be called with a valid mode
The open builtin function can open files in different modes. These modes are provided as a combination of characters. Using an invalid sequence of characters will make open fail with a ValueError.
A valid mode:
should contain only one of the following characters: r (read), w (write), a (append), x (create).
should contain zero or one of the following characters: t (text), b (binary).
should contain zero or one + character (open for updating)
For example: a, rt, r+ and w+b are valid modes.
If no t or b character is provided the mode will default to t (text), so specifying r is equivalent to rt.
Note: In Python 2, providing an incorrect mode may have an undefined behavior (ex: it might ignore some characters)
HTML autoescape mechanism should not be globally disabled
HTML autoescape mechanism should not be globally disabled
Template engines have an HTML autoescape mechanism that protects web applications against most common cross-site-scripting (XSS) vulnerabilities.
By default, it automatically replaces HTML special characters in any template variables. This secure by design configuration should not be globally disabled.
Escaping HTML from template variables prevents switching into any execution context, like <script>. Disabling autoescaping forces developers to manually escape each template variable for the application to be safe. A more pragmatic approach is to escape by default and to manually disable escaping when needed.
A successful exploitation of a cross-site-scripting vulnerability by an attacker allow him to execute malicious JavaScript code in a user’s web browser. The most severe XSS attacks involve:
Forced redirection
Modify presentation of content
User accounts takeover after disclosure of sensitive information like session cookies or passwords
This rule supports the following libraries:
Bare raise statements should only be used in except blocks
Bare raise statements should only be used in except blocks
A bare raise statement, i.e. a raise with no exception provided, will re-raise the last active exception in the current scope:
yield and return should not be used outside functions
yield and return should not be used outside functions
yield and return only make sense in the context of functions. Using them outside a function raises a SyntaxError.
If the goal is to break out of a loop, use break instead of return.
The output of functions that dont return anything should not be used
The output of functions that dont return anything should not be used
If a function does not return anything, it makes no sense to use its output. Specifically, passing it to another function, or assigning its “result” to a variable is probably a bug because such functions return nothing, which is probably not what was intended.
locals() should not be passed to a Django render() function
locals() should not be passed to a Django render() function
Using the “locals()” function to pass context to a Django “render()” function can lead to security vulnerabilities and unexpected behavior. “locals()” returns a dictionary of the current local scope, including any sensitive information that may be present in the function’s local namespace. This means that if “locals()” is used to pass context to “render()”, sensitive data such as passwords, keys, and other secrets could be leaked.
Additionally, using “locals()” to pass context can make code more difficult to read and understand. It can also make it harder to maintain code over time.
Constructor attributes of date and time objects should be in the range of possible values
Constructor attributes of date and time objects should be in the range of possible values
Setting a date attribute value with a value which is out of the range of possible values will lead to a ValueError.
Assertions should not be made at the end of blocks expecting an exception
Assertions should not be made at the end of blocks expecting an exception
Using pytest.raises or unittest.TestCase.assertRaises will assert that an exception is raised in the following block. Ending such block in an assertion means that the test can succeed with that last assertion never being executed.
Values assigned to variables should match their type annotations
Values assigned to variables should match their type annotations
Type hints in Python allow you to specify the expected types of variables and function return values. While type hints are not enforced at runtime, they serve as documentation and can be checked using static type checkers to catch type-related errors during development.
When an assigned value type is incompatible with the type hint of the assigning variable, it can lead to several issues:
Type-related bugs: Assigning a value of an incompatible type to a variable with a specific type hint may lead to unexpected behavior or errors at runtime.
Readability and maintainability: Type hints improve code readability by explicitly stating the intended types of variables and functions. When the assigned value type doesn’t match the hint, it can confuse other developers and make the code harder to maintain.
Non-existent dictionary keys should not be accessed
Non-existent dictionary keys should not be accessed
Trying to access a dictionary key that does not exist will raise a KeyError exception.
When trying to access or remove a key that may not be there, several solutions are possible:
Use the get() method instead of a subscription. It will return None for a missing key instead of raising a KeyError.
Use the setdefault() method to provide keys that may be missing with a default value.
Check that the key is present in the dictionary with the if key in dict: construct.
Use a try/except block and handle the potential KeyError exception.
Use a defaultdict instead of a regular dict object, and provide a default_factory attribute.
Property getter, setter and deleter methods should have the expected number of parameters
Property getter, setter and deleter methods should have the expected number of parameters
Creating property accessors and mutators is quite common in Object-Oriented Programming. Python provides two main ways of implementing getters, setters and deleters; either with the `@property decorator, or with the property function.
The following program illustrates how using the built-in operations will call the custom methods defined above.
Defining a property this way allows for flexibility when refactoring the implementation of the getters, setters and deleters method, as all the accesses and modifications are done through the Python built-in operators (=,.) and keyword (del).
Property getter, setter and deleter methods are called by the Python interpreter with a specific number of arguments:
Property getter and deleter methods only require a “self” argument.
Property setter methods require a “self” argument as well as a value.
Adding any other parameters, or removing these mandatory parameters will throw a TypeError` exception at runtime when trying to access or modify the property.
Any should not be used as a type hint
Any should not be used as a type hint
The type hint Any represents any possible Python type, on which all operations are possible. This conveys the information that all operations could be possible on a value annotated with Any, making the value dynamically-typed.
Any as a type hint provides no information about the expected type of the variable or parameter, essentially losing the benefits of type hinting. This can make the code less clear and harder to understand and will reduce the code insight capabilities of IDEs and static analysis tools.
dtype parameter should be provided when using pandas.read_csv or pandas.read_table
dtype parameter should be provided when using pandas.read_csv or pandas.read_table
The pandas library provides an easy way to load data from documents hosted locally or remotely, for example with the pandas.read_csv or pandas.read_table functions:
Parameters should be passed in the correct order
Parameters should be passed in the correct order
When the names of parameters in a function/method call match the names of the method arguments, it contributes to clearer, more readable code. However, when the names match, but are passed in a different order than the function/method arguments, it indicates a mistake in the parameter order which will likely lead to unexpected results.
All except blocks should be able to catch exceptions
All except blocks should be able to catch exceptions
Exceptions handlers (except) are evaluated in the order they are written. Once a match is found, the evaluation stops.
In some contexts, an except block is dead code as it will never catch any exception:
If there is a handler for a base class followed by a handler for class derived from that base class, the second handler will never trigger: The handler for the base class will match the derived class, and will be the only executed handler.
When multiple except statements try to catch the same exception class, only the first one will be executed.
In Python 3, BaseException is the parent of every exception class. When a BaseException is caught by an except clause, none of the subsequent except statement will catch anything. This is true as well for the bare except statement (except:).
Unnecessary imports should be removed
Unnecessary imports should be removed
Importing names and not using them can be a source of confusion and lead to maintainability issues.
Such imports should be removed.
Allowing unrestricted outbound communications is security-sensitive
Allowing unrestricted outbound communications is security-sensitive
utbound communications can lead to data leaks.
A restrictive security group is an additional layer of protection that might prevent the abuse or exploitation of a resource. For example, it complicates the exfiltration of data in the case of a successfully exploited vulnerability.
When deciding if outgoing connections should be limited, consider that limiting the connections results in additional administration and maintenance work.
Backticks should not be used
Backticks should not be used
In Python 2, backticks are a deprecated alias for repr(). The syntax was removed in Python 3. To make the transition to Python 3 easier, they should not be used anymore.
Implicit string and byte concatenations should not be confusing
Implicit string and byte concatenations should not be confusing
Python concatenates adjacent string or byte literals at compile time. It means that “a” “b” is equivalent to “ab”.
This is sometimes used to split a long string on multiple lines. However an implicit string concatenation can also be very confusing.
In the following contexts it might indicate that a comma was forgotten:
when the two strings are on the same line. This could be interpreted as an incorrectly formatted tuple (parentheses are not mandatory to create a tuple, only the comma is).
when the strings are in a list, a set or a tuple.
String formatting should be used correctly
String formatting should be used correctly
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 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 S2275 covers cases where formatting a string will raise an exception.
global should not be used
global should not be used
Global variables are a useful construct, but they should not be abused. Functions access the global scope through the global keyword, but this practice considerably reduce the function’s readability and reusability. Instead, the global variable should be passed as a parameter to the function.
Dictionary definitions should not contain duplicate keys
Dictionary definitions should not contain duplicate keys
During dictionary use, it is normal that you might want to replace the value associated with one of the dictionary’s keys. But do so during the initial definition of a dictionary, and you’ve probably made an error.
This rule raises an issue when the same key is used multiple times in the initial definition of a dictionary.
Django signal handler functions should have the @receiver decorator on top of all other decorators
Django signal handler functions should have the @receiver decorator on top of all other decorators
In Django, the ‘@receiver’ decorator is used to register signal handlers. These handlers are used to respond to events that occur in the application, such as a user logging in or a database record being saved.
The order in which decorators are applied can have a significant impact on their behavior. In the case of the @receiver decorator, it is important that it is applied first, before any other decorators, in order to ensure that the signal handler is registered correctly.
If the ‘@receiver’ decorator is not applied first, the decorators placed above it will be ignored, which can result in unexpected behavior or even errors in the application.
The most specific unittest assertion should be used
The most specific unittest assertion should be used
The `unittest module provides assertion methods specific to common types and operations. Both versions will test the same things, but the dedicated one will provide a better error message, simplifying the debugging process.
This rule reports an issue when an assertion can be simplified by using a more specific function. The array below gives a list of assertions on which an issue will be raised, and which function should be used instead:
True and False should not be used as identifiers
True and False should not be used as identifiers
Python interprets False as a “false” boolean value, and True as a “true” boolean value. Assigning them other values could lead to unexpected behaviors.
This rule raises an issue when “True” and “False”, with any case, are used as identifiers.
Variables, classes and functions should be defined before being used
Variables, classes and functions should be defined before being used
Variables, Classes and functions should be defined before they are used, otherwise the code will fail.
Attributes should not be accessed on None values
Attributes should not be accessed on None values
None is a built-in object that represents the absence of a value. It is often used as a placeholder value for variables that only sometimes hold a value or as a return value for method calls that have no result.
Attributes and methods of symbols that sometimes can be None should only be accessed in circumstances where it is certain that they are not set to None. Otherwise, an AttributeError is raised, and the program is interrupted. Hence, this issue indicates a logical error as it results from incorrect assumptions about the state of variables or the results of computations.
Arguments given to functions should be of an expected type
Arguments given to functions should be of an expected type
The CPython interpreter does not check types of arguments when functions are called. However, a function can express the type it expects for each argument in its documentation or by using Type Hints. While the code may initially work as intended, not respecting the contract of an API may lead to bugs later when its implementation evolves or when type checks are added (i.e. with isinstance).
This rule also checks argument types for built-in functions.
Calls should not use too many positional arguments
Calls should not use too many positional arguments
You’re allowed to make function calls with positionally-identified parameters or with named parameters. In long parameter lists, explicitly naming your parameters both eliminates the risk of swapping parameter values and makes the call clearer to maintainers.
The print statement should not be used
The print statement should not be used
The print statement was removed in Python 3.0. The built-in function should be used instead.
Functions should use return consistently
Functions should use return consistently
Because it is dynamically typed, Python does not enforce a return type on a function. This means that different paths through a function can return different types of values, which can be very confusing to the user and significantly harder to maintain.
In particular, it is consequently also possible to mix empty return statements (implicitly returning None) with some returning an expression. This rule verifies that all the return statements from a function are consistent.
GraphQL queries should not be vulnerable to Denial of Service attacks
GraphQL queries should not be vulnerable to Denial of Service attacks
When a server receives a deeply nested query, it attempts to resolve all the requested data. This process can consume a substantial amount of computational resources, leading to a slowdown in server response times.
A reason should be provided when skipping a test
A reason should be provided when skipping a test
When a test fails due, for example, to infrastructure issues, you might want to ignore it temporarily. But without some kind of notation about why the test is being ignored, it may never be reactivated. Such tests are difficult to address without comprehensive knowledge of the project, and end up polluting their projects.
This rule raises an issue for each skipped test with “unittest.skip” or “pytest.mark.skip” without providing a reason argument.
Break, continue and return statements should not occur in finally blocks
Break, continue and return statements should not occur in finally blocks
Using `return, break or continue in a finally block suppresses the propagation of any unhandled exception which was raised in the try, else or except blocks. It will also ignore their return statements.
SystemExit is raised when sys.exit() is called. KeyboardInterrupt is raised when the user asks the program to stop by pressing interrupt keys. Both exceptions are expected to propagate up until the application stops. It is ok to catch them when a clean-up is necessary but they should be raised again immediately. They should never be ignored.
If you need to ignore every other exception you can simply catch the Exception class. However you should be very careful when you do this as it will ignore other important exceptions such as MemoryError
In python 2 it is possible to raise old style classes. You can use a bare except: statement to catch every exception. Remember to still reraise SystemExit and KeyboardInterrupt.
This rule raises an issue when a jump statement (break, continue, return`) would force the control flow to leave a finally block.
Type aliases should be declared with a type statement
Type aliases should be declared with a type statement
Since Python 3.12 the keyword type is used to defined type aliases. It replaces the following construct:
Unused scope-limited definitions should be removed
Unused scope-limited definitions should be removed
When a class or function is defined in a parent function or method, it is only visible in this parent function or method’s scope. If the defined class or function is not used within this scope it is 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.
pass should not be used needlessly
pass should not be used needlessly
The use of a pass statement where it is not required by the syntax is redundant. It makes the code less readable and its intent confusing.
To fix this issue, remove pass statements that do not affect the behaviour of the program.
The 12-hour format should be used with the AM/PM marker, otherwise the 24-hour format should be used
The 12-hour format should be used with the AM/PM marker, otherwise the 24-hour format should be used
The %p directive in the strftime method is used to represent the AM/PM marker in a time string. It is commonly used in conjunction with the %I directive, which represents the hour in a 12-hour clock.
Using the 24-hour format directive with an AM/PM marker can lead to unwanted results e.g.:
Boolean checks should not be inverted
Boolean checks should not be inverted
It is needlessly complex to invert the result of a boolean comparison. The opposite comparison should be made instead.
Regular expressions should be syntactically valid
Regular expressions should be syntactically valid
Regular expressions have their own syntax that is understood by regular expression engines. Those engines will throw an exception at runtime if they are given a regular expression that does not conform to that syntax.
To avoid syntax errors, special characters should be escaped with backslashes when they are intended to be matched literally and references to capturing groups should use the correctly spelled name or number of the group.
Using publicly writable directories is security-sensitive
Using publicly writable directories is security-sensitive
Operating systems have global directories where any user has write access. Those folders are mostly used as temporary storage areas like `/tmp in Linux based systems. An application manipulating files from these folders is exposed to race conditions on filenames: a malicious user can try to create a file with a predictable name before the application does. A successful attack can result in other files being accessed, modified, corrupted or deleted. This risk is even higher if the application runs with elevated permissions.
In the past, it has led to the following vulnerabilities:
This rule raises an issue whenever it detects a hard-coded path to a publicly writable directory like /tmp (see examples bellow). It also detects access to environment variables that point to publicly writable directories, e.g., TMP and TMPDIR.
/tmp
/var/tmp
/usr/tmp
/dev/shm
/dev/mqueue
/run/lock
/var/run/lock
/Library/Caches
/Users/Shared
/private/tmp
/private/var/tmp
\Windows\Temp
\Temp
\TMP`
Non-capturing groups without quantifier should not be used
Non-capturing groups without quantifier should not be used
Sub-patterns can be wrapped by parentheses to build a group. This enables to restrict alternations, back reference the group or apply quantifier to the sub-pattern.
If this group should not be part of the match result or if no reference to this group is required, a non-capturing group can be created by adding ?: behind the opening parenthesis.
However, if this non-capturing group does not have a quantifier, or does not wrap an alternation, then imaging this group is redundant.
Superfluous curly brace quantifiers should be avoided
Superfluous curly brace quantifiers should be avoided
Curly brace quantifiers in regular expressions can be used to have a more fine-grained control over how many times the character or the sub-expression preceeding them should occur. They can be used to match an expression exactly n times with `, between n and m times with , or at least n times with n. In some cases, using such a quantifier is superfluous for the semantic of the regular expression, and it can be removed to improve readability. This rule raises an issue when one of the following quantifiers is encountered:
or : they match the expression exactly once. The same behavior can be achieved without the quantifier.
or `: they match the expression zero times. The same behavior can be achieved by removing the expression.
Statements should be on separate lines
Statements should be on separate lines
Putting multiple statements on a single line lowers the code readability and makes debugging the code more complex.
Unresolved directive in <stdin> - include::[]
Write one statement per line to improve readability.
Unresolved directive in <stdin> - include::[]
Disabling CSRF protections is security-sensitive
Disabling CSRF protections is security-sensitive
A cross-site request forgery (CSRF) attack occurs when a trusted user of a web application can be forced, by an attacker, to perform sensitive actions that he didn’t intend, such as updating his profile or sending a message, more generally anything that can change the state of the application.
The attacker can trick the user/victim to click on a link, corresponding to the privileged action, or to visit a malicious web site that embeds a hidden web request and as web browsers automatically include cookies, the actions can be authenticated and sensitive.
Alternation in regular expressions should not contain empty alternatives
Alternation in regular expressions should not contain empty alternatives
Alternation is used to match a single regular expression out of several possible regular expressions. If one of the alternatives is empty it would match any input, which is most probably a mistake.
Searching OS commands in PATH is security-sensitive
Searching OS commands in PATH is security-sensitive
When executing an OS command and unless you specify the full path to the executable, then the locations in your application’s PATH environment variable will be searched for the executable. That search could leave an opening for an attacker if one of the elements in PATH is a directory under his control.
Having a permissive Cross-Origin Resource Sharing policy is security-sensitive
Having a permissive Cross-Origin Resource Sharing policy is security-sensitive
Having a permissive Cross-Origin Resource Sharing policy is security-sensitive. It has led in the past to the following vulnerabilities:
Same origin policy in browsers prevents, by default and for security-reasons, a javascript frontend to perform a cross-origin HTTP request to a resource that has a different origin (domain, protocol, or port) from its own. The requested target can append additional HTTP headers in response, called CORS, that act like directives for the browser and change the access control policy / relax the same origin policy.
Character classes in regular expressions should not contain only one character
Character classes in regular expressions should not contain only one character
Character classes in regular expressions are a convenient way to match one of several possible characters by listing the allowed characters or ranges of characters. If a character class contains only one character, the effect is the same as just writing the character without a character class.
Thus, having only one character in a character class is usually a simple oversight that remained after removing other characters of the class.
Collection content should not be replaced unconditionally
Collection content should not be replaced unconditionally
Allowing public network access to cloud resources is security-sensitive
Allowing public network access to cloud resources is security-sensitive
Enabling public network access to cloud resources can affect an organization’s ability to protect its data or internal operations from data theft or disruption.
Depending on the component, inbound access from the Internet can be enabled via:
a boolean value that explicitly allows access to the public network.
the assignment of a public IP address.
database firewall rules that allow public IP ranges.
Deciding to allow public access may happen for various reasons such as for quick maintenance, time saving, or by accident.
This decision increases the likelihood of attacks on the organization, such as:
data breaches.
intrusions into the infrastructure to permanently steal from it.
and various malicious traffic, such as DDoS attacks.
Using unencrypted RDS DB resources is security-sensitive
Using unencrypted RDS DB resources is security-sensitive
Using unencrypted RDS DB resources exposes data to unauthorized access. This includes database data, logs, automatic backups, read replicas, snapshots, and cluster metadata.
This situation can occur in a variety of scenarios, such as:
A malicious insider working at the cloud provider gains physical access to the storage device.
Unknown attackers penetrate the cloud provider’s logical infrastructure and systems.
After a successful intrusion, the underlying applications are exposed to:
theft of intellectual property and/or personal data
extortion
denial of services and security bypasses via data corruption or deletion
AWS-managed encryption at rest reduces this risk with a simple switch.
General except clauses should not be used
General except clauses should not be used
A general catch block seems like an efficient way to handle multiple possible exceptions. Unfortunately, it traps all exception types, casting too broad a net, and perhaps mishandling extraordinary cases. Instead, specific exception sub-types should be caught.
Delivering code in production with debug features activated is security-sensitive
Delivering code in production with debug features activated is security-sensitive
Development tools and frameworks usually have options to make debugging easier for developers. Although these features are useful during development, they should never be enabled for applications deployed in production. Debug instructions or error messages can leak detailed information about the system, like the application’s path or file names.
Using unencrypted SageMaker notebook instances is security-sensitive
Using unencrypted SageMaker notebook instances is security-sensitive
Amazon SageMaker is a managed machine learning service in a hosted production-ready environment. To train machine learning models, SageMaker instances can process potentially sensitive data, such as personal information that should not be stored unencrypted. In the event that adversaries physically access the storage media, they cannot decrypt encrypted data.
Exceptions should not be ignored
Exceptions should not be ignored
When exceptions occur, it is usually a bad idea to simply ignore them. Instead, it is better to handle them properly, or at least to log them.
Expanding archive files without controlling resource consumption is security-sensitive
Expanding archive files without controlling resource consumption is security-sensitive
Successful Zip Bomb attacks occur when an application expands untrusted archive files without controlling the size of the expanded data, which can lead to denial of service. A Zip bomb is usually a malicious archive file of a few kilobytes of compressed data but turned into gigabytes of uncompressed data. To achieve this extreme compression ratio, attackers will compress irrelevant data (eg: a long string of repeated bytes).
Allowing both safe and unsafe HTTP methods is security-sensitive
Allowing both safe and unsafe HTTP methods is security-sensitive
An HTTP method is safe when used to perform a read-only operation, such as retrieving information. In contrast, an unsafe HTTP method is used to change the state of an application, for instance to update a user’s profile on a web application.
Common safe HTTP methods are GET, HEAD, or OPTIONS.
Common unsafe HTTP methods are POST, PUT and DELETE.
Allowing both safe and unsafe HTTP methods to perform a specific operation on a web application could impact its security, for example CSRF protections are most of the time only protecting operations performed by unsafe HTTP methods.
Policies granting all privileges are security-sensitive
Policies granting all privileges are security-sensitive
A policy that grants all permissions may indicate an improper access control, which violates the principle of least privilege. Suppose an identity is granted full permissions to a resource even though it only requires read permission to work as expected. In this case, an unintentional overwriting of resources may occur and therefore result in loss of information.
Mergeable if statements should be combined
Mergeable if statements should be combined
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.
Functions and methods should not be empty
Functions and methods should not be empty
An empty is generally considered bad practice and can lead to confusion, readability, and maintenance issues. Empty s bring no functionality and are misleading to others as they might think the implementation fulfills a specific and identified requirement.
There are several reasons for a 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.
Disabling versioning of S3 buckets is security-sensitive
Disabling versioning of S3 buckets is security-sensitive
S3 buckets can be in three states related to versioning:
unversioned (default one)
enabled
suspended
When the S3 bucket is unversioned or has versioning suspended it means that a new version of an object overwrites an existing one in the S3 bucket.
It can lead to unintentional or intentional information loss.
Regex lookahead assertions should not be contradictory
Regex lookahead assertions should not be contradictory
Lookahead assertions are a regex feature that makes it possible to look ahead in the input without consuming it. It is often used at the end of regular expressions to make sure that substrings only match when they are followed by a specific pattern.
For example, the following pattern will match an “a” only if it is directly followed by a “b”. This does not consume the “b” in the process:
Unresolved directive in <stdin> - include::[]
However, lookaheads can also be used in the middle (or at the beginning) of a regex. In that case there is the possibility that what comes after the lookahead contradicts the pattern inside the lookahead. Since the lookahead does not consume input, this makes the lookahead impossible to match and is a sign that there’s a mistake in the regular expression that should be fixed.
Using clear-text protocols is security-sensitive
Using clear-text protocols is security-sensitive
Clear-text protocols such as `ftp, telnet, or http lack encryption of transported data, as well as the capability to build an authenticated connection. It means that an attacker able to sniff traffic from the network can read, modify, or corrupt the transported content. These protocols are not secure as they expose applications to an extensive range of risks:
sensitive data exposure
traffic redirected to a malicious endpoint
malware-infected software update or installer
execution of client-side code
corruption of critical information
Even in the context of isolated networks like offline environments or segmented cloud environments, the insider threat exists. Thus, attacks involving communications being sniffed or tampered with can still happen.
For example, attackers could successfully compromise prior security layers by:
bypassing isolation mechanisms
compromising a component of the network
getting the credentials of an internal IAM account (either from a service account or an actual person)
In such cases, encrypting communications would decrease the chances of attackers to successfully leak data or steal credentials from other network components. By layering various security practices (segmentation and encryption, for example), the application will follow the defense-in-depth principle.
Note that using the http` protocol is being deprecated by major web browsers.
In the past, it has led to the following vulnerabilities:
Track lack of copyright and license headers
Track lack of copyright and license headers
Each source file should start with a header stating file ownership and the license which must be used to distribute the application.
This rule must be fed with the header text that is expected at the beginning of every file.
Reluctant quantifiers in regular expressions should be followed by an expression that cant match the empty string
Reluctant quantifiers in regular expressions should be followed by an expression that cant match the empty string
When a reluctant (or lazy) quantifier is followed by a pattern that can match the empty string or directly by the end of the regex, it will always match zero times for *? or one time for +?. If a reluctant quantifier is followed directly by the end anchor ($), it behaves indistinguishably from a greedy quantifier while being less efficient.
This is likely a sign that the regex does not work as intended.
Regular expression quantifiers and character classes should be used concisely
Regular expression quantifiers and character classes should be used concisely
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] or \d. 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_]
. for character classes matching everything (e.g. [\w\W], [\d\D], or [\s\S] with s flag)
x? for x0,1, x* for x0, x+ for x1, xN for xN,N
Disabling server-side encryption of S3 buckets is security-sensitive
Disabling server-side encryption of S3 buckets is security-sensitive
Server-side encryption (SSE) encrypts an object (not the metadata) as it is written to disk (where the S3 bucket resides) and decrypts it as it is read from disk. This doesn’t change the way the objects are accessed, as long as the user has the necessary permissions, objects are retrieved as if they were unencrypted. Thus, SSE only helps in the event of disk thefts, improper disposals of disks and other attacks on the AWS infrastructure itself.
There are three SSE options:
Server-Side Encryption with Amazon S3-Managed Keys (SSE-S3)
AWS manages encryption keys and the encryption itself (with AES-256) on its own.
Server-Side Encryption with Customer Master Keys (CMKs) Stored in AWS Key Management Service (SSE-KMS)
AWS manages the encryption (AES-256) of objects and encryption keys provided by the AWS KMS service.
Server-Side Encryption with Customer-Provided Keys (SSE-C)
AWS manages only the encryption (AES-256) of objects with encryption keys provided by the customer. AWS doesn’t store the customer’s encryption keys.
Using shell interpreter when executing OS commands is security-sensitive
Using shell interpreter when executing OS commands is security-sensitive
Arbitrary OS command injection vulnerabilities are more likely when a shell is spawned rather than a new process, indeed shell meta-chars can be used (when parameters are user-controlled for instance) to inject OS commands.
Using unencrypted SNS topics is security-sensitive
Using unencrypted SNS topics is security-sensitive
Amazon Simple Notification Service (SNS) is a managed messaging service for application-to-application (A2A) and application-to-person (A2P) communication. SNS topics allows publisher systems to fanout messages to a large number of subscriber systems. Amazon SNS allows to encrypt messages when they are received. In the case that adversaries gain physical access to the storage medium or otherwise leak a message they are not able to access the data.
Regex boundaries should not be used in a way that can never be matched
Regex boundaries should not be used in a way that can never be matched
In regular expressions the boundaries `^ and A can only match at the beginning of the input (or, in case of ^ in combination with the MULTILINE flag, the beginning of the line) and $, \Z and \z only at the end.
These patterns can be misused, by accidentally switching ^ and $` for example, to create a pattern that can never match.
Alternatives in regular expressions should be grouped when used with anchors
Alternatives in regular expressions should be grouped when used with anchors
In regular expressions, anchors (^, , alt1 would be anchored to the beginning, alt3 to the end and alt2 wouldn’t be anchored at all. Usually the intended behavior is that all alternatives are anchored at both ends. To achieve this, a non-capturing group should be used around the alternatives.
In cases where it is intended that the anchors only apply to one alternative each, adding (non-capturing) groups around the anchors and the parts that they apply to will make it explicit which parts are anchored and avoid readers misunderstanding the precedence or changing it because they mistakenly assume the precedence was not intended.
Formatting SQL queries is security-sensitive
Formatting SQL queries is security-sensitive
Formatted SQL queries can be difficult to maintain, debug and can increase the risk of SQL injection when concatenating untrusted values into the query. However, this rule doesn’t detect SQL injections (unlike rule S3649), the goal is only to highlight complex/formatted queries.
Unused function parameters should be removed
Unused function parameters should be removed
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.
Unicode Grapheme Clusters should be avoided inside regex character classes
Unicode Grapheme Clusters should be avoided inside regex character classes
When placing Unicode Grapheme Clusters (characters which require to be encoded in multiple Code Points) inside a character class of a regular expression, this will likely lead to unintended behavior.
For instance, the grapheme cluster c̈ requires two code points: one for ‘c’, followed by one for the umlaut modifier . If placed within a character class, such as [c̈], the regex will consider the character class being the enumeration instead. It will, therefore, match every ‘c’ and every umlaut that isn’t expressed as a single codepoint, which is extremely unlikely to be the intended behavior.
This rule raises an issue every time Unicode Grapheme Clusters are used within a character class of a regular expression.
Class names should comply with a naming convention
Class names should comply with a naming convention
Shared naming conventions allow teams to collaborate efficiently.
This rule raises an issue when a class name does not match a provided regular expression.
Repeated patterns in regular expressions should not match the empty string
Repeated patterns in regular expressions should not match the empty string
A regex should never include a repetitive pattern whose body would match the empty string. This is usually a sign that a part of the regex is redundant or does not do what the author intended.
Constructing arguments of system commands from user input is security-sensitive
Constructing arguments of system commands from user input is security-sensitive
Constructing arguments of system commands from user input is security-sensitive. It has led in the past to the following vulnerabilities:
Arguments of system commands are processed by the executed program. The arguments are usually used to configure and influence the behavior of the programs. Control over a single argument might be enough for an attacker to trigger dangerous features like executing arbitrary commands or writing files into specific directories.
Signaling processes is security-sensitive
Signaling processes is security-sensitive
Signaling processes or process groups can seriously affect the stability of this application or other applications on the same system.
Accidentally setting an incorrect PID or signal or allowing untrusted sources to assign arbitrary values to these parameters may result in a denial of service.
Also, the system treats the signal differently if the destination PID is less than or equal to 0. This different behavior may affect multiple processes with the same (E)UID simultaneously if the call is left uncontrolled.
Variables should not be self-assigned
Variables should not be self-assigned
There is no reason to re-assign a variable to itself. Either this statement is redundant and should be removed, or the re-assignment is a mistake and some other value or variable was intended for the assignment instead.
Disabling auto-escaping in template engines is security-sensitive
Disabling auto-escaping in template engines is security-sensitive
To reduce the risk of cross-site scripting attacks, templating systems, such as `Twig, Django, Smarty, Groovy’s template engine, allow configuration of automatic variable escaping before rendering templates. When escape occurs, characters that make sense to the browser (eg: <a>) will be transformed/replaced with escaped/sanitized values (eg: & lt;a& gt; ).
Auto-escaping is not a magic feature to annihilate all cross-site scripting attacks, it depends on the strategy applied and the context, for example a “html auto-escaping” strategy (which only transforms html characters into html entities) will not be relevant when variables are used in a html attribute because ’:’ character is not escaped and thus an attack as below is possible:
<a href="{{ myLink }}">link</a> // myLink = javascript:alert(document.cookie) <a href="javascript:alert(document.cookie)">link</a> // JS injection (XSS attack)Regular expressions should not contain multiple spaces
Regular expressions should not contain multiple spaces
Multiple spaces in a regular expression can make it hard to tell how many spaces should be matched. It’s more readable to use only one space and then indicate with a quantifier how many spaces are expected.
HTTP response headers should not be vulnerable to injection attacks
HTTP response headers should not be vulnerable to injection attacks
User-provided data, such as URL parameters, POST data payloads, or cookies, should always be considered untrusted and tainted. Applications constructing HTTP response headers based on tainted data could allow attackers to change security sensitive headers like Cross-Origin Resource Sharing headers.
Web application frameworks and servers might also allow attackers to inject new line characters in headers to craft malformed HTTP response. In this case the application would be vulnerable to a larger range of attacks like HTTP Response Splitting/Smuggling. Most of the time this type of attack is mitigated by default modern web application frameworks but there might be rare cases where older versions are still vulnerable.
As a best practice, applications that use user-provided data to construct the response header should always validate the data first. Validation should be based on a whitelist.
Using unencrypted EBS volumes is security-sensitive
Using unencrypted EBS volumes is security-sensitive
Amazon Elastic Block Store (EBS) is a block-storage service for Amazon Elastic Compute Cloud (EC2). EBS volumes can be encrypted, ensuring the security of both data-at-rest and data-in-transit between an instance and its attached EBS storage. In the case that adversaries gain physical access to the storage medium they are not able to access the data. Encryption can be enabled for specific volumes or for all new volumes and snapshots. Volumes created from snapshots inherit their encryption configuration. A volume created from an encrypted snapshot will also be encrypted by default.
Using unencrypted EFS file systems is security-sensitive
Using unencrypted EFS file systems is security-sensitive
Amazon Elastic File System (EFS) is a serverless file system that does not require provisioning or managing storage. Stored files can be automatically encrypted by the service. In the case that adversaries gain physical access to the storage medium or otherwise leak a message they are not able to access the data.
Functions should not contain too many return statements
Functions should not contain too many return statements
Having too many return statements in a function increases the function’s essential complexity because the flow of execution is broken each time a return statement is encountered. This makes it harder to read and understand the logic of the function.
Non-empty statements should change control flow or have at least one side-effect
Non-empty statements should change control flow or have at least one side-effect
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:
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.
The statements are residual after a refactoring.
Creating public APIs is security-sensitive
Creating public APIs is security-sensitive
Creating APIs without authentication unnecessarily increases the attack surface on the target infrastructure.
Unless another authentication method is used, attackers have the opportunity to attempt attacks against the underlying API. This means attacks both on the functionality provided by the API and its infrastructure.
HTTP response headers should not be vulnerable to response splitting attacks
HTTP response headers should not be vulnerable to response splitting attacks
Without proper validation or sanitation, an attacker with control over a header’s content could insert line return characters in it and inject arbitrary content in the HTTP response. This includes headers, their content, and the response body.
String literals should not be duplicated
String literals should not be duplicated
Duplicated string literals make the process of refactoring complex and error-prone, as any change would need to be propagated on all occurrences.
Neither DES (Data Encryption Standard) nor DESede (3DES) should be used
Neither DES (Data Encryption Standard) nor DESede (3DES) should be used
According to the US National Institute of Standards and Technology (NIST), the Data Encryption Standard (DES) is no longer considered secure:
For similar reasons, RC2 should also be avoided.
Granting access to S3 buckets to all or authenticated users is security-sensitive
Granting access to S3 buckets to all or authenticated users is security-sensitive
Predefined permissions, also known as canned ACLs, are an easy way to grant large privileges to predefined groups or users.
The following canned ACLs are security-sensitive:
`PublicRead, PublicReadWrite grant respectively “read” and “read and write” privileges to everyone in the world (AllUsers group).
AuthenticatedRead grants “read” privilege to all authenticated users (AuthenticatedUsers` group).
SHA-1 and Message-Digest hash algorithms should not be used in secure contexts
SHA-1 and Message-Digest hash algorithms should not be used in secure contexts
The MD5 algorithm and its successor, SHA-1, are no longer considered secure, because it is too easy to create hash collisions with them. That is, it takes too little computational effort to come up with a different input that produces the same MD5 or SHA-1 hash, and using the new, same-hash value gives an attacker the same access as if he had the originally-hashed value. This applies as well to the other Message-Digest algorithms: MD2, MD4, MD6, HAVAL-128, HMAC-MD5, DSA (which uses SHA-1), RIPEMD, RIPEMD-128, RIPEMD-160, HMACRIPEMD160.
Consider using safer alternatives, such as SHA-256, SHA-512 or SHA-3.
A field should not duplicate the name of its containing class
A field should not duplicate the name of its containing class
It’s confusing to have a class member with the same name (case differences aside) as its enclosing class. This is particularly so when you consider the common practice of naming a class instance for the class itself.
Best practice dictates that any field or member with the same name as the enclosing class be renamed to be more descriptive of the particular aspect of the class it represents or holds.
Comments should not be located at the end of lines of code
Comments should not be located at the end of lines of code
Function names should comply with a naming convention
Function names should comply with a naming convention
Shared coding conventions allow teams to collaborate efficiently. This rule checks that all function names match a provided regular expression.
Functions and methods should not have identical implementations
Functions and methods should not have identical implementations
Two s having the same implementation are suspicious. It might be that something else was intended. Or the duplication is intentional, which becomes a maintenance burden.
Using hardcoded IP addresses is security-sensitive
Using hardcoded IP addresses is security-sensitive
Hardcoding IP addresses is security-sensitive. It has led in the past to the following vulnerabilities:
Today’s services have an ever-changing architecture due to their scaling and redundancy needs. It is a mistake to think that a service will always have the same IP address. When it does change, the hardcoded IP will have to be modified too. This will have an impact on the product development, delivery, and deployment:
The developers will have to do a rapid fix every time this happens, instead of having an operation team change a configuration file.
It misleads to use the same address in every environment (dev, sys, qa, prod).
Last but not least it has an effect on application security. Attackers might be able to decompile the code and thereby discover a potentially sensitive address. They can perform a Denial of Service attack on the service, try to get access to the system, or try to spoof the IP address to bypass security checks. Such attacks can always be possible, but in the case of a hardcoded IP address solving the issue will take more time, which will increase an attack’s impact.
Policies granting access to all resources of an account are security-sensitive
Policies granting access to all resources of an account are security-sensitive
A policy that allows identities to access all resources in an AWS account may violate the principle of least privilege. Suppose an identity has permission to access all resources even though it only requires access to some non-sensitive ones. In this case, unauthorized access and disclosure of sensitive information will occur.
Character classes in regular expressions should not contain the same character twice
Character classes in regular expressions should not contain the same character twice
Character classes in regular expressions are a convenient way to match one of several possible characters by listing the allowed characters or ranges of characters. If the same character is listed twice in the same character class or if the character class contains overlapping ranges, this has no effect.
Thus duplicate characters in a character class are either a simple oversight or a sign that a range in the character class matches more than is intended or that the author misunderstood how character classes work and wanted to match more than one character. A common example of the latter mistake is trying to use a range like [0-99] to match numbers of up to two digits, when in fact it is equivalent to [0-9]. Another common cause is forgetting to escape the - character, creating an unintended range that overlaps with other characters in the character class.
Regex alternatives should not be redundant
Regex alternatives should not be redundant
If an alternative in a regular expression only matches things that are already matched by another alternative, that alternative is redundant and serves no purpose.
In the best case this means that the offending subpattern is merely redundant and should be removed. In the worst case it’s a sign that this regex does not match what it was intended to match and should be reworked.
Field names should comply with a naming convention
Field names should comply with a naming convention
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.
Setting loose POSIX file permissions is security-sensitive
Setting loose POSIX file permissions is security-sensitive
In Unix file system permissions, the “others” category refers to all
users except the owner of the file system resource and the members of the group
assigned to this resource.
Granting permissions to this category can lead to unintended access to files or directories that could allow attackers to obtain sensitive information, disrupt services or elevate privileges.
Using weak hashing algorithms is security-sensitive
Using weak hashing algorithms is security-sensitive
Cryptographic hash algorithms such as MD2, MD4, MD5, MD6, HAVAL-128, HMAC-MD5, DSA (which uses SHA-1), RIPEMD, RIPEMD-128, RIPEMD-160, HMACRIPEMD160 and SHA-1 are no longer considered secure, because it is possible to have collisions (little computational effort is enough to find two or more different inputs that produce the same hash).
Regex patterns following a possessive quantifier should not always fail
Regex patterns following a possessive quantifier should not always fail
Possessive quantifiers in Regex patterns like below improve performance by eliminating needless backtracking:
?+ , *+ , ++ , n+ , n,+ , n,m+
But because possessive quantifiers do not keep backtracking positions and never give back, the following sub-patterns should not match only similar characters. Otherwise, possessive quantifiers consume all characters that could have matched the following sub-patterns and nothing remains for the following sub-patterns.
Using unencrypted SQS queues is security-sensitive
Using unencrypted SQS queues is security-sensitive
Amazon Simple Queue Service (SQS) is a managed message queuing service for application-to-application (A2A) communication. Amazon SQS can store messages encrypted as soon as they are received. In the case that adversaries gain physical access to the storage medium or otherwise leak a message from the file system, for example through a vulnerability in the service, they are not able to access the data.
Allowing public ACLs or policies on a S3 bucket is security-sensitive
Allowing public ACLs or policies on a S3 bucket is security-sensitive
By default S3 buckets are private, it means that only the bucket owner can access it.
This access control can be relaxed with ACLs or policies.
To prevent permissive policies to be set on a S3 bucket the following settings can be configured:
`BlockPublicAcls: to block or not public ACLs to be set to the S3 bucket.
IgnorePublicAcls: to consider or not existing public ACLs set to the S3 bucket.
BlockPublicPolicy: to block or not public policies to be set to the S3 bucket.
RestrictPublicBuckets: to restrict or not the access to the S3 endpoints of public policies to the principals within the bucket owner account.
Regular expressions should not contain empty groups
Regular expressions should not contain empty groups
There are several reasons to use a group in a regular expression:
to change the precedence (e.g. do(g|or) will match ‘dog’ and ‘door’)
to remember parenthesised part of the match in the case of capturing group
to improve readability
In any case, having an empty group is most probably a mistake. Either it is a leftover after refactoring and should be removed, or the actual parentheses were intended and were not escaped.
Hard-coded credentials are security-sensitive
Hard-coded credentials are security-sensitive
Because it is easy to extract strings from an application source code or binary, credentials should not be hard-coded. This is particularly true for applications that are distributed or that are open-source.
In the past, it has led to the following vulnerabilities:
Credentials should be stored outside of the code in a configuration file, a database, or a management service for secrets.
This rule flags instances of hard-coded credentials used in database and LDAP connections. It looks for hard-coded credentials in connection strings, and for variable names that match any of the patterns from the provided list.
It’s recommended to customize the configuration of this rule with additional credential words such as “oauthToken”, “secret”, …
Track TODO and FIXME comments that do not contain a reference to a person
Track TODO and FIXME comments that do not contain a reference to a person
TODO and FIXME comments are typically intended to be short-lived; they are placeholders and reminders that programmers leave for themselves. Unfortunately, even with the best of intentions, those comments are not always acted on and removed in a timely manner. Thus, they can become mysterious, lingering cruft in a code base, reducing both readability and understand-ability.
This rule flags all FIXME and TODO comments that do not have an attribution matching the specified regular expression immediately after the FIXME or TODO. Ideally, such comments will also contain information about what needs to be fixed or done, but this rule does not enforce that.
Administration services access should be restricted to specific IP addresses
Administration services access should be restricted to specific IP addresses
Cloud platforms such as AWS, Azure, or GCP support virtual firewalls that can be used to restrict access to services by controlling inbound and outbound traffic. Any firewall rule allowing traffic from all IP addresses to standard network ports on which administration services traditionally listen, such as 22 for SSH, can expose these services to exploits and unauthorized access.
Unused local variables should be removed
Unused local variables should be removed
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.
Loop boundaries should not be vulnerable to injection attacks
Loop boundaries should not be vulnerable to injection attacks
Loop boundary injections occur in an application when the application retrieves data from a user or a third-party service and inserts it into a loop or a function acting as a loop, without sanitizing it first.
If an application contains a loop that is vulnerable to injections, it is exposed to attacks that target its availability where that loop is used.
A user with malicious intent carefully performs actions whose goal is to cause the loop to run for more iterations than the developer intended, resulting in unexpected behavior or even a crash of the program.
After creating the malicious request, the attacker can attack the servers affected by this vulnerability without relying on any prerequisites.
Unused assignments should be removed
Unused assignments should be removed
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.
Cognitive Complexity of functions should not be too high
Cognitive Complexity of functions should not be too high
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.
Boolean expressions should not be gratuitous
Boolean expressions should not be gratuitous
Control flow constructs like if-statements allow the programmer to direct the flow of a program depending on a boolean expression. However, if the condition is always true or always false, only one of the branches will ever be executed. In that case, the control flow construct and the condition no longer serve a purpose; they become gratuitous.
This rule verifies that single-line comments are not located at the ends of lines of code. The main idea behind this rule is that in order to be really readable, trailing comments would have to be properly written and formatted (correct alignment, no interference with the visual structure of the code, not too long to be visible) but most often, automatic code formatters would not handle this correctly: the code would end up less readable. Comments are far better placed on the previous empty line of code, where they will always be visible and properly formatted.