diff --git a/integration_tests/base_test.py b/integration_tests/base_test.py index 2bfd5356..e463c135 100644 --- a/integration_tests/base_test.py +++ b/integration_tests/base_test.py @@ -47,7 +47,7 @@ def check_dependencies_after(self): class BaseIntegrationTest(DependencyTestMixin, CleanRepoMixin): codemod = NotImplementedError - code_path = NotImplementedError + code_path: str = NotImplementedError original_code = NotImplementedError expected_new_code = NotImplementedError output_path = "test-codetf.txt" @@ -77,13 +77,14 @@ def setup_method(self): ) from exc def _assert_run_fields(self, run, output_path): + code_path = os.path.relpath(self.code_path, SAMPLES_DIR) assert run["vendor"] == "pixee" assert run["tool"] == "codemodder-python" assert run["version"] == __version__ assert run["elapsed"] != "" assert ( run["commandLine"] - == f"codemodder {SAMPLES_DIR} --output {output_path} --codemod-include={self.codemod_instance.name} --path-include={self.code_path}" + == f'codemodder {SAMPLES_DIR} --output {output_path} --codemod-include={self.codemod_instance.name} --path-include={code_path} --path-exclude=""' ) assert run["directory"] == os.path.abspath(SAMPLES_DIR) assert run["sarifs"] == [] @@ -149,14 +150,15 @@ def test_file_rewritten(self): Mocks won't work when making a subprocess call so make sure to delete all output files """ - + code_path = os.path.relpath(self.code_path, SAMPLES_DIR) command = [ "codemodder", SAMPLES_DIR, "--output", self.output_path, f"--codemod-include={self.codemod_instance.name}", - f"--path-include={self.code_path}", + f"--path-include={code_path}", + '--path-exclude=""', ] self.check_code_before() diff --git a/integration_tests/test_multiple_codemods.py b/integration_tests/test_multiple_codemods.py index b85de67d..abe249a5 100644 --- a/integration_tests/test_multiple_codemods.py +++ b/integration_tests/test_multiple_codemods.py @@ -28,7 +28,8 @@ def test_two_codemods(self, codemods, tmpdir): str(codetf_path), f"--codemod-include={codemods}", "--path-include", - f"**/{source_file_name}", + f"{source_file_name}", + '--path-exclude=""', ] completed_process = subprocess.run( diff --git a/src/codemodder/code_directory.py b/src/codemodder/code_directory.py index 7e132340..4c01ec89 100644 --- a/src/codemodder/code_directory.py +++ b/src/codemodder/code_directory.py @@ -6,21 +6,23 @@ DEFAULT_INCLUDED_PATHS = ["**.py", "**/*.py"] DEFAULT_EXCLUDED_PATHS = [ - "**/test/**", - "**/tests/**", - "**/conftest.py", - "**/build/**", - "**/dist/**", - "**/venv/**", - "**/.venv/**", - "**/.tox/**", - "**/.nox/**", - "**/.eggs/**", - "**/.git/**", - "**/.mypy_cache/**", - "**/.pytest_cache/**", - "**/.hypothesis/**", - "**/.coverage*", + # TODO: test code should eventually only be excluded on a per-codemod basis + # Some codemods represent fixes that should be applied to test code + "test/**", + "tests/**", + "conftest.py", + "build/**", + "dist/**", + "venv/**", + ".venv/**", + ".tox/**", + ".nox/**", + ".eggs/**", + ".git/**", + ".mypy_cache/**", + ".pytest_cache/**", + ".hypothesis/**", + ".coverage*", ] @@ -64,7 +66,10 @@ def match_files( :return: list of files found within (including recursively) the parent directory that match the criteria of both exclude and include patterns. """ - all_files = [str(path) for path in Path(parent_path).rglob("*")] + all_files = [ + str(Path(path).relative_to(parent_path)) + for path in Path(parent_path).rglob("*") + ] included_files = set( filter_files( all_files, @@ -82,5 +87,5 @@ def match_files( return [ path for p in sorted(list(included_files - excluded_files)) - if (path := Path(p)).is_file() and path.suffix == ".py" + if (path := Path(parent_path).joinpath(p)).is_file() and path.suffix == ".py" ] diff --git a/src/codemodder/codemodder.py b/src/codemodder/codemodder.py index cf9215fc..da471919 100644 --- a/src/codemodder/codemodder.py +++ b/src/codemodder/codemodder.py @@ -154,6 +154,7 @@ def run(original_args) -> int: log_section("startup") logger.info("codemodder: python/%s", __version__) + logger.info("command: %s %s", Path(sys.argv[0]).name, " ".join(original_args)) repo_manager = PythonRepoManager(Path(argv.directory)) context = CodemodExecutionContext( diff --git a/tests/test_code_directory.py b/tests/test_code_directory.py index 17c34b2d..5b7f5f0d 100644 --- a/tests/test_code_directory.py +++ b/tests/test_code_directory.py @@ -42,7 +42,7 @@ def test_all_py_files_match(self, dir_structure): def test_match_excluded(self, dir_structure): expected = ["empty_for_testing.py", "insecure_random.py"] - files = match_files(dir_structure, ["**/tests/**", "*request.py"]) + files = match_files(dir_structure, ["tests/**", "*request.py"]) self._assert_expected(files, expected) def test_match_included_file_with_line(self, dir_structure): @@ -53,7 +53,7 @@ def test_match_included_file_with_line(self, dir_structure): def test_match_excluded_line(self, dir_structure): expected = ["empty_for_testing.py", "insecure_random.py", "make_request.py"] files = match_files( - dir_structure, exclude_paths=["**/tests/**", "**/insecure_random.py:2"] + dir_structure, exclude_paths=["tests/**", "**/insecure_random.py:2"] ) self._assert_expected(files, expected) @@ -65,26 +65,26 @@ def test_match_included_line_and_glob(self, dir_structure): def test_match_excluded_line_and_glob(self, dir_structure): expected = ["empty_for_testing.py", "insecure_random.py", "make_request.py"] files = match_files( - dir_structure, exclude_paths=["**/tests/**", "**/insecure*.py:3"] + dir_structure, exclude_paths=["tests/**", "**/insecure*.py:3"] ) self._assert_expected(files, expected) def test_match_excluded_dir_incorrect_glob(self, dir_structure): incorrect_glob = "more_samples" expected = ["empty_for_testing.py", "insecure_random.py", "make_request.py"] - files = match_files(dir_structure, ["**/tests/**", incorrect_glob]) + files = match_files(dir_structure, ["tests/**", incorrect_glob]) self._assert_expected(files, expected) def test_match_excluded_dir_correct_glob(self, dir_structure): correct_globs = ["**/more_samples/**", "*/more_samples/*"] for correct_glob in correct_globs: expected = ["insecure_random.py", "make_request.py"] - files = match_files(dir_structure, ["**/tests/**", correct_glob]) + files = match_files(dir_structure, ["tests/**", correct_glob]) self._assert_expected(files, expected) def test_match_excluded_multiple(self, dir_structure): expected = ["insecure_random.py"] - files = match_files(dir_structure, ["**/tests/**", "*request.py", "*empty*"]) + files = match_files(dir_structure, ["tests/**", "*request.py", "*empty*"]) self._assert_expected(files, expected) def test_match_included(self, dir_structure): @@ -96,7 +96,7 @@ def test_match_excluded_precedence_over_included(self, dir_structure): expected = ["empty_for_testing.py", "insecure_random.py"] files = match_files( dir_structure, - exclude_paths=["**/tests/**", "*request.py"], + exclude_paths=["tests/**", "*request.py"], include_paths=["*request.py", "*empty*.py", "*random.py"], ) self._assert_expected(files, expected) @@ -104,7 +104,7 @@ def test_match_excluded_precedence_over_included(self, dir_structure): def test_test_directory_not_excluded(self, dir_structure): expected = ["test_insecure_random.py", "test_make_request.py"] files = match_files( - dir_structure, exclude_paths=["**/samples/**", "**/more_samples/**"] + dir_structure, exclude_paths=["samples/**", "**/more_samples/**"] ) self._assert_expected(files, expected) @@ -120,7 +120,7 @@ def test_include_test_overridden_by_default_excludes(self, mocker): "codemodder.code_directory.Path.is_file", return_value=True, ) - files = match_files(Path("."), include_paths=["**/tests/**"]) + files = match_files(Path("."), include_paths=["tests/**"]) self._assert_expected(files, []) def test_include_test_without_default_includes(self, mocker):