Skip to content

Commit 638264f

Browse files
committed
tested via CLI in github and gitlab, ready to release to prod pypi
1 parent beea17a commit 638264f

File tree

1 file changed

+40
-92
lines changed

1 file changed

+40
-92
lines changed

socketdev/fullscans/__init__.py

Lines changed: 40 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ class FullScanMetadata:
123123
repository_id: str
124124
branch: str
125125
html_report_url: str
126-
repo: Optional[str] = None # In docs, never shows up
127-
organization_slug: Optional[str] = None # In docs, never shows up
126+
repo: Optional[str] = None
127+
organization_slug: Optional[str] = None
128128
committers: Optional[List[str]] = None
129129
commit_message: Optional[str] = None
130130
commit_hash: Optional[str] = None
@@ -189,26 +189,30 @@ def from_dict(cls, data: dict) -> "GetFullScanMetadataResponse":
189189
data=FullScanMetadata.from_dict(data.get("data")) if data.get("data") else None
190190
)
191191

192-
@dataclass
193-
class DependencyRef:
192+
@dataclass(kw_only=True)
193+
class SocketArtifactLink:
194194
topLevelAncestors: List[str]
195-
direct: Optional[bool] = None
196-
manifestFiles: Optional[List[SocketManifestReference]] = None
195+
direct: bool = False
196+
artifact: Optional[Dict] = None
197197
dependencies: Optional[List[str]] = None
198+
manifestFiles: Optional[List[SocketManifestReference]] = None
198199

199200
def __getitem__(self, key): return getattr(self, key)
200201
def to_dict(self): return asdict(self)
201202

202203
@classmethod
203-
def from_dict(cls, data: dict) -> "DependencyRef":
204+
def from_dict(cls, data: dict) -> "SocketArtifactLink":
204205
manifest_files = data.get("manifestFiles")
206+
direct_val = data.get("direct", False)
205207
return cls(
206208
topLevelAncestors=data["topLevelAncestors"],
207-
direct=data.get("direct"),
208-
manifestFiles=[SocketManifestReference.from_dict(m) for m in manifest_files] if manifest_files else None,
209-
dependencies=data.get("dependencies")
209+
direct=direct_val if isinstance(direct_val, bool) else direct_val.lower() == "true",
210+
artifact=data.get("artifact"),
211+
dependencies=data.get("dependencies"),
212+
manifestFiles=[SocketManifestReference.from_dict(m) for m in manifest_files] if manifest_files else None
210213
)
211214

215+
212216
@dataclass
213217
class SocketScore:
214218
supplyChain: float
@@ -360,11 +364,11 @@ def from_dict(cls, data: dict) -> "LicenseAttribution":
360364
)
361365

362366
@dataclass
363-
class DiffArtifactAlert:
367+
class SocketAlert:
364368
key: str
365369
type: str
366-
severity: Optional[SocketIssueSeverity] = None
367-
category: Optional[SocketCategory] = None
370+
severity: SocketIssueSeverity
371+
category: SocketCategory
368372
file: Optional[str] = None
369373
start: Optional[int] = None
370374
end: Optional[int] = None
@@ -376,14 +380,12 @@ def __getitem__(self, key): return getattr(self, key)
376380
def to_dict(self): return asdict(self)
377381

378382
@classmethod
379-
def from_dict(cls, data: dict) -> "DiffArtifactAlert":
380-
severity = data.get("severity")
381-
category = data.get("category")
383+
def from_dict(cls, data: dict) -> "SocketAlert":
382384
return cls(
383385
key=data["key"],
384386
type=data["type"],
385-
severity=SocketIssueSeverity(severity) if severity else None,
386-
category=SocketCategory(category) if category else None,
387+
severity=SocketIssueSeverity(data["severity"]),
388+
category=SocketCategory(data["category"]),
387389
file=data.get("file"),
388390
start=data.get("start"),
389391
end=data.get("end"),
@@ -392,28 +394,29 @@ def from_dict(cls, data: dict) -> "DiffArtifactAlert":
392394
actionPolicyIndex=data.get("actionPolicyIndex")
393395
)
394396

397+
395398
@dataclass
396399
class DiffArtifact:
397400
diffType: DiffType
398401
id: str
399402
type: str
400403
name: str
401-
license: str
402-
scores: SocketScore
404+
score: SocketScore
403405
version: str
404-
alerts: List[DiffArtifactAlert]
406+
alerts: List[SocketAlert]
407+
author: List[str] = field(default_factory=list)
405408
licenseDetails: List[LicenseDetail]
409+
license: Optional[str] = None
406410
files: Optional[str] = None
407411
capabilities: Optional[SecurityCapabilities] = None
408-
base: Optional[List[DependencyRef]] = None
409-
head: Optional[List[DependencyRef]] = None
412+
base: Optional[List[SocketArtifactLink]] = None
413+
head: Optional[List[SocketArtifactLink]] = None
410414
namespace: Optional[str] = None
411415
subpath: Optional[str] = None
412416
artifact_id: Optional[str] = None
413417
artifactId: Optional[str] = None
414418
qualifiers: Optional[Dict[str, Any]] = None
415419
size: Optional[int] = None
416-
author: Optional[str] = None
417420
state: Optional[str] = None
418421
error: Optional[str] = None
419422
licenseAttrib: Optional[List[LicenseAttribution]] = None
@@ -430,22 +433,22 @@ def from_dict(cls, data: dict) -> "DiffArtifact":
430433
id=data["id"],
431434
type=data["type"],
432435
name=data["name"],
433-
license=data.get("license", ""),
434-
scores=SocketScore.from_dict(data["score"]),
436+
score=SocketScore.from_dict(data["score"]),
435437
version=data["version"],
436-
alerts=[DiffArtifactAlert.from_dict(alert) for alert in data["alerts"]],
438+
alerts=[SocketAlert.from_dict(alert) for alert in data["alerts"]],
437439
licenseDetails=[LicenseDetail.from_dict(detail) for detail in data["licenseDetails"]],
438440
files=data.get("files"),
441+
license=data.get("license"),
439442
capabilities=SecurityCapabilities.from_dict(data["capabilities"]) if data.get("capabilities") else None,
440-
base=[DependencyRef.from_dict(b) for b in base_data] if base_data else None,
441-
head=[DependencyRef.from_dict(h) for h in head_data] if head_data else None,
443+
base=[SocketArtifactLink.from_dict(b) for b in base_data] if base_data else None,
444+
head=[SocketArtifactLink.from_dict(h) for h in head_data] if head_data else None,
442445
namespace=data.get("namespace"),
443446
subpath=data.get("subpath"),
444447
artifact_id=data.get("artifact_id"),
445448
artifactId=data.get("artifactId"),
446449
qualifiers=data.get("qualifiers"),
447450
size=data.get("size"),
448-
author=data.get("author"),
451+
author=data.get("author", []),
449452
state=data.get("state"),
450453
error=data.get("error"),
451454
licenseAttrib=[LicenseAttribution.from_dict(attrib) for attrib in data["licenseAttrib"]] if data.get("licenseAttrib") else None
@@ -539,81 +542,26 @@ def from_dict(cls, data: dict) -> "StreamDiffResponse":
539542
data=FullScanDiffReport.from_dict(data.get("data")) if data.get("data") else None
540543
)
541544

542-
@dataclass(kw_only=True)
543-
class SocketArtifactLink:
544-
topLevelAncestors: List[str]
545-
artifact: Optional[Dict] = None
546-
dependencies: Optional[List[str]] = None
547-
direct: Optional[bool] = None
548-
manifestFiles: Optional[List[SocketManifestReference]] = None
549-
550-
def __getitem__(self, key): return getattr(self, key)
551-
def to_dict(self): return asdict(self)
552-
553-
@classmethod
554-
def from_dict(cls, data: dict) -> "SocketArtifactLink":
555-
manifest_files = data.get("manifestFiles")
556-
return cls(
557-
topLevelAncestors=data["topLevelAncestors"],
558-
artifact=data.get("artifact"),
559-
dependencies=data.get("dependencies"),
560-
direct=data.get("direct"),
561-
manifestFiles=[SocketManifestReference.from_dict(m) for m in manifest_files] if manifest_files else None
562-
)
563-
564-
@dataclass
565-
class SocketAlert:
566-
key: str
567-
type: str
568-
severity: SocketIssueSeverity
569-
category: SocketCategory
570-
file: Optional[str] = None
571-
start: Optional[int] = None
572-
end: Optional[int] = None
573-
props: Optional[Dict[str, Any]] = None
574-
action: Optional[str] = None
575-
actionPolicyIndex: Optional[int] = None
576-
577-
def __getitem__(self, key): return getattr(self, key)
578-
def to_dict(self): return asdict(self)
579-
580-
@classmethod
581-
def from_dict(cls, data: dict) -> "SocketAlert":
582-
return cls(
583-
key=data["key"],
584-
type=data["type"],
585-
severity=SocketIssueSeverity(data["severity"]),
586-
category=SocketCategory(data["category"]),
587-
file=data.get("file"),
588-
start=data.get("start"),
589-
end=data.get("end"),
590-
props=data.get("props"),
591-
action=data.get("action"),
592-
actionPolicyIndex=data.get("actionPolicyIndex")
593-
)
594-
595545
@dataclass(kw_only=True)
596546
class SocketArtifact(SocketPURL, SocketArtifactLink):
597547
id: str
598-
alerts: Optional[List[SocketAlert]] = field(default_factory=list)
548+
alerts: List[SocketAlert]
549+
score: SocketScore
599550
author: Optional[List[str]] = field(default_factory=list)
600551
batchIndex: Optional[int] = None
601552
license: Optional[str] = None
602553
licenseAttrib: Optional[List[LicenseAttribution]] = field(default_factory=list)
603554
licenseDetails: Optional[List[LicenseDetail]] = field(default_factory=list)
604-
score: Optional[SocketScore] = None
605-
size: Optional[float] = None
555+
size: Optional[int] = None
606556

607557
def __getitem__(self, key): return getattr(self, key)
608558
def to_dict(self): return asdict(self)
609559

610560
@classmethod
611561
def from_dict(cls, data: dict) -> "SocketArtifact":
612-
# First get the base class data
613562
purl_data = {k: data.get(k) for k in SocketPURL.__dataclass_fields__}
614563
link_data = {k: data.get(k) for k in SocketArtifactLink.__dataclass_fields__}
615564

616-
# Handle nested types
617565
alerts = data.get("alerts")
618566
license_attrib = data.get("licenseAttrib")
619567
license_details = data.get("licenseDetails")
@@ -665,7 +613,7 @@ def create_params_string(self, params: dict) -> str:
665613
for name, value in params.items():
666614
if value:
667615
if name == "committers" and isinstance(value, list):
668-
# Handle committers specially - add multiple params
616+
669617
for committer in value:
670618
param_str += f"&{name}={committer}"
671619
else:
@@ -706,7 +654,7 @@ def post(self, files: list, params: FullScanParams) -> CreateFullScanResponse:
706654
org_slug = str(params.org_slug)
707655
params_dict = params.to_dict()
708656
params_dict.pop("org_slug")
709-
params_arg = self.create_params_string(params_dict) # Convert params to dict
657+
params_arg = self.create_params_string(params_dict)
710658

711659
path = "orgs/" + org_slug + "/full-scans" + str(params_arg)
712660

@@ -779,12 +727,12 @@ def stream(self, org_slug: str, full_scan_id: str) -> FullScanStreamResponse:
779727
item = json.loads(line)
780728
stream_str.append(item)
781729
for val in stream_str:
782-
artifacts[val["id"]] = val # Just store the raw dict
730+
artifacts[val["id"]] = val
783731

784732
return FullScanStreamResponse.from_dict({
785733
"success": True,
786734
"status": 200,
787-
"artifacts": artifacts # Let from_dict handle the conversion
735+
"artifacts": artifacts
788736
})
789737
except Exception as e:
790738
error_message = f"Error parsing stream response: {str(e)}"

0 commit comments

Comments
 (0)