From a72983a336d98674290966f384d23b4c4be964b0 Mon Sep 17 00:00:00 2001 From: Daniel D'Avella Date: Mon, 25 Sep 2023 15:35:34 -0400 Subject: [PATCH] Get rid of subclass validation in base API --- src/codemodder/codemods/base_codemod.py | 32 ++---------------- tests/codemods/test_base_codemod.py | 33 ------------------- tests/codemods/test_django_debug_flag_on.py | 8 +++-- .../test_django_session_cookie_secure_off.py | 8 +++-- tests/codemods/test_url_sandbox.py | 8 +++-- 5 files changed, 20 insertions(+), 69 deletions(-) diff --git a/src/codemodder/codemods/base_codemod.py b/src/codemodder/codemods/base_codemod.py index a8f3d5728..c5348c5ad 100644 --- a/src/codemodder/codemods/base_codemod.py +++ b/src/codemodder/codemods/base_codemod.py @@ -1,4 +1,4 @@ -from dataclasses import dataclass, asdict +from dataclasses import dataclass from enum import Enum import itertools from typing import List, ClassVar @@ -30,25 +30,6 @@ class BaseCodemod: execution_context: CodemodExecutionContext file_context: FileContext - def __init_subclass__(cls, **kwargs): - super().__init_subclass__(**kwargs) - - if "codemodder.codemods.base_codemod.SemgrepCodemod" in str(cls): - # hack: SemgrepCodemod won't NotImplementedError but all other child - # classes will. - return - - for attr in ["SUMMARY", "METADATA"]: - if getattr(cls, attr) is NotImplemented: - raise NotImplementedError( - f"You forgot to define {attr} for {cls.__name__}" - ) - for k, v in asdict(cls.METADATA).items(): - if v is NotImplemented: - raise NotImplementedError(f"You forgot to define METADATA.{k}") - if not v: - raise NotImplementedError(f"METADATA.{k} should not be None or empty") - def __init__(self, execution_context: CodemodExecutionContext, file_context): self.execution_context = execution_context self.file_context = file_context @@ -88,18 +69,9 @@ class SemgrepCodemod(BaseCodemod): YAML_FILES: ClassVar[List[str]] = NotImplemented is_semgrep = True - def __init_subclass__(cls, **kwargs): - super().__init_subclass__(**kwargs) - - if cls.YAML_FILES is NotImplemented: - raise NotImplementedError( - "You forgot to define class attribute: YAML_FILES" - ) - - cls.RULE_IDS = rule_ids_from_yaml_files(cls.YAML_FILES) - def __init__(self, *args): super().__init__(*args) + self.RULE_IDS = rule_ids_from_yaml_files(self.YAML_FILES) self._results = list( itertools.chain.from_iterable( map(lambda rId: self.file_context.results_by_id[rId], self.RULE_IDS) diff --git a/tests/codemods/test_base_codemod.py b/tests/codemods/test_base_codemod.py index 571019e99..e277d90ec 100644 --- a/tests/codemods/test_base_codemod.py +++ b/tests/codemods/test_base_codemod.py @@ -2,7 +2,6 @@ from typing import DefaultDict import libcst as cst from libcst.codemod import Codemod, CodemodContext -import pytest import mock from codemodder.codemods.base_codemod import ( SemgrepCodemod, @@ -43,35 +42,3 @@ def run_and_assert(self, input_code, expexted_output): def test_empty_results(self): input_code = """print('Hello World')""" self.run_and_assert(input_code, input_code) - - -class TestSemgrepCodemod: - # pylint: disable=unused-variable - def test_missing_class_attrs(self): - with pytest.raises(NotImplementedError): - - class MissingInfoCodemod(SemgrepCodemod): - ... - - with pytest.raises(NotImplementedError): - - class MissingNameCodemod(SemgrepCodemod): - METADATA = CodemodMetadata( - "Description", None, ReviewGuidance.MERGE_WITHOUT_REVIEW - ) - - with pytest.raises(NotImplementedError): - - class MissingDescriptionCodemod(SemgrepCodemod): - METADATA = CodemodMetadata( - "", "Name", ReviewGuidance.MERGE_WITHOUT_REVIEW - ) - - with pytest.raises(NotImplementedError): - - class MissingAuthorCodemod(SemgrepCodemod): - METADATA = CodemodMetadata( - NotImplemented, - "Name", - ReviewGuidance.MERGE_WITHOUT_REVIEW, - ) diff --git a/tests/codemods/test_django_debug_flag_on.py b/tests/codemods/test_django_debug_flag_on.py index 204265301..4db6ab22d 100644 --- a/tests/codemods/test_django_debug_flag_on.py +++ b/tests/codemods/test_django_debug_flag_on.py @@ -5,8 +5,12 @@ class TestDjangoDebugFlagOn(BaseDjangoCodemodTest): codemod = DjangoDebugFlagOn - def test_rule_ids(self): - assert self.codemod.RULE_IDS == ["django-debug-flag-on"] + def test_rule_ids(self, mocker): + assert self.codemod( + mocker.MagicMock(), + mocker.MagicMock(), + mocker.MagicMock(), + ).RULE_IDS == ["django-debug-flag-on"] def test_settings_dot_py(self, tmpdir): django_root, settings_folder = self.create_dir_structure(tmpdir) diff --git a/tests/codemods/test_django_session_cookie_secure_off.py b/tests/codemods/test_django_session_cookie_secure_off.py index 327f4457a..8e4afac15 100644 --- a/tests/codemods/test_django_session_cookie_secure_off.py +++ b/tests/codemods/test_django_session_cookie_secure_off.py @@ -8,8 +8,12 @@ class TestDjangoSessionSecureCookieOff(BaseDjangoCodemodTest): codemod = DjangoSessionCookieSecureOff - def test_rule_ids(self): - assert self.codemod.RULE_IDS == ["found-settings-file"] + def test_rule_ids(self, mocker): + assert self.codemod( + mocker.MagicMock(), + mocker.MagicMock(), + mocker.MagicMock(), + ).RULE_IDS == ["found-settings-file"] def test_not_settings_dot_py(self, tmpdir): django_root, settings_folder = self.create_dir_structure(tmpdir) diff --git a/tests/codemods/test_url_sandbox.py b/tests/codemods/test_url_sandbox.py index eafb0fab2..379effc9a 100644 --- a/tests/codemods/test_url_sandbox.py +++ b/tests/codemods/test_url_sandbox.py @@ -6,8 +6,12 @@ class TestUrlSandbox(BaseSemgrepCodemodTest): codemod = UrlSandbox - def test_rule_ids(self): - assert self.codemod.RULE_IDS == ["sandbox-url-creation"] + def test_rule_ids(self, mocker): + assert self.codemod( + mocker.MagicMock(), + mocker.MagicMock(), + mocker.MagicMock(), + ).RULE_IDS == ["sandbox-url-creation"] def test_import_requests(self, tmpdir): input_code = """import requests