embed-client 1.0.0__tar.gz → 1.0.0.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: embed-client
3
- Version: 1.0.0
3
+ Version: 1.0.0.1
4
4
  Summary: Async client for Embedding Service API
5
5
  Author: Your Name
6
6
  Requires-Dist: aiohttp
@@ -153,6 +153,37 @@ class EmbeddingServiceAsyncClient:
153
153
  except Exception as e:
154
154
  raise EmbeddingServiceError(f"Unexpected error: {e}") from e
155
155
 
156
+ def _validate_texts(self, texts: List[str]) -> None:
157
+ """
158
+ Validate input texts before sending to the API.
159
+ Args:
160
+ texts (List[str]): List of texts to validate
161
+ Raises:
162
+ EmbeddingServiceAPIError: If texts are invalid
163
+ """
164
+ if not texts:
165
+ raise EmbeddingServiceAPIError({
166
+ "code": -32602,
167
+ "message": "Empty texts list provided"
168
+ })
169
+
170
+ invalid_texts = []
171
+ for i, text in enumerate(texts):
172
+ if not isinstance(text, str):
173
+ invalid_texts.append(f"Text at index {i} is not a string")
174
+ continue
175
+ if not text or not text.strip():
176
+ invalid_texts.append(f"Text at index {i} is empty or contains only whitespace")
177
+ elif len(text.strip()) < 2: # Минимальная длина текста
178
+ invalid_texts.append(f"Text at index {i} is too short (minimum 2 characters)")
179
+
180
+ if invalid_texts:
181
+ raise EmbeddingServiceAPIError({
182
+ "code": -32602,
183
+ "message": "Invalid input texts",
184
+ "details": invalid_texts
185
+ })
186
+
156
187
  async def cmd(self, command: str, params: Optional[Dict[str, Any]] = None, base_url: Optional[str] = None, port: Optional[int] = None) -> Dict[str, Any]:
157
188
  """
158
189
  Execute a command via JSON-RPC protocol.
@@ -166,7 +197,8 @@ class EmbeddingServiceAsyncClient:
166
197
  {
167
198
  "error": {
168
199
  "code": <код ошибки>,
169
- "message": <сообщение об ошибке>
200
+ "message": <сообщение об ошибке>,
201
+ "details": <опциональные детали ошибки>
170
202
  }
171
203
  }
172
204
  или
@@ -180,31 +212,50 @@ class EmbeddingServiceAsyncClient:
180
212
  }
181
213
  """
182
214
  if not command:
183
- raise EmbeddingServiceAPIError("Command is required")
215
+ raise EmbeddingServiceAPIError({
216
+ "code": -32602,
217
+ "message": "Command is required"
218
+ })
219
+
220
+ # Валидация текстов для команды embed
221
+ if command == "embed" and params and "texts" in params:
222
+ self._validate_texts(params["texts"])
223
+
184
224
  url = self._make_url("/cmd", base_url, port)
185
225
  payload = {"command": command}
186
226
  if params is not None:
187
227
  payload["params"] = params
228
+
188
229
  try:
189
230
  async with self._session.post(url, json=payload) as resp:
190
231
  await self._raise_for_status(resp)
191
232
  data = await resp.json()
233
+
192
234
  if "error" in data:
193
235
  raise EmbeddingServiceAPIError(data["error"])
236
+
194
237
  if "result" in data:
195
238
  res = data["result"]
196
239
  if isinstance(res, dict) and "success" in res and res["success"] is False:
197
240
  if "error" in res:
198
241
  raise EmbeddingServiceAPIError(res["error"])
242
+
199
243
  return data
244
+
200
245
  except aiohttp.ClientConnectionError as e:
201
- raise EmbeddingServiceAPIError(f"Connection error: {e}") from e
246
+ raise EmbeddingServiceAPIError({
247
+ "code": -32000,
248
+ "message": f"Connection error: {e}"
249
+ }) from e
202
250
  except aiohttp.ClientResponseError as e:
203
251
  raise EmbeddingServiceHTTPError(e.status, e.message) from e
204
252
  except EmbeddingServiceHTTPError:
205
253
  raise
206
254
  except Exception as e:
207
- raise EmbeddingServiceAPIError(f"Unexpected error: {e}") from e
255
+ raise EmbeddingServiceAPIError({
256
+ "code": -32000,
257
+ "message": f"Unexpected error: {e}"
258
+ }) from e
208
259
 
209
260
  async def _raise_for_status(self, resp: aiohttp.ClientResponse):
210
261
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: embed-client
3
- Version: 1.0.0
3
+ Version: 1.0.0.1
4
4
  Summary: Async client for Embedding Service API
5
5
  Author: Your Name
6
6
  Requires-Dist: aiohttp
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "embed-client"
7
- version = "1.0.0"
7
+ version = "1.0.0.001"
8
8
  description = "Async client for Embedding Service API"
9
9
  authors = [{name = "Your Name"}]
10
10
  dependencies = [
@@ -137,11 +137,11 @@ async def test_cmd_success(client):
137
137
  # Некорректные параметры: не-строка в texts
138
138
  @pytest.mark.asyncio
139
139
  async def test_embed_non_string_text(client):
140
- mock_response = MockAiohttpResponse(json_data={"error": {"code": 422, "message": "Invalid input"}})
141
- with patch.object(client._session, 'post', return_value=mock_response) as mock_post:
142
- with pytest.raises(EmbeddingServiceAPIError) as excinfo:
143
- await client.cmd("embed", params={"texts": [123, "ok"]})
144
- assert "Invalid input" in str(excinfo.value)
140
+ """Test validation of non-string values in texts list."""
141
+ with pytest.raises(EmbeddingServiceAPIError) as excinfo:
142
+ await client.cmd("embed", params={"texts": [123, "ok"]})
143
+ assert "Invalid input texts" in str(excinfo.value)
144
+ assert "Text at index 0 is not a string" in str(excinfo.value)
145
145
 
146
146
  # Некорректные параметры: невалидный params
147
147
  @pytest.mark.asyncio
@@ -282,4 +282,36 @@ async def test_aenter_aexit_exceptions():
282
282
  raise RuntimeError("fail")
283
283
  client._session = BadSession()
284
284
  with pytest.raises(RuntimeError):
285
- await client.__aexit__(None, None, None)
285
+ await client.__aexit__(None, None, None)
286
+
287
+ @pytest.mark.asyncio
288
+ async def test_embed_validation():
289
+ """Test validation of input texts for embed command."""
290
+ client = EmbeddingServiceAsyncClient()
291
+
292
+ # Test empty texts list
293
+ with pytest.raises(EmbeddingServiceAPIError) as excinfo:
294
+ await client.cmd("embed", params={"texts": []})
295
+ assert "Empty texts list provided" in str(excinfo.value)
296
+
297
+ # Test empty strings
298
+ with pytest.raises(EmbeddingServiceAPIError) as excinfo:
299
+ await client.cmd("embed", params={"texts": ["", " "]})
300
+ assert "Invalid input texts" in str(excinfo.value)
301
+ assert "Text at index 0 is empty" in str(excinfo.value)
302
+ assert "Text at index 1 is empty" in str(excinfo.value)
303
+
304
+ # Test too short texts
305
+ with pytest.raises(EmbeddingServiceAPIError) as excinfo:
306
+ await client.cmd("embed", params={"texts": ["a", "b"]})
307
+ assert "Invalid input texts" in str(excinfo.value)
308
+ assert "Text at index 0 is too short" in str(excinfo.value)
309
+ assert "Text at index 1 is too short" in str(excinfo.value)
310
+
311
+ # Test mixed valid and invalid texts
312
+ with pytest.raises(EmbeddingServiceAPIError) as excinfo:
313
+ await client.cmd("embed", params={"texts": ["valid text", "", " ", "a"]})
314
+ assert "Invalid input texts" in str(excinfo.value)
315
+ assert "Text at index 1 is empty" in str(excinfo.value)
316
+ assert "Text at index 2 is empty" in str(excinfo.value)
317
+ assert "Text at index 3 is too short" in str(excinfo.value)
File without changes
File without changes