jigsawstack 0.2.2__tar.gz → 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/PKG-INFO +1 -1
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/audio.py +67 -23
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack.egg-info/PKG-INFO +1 -1
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/setup.py +1 -1
- jigsawstack-0.2.4/tests/test_audio.py +112 -0
- jigsawstack-0.2.2/tests/test_audio.py +0 -22
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/README.md +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/__init__.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/_client.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/_config.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/async_request.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/custom_typing.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/embedding.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/exceptions.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/geo.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/helpers.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/image_generation.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/prediction.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/prompt_engine.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/request.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/search.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/sentiment.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/sql.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/store.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/summary.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/translate.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/validate.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/version.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/vision.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack/web.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack.egg-info/SOURCES.txt +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack.egg-info/dependency_links.txt +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack.egg-info/not-zip-safe +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack.egg-info/requires.txt +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/jigsawstack.egg-info/top_level.txt +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/setup.cfg +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/tests/test_async_web.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/tests/test_embedding_async.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/tests/test_geo.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/tests/test_prompt_engine.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/tests/test_search.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/tests/test_sentiment.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/tests/test_store.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/tests/test_validate.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/tests/test_vision.py +0 -0
- {jigsawstack-0.2.2 → jigsawstack-0.2.4}/tests/test_web.py +0 -0
|
@@ -16,6 +16,17 @@ class TextToSpeechParams(TypedDict):
|
|
|
16
16
|
speaker_clone_file_store_key: NotRequired[str]
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
class TTSCloneParams(TypedDict):
|
|
20
|
+
url: NotRequired[str]
|
|
21
|
+
file_store_key: NotRequired[str]
|
|
22
|
+
name: str
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ListTTSVoiceClonesParams(TypedDict):
|
|
26
|
+
limit: NotRequired[int]
|
|
27
|
+
page: NotRequired[int]
|
|
28
|
+
|
|
29
|
+
|
|
19
30
|
class TextToSpeechResponse(TypedDict):
|
|
20
31
|
success: bool
|
|
21
32
|
text: str
|
|
@@ -70,12 +81,10 @@ class Audio(ClientConfig):
|
|
|
70
81
|
@overload
|
|
71
82
|
def speech_to_text(self, file: bytes, options: Optional[SpeechToTextParams] = None) -> SpeechToTextResponse: ...
|
|
72
83
|
|
|
73
|
-
def speech_to_text(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
) -> SpeechToTextResponse:
|
|
78
|
-
if isinstance(blob, dict): # If params is provided as a dict, we assume it's the first argument
|
|
84
|
+
def speech_to_text(self, blob: Union[SpeechToTextParams, bytes], options: Optional[SpeechToTextParams] = None) -> SpeechToTextResponse:
|
|
85
|
+
if isinstance(
|
|
86
|
+
blob, dict
|
|
87
|
+
): # If params is provided as a dict, we assume it's the first argument
|
|
79
88
|
resp = Request(
|
|
80
89
|
config=self.config,
|
|
81
90
|
path="/ai/transcribe",
|
|
@@ -89,17 +98,9 @@ class Audio(ClientConfig):
|
|
|
89
98
|
content_type = options.get("content_type", "application/octet-stream")
|
|
90
99
|
headers = {"Content-Type": content_type}
|
|
91
100
|
|
|
92
|
-
resp = Request(
|
|
93
|
-
config=self.config,
|
|
94
|
-
path=path,
|
|
95
|
-
params=options,
|
|
96
|
-
data=blob,
|
|
97
|
-
headers=headers,
|
|
98
|
-
verb="post",
|
|
99
|
-
).perform_with_content()
|
|
101
|
+
resp = Request(config=self.config, path=path, params=options, data=blob, headers=headers, verb="post").perform_with_content()
|
|
100
102
|
return resp
|
|
101
103
|
|
|
102
|
-
|
|
103
104
|
def text_to_speech(self, params: TextToSpeechParams) -> TextToSpeechResponse:
|
|
104
105
|
path = "/ai/tts"
|
|
105
106
|
resp = Request(
|
|
@@ -112,12 +113,23 @@ class Audio(ClientConfig):
|
|
|
112
113
|
|
|
113
114
|
def speaker_voice_accents(self) -> TextToSpeechResponse:
|
|
114
115
|
path = "/ai/tts"
|
|
115
|
-
resp = Request(
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
).perform_with_content()
|
|
116
|
+
resp = Request(config=self.config, path=path, params={}, verb="get").perform_with_content()
|
|
117
|
+
return resp
|
|
118
|
+
|
|
119
|
+
def create_clone(self, params: TTSCloneParams) -> TextToSpeechResponse:
|
|
120
|
+
path = "/ai/tts/clone"
|
|
121
|
+
resp = Request(config=self.config, path=path, params=cast(Dict[Any, Any], params), verb="post").perform_with_content()
|
|
122
|
+
|
|
123
|
+
return resp
|
|
124
|
+
|
|
125
|
+
def list_clones(self, params: ListTTSVoiceClonesParams) -> TextToSpeechResponse:
|
|
126
|
+
path = "/ai/tts/clone"
|
|
127
|
+
resp = Request(config=self.config, path=path, params=cast(Dict[Any, Any], params), verb="get").perform_with_content()
|
|
128
|
+
return resp
|
|
129
|
+
|
|
130
|
+
def delete_clone(self, voice_id: str) -> TextToSpeechResponse:
|
|
131
|
+
path = f"/ai/tts/clone/{voice_id}"
|
|
132
|
+
resp = Request(config=self.config, path=path, params={}, verb="delete").perform_with_content()
|
|
121
133
|
return resp
|
|
122
134
|
|
|
123
135
|
|
|
@@ -140,7 +152,9 @@ class AsyncAudio(ClientConfig):
|
|
|
140
152
|
@overload
|
|
141
153
|
async def speech_to_text(self, params: SpeechToTextParams) -> SpeechToTextResponse: ...
|
|
142
154
|
@overload
|
|
143
|
-
async def speech_to_text(
|
|
155
|
+
async def speech_to_text(
|
|
156
|
+
self, file: bytes, options: Optional[SpeechToTextParams] = None
|
|
157
|
+
) -> SpeechToTextResponse: ...
|
|
144
158
|
|
|
145
159
|
async def speech_to_text(
|
|
146
160
|
self,
|
|
@@ -155,7 +169,7 @@ class AsyncAudio(ClientConfig):
|
|
|
155
169
|
verb="post",
|
|
156
170
|
).perform_with_content()
|
|
157
171
|
return resp
|
|
158
|
-
|
|
172
|
+
|
|
159
173
|
options = options or {}
|
|
160
174
|
path = build_path(base_path="/ai/transcribe", params=options)
|
|
161
175
|
content_type = options.get("content_type", "application/octet-stream")
|
|
@@ -190,3 +204,33 @@ class AsyncAudio(ClientConfig):
|
|
|
190
204
|
verb="get",
|
|
191
205
|
).perform_with_content()
|
|
192
206
|
return resp
|
|
207
|
+
|
|
208
|
+
async def create_clone(self, params: TTSCloneParams) -> TextToSpeechResponse:
|
|
209
|
+
path = "/ai/tts/clone"
|
|
210
|
+
resp = await AsyncRequest(
|
|
211
|
+
config=self.config,
|
|
212
|
+
path=path,
|
|
213
|
+
params=cast(Dict[Any, Any], params),
|
|
214
|
+
verb="post"
|
|
215
|
+
).perform_with_content()
|
|
216
|
+
return resp
|
|
217
|
+
|
|
218
|
+
async def list_clones(self, params: ListTTSVoiceClonesParams) -> TextToSpeechResponse:
|
|
219
|
+
path = "/ai/tts/clone"
|
|
220
|
+
resp = await AsyncRequest(
|
|
221
|
+
config=self.config,
|
|
222
|
+
path=path,
|
|
223
|
+
params=cast(Dict[Any, Any], params),
|
|
224
|
+
verb="get"
|
|
225
|
+
).perform_with_content()
|
|
226
|
+
return resp
|
|
227
|
+
|
|
228
|
+
async def delete_clone(self, voice_id: str) -> TextToSpeechResponse:
|
|
229
|
+
path = f"/ai/tts/clone/{voice_id}"
|
|
230
|
+
resp = await AsyncRequest(
|
|
231
|
+
config=self.config,
|
|
232
|
+
path=path,
|
|
233
|
+
params={},
|
|
234
|
+
verb="delete"
|
|
235
|
+
).perform_with_content()
|
|
236
|
+
return resp
|
|
@@ -6,7 +6,7 @@ install_requires = open("requirements.txt").readlines()
|
|
|
6
6
|
|
|
7
7
|
setup(
|
|
8
8
|
name="jigsawstack",
|
|
9
|
-
version="0.2.
|
|
9
|
+
version="0.2.4",
|
|
10
10
|
description="JigsawStack - The AI SDK for Python",
|
|
11
11
|
long_description=open("README.md", encoding="utf8").read(),
|
|
12
12
|
long_description_content_type="text/markdown",
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
from unittest.mock import MagicMock
|
|
2
|
+
import unittest
|
|
3
|
+
from jigsawstack.exceptions import JigsawStackError
|
|
4
|
+
from jigsawstack import AsyncJigsawStack
|
|
5
|
+
import pytest
|
|
6
|
+
import asyncio
|
|
7
|
+
import logging
|
|
8
|
+
from jigsawstack import AsyncJigsawStack
|
|
9
|
+
|
|
10
|
+
logging.basicConfig(level=logging.INFO)
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_text_to_speech():
|
|
15
|
+
async def _test():
|
|
16
|
+
client = AsyncJigsawStack()
|
|
17
|
+
|
|
18
|
+
"""Test converting text to speech"""
|
|
19
|
+
try:
|
|
20
|
+
response = await client.audio.text_to_speech(
|
|
21
|
+
{
|
|
22
|
+
"text": "Hello world, this is a test of the JigsawStack text to speech API."
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
print("Text to speech response:", response)
|
|
26
|
+
assert response["success"] == True
|
|
27
|
+
|
|
28
|
+
except Exception as e:
|
|
29
|
+
print(f"Error in text_to_speech test: {e}")
|
|
30
|
+
|
|
31
|
+
asyncio.run(_test())
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_speaker_voice_accents():
|
|
35
|
+
async def _test():
|
|
36
|
+
client = AsyncJigsawStack()
|
|
37
|
+
|
|
38
|
+
"""Test getting available voice accents"""
|
|
39
|
+
try:
|
|
40
|
+
response = await client.audio.speaker_voice_accents()
|
|
41
|
+
print("Speaker voice accents response:", response)
|
|
42
|
+
assert response["success"] == True
|
|
43
|
+
|
|
44
|
+
except Exception as e:
|
|
45
|
+
print(f"Error in speaker voice accents test: {e}")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_create_clone():
|
|
49
|
+
async def _test():
|
|
50
|
+
client = AsyncJigsawStack()
|
|
51
|
+
|
|
52
|
+
"""Test creating a voice clone with URL"""
|
|
53
|
+
try:
|
|
54
|
+
audio_url = (
|
|
55
|
+
"https://jigsawstack.com/audio/test.mp3" # Replace with an actual URL
|
|
56
|
+
)
|
|
57
|
+
clone_response_url = await client.audio.create_clone(
|
|
58
|
+
{"url": audio_url, "name": "Test Voice Clone URL"}
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
assert clone_response_url["success"] == True
|
|
62
|
+
|
|
63
|
+
clone_response_file_store_key = client.audio.create_clone(
|
|
64
|
+
{
|
|
65
|
+
"file_store_key": "hello_audio",
|
|
66
|
+
"name": "Test Voice Clone File Store Key",
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
assert clone_response_file_store_key["success"] == True
|
|
71
|
+
|
|
72
|
+
except Exception as e:
|
|
73
|
+
print(f"Error in voice_cloning test: {e}")
|
|
74
|
+
|
|
75
|
+
asyncio.run(_test())
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def test_list_clones():
|
|
79
|
+
async def _test():
|
|
80
|
+
client = AsyncJigsawStack()
|
|
81
|
+
"""Test listing voice clones"""
|
|
82
|
+
try:
|
|
83
|
+
# List available voice clones
|
|
84
|
+
clones_response = await client.audio.list_clones({"limit": 10, "page": 1})
|
|
85
|
+
|
|
86
|
+
assert clones_response["success"] == True
|
|
87
|
+
|
|
88
|
+
except Exception as e:
|
|
89
|
+
print(f"Error in voice_cloning test: {e}")
|
|
90
|
+
|
|
91
|
+
asyncio.run(_test())
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def test_delete_clone():
|
|
95
|
+
async def _test():
|
|
96
|
+
client = AsyncJigsawStack()
|
|
97
|
+
"""Test getting a voice clone"""
|
|
98
|
+
try:
|
|
99
|
+
create_clone_response = await client.audio.create_clone(
|
|
100
|
+
{"name": "Test Voice Clone URL", "file_store_key": "hello_audio"}
|
|
101
|
+
)
|
|
102
|
+
clones = await client.audio.list_clones({"limit": 10, "page": 1})
|
|
103
|
+
print("Clones:", clones)
|
|
104
|
+
clone_id = clones["data"][0]["id"]
|
|
105
|
+
delete_clone_response = await client.audio.delete_clone(clone_id)
|
|
106
|
+
print("Delete clone response:", delete_clone_response)
|
|
107
|
+
assert delete_clone_response["success"] == True
|
|
108
|
+
|
|
109
|
+
except Exception as e:
|
|
110
|
+
print(f"Error in list_clones test: {e}")
|
|
111
|
+
|
|
112
|
+
asyncio.run(_test())
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
from unittest.mock import MagicMock
|
|
2
|
-
import unittest
|
|
3
|
-
from jigsawstack.exceptions import JigsawStackError
|
|
4
|
-
from jigsawstack import AsyncJigsawStack
|
|
5
|
-
import pytest
|
|
6
|
-
import asyncio
|
|
7
|
-
import logging
|
|
8
|
-
|
|
9
|
-
logging.basicConfig(level=logging.INFO)
|
|
10
|
-
logger = logging.getLogger(__name__)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def test_async_speaker_voice_accents_response():
|
|
14
|
-
async def _test():
|
|
15
|
-
client = AsyncJigsawStack()
|
|
16
|
-
try:
|
|
17
|
-
result = await client.audio.speaker_voice_accents()
|
|
18
|
-
assert result["success"] == True
|
|
19
|
-
except JigsawStackError as e:
|
|
20
|
-
pytest.fail(f"Unexpected JigsawStackError: {e}")
|
|
21
|
-
|
|
22
|
-
asyncio.run(_test())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|