meilisearch-python-sdk 6.0.0__tar.gz → 7.0.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-6.0.0 → meilisearch_python_sdk-7.0.0}/.github/workflows/testing.yml +8 -4
  2. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/.pre-commit-config.yaml +1 -1
  3. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/PKG-INFO +1 -1
  4. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/_client.py +9 -0
  5. meilisearch_python_sdk-7.0.0/meilisearch_python_sdk/_version.py +1 -0
  6. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/index/_common.py +4 -0
  7. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/index/async_index.py +45 -1
  8. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/index/index.py +45 -1
  9. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/models/index.py +59 -0
  10. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/models/search.py +2 -0
  11. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/pyproject.toml +3 -3
  12. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/tests/test_async_index.py +24 -0
  13. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/tests/test_async_search.py +24 -0
  14. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/tests/test_index.py +24 -0
  15. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/tests/test_search.py +24 -0
  16. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/uv.lock +242 -237
  17. meilisearch_python_sdk-6.0.0/meilisearch_python_sdk/_version.py +0 -1
  18. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/.github/FUNDING.yml +0 -0
  19. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/.github/release-draft-template.yaml +0 -0
  20. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/.github/renovate.json5 +0 -0
  21. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/.github/workflows/docs_publish.yml +0 -0
  22. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/.github/workflows/nightly_testing.yml +0 -0
  23. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/.github/workflows/pypi_publish.yml +0 -0
  24. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/.github/workflows/release-drafter.yml +0 -0
  25. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/.gitignore +0 -0
  26. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/CONTRIBUTING.md +0 -0
  27. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/LICENSE +0 -0
  28. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/README.md +0 -0
  29. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/assets/add_in_batches.png +0 -0
  30. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/assets/searches.png +0 -0
  31. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/codecov.yml +0 -0
  32. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/datasets/small_movies.json +0 -0
  33. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/docker-compose.https.yml +0 -0
  34. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/docker-compose.yml +0 -0
  35. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/docs/.nojekyll +0 -0
  36. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/docs/CNAME +0 -0
  37. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/docs/async_client_api.md +0 -0
  38. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/docs/async_index_api.md +0 -0
  39. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/docs/client_api.md +0 -0
  40. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/docs/css/custom.css +0 -0
  41. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/docs/decorators_api.md +0 -0
  42. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/docs/index.md +0 -0
  43. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/docs/index_api.md +0 -0
  44. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/docs/js/umami.js +0 -0
  45. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/docs/json_handler.md +0 -0
  46. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/docs/overrides/partials/footer.html +0 -0
  47. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/docs/plugins.md +0 -0
  48. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/docs/pydantic.md +0 -0
  49. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/.gitignore +0 -0
  50. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/README.md +0 -0
  51. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/__init__.py +0 -0
  52. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/add_documents_decorator.py +0 -0
  53. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/add_documents_in_batches.py +0 -0
  54. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/async_add_documents_decorator.py +0 -0
  55. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/async_add_documents_in_batches.py +0 -0
  56. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/async_documents_and_search_results.py +0 -0
  57. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/async_search_tracker.py +0 -0
  58. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/async_update_settings.py +0 -0
  59. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/documents_and_search_results.py +0 -0
  60. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/fastapi_example.py +0 -0
  61. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/orjson_example.py +0 -0
  62. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/pyproject.toml +0 -0
  63. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/requirements.txt +0 -0
  64. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/search_tracker.py +0 -0
  65. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/tests/__init__.py +0 -0
  66. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/tests/conftest.py +0 -0
  67. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/tests/test_async_examples.py +0 -0
  68. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/tests/test_examples.py +0 -0
  69. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/examples/update_settings.py +0 -0
  70. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/justfile +0 -0
  71. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/__init__.py +0 -0
  72. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/_batch.py +0 -0
  73. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/_http_requests.py +0 -0
  74. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/_task.py +0 -0
  75. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/_utils.py +0 -0
  76. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/decorators.py +0 -0
  77. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/errors.py +0 -0
  78. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/index/__init__.py +0 -0
  79. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/json_handler.py +0 -0
  80. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/models/__init__.py +0 -0
  81. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/models/batch.py +0 -0
  82. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/models/client.py +0 -0
  83. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/models/documents.py +0 -0
  84. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/models/health.py +0 -0
  85. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/models/settings.py +0 -0
  86. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/models/task.py +0 -0
  87. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/models/version.py +0 -0
  88. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/models/webhook.py +0 -0
  89. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/plugins.py +0 -0
  90. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/py.typed +0 -0
  91. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/meilisearch_python_sdk/types.py +0 -0
  92. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/mkdocs.yaml +0 -0
  93. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/tests/__init__.py +0 -0
  94. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/tests/conftest.py +0 -0
  95. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/tests/test_async_client.py +0 -0
  96. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/tests/test_async_documents.py +0 -0
  97. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/tests/test_async_index_plugins.py +0 -0
  98. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/tests/test_client.py +0 -0
  99. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/tests/test_decorators.py +0 -0
  100. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/tests/test_documents.py +0 -0
  101. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/tests/test_errors.py +0 -0
  102. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/tests/test_http_requests.py +0 -0
  103. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/tests/test_index_plugins.py +0 -0
  104. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/tests/test_settings_models.py +0 -0
  105. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/tests/test_utils.py +0 -0
  106. {meilisearch_python_sdk-6.0.0 → meilisearch_python_sdk-7.0.0}/tests/test_version.py +0 -0
@@ -53,8 +53,9 @@ jobs:
53
53
  run: just test-parallel-ci
54
54
  - name: Upload coverage
55
55
  uses: codecov/codecov-action@v5.5.2
56
+ env:
57
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
56
58
  with:
57
- token: ${{ secrets.CODECOV_TOKEN }}
58
59
  fail_ci_if_error: true
59
60
 
60
61
  parallel-testing-http2:
@@ -93,8 +94,9 @@ jobs:
93
94
  run: just test-parallel-ci-http2
94
95
  - name: Upload coverage
95
96
  uses: codecov/codecov-action@v5.5.2
97
+ env:
98
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
96
99
  with:
97
- token: ${{ secrets.CODECOV_TOKEN }}
98
100
  fail_ci_if_error: true
99
101
 
100
102
  no-parallel-testing:
@@ -122,8 +124,9 @@ jobs:
122
124
  run: just test-no-parallel-ci
123
125
  - name: Upload coverage
124
126
  uses: codecov/codecov-action@v5.5.2
127
+ env:
128
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
125
129
  with:
126
- token: ${{ secrets.CODECOV_TOKEN }}
127
130
  fail_ci_if_error: true
128
131
 
129
132
  no-parallel-testing-http2:
@@ -162,8 +165,9 @@ jobs:
162
165
  run: just test-no-parallel-ci-http2
163
166
  - name: Upload coverage
164
167
  uses: codecov/codecov-action@v5.5.2
168
+ env:
169
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
165
170
  with:
166
- token: ${{ secrets.CODECOV_TOKEN }}
167
171
  fail_ci_if_error: true
168
172
  example-testing:
169
173
  strategy:
@@ -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.11
17
+ rev: v0.14.14
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: 6.0.0
3
+ Version: 7.0.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
@@ -814,6 +814,9 @@ class AsyncClient(BaseClient):
814
814
  if query.media is None:
815
815
  del q["media"]
816
816
 
817
+ if query.show_performance_details is None:
818
+ del q["showPerformanceDetails"]
819
+
817
820
  processed_queries.append(q)
818
821
 
819
822
  if federation:
@@ -1970,6 +1973,12 @@ class Client(BaseClient):
1970
1973
  del q["limit"]
1971
1974
  del q["offset"]
1972
1975
 
1976
+ if query.media is None:
1977
+ del q["media"]
1978
+
1979
+ if query.show_performance_details is None:
1980
+ del q["showPerformanceDetails"]
1981
+
1973
1982
  processed_queries.append(q)
1974
1983
 
1975
1984
  if federation:
@@ -0,0 +1 @@
1
+ VERSION = "7.0.0"
@@ -140,6 +140,7 @@ def process_search_parameters(
140
140
  retrieve_vectors: bool | None = None,
141
141
  exhaustive_facet_count: bool | None = None,
142
142
  media: JsonMapping | None = None,
143
+ show_performance_details: bool = False,
143
144
  ) -> JsonDict:
144
145
  if attributes_to_retrieve is None:
145
146
  attributes_to_retrieve = ["*"]
@@ -197,6 +198,9 @@ def process_search_parameters(
197
198
  if media is not None:
198
199
  body["media"] = media
199
200
 
201
+ if show_performance_details:
202
+ body["showPerformanceDetails"] = True
203
+
200
204
  return body
201
205
 
202
206
 
@@ -31,7 +31,7 @@ from meilisearch_python_sdk.index._common import (
31
31
  from meilisearch_python_sdk.index._common import combine_documents as combine_documents_
32
32
  from meilisearch_python_sdk.json_handler import BuiltinHandler, OrjsonHandler
33
33
  from meilisearch_python_sdk.models.documents import DocumentsInfo
34
- from meilisearch_python_sdk.models.index import IndexStats
34
+ from meilisearch_python_sdk.models.index import Field, FieldResults, FieldsFilter, IndexStats
35
35
  from meilisearch_python_sdk.models.search import (
36
36
  FacetSearchResults,
37
37
  Hybrid,
@@ -712,6 +712,7 @@ class AsyncIndex(BaseIndex):
712
712
  locales: list[str] | None = None,
713
713
  retrieve_vectors: bool | None = None,
714
714
  media: JsonMapping | None = None,
715
+ show_performance_details: bool = False,
715
716
  ) -> SearchResults:
716
717
  """Search the index.
717
718
 
@@ -780,6 +781,8 @@ class AsyncIndex(BaseIndex):
780
781
  to /experimental-features with { "multimodal": true }. Because this feature is
781
782
  experimental it may be removed or updated causing breaking changes in this library
782
783
  without a major version bump so use with caution.
784
+ show_performance_details: When set to true, the search response contains a performance
785
+ trace. Default False.
783
786
 
784
787
  Returns:
785
788
  Results of the search
@@ -825,6 +828,7 @@ class AsyncIndex(BaseIndex):
825
828
  locales=locales,
826
829
  retrieve_vectors=retrieve_vectors,
827
830
  media=media,
831
+ show_performance_details=show_performance_details,
828
832
  )
829
833
  search_url = f"{self._base_url_with_uid}/search"
830
834
 
@@ -4815,6 +4819,46 @@ class AsyncIndex(BaseIndex):
4815
4819
 
4816
4820
  return TaskInfo(**self._http_requests.parse_json(response))
4817
4821
 
4822
+ async def fields(
4823
+ self, offset: int = 0, limit: int = 20, filter: FieldsFilter | None = None
4824
+ ) -> FieldResults:
4825
+ """Get the field properties on an index.
4826
+
4827
+ Args:
4828
+ offset: Number of fields to skip. Defaults to 0.
4829
+ limit: Maximum number of fields returned. Defaults to 20.
4830
+ filter: Filter fields to return based on properties. Defaults to None.
4831
+
4832
+ Returns:
4833
+ Field properties
4834
+
4835
+ Raises:
4836
+ MeilisearchCommunicationError: If there was an error communicating with the server.
4837
+ MeilisearchApiError: If the Meilisearch API returned an error.
4838
+
4839
+ Examples
4840
+ >>> from meilisearch_async_client import AsyncClient
4841
+ >>> async with AsyncClient("http://localhost.com", "masterKey") as client:
4842
+ >>> docs = [{"id": 1, "title": "Some Title}]
4843
+ >>> index = await client.index("movies")
4844
+ >>> await index.add_documents(docs)
4845
+ >>> fields = await index.fields()
4846
+ """
4847
+ filter_value = filter.model_dump(by_alias=True) if filter else None
4848
+ response = await self._http_requests.post(
4849
+ f"{self._base_url_with_uid}/fields",
4850
+ body={"offset": offset, "limit": limit, "filter": filter_value},
4851
+ )
4852
+ response_json = response.json()
4853
+ fields = [Field(**field) for field in response_json["results"]]
4854
+
4855
+ return FieldResults(
4856
+ fields=fields,
4857
+ offset=response_json["offset"],
4858
+ limit=response_json["limit"],
4859
+ total=response_json["total"],
4860
+ )
4861
+
4818
4862
  @staticmethod
4819
4863
  async def _run_plugins(
4820
4864
  plugins: Sequence[AsyncPlugin | AsyncDocumentPlugin | AsyncPostSearchPlugin],
@@ -28,7 +28,7 @@ from meilisearch_python_sdk.index._common import (
28
28
  from meilisearch_python_sdk.index._common import combine_documents as combine_documents_
29
29
  from meilisearch_python_sdk.json_handler import BuiltinHandler, OrjsonHandler
30
30
  from meilisearch_python_sdk.models.documents import DocumentsInfo
31
- from meilisearch_python_sdk.models.index import IndexStats
31
+ from meilisearch_python_sdk.models.index import Field, FieldResults, FieldsFilter, IndexStats
32
32
  from meilisearch_python_sdk.models.search import (
33
33
  FacetSearchResults,
34
34
  Hybrid,
@@ -586,6 +586,7 @@ class Index(BaseIndex):
586
586
  locales: list[str] | None = None,
587
587
  retrieve_vectors: bool | None = None,
588
588
  media: JsonMapping | None = None,
589
+ show_performance_details: bool = False,
589
590
  ) -> SearchResults:
590
591
  """Search the index.
591
592
 
@@ -654,6 +655,8 @@ class Index(BaseIndex):
654
655
  to /experimental-features with { "multimodal": true }. Because this feature is
655
656
  experimental it may be removed or updated causing breaking changes in this library
656
657
  without a major version bump so use with caution.
658
+ show_performance_details: When set to true, the search response contains a performance
659
+ trace. Default False.
657
660
 
658
661
  Returns:
659
662
  Results of the search
@@ -699,6 +702,7 @@ class Index(BaseIndex):
699
702
  locales=locales,
700
703
  retrieve_vectors=retrieve_vectors,
701
704
  media=media,
705
+ show_performance_details=show_performance_details,
702
706
  )
703
707
 
704
708
  if self._pre_search_plugins:
@@ -3810,6 +3814,46 @@ class Index(BaseIndex):
3810
3814
 
3811
3815
  return TaskInfo(**self._http_requests.parse_json(response))
3812
3816
 
3817
+ def fields(
3818
+ self, offset: int = 0, limit: int = 20, filter: FieldsFilter | None = None
3819
+ ) -> FieldResults:
3820
+ """Get the field properties on an index.
3821
+
3822
+ Args:
3823
+ offset: Number of fields to skip. Defaults to 0.
3824
+ limit: Maximum number of fields returned. Defaults to 20.
3825
+ filter: Filter fields to return based on properties. Defaults to None.
3826
+
3827
+ Returns:
3828
+ Field properties
3829
+
3830
+ Raises:
3831
+ MeilisearchCommunicationError: If there was an error communicating with the server.
3832
+ MeilisearchApiError: If the Meilisearch API returned an error.
3833
+
3834
+ Examples
3835
+ >>> from meilisearch_async_client import Client
3836
+ >>> with Client("http://localhost.com", "masterKey") as client:
3837
+ >>> docs = [{"id": 1, "title": "Some Title}]
3838
+ >>> index = client.index("movies")
3839
+ >>> index.add_documents(docs)
3840
+ >>> fields = index.fields()
3841
+ """
3842
+ filter_value = filter.model_dump(by_alias=True) if filter else None
3843
+ response = self._http_requests.post(
3844
+ f"{self._base_url_with_uid}/fields",
3845
+ body={"offset": offset, "limit": limit, "filter": filter_value},
3846
+ )
3847
+ response_json = response.json()
3848
+ fields = [Field(**field) for field in response_json["results"]]
3849
+
3850
+ return FieldResults(
3851
+ fields=fields,
3852
+ offset=response_json["offset"],
3853
+ limit=response_json["limit"],
3854
+ total=response_json["total"],
3855
+ )
3856
+
3813
3857
  @staticmethod
3814
3858
  def _run_plugins(
3815
3859
  plugins: Sequence[Plugin | DocumentPlugin | PostSearchPlugin],
@@ -44,3 +44,62 @@ class IndexStats(CamelBase):
44
44
  number_of_embeddings: int | None = None
45
45
  is_indexing: bool
46
46
  field_distribution: dict[str, int]
47
+
48
+
49
+ class FieldsFilter(CamelBase):
50
+ attribute_patterns: str | None = None
51
+ displayed: bool | None = None
52
+ sortable: bool | None = None
53
+ searchable: bool | None = None
54
+ ranking_rule: bool | None = None
55
+ filterable: bool | None = None
56
+
57
+
58
+ class FieldDisplayConfig(CamelBase):
59
+ enabled: bool
60
+
61
+
62
+ class FieldSearchConfig(CamelBase):
63
+ enabled: bool
64
+
65
+
66
+ class FieldSortableConfig(CamelBase):
67
+ enabled: bool
68
+
69
+
70
+ class FieldRankingRuleConfig(CamelBase):
71
+ order: str | None = None
72
+
73
+
74
+ class FieldDistinctConfig(CamelBase):
75
+ enabled: bool
76
+
77
+
78
+ class FieldFilterableConfig(CamelBase):
79
+ enabled: bool
80
+ sort_by: str
81
+ facet_search: bool
82
+ equality: bool
83
+ comparison: bool
84
+
85
+
86
+ class FieldLocalizedConfig(CamelBase):
87
+ locales: list[str]
88
+
89
+
90
+ class Field(CamelBase):
91
+ name: str
92
+ displayed: FieldDisplayConfig
93
+ searchable: FieldSearchConfig
94
+ sortable: FieldSortableConfig
95
+ distinct: FieldDistinctConfig
96
+ ranking_rule: FieldRankingRuleConfig
97
+ filterable: FieldFilterableConfig
98
+ localized: FieldLocalizedConfig
99
+
100
+
101
+ class FieldResults(CamelBase):
102
+ fields: list[Field]
103
+ offset: int
104
+ limit: int
105
+ total: int
@@ -72,6 +72,7 @@ class SearchParams(CamelBase):
72
72
  locales: list[str] | None = None
73
73
  retrieve_vectors: bool | None = None
74
74
  media: JsonMapping | None = None
75
+ show_performance_details: bool | None = None
75
76
 
76
77
  @field_validator("ranking_score_threshold", mode="before") # type: ignore[attr-defined]
77
78
  @classmethod
@@ -96,6 +97,7 @@ class SearchResults(CamelBase, Generic[T]):
96
97
  hits_per_page: int | None = None
97
98
  semantic_hit_count: int | None = None
98
99
  query_vector: list[float] | None = None
100
+ performance_details: JsonDict | None = None
99
101
 
100
102
 
101
103
  class SearchResultsWithUID(SearchResults, Generic[T]):
@@ -39,14 +39,14 @@ all = ["orjson"]
39
39
  dev = [
40
40
  "mkdocs==1.6.1",
41
41
  "mkdocs-material==9.7.1",
42
- "mkdocstrings[python]==1.0.0",
43
- "mypy[fastercache]>=1.19.1",
42
+ "mkdocstrings[python]==1.0.2",
43
+ "mypy[faster-cache]>=1.19.1",
44
44
  "pytest==9.0.2",
45
45
  "pytest-cov==7.0.0",
46
46
  "pytest-asyncio==1.3.0",
47
47
  "pytest-xdist==3.8.0",
48
48
  "prek>=0.2.27",
49
- "ruff==0.14.13",
49
+ "ruff==0.14.14",
50
50
  "types-aiofiles==25.1.0.20251011",
51
51
  "typing-extensions==4.15.0",
52
52
  ]
@@ -4,6 +4,7 @@ from httpx import Response
4
4
  from meilisearch_python_sdk._http_requests import AsyncHttpRequests
5
5
  from meilisearch_python_sdk._task import async_wait_for_task
6
6
  from meilisearch_python_sdk.errors import MeilisearchApiError
7
+ from meilisearch_python_sdk.models.index import FieldsFilter
7
8
  from meilisearch_python_sdk.models.settings import (
8
9
  Embedders,
9
10
  Faceting,
@@ -1031,3 +1032,26 @@ async def test_compact(async_client, async_index_with_documents):
1031
1032
  result = await async_client.get_task(task_id=task.task_uid)
1032
1033
 
1033
1034
  assert result.status == "succeeded"
1035
+
1036
+
1037
+ async def test_fields(async_index_with_documents):
1038
+ index = await async_index_with_documents()
1039
+ result = await index.fields()
1040
+ assert "genre" in [field.name for field in result.fields]
1041
+
1042
+
1043
+ async def test_fields_with_limit_and_offset(async_index_with_documents):
1044
+ index = await async_index_with_documents()
1045
+ result = await index.fields(limit=2, offset=2)
1046
+ assert len(result.fields) == 2
1047
+ assert "overview" in [field.name for field in result.fields]
1048
+
1049
+
1050
+ async def test_fields_with_filter(async_client, async_index_with_documents):
1051
+ filter = FieldsFilter(sortable=True)
1052
+ index = await async_index_with_documents()
1053
+ task = await index.update_sortable_attributes(["title"])
1054
+ await async_client.wait_for_task(task.task_uid)
1055
+ result = await index.fields(filter=filter)
1056
+ assert len(result.fields) == 1
1057
+ assert "title" in result.fields[0].name
@@ -632,6 +632,24 @@ async def test_multi_search_ranking_score_threshold(async_client, async_index_wi
632
632
  assert len(result[0].hits) > 0
633
633
 
634
634
 
635
+ async def test_multi_search_show_performance_details(async_client, async_index_with_documents):
636
+ index1 = await async_index_with_documents()
637
+ index2 = await async_index_with_documents()
638
+ response = await async_client.multi_search(
639
+ [
640
+ SearchParams(
641
+ index_uid=index1.uid,
642
+ query="How to Train Your Dragon",
643
+ show_performance_details=True,
644
+ ),
645
+ SearchParams(index_uid=index2.uid, query=""),
646
+ ],
647
+ )
648
+
649
+ assert response[0].performance_details is not None
650
+ assert response[1].performance_details is None
651
+
652
+
635
653
  async def test_facet_search_ranking_score_threshold(async_index_with_documents_and_vectors):
636
654
  index = await async_index_with_documents_and_vectors()
637
655
  update = await index.update_filterable_attributes(["genre"])
@@ -703,3 +721,9 @@ async def test_search_show_matches_position(async_index_with_documents):
703
721
  index = await async_index_with_documents()
704
722
  response = await index.search("with", show_matches_position=True)
705
723
  assert "_matchesPosition" in response.hits[0]
724
+
725
+
726
+ async def test_search_show_performance_parameters(async_index_with_documents):
727
+ index = await async_index_with_documents()
728
+ response = await index.search(show_performance_details=True)
729
+ assert response.performance_details is not None
@@ -5,6 +5,7 @@ from meilisearch_python_sdk._http_requests import HttpRequests
5
5
  from meilisearch_python_sdk._task import wait_for_task
6
6
  from meilisearch_python_sdk.errors import MeilisearchApiError
7
7
  from meilisearch_python_sdk.index._common import process_search_parameters
8
+ from meilisearch_python_sdk.models.index import FieldsFilter
8
9
  from meilisearch_python_sdk.models.settings import (
9
10
  Embedders,
10
11
  Faceting,
@@ -1032,3 +1033,26 @@ def test_compact(client, index_with_documents):
1032
1033
  result = client.get_task(task_id=task.task_uid)
1033
1034
 
1034
1035
  assert result.status == "succeeded"
1036
+
1037
+
1038
+ def test_fields(index_with_documents):
1039
+ index = index_with_documents()
1040
+ result = index.fields()
1041
+ assert "genre" in [field.name for field in result.fields]
1042
+
1043
+
1044
+ def test_fields_with_limit_and_offset(index_with_documents):
1045
+ index = index_with_documents()
1046
+ result = index.fields(limit=2, offset=2)
1047
+ assert len(result.fields) == 2
1048
+ assert "overview" in [field.name for field in result.fields]
1049
+
1050
+
1051
+ def test_fields_with_filter(client, index_with_documents):
1052
+ filter = FieldsFilter(sortable=True)
1053
+ index = index_with_documents()
1054
+ task = index.update_sortable_attributes(["title"])
1055
+ client.wait_for_task(task.task_uid)
1056
+ result = index.fields(filter=filter)
1057
+ assert len(result.fields) == 1
1058
+ assert "title" in result.fields[0].name
@@ -612,6 +612,24 @@ def test_multi_search_ranking_score_threshold(client, index_with_documents):
612
612
  assert len(result[0].hits) > 0
613
613
 
614
614
 
615
+ def test_multi_search_show_performance_details(client, index_with_documents):
616
+ index1 = index_with_documents()
617
+ index2 = index_with_documents()
618
+ response = client.multi_search(
619
+ [
620
+ SearchParams(
621
+ index_uid=index1.uid,
622
+ query="How to Train Your Dragon",
623
+ show_performance_details=True,
624
+ ),
625
+ SearchParams(index_uid=index2.uid, query=""),
626
+ ],
627
+ )
628
+
629
+ assert response[0].performance_details is not None
630
+ assert response[1].performance_details is None
631
+
632
+
615
633
  def test_facet_search_ranking_score_threshold(index_with_documents_and_vectors):
616
634
  index = index_with_documents_and_vectors()
617
635
  update = index.update_filterable_attributes(["genre"])
@@ -683,3 +701,9 @@ def test_search_show_matches_position(index_with_documents):
683
701
  index = index_with_documents()
684
702
  response = index.search("with", show_matches_position=True)
685
703
  assert "_matchesPosition" in response.hits[0]
704
+
705
+
706
+ async def test_search_show_performance_parameters(async_index_with_documents):
707
+ index = await async_index_with_documents()
708
+ response = await index.search(show_performance_details=True)
709
+ assert response.performance_details is not None