meilisearch-python-sdk 3.3.0__tar.gz → 3.4.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.

Potentially problematic release.


This version of meilisearch-python-sdk might be problematic. Click here for more details.

Files changed (92) hide show
  1. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/.github/workflows/nightly_testing.yml +4 -1
  2. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/.github/workflows/pypi_publish.yaml +3 -1
  3. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/.github/workflows/testing.yaml +91 -1
  4. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/.gitignore +2 -0
  5. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/.pre-commit-config.yaml +2 -2
  6. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/CONTRIBUTING.md +1 -1
  7. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/PKG-INFO +2 -2
  8. meilisearch_python_sdk-3.4.0/docker-compose.https.yml +12 -0
  9. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/justfile +26 -1
  10. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/_client.py +13 -6
  11. meilisearch_python_sdk-3.4.0/meilisearch_python_sdk/_version.py +1 -0
  12. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/decorators.py +10 -2
  13. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/pyproject.toml +4 -1
  14. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/tests/conftest.py +58 -21
  15. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/tests/test_async_client.py +20 -9
  16. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/tests/test_async_search.py +5 -4
  17. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/tests/test_client.py +20 -10
  18. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/tests/test_decorators.py +8 -3
  19. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/tests/test_search.py +7 -4
  20. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/uv.lock +110 -54
  21. meilisearch_python_sdk-3.3.0/meilisearch_python_sdk/_version.py +0 -1
  22. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/.github/FUNDING.yml +0 -0
  23. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/.github/dependabot.yaml +0 -0
  24. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/.github/release-draft-template.yaml +0 -0
  25. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/.github/workflows/release-drafter.yaml +0 -0
  26. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/LICENSE +0 -0
  27. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/README.md +0 -0
  28. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/assets/add_in_batches.png +0 -0
  29. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/assets/searches.png +0 -0
  30. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/benchmark/run_benchmark.py +0 -0
  31. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/codecov.yml +0 -0
  32. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/datasets/small_movies.json +0 -0
  33. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/docker-compose.yml +0 -0
  34. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/docs/.nojekyll +0 -0
  35. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/docs/CNAME +0 -0
  36. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/docs/async_client_api.md +0 -0
  37. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/docs/async_index_api.md +0 -0
  38. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/docs/client_api.md +0 -0
  39. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/docs/css/custom.css +0 -0
  40. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/docs/decorators_api.md +0 -0
  41. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/docs/index.md +0 -0
  42. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/docs/index_api.md +0 -0
  43. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/docs/js/umami.js +0 -0
  44. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/docs/json_handler.md +0 -0
  45. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/docs/plugins.md +0 -0
  46. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/docs/pydantic.md +0 -0
  47. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/examples/.gitignore +0 -0
  48. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/examples/README.md +0 -0
  49. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/examples/add_documents_decorator.py +0 -0
  50. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/examples/add_documents_in_batches.py +0 -0
  51. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/examples/async_add_documents_decorator.py +0 -0
  52. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/examples/async_add_documents_in_batches.py +0 -0
  53. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/examples/async_documents_and_search_results.py +0 -0
  54. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/examples/async_search_tracker.py +0 -0
  55. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/examples/async_update_settings.py +0 -0
  56. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/examples/documents_and_search_results.py +0 -0
  57. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/examples/fastapi_example.py +0 -0
  58. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/examples/orjson_example.py +0 -0
  59. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/examples/requirements.txt +0 -0
  60. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/examples/search_tracker.py +0 -0
  61. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/examples/ujson_example.py +0 -0
  62. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/examples/update_settings.py +0 -0
  63. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/__init__.py +0 -0
  64. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/_http_requests.py +0 -0
  65. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/_task.py +0 -0
  66. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/_utils.py +0 -0
  67. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/errors.py +0 -0
  68. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/index.py +0 -0
  69. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/json_handler.py +0 -0
  70. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/models/__init__.py +0 -0
  71. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/models/client.py +0 -0
  72. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/models/documents.py +0 -0
  73. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/models/health.py +0 -0
  74. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/models/index.py +0 -0
  75. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/models/search.py +0 -0
  76. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/models/settings.py +0 -0
  77. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/models/task.py +0 -0
  78. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/models/version.py +0 -0
  79. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/plugins.py +0 -0
  80. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/py.typed +0 -0
  81. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/meilisearch_python_sdk/types.py +0 -0
  82. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/mkdocs.yaml +0 -0
  83. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/tests/__init__.py +0 -0
  84. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/tests/test_async_documents.py +0 -0
  85. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/tests/test_async_index.py +0 -0
  86. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/tests/test_async_index_plugins.py +0 -0
  87. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/tests/test_documents.py +0 -0
  88. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/tests/test_errors.py +0 -0
  89. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/tests/test_index.py +0 -0
  90. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/tests/test_index_plugins.py +0 -0
  91. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/tests/test_utils.py +0 -0
  92. {meilisearch_python_sdk-3.3.0 → meilisearch_python_sdk-3.4.0}/tests/test_version.py +0 -0
@@ -4,6 +4,9 @@ on:
4
4
  schedule:
5
5
  # Set with UTC time
6
6
  - cron: "0 5 * * *"
7
+ env:
8
+ UV_CACHE_DIR: /tmp/.uv-cache
9
+ PYTHON_VERSION: "3.12"
7
10
  jobs:
8
11
  random-test-order:
9
12
  strategy:
@@ -18,7 +21,7 @@ jobs:
18
21
  - name: Set up Python
19
22
  uses: actions/setup-python@v5
20
23
  with:
21
- python-version: 3.12
24
+ python-version: ${{ env.PYTHON_VERSION }}
22
25
  - name: Restore uv cache
23
26
  uses: actions/cache@v4
24
27
  with:
@@ -3,6 +3,8 @@ on:
3
3
  release:
4
4
  types:
5
5
  - published
6
+ env:
7
+ PYTHON_VERSION: "3.12"
6
8
  jobs:
7
9
  deploy:
8
10
  runs-on: ubuntu-latest
@@ -13,7 +15,7 @@ jobs:
13
15
  - name: Set up Python
14
16
  uses: actions/setup-python@v5
15
17
  with:
16
- python-version: 3.12
18
+ python-version: ${{ env.PYTHON_VERSION }}
17
19
  - name: Install Dependencies
18
20
  run: uv sync --frozen --all-extras
19
21
  - name: Build and publish package
@@ -7,6 +7,7 @@ on:
7
7
  pull_request:
8
8
  env:
9
9
  UV_CACHE_DIR: /tmp/.uv-cache
10
+ PYTHON_VERSION: "3.9"
10
11
  jobs:
11
12
  linting:
12
13
  runs-on: ubuntu-latest
@@ -19,7 +20,7 @@ jobs:
19
20
  - name: Set up Python
20
21
  uses: actions/setup-python@v5
21
22
  with:
22
- python-version: 3.9
23
+ python-version: ${{ env.PYTHON_VERSION }}
23
24
  - name: Restore uv cache
24
25
  uses: actions/cache@v4
25
26
  with:
@@ -71,6 +72,50 @@ jobs:
71
72
  - name: Minimize uv cache
72
73
  run: uv cache prune --ci
73
74
 
75
+ parallel-testing-http2:
76
+ strategy:
77
+ fail-fast: false
78
+ matrix:
79
+ python-version: [ "3.9", "3.10", "3.11", "3.12", "3.13.0-beta.4" ]
80
+ runs-on: ubuntu-latest
81
+ steps:
82
+ - uses: actions/checkout@v4
83
+ - name: install Just
84
+ uses: taiki-e/install-action@just
85
+ - name: Install uv
86
+ run: curl -LsSf https://astral.sh/uv/install.sh | sh
87
+ - name: Set up Python ${{ matrix.python-version }}
88
+ uses: actions/setup-python@v5
89
+ with:
90
+ python-version: ${{ matrix.python-version }}
91
+ - name: Restore uv cache
92
+ uses: actions/cache@v4
93
+ with:
94
+ path: ${{ env.UV_CACHE_DIR }}
95
+ key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
96
+ restore-keys: |
97
+ uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
98
+ uv-${{ runner.os }}
99
+ - name: Install Dependencies
100
+ run: just install
101
+ - name: Test with pytest
102
+ run: |
103
+ sudo apt-get update && \
104
+ sudo apt-get install -y libnss3-tools build-essential gcc && \
105
+ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" && \
106
+ eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" && \
107
+ brew install mkcert && \
108
+ mkcert -install && \
109
+ mkcert -key-file meilisearch.key -cert-file meilisearch.crt localhost 127.0.0.1 ::1 && \
110
+ just test-parallel-ci-http2
111
+ - name: Upload coverage
112
+ uses: codecov/codecov-action@v4
113
+ with:
114
+ token: ${{ secrets.CODECOV_TOKEN }}
115
+ fail_ci_if_error: true
116
+ - name: Minimize uv cache
117
+ run: uv cache prune --ci
118
+
74
119
  no-parallel-testing:
75
120
  strategy:
76
121
  fail-fast: false
@@ -107,6 +152,51 @@ jobs:
107
152
  - name: Minimize uv cache
108
153
  run: uv cache prune --ci
109
154
 
155
+ no-parallel-testing-http2:
156
+ strategy:
157
+ fail-fast: false
158
+ matrix:
159
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13.0-beta.4"]
160
+ runs-on: ubuntu-latest
161
+ steps:
162
+ - uses: actions/checkout@v4
163
+ - name: install Just
164
+ uses: taiki-e/install-action@just
165
+ - name: Install uv
166
+ run: curl -LsSf https://astral.sh/uv/install.sh | sh
167
+ - name: Set up Python ${{ matrix.python-version }}
168
+ uses: actions/setup-python@v5
169
+ with:
170
+ python-version: ${{ matrix.python-version }}
171
+ - name: Restore uv cache
172
+ uses: actions/cache@v4
173
+ with:
174
+ path: ${{ env.UV_CACHE_DIR }}
175
+ key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
176
+ restore-keys: |
177
+ uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
178
+ uv-${{ runner.os }}
179
+ - name: Install Dependencies
180
+ run: just install
181
+ - name: Test with pytest
182
+ run: |
183
+ sudo apt-get update && \
184
+ sudo apt-get install -y libnss3-tools build-essential gcc && \
185
+ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" && \
186
+ eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" && \
187
+ brew install mkcert && \
188
+ mkcert -install && \
189
+ mkcert -key-file meilisearch.key -cert-file meilisearch.crt localhost 127.0.0.1 ::1 && \
190
+ just test-no-parallel-ci-http2
191
+ - name: Upload coverage
192
+ uses: codecov/codecov-action@v4
193
+ with:
194
+ token: ${{ secrets.CODECOV_TOKEN }}
195
+ fail_ci_if_error: true
196
+ - name: Minimize uv cache
197
+ run: uv cache prune --ci
198
+
199
+
110
200
  docs:
111
201
  runs-on: ubuntu-latest
112
202
  steps:
@@ -1,3 +1,5 @@
1
+ meilisearch.crt
2
+ meilisearch.key
1
3
  # Byte-compiled / optimized / DLL files
2
4
  __pycache__/
3
5
  *.py[cod]
@@ -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.11.1
12
+ rev: v1.11.2
13
13
  hooks:
14
14
  - id: mypy
15
15
  additional_dependencies: [pydantic, types-aiofiles, types-ujson]
16
16
  - repo: https://github.com/astral-sh/ruff-pre-commit
17
- rev: v0.6.1
17
+ rev: v0.6.3
18
18
  hooks:
19
19
  - id: ruff
20
20
  args: [--fix, --exit-non-zero-on-fix]
@@ -52,7 +52,7 @@ need to install it with the instructions [here](https://docs.astral.sh/uv/gettin
52
52
  First the requirements need to be installed.
53
53
 
54
54
  ```sh
55
- uv sync --locked --all-extras
55
+ uv sync --frozen --all-extras
56
56
  ```
57
57
 
58
58
  ### Creating a branch
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: meilisearch-python-sdk
3
- Version: 3.3.0
3
+ Version: 3.4.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
@@ -42,7 +42,7 @@ Requires-Python: >=3.9
42
42
  Requires-Dist: aiofiles>=0.7
43
43
  Requires-Dist: camel-converter>=1.0.0
44
44
  Requires-Dist: eval-type-backport>=0.2.0; python_version < '3.10'
45
- Requires-Dist: httpx>=0.17
45
+ Requires-Dist: httpx[http2]>=0.17
46
46
  Requires-Dist: pydantic>=2.0.0
47
47
  Requires-Dist: pyjwt>=2.3.0
48
48
  Provides-Extra: all
@@ -0,0 +1,12 @@
1
+ services:
2
+ meilisearch:
3
+ image: getmeili/meilisearch:latest
4
+ ports:
5
+ - "7700:7700"
6
+ environment:
7
+ - MEILI_MASTER_KEY=masterKey
8
+ - MEILI_NO_ANALYTICS=true
9
+ volumes:
10
+ - ./meilisearch.key:/meilisearch.key
11
+ - ./meilisearch.crt:/meilisearch.crt
12
+ command: ["meilisearch", "--ssl-cert-path", "/meilisearch.crt", "--ssl-key-path", "/meilisearch.key"]
@@ -18,12 +18,21 @@
18
18
  @test:
19
19
  -uv run pytest -x
20
20
 
21
+ @test-http2:
22
+ -uv run pytest -x --http2
23
+
21
24
  @test-parallel:
22
25
  -uv run pytest -n auto -x -m "not no_parallel"
23
26
 
24
27
  @test-no-parallel:
25
28
  -uv run pytest -x -m "no_parallel"
26
29
 
30
+ @test-parallel-http2:
31
+ -uv run pytest -n auto -x -m "not no_parallel" --http2
32
+
33
+ @test-no-parallel-http2:
34
+ -uv run pytest -x -m "no_parallel" --http2
35
+
27
36
  @test-ci: start-meilisearch-detached && stop-meilisearch
28
37
  uv run pytest --cov=meilisearch_python_sdk --cov-report=xml
29
38
 
@@ -33,6 +42,13 @@
33
42
  @test-no-parallel-ci: start-meilisearch-detached && stop-meilisearch
34
43
  uv run pytest --cov=meilisearch_python_sdk --cov-report=xml -m "no_parallel"
35
44
 
45
+ @test-parallel-ci-http2: start-meilisearch-detached-http2 && stop-meilisearch-http2
46
+ uv run pytest --cov=meilisearch_python_sdk --cov-report=xml -n auto -m "not no_parallel" --http2
47
+
48
+ @test-no-parallel-ci-http2: start-meilisearch-detached-http2 && stop-meilisearch-http2
49
+ uv run pytest --cov=meilisearch_python_sdk --cov-report=xml -m "no_parallel" --http2
50
+
51
+
36
52
  @start-meilisearch:
37
53
  docker compose up
38
54
 
@@ -42,6 +58,15 @@
42
58
  @stop-meilisearch:
43
59
  docker compose down
44
60
 
61
+ @start-meilisearch-http2:
62
+ docker compose -f docker-compose.https.yml up
63
+
64
+ @start-meilisearch-detached-http2:
65
+ docker compose -f docker-compose.https.yml up -d
66
+
67
+ @stop-meilisearch-http2:
68
+ docker compose -f docker-compose.https.yml down
69
+
45
70
  @build-docs:
46
71
  uv run mkdocs build --strict
47
72
 
@@ -49,7 +74,7 @@
49
74
  mkdocs serve
50
75
 
51
76
  @install:
52
- uv sync --locked --all-extras
77
+ uv sync --frozen --all-extras
53
78
 
54
79
  @benchmark: start-meilisearch-detached && stop-meilisearch
55
80
  -uv run benchmark/run_benchmark.py
@@ -150,6 +150,7 @@ class AsyncClient(BaseClient):
150
150
  verify: str | bool | SSLContext = True,
151
151
  custom_headers: dict[str, str] | None = None,
152
152
  json_handler: BuiltinHandler | OrjsonHandler | UjsonHandler | None = None,
153
+ http2: bool = False,
153
154
  ) -> None:
154
155
  """Class initializer.
155
156
 
@@ -168,11 +169,12 @@ class AsyncClient(BaseClient):
168
169
  (uses the json module from the standard library), OrjsonHandler (uses orjson), or
169
170
  UjsonHandler (uses ujson). Note that in order use orjson or ujson the corresponding
170
171
  extra needs to be included. Default: BuiltinHandler.
172
+ http2: Whether or not to use HTTP/2. Defaults to False.
171
173
  """
172
174
  super().__init__(api_key, custom_headers, json_handler)
173
175
 
174
176
  self.http_client = HttpxAsyncClient(
175
- base_url=url, timeout=timeout, headers=self._headers, verify=verify
177
+ base_url=url, timeout=timeout, headers=self._headers, verify=verify, http2=http2
176
178
  )
177
179
  self._http_requests = AsyncHttpRequests(self.http_client, json_handler=self.json_handler)
178
180
 
@@ -649,8 +651,9 @@ class AsyncClient(BaseClient):
649
651
  Args:
650
652
 
651
653
  queries: List of SearchParameters
652
- federation: If included a single search result with hits built from all queries. This
653
- parameter can only be used with Meilisearch >= v1.10.0. Defaults to None.
654
+ federation: If included a single search result with hits built from all queries will
655
+ be returned. This parameter can only be used with Meilisearch >= v1.10.0. Defaults
656
+ to None.
654
657
  hits_type: Allows for a custom type to be passed to use for hits. Defaults to
655
658
  JsonDict
656
659
 
@@ -1072,6 +1075,7 @@ class Client(BaseClient):
1072
1075
  verify: str | bool | SSLContext = True,
1073
1076
  custom_headers: dict[str, str] | None = None,
1074
1077
  json_handler: BuiltinHandler | OrjsonHandler | UjsonHandler | None = None,
1078
+ http2: bool = False,
1075
1079
  ) -> None:
1076
1080
  """Class initializer.
1077
1081
 
@@ -1090,12 +1094,14 @@ class Client(BaseClient):
1090
1094
  (uses the json module from the standard library), OrjsonHandler (uses orjson), or
1091
1095
  UjsonHandler (uses ujson). Note that in order use orjson or ujson the corresponding
1092
1096
  extra needs to be included. Default: BuiltinHandler.
1097
+ http2: If set to True, the client will use HTTP/2. Defaults to False.
1093
1098
  """
1094
1099
  super().__init__(api_key, custom_headers, json_handler)
1095
1100
 
1096
1101
  self.http_client = HttpxClient(
1097
- base_url=url, timeout=timeout, headers=self._headers, verify=verify
1102
+ base_url=url, timeout=timeout, headers=self._headers, verify=verify, http2=http2
1098
1103
  )
1104
+
1099
1105
  self._http_requests = HttpRequests(self.http_client, json_handler=self.json_handler)
1100
1106
 
1101
1107
  def create_dump(self) -> TaskInfo:
@@ -1549,8 +1555,9 @@ class Client(BaseClient):
1549
1555
  Args:
1550
1556
 
1551
1557
  queries: List of SearchParameters
1552
- federation: If included a single search result with hits built from all queries. This
1553
- parameter can only be used with Meilisearch >= v1.10.0. Defaults to None.
1558
+ federation: If included a single search result with hits built from all queries will
1559
+ be returned. This parameter can only be used with Meilisearch >= v1.10.0. Defaults
1560
+ to None.
1554
1561
  hits_type: Allows for a custom type to be passed to use for hits. Defaults to
1555
1562
  JsonDict
1556
1563
 
@@ -0,0 +1 @@
1
+ VERSION = "3.4.0"
@@ -26,6 +26,7 @@ def async_add_documents(
26
26
  batch_size: int | None = None,
27
27
  primary_key: str | None = None,
28
28
  wait_for_task: bool = False,
29
+ verify: bool = True,
29
30
  ) -> Callable:
30
31
  """Decorator that takes the returned documents from a function and asyncronously adds them to Meilisearch.
31
32
 
@@ -42,6 +43,7 @@ def async_add_documents(
42
43
  Defaults to None.
43
44
  wait_for_task: If set to `True` the decorator will wait for the document addition to finish
44
45
  indexing before returning, otherwise it will return right away. Default = False.
46
+ verify: If set to `False` the decorator will not verify the SSL certificate of the server.
45
47
 
46
48
  Returns:
47
49
 
@@ -89,7 +91,9 @@ def async_add_documents(
89
91
  )
90
92
  return result
91
93
 
92
- async with AsyncClient(connection_info.url, connection_info.api_key) as client:
94
+ async with AsyncClient(
95
+ connection_info.url, connection_info.api_key, verify=verify
96
+ ) as client:
93
97
  await _async_add_documents(
94
98
  client, index_name, result, batch_size, primary_key, wait_for_task
95
99
  )
@@ -108,6 +112,7 @@ def add_documents(
108
112
  batch_size: int | None = None,
109
113
  primary_key: str | None = None,
110
114
  wait_for_task: bool = False,
115
+ verify: bool = True,
111
116
  ) -> Callable:
112
117
  """Decorator that takes the returned documents from a function and adds them to Meilisearch.
113
118
 
@@ -124,6 +129,7 @@ def add_documents(
124
129
  Defaults to None.
125
130
  wait_for_task: If set to `True` the decorator will wait for the document addition to finish
126
131
  indexing before returning, otherwise it will return right away. Default = False.
132
+ verify: If set to `False` the decorator will not verify the SSL certificate of the server.
127
133
 
128
134
  Returns:
129
135
 
@@ -171,7 +177,9 @@ def add_documents(
171
177
  )
172
178
  return result
173
179
 
174
- decorator_client = Client(url=connection_info.url, api_key=connection_info.api_key)
180
+ decorator_client = Client(
181
+ url=connection_info.url, api_key=connection_info.api_key, verify=verify
182
+ )
175
183
  _add_documents(
176
184
  decorator_client,
177
185
  index_name,
@@ -27,7 +27,7 @@ dependencies = [
27
27
  "camel-converter>=1.0.0",
28
28
  # allows pydantic to use pipe instead of Union
29
29
  "eval-type-backport>=0.2.0; python_version < '3.10'",
30
- "httpx>=0.17",
30
+ "httpx[http2]>=0.17",
31
31
  "pydantic>=2.0.0",
32
32
  "PyJWT>=2.3.0",
33
33
  ]
@@ -49,6 +49,7 @@ dev-dependencies = [
49
49
  "pytest-asyncio==0.24.0",
50
50
  "pytest-xdist==3.6.1",
51
51
  "ruff==0.6.2",
52
+ "truststore==0.9.2; python_version >= '3.10'",
52
53
  "types-aiofiles==24.1.0.20240626",
53
54
  "typing-extensions==4.12.2",
54
55
  "types-ujson==5.10.0.20240515",
@@ -56,6 +57,8 @@ dev-dependencies = [
56
57
  "rich==13.7.1",
57
58
  ]
58
59
 
60
+ environments = ["python_version < '3.10'", "python_version >= '3.10'"]
61
+
59
62
  [tool.hatch.version]
60
63
  path = "meilisearch_python_sdk/_version.py"
61
64
 
@@ -1,10 +1,20 @@
1
1
  import asyncio
2
2
  import csv
3
3
  import json
4
+ import ssl
5
+ import sys
6
+ from logging import warning
4
7
  from pathlib import Path
5
8
  from uuid import uuid4
6
9
 
7
10
  import pytest
11
+
12
+ try:
13
+ import truststore
14
+
15
+ has_truststore = True
16
+ except ImportError:
17
+ has_truststore = False
8
18
  from httpx import AsyncClient as HttpxAsyncClient
9
19
 
10
20
  from meilisearch_python_sdk import AsyncClient, Client
@@ -22,49 +32,75 @@ from meilisearch_python_sdk.models.settings import (
22
32
  )
23
33
 
24
34
  MASTER_KEY = "masterKey"
25
- BASE_URL = "http://127.0.0.1:7700"
26
35
 
27
36
  ROOT_PATH = Path().absolute()
28
37
  SMALL_MOVIES_PATH = ROOT_PATH / "datasets" / "small_movies.json"
29
38
 
30
39
 
40
+ def pytest_addoption(parser):
41
+ parser.addoption("--http2", action="store_true")
42
+
43
+
44
+ @pytest.fixture(scope="session")
45
+ def http2_enabled(request):
46
+ return request.config.getoption("--http2")
47
+
48
+
49
+ @pytest.fixture(scope="session")
50
+ def ssl_verify(request, http2_enabled):
51
+ if has_truststore: # truststore is installed
52
+ if http2_enabled:
53
+ # http2 needs ssl so best to use truststore to make things work with mkcert
54
+ return truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT) if http2_enabled else True
55
+ return True # recommended default
56
+ else: # truststore isn't installed
57
+ if sys.version_info >= (3, 10): # should be available in 3.10+
58
+ warning("truststore not installed, your environment may be broken run uv sync")
59
+ # without truststore we can't verify the ssl (and when http2 is enabled, verification must be disabled)
60
+ return not http2_enabled
61
+
62
+
31
63
  @pytest.fixture
32
- async def async_client():
33
- async with AsyncClient(BASE_URL, MASTER_KEY) as client:
64
+ async def async_client(base_url, ssl_verify):
65
+ async with AsyncClient(base_url, MASTER_KEY, verify=ssl_verify) as client:
34
66
  yield client
35
67
 
36
68
 
37
69
  @pytest.fixture
38
- async def async_client_orjson_handler():
39
- async with AsyncClient(BASE_URL, MASTER_KEY, json_handler=OrjsonHandler()) as client:
70
+ async def async_client_orjson_handler(base_url, ssl_verify):
71
+ async with AsyncClient(
72
+ base_url, MASTER_KEY, json_handler=OrjsonHandler(), verify=ssl_verify
73
+ ) as client:
40
74
  yield client
41
75
 
42
76
 
43
77
  @pytest.fixture
44
- async def async_client_ujson_handler():
45
- async with AsyncClient(BASE_URL, MASTER_KEY, json_handler=UjsonHandler()) as client:
78
+ async def async_client_ujson_handler(base_url, ssl_verify):
79
+ async with AsyncClient(
80
+ base_url, MASTER_KEY, json_handler=UjsonHandler(), verify=ssl_verify
81
+ ) as client:
46
82
  yield client
47
83
 
48
84
 
49
85
  @pytest.fixture
50
- async def async_client_with_plugins():
51
- async with AsyncClient(BASE_URL, MASTER_KEY) as client:
86
+ async def async_client_with_plugins(base_url, ssl_verify):
87
+ async with AsyncClient(base_url, MASTER_KEY, verify=ssl_verify) as client:
52
88
  yield client
53
89
 
54
90
 
55
91
  @pytest.fixture
56
- def client():
57
- yield Client(BASE_URL, MASTER_KEY)
92
+ def client(base_url, ssl_verify):
93
+ yield Client(base_url, MASTER_KEY, verify=ssl_verify)
58
94
 
59
95
 
60
96
  @pytest.fixture
61
- def client_orjson_handler():
62
- yield Client(BASE_URL, MASTER_KEY, json_handler=OrjsonHandler())
97
+ def client_orjson_handler(base_url, ssl_verify):
98
+ yield Client(base_url, MASTER_KEY, json_handler=OrjsonHandler(), verify=ssl_verify)
63
99
 
64
100
 
65
101
  @pytest.fixture
66
- def client_ujson_handler():
67
- yield Client(BASE_URL, MASTER_KEY, json_handler=UjsonHandler())
102
+ def client_ujson_handler(base_url, ssl_verify):
103
+ yield Client(base_url, MASTER_KEY, json_handler=UjsonHandler(), verify=ssl_verify)
68
104
 
69
105
 
70
106
  @pytest.fixture(autouse=True)
@@ -89,8 +125,9 @@ def master_key():
89
125
 
90
126
 
91
127
  @pytest.fixture(scope="session")
92
- def base_url():
93
- return BASE_URL
128
+ def base_url(request, http2_enabled):
129
+ schema = "https" if http2_enabled else "http"
130
+ return f"{schema}://127.0.0.1:7700"
94
131
 
95
132
 
96
133
  @pytest.fixture
@@ -252,18 +289,18 @@ async def default_search_key(async_client):
252
289
 
253
290
 
254
291
  @pytest.fixture(scope="session", autouse=True)
255
- async def enable_vector_search():
292
+ async def enable_vector_search(base_url, ssl_verify):
256
293
  async with HttpxAsyncClient(
257
- base_url=BASE_URL, headers={"Authorization": f"Bearer {MASTER_KEY}"}
294
+ base_url=base_url, headers={"Authorization": f"Bearer {MASTER_KEY}"}, verify=ssl_verify
258
295
  ) as client:
259
296
  await client.patch("/experimental-features", json={"vectorStore": True})
260
297
  yield
261
298
 
262
299
 
263
300
  @pytest.fixture(scope="session", autouse=True)
264
- async def enable_edit_by_function():
301
+ async def enable_edit_by_function(base_url, ssl_verify):
265
302
  async with HttpxAsyncClient(
266
- base_url=BASE_URL, headers={"Authorization": f"Bearer {MASTER_KEY}"}
303
+ base_url=base_url, headers={"Authorization": f"Bearer {MASTER_KEY}"}, verify=ssl_verify
267
304
  ) as client:
268
305
  await client.patch("/experimental-features", json={"editDocumentsByFunction": True})
269
306
  yield
@@ -106,9 +106,9 @@ async def wait_for_dump_creation(
106
106
  (None, None, None),
107
107
  ),
108
108
  )
109
- async def test_headers(api_key, custom_headers, expected):
109
+ async def test_headers(api_key, custom_headers, expected, ssl_verify):
110
110
  async with AsyncClient(
111
- "127.0.0.1:7700", api_key=api_key, custom_headers=custom_headers
111
+ "https://127.0.0.1:7700", api_key=api_key, custom_headers=custom_headers, verify=ssl_verify
112
112
  ) as client:
113
113
  assert client._headers == expected
114
114
 
@@ -318,10 +318,10 @@ async def test_get_or_create_index_no_primary_key(async_client):
318
318
 
319
319
  async def test_get_or_create_index_communication_error(async_client, monkeypatch):
320
320
  async def mock_get_response(*args, **kwargs):
321
- raise ConnectError("test", request=Request("GET", url="http://localhost"))
321
+ raise ConnectError("test", request=Request("GET", url="https://localhost"))
322
322
 
323
323
  async def mock_post_response(*args, **kwargs):
324
- raise ConnectError("test", request=Request("POST", url="http://localhost"))
324
+ raise ConnectError("test", request=Request("POST", url="https://localhost"))
325
325
 
326
326
  monkeypatch.setattr(HttpxAsyncClient, "get", mock_get_response)
327
327
  monkeypatch.setattr(HttpxAsyncClient, "post", mock_post_response)
@@ -503,21 +503,21 @@ async def test_create_snapshot(async_client, async_index_with_documents):
503
503
  assert snapshot_status.task_type == "snapshotCreation"
504
504
 
505
505
 
506
- async def test_no_master_key(base_url):
506
+ async def test_no_master_key(base_url, ssl_verify):
507
507
  with pytest.raises(MeilisearchApiError):
508
- async with AsyncClient(base_url) as client:
508
+ async with AsyncClient(base_url, verify=ssl_verify) as client:
509
509
  await client.create_index("some_index")
510
510
 
511
511
 
512
- async def test_bad_master_key(base_url, master_key):
512
+ async def test_bad_master_key(base_url, master_key, ssl_verify):
513
513
  with pytest.raises(MeilisearchApiError):
514
- async with AsyncClient(base_url) as client:
514
+ async with AsyncClient(base_url, verify=ssl_verify) as client:
515
515
  await client.create_index("some_index", f"{master_key}bad")
516
516
 
517
517
 
518
518
  async def test_communication_error(master_key):
519
519
  with pytest.raises(MeilisearchCommunicationError):
520
- async with AsyncClient("http://wrongurl:1234", master_key, timeout=1) as client:
520
+ async with AsyncClient("https://wrongurl:1234", master_key, timeout=1) as client:
521
521
  await client.create_index("some_index")
522
522
 
523
523
 
@@ -975,3 +975,14 @@ async def test_wait_for_task_raise_for_status_false(
975
975
  monkeypatch.setattr(HttpxAsyncClient, "get", mock_get_response)
976
976
  with pytest.raises(MeilisearchTaskFailedError):
977
977
  await async_client.wait_for_task(response.task_uid, raise_for_status=True)
978
+
979
+
980
+ @pytest.mark.parametrize("http2, expected", [(True, "HTTP/2"), (False, "HTTP/1.1")])
981
+ async def test_http_version(http2, expected, master_key, ssl_verify, http2_enabled):
982
+ if not http2_enabled:
983
+ pytest.skip("HTTP/2 is not enabled")
984
+ async with AsyncClient(
985
+ "https://127.0.0.1:7700", master_key, http2=http2, verify=ssl_verify
986
+ ) as client:
987
+ response = await client.http_client.get("health")
988
+ assert response.http_version == expected