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.
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.github/workflows/docs_publish.yml +1 -1
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.github/workflows/nightly_testing.yml +1 -1
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.github/workflows/pypi_publish.yml +1 -1
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.github/workflows/testing.yml +7 -7
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.pre-commit-config.yaml +1 -1
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/PKG-INFO +1 -1
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/_client.py +95 -2
- meilisearch_python_sdk-5.5.0/meilisearch_python_sdk/_version.py +1 -0
- meilisearch_python_sdk-5.5.0/meilisearch_python_sdk/index/__init__.py +4 -0
- meilisearch_python_sdk-5.5.0/meilisearch_python_sdk/index/_common.py +296 -0
- 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
- meilisearch_python_sdk-5.5.0/meilisearch_python_sdk/index/index.py +3839 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/task.py +2 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/pyproject.toml +5 -5
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_async_client.py +8 -1
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_async_documents.py +143 -2
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_client.py +8 -1
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_documents.py +139 -2
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_index.py +3 -3
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/uv.lock +282 -278
- meilisearch_python_sdk-5.3.0/meilisearch_python_sdk/_version.py +0 -1
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.github/FUNDING.yml +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.github/release-draft-template.yaml +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.github/renovate.json5 +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.github/workflows/release-drafter.yml +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/.gitignore +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/CONTRIBUTING.md +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/LICENSE +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/README.md +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/assets/add_in_batches.png +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/assets/searches.png +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/codecov.yml +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/datasets/small_movies.json +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docker-compose.https.yml +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docker-compose.yml +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/.nojekyll +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/CNAME +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/async_client_api.md +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/async_index_api.md +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/client_api.md +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/css/custom.css +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/decorators_api.md +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/index.md +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/index_api.md +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/js/umami.js +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/json_handler.md +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/overrides/partials/footer.html +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/plugins.md +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/docs/pydantic.md +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/.gitignore +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/README.md +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/__init__.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/add_documents_decorator.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/add_documents_in_batches.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/async_add_documents_decorator.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/async_add_documents_in_batches.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/async_documents_and_search_results.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/async_search_tracker.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/async_update_settings.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/documents_and_search_results.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/fastapi_example.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/orjson_example.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/pyproject.toml +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/requirements.txt +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/search_tracker.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/tests/__init__.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/tests/conftest.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/tests/test_async_examples.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/tests/test_examples.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/ujson_example.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/examples/update_settings.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/justfile +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/__init__.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/_batch.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/_http_requests.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/_task.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/_utils.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/decorators.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/errors.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/json_handler.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/__init__.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/batch.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/client.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/documents.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/health.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/index.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/search.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/settings.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/version.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/models/webhook.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/plugins.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/py.typed +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/types.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/mkdocs.yaml +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/__init__.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/conftest.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_async_index.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_async_index_plugins.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_async_search.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_decorators.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_errors.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_index_plugins.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_search.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_settings_models.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_utils.py +0 -0
- {meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/tests/test_version.py +0 -0
|
@@ -11,7 +11,7 @@ jobs:
|
|
|
11
11
|
linting:
|
|
12
12
|
runs-on: ubuntu-latest
|
|
13
13
|
steps:
|
|
14
|
-
- uses: actions/checkout@
|
|
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@
|
|
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@
|
|
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@
|
|
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@
|
|
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@
|
|
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@
|
|
190
|
+
- uses: actions/checkout@v6
|
|
191
191
|
- name: install Just
|
|
192
192
|
uses: taiki-e/install-action@just
|
|
193
193
|
- name: Install uv
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meilisearch-python-sdk
|
|
3
|
-
Version: 5.
|
|
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
|
{meilisearch_python_sdk-5.3.0 → meilisearch_python_sdk-5.5.0}/meilisearch_python_sdk/_client.py
RENAMED
|
@@ -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
|
|
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
|
|
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,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")
|