Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 59 additions & 1 deletion src/codemodder/codetf/common.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from abc import ABCMeta
from enum import Enum
from pathlib import Path
from typing import Optional

from pydantic import BaseModel
from pydantic import BaseModel, ConfigDict, model_validator

from codemodder.logging import logger

Expand All @@ -26,3 +27,60 @@ def write_report(self, outfile: Path | str) -> int:
return 2
logger.debug("wrote report to %s", outfile)
return 0


class Rule(BaseModel):
id: str
name: str
url: Optional[str] = None

model_config = ConfigDict(frozen=True)


class Finding(BaseModel):
id: str
rule: Rule

model_config = ConfigDict(frozen=True)


class Action(CaseInsensitiveEnum):
ADD = "add"
REMOVE = "remove"


class PackageResult(CaseInsensitiveEnum):
COMPLETED = "completed"
FAILED = "failed"
SKIPPED = "skipped"


class DiffSide(CaseInsensitiveEnum):
LEFT = "left"
RIGHT = "right"


class PackageAction(BaseModel):
action: Action
result: PackageResult
package: str


class Change(BaseModel):
lineNumber: int
description: Optional[str]
diffSide: DiffSide = DiffSide.RIGHT
properties: Optional[dict] = None
packageActions: Optional[list[PackageAction]] = None

@model_validator(mode="after")
def validate_lineNumber(self):
if self.lineNumber < 1:
raise ValueError("lineNumber must be greater than 0")
return self

@model_validator(mode="after")
def validate_description(self):
if self.description is not None and not self.description:
raise ValueError("description must not be empty")
return self
44 changes: 23 additions & 21 deletions src/codemodder/codetf/v2/codetf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,21 @@
from enum import Enum
from typing import TYPE_CHECKING, Optional

from pydantic import BaseModel, ConfigDict, model_validator
from pydantic import BaseModel, model_validator

from codemodder import __version__

from ..common import CaseInsensitiveEnum, CodeTFWriter
from ..common import (
CaseInsensitiveEnum,
)
from ..common import Change as CommonChange
from ..common import (
CodeTFWriter,
)
from ..common import Finding as CommonFinding
from ..common import (
Rule,
)

if TYPE_CHECKING:
from codemodder.context import CodemodExecutionContext
Expand Down Expand Up @@ -46,10 +56,6 @@ class PackageAction(BaseModel):
class Change(BaseModel):
lineNumber: int
description: Optional[str]
# All of our changes are currently treated as additive, so it makes sense
# for the comments to appear on the RIGHT side of the split diff. Eventually we
# may want to differentiate between LEFT and RIGHT, but for now we'll just
# default to RIGHT.
diffSide: DiffSide = DiffSide.RIGHT
properties: Optional[dict] = None
packageActions: Optional[list[PackageAction]] = None
Expand Down Expand Up @@ -77,6 +83,15 @@ def with_findings(self, findings: list[Finding] | None) -> Change:
fixedFindings=findings,
)

def to_common(self) -> CommonChange:
return CommonChange(
lineNumber=self.lineNumber,
description=self.description,
diffSide=self.diffSide,
properties=self.properties,
packageActions=self.packageActions,
)


class AIMetadata(BaseModel):
provider: Optional[str] = None
Expand Down Expand Up @@ -138,20 +153,7 @@ def validate_description(self):
return self


class Rule(BaseModel):
id: str
name: str
url: Optional[str] = None

model_config = ConfigDict(frozen=True)


class Finding(BaseModel):
id: Optional[str] = None
rule: Rule

model_config = ConfigDict(frozen=True)

class Finding(CommonFinding):
def to_unfixed_finding(
self,
*,
Expand All @@ -170,7 +172,7 @@ def to_unfixed_finding(
def with_rule(self, name: str, url: Optional[str]) -> Finding:
return Finding(
id=self.id,
rule=Rule(id=self.rule.id, name=name, url=url),
rule=Rule(id=self.rule.id, name=name, url=url) if self.rule else None,
)


Expand Down
58 changes: 3 additions & 55 deletions src/codemodder/codetf/v3/codetf.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

from pydantic import BaseModel, model_validator

from ..common import CaseInsensitiveEnum, CodeTFWriter
from ..common import Change, CodeTFWriter, Finding
from ..v2.codetf import Finding as V2Finding


class Run(BaseModel):
Expand Down Expand Up @@ -44,59 +45,6 @@ class FixStatus(BaseModel):
details: Optional[str]


class Rule(BaseModel):
id: str
name: str
url: Optional[str] = None


class Finding(BaseModel):
id: str
rule: Optional[Rule] = None


class Action(CaseInsensitiveEnum):
ADD = "add"
REMOVE = "remove"


class PackageResult(CaseInsensitiveEnum):
COMPLETED = "completed"
FAILED = "failed"
SKIPPED = "skipped"


class DiffSide(CaseInsensitiveEnum):
LEFT = "left"
RIGHT = "right"


class PackageAction(BaseModel):
action: Action
result: PackageResult
package: str


class Change(BaseModel):
lineNumber: int
description: Optional[str]
diffSide: DiffSide = DiffSide.RIGHT
properties: Optional[dict] = None
packageActions: Optional[list[PackageAction]] = None

@model_validator(mode="after")
def validate_lineNumber(self):
if self.lineNumber < 1:
raise ValueError("lineNumber must be greater than 0")
return self

@model_validator(mode="after")
def validate_description(self):
if self.description is not None and not self.description:
raise ValueError("description must not be empty")
return self


class ChangeSet(BaseModel):
path: str
diff: str
Expand Down Expand Up @@ -158,7 +106,7 @@ class FixQuality(BaseModel):
class FixResult(BaseModel):
"""Result corresponding to a single finding"""

finding: Finding
finding: Finding | V2Finding
fixStatus: FixStatus
changeSets: list[ChangeSet]
fixMetadata: Optional[FixMetadata] = None
Expand Down
Loading