Skip to content

Commit e162dfd

Browse files
Merge pull request #57 from JigsawStack/feat/file-upload-native-others
update file upload works
2 parents f0d6cfd + cb9979a commit e162dfd

File tree

8 files changed

+202
-59
lines changed

8 files changed

+202
-59
lines changed

jigsawstack/__init__.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Union
1+
from typing import Union, Dict
22
import os
33
from .audio import Audio, AsyncAudio
44
from .vision import Vision, AsyncVision
@@ -27,13 +27,15 @@ class JigsawStack:
2727
classification: Classification
2828
api_key: str
2929
api_url: str
30-
disable_request_logging: bool
30+
headers: Dict[str, str]
31+
# disable_request_logging: bool
3132

3233
def __init__(
3334
self,
3435
api_key: Union[str, None] = None,
3536
api_url: Union[str, None] = None,
36-
disable_request_logging: Union[bool, None] = None,
37+
# disable_request_logging: Union[bool, None] = None,
38+
headers: Union[Dict[str, str], None] = None,
3739
) -> None:
3840
if api_key is None:
3941
api_key = os.environ.get("JIGSAWSTACK_API_KEY")
@@ -51,6 +53,10 @@ def __init__(
5153
self.api_key = api_key
5254
self.api_url = api_url
5355

56+
self.headers = headers or {}
57+
58+
disable_request_logging = self.headers.get("x-jigsaw-no-request-log")
59+
5460
self.audio = Audio(
5561
api_key=api_key,
5662
api_url=api_url,

jigsawstack/async_request.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ def __init__(
3636
self.disable_request_logging = config.get("disable_request_logging")
3737
self.stream = stream
3838

39-
def __convert_params(self, params: Union[Dict[Any, Any], List[Dict[Any, Any]]]) -> Dict[str, str]:
39+
def __convert_params(
40+
self, params: Union[Dict[Any, Any], List[Dict[Any, Any]]]
41+
) -> Dict[str, str]:
4042
"""
4143
Convert parameters to string values for URL encoding.
4244
"""
@@ -45,10 +47,10 @@ def __convert_params(self, params: Union[Dict[Any, Any], List[Dict[Any, Any]]])
4547

4648
if isinstance(params, str):
4749
return params
48-
50+
4951
if isinstance(params, list):
5052
return {} # List params are only used in JSON body
51-
53+
5254
converted = {}
5355
for key, value in params.items():
5456
if isinstance(value, bool):
@@ -67,7 +69,15 @@ async def perform(self) -> Union[T, None]:
6769
# For binary responses
6870
if resp.status == 200:
6971
content_type = resp.headers.get("content-type", "")
70-
if not resp.text or any(t in content_type for t in ["audio/", "image/", "application/octet-stream", "image/png"]):
72+
if not resp.text or any(
73+
t in content_type
74+
for t in [
75+
"audio/",
76+
"image/",
77+
"application/octet-stream",
78+
"image/png",
79+
]
80+
):
7181
content = await resp.read()
7282
return cast(T, content)
7383

jigsawstack/audio.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
from .helpers import build_path
1010

1111

12-
1312
class SpeechToTextParams(TypedDict):
1413
url: NotRequired[str]
1514
file_store_key: NotRequired[str]
@@ -57,7 +56,7 @@ def __init__(
5756
def speech_to_text(self, params: SpeechToTextParams) -> SpeechToTextResponse: ...
5857
@overload
5958
def speech_to_text(
60-
self, file: bytes, options: Optional[SpeechToTextParams] = None
59+
self, blob: bytes, options: Optional[SpeechToTextParams] = None
6160
) -> SpeechToTextResponse: ...
6261

6362
def speech_to_text(
@@ -114,7 +113,7 @@ async def speech_to_text(
114113
) -> SpeechToTextResponse: ...
115114
@overload
116115
async def speech_to_text(
117-
self, file: bytes, options: Optional[SpeechToTextParams] = None
116+
self, blob: bytes, options: Optional[SpeechToTextParams] = None
118117
) -> SpeechToTextResponse: ...
119118

120119
async def speech_to_text(
@@ -145,4 +144,3 @@ async def speech_to_text(
145144
verb="post",
146145
).perform_with_content()
147146
return resp
148-

jigsawstack/embedding.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def __init__(
4242
@overload
4343
def execute(self, params: EmbeddingParams) -> EmbeddingResponse: ...
4444
@overload
45-
def execute(self, file: bytes, options: EmbeddingParams = None) -> EmbeddingResponse: ...
45+
def execute(self, blob: bytes, options: EmbeddingParams = None) -> EmbeddingResponse: ...
4646

4747
def execute(
4848
self,
@@ -95,7 +95,7 @@ def __init__(
9595
@overload
9696
async def execute(self, params: EmbeddingParams) -> EmbeddingResponse: ...
9797
@overload
98-
async def execute(self, file: bytes, options: EmbeddingParams = None) -> EmbeddingResponse: ...
98+
async def execute(self, blob: bytes, options: EmbeddingParams = None) -> EmbeddingResponse: ...
9999

100100
async def execute(
101101
self,

jigsawstack/request.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,16 @@ def perform(self) -> Union[T, None]:
5050
"""
5151
resp = self.make_request(url=f"{self.api_url}{self.path}")
5252

53-
#for binary responses
53+
# for binary responses
5454
if resp.status_code == 200:
5555
content_type = resp.headers.get("content-type", "")
56-
if not resp.text or any(t in content_type for t in ["audio/", "image/", "application/octet-stream", "image/png"]):
56+
if not resp.text or any(
57+
t in content_type
58+
for t in ["audio/", "image/", "application/octet-stream", "image/png"]
59+
):
5760
return cast(T, resp.content)
5861

59-
#for json resposes.
62+
# for json resposes.
6063
if resp.status_code != 200:
6164
try:
6265
error = resp.json()
@@ -105,7 +108,7 @@ def perform_file(self) -> Union[T, None]:
105108
err=error.get("error"),
106109
)
107110

108-
#for binary responses
111+
# for binary responses
109112
if resp.status_code == 200:
110113
content_type = resp.headers.get("content-type", "")
111114
if "application/json" not in content_type:

jigsawstack/translate.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def text(
9898
@overload
9999
def image(self, params: TranslateImageParams) -> TranslateImageResponse: ...
100100
@overload
101-
def image(self, file: bytes, options: TranslateImageParams = None) -> TranslateImageParams: ...
101+
def image(self, blob: bytes, options: TranslateImageParams = None) -> TranslateImageParams: ...
102102

103103
def image(
104104
self,
@@ -160,7 +160,7 @@ async def text(
160160
@overload
161161
async def image(self, params: TranslateImageParams) -> TranslateImageResponse: ...
162162
@overload
163-
async def image(self, file: bytes, options: TranslateImageParams = None) -> TranslateImageParams: ...
163+
async def image(self, blob: bytes, options: TranslateImageParams = None) -> TranslateImageParams: ...
164164

165165
async def image(
166166
self,

jigsawstack/validate.py

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ class NSFWParams(TypedDict):
5050
file_store_key: NotRequired[str]
5151

5252

53-
5453
class NSFWResponse(TypedDict):
5554
success: bool
5655
nsfw: bool
@@ -107,25 +106,39 @@ def email(self, params: EmailValidationParams) -> EmailValidationResponse:
107106
verb="get",
108107
).perform_with_content()
109108
return resp
110-
111-
def nsfw(self, params: Union[NSFWParams, bytes]) -> NSFWResponse:
112-
path="/validate/nsfw"
113-
if isinstance(params, dict):
109+
110+
@overload
111+
def nsfw(self, params: NSFWParams) -> NSFWResponse: ...
112+
@overload
113+
def nsfw(self, blob: bytes, options: NSFWParams = None) -> NSFWResponse: ...
114+
115+
def nsfw(
116+
self,
117+
blob: Union[NSFWParams, bytes],
118+
options: NSFWParams = None,
119+
) -> NSFWResponse:
120+
if isinstance(
121+
blob, dict
122+
): # If params is provided as a dict, we assume it's the first argument
114123
resp = Request(
115124
config=self.config,
116-
path=path,
117-
params=cast(Dict[Any, Any], params),
125+
path="/validate/nsfw",
126+
params=cast(Dict[Any, Any], blob),
118127
verb="post",
119128
).perform_with_content()
120129
return resp
121130

122-
_headers = {"Content-Type": "application/octet-stream"}
131+
options = options or {}
132+
path = build_path(base_path="/validate/nsfw", params=options)
133+
content_type = options.get("content_type", "application/octet-stream")
134+
headers = {"Content-Type": content_type}
135+
123136
resp = Request(
124137
config=self.config,
125138
path=path,
126-
params={}, #since we're already passing data.
127-
data=params,
128-
headers=_headers,
139+
params=options,
140+
data=blob,
141+
headers=headers,
129142
verb="post",
130143
).perform_with_content()
131144
return resp
@@ -138,9 +151,7 @@ def profanity(self, params: ProfanityParams) -> ProfanityResponse:
138151
resp = Request(
139152
config=self.config,
140153
path=path,
141-
params=cast(
142-
Dict[Any, Any], params
143-
),
154+
params=cast(Dict[Any, Any], params),
144155
verb="post",
145156
).perform_with_content()
146157
return resp
@@ -198,25 +209,39 @@ async def email(self, params: EmailValidationParams) -> EmailValidationResponse:
198209
verb="get",
199210
).perform_with_content()
200211
return resp
201-
202-
async def nsfw(self, params: Union[NSFWParams, bytes]) -> NSFWResponse:
203-
path="/validate/nsfw"
204-
if isinstance(params, dict):
212+
213+
@overload
214+
async def nsfw(self, params: NSFWParams) -> NSFWResponse: ...
215+
@overload
216+
async def nsfw(self, blob: bytes, options: NSFWParams = None) -> NSFWResponse: ...
217+
218+
async def nsfw(
219+
self,
220+
blob: Union[NSFWParams, bytes],
221+
options: NSFWParams = None,
222+
) -> NSFWResponse:
223+
if isinstance(
224+
blob, dict
225+
): # If params is provided as a dict, we assume it's the first argument
205226
resp = await AsyncRequest(
206227
config=self.config,
207-
path=path,
208-
params=cast(Dict[Any, Any], params),
228+
path="/validate/nsfw",
229+
params=cast(Dict[Any, Any], blob),
209230
verb="post",
210231
).perform_with_content()
211232
return resp
212233

213-
_headers = {"Content-Type": "application/octet-stream"}
234+
options = options or {}
235+
path = build_path(base_path="/validate/nsfw", params=options)
236+
content_type = options.get("content_type", "application/octet-stream")
237+
headers = {"Content-Type": content_type}
238+
214239
resp = await AsyncRequest(
215240
config=self.config,
216241
path=path,
217-
params={},
218-
data=params,
219-
headers=_headers,
242+
params=options,
243+
data=blob,
244+
headers=headers,
220245
verb="post",
221246
).perform_with_content()
222247
return resp
@@ -229,9 +254,7 @@ async def profanity(self, params: ProfanityParams) -> ProfanityResponse:
229254
resp = await AsyncRequest(
230255
config=self.config,
231256
path=path,
232-
params=cast(
233-
Dict[Any, Any], params
234-
),
257+
params=cast(Dict[Any, Any], params),
235258
verb="post",
236259
).perform_with_content()
237260
return resp

0 commit comments

Comments
 (0)