Skip to content

Commit 3a69fa9

Browse files
committed
feat: Add support for base_paths parameter in fullscans and diffscans
- Add base_paths parameter to Utils.load_files_for_sending_lazy() to support multiple base paths for file key stripping - Update FullScans.post() method to accept base_paths parameter with lazy loading support - Update DiffScans.create_from_repo() method to accept base_paths parameter - Maintain backward compatibility with existing base_path parameter - Fix test issues: correct fullscans.get() usage in comprehensive integration test - Update test expectations to match correct API path handling (path segments vs query params) The base_paths parameter takes precedence over base_path when both are provided, allowing users to specify multiple directory paths to strip from uploaded file keys for cleaner file organization in Socket scans.
1 parent cf621a4 commit 3a69fa9

File tree

7 files changed

+48
-21
lines changed

7 files changed

+48
-21
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "socketdev"
7-
version = "3.0.5"
7+
version = "3.0.6"
88
requires-python = ">= 3.9"
99
dependencies = [
1010
'requests',

socketdev/diffscans/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import json
22
import logging
3-
from typing import Any, Dict, Optional, Union
3+
from typing import Any, Dict, List, Optional, Union
44
from ..utils import Utils
55

66
log = logging.getLogger("socketdev")
@@ -30,7 +30,7 @@ def get(self, org_slug: str, diff_scan_id: str) -> dict:
3030
log.error(f"Error fetching diff scan: {response.status_code}, message: {response.text}")
3131
return {}
3232

33-
def create_from_repo(self, org_slug: str, repo_slug: str, files: list, params: Optional[Dict[str, Any]] = None, use_lazy_loading: bool = False, workspace: str = None, max_open_files: int = 100, base_path: str = None) -> dict:
33+
def create_from_repo(self, org_slug: str, repo_slug: str, files: list, params: Optional[Dict[str, Any]] = None, use_lazy_loading: bool = False, workspace: str = None, max_open_files: int = 100, base_path: str = None, base_paths: list = None) -> dict:
3434
"""
3535
Create a diff scan from repo HEAD, uploading files as multipart form data.
3636
@@ -46,6 +46,7 @@ def create_from_repo(self, org_slug: str, repo_slug: str, files: list, params: O
4646
max_open_files: Maximum number of files to keep open simultaneously when using
4747
lazy loading. Useful for systems with low ulimit values (default: 100)
4848
base_path: Optional base path to strip from key names for cleaner file organization
49+
base_paths: Optional list of base paths to strip from key names (takes precedence over base_path)
4950
5051
Returns:
5152
dict: API response containing diff scan results
@@ -64,7 +65,7 @@ def create_from_repo(self, org_slug: str, repo_slug: str, files: list, params: O
6465

6566
# Use lazy loading if requested
6667
if use_lazy_loading:
67-
prepared_files = Utils.load_files_for_sending_lazy(files, workspace, max_open_files, base_path)
68+
prepared_files = Utils.load_files_for_sending_lazy(files, workspace, max_open_files, base_path, base_paths)
6869
else:
6970
prepared_files = files
7071

socketdev/fullscans/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,7 @@ def get(self, org_slug: str, params: dict, use_types: bool = False) -> Union[dic
728728
)
729729
return {}
730730

731-
def post(self, files: list, params: FullScanParams, use_types: bool = False, use_lazy_loading: bool = False, workspace: str = None, max_open_files: int = 100, base_path: str = None) -> Union[dict, CreateFullScanResponse]:
731+
def post(self, files: list, params: FullScanParams, use_types: bool = False, use_lazy_loading: bool = False, workspace: str = None, max_open_files: int = 100, base_path: str = None, base_paths: List[str] = None) -> Union[dict, CreateFullScanResponse]:
732732
"""
733733
Create a new full scan by uploading manifest files.
734734
@@ -743,6 +743,7 @@ def post(self, files: list, params: FullScanParams, use_types: bool = False, use
743743
max_open_files: Maximum number of files to keep open simultaneously when using
744744
lazy loading. Useful for systems with low ulimit values (default: 100)
745745
base_path: Optional base path to strip from key names for cleaner file organization
746+
base_paths: Optional list of base paths to strip from key names (takes precedence over base_path)
746747
747748
Returns:
748749
dict or CreateFullScanResponse: API response containing scan results
@@ -763,7 +764,7 @@ def post(self, files: list, params: FullScanParams, use_types: bool = False, use
763764

764765
# Use lazy loading if requested
765766
if use_lazy_loading:
766-
prepared_files = Utils.load_files_for_sending_lazy(files, workspace, max_open_files, base_path)
767+
prepared_files = Utils.load_files_for_sending_lazy(files, workspace, max_open_files, base_path, base_paths)
767768
else:
768769
prepared_files = files
769770

socketdev/utils/__init__.py

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ def validate_integration_type(integration_type: str) -> IntegrationType:
233233
return integration_type # type: ignore
234234

235235
@staticmethod
236-
def load_files_for_sending_lazy(files: List[str], workspace: str = None, max_open_files: int = 100, base_path: str = None) -> List[Tuple[str, Tuple[str, LazyFileLoader]]]:
236+
def load_files_for_sending_lazy(files: List[str], workspace: str = None, max_open_files: int = 100, base_path: str = None, base_paths: List[str] = None) -> List[Tuple[str, Tuple[str, LazyFileLoader]]]:
237237
"""
238238
Prepares files for sending to the Socket API using lazy loading.
239239
@@ -247,6 +247,7 @@ def load_files_for_sending_lazy(files: List[str], workspace: str = None, max_ope
247247
workspace: Base directory path to make paths relative to
248248
max_open_files: Maximum number of files to keep open simultaneously (default: 100)
249249
base_path: Optional base path to strip from key names for cleaner file organization
250+
base_paths: Optional list of base paths to strip from key names (takes precedence over base_path)
250251
251252
Returns:
252253
List of tuples formatted for requests multipart upload:
@@ -260,6 +261,8 @@ def load_files_for_sending_lazy(files: List[str], workspace: str = None, max_ope
260261
workspace = workspace.replace("\\", "/")
261262
if base_path and "\\" in base_path:
262263
base_path = base_path.replace("\\", "/")
264+
if base_paths:
265+
base_paths = [bp.replace("\\", "/") if "\\" in bp else bp for bp in base_paths]
263266

264267
for file_path in files:
265268
# Normalize file path
@@ -270,29 +273,51 @@ def load_files_for_sending_lazy(files: List[str], workspace: str = None, max_ope
270273

271274
# Calculate the key name for the form data
272275
key = file_path
276+
path_stripped = False
273277

274-
# If base_path is provided, strip it from the file path to create the key
275-
if base_path:
278+
# If base_paths is provided, try to strip one of the paths from the file path
279+
if base_paths:
280+
for bp in base_paths:
281+
# Normalize base_path to ensure consistent handling of trailing slashes
282+
normalized_base_path = bp.rstrip("/") + "/" if not bp.endswith("/") else bp
283+
if key.startswith(normalized_base_path):
284+
key = key[len(normalized_base_path):]
285+
path_stripped = True
286+
break
287+
elif key.startswith(bp.rstrip("/")):
288+
# Handle case where base_path matches exactly without trailing slash
289+
stripped_base = bp.rstrip("/")
290+
if key.startswith(stripped_base + "/") or key == stripped_base:
291+
key = key[len(stripped_base):]
292+
key = key.lstrip("/")
293+
path_stripped = True
294+
break
295+
296+
# If base_path is provided and no base_paths matched, use single base_path
297+
elif base_path:
276298
# Normalize base_path to ensure consistent handling of trailing slashes
277299
normalized_base_path = base_path.rstrip("/") + "/" if not base_path.endswith("/") else base_path
278300
if key.startswith(normalized_base_path):
279301
key = key[len(normalized_base_path):]
302+
path_stripped = True
280303
elif key.startswith(base_path.rstrip("/")):
281304
# Handle case where base_path matches exactly without trailing slash
282305
stripped_base = base_path.rstrip("/")
283306
if key.startswith(stripped_base + "/") or key == stripped_base:
284307
key = key[len(stripped_base):]
285308
key = key.lstrip("/")
309+
path_stripped = True
286310

287-
# If workspace is provided and base_path wasn't used, fall back to workspace logic
288-
elif workspace and file_path.startswith(workspace):
311+
# If workspace is provided and no base paths matched, fall back to workspace logic
312+
if not path_stripped and workspace and file_path.startswith(workspace):
289313
key = file_path[len(workspace):]
290314
key = key.lstrip("/")
291315
key = key.lstrip("./")
316+
path_stripped = True
292317

293-
# If neither base_path nor workspace matched, clean up the key
294-
if key == file_path:
295-
# No base_path or workspace stripping occurred, clean up leading parts
318+
# If no path stripping occurred, clean up the key
319+
if not path_stripped:
320+
# No base_path, base_paths, or workspace stripping occurred, clean up leading parts
296321
key = key.lstrip("/")
297322
key = key.lstrip("./")
298323

socketdev/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "3.0.5"
1+
__version__ = "3.0.6"

tests/integration/test_comprehensive_integration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ def test_fullscans_basic_workflow(self):
152152
self.created_scan_ids.append(scan_id)
153153

154154
# Get the scan
155-
scan_info = self.sdk.fullscans.get(self.org_slug, scan_id)
155+
scan_info = self.sdk.fullscans.get(self.org_slug, {"id": scan_id})
156156
self.assertIsInstance(scan_info, dict)
157157

158158
# List scans

tests/unit/test_working_endpoints_unit.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -346,15 +346,15 @@ def test_fullscans_get_corrected_unit(self):
346346
"""Test fullscans get - CORRECTED PARAMETER HANDLING."""
347347
expected_data = {"id": "scan-123", "status": "completed"}
348348
self._mock_response(expected_data)
349-
350-
# The actual API uses query parameters, not path parameters
349+
350+
# When getting a specific scan by ID, it uses path parameters
351351
result = self.sdk.fullscans.get("test-org", {"id": "scan-123"})
352-
352+
353353
self.assertEqual(result, expected_data)
354354
call_args = self.mock_requests.request.call_args
355355
self.assertEqual(call_args[0][0], "GET")
356-
# Path includes query params, not path segments
357-
self.assertIn("/orgs/test-org/full-scans?id=scan-123", call_args[0][1])
356+
# Single ID param creates path segment, not query params
357+
self.assertIn("/orgs/test-org/full-scans/scan-123", call_args[0][1])
358358

359359
def test_diffscans_create_from_repo_corrected_unit(self):
360360
"""Test diffscans creation from repo - CORRECTED PATH."""

0 commit comments

Comments
 (0)