Skip to content

Commit 38c83a8

Browse files
authored
properties removed from DiffArtifact (#19)
* updated to support CLI v2 latest and remove props from DiffArtifact
1 parent a411134 commit 38c83a8

File tree

4 files changed

+102
-97
lines changed

4 files changed

+102
-97
lines changed

scripts/build.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ else
1717
echo "Doing test build of version $VERSION"
1818
python -m build --wheel --sdist \
1919
&& ls dist/*${VERSION}* \
20-
&& twine upload -r testpypi dist/*${VERSION}*
20+
&& twine upload --verbose -r testpypi dist/*${VERSION}*
2121
fi

scripts/deploy-test-pypi.sh

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/bin/sh
2+
3+
# Get version from version.py
4+
VERSION_FILE="socketdev/version.py"
5+
ORIGINAL_VERSION=$(grep -o "__version__.*" $VERSION_FILE | awk '{print $3}' | sed 's/"//g' | sed "s/'//g" | tr -d '\r')
6+
BACKUP_FILE="${VERSION_FILE}.bak"
7+
8+
# Get existing versions from TestPyPI
9+
echo "Checking existing versions on TestPyPI..."
10+
EXISTING_VERSIONS=$(curl -s https://test.pypi.org/pypi/socket-sdk-python/json | python -c "
11+
import sys, json
12+
data = json.load(sys.stdin)
13+
versions = [v for v in data.get('releases', {}).keys() if v.startswith('$ORIGINAL_VERSION.dev')]
14+
if versions:
15+
versions.sort(key=lambda x: int(x.split('dev')[1]))
16+
print(versions[-1])
17+
")
18+
19+
# Determine new version
20+
if [ -z "$EXISTING_VERSIONS" ]; then
21+
VERSION="${ORIGINAL_VERSION}.dev1"
22+
echo "No existing dev versions found. Using ${VERSION}"
23+
else
24+
LAST_DEV_NUM=$(echo $EXISTING_VERSIONS | grep -o 'dev[0-9]*' | grep -o '[0-9]*')
25+
NEXT_DEV_NUM=$((LAST_DEV_NUM + 1))
26+
VERSION="${ORIGINAL_VERSION}.dev${NEXT_DEV_NUM}"
27+
echo "Found existing version ${EXISTING_VERSIONS}. Using ${VERSION}"
28+
fi
29+
30+
echo "Deploying version ${VERSION} to Test PyPI"
31+
32+
# Backup original version.py
33+
cp $VERSION_FILE $BACKUP_FILE
34+
35+
# Update version in version.py
36+
sed -i.tmp "s/__version__ = [\"']${ORIGINAL_VERSION}[\"']/__version__ = '${VERSION}'/" $VERSION_FILE
37+
rm "${VERSION_FILE}.tmp"
38+
39+
# Build and upload to test PyPI (with suppressed output)
40+
python -m build --wheel --sdist > /dev/null 2>&1
41+
42+
# Restore original version.py
43+
mv $BACKUP_FILE $VERSION_FILE
44+
45+
# Upload to TestPyPI
46+
python -m twine upload --verbose --repository testpypi dist/*${VERSION}*
47+
48+
echo "Deployed to Test PyPI. Wait a few minutes before installing the new version."
49+
echo -e "\nNew version deployed:"
50+
echo "${VERSION}"

socketdev/fullscans/__init__.py

+50-95
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,21 +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:
194-
direct: bool
195-
toplevelAncestors: List[str]
192+
@dataclass(kw_only=True)
193+
class SocketArtifactLink:
194+
topLevelAncestors: List[str]
195+
direct: bool = False
196+
artifact: Optional[Dict] = None
197+
dependencies: Optional[List[str]] = None
198+
manifestFiles: Optional[List[SocketManifestReference]] = None
196199

197200
def __getitem__(self, key): return getattr(self, key)
198201
def to_dict(self): return asdict(self)
199202

200203
@classmethod
201-
def from_dict(cls, data: dict) -> "DependencyRef":
204+
def from_dict(cls, data: dict) -> "SocketArtifactLink":
205+
manifest_files = data.get("manifestFiles")
206+
direct_val = data.get("direct", False)
202207
return cls(
203-
direct=data["direct"],
204-
toplevelAncestors=data["toplevelAncestors"]
208+
topLevelAncestors=data["topLevelAncestors"],
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
205213
)
206214

215+
207216
@dataclass
208217
class SocketScore:
209218
supplyChain: float
@@ -355,11 +364,11 @@ def from_dict(cls, data: dict) -> "LicenseAttribution":
355364
)
356365

357366
@dataclass
358-
class DiffArtifactAlert:
367+
class SocketAlert:
359368
key: str
360369
type: str
361-
severity: Optional[SocketIssueSeverity] = None
362-
category: Optional[SocketCategory] = None
370+
severity: SocketIssueSeverity
371+
category: SocketCategory
363372
file: Optional[str] = None
364373
start: Optional[int] = None
365374
end: Optional[int] = None
@@ -371,14 +380,12 @@ def __getitem__(self, key): return getattr(self, key)
371380
def to_dict(self): return asdict(self)
372381

373382
@classmethod
374-
def from_dict(cls, data: dict) -> "DiffArtifactAlert":
375-
severity = data.get("severity")
376-
category = data.get("category")
383+
def from_dict(cls, data: dict) -> "SocketAlert":
377384
return cls(
378385
key=data["key"],
379386
type=data["type"],
380-
severity=SocketIssueSeverity(severity) if severity else None,
381-
category=SocketCategory(category) if category else None,
387+
severity=SocketIssueSeverity(data["severity"]),
388+
category=SocketCategory(data["category"]),
382389
file=data.get("file"),
383390
start=data.get("start"),
384391
end=data.get("end"),
@@ -387,28 +394,29 @@ def from_dict(cls, data: dict) -> "DiffArtifactAlert":
387394
actionPolicyIndex=data.get("actionPolicyIndex")
388395
)
389396

397+
390398
@dataclass
391399
class DiffArtifact:
392400
diffType: DiffType
393401
id: str
394402
type: str
395403
name: str
396-
license: str
397-
scores: SocketScore
398-
capabilities: SecurityCapabilities
399-
files: str
404+
score: SocketScore
400405
version: str
401-
alerts: List[DiffArtifactAlert]
406+
alerts: List[SocketAlert]
402407
licenseDetails: List[LicenseDetail]
403-
base: Optional[DependencyRef] = None
404-
head: Optional[DependencyRef] = None
408+
author: List[str] = field(default_factory=list)
409+
license: Optional[str] = None
410+
files: Optional[str] = None
411+
capabilities: Optional[SecurityCapabilities] = None
412+
base: Optional[List[SocketArtifactLink]] = None
413+
head: Optional[List[SocketArtifactLink]] = None
405414
namespace: Optional[str] = None
406415
subpath: Optional[str] = None
407416
artifact_id: Optional[str] = None
408417
artifactId: Optional[str] = None
409418
qualifiers: Optional[Dict[str, Any]] = None
410419
size: Optional[int] = None
411-
author: Optional[str] = None
412420
state: Optional[str] = None
413421
error: Optional[str] = None
414422
licenseAttrib: Optional[List[LicenseAttribution]] = None
@@ -418,27 +426,29 @@ def to_dict(self): return asdict(self)
418426

419427
@classmethod
420428
def from_dict(cls, data: dict) -> "DiffArtifact":
429+
base_data = data.get("base")
430+
head_data = data.get("head")
421431
return cls(
422432
diffType=DiffType(data["diffType"]),
423433
id=data["id"],
424434
type=data["type"],
425435
name=data["name"],
426-
license=data.get("license", ""),
427-
scores=SocketScore.from_dict(data["score"]),
428-
capabilities=SecurityCapabilities.from_dict(data["capabilities"]),
429-
files=data["files"],
436+
score=SocketScore.from_dict(data["score"]),
430437
version=data["version"],
431-
alerts=[DiffArtifactAlert.from_dict(alert) for alert in data["alerts"]],
438+
alerts=[SocketAlert.from_dict(alert) for alert in data["alerts"]],
432439
licenseDetails=[LicenseDetail.from_dict(detail) for detail in data["licenseDetails"]],
433-
base=DependencyRef.from_dict(data["base"]) if data.get("base") else None,
434-
head=DependencyRef.from_dict(data["head"]) if data.get("head") else None,
440+
files=data.get("files"),
441+
license=data.get("license"),
442+
capabilities=SecurityCapabilities.from_dict(data["capabilities"]) if data.get("capabilities") 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,
435445
namespace=data.get("namespace"),
436446
subpath=data.get("subpath"),
437447
artifact_id=data.get("artifact_id"),
438448
artifactId=data.get("artifactId"),
439449
qualifiers=data.get("qualifiers"),
440450
size=data.get("size"),
441-
author=data.get("author"),
451+
author=data.get("author", []),
442452
state=data.get("state"),
443453
error=data.get("error"),
444454
licenseAttrib=[LicenseAttribution.from_dict(attrib) for attrib in data["licenseAttrib"]] if data.get("licenseAttrib") else None
@@ -532,81 +542,26 @@ def from_dict(cls, data: dict) -> "StreamDiffResponse":
532542
data=FullScanDiffReport.from_dict(data.get("data")) if data.get("data") else None
533543
)
534544

535-
@dataclass(kw_only=True)
536-
class SocketArtifactLink:
537-
topLevelAncestors: List[str]
538-
artifact: Optional[Dict] = None
539-
dependencies: Optional[List[str]] = None
540-
direct: Optional[bool] = None
541-
manifestFiles: Optional[List[SocketManifestReference]] = None
542-
543-
def __getitem__(self, key): return getattr(self, key)
544-
def to_dict(self): return asdict(self)
545-
546-
@classmethod
547-
def from_dict(cls, data: dict) -> "SocketArtifactLink":
548-
manifest_files = data.get("manifestFiles")
549-
return cls(
550-
topLevelAncestors=data["topLevelAncestors"],
551-
artifact=data.get("artifact"),
552-
dependencies=data.get("dependencies"),
553-
direct=data.get("direct"),
554-
manifestFiles=[SocketManifestReference.from_dict(m) for m in manifest_files] if manifest_files else None
555-
)
556-
557-
@dataclass
558-
class SocketAlert:
559-
key: str
560-
type: str
561-
severity: SocketIssueSeverity
562-
category: SocketCategory
563-
file: Optional[str] = None
564-
start: Optional[int] = None
565-
end: Optional[int] = None
566-
props: Optional[Dict[str, Any]] = None
567-
action: Optional[str] = None
568-
actionPolicyIndex: Optional[int] = None
569-
570-
def __getitem__(self, key): return getattr(self, key)
571-
def to_dict(self): return asdict(self)
572-
573-
@classmethod
574-
def from_dict(cls, data: dict) -> "SocketAlert":
575-
return cls(
576-
key=data["key"],
577-
type=data["type"],
578-
severity=SocketIssueSeverity(data["severity"]),
579-
category=SocketCategory(data["category"]),
580-
file=data.get("file"),
581-
start=data.get("start"),
582-
end=data.get("end"),
583-
props=data.get("props"),
584-
action=data.get("action"),
585-
actionPolicyIndex=data.get("actionPolicyIndex")
586-
)
587-
588545
@dataclass(kw_only=True)
589546
class SocketArtifact(SocketPURL, SocketArtifactLink):
590547
id: str
591-
alerts: Optional[List[SocketAlert]] = field(default_factory=list)
548+
alerts: List[SocketAlert]
549+
score: SocketScore
592550
author: Optional[List[str]] = field(default_factory=list)
593551
batchIndex: Optional[int] = None
594552
license: Optional[str] = None
595553
licenseAttrib: Optional[List[LicenseAttribution]] = field(default_factory=list)
596554
licenseDetails: Optional[List[LicenseDetail]] = field(default_factory=list)
597-
score: Optional[SocketScore] = None
598-
size: Optional[float] = None
555+
size: Optional[int] = None
599556

600557
def __getitem__(self, key): return getattr(self, key)
601558
def to_dict(self): return asdict(self)
602559

603560
@classmethod
604561
def from_dict(cls, data: dict) -> "SocketArtifact":
605-
# First get the base class data
606562
purl_data = {k: data.get(k) for k in SocketPURL.__dataclass_fields__}
607563
link_data = {k: data.get(k) for k in SocketArtifactLink.__dataclass_fields__}
608564

609-
# Handle nested types
610565
alerts = data.get("alerts")
611566
license_attrib = data.get("licenseAttrib")
612567
license_details = data.get("licenseDetails")
@@ -658,7 +613,7 @@ def create_params_string(self, params: dict) -> str:
658613
for name, value in params.items():
659614
if value:
660615
if name == "committers" and isinstance(value, list):
661-
# Handle committers specially - add multiple params
616+
662617
for committer in value:
663618
param_str += f"&{name}={committer}"
664619
else:
@@ -699,7 +654,7 @@ def post(self, files: list, params: FullScanParams) -> CreateFullScanResponse:
699654
org_slug = str(params.org_slug)
700655
params_dict = params.to_dict()
701656
params_dict.pop("org_slug")
702-
params_arg = self.create_params_string(params_dict) # Convert params to dict
657+
params_arg = self.create_params_string(params_dict)
703658

704659
path = "orgs/" + org_slug + "/full-scans" + str(params_arg)
705660

@@ -772,12 +727,12 @@ def stream(self, org_slug: str, full_scan_id: str) -> FullScanStreamResponse:
772727
item = json.loads(line)
773728
stream_str.append(item)
774729
for val in stream_str:
775-
artifacts[val["id"]] = val # Just store the raw dict
730+
artifacts[val["id"]] = val
776731

777732
return FullScanStreamResponse.from_dict({
778733
"success": True,
779734
"status": 200,
780-
"artifacts": artifacts # Let from_dict handle the conversion
735+
"artifacts": artifacts
781736
})
782737
except Exception as e:
783738
error_message = f"Error parsing stream response: {str(e)}"

socketdev/version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "2.0.2"
1+
__version__ = "2.0.4"

0 commit comments

Comments
 (0)