Skip to content

Commit

Permalink
If json or sarif are present, only sast codemods are included
Browse files Browse the repository at this point in the history
  • Loading branch information
andrecsilva committed Jan 29, 2024
1 parent 7a9bbfb commit abbfdaa
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 10 deletions.
21 changes: 21 additions & 0 deletions integration_tests/test_program.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import subprocess
from core_codemods.remove_assertion_in_pytest_raises import (
RemoveAssertionInPytestRaises,
)


class TestProgramFails:
Expand All @@ -21,3 +24,21 @@ def test_codemods_include_exclude_conflict(self):
check=False,
)
assert completed_process.returncode == 3

def test_load_sast_only_by_flag(self, tmp_path):
tmp_file_path = tmp_path / "sonar.json"
tmp_file_path.touch()
completed_process = subprocess.run(
[
"codemodder",
"tests/samples/",
"--sonar-issues-json",
f"{tmp_file_path}",
"--dry-run",
],
check=False,
capture_output=True,
text=True,
)
assert completed_process.returncode == 0
assert RemoveAssertionInPytestRaises.id not in completed_process.stdout
4 changes: 3 additions & 1 deletion src/codemodder/codemodder.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,9 @@ def run(original_args) -> int:

# TODO: this should be a method of CodemodExecutionContext
codemods_to_run = codemod_registry.match_codemods(
argv.codemod_include, argv.codemod_exclude
argv.codemod_include,
argv.codemod_exclude,
sast_only=argv.sonar_issues_json or argv.sarif,
)

log_section("setup")
Expand Down
4 changes: 2 additions & 2 deletions src/codemodder/codemods/base_codemod.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,10 @@ def docs_module(self) -> Traversable:

@cached_property
def description(self) -> str:
if not self._metadata.description:
if self._metadata.description == None:
doc_path = self.docs_module / f"{self.origin}_python_{self.name}.md"
return doc_path.read_text()
return self._metadata.description
return self._metadata.description # type: ignore

@property
def review_guidance(self):
Expand Down
1 change: 0 additions & 1 deletion src/codemodder/codemods/base_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ def node_is_selected(self, node) -> bool:
return False

pos_to_match = self.node_position(node)
print(pos_to_match)
return self.filter_by_result(
pos_to_match
) and self.filter_by_path_includes_or_excludes(pos_to_match)
Expand Down
12 changes: 11 additions & 1 deletion src/codemodder/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,24 @@ def match_codemods(
self,
codemod_include: Optional[list] = None,
codemod_exclude: Optional[list] = None,
sast_only=False,
) -> list[BaseCodemod]:
codemod_include = codemod_include or []
codemod_exclude = codemod_exclude or DEFAULT_EXCLUDED_CODEMODS

if sast_only:
base_list = [
codemod for codemod in self.codemods if codemod.origin != "pixee"
]
else:
base_list = [
codemod for codemod in self.codemods if codemod.origin == "pixee"
]

if codemod_exclude and not codemod_include:
return [
codemod
for codemod in self.codemods
for codemod in base_list
if codemod.name not in codemod_exclude
and codemod.id not in codemod_exclude
]
Expand Down
30 changes: 26 additions & 4 deletions tests/codemods/test_include_exclude.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pytest
from codemodder.registry import DEFAULT_EXCLUDED_CODEMODS, load_registered_codemods
from core_codemods import registry


class TestMatchCodemods:
Expand All @@ -9,12 +10,31 @@ def setup_class(cls):
cls.codemod_map = (
cls.registry._codemods_by_name # pylint: disable=protected-access
)
cls.default_ids = [
c().id if isinstance(c, type) else c.id for c in registry.codemods
]

def test_no_include_exclude(self):
defaults = set(
x for x in self.registry.codemods if x.id not in DEFAULT_EXCLUDED_CODEMODS
default_codemods = set(
x
for x in self.registry.codemods
if x.id in self.default_ids and x.id not in DEFAULT_EXCLUDED_CODEMODS
)
assert set(self.registry.match_codemods(None, None)) == default_codemods

def test_load_sast_codemods(self):
sast_codemods = set(
c for c in self.registry.codemods if c.id not in self.default_ids
)
assert set(self.registry.match_codemods(None, None)) == defaults
assert (
set(self.registry.match_codemods(None, None, sast_only=True))
== sast_codemods
)

def test_include_non_sast_in_sast(self):
assert set(
self.registry.match_codemods(["secure-random"], None, sast_only=True)
) == {self.codemod_map["secure-random"]}

@pytest.mark.parametrize(
"input_str", ["secure-random", "secure-random,url-sandbox"]
Expand Down Expand Up @@ -44,5 +64,7 @@ def test_include_preserve_order(self, input_str):
def test_exclude(self, input_str):
excludes = input_str.split(",")
assert self.registry.match_codemods(None, excludes) == [
v for (k, v) in self.codemod_map.items() if k not in excludes
c
for c in self.registry.codemods
if c.name not in excludes and c.id in self.default_ids
]
3 changes: 2 additions & 1 deletion tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from codemodder.cli import parse_args
from codemodder import __version__
from codemodder.registry import DEFAULT_EXCLUDED_CODEMODS, load_registered_codemods
from core_codemods import registry as core_registry


class TestParseArgs:
Expand Down Expand Up @@ -102,7 +103,7 @@ def test_describe_prints_codemod_metadata(self, mock_print):
assert mock_print.call_count == 1

results = json.loads(mock_print.call_args_list[0][0][0])
assert len(results["results"]) == len(self.registry.codemods) - len(
assert len(results["results"]) == len(core_registry.codemods) - len(
DEFAULT_EXCLUDED_CODEMODS
)

Expand Down

0 comments on commit abbfdaa

Please sign in to comment.