Skip to content

Commit 68a15b0

Browse files
committed
updated to support cli testing branch
1 parent 0dabc45 commit 68a15b0

File tree

18 files changed

+413
-271
lines changed

18 files changed

+413
-271
lines changed

pyproject.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
[build-system]
2-
requires = ["setuptools >= 61.0"]
2+
requires = [
3+
"setuptools >= 61.0",
4+
"requests"
5+
]
36
build-backend = "setuptools.build_meta"
47

58
[project]
69
name = "socket-sdk-python"
710
dynamic = ["version"]
811
requires-python = ">= 3.9"
912
dependencies = [
10-
'requests'
13+
'requests',
14+
'typing-extensions>=4.12.2'
1115
]
1216
readme = "README.rst"
1317
license = {file = "LICENSE"}

socketdev/__init__.py

Lines changed: 25 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import logging
2-
import requests
3-
import base64
42

5-
from socketdev.core.classes import Response
3+
from socketdev.core.api import API
64
from socketdev.dependencies import Dependencies
7-
from socketdev.exceptions import APIKeyMissing, APIFailure, APIAccessDenied, APIInsufficientQuota, APIResourceNotFound
85
from socketdev.export import Export
96
from socketdev.fullscans import FullScans
107
from socketdev.npm import NPM
@@ -17,106 +14,40 @@
1714
from socketdev.repositories import Repositories
1815
from socketdev.sbom import Sbom
1916
from socketdev.settings import Settings
17+
from socketdev.version import __version__
18+
from socketdev.utils import Utils, IntegrationType, INTEGRATION_TYPES
2019

21-
20+
__version__ = __version__
2221
__author__ = "socket.dev"
23-
__version__ = "1.0.14"
24-
__all__ = ["socketdev"]
25-
26-
27-
global encoded_key
28-
encoded_key: str
22+
__all__ = ["socketdev", "Utils", "IntegrationType", "INTEGRATION_TYPES"]
2923

30-
api_url = "https://api.socket.dev/v0"
31-
request_timeout = 30
3224
log = logging.getLogger("socketdev")
3325
log.addHandler(logging.NullHandler())
3426

3527

36-
def encode_key(token: str):
37-
global encoded_key
38-
encoded_key = base64.b64encode(token.encode()).decode("ascii")
39-
40-
41-
def do_request(
42-
path: str, headers: dict = None, payload: [dict, str] = None, files: list = None, method: str = "GET"
43-
) -> Response:
44-
"""
45-
Shared function for performing the requests against the API.
46-
:param path: String path of the URL
47-
:param headers: Optional dictionary of the headers to include in the request. Defaults to None
48-
:param payload: Optional dictionary or string of the payload to POST. Defaults to None
49-
:param files: Optional list of files to send. Defaults to None
50-
:param method: Optional string of the method for the Request. Defaults to GET
51-
"""
52-
53-
if encoded_key is None or encoded_key == "":
54-
raise APIKeyMissing
55-
56-
if headers is None:
57-
headers = {
58-
"Authorization": f"Basic {encoded_key}",
59-
"User-Agent": f"SocketPythonScript/{__version__}",
60-
"accept": "application/json",
61-
}
62-
url = f"{api_url}/{path}"
63-
try:
64-
response = requests.request(
65-
method.upper(), url, headers=headers, data=payload, files=files, timeout=request_timeout
66-
)
67-
if response.status_code >= 400:
68-
raise APIFailure("Bad Request")
69-
elif response.status_code == 401:
70-
raise APIAccessDenied("Unauthorized")
71-
elif response.status_code == 403:
72-
raise APIInsufficientQuota("Insufficient max_quota for API method")
73-
elif response.status_code == 404:
74-
raise APIResourceNotFound(f"Path not found {path}")
75-
elif response.status_code == 429:
76-
raise APIInsufficientQuota("Insufficient quota for API route")
77-
except Exception as error:
78-
response = Response(text=f"{error}", error=True, status_code=500)
79-
raise APIFailure(response)
80-
return response
81-
82-
8328
class socketdev:
84-
token: str
85-
timeout: int
86-
dependencies: Dependencies
87-
npm: NPM
88-
openapi: OpenAPI
89-
org: Orgs
90-
quota: Quota
91-
report: Report
92-
sbom: Sbom
93-
purl: Purl
94-
fullscans: FullScans
95-
export: Export
96-
repositories: Repositories
97-
settings: Settings
98-
repos: Repos
99-
10029
def __init__(self, token: str, timeout: int = 30):
30+
self.api = API()
10131
self.token = token + ":"
102-
encode_key(self.token)
103-
self.timeout = timeout
104-
socketdev.set_timeout(self.timeout)
105-
self.dependencies = Dependencies()
106-
self.npm = NPM()
107-
self.openapi = OpenAPI()
108-
self.org = Orgs()
109-
self.quota = Quota()
110-
self.report = Report()
111-
self.sbom = Sbom()
112-
self.purl = Purl()
113-
self.fullscans = FullScans()
114-
self.export = Export()
115-
self.repositories = Repositories()
116-
self.repos = Repos()
117-
self.settings = Settings()
32+
self.api.encode_key(self.token)
33+
self.api.set_timeout(timeout)
34+
35+
self.dependencies = Dependencies(self.api)
36+
self.npm = NPM(self.api)
37+
self.openapi = OpenAPI(self.api)
38+
self.org = Orgs(self.api)
39+
self.quota = Quota(self.api)
40+
self.report = Report(self.api)
41+
self.sbom = Sbom(self.api)
42+
self.purl = Purl(self.api)
43+
self.fullscans = FullScans(self.api)
44+
self.export = Export(self.api)
45+
self.repositories = Repositories(self.api)
46+
self.repos = Repos(self.api)
47+
self.settings = Settings(self.api)
48+
self.utils = Utils()
11849

11950
@staticmethod
12051
def set_timeout(timeout: int):
121-
global request_timeout
122-
request_timeout = timeout
52+
# Kept for backwards compatibility
53+
pass

socketdev/core/api.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import base64
2+
import requests
3+
from socketdev.core.classes import Response
4+
from socketdev.exceptions import APIKeyMissing, APIFailure, APIAccessDenied, APIInsufficientQuota, APIResourceNotFound
5+
from socketdev.version import __version__
6+
7+
8+
class API:
9+
def __init__(self):
10+
self.encoded_key = None
11+
self.api_url = "https://api.socket.dev/v0"
12+
self.request_timeout = 30
13+
14+
def encode_key(self, token: str):
15+
self.encoded_key = base64.b64encode(token.encode()).decode("ascii")
16+
17+
def set_timeout(self, timeout: int):
18+
self.request_timeout = timeout
19+
20+
def do_request(
21+
self, path: str, headers: dict = None, payload: [dict, str] = None, files: list = None, method: str = "GET"
22+
) -> Response:
23+
if self.encoded_key is None or self.encoded_key == "":
24+
raise APIKeyMissing
25+
26+
if headers is None:
27+
headers = {
28+
"Authorization": f"Basic {self.encoded_key}",
29+
"User-Agent": f"SocketPythonScript/{__version__}",
30+
"accept": "application/json",
31+
}
32+
url = f"{self.api_url}/{path}"
33+
try:
34+
response = requests.request(
35+
method.upper(), url, headers=headers, data=payload, files=files, timeout=self.request_timeout
36+
)
37+
if response.status_code >= 400:
38+
raise APIFailure("Bad Request")
39+
elif response.status_code == 401:
40+
raise APIAccessDenied("Unauthorized")
41+
elif response.status_code == 403:
42+
raise APIInsufficientQuota("Insufficient max_quota for API method")
43+
elif response.status_code == 404:
44+
raise APIResourceNotFound(f"Path not found {path}")
45+
elif response.status_code == 429:
46+
raise APIInsufficientQuota("Insufficient quota for API route")
47+
except Exception as error:
48+
response = Response(text=f"{error}", error=True, status_code=500)
49+
raise APIFailure(response)
50+
return response

socketdev/dependencies/__init__.py

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
1-
import socketdev
2-
from socketdev.tools import load_files
3-
from urllib.parse import urlencode
41
import json
2+
from urllib.parse import urlencode
3+
4+
from socketdev.tools import load_files
55

66

77
class Dependencies:
8-
@staticmethod
9-
def post(files: list, params: dict) -> dict:
8+
def __init__(self, api):
9+
self.api = api
10+
11+
def post(self, files: list, params: dict) -> dict:
1012
loaded_files = []
1113
loaded_files = load_files(files, loaded_files)
1214
path = "dependencies/upload?" + urlencode(params)
13-
response = socketdev.do_request(
14-
path=path,
15-
files=loaded_files,
16-
method="POST"
17-
)
15+
response = self.api.do_request(path=path, files=loaded_files, method="POST")
1816
if response.status_code == 200:
1917
result = response.json()
2018
else:
@@ -23,22 +21,15 @@ def post(files: list, params: dict) -> dict:
2321
print(response.text)
2422
return result
2523

26-
@staticmethod
2724
def get(
28-
limit: int = 50,
29-
offset: int = 0,
25+
self,
26+
limit: int = 50,
27+
offset: int = 0,
3028
) -> dict:
3129
path = "dependencies/search"
32-
payload = {
33-
"limit": limit,
34-
"offset": offset
35-
}
30+
payload = {"limit": limit, "offset": offset}
3631
payload_str = json.dumps(payload)
37-
response = socketdev.do_request(
38-
path=path,
39-
method="POST",
40-
payload=payload_str
41-
)
32+
response = self.api.do_request(path=path, method="POST", payload=payload_str)
4233
if response.status_code == 200:
4334
result = response.json()
4435
else:

socketdev/export/__init__.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from urllib.parse import urlencode
22
from dataclasses import dataclass, asdict
33
from typing import Optional
4-
import socketdev
54

65

76
@dataclass
@@ -21,8 +20,10 @@ def to_query_params(self) -> str:
2120

2221

2322
class Export:
24-
@staticmethod
25-
def cdx_bom(org_slug: str, id: str, query_params: Optional[ExportQueryParams] = None) -> dict:
23+
def __init__(self, api):
24+
self.api = api
25+
26+
def cdx_bom(self, org_slug: str, id: str, query_params: Optional[ExportQueryParams] = None) -> dict:
2627
"""
2728
Export a Socket SBOM as a CycloneDX SBOM
2829
:param org_slug: String - The slug of the organization
@@ -33,16 +34,15 @@ def cdx_bom(org_slug: str, id: str, query_params: Optional[ExportQueryParams] =
3334
path = f"orgs/{org_slug}/export/cdx/{id}"
3435
if query_params:
3536
path += query_params.to_query_params()
36-
result = socketdev.do_request(path=path)
37+
response = self.api.do_request(path=path)
3738
try:
38-
sbom = result.json()
39+
sbom = response.json()
3940
sbom["success"] = True
4041
except Exception as error:
4142
sbom = {"success": False, "message": str(error)}
4243
return sbom
4344

44-
@staticmethod
45-
def spdx_bom(org_slug: str, id: str, query_params: Optional[ExportQueryParams] = None) -> dict:
45+
def spdx_bom(self, org_slug: str, id: str, query_params: Optional[ExportQueryParams] = None) -> dict:
4646
"""
4747
Export a Socket SBOM as an SPDX SBOM
4848
:param org_slug: String - The slug of the organization
@@ -53,9 +53,9 @@ def spdx_bom(org_slug: str, id: str, query_params: Optional[ExportQueryParams] =
5353
path = f"orgs/{org_slug}/export/spdx/{id}"
5454
if query_params:
5555
path += query_params.to_query_params()
56-
result = socketdev.do_request(path=path)
56+
response = self.api.do_request(path=path)
5757
try:
58-
sbom = result.json()
58+
sbom = response.json()
5959
sbom["success"] = True
6060
except Exception as error:
6161
sbom = {"success": False, "message": str(error)}

0 commit comments

Comments
 (0)