meilisearch-python-sdk 5.3.0__tar.gz → 5.5.0__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.3.0 → meilisearch_python_sdk-5.5.0}/.github/workflows/docs_publish.yml +1 -1
  2. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.github/workflows/nightly_testing.yml +1 -1
  3. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.github/workflows/pypi_publish.yml +1 -1
  4. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.github/workflows/testing.yml +7 -7
  5. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.pre-commit-config.yaml +1 -1
  6. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/PKG-INFO +1 -1
  7. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/_client.py +95 -2
  8. meilisearch_python_sdk-5.5.0/meilisearch_python_sdk/_version.py +1 -0
  9. meilisearch_python_sdk-5.5.0/meilisearch_python_sdk/index/__init__.py +4 -0
  10. meilisearch_python_sdk-5.5.0/meilisearch_python_sdk/index/_common.py +296 -0
  11. meilisearch_python_sdk-5.3.0/meilisearch_python_sdk/index.py → meilisearch_python_sdk-5.5.0/meilisearch_python_sdk/index/async_index.py +328 -4056
  12. meilisearch_python_sdk-5.5.0/meilisearch_python_sdk/index/index.py +3839 -0
  13. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/task.py +2 -0
  14. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/pyproject.toml +5 -5
  15. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_async_client.py +8 -1
  16. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_async_documents.py +143 -2
  17. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_client.py +8 -1
  18. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_documents.py +139 -2
  19. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_index.py +3 -3
  20. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/uv.lock +282 -278
  21. meilisearch_python_sdk-5.3.0/meilisearch_python_sdk/_version.py +0 -1
  22. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.github/FUNDING.yml +0 -0
  23. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.github/release-draft-template.yaml +0 -0
  24. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.github/renovate.json5 +0 -0
  25. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.github/workflows/release-drafter.yml +0 -0
  26. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.gitignore +0 -0
  27. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/CONTRIBUTING.md +0 -0
  28. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/LICENSE +0 -0
  29. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/README.md +0 -0
  30. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/assets/add_in_batches.png +0 -0
  31. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/assets/searches.png +0 -0
  32. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/codecov.yml +0 -0
  33. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/datasets/small_movies.json +0 -0
  34. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docker-compose.https.yml +0 -0
  35. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docker-compose.yml +0 -0
  36. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/.nojekyll +0 -0
  37. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/CNAME +0 -0
  38. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/async_client_api.md +0 -0
  39. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/async_index_api.md +0 -0
  40. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/client_api.md +0 -0
  41. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/css/custom.css +0 -0
  42. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/decorators_api.md +0 -0
  43. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/index.md +0 -0
  44. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/index_api.md +0 -0
  45. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/js/umami.js +0 -0
  46. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/json_handler.md +0 -0
  47. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/overrides/partials/footer.html +0 -0
  48. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/plugins.md +0 -0
  49. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/pydantic.md +0 -0
  50. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/.gitignore +0 -0
  51. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/README.md +0 -0
  52. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/__init__.py +0 -0
  53. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/add_documents_decorator.py +0 -0
  54. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/add_documents_in_batches.py +0 -0
  55. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/async_add_documents_decorator.py +0 -0
  56. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/async_add_documents_in_batches.py +0 -0
  57. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/async_documents_and_search_results.py +0 -0
  58. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/async_search_tracker.py +0 -0
  59. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/async_update_settings.py +0 -0
  60. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/documents_and_search_results.py +0 -0
  61. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/fastapi_example.py +0 -0
  62. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/orjson_example.py +0 -0
  63. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/pyproject.toml +0 -0
  64. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/requirements.txt +0 -0
  65. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/search_tracker.py +0 -0
  66. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/tests/__init__.py +0 -0
  67. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/tests/conftest.py +0 -0
  68. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/tests/test_async_examples.py +0 -0
  69. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/tests/test_examples.py +0 -0
  70. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/ujson_example.py +0 -0
  71. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/update_settings.py +0 -0
  72. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/justfile +0 -0
  73. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/__init__.py +0 -0
  74. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/_batch.py +0 -0
  75. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/_http_requests.py +0 -0
  76. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/_task.py +0 -0
  77. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/_utils.py +0 -0
  78. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/decorators.py +0 -0
  79. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/errors.py +0 -0
  80. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/json_handler.py +0 -0
  81. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/__init__.py +0 -0
  82. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/batch.py +0 -0
  83. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/client.py +0 -0
  84. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/documents.py +0 -0
  85. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/health.py +0 -0
  86. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/index.py +0 -0
  87. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/search.py +0 -0
  88. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/settings.py +0 -0
  89. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/version.py +0 -0
  90. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/webhook.py +0 -0
  91. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/plugins.py +0 -0
  92. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/py.typed +0 -0
  93. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/types.py +0 -0
  94. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/mkdocs.yaml +0 -0
  95. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/__init__.py +0 -0
  96. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/conftest.py +0 -0
  97. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_async_index.py +0 -0
  98. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_async_index_plugins.py +0 -0
  99. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_async_search.py +0 -0
  100. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_decorators.py +0 -0
  101. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_errors.py +0 -0
  102. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_index_plugins.py +0 -0
  103. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_search.py +0 -0
  104. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_settings_models.py +0 -0
  105. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_utils.py +0 -0
  106. {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_version.py +0 -0
@@ -10,7 +10,7 @@ jobs:
10
10
  deploy:
11
11
  runs-on: ubuntu-latest
12
12
  steps:
13
- - uses: actions/checkout@v5
13
+ - uses: actions/checkout@v6
14
14
  - name: Install uv
15
15
  uses: astral-sh/setup-uv@v7
16
16
  with:
@@ -12,7 +12,7 @@ jobs:
12
12
  fail-fast: false
13
13
  runs-on: ubuntu-latest
14
14
  steps:
15
- - uses: actions/checkout@v5
15
+ - uses: actions/checkout@v6
16
16
  - name: Install uv
17
17
  uses: astral-sh/setup-uv@v7
18
18
  with:
@@ -12,7 +12,7 @@ jobs:
12
12
  # For PyPI's trusted publishing.
13
13
  id-token: write
14
14
  steps:
15
- - uses: actions/checkout@v5
15
+ - uses: actions/checkout@v6
16
16
  - name: Install uv
17
17
  uses: astral-sh/setup-uv@v7
18
18
  with:
@@ -11,7 +11,7 @@ jobs:
11
11
  linting:
12
12
  runs-on: ubuntu-latest
13
13
  steps:
14
- - uses: actions/checkout@v5
14
+ - uses: actions/checkout@v6
15
15
  - name: install Just
16
16
  uses: taiki-e/install-action@just
17
17
  - name: Install uv
@@ -35,7 +35,7 @@ jobs:
35
35
  python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
36
36
  runs-on: ubuntu-latest
37
37
  steps:
38
- - uses: actions/checkout@v5
38
+ - uses: actions/checkout@v6
39
39
  - name: install Just
40
40
  uses: taiki-e/install-action@just
41
41
  - name: Install uv
@@ -64,7 +64,7 @@ jobs:
64
64
  python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
65
65
  runs-on: ubuntu-latest
66
66
  steps:
67
- - uses: actions/checkout@v5
67
+ - uses: actions/checkout@v6
68
68
  - name: install Just
69
69
  uses: taiki-e/install-action@just
70
70
  - name: Install uv
@@ -104,7 +104,7 @@ jobs:
104
104
  python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
105
105
  runs-on: ubuntu-latest
106
106
  steps:
107
- - uses: actions/checkout@v5
107
+ - uses: actions/checkout@v6
108
108
  - name: install Just
109
109
  uses: taiki-e/install-action@just
110
110
  - name: Install uv
@@ -133,7 +133,7 @@ jobs:
133
133
  python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
134
134
  runs-on: ubuntu-latest
135
135
  steps:
136
- - uses: actions/checkout@v5
136
+ - uses: actions/checkout@v6
137
137
  - name: install Just
138
138
  uses: taiki-e/install-action@just
139
139
  - name: Install uv
@@ -172,7 +172,7 @@ jobs:
172
172
  python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
173
173
  runs-on: ubuntu-latest
174
174
  steps:
175
- - uses: actions/checkout@v5
175
+ - uses: actions/checkout@v6
176
176
  - name: install Just
177
177
  uses: taiki-e/install-action@just
178
178
  - name: Set up Python ${{ matrix.python-version }}
@@ -187,7 +187,7 @@ jobs:
187
187
  docs:
188
188
  runs-on: ubuntu-latest
189
189
  steps:
190
- - uses: actions/checkout@v5
190
+ - uses: actions/checkout@v6
191
191
  - name: install Just
192
192
  uses: taiki-e/install-action@just
193
193
  - name: Install uv
@@ -14,7 +14,7 @@ repos:
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.2
17
+ rev: v0.14.5
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.3.0
3
+ Version: 5.5.0
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
@@ -5,6 +5,7 @@ from ssl import SSLContext
5
5
  from typing import TYPE_CHECKING, Any
6
6
 
7
7
  import jwt
8
+ from camel_converter import dict_to_camel
8
9
  from httpx import AsyncClient as HttpxAsyncClient
9
10
  from httpx import Client as HttpxClient
10
11
 
@@ -1189,7 +1190,7 @@ class AsyncClient(BaseClient):
1189
1190
  >>> {"id": 1, "title": "Movie 1", "genre": "comedy"},
1190
1191
  >>> {"id": 2, "title": "Movie 2", "genre": "drama"},
1191
1192
  >>> ]
1192
- >>> async with Client("http://localhost.com", "masterKey") as client:
1193
+ >>> async with AsyncClient("http://localhost.com", "masterKey") as client:
1193
1194
  >>> index = client.index("movies")
1194
1195
  >>> response = await index.add_documents(documents)
1195
1196
  >>> await client.wait_for_task(client, response.update_id)
@@ -1232,7 +1233,7 @@ class AsyncClient(BaseClient):
1232
1233
 
1233
1234
  Examples
1234
1235
  >>> from meilisearch_python_sdk import AsyncClient
1235
- >>> async with Client("http://localhost.com", "masterKey") as client:
1236
+ >>> async with AsyncClient("http://localhost.com", "masterKey") as client:
1236
1237
  >>> await index.transfer_documents(
1237
1238
  >>> "https://another-instance.com", api_key="otherMasterKey"
1238
1239
  >>> )
@@ -1252,6 +1253,52 @@ class AsyncClient(BaseClient):
1252
1253
 
1253
1254
  return TaskInfo(**response.json())
1254
1255
 
1256
+ async def get_experimental_features(self) -> dict[str, bool]:
1257
+ """Gets all experimental features and if they are enabled or not.
1258
+
1259
+ Returns:
1260
+ The status of the experimental features.
1261
+
1262
+ Raises:
1263
+ MeilisearchCommunicationError: If there was an error communicating with the server.
1264
+ MeilisearchApiError: If the Meilisearch API returned an error.
1265
+ MeilisearchTimeoutError: If the connection times out.
1266
+
1267
+ Examples
1268
+ >>> from meilisearch_python_sdk import AsyncClient
1269
+ >>> async with AsyncClient("http://localhost.com", "masterKey") as client:
1270
+ >>> await index.get_experimental_feature()
1271
+ """
1272
+
1273
+ response = await self._http_requests.get("/experimental-features")
1274
+ return response.json()
1275
+
1276
+ async def update_experimental_features(self, features: dict[str, bool]) -> dict[str, bool]:
1277
+ """Update the status of an experimental feature.
1278
+
1279
+ Args:
1280
+ features: Dictionary of features to enable/disable. The dictionary keys can be in either
1281
+ camel case or snake case, the conversion to the correct type will be handed for you by
1282
+ the program. For example {"logsRoute": True} and {"logs_route": True} will both work.
1283
+
1284
+ Returns:
1285
+ The status of the experimental features.
1286
+
1287
+ Raises:
1288
+ MeilisearchCommunicationError: If there was an error communicating with the server.
1289
+ MeilisearchApiError: If the Meilisearch API returned an error.
1290
+ MeilisearchTimeoutError: If the connection times out.
1291
+
1292
+ Examples
1293
+ >>> from meilisearch_python_sdk import AsyncClient
1294
+ >>> async with AsyncClient("http://localhost.com", "masterKey") as client:
1295
+ >>> await index.update_experimental_features({"logsRoute": True})
1296
+ """
1297
+ payload = dict_to_camel(features)
1298
+ response = await self._http_requests.patch("/experimental-features", body=payload)
1299
+
1300
+ return response.json()
1301
+
1255
1302
 
1256
1303
  class Client(BaseClient):
1257
1304
  """client to connect to the Meilisearch API."""
@@ -2351,6 +2398,52 @@ class Client(BaseClient):
2351
2398
 
2352
2399
  return TaskInfo(**response.json())
2353
2400
 
2401
+ def get_experimental_features(self) -> dict[str, bool]:
2402
+ """Gets all experimental features and if they are enabled or not.
2403
+
2404
+ Returns:
2405
+ The status of the experimental features.
2406
+
2407
+ Raises:
2408
+ MeilisearchCommunicationError: If there was an error communicating with the server.
2409
+ MeilisearchApiError: If the Meilisearch API returned an error.
2410
+ MeilisearchTimeoutError: If the connection times out.
2411
+
2412
+ Examples
2413
+ >>> from meilisearch_python_sdk import Client
2414
+ >>> with Client("http://localhost.com", "masterKey") as client:
2415
+ >>> index.get_experimental_feature()
2416
+ """
2417
+
2418
+ response = self._http_requests.get("/experimental-features")
2419
+ return response.json()
2420
+
2421
+ def update_experimental_features(self, features: dict[str, bool]) -> dict[str, bool]:
2422
+ """Update the status of an experimental feature.
2423
+
2424
+ Args:
2425
+ features: Dictionary of features to enable/disable. The dictionary keys can be in either
2426
+ camel case or snake case, the conversion to the correct type will be handed for you by
2427
+ the program. For example {"logsRoute": True} and {"logs_route": True} will both work.
2428
+
2429
+ Returns:
2430
+ The status of the experimental features.
2431
+
2432
+ Raises:
2433
+ MeilisearchCommunicationError: If there was an error communicating with the server.
2434
+ MeilisearchApiError: If the Meilisearch API returned an error.
2435
+ MeilisearchTimeoutError: If the connection times out.
2436
+
2437
+ Examples
2438
+ >>> from meilisearch_python_sdk import Client
2439
+ >>> with Client("http://localhost.com", "masterKey") as client:
2440
+ >>> index.update_experimental_features({"logsRoute": True})
2441
+ """
2442
+ payload = dict_to_camel(features)
2443
+ response = self._http_requests.patch("/experimental-features", body=payload)
2444
+
2445
+ return response.json()
2446
+
2354
2447
 
2355
2448
  def _build_offset_limit_url(base: str, offset: int | None, limit: int | None) -> str:
2356
2449
  if offset is not None and limit is not None:
@@ -0,0 +1 @@
1
+ VERSION = "5.5.0"
@@ -0,0 +1,4 @@
1
+ from meilisearch_python_sdk.index.async_index import AsyncIndex
2
+ from meilisearch_python_sdk.index.index import Index
3
+
4
+ __all__ = ["AsyncIndex", "Index"]
@@ -0,0 +1,296 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Generator, MutableMapping, Sequence
4
+ from datetime import datetime
5
+ from pathlib import Path
6
+ from typing import TYPE_CHECKING, Any, Literal
7
+ from urllib.parse import urlencode
8
+
9
+ from meilisearch_python_sdk._utils import iso_to_date_time
10
+ from meilisearch_python_sdk.errors import MeilisearchError
11
+ from meilisearch_python_sdk.json_handler import BuiltinHandler, OrjsonHandler, UjsonHandler
12
+ from meilisearch_python_sdk.models.search import (
13
+ Hybrid,
14
+ )
15
+ from meilisearch_python_sdk.models.settings import (
16
+ CompositeEmbedder,
17
+ Embedders,
18
+ HuggingFaceEmbedder,
19
+ OllamaEmbedder,
20
+ OpenAiEmbedder,
21
+ RestEmbedder,
22
+ UserProvidedEmbedder,
23
+ )
24
+ from meilisearch_python_sdk.plugins import (
25
+ AsyncDocumentPlugin,
26
+ AsyncPlugin,
27
+ AsyncPostSearchPlugin,
28
+ DocumentPlugin,
29
+ Plugin,
30
+ PostSearchPlugin,
31
+ )
32
+ from meilisearch_python_sdk.types import JsonDict
33
+
34
+ if TYPE_CHECKING: # pragma: no cover
35
+ import sys
36
+
37
+ from meilisearch_python_sdk.types import Filter, JsonMapping
38
+
39
+ if sys.version_info >= (3, 11):
40
+ pass
41
+ else:
42
+ pass
43
+
44
+
45
+ class BaseIndex:
46
+ def __init__(
47
+ self,
48
+ uid: str,
49
+ primary_key: str | None = None,
50
+ created_at: str | datetime | None = None,
51
+ updated_at: str | datetime | None = None,
52
+ json_handler: BuiltinHandler | OrjsonHandler | UjsonHandler | None = None,
53
+ hits_type: Any = JsonDict,
54
+ ):
55
+ self.uid = uid
56
+ self.primary_key = primary_key
57
+ self.created_at: datetime | None = iso_to_date_time(created_at)
58
+ self.updated_at: datetime | None = iso_to_date_time(updated_at)
59
+ self.hits_type = hits_type
60
+ self._base_url = "indexes/"
61
+ self._base_url_with_uid = f"{self._base_url}{self.uid}"
62
+ self._documents_url = f"{self._base_url_with_uid}/documents"
63
+ self._stats_url = f"{self._base_url_with_uid}/stats"
64
+ self._settings_url = f"{self._base_url_with_uid}/settings"
65
+ self._json_handler = json_handler if json_handler else BuiltinHandler()
66
+
67
+ def __str__(self) -> str:
68
+ return f"{type(self).__name__}(uid={self.uid}, primary_key={self.primary_key}, created_at={self.created_at}, updated_at={self.updated_at})"
69
+
70
+ def __repr__(self) -> str:
71
+ return f"{type(self).__name__}(uid={self.uid!r}, primary_key={self.primary_key!r}, created_at={self.created_at!r}, updated_at={self.updated_at!r})"
72
+
73
+ def _set_fetch_info(
74
+ self, primary_key: str, created_at_iso_str: str, updated_at_iso_str: str
75
+ ) -> None:
76
+ self.primary_key = primary_key
77
+ self.created_at = iso_to_date_time(created_at_iso_str)
78
+ self.updated_at = iso_to_date_time(updated_at_iso_str)
79
+
80
+
81
+ def batch(
82
+ documents: Sequence[MutableMapping], batch_size: int
83
+ ) -> Generator[Sequence[MutableMapping], None, None]:
84
+ total_len = len(documents)
85
+ for i in range(0, total_len, batch_size):
86
+ yield documents[i : i + batch_size]
87
+
88
+
89
+ def combine_documents(documents: list[list[Any]]) -> list[Any]:
90
+ return [x for y in documents for x in y]
91
+
92
+
93
+ def plugin_has_method(
94
+ plugin: AsyncPlugin
95
+ | AsyncDocumentPlugin
96
+ | AsyncPostSearchPlugin
97
+ | Plugin
98
+ | DocumentPlugin
99
+ | PostSearchPlugin,
100
+ method: str,
101
+ ) -> bool:
102
+ check = getattr(plugin, method, None)
103
+ if callable(check):
104
+ return True
105
+
106
+ return False
107
+
108
+
109
+ def raise_on_no_documents(
110
+ documents: list[Any], document_type: str, directory_path: str | Path
111
+ ) -> None:
112
+ if not documents:
113
+ raise MeilisearchError(f"No {document_type} files found in {directory_path}")
114
+
115
+
116
+ def process_search_parameters(
117
+ *,
118
+ q: str | None = None,
119
+ facet_name: str | None = None,
120
+ facet_query: str | None = None,
121
+ offset: int = 0,
122
+ limit: int = 20,
123
+ filter: Filter | None = None,
124
+ facets: list[str] | None = None,
125
+ attributes_to_retrieve: list[str] | None = None,
126
+ attributes_to_crop: list[str] | None = None,
127
+ crop_length: int = 200,
128
+ attributes_to_highlight: list[str] | None = None,
129
+ sort: list[str] | None = None,
130
+ show_matches_position: bool = False,
131
+ highlight_pre_tag: str = "<em>",
132
+ highlight_post_tag: str = "</em>",
133
+ crop_marker: str = "...",
134
+ matching_strategy: Literal["all", "last", "frequency"] = "last",
135
+ hits_per_page: int | None = None,
136
+ page: int | None = None,
137
+ attributes_to_search_on: list[str] | None = None,
138
+ distinct: str | None = None,
139
+ show_ranking_score: bool = False,
140
+ show_ranking_score_details: bool = False,
141
+ ranking_score_threshold: float | None = None,
142
+ vector: list[float] | None = None,
143
+ hybrid: Hybrid | None = None,
144
+ locales: list[str] | None = None,
145
+ retrieve_vectors: bool | None = None,
146
+ exhaustive_facet_count: bool | None = None,
147
+ media: JsonMapping | None = None,
148
+ ) -> JsonDict:
149
+ if attributes_to_retrieve is None:
150
+ attributes_to_retrieve = ["*"]
151
+
152
+ body: JsonDict = {
153
+ "q": q,
154
+ "offset": offset,
155
+ "limit": limit,
156
+ "filter": filter,
157
+ "facets": facets,
158
+ "attributesToRetrieve": attributes_to_retrieve,
159
+ "attributesToCrop": attributes_to_crop,
160
+ "cropLength": crop_length,
161
+ "attributesToHighlight": attributes_to_highlight,
162
+ "sort": sort,
163
+ "showMatchesPosition": show_matches_position,
164
+ "highlightPreTag": highlight_pre_tag,
165
+ "highlightPostTag": highlight_post_tag,
166
+ "cropMarker": crop_marker,
167
+ "matchingStrategy": matching_strategy,
168
+ "hitsPerPage": hits_per_page,
169
+ "page": page,
170
+ "attributesToSearchOn": attributes_to_search_on,
171
+ "showRankingScore": show_ranking_score,
172
+ "rankingScoreThreshold": ranking_score_threshold,
173
+ }
174
+
175
+ if facet_name:
176
+ body["facetName"] = facet_name
177
+
178
+ if facet_query:
179
+ body["facetQuery"] = facet_query
180
+
181
+ if distinct:
182
+ body["distinct"] = distinct
183
+
184
+ if show_ranking_score_details:
185
+ body["showRankingScoreDetails"] = show_ranking_score_details
186
+
187
+ if vector:
188
+ body["vector"] = vector
189
+
190
+ if hybrid:
191
+ body["hybrid"] = hybrid.model_dump(by_alias=True)
192
+
193
+ if locales:
194
+ body["locales"] = locales
195
+
196
+ if retrieve_vectors is not None:
197
+ body["retrieveVectors"] = retrieve_vectors
198
+
199
+ if exhaustive_facet_count is not None:
200
+ body["exhaustivefacetCount"] = exhaustive_facet_count
201
+
202
+ if media is not None:
203
+ body["media"] = media
204
+
205
+ return body
206
+
207
+
208
+ def build_encoded_url(base_url: str, params: JsonMapping) -> str:
209
+ return f"{base_url}?{urlencode(params)}"
210
+
211
+
212
+ # TODO: Add back after embedder setting issue fixed https://github.com/meilisearch/meilisearch/issues/4585
213
+ def embedder_json_to_embedders_model( # pragma: no cover
214
+ embedder_json: JsonDict | None,
215
+ ) -> Embedders | None:
216
+ if not embedder_json: # pragma: no cover
217
+ return None
218
+
219
+ embedders: dict[
220
+ str,
221
+ OpenAiEmbedder
222
+ | HuggingFaceEmbedder
223
+ | OllamaEmbedder
224
+ | RestEmbedder
225
+ | UserProvidedEmbedder
226
+ | CompositeEmbedder,
227
+ ] = {}
228
+ for k, v in embedder_json.items():
229
+ if v.get("source") == "openAi":
230
+ embedders[k] = OpenAiEmbedder(**v)
231
+ elif v.get("source") == "huggingFace":
232
+ embedders[k] = HuggingFaceEmbedder(**v)
233
+ elif v.get("source") == "ollama":
234
+ embedders[k] = OllamaEmbedder(**v)
235
+ elif v.get("source") == "rest":
236
+ embedders[k] = RestEmbedder(**v)
237
+ elif v.get("source") == "composit":
238
+ embedders[k] = CompositeEmbedder(**v)
239
+ else:
240
+ embedders[k] = UserProvidedEmbedder(**v)
241
+
242
+ return Embedders(embedders=embedders)
243
+
244
+
245
+ # TODO: Add back after embedder setting issue fixed https://github.com/meilisearch/meilisearch/issues/4585
246
+ def embedder_json_to_settings_model( # pragma: no cover
247
+ embedder_json: JsonDict | None,
248
+ ) -> (
249
+ dict[
250
+ str,
251
+ OpenAiEmbedder
252
+ | HuggingFaceEmbedder
253
+ | OllamaEmbedder
254
+ | RestEmbedder
255
+ | UserProvidedEmbedder
256
+ | CompositeEmbedder,
257
+ ]
258
+ | None
259
+ ):
260
+ if not embedder_json: # pragma: no cover
261
+ return None
262
+
263
+ embedders: dict[
264
+ str,
265
+ OpenAiEmbedder
266
+ | HuggingFaceEmbedder
267
+ | OllamaEmbedder
268
+ | RestEmbedder
269
+ | UserProvidedEmbedder
270
+ | CompositeEmbedder,
271
+ ] = {}
272
+ for k, v in embedder_json.items():
273
+ if v.get("source") == "openAi":
274
+ embedders[k] = OpenAiEmbedder(**v)
275
+ elif v.get("source") == "huggingFace":
276
+ embedders[k] = HuggingFaceEmbedder(**v)
277
+ elif v.get("source") == "ollama":
278
+ embedders[k] = OllamaEmbedder(**v)
279
+ elif v.get("source") == "rest":
280
+ embedders[k] = RestEmbedder(**v)
281
+ elif v.get("source") == "composit":
282
+ embedders[k] = CompositeEmbedder(**v)
283
+ else:
284
+ embedders[k] = UserProvidedEmbedder(**v)
285
+
286
+ return embedders
287
+
288
+
289
+ def validate_file_type(file_path: Path) -> None:
290
+ if file_path.suffix not in (".json", ".csv", ".ndjson"):
291
+ raise MeilisearchError("File must be a json, ndjson, or csv file")
292
+
293
+
294
+ def validate_ranking_score_threshold(ranking_score_threshold: float) -> None:
295
+ if not 0.0 <= ranking_score_threshold <= 1.0:
296
+ raise MeilisearchError("ranking_score_threshold must be between 0.0 and 1.0")