Skip to content

Commit 95372ec

Browse files
committed
Add from_dict for plain-scan, remove old nested_checks
1 parent 9cc7ac1 commit 95372ec

File tree

3 files changed

+73
-16
lines changed

3 files changed

+73
-16
lines changed

plain-scan/plain/scan/metadata.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@ class CookieMetadata:
2121
samesite: str | None
2222
expires: int | None = None
2323

24+
@classmethod
25+
def from_dict(cls, data: dict) -> CookieMetadata:
26+
"""Reconstruct CookieMetadata from dictionary."""
27+
return cls(
28+
name=data["name"],
29+
value=data["value"],
30+
domain=data["domain"],
31+
path=data["path"],
32+
secure=data["secure"],
33+
httponly=data["httponly"],
34+
samesite=data["samesite"],
35+
expires=data.get("expires"),
36+
)
37+
2438
def to_dict(self) -> dict:
2539
"""Convert to dictionary for JSON serialization."""
2640
result = {
@@ -82,6 +96,17 @@ def from_response(cls, response: requests.Response) -> ResponseMetadata:
8296
cookies=cookies,
8397
)
8498

99+
@classmethod
100+
def from_dict(cls, data: dict) -> ResponseMetadata:
101+
"""Reconstruct ResponseMetadata from dictionary."""
102+
cookies = [CookieMetadata.from_dict(c) for c in data.get("cookies", [])]
103+
return cls(
104+
url=data["url"],
105+
status_code=data["status_code"],
106+
headers=data["headers"],
107+
cookies=cookies,
108+
)
109+
85110
def to_dict(self) -> dict:
86111
"""Convert to dictionary for JSON serialization."""
87112
result = {
@@ -122,6 +147,15 @@ def from_response(cls, response: requests.Response | None) -> ScanMetadata:
122147

123148
return cls(timestamp=timestamp, responses=responses)
124149

150+
@classmethod
151+
def from_dict(cls, data: dict) -> ScanMetadata:
152+
"""Reconstruct ScanMetadata from dictionary."""
153+
responses = [ResponseMetadata.from_dict(r) for r in data.get("responses", [])]
154+
return cls(
155+
timestamp=data["timestamp"],
156+
responses=responses,
157+
)
158+
125159
def to_dict(self) -> dict:
126160
"""Convert to dictionary for JSON serialization."""
127161
return {

plain-scan/plain/scan/output.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,7 @@ def format_check_result(check: CheckResult, indent: int = 0) -> list[str]:
2121
+ ": "
2222
+ click.style(check.message, dim=True)
2323
)
24-
lines = [line]
25-
26-
# Add nested checks
27-
for nested_check in check.nested_checks:
28-
lines.extend(format_check_result(nested_check, indent + 1))
29-
30-
return lines
24+
return [line]
3125

3226

3327
def format_verbose_metadata(metadata: ScanMetadata | None) -> str:
@@ -282,10 +276,6 @@ def to_markdown(scan_result: ScanResult, verbose: bool = False) -> str:
282276
for check in audit.checks:
283277
check_icon = "✓" if check.passed else "✗"
284278
lines.append(f"- {check_icon} **{check.name}:** {check.message}")
285-
286-
for nested in check.nested_checks:
287-
nested_icon = "✓" if nested.passed else "✗"
288-
lines.append(f" - {nested_icon} {nested.message}")
289279
else:
290280
# Security feature not detected - check if user disabled or just not found
291281
if audit.disabled:

plain-scan/plain/scan/results.py

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,23 @@ class CheckResult:
1414
name: str
1515
passed: bool
1616
message: str
17-
nested_checks: list[CheckResult] = field(default_factory=list)
17+
18+
@classmethod
19+
def from_dict(cls, data: dict) -> CheckResult:
20+
"""Reconstruct CheckResult from dictionary."""
21+
return cls(
22+
name=data["name"],
23+
passed=data["passed"],
24+
message=data["message"],
25+
)
1826

1927
def to_dict(self) -> dict:
2028
"""Convert to dictionary for JSON serialization."""
21-
result = {
29+
return {
2230
"name": self.name,
2331
"passed": self.passed,
2432
"message": self.message,
2533
}
26-
if self.nested_checks:
27-
result["nested_checks"] = [check.to_dict() for check in self.nested_checks]
28-
return result
2934

3035

3136
@dataclass
@@ -50,6 +55,19 @@ def passed(self) -> bool:
5055
return not self.required
5156
return all(check.passed for check in self.checks)
5257

58+
@classmethod
59+
def from_dict(cls, data: dict) -> AuditResult:
60+
"""Reconstruct AuditResult from dictionary."""
61+
checks = [CheckResult.from_dict(c) for c in data.get("checks", [])]
62+
return cls(
63+
name=data["name"],
64+
detected=data["detected"],
65+
checks=checks,
66+
required=data.get("required", True),
67+
disabled=data.get("disabled", False),
68+
description=data.get("description"),
69+
)
70+
5371
def to_dict(self) -> dict:
5472
"""Convert to dictionary for JSON serialization."""
5573
result = {
@@ -98,6 +116,21 @@ def total_count(self) -> int:
98116
"""Total count of audits (excluding disabled audits)."""
99117
return sum(1 for audit in self.audits if not audit.disabled)
100118

119+
@classmethod
120+
def from_dict(cls, data: dict) -> ScanResult:
121+
"""Reconstruct ScanResult from dictionary."""
122+
from .metadata import ScanMetadata
123+
124+
audits = [AuditResult.from_dict(a) for a in data.get("audits", [])]
125+
metadata = None
126+
if "metadata" in data:
127+
metadata = ScanMetadata.from_dict(data["metadata"])
128+
return cls(
129+
url=data["url"],
130+
audits=audits,
131+
metadata=metadata,
132+
)
133+
101134
def to_dict(self) -> dict:
102135
"""Convert to dictionary for JSON serialization."""
103136
result = {

0 commit comments

Comments
 (0)