Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions jigsawstack/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Union
from typing import Union, Dict
import os
from .audio import Audio, AsyncAudio
from .vision import Vision, AsyncVision
Expand Down Expand Up @@ -27,13 +27,15 @@ class JigsawStack:
classification: Classification
api_key: str
api_url: str
disable_request_logging: bool
headers: Dict[str, str]
# disable_request_logging: bool

def __init__(
self,
api_key: Union[str, None] = None,
api_url: Union[str, None] = None,
disable_request_logging: Union[bool, None] = None,
# disable_request_logging: Union[bool, None] = None,
headers: Union[Dict[str, str], None] = None,
) -> None:
if api_key is None:
api_key = os.environ.get("JIGSAWSTACK_API_KEY")
Expand All @@ -51,6 +53,10 @@ def __init__(
self.api_key = api_key
self.api_url = api_url

self.headers = headers or {}

disable_request_logging = self.headers.get("x-jigsaw-no-request-log")

self.audio = Audio(
api_key=api_key,
api_url=api_url,
Expand Down
18 changes: 14 additions & 4 deletions jigsawstack/async_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ def __init__(
self.disable_request_logging = config.get("disable_request_logging")
self.stream = stream

def __convert_params(self, params: Union[Dict[Any, Any], List[Dict[Any, Any]]]) -> Dict[str, str]:
def __convert_params(
self, params: Union[Dict[Any, Any], List[Dict[Any, Any]]]
) -> Dict[str, str]:
"""
Convert parameters to string values for URL encoding.
"""
Expand All @@ -45,10 +47,10 @@ def __convert_params(self, params: Union[Dict[Any, Any], List[Dict[Any, Any]]])

if isinstance(params, str):
return params

if isinstance(params, list):
return {} # List params are only used in JSON body

converted = {}
for key, value in params.items():
if isinstance(value, bool):
Expand All @@ -67,7 +69,15 @@ async def perform(self) -> Union[T, None]:
# For binary responses
if resp.status == 200:
content_type = resp.headers.get("content-type", "")
if not resp.text or any(t in content_type for t in ["audio/", "image/", "application/octet-stream", "image/png"]):
if not resp.text or any(
t in content_type
for t in [
"audio/",
"image/",
"application/octet-stream",
"image/png",
]
):
content = await resp.read()
return cast(T, content)

Expand Down
6 changes: 2 additions & 4 deletions jigsawstack/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from .helpers import build_path



class SpeechToTextParams(TypedDict):
url: NotRequired[str]
file_store_key: NotRequired[str]
Expand Down Expand Up @@ -57,7 +56,7 @@ def __init__(
def speech_to_text(self, params: SpeechToTextParams) -> SpeechToTextResponse: ...
@overload
def speech_to_text(
self, file: bytes, options: Optional[SpeechToTextParams] = None
self, blob: bytes, options: Optional[SpeechToTextParams] = None
) -> SpeechToTextResponse: ...

def speech_to_text(
Expand Down Expand Up @@ -114,7 +113,7 @@ async def speech_to_text(
) -> SpeechToTextResponse: ...
@overload
async def speech_to_text(
self, file: bytes, options: Optional[SpeechToTextParams] = None
self, blob: bytes, options: Optional[SpeechToTextParams] = None
) -> SpeechToTextResponse: ...

async def speech_to_text(
Expand Down Expand Up @@ -145,4 +144,3 @@ async def speech_to_text(
verb="post",
).perform_with_content()
return resp

4 changes: 2 additions & 2 deletions jigsawstack/embedding.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def __init__(
@overload
def execute(self, params: EmbeddingParams) -> EmbeddingResponse: ...
@overload
def execute(self, file: bytes, options: EmbeddingParams = None) -> EmbeddingResponse: ...
def execute(self, blob: bytes, options: EmbeddingParams = None) -> EmbeddingResponse: ...

def execute(
self,
Expand Down Expand Up @@ -95,7 +95,7 @@ def __init__(
@overload
async def execute(self, params: EmbeddingParams) -> EmbeddingResponse: ...
@overload
async def execute(self, file: bytes, options: EmbeddingParams = None) -> EmbeddingResponse: ...
async def execute(self, blob: bytes, options: EmbeddingParams = None) -> EmbeddingResponse: ...

async def execute(
self,
Expand Down
11 changes: 7 additions & 4 deletions jigsawstack/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,16 @@ def perform(self) -> Union[T, None]:
"""
resp = self.make_request(url=f"{self.api_url}{self.path}")

#for binary responses
# for binary responses
if resp.status_code == 200:
content_type = resp.headers.get("content-type", "")
if not resp.text or any(t in content_type for t in ["audio/", "image/", "application/octet-stream", "image/png"]):
if not resp.text or any(
t in content_type
for t in ["audio/", "image/", "application/octet-stream", "image/png"]
):
return cast(T, resp.content)

#for json resposes.
# for json resposes.
if resp.status_code != 200:
try:
error = resp.json()
Expand Down Expand Up @@ -105,7 +108,7 @@ def perform_file(self) -> Union[T, None]:
err=error.get("error"),
)

#for binary responses
# for binary responses
if resp.status_code == 200:
content_type = resp.headers.get("content-type", "")
if "application/json" not in content_type:
Expand Down
4 changes: 2 additions & 2 deletions jigsawstack/translate.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def text(
@overload
def image(self, params: TranslateImageParams) -> TranslateImageResponse: ...
@overload
def image(self, file: bytes, options: TranslateImageParams = None) -> TranslateImageParams: ...
def image(self, blob: bytes, options: TranslateImageParams = None) -> TranslateImageParams: ...

def image(
self,
Expand Down Expand Up @@ -160,7 +160,7 @@ async def text(
@overload
async def image(self, params: TranslateImageParams) -> TranslateImageResponse: ...
@overload
async def image(self, file: bytes, options: TranslateImageParams = None) -> TranslateImageParams: ...
async def image(self, blob: bytes, options: TranslateImageParams = None) -> TranslateImageParams: ...

async def image(
self,
Expand Down
77 changes: 50 additions & 27 deletions jigsawstack/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ class NSFWParams(TypedDict):
file_store_key: NotRequired[str]



class NSFWResponse(TypedDict):
success: bool
nsfw: bool
Expand Down Expand Up @@ -107,25 +106,39 @@ def email(self, params: EmailValidationParams) -> EmailValidationResponse:
verb="get",
).perform_with_content()
return resp

def nsfw(self, params: Union[NSFWParams, bytes]) -> NSFWResponse:
path="/validate/nsfw"
if isinstance(params, dict):

@overload
def nsfw(self, params: NSFWParams) -> NSFWResponse: ...
@overload
def nsfw(self, blob: bytes, options: NSFWParams = None) -> NSFWResponse: ...

def nsfw(
self,
blob: Union[NSFWParams, bytes],
options: NSFWParams = None,
) -> NSFWResponse:
if isinstance(
blob, dict
): # If params is provided as a dict, we assume it's the first argument
resp = Request(
config=self.config,
path=path,
params=cast(Dict[Any, Any], params),
path="/validate/nsfw",
params=cast(Dict[Any, Any], blob),
verb="post",
).perform_with_content()
return resp

_headers = {"Content-Type": "application/octet-stream"}
options = options or {}
path = build_path(base_path="/validate/nsfw", params=options)
content_type = options.get("content_type", "application/octet-stream")
headers = {"Content-Type": content_type}

resp = Request(
config=self.config,
path=path,
params={}, #since we're already passing data.
data=params,
headers=_headers,
params=options,
data=blob,
headers=headers,
verb="post",
).perform_with_content()
return resp
Expand All @@ -138,9 +151,7 @@ def profanity(self, params: ProfanityParams) -> ProfanityResponse:
resp = Request(
config=self.config,
path=path,
params=cast(
Dict[Any, Any], params
),
params=cast(Dict[Any, Any], params),
verb="post",
).perform_with_content()
return resp
Expand Down Expand Up @@ -198,25 +209,39 @@ async def email(self, params: EmailValidationParams) -> EmailValidationResponse:
verb="get",
).perform_with_content()
return resp

async def nsfw(self, params: Union[NSFWParams, bytes]) -> NSFWResponse:
path="/validate/nsfw"
if isinstance(params, dict):

@overload
async def nsfw(self, params: NSFWParams) -> NSFWResponse: ...
@overload
async def nsfw(self, blob: bytes, options: NSFWParams = None) -> NSFWResponse: ...

async def nsfw(
self,
blob: Union[NSFWParams, bytes],
options: NSFWParams = None,
) -> NSFWResponse:
if isinstance(
blob, dict
): # If params is provided as a dict, we assume it's the first argument
resp = await AsyncRequest(
config=self.config,
path=path,
params=cast(Dict[Any, Any], params),
path="/validate/nsfw",
params=cast(Dict[Any, Any], blob),
verb="post",
).perform_with_content()
return resp

_headers = {"Content-Type": "application/octet-stream"}
options = options or {}
path = build_path(base_path="/validate/nsfw", params=options)
content_type = options.get("content_type", "application/octet-stream")
headers = {"Content-Type": content_type}

resp = await AsyncRequest(
config=self.config,
path=path,
params={},
data=params,
headers=_headers,
params=options,
data=blob,
headers=headers,
verb="post",
).perform_with_content()
return resp
Expand All @@ -229,9 +254,7 @@ async def profanity(self, params: ProfanityParams) -> ProfanityResponse:
resp = await AsyncRequest(
config=self.config,
path=path,
params=cast(
Dict[Any, Any], params
),
params=cast(Dict[Any, Any], params),
verb="post",
).perform_with_content()
return resp
Expand Down
Loading