-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into chore/add-dependabot-triggered-updates
- Loading branch information
Showing
15 changed files
with
449 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
from codemodder.codemods.test import ( | ||
BaseIntegrationTest, | ||
original_and_expected_from_code_path, | ||
) | ||
from core_codemods.fix_missing_self_or_cls import ( | ||
FixMissingSelfOrCls, | ||
FixMissingSelfOrClsTransformer, | ||
) | ||
|
||
|
||
class TestFixMissingSelfOrCls(BaseIntegrationTest): | ||
codemod = FixMissingSelfOrCls | ||
code_path = "tests/samples/fix_missing_self_or_cls.py" | ||
original_code, expected_new_code = original_and_expected_from_code_path( | ||
code_path, | ||
[ | ||
( | ||
1, | ||
""" def instance_method(self):\n""", | ||
), | ||
( | ||
5, | ||
""" def class_method(cls):\n""", | ||
), | ||
], | ||
) | ||
|
||
# fmt: off | ||
expected_diff = ( | ||
"""--- \n""" | ||
"""+++ \n""" | ||
"""@@ -1,7 +1,7 @@\n""" | ||
""" class MyClass:\n""" | ||
"""- def instance_method():\n""" | ||
"""+ def instance_method(self):\n""" | ||
""" print("instance_method")\n""" | ||
""" \n""" | ||
""" @classmethod\n""" | ||
"""- def class_method():\n""" | ||
"""+ def class_method(cls):\n""" | ||
""" print("class_method")\n""" | ||
) | ||
# fmt: on | ||
|
||
expected_line_change = "2" | ||
change_description = FixMissingSelfOrClsTransformer.change_description | ||
num_changes = 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
from codemodder.codemods.test import ( | ||
BaseIntegrationTest, | ||
original_and_expected_from_code_path, | ||
) | ||
from core_codemods.fix_missing_self_or_cls import FixMissingSelfOrClsTransformer | ||
from core_codemods.sonar.sonar_fix_missing_self_or_cls import SonarFixMissingSelfOrCls | ||
|
||
|
||
class TestSonarFixMissingSelfOrCls(BaseIntegrationTest): | ||
codemod = SonarFixMissingSelfOrCls | ||
code_path = "tests/samples/fix_missing_self_or_cls.py" | ||
original_code, expected_new_code = original_and_expected_from_code_path( | ||
code_path, | ||
[ | ||
( | ||
1, | ||
""" def instance_method(self):\n""", | ||
), | ||
( | ||
5, | ||
""" def class_method(cls):\n""", | ||
), | ||
], | ||
) | ||
sonar_issues_json = "tests/samples/sonar_issues.json" | ||
# fmt: off | ||
expected_diff = ( | ||
"""--- \n""" | ||
"""+++ \n""" | ||
"""@@ -1,7 +1,7 @@\n""" | ||
""" class MyClass:\n""" | ||
"""- def instance_method():\n""" | ||
"""+ def instance_method(self):\n""" | ||
""" print("instance_method")\n""" | ||
""" \n""" | ||
""" @classmethod\n""" | ||
"""- def class_method():\n""" | ||
"""+ def class_method(cls):\n""" | ||
""" print("class_method")\n""" | ||
) | ||
# fmt: on | ||
|
||
expected_line_change = "2" | ||
change_description = FixMissingSelfOrClsTransformer.change_description | ||
num_changes = 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
src/core_codemods/docs/pixee_python_fix-missing-self-or-cls.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
Python instance methods must be defined with `self` as the first argument. Likewise, class methods must have `cls` as the first argument. This codemod will add these arguments when the method/class method has no arguments defined. | ||
|
||
Our changes look something like this: | ||
|
||
```diff | ||
class MyClass: | ||
- def instance_method(): | ||
+ def instance_method(self): | ||
print("instance_method") | ||
|
||
@classmethod | ||
- def class_method(): | ||
+ def class_method(cls): | ||
print("class_method") | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import libcst as cst | ||
|
||
from codemodder.codemods.libcst_transformer import ( | ||
LibcstResultTransformer, | ||
LibcstTransformerPipeline, | ||
) | ||
from codemodder.codemods.utils_mixin import NameAndAncestorResolutionMixin | ||
from core_codemods.api import Metadata, ReviewGuidance | ||
from core_codemods.api.core_codemod import CoreCodemod | ||
|
||
|
||
class FixMissingSelfOrClsTransformer( | ||
LibcstResultTransformer, NameAndAncestorResolutionMixin | ||
): | ||
change_description = "Add `self` or `cls` parameter to instance or class method." | ||
|
||
def leave_FunctionDef( | ||
self, original_node: cst.FunctionDef, updated_node: cst.FunctionDef | ||
) -> cst.FunctionDef: | ||
# TODO: add filter by include or exclude that works for nodes | ||
# that that have different start/end numbers. | ||
|
||
if not self.find_immediate_class_def(original_node): | ||
# If `original_node` is not inside a class, nothing to do. | ||
return original_node | ||
|
||
if self.find_immediate_function_def(original_node): | ||
# If `original_node` is inside a class but also nested within a function/method | ||
# We won't touch it. | ||
return original_node | ||
|
||
if original_node.decorators: | ||
if self.is_staticmethod(original_node): | ||
return updated_node | ||
if self.is_classmethod(original_node): | ||
if self.has_no_args(original_node): | ||
self.report_change(original_node) | ||
return updated_node.with_changes( | ||
params=updated_node.params.with_changes( | ||
params=[cst.Param(name=cst.Name("cls"))] | ||
) | ||
) | ||
else: | ||
if self.has_no_args(original_node): | ||
self.report_change(original_node) | ||
return updated_node.with_changes( | ||
params=updated_node.params.with_changes( | ||
params=[cst.Param(name=self._pick_arg_name(original_node))] | ||
) | ||
) | ||
return updated_node | ||
|
||
def _pick_arg_name(self, node: cst.FunctionDef) -> cst.Name: | ||
match node.name: | ||
case cst.Name(value="__new__") | cst.Name(value="__init_subclass__"): | ||
new_name = "cls" | ||
case _: | ||
new_name = "self" | ||
return cst.Name(value=new_name) | ||
|
||
def has_no_args(self, node: cst.FunctionDef) -> bool: | ||
converted_star_arg = ( | ||
None | ||
if node.params.star_arg is cst.MaybeSentinel.DEFAULT | ||
else node.params.star_arg | ||
) | ||
return not any( | ||
( | ||
node.params.params, | ||
converted_star_arg, | ||
node.params.kwonly_params, | ||
node.params.star_kwarg, | ||
node.params.posonly_params, | ||
) | ||
) | ||
|
||
|
||
FixMissingSelfOrCls = CoreCodemod( | ||
metadata=Metadata( | ||
name="fix-missing-self-or-cls", | ||
review_guidance=ReviewGuidance.MERGE_AFTER_CURSORY_REVIEW, | ||
summary="Add Missing Positional Parameter for Instance and Class Methods", | ||
references=[], | ||
), | ||
transformer=LibcstTransformerPipeline(FixMissingSelfOrClsTransformer), | ||
detector=None, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from codemodder.codemods.sonar import SonarCodemod | ||
from core_codemods.fix_missing_self_or_cls import FixMissingSelfOrCls | ||
|
||
SonarFixMissingSelfOrCls = SonarCodemod.from_core_codemod( | ||
name="fix-missing-self-or-cls-S5719", | ||
other=FixMissingSelfOrCls, | ||
rule_id="python:S5719", | ||
rule_name="Instance and class methods should have at least one positional parameter", | ||
rule_url="https://rules.sonarsource.com/python/RSPEC-5719/", | ||
) |
Oops, something went wrong.