meilisearch-python-sdk 5.5.0__tar.gz → 5.5.2__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.
Files changed (106) hide show
  1. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/.pre-commit-config.yaml +2 -2
  2. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/PKG-INFO +1 -1
  3. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/_batch.py +9 -5
  4. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/_client.py +66 -56
  5. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/_http_requests.py +8 -0
  6. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/_task.py +25 -27
  7. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/_utils.py +11 -0
  8. meilisearch_python_sdk-5.5.2/meilisearch_python_sdk/_version.py +1 -0
  9. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/errors.py +5 -4
  10. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/index/_common.py +8 -4
  11. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/index/async_index.py +196 -210
  12. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/index/index.py +97 -91
  13. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/pyproject.toml +4 -4
  14. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/uv.lock +235 -171
  15. meilisearch_python_sdk-5.5.0/meilisearch_python_sdk/_version.py +0 -1
  16. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/.github/FUNDING.yml +0 -0
  17. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/.github/release-draft-template.yaml +0 -0
  18. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/.github/renovate.json5 +0 -0
  19. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/.github/workflows/docs_publish.yml +0 -0
  20. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/.github/workflows/nightly_testing.yml +0 -0
  21. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/.github/workflows/pypi_publish.yml +0 -0
  22. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/.github/workflows/release-drafter.yml +0 -0
  23. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/.github/workflows/testing.yml +0 -0
  24. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/.gitignore +0 -0
  25. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/CONTRIBUTING.md +0 -0
  26. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/LICENSE +0 -0
  27. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/README.md +0 -0
  28. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/assets/add_in_batches.png +0 -0
  29. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/assets/searches.png +0 -0
  30. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/codecov.yml +0 -0
  31. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/datasets/small_movies.json +0 -0
  32. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/docker-compose.https.yml +0 -0
  33. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/docker-compose.yml +0 -0
  34. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/docs/.nojekyll +0 -0
  35. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/docs/CNAME +0 -0
  36. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/docs/async_client_api.md +0 -0
  37. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/docs/async_index_api.md +0 -0
  38. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/docs/client_api.md +0 -0
  39. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/docs/css/custom.css +0 -0
  40. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/docs/decorators_api.md +0 -0
  41. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/docs/index.md +0 -0
  42. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/docs/index_api.md +0 -0
  43. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/docs/js/umami.js +0 -0
  44. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/docs/json_handler.md +0 -0
  45. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/docs/overrides/partials/footer.html +0 -0
  46. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/docs/plugins.md +0 -0
  47. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/docs/pydantic.md +0 -0
  48. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/.gitignore +0 -0
  49. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/README.md +0 -0
  50. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/__init__.py +0 -0
  51. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/add_documents_decorator.py +0 -0
  52. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/add_documents_in_batches.py +0 -0
  53. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/async_add_documents_decorator.py +0 -0
  54. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/async_add_documents_in_batches.py +0 -0
  55. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/async_documents_and_search_results.py +0 -0
  56. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/async_search_tracker.py +0 -0
  57. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/async_update_settings.py +0 -0
  58. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/documents_and_search_results.py +0 -0
  59. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/fastapi_example.py +0 -0
  60. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/orjson_example.py +0 -0
  61. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/pyproject.toml +0 -0
  62. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/requirements.txt +0 -0
  63. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/search_tracker.py +0 -0
  64. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/tests/__init__.py +0 -0
  65. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/tests/conftest.py +0 -0
  66. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/tests/test_async_examples.py +0 -0
  67. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/tests/test_examples.py +0 -0
  68. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/ujson_example.py +0 -0
  69. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/examples/update_settings.py +0 -0
  70. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/justfile +0 -0
  71. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/__init__.py +0 -0
  72. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/decorators.py +0 -0
  73. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/index/__init__.py +0 -0
  74. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/json_handler.py +0 -0
  75. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/models/__init__.py +0 -0
  76. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/models/batch.py +0 -0
  77. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/models/client.py +0 -0
  78. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/models/documents.py +0 -0
  79. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/models/health.py +0 -0
  80. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/models/index.py +0 -0
  81. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/models/search.py +0 -0
  82. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/models/settings.py +0 -0
  83. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/models/task.py +0 -0
  84. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/models/version.py +0 -0
  85. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/models/webhook.py +0 -0
  86. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/plugins.py +0 -0
  87. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/py.typed +0 -0
  88. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/meilisearch_python_sdk/types.py +0 -0
  89. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/mkdocs.yaml +0 -0
  90. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/tests/__init__.py +0 -0
  91. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/tests/conftest.py +0 -0
  92. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/tests/test_async_client.py +0 -0
  93. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/tests/test_async_documents.py +0 -0
  94. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/tests/test_async_index.py +0 -0
  95. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/tests/test_async_index_plugins.py +0 -0
  96. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/tests/test_async_search.py +0 -0
  97. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/tests/test_client.py +0 -0
  98. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/tests/test_decorators.py +0 -0
  99. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/tests/test_documents.py +0 -0
  100. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/tests/test_errors.py +0 -0
  101. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/tests/test_index.py +0 -0
  102. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/tests/test_index_plugins.py +0 -0
  103. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/tests/test_search.py +0 -0
  104. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/tests/test_settings_models.py +0 -0
  105. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/tests/test_utils.py +0 -0
  106. {meilisearch_python_sdk-5.5.0 → meilisearch_python_sdk-5.5.2}/tests/test_version.py +0 -0
@@ -9,12 +9,12 @@ repos:
9
9
  - id: end-of-file-fixer
10
10
  - id: trailing-whitespace
11
11
  - repo: https://github.com/pre-commit/mirrors-mypy
12
- rev: v1.18.2
12
+ rev: v1.19.0
13
13
  hooks:
14
14
  - id: mypy
15
15
  additional_dependencies: [pydantic, orjson, types-aiofiles, types-ujson]
16
16
  - repo: https://github.com/astral-sh/ruff-pre-commit
17
- rev: v0.14.5
17
+ rev: v0.14.8
18
18
  hooks:
19
19
  - id: ruff-check
20
20
  args: [--fix, --exit-non-zero-on-fix]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meilisearch-python-sdk
3
- Version: 5.5.0
3
+ Version: 5.5.2
4
4
  Summary: A Python client providing both async and sync support for the Meilisearch API
5
5
  Project-URL: repository, https://github.com/sanders41/meilisearch-python-sdk
6
6
  Project-URL: homepage, https://github.com/sanders41/meilisearch-python-sdk
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from datetime import datetime
4
4
  from typing import TYPE_CHECKING
5
5
 
6
- from meilisearch_python_sdk._utils import get_async_client, get_client
6
+ from meilisearch_python_sdk._utils import get_async_client, get_client, get_json_handler
7
7
  from meilisearch_python_sdk.errors import BatchNotFoundError
8
8
  from meilisearch_python_sdk.models.batch import BatchResult, BatchStatus
9
9
 
@@ -21,12 +21,13 @@ async def async_get_batch(
21
21
  client: HttpxAsyncClient | AsyncClient, batch_uid: int
22
22
  ) -> BatchResult | None:
23
23
  client_ = get_async_client(client)
24
+ json_handler = get_json_handler(client)
24
25
  response = await client_.get(f"batches/{batch_uid}")
25
26
 
26
27
  if response.status_code == 404:
27
28
  raise BatchNotFoundError(f"Batch {batch_uid} not found")
28
29
 
29
- return BatchResult(**response.json())
30
+ return BatchResult(**json_handler.loads(response.content))
30
31
 
31
32
 
32
33
  async def async_get_batches(
@@ -46,6 +47,7 @@ async def async_get_batches(
46
47
  after_finished_at: datetime | None = None,
47
48
  ) -> BatchStatus:
48
49
  client_ = get_async_client(client)
50
+ json_handler = get_json_handler(client)
49
51
  params = _build_parameters(
50
52
  uids=uids,
51
53
  batch_uids=batch_uids,
@@ -62,17 +64,18 @@ async def async_get_batches(
62
64
  )
63
65
  response = await client_.get("batches", params=params)
64
66
 
65
- return BatchStatus(**response.json())
67
+ return BatchStatus(**json_handler.loads(response.content))
66
68
 
67
69
 
68
70
  def get_batch(client: HttpxClient | Client, batch_uid: int) -> BatchResult | None:
69
71
  client_ = get_client(client)
72
+ json_handler = get_json_handler(client)
70
73
  response = client_.get(f"batches/{batch_uid}")
71
74
 
72
75
  if response.status_code == 404:
73
76
  raise BatchNotFoundError(f"Batch {batch_uid} not found")
74
77
 
75
- return BatchResult(**response.json())
78
+ return BatchResult(**json_handler.loads(response.content))
76
79
 
77
80
 
78
81
  def get_batches(
@@ -92,6 +95,7 @@ def get_batches(
92
95
  after_finished_at: datetime | None = None,
93
96
  ) -> BatchStatus:
94
97
  client_ = get_client(client)
98
+ json_handler = get_json_handler(client)
95
99
  params = _build_parameters(
96
100
  uids=uids,
97
101
  batch_uids=batch_uids,
@@ -109,7 +113,7 @@ def get_batches(
109
113
 
110
114
  response = client_.get("batches", params=params)
111
115
 
112
- return BatchStatus(**response.json())
116
+ return BatchStatus(**json_handler.loads(response.content))
113
117
 
114
118
 
115
119
  def _build_parameters(
@@ -231,7 +231,7 @@ class AsyncClient(BaseClient):
231
231
  "network", network.model_dump(by_alias=True, exclude_none=True)
232
232
  )
233
233
 
234
- return Network(**response.json())
234
+ return Network(**self._http_requests.parse_json(response))
235
235
 
236
236
  async def get_networks(self) -> Network:
237
237
  """Fetches the remote-networks
@@ -252,7 +252,7 @@ class AsyncClient(BaseClient):
252
252
  """
253
253
  response = await self._http_requests.get("network")
254
254
 
255
- return Network(**response.json())
255
+ return Network(**self._http_requests.parse_json(response))
256
256
 
257
257
  async def get_webhooks(self) -> Webhooks:
258
258
  """Get all webhooks.
@@ -271,7 +271,7 @@ class AsyncClient(BaseClient):
271
271
  """
272
272
  response = await self._http_requests.get("webhooks")
273
273
 
274
- return Webhooks(**response.json())
274
+ return Webhooks(**self._http_requests.parse_json(response))
275
275
 
276
276
  async def get_webhook(self, uuid: str) -> Webhook:
277
277
  """Get a specific webhook by UUID.
@@ -293,7 +293,7 @@ class AsyncClient(BaseClient):
293
293
  """
294
294
  response = await self._http_requests.get(f"webhooks/{uuid}")
295
295
 
296
- return Webhook(**response.json())
296
+ return Webhook(**self._http_requests.parse_json(response))
297
297
 
298
298
  async def create_webhook(self, webhook: WebhookCreate) -> Webhook:
299
299
  """Create a new webhook.
@@ -322,7 +322,7 @@ class AsyncClient(BaseClient):
322
322
  "webhooks", webhook.model_dump(by_alias=True, exclude_none=True)
323
323
  )
324
324
 
325
- return Webhook(**response.json())
325
+ return Webhook(**self._http_requests.parse_json(response))
326
326
 
327
327
  async def update_webhook(self, *, uuid: str, webhook: WebhookUpdate) -> Webhook:
328
328
  """Update an existing webhook.
@@ -349,7 +349,7 @@ class AsyncClient(BaseClient):
349
349
  f"webhooks/{uuid}", webhook.model_dump(by_alias=True, exclude_none=True)
350
350
  )
351
351
 
352
- return Webhook(**response.json())
352
+ return Webhook(**self._http_requests.parse_json(response))
353
353
 
354
354
  async def delete_webhook(self, uuid: str) -> int:
355
355
  """Delete a webhook.
@@ -388,7 +388,7 @@ class AsyncClient(BaseClient):
388
388
  """
389
389
  response = await self._http_requests.post("dumps")
390
390
 
391
- return TaskInfo(**response.json())
391
+ return TaskInfo(**self._http_requests.parse_json(response))
392
392
 
393
393
  async def create_index(
394
394
  self,
@@ -462,7 +462,7 @@ class AsyncClient(BaseClient):
462
462
  """
463
463
  response = await self._http_requests.post("snapshots")
464
464
 
465
- return TaskInfo(**response.json())
465
+ return TaskInfo(**self._http_requests.parse_json(response))
466
466
 
467
467
  async def delete_index_if_exists(self, uid: str) -> bool:
468
468
  """Deletes an index if it already exists.
@@ -483,7 +483,9 @@ class AsyncClient(BaseClient):
483
483
  >>> await client.delete_index_if_exists()
484
484
  """
485
485
  response = await self._http_requests.delete(f"indexes/{uid}")
486
- status = await self.wait_for_task(response.json()["taskUid"], timeout_in_ms=100000)
486
+ status = await self.wait_for_task(
487
+ self._http_requests.parse_json(response)["taskUid"], timeout_in_ms=100000
488
+ )
487
489
  if status.status == "succeeded":
488
490
  return True
489
491
  return False
@@ -514,7 +516,7 @@ class AsyncClient(BaseClient):
514
516
  url = _build_offset_limit_url("indexes", offset, limit)
515
517
  response = await self._http_requests.get(url)
516
518
 
517
- if not response.json()["results"]:
519
+ if not self._http_requests.parse_json(response)["results"]:
518
520
  return None
519
521
 
520
522
  return [
@@ -526,7 +528,7 @@ class AsyncClient(BaseClient):
526
528
  updated_at=x["updatedAt"],
527
529
  json_handler=self.json_handler,
528
530
  )
529
- for x in response.json()["results"]
531
+ for x in self._http_requests.parse_json(response)["results"]
530
532
  ]
531
533
 
532
534
  async def get_index(self, uid: str) -> AsyncIndex:
@@ -592,7 +594,7 @@ class AsyncClient(BaseClient):
592
594
  """
593
595
  response = await self._http_requests.get("stats")
594
596
 
595
- return ClientStats(**response.json())
597
+ return ClientStats(**self._http_requests.parse_json(response))
596
598
 
597
599
  async def get_or_create_index(
598
600
  self,
@@ -660,10 +662,10 @@ class AsyncClient(BaseClient):
660
662
  >>> keys = await client.create_key(key_info)
661
663
  """
662
664
  response = await self._http_requests.post(
663
- "keys", self.json_handler.loads(key.model_dump_json(by_alias=True))
664
- ) # type: ignore[attr-defined]
665
+ "keys", key.model_dump(by_alias=True, mode="json")
666
+ )
665
667
 
666
- return Key(**response.json())
668
+ return Key(**self._http_requests.parse_json(response))
667
669
 
668
670
  async def delete_key(self, key: str) -> int:
669
671
  """Deletes an API key.
@@ -710,7 +712,7 @@ class AsyncClient(BaseClient):
710
712
  url = _build_offset_limit_url("keys", offset, limit)
711
713
  response = await self._http_requests.get(url)
712
714
 
713
- return KeySearch(**response.json())
715
+ return KeySearch(**self._http_requests.parse_json(response))
714
716
 
715
717
  async def get_key(self, key: str) -> Key:
716
718
  """Gets information about a specific API key.
@@ -732,7 +734,7 @@ class AsyncClient(BaseClient):
732
734
  """
733
735
  response = await self._http_requests.get(f"keys/{key}")
734
736
 
735
- return Key(**response.json())
737
+ return Key(**self._http_requests.parse_json(response))
736
738
 
737
739
  async def update_key(self, key: KeyUpdate) -> Key:
738
740
  """Update an API key.
@@ -761,7 +763,7 @@ class AsyncClient(BaseClient):
761
763
  payload = _build_update_key_payload(key, self.json_handler)
762
764
  response = await self._http_requests.patch(f"keys/{key.key}", payload)
763
765
 
764
- return Key(**response.json())
766
+ return Key(**self._http_requests.parse_json(response))
765
767
 
766
768
  async def multi_search(
767
769
  self,
@@ -831,10 +833,13 @@ class AsyncClient(BaseClient):
831
833
  )
832
834
 
833
835
  if federation:
834
- results = response.json()
836
+ results = self._http_requests.parse_json(response)
835
837
  return SearchResultsFederated[hits_type](**results)
836
838
 
837
- return [SearchResultsWithUID[hits_type](**x) for x in response.json()["results"]]
839
+ return [
840
+ SearchResultsWithUID[hits_type](**x)
841
+ for x in self._http_requests.parse_json(response)["results"]
842
+ ]
838
843
 
839
844
  async def get_raw_index(self, uid: str) -> IndexInfo | None:
840
845
  """Gets the index and returns all the index information rather than an AsyncIndex instance.
@@ -859,7 +864,7 @@ class AsyncClient(BaseClient):
859
864
  if response.status_code == 404:
860
865
  return None
861
866
 
862
- return IndexInfo(**response.json())
867
+ return IndexInfo(**self._http_requests.parse_json(response))
863
868
 
864
869
  async def get_raw_indexes(
865
870
  self, *, offset: int | None = None, limit: int | None = None
@@ -889,10 +894,10 @@ class AsyncClient(BaseClient):
889
894
  url = _build_offset_limit_url("indexes", offset, limit)
890
895
  response = await self._http_requests.get(url)
891
896
 
892
- if not response.json()["results"]:
897
+ if not self._http_requests.parse_json(response)["results"]:
893
898
  return None
894
899
 
895
- return [IndexInfo(**x) for x in response.json()["results"]]
900
+ return [IndexInfo(**x) for x in self._http_requests.parse_json(response)["results"]]
896
901
 
897
902
  async def get_version(self) -> Version:
898
903
  """Get the Meilisearch version.
@@ -911,7 +916,7 @@ class AsyncClient(BaseClient):
911
916
  """
912
917
  response = await self._http_requests.get("version")
913
918
 
914
- return Version(**response.json())
919
+ return Version(**self._http_requests.parse_json(response))
915
920
 
916
921
  async def health(self) -> Health:
917
922
  """Get health of the Meilisearch server.
@@ -930,7 +935,7 @@ class AsyncClient(BaseClient):
930
935
  """
931
936
  response = await self._http_requests.get("health")
932
937
 
933
- return Health(**response.json())
938
+ return Health(**self._http_requests.parse_json(response))
934
939
 
935
940
  async def swap_indexes(self, indexes: list[tuple[str, str]], rename: bool = False) -> TaskInfo:
936
941
  """Swap two indexes.
@@ -958,7 +963,7 @@ class AsyncClient(BaseClient):
958
963
  processed_indexes = [{"indexes": x} for x in indexes]
959
964
  response = await self._http_requests.post("swap-indexes", processed_indexes)
960
965
 
961
- return TaskInfo(**response.json())
966
+ return TaskInfo(**self._http_requests.parse_json(response))
962
967
 
963
968
  async def get_batch(self, batch_uid: int) -> BatchResult | None:
964
969
  return await async_get_batch(self, batch_uid)
@@ -1251,7 +1256,7 @@ class AsyncClient(BaseClient):
1251
1256
 
1252
1257
  response = await self._http_requests.post(url, body=payload)
1253
1258
 
1254
- return TaskInfo(**response.json())
1259
+ return TaskInfo(**self._http_requests.parse_json(response))
1255
1260
 
1256
1261
  async def get_experimental_features(self) -> dict[str, bool]:
1257
1262
  """Gets all experimental features and if they are enabled or not.
@@ -1271,7 +1276,7 @@ class AsyncClient(BaseClient):
1271
1276
  """
1272
1277
 
1273
1278
  response = await self._http_requests.get("/experimental-features")
1274
- return response.json()
1279
+ return self._http_requests.parse_json(response)
1275
1280
 
1276
1281
  async def update_experimental_features(self, features: dict[str, bool]) -> dict[str, bool]:
1277
1282
  """Update the status of an experimental feature.
@@ -1297,7 +1302,7 @@ class AsyncClient(BaseClient):
1297
1302
  payload = dict_to_camel(features)
1298
1303
  response = await self._http_requests.patch("/experimental-features", body=payload)
1299
1304
 
1300
- return response.json()
1305
+ return self._http_requests.parse_json(response)
1301
1306
 
1302
1307
 
1303
1308
  class Client(BaseClient):
@@ -1390,7 +1395,7 @@ class Client(BaseClient):
1390
1395
  "network", network.model_dump(by_alias=True, exclude_none=True)
1391
1396
  )
1392
1397
 
1393
- return Network(**response.json())
1398
+ return Network(**self._http_requests.parse_json(response))
1394
1399
 
1395
1400
  def get_networks(self) -> Network:
1396
1401
  """Fetches the remote-networks
@@ -1411,7 +1416,7 @@ class Client(BaseClient):
1411
1416
  """
1412
1417
  response = self._http_requests.get("network")
1413
1418
 
1414
- return Network(**response.json())
1419
+ return Network(**self._http_requests.parse_json(response))
1415
1420
 
1416
1421
  def get_webhooks(self) -> Webhooks:
1417
1422
  """Get all webhooks.
@@ -1430,7 +1435,7 @@ class Client(BaseClient):
1430
1435
  """
1431
1436
  response = self._http_requests.get("webhooks")
1432
1437
 
1433
- return Webhooks(**response.json())
1438
+ return Webhooks(**self._http_requests.parse_json(response))
1434
1439
 
1435
1440
  def get_webhook(self, uuid: str) -> Webhook:
1436
1441
  """Get a specific webhook by UUID.
@@ -1452,7 +1457,7 @@ class Client(BaseClient):
1452
1457
  """
1453
1458
  response = self._http_requests.get(f"webhooks/{uuid}")
1454
1459
 
1455
- return Webhook(**response.json())
1460
+ return Webhook(**self._http_requests.parse_json(response))
1456
1461
 
1457
1462
  def create_webhook(self, webhook: WebhookCreate) -> Webhook:
1458
1463
  """Create a new webhook.
@@ -1481,7 +1486,7 @@ class Client(BaseClient):
1481
1486
  "webhooks", webhook.model_dump(by_alias=True, exclude_none=True)
1482
1487
  )
1483
1488
 
1484
- return Webhook(**response.json())
1489
+ return Webhook(**self._http_requests.parse_json(response))
1485
1490
 
1486
1491
  def update_webhook(self, *, uuid: str, webhook: WebhookUpdate) -> Webhook:
1487
1492
  """Update an existing webhook.
@@ -1508,7 +1513,7 @@ class Client(BaseClient):
1508
1513
  f"webhooks/{uuid}", webhook.model_dump(by_alias=True, exclude_none=True)
1509
1514
  )
1510
1515
 
1511
- return Webhook(**response.json())
1516
+ return Webhook(**self._http_requests.parse_json(response))
1512
1517
 
1513
1518
  def delete_webhook(self, uuid: str) -> int:
1514
1519
  """Delete a webhook.
@@ -1548,7 +1553,7 @@ class Client(BaseClient):
1548
1553
  """
1549
1554
  response = self._http_requests.post("dumps")
1550
1555
 
1551
- return TaskInfo(**response.json())
1556
+ return TaskInfo(**self._http_requests.parse_json(response))
1552
1557
 
1553
1558
  def create_index(
1554
1559
  self,
@@ -1622,7 +1627,7 @@ class Client(BaseClient):
1622
1627
  """
1623
1628
  response = self._http_requests.post("snapshots")
1624
1629
 
1625
- return TaskInfo(**response.json())
1630
+ return TaskInfo(**self._http_requests.parse_json(response))
1626
1631
 
1627
1632
  def delete_index_if_exists(self, uid: str) -> bool:
1628
1633
  """Deletes an index if it already exists.
@@ -1643,7 +1648,9 @@ class Client(BaseClient):
1643
1648
  >>> client.delete_index_if_exists()
1644
1649
  """
1645
1650
  response = self._http_requests.delete(f"indexes/{uid}")
1646
- status = self.wait_for_task(response.json()["taskUid"], timeout_in_ms=100000)
1651
+ status = self.wait_for_task(
1652
+ self._http_requests.parse_json(response)["taskUid"], timeout_in_ms=100000
1653
+ )
1647
1654
  if status.status == "succeeded":
1648
1655
  return True
1649
1656
  return False
@@ -1673,7 +1680,7 @@ class Client(BaseClient):
1673
1680
  url = _build_offset_limit_url("indexes", offset, limit)
1674
1681
  response = self._http_requests.get(url)
1675
1682
 
1676
- if not response.json()["results"]:
1683
+ if not self._http_requests.parse_json(response)["results"]:
1677
1684
  return None
1678
1685
 
1679
1686
  return [
@@ -1685,7 +1692,7 @@ class Client(BaseClient):
1685
1692
  updated_at=x["updatedAt"],
1686
1693
  json_handler=self.json_handler,
1687
1694
  )
1688
- for x in response.json()["results"]
1695
+ for x in self._http_requests.parse_json(response)["results"]
1689
1696
  ]
1690
1697
 
1691
1698
  def get_index(self, uid: str) -> Index:
@@ -1747,7 +1754,7 @@ class Client(BaseClient):
1747
1754
  """
1748
1755
  response = self._http_requests.get("stats")
1749
1756
 
1750
- return ClientStats(**response.json())
1757
+ return ClientStats(**self._http_requests.parse_json(response))
1751
1758
 
1752
1759
  def get_or_create_index(
1753
1760
  self,
@@ -1818,7 +1825,7 @@ class Client(BaseClient):
1818
1825
  "keys", self.json_handler.loads(key.model_dump_json(by_alias=True))
1819
1826
  ) # type: ignore[attr-defined]
1820
1827
 
1821
- return Key(**response.json())
1828
+ return Key(**self._http_requests.parse_json(response))
1822
1829
 
1823
1830
  def delete_key(self, key: str) -> int:
1824
1831
  """Deletes an API key.
@@ -1864,7 +1871,7 @@ class Client(BaseClient):
1864
1871
  url = _build_offset_limit_url("keys", offset, limit)
1865
1872
  response = self._http_requests.get(url)
1866
1873
 
1867
- return KeySearch(**response.json())
1874
+ return KeySearch(**self._http_requests.parse_json(response))
1868
1875
 
1869
1876
  def get_key(self, key: str) -> Key:
1870
1877
  """Gets information about a specific API key.
@@ -1886,7 +1893,7 @@ class Client(BaseClient):
1886
1893
  """
1887
1894
  response = self._http_requests.get(f"keys/{key}")
1888
1895
 
1889
- return Key(**response.json())
1896
+ return Key(**self._http_requests.parse_json(response))
1890
1897
 
1891
1898
  def update_key(self, key: KeyUpdate) -> Key:
1892
1899
  """Update an API key.
@@ -1915,7 +1922,7 @@ class Client(BaseClient):
1915
1922
  payload = _build_update_key_payload(key, self.json_handler)
1916
1923
  response = self._http_requests.patch(f"keys/{key.key}", payload)
1917
1924
 
1918
- return Key(**response.json())
1925
+ return Key(**self._http_requests.parse_json(response))
1919
1926
 
1920
1927
  def multi_search(
1921
1928
  self,
@@ -1982,10 +1989,13 @@ class Client(BaseClient):
1982
1989
  )
1983
1990
 
1984
1991
  if federation:
1985
- results = response.json()
1992
+ results = self._http_requests.parse_json(response)
1986
1993
  return SearchResultsFederated[hits_type](**results)
1987
1994
 
1988
- return [SearchResultsWithUID[hits_type](**x) for x in response.json()["results"]]
1995
+ return [
1996
+ SearchResultsWithUID[hits_type](**x)
1997
+ for x in self._http_requests.parse_json(response)["results"]
1998
+ ]
1989
1999
 
1990
2000
  def get_raw_index(self, uid: str) -> IndexInfo | None:
1991
2001
  """Gets the index and returns all the index information rather than an Index instance.
@@ -2010,7 +2020,7 @@ class Client(BaseClient):
2010
2020
  if response.status_code == 404:
2011
2021
  return None
2012
2022
 
2013
- return IndexInfo(**response.json())
2023
+ return IndexInfo(**self._http_requests.parse_json(response))
2014
2024
 
2015
2025
  def get_raw_indexes(
2016
2026
  self, *, offset: int | None = None, limit: int | None = None
@@ -2039,10 +2049,10 @@ class Client(BaseClient):
2039
2049
  url = _build_offset_limit_url("indexes", offset, limit)
2040
2050
  response = self._http_requests.get(url)
2041
2051
 
2042
- if not response.json()["results"]:
2052
+ if not self._http_requests.parse_json(response)["results"]:
2043
2053
  return None
2044
2054
 
2045
- return [IndexInfo(**x) for x in response.json()["results"]]
2055
+ return [IndexInfo(**x) for x in self._http_requests.parse_json(response)["results"]]
2046
2056
 
2047
2057
  def get_version(self) -> Version:
2048
2058
  """Get the Meilisearch version.
@@ -2061,7 +2071,7 @@ class Client(BaseClient):
2061
2071
  """
2062
2072
  response = self._http_requests.get("version")
2063
2073
 
2064
- return Version(**response.json())
2074
+ return Version(**self._http_requests.parse_json(response))
2065
2075
 
2066
2076
  def health(self) -> Health:
2067
2077
  """Get health of the Meilisearch server.
@@ -2080,7 +2090,7 @@ class Client(BaseClient):
2080
2090
  """
2081
2091
  response = self._http_requests.get("health")
2082
2092
 
2083
- return Health(**response.json())
2093
+ return Health(**self._http_requests.parse_json(response))
2084
2094
 
2085
2095
  def swap_indexes(self, indexes: list[tuple[str, str]], rename: bool = False) -> TaskInfo:
2086
2096
  """Swap two indexes.
@@ -2108,7 +2118,7 @@ class Client(BaseClient):
2108
2118
  processed_indexes = [{"indexes": x} for x in indexes]
2109
2119
  response = self._http_requests.post("swap-indexes", processed_indexes)
2110
2120
 
2111
- return TaskInfo(**response.json())
2121
+ return TaskInfo(**self._http_requests.parse_json(response))
2112
2122
 
2113
2123
  def get_batch(self, batch_uid: int) -> BatchResult | None:
2114
2124
  return _get_batch(self, batch_uid)
@@ -2396,7 +2406,7 @@ class Client(BaseClient):
2396
2406
 
2397
2407
  response = self._http_requests.post(url, body=payload)
2398
2408
 
2399
- return TaskInfo(**response.json())
2409
+ return TaskInfo(**self._http_requests.parse_json(response))
2400
2410
 
2401
2411
  def get_experimental_features(self) -> dict[str, bool]:
2402
2412
  """Gets all experimental features and if they are enabled or not.
@@ -2416,7 +2426,7 @@ class Client(BaseClient):
2416
2426
  """
2417
2427
 
2418
2428
  response = self._http_requests.get("/experimental-features")
2419
- return response.json()
2429
+ return self._http_requests.parse_json(response)
2420
2430
 
2421
2431
  def update_experimental_features(self, features: dict[str, bool]) -> dict[str, bool]:
2422
2432
  """Update the status of an experimental feature.
@@ -2442,7 +2452,7 @@ class Client(BaseClient):
2442
2452
  payload = dict_to_camel(features)
2443
2453
  response = self._http_requests.patch("/experimental-features", body=payload)
2444
2454
 
2445
- return response.json()
2455
+ return self._http_requests.parse_json(response)
2446
2456
 
2447
2457
 
2448
2458
  def _build_offset_limit_url(base: str, offset: int | None, limit: int | None) -> str:
@@ -31,6 +31,10 @@ class AsyncHttpRequests:
31
31
  self.http_client = http_client
32
32
  self.json_handler = json_handler
33
33
 
34
+ def parse_json(self, response: Response) -> Any:
35
+ """Parse JSON response using the custom json_handler."""
36
+ return self.json_handler.loads(response.content)
37
+
34
38
  async def _send_request(
35
39
  self,
36
40
  http_method: Callable,
@@ -112,6 +116,10 @@ class HttpRequests:
112
116
  self.http_client = http_client
113
117
  self.json_handler = json_handler
114
118
 
119
+ def parse_json(self, response: Response) -> Any:
120
+ """Parse JSON response using the custom json_handler."""
121
+ return self.json_handler.loads(response.content)
122
+
115
123
  def _send_request(
116
124
  self,
117
125
  http_method: Callable,