Over the past month, we have added 1 new Django checker and the ability to Autofix 9 more issues to our Python analyzer. We have also fixed the false-positives you reported for the analyzer.
Here’s a detailed changelog.
New Issues
PTC-W0910 - Missing reverse_code for backward migration
Migration in Django is a way of applying changes that we have made to a model into the database schema.
Sometimes, you might find yourself in a situation when you have to revert or reverse a migration. This is done with the migrate
command to go back to a previous migration.
At the moment, this issue will only be raised when the migration operations
contains a RunPython
command to do things and is missing the logic to go to a previous migration.
By default, this command is not reversible unless its reverse_code
argument is provided with a function with the logic to reverse the migration.
Sometimes, a migration (e.g., a data migration) may do nothing when you migrate it forward. So, no schema changes are required when you do a reverse migration. In such cases, instead of implementing an empty function, you can also pass a reference to RunPython.noop
, which does nothing.
Example
from django.db import migrations
def update_marks(apps, schema_editor):
# Logic for a forward migration
...
class Migration(migrations.Migration):
dependencies = [("0002_field_with_default_value", "0001_no_issue")]
operations = [
migrations.RunPython(update_marks), # Missing
]
New Autofixes
PTC-W0048 - if
statements can be merged
Merges collapsible if
statements.
Before Autofix:
if x > 0:
if y > 0:
if z > 0:
doSomething()
After Autofix:
if x > 0 and y > 0 and z > 0:
doSomething()
PTC-W0062 - with
statements can be merged
Merges collapsible with
statements.
Before Autofix:
with open("file1", "w") as file1:
with open("file2", "w") as file2:
doSomething()
After Autofix:
with open("file1", "w") as file1, open("file2", "w") as file2:
doSomething()
PYL-E0118 - Name used prior global declaration
Moves global declaration before variable access.
Before Autofix:
var = "Some Value"
def get_result():
var = "New value"
global var
...
After Autofix:
var = "Some Value"
def get_result():
global var
var = "New value"
...
PYL-R1708 - StopIteration detected in a generator
Replaces StopIteration
with return
. See PEP 479 for reference.
Before Autofix:
def some_generator(n):
for i in range(n):
yield i
if i >= 5:
raise StopIteration
After Autofix:
def some_generator(n):
for i in range(n):
yield i
if i >= 5:
return
PYL-W0301 - Unnecessary semicolon
Removes unnecessary semicolons.
Before Autofix:
for x in range(10):
if input[x]:
i = x - 2;
x = i * i;
print(i);
After Autofix:
for x in range(10):
if input[x]:
i = x - 2
x = i * i
print(i)
PYL-W0706 - Except handler raises immediately
Removes unnecessary except handlers.
Before Autofix:
try:
run_transaction(transaction_id)
except ValueError as e:
raise TransactionError(e)
except: # Issue
raise
After Autofix:
try:
run_transaction(transaction_id)
except ValueError as e:
raise TransactionError(e)
PTC-W0910 - Missing backward migration
Adds RunPython.noop
as reverse migration.
Note: This Autofix needs to be verified after the patches are generated. Since this is adding
RunPython.noop
as thereverse_code
at the moment, we recommend you not to use it if the backward migration requires logic for schema changes.
Before Autofix:
from django.db import migrations
def update_marks(apps, schema_editor):
pass
class Migration(migrations.Migration):
dependencies = [("0002_field_with_default_value", "0001_no_issue")]
operations = [
migrations.RunPython(update_marks),
]
After Autofix:
from django.db import migrations
def update_marks(apps, schema_editor):
pass
class Migration(migrations.Migration):
dependencies = [("0002_field_with_default_value", "0001_no_issue")]
operations = [
migrations.RunPython(update_marks, reverse_code=migrations.RunPython.noop),
]
PYL-W0104 - Statement has no effect
Removes the unnecessary statements that have no effect on your code.
Before Autofix:
x = input()
x == 3 # Statement has no effect
calculate_res(x)
After Autofix:
x = input()
calculate_res(x)
PTC-W0047 - Empty block of code found
Removes empty blocks of code that aren’t doing anything.
Before Autofix:
x = 3
for i in range(10):
pass
...
After Autofix:
x = 3
...
False-positive fixes:
- PYL-W0621 is no longer raised for
pytest
fixtures. - PTC-W0063 is not raised when the nested function is accessed using the
locals
method. - PYL-W0108 is no longer flagged for methods from
factoryboy
library. - The checker for PTC-W0048 has been modified to account for walrus operator (
:=
) in the mergeable if conditions. - PYL-W0221 is no longer raised for methods in the
torchmetric
library.