diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0777160a..63033e16 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -48,33 +48,6 @@ jobs: - name: Test with pytest run: uv run pytest --cov-report=xml - pylint: - name: pylint - runs-on: ubuntu-latest - env: - PYTHONUNBUFFERED: 1 - PYTHON_VERSION: "3.10" - UV_LOCKED: 1 - steps: - - name: Checkout the repository - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - persist-credentials: false - - - name: Set up Python ${{ env.PYTHON_VERSION }} - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 - with: - version: "0.11.21" - python-version: ${{ env.PYTHON_VERSION }} - - - name: Linter with pylint - run: uv run pylint meilisearch tests - mypy: name: mypy runs-on: ubuntu-latest @@ -111,37 +84,13 @@ jobs: with: persist-credentials: false - - name: ruff format + - name: Run linter uses: astral-sh/ruff-action@0ce1b0bf8b818ef400413f810f8a11cdbda0034b # v4.0.0 with: - args: "format --check" - - isort: - name: isort - runs-on: ubuntu-latest - env: - PYTHONUNBUFFERED: 1 - PYTHON_VERSION: "3.10" - UV_LOCKED: 1 - steps: - - name: Checkout the repository - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - persist-credentials: false - - - name: Set up Python ${{ env.PYTHON_VERSION }} - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install uv - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 - with: - version: "0.11.21" - python-version: ${{ env.PYTHON_VERSION }} + args: "check --output-format=full" - - name: isort - run: uv run isort meilisearch tests --check-only + - name: Run formatter + run: ruff format --check --output-format=full yaml-lint: name: Yaml linting check diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d45d9c2a..94d8e696 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -44,7 +44,7 @@ You can set up your local environment natively or using `docker`, check out the Example of running all the checks with docker: ```bash -docker-compose run --rm package bash -c "uv run mypy meilisearch && uv run pylint meilisearch tests && uv run pytest tests" +docker-compose run --rm package bash -c "uv run mypy meilisearch && uv run ruff check && uv run ruff format --check && uv run pytest tests" ``` To install dependencies: @@ -55,22 +55,22 @@ uv sync ### Tests and Linter -Each PR should pass the tests, mypy type checking, and the linter to be accepted. -Your PR also needs to be formatted using ruff and have its imports sorted using isort. +Each PR should pass the tests, mypy type checking, linting, and formatting before it can be accepted. ```bash # Tests curl -L https://install.meilisearch.com | sh # download Meilisearch ./meilisearch --master-key=masterKey --no-analytics # run Meilisearch uv run pytest tests + # MyPy uv run mypy meilisearch + # Linter -uv run pylint meilisearch tests -# Format +uv run ruff check --fix . + +# Formatter uv run ruff format . -# Isort -uv run isort meilisearch tests ``` Optionally tox can be used to run test on all supported version of Python, mypy, and linting. diff --git a/docs/conf.py b/docs/conf.py index a4fac860..ccbe140e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -53,7 +53,7 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = [] +html_static_path: list[str] = [] # This value contains a list of modules to be mocked up. autodoc_mock_imports = ["camel_converter"] diff --git a/meilisearch/__init__.py b/meilisearch/__init__.py index 20bf3629..653cae33 100644 --- a/meilisearch/__init__.py +++ b/meilisearch/__init__.py @@ -1 +1 @@ -from meilisearch.client import Client as Client # pylint: disable=useless-import-alias +from meilisearch.client import Client as Client diff --git a/meilisearch/_httprequests.py b/meilisearch/_httprequests.py index 1e98c3a2..ba768c5d 100644 --- a/meilisearch/_httprequests.py +++ b/meilisearch/_httprequests.py @@ -1,8 +1,9 @@ from __future__ import annotations import json +from collections.abc import Callable, Mapping, Sequence from functools import lru_cache -from typing import Any, Callable, List, Mapping, Optional, Sequence, Tuple, Type, Union +from typing import Any import requests @@ -17,7 +18,7 @@ class HttpRequests: - def __init__(self, config: Config, custom_headers: Optional[Mapping[str, str]] = None) -> None: + def __init__(self, config: Config, custom_headers: Mapping[str, str] | None = None) -> None: self.config = config self.headers = { "Authorization": f"Bearer {self.config.api_key}", @@ -31,21 +32,18 @@ def send_request( self, http_method: Callable, path: str, - body: Optional[ - Union[ - Mapping[str, Any], - Sequence[Mapping[str, Any]], - List[str], - bool, - bytes, - str, - int, - ProximityPrecision, - ] - ] = None, - content_type: Optional[str] = None, + body: Mapping[str, Any] + | Sequence[Mapping[str, Any]] + | list[str] + | bool + | bytes + | str + | int + | ProximityPrecision + | None = None, + content_type: str | None = None, *, - serializer: Optional[Type[json.JSONEncoder]] = None, + serializer: type[json.JSONEncoder] | None = None, ) -> Any: if content_type: self.headers["Content-Type"] = content_type @@ -102,63 +100,69 @@ def get(self, path: str) -> Any: def post( self, path: str, - body: Optional[ - Union[Mapping[str, Any], Sequence[Mapping[str, Any]], List[str], bytes, str] - ] = None, - content_type: Optional[str] = "application/json", + body: Mapping[str, Any] + | Sequence[Mapping[str, Any]] + | list[str] + | bytes + | str + | None = None, + content_type: str | None = "application/json", *, - serializer: Optional[Type[json.JSONEncoder]] = None, + serializer: type[json.JSONEncoder] | None = None, ) -> Any: return self.send_request(requests.post, path, body, content_type, serializer=serializer) def patch( self, path: str, - body: Optional[ - Union[Mapping[str, Any], Sequence[Mapping[str, Any]], List[str], bytes, str] - ] = None, - content_type: Optional[str] = "application/json", + body: Mapping[str, Any] + | Sequence[Mapping[str, Any]] + | list[str] + | bytes + | str + | None = None, + content_type: str | None = "application/json", ) -> Any: return self.send_request(requests.patch, path, body, content_type) def put( self, path: str, - body: Optional[ - Union[ - Mapping[str, Any], - Sequence[Mapping[str, Any]], - List[str], - bool, - bytes, - str, - int, - PrefixSearch, - ProximityPrecision, - ] - ] = None, - content_type: Optional[str] = "application/json", + body: Mapping[str, Any] + | Sequence[Mapping[str, Any]] + | list[str] + | bool + | bytes + | str + | int + | PrefixSearch + | ProximityPrecision + | None = None, + content_type: str | None = "application/json", *, - serializer: Optional[Type[json.JSONEncoder]] = None, + serializer: type[json.JSONEncoder] | None = None, ) -> Any: return self.send_request(requests.put, path, body, content_type, serializer=serializer) def delete( self, path: str, - body: Optional[Union[Mapping[str, Any], Sequence[Mapping[str, Any]], List[str]]] = None, + body: Mapping[str, Any] | Sequence[Mapping[str, Any]] | list[str] | None = None, ) -> Any: return self.send_request(requests.delete, path, body) def post_stream( self, path: str, - body: Optional[ - Union[Mapping[str, Any], Sequence[Mapping[str, Any]], List[str], bytes, str] - ] = None, - content_type: Optional[str] = "application/json", + body: Mapping[str, Any] + | Sequence[Mapping[str, Any]] + | list[str] + | bytes + | str + | None = None, + content_type: str | None = "application/json", *, - serializer: Optional[Type[json.JSONEncoder]] = None, + serializer: type[json.JSONEncoder] | None = None, ) -> requests.Response: """Send a POST request with streaming enabled. @@ -236,7 +240,7 @@ def __validate(request: requests.Response) -> Any: @lru_cache(maxsize=1) -def _build_user_agent(client_agents: Optional[Tuple[str, ...]] = None) -> str: +def _build_user_agent(client_agents: tuple[str, ...] | None = None) -> str: user_agent = qualified_version() if not client_agents: return user_agent diff --git a/meilisearch/_utils.py b/meilisearch/_utils.py index e1150cb6..ae915c85 100644 --- a/meilisearch/_utils.py +++ b/meilisearch/_utils.py @@ -1,6 +1,5 @@ from datetime import datetime from functools import lru_cache -from typing import Union import pydantic @@ -20,7 +19,7 @@ def is_pydantic_2() -> bool: return False -def iso_to_date_time(iso_date: Union[datetime, str, None]) -> Union[datetime, None]: +def iso_to_date_time(iso_date: datetime | str | None) -> datetime | None: """Handle conversion of iso string to datetime. The microseconds from Meilisearch are sometimes too long for python to convert so this diff --git a/meilisearch/client.py b/meilisearch/client.py index bd0ec8fa..5e1d890b 100644 --- a/meilisearch/client.py +++ b/meilisearch/client.py @@ -1,5 +1,3 @@ -# pylint: disable=too-many-public-methods - from __future__ import annotations import base64 @@ -8,17 +6,9 @@ import hmac import json import re +from collections.abc import Iterator, Mapping, MutableMapping, Sequence from typing import ( Any, - Dict, - Iterator, - List, - Mapping, - MutableMapping, - Optional, - Sequence, - Tuple, - Union, ) from urllib import parse @@ -44,16 +34,13 @@ class Client: Meilisearch and its permissions. """ - # Import aliases to satisfy pylint (used in docstrings) - MeilisearchApiError = MeilisearchApiError - def __init__( self, url: str, - api_key: Optional[str] = None, - timeout: Optional[int] = None, - client_agents: Optional[Tuple[str, ...]] = None, - custom_headers: Optional[Mapping[str, str]] = None, + api_key: str | None = None, + timeout: int | None = None, + client_agents: tuple[str, ...] | None = None, + custom_headers: Mapping[str, str] | None = None, ) -> None: """ Parameters @@ -84,9 +71,9 @@ def __init__( def create_index( self, uid: str, - options: Optional[Mapping[str, Any]] = None, + options: Mapping[str, Any] | None = None, *, - metadata: Optional[str] = None, + metadata: str | None = None, ) -> TaskInfo: """Create an index. @@ -114,7 +101,7 @@ def create_index( self.config, uid, options, custom_headers=self._custom_headers, metadata=metadata ) - def delete_index(self, uid: str, *, metadata: Optional[str] = None) -> TaskInfo: + def delete_index(self, uid: str, *, metadata: str | None = None) -> TaskInfo: """Deletes an index Parameters @@ -143,7 +130,7 @@ def delete_index(self, uid: str, *, metadata: Optional[str] = None) -> TaskInfo: return TaskInfo(**task) - def get_indexes(self, parameters: Optional[Mapping[str, Any]] = None) -> Dict[str, List[Index]]: + def get_indexes(self, parameters: Mapping[str, Any] | None = None) -> dict[str, list[Index]]: """Get all indexes. Parameters @@ -177,9 +164,7 @@ def get_indexes(self, parameters: Optional[Mapping[str, Any]] = None) -> Dict[st ] return response - def get_raw_indexes( - self, parameters: Optional[Mapping[str, Any]] = None - ) -> List[Dict[str, Any]]: + def get_raw_indexes(self, parameters: Mapping[str, Any] | None = None) -> list[dict[str, Any]]: """Get all indexes in dictionary format. Parameters @@ -222,7 +207,7 @@ def get_index(self, uid: str) -> Index: """ return Index(self.config, uid, custom_headers=self._custom_headers).fetch_info() - def get_raw_index(self, uid: str) -> Dict[str, Any]: + def get_raw_index(self, uid: str) -> dict[str, Any]: """Get the index as a dictionary. This index should already exist. @@ -262,8 +247,8 @@ def index(self, uid: str) -> Index: raise ValueError("The index UID should not be None") def multi_search( - self, queries: Sequence[Mapping[str, Any]], federation: Optional[Dict[str, Any]] = None - ) -> Dict[str, List[Dict[str, Any]]]: + self, queries: Sequence[Mapping[str, Any]], federation: dict[str, Any] | None = None + ) -> dict[str, list[dict[str, Any]]]: """Multi-index search. Parameters @@ -296,8 +281,8 @@ def multi_search( ) def update_documents_by_function( - self, index_uid: str, queries: Dict[str, List[Dict[str, Any]]] - ) -> Dict[str, Any]: + self, index_uid: str, queries: dict[str, list[dict[str, Any]]] + ) -> dict[str, Any]: """Update Documents by function Parameters ---------- @@ -322,7 +307,7 @@ def update_documents_by_function( body=dict(queries), ) - def get_all_stats(self) -> Dict[str, Any]: + def get_all_stats(self) -> dict[str, Any]: """Get all stats of Meilisearch Get information about database size and all indexes @@ -340,7 +325,7 @@ def get_all_stats(self) -> Dict[str, Any]: """ return self.http.get(self.config.paths.stat) - def health(self) -> Dict[str, str]: + def health(self) -> dict[str, str]: """Get health of the Meilisearch server. Returns @@ -386,7 +371,7 @@ def get_key(self, key_or_uid: str) -> Key: return Key(**key) - def get_keys(self, parameters: Optional[Mapping[str, Any]] = None) -> KeysResults: + def get_keys(self, parameters: Mapping[str, Any] | None = None) -> KeysResults: """Gets the Meilisearch API keys. Parameters @@ -601,7 +586,7 @@ def delete_webhook(self, webhook_uuid: str) -> int: response = self.http.delete(f"{self.config.paths.webhooks}/{webhook_uuid}") return response.status_code - def get_version(self) -> Dict[str, str]: + def get_version(self) -> dict[str, str]: """Get version Meilisearch Returns @@ -616,7 +601,7 @@ def get_version(self) -> Dict[str, str]: """ return self.http.get(self.config.paths.version) - def version(self) -> Dict[str, str]: + def version(self) -> dict[str, str]: """Alias for get_version Returns @@ -652,9 +637,9 @@ def create_dump(self) -> TaskInfo: def export( self, url: str, - api_key: Optional[str] = None, - payload_size: Optional[str] = None, - indexes: Optional[Mapping[str, Any]] = None, + api_key: str | None = None, + payload_size: str | None = None, + indexes: Mapping[str, Any] | None = None, ) -> TaskInfo: """Trigger the creation of a Meilisearch export. @@ -688,7 +673,7 @@ def export( Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors """ - payload: Dict[str, Any] = {"url": url} + payload: dict[str, Any] = {"url": url} if api_key is not None: payload["apiKey"] = api_key if payload_size is not None: @@ -718,7 +703,7 @@ def create_snapshot(self) -> TaskInfo: return TaskInfo(**task) - def swap_indexes(self, parameters: List[Mapping[str, List[str] | bool]]) -> TaskInfo: + def swap_indexes(self, parameters: list[Mapping[str, list[str] | bool]]) -> TaskInfo: """Swap two indexes. Parameters @@ -742,7 +727,7 @@ def swap_indexes(self, parameters: List[Mapping[str, List[str] | bool]]) -> Task """ return TaskInfo(**self.http.post(self.config.paths.swap, parameters)) - def get_tasks(self, parameters: Optional[MutableMapping[str, Any]] = None) -> TaskResults: + def get_tasks(self, parameters: MutableMapping[str, Any] | None = None) -> TaskResults: """Get all tasks. Parameters @@ -784,7 +769,7 @@ def get_task(self, uid: int) -> Task: return self.task_handler.get_task(uid) def cancel_tasks( - self, parameters: MutableMapping[str, Any], *, metadata: Optional[str] = None + self, parameters: MutableMapping[str, Any], *, metadata: str | None = None ) -> TaskInfo: """Cancel a list of enqueued or processing tasks. @@ -809,7 +794,7 @@ def cancel_tasks( return self.task_handler.cancel_tasks(parameters=parameters, metadata=metadata) def delete_tasks( - self, parameters: MutableMapping[str, Any], *, metadata: Optional[str] = None + self, parameters: MutableMapping[str, Any], *, metadata: str | None = None ) -> TaskInfo: """Delete a list of finished tasks. @@ -860,7 +845,7 @@ def wait_for_task( """ return self.task_handler.wait_for_task(uid, timeout_in_ms, interval_in_ms) - def get_batches(self, parameters: Optional[MutableMapping[str, Any]] = None) -> BatchResults: + def get_batches(self, parameters: MutableMapping[str, Any] | None = None) -> BatchResults: """Get all batches. Parameters @@ -903,10 +888,10 @@ def get_batch(self, uid: int) -> Batch: def generate_tenant_token( self, api_key_uid: str, - search_rules: Union[Mapping[str, Any], Sequence[str]], + search_rules: Mapping[str, Any] | Sequence[str], *, - expires_at: Optional[datetime.datetime] = None, - api_key: Optional[str] = None, + expires_at: datetime.datetime | None = None, + api_key: str | None = None, ) -> str: """Generate a JWT token for the use of multitenancy. @@ -974,7 +959,7 @@ def generate_tenant_token( return jwt_token - def add_or_update_networks(self, body: Union[MutableMapping[str, Any], None]) -> Dict[str, str]: + def add_or_update_networks(self, body: MutableMapping[str, Any] | None) -> dict[str, str]: """Configure the network topology Parameters @@ -998,7 +983,7 @@ def add_or_update_networks(self, body: Union[MutableMapping[str, Any], None]) -> return self.http.patch(path=f"{self.config.paths.network}", body=body) - def get_all_networks(self) -> Dict[str, str]: + def get_all_networks(self) -> dict[str, str]: """Fetches all the remote-networks present Returns @@ -1016,10 +1001,10 @@ def get_all_networks(self) -> Dict[str, str]: def create_chat_completion( self, workspace_uid: str, - messages: List[Dict[str, str]], + messages: list[dict[str, str]], model: str = "gpt-3.5-turbo", stream: bool = True, - ) -> Iterator[Dict[str, Any]]: + ) -> Iterator[dict[str, Any]]: """Streams a chat completion from the Meilisearch chat API. Parameters @@ -1091,9 +1076,9 @@ def create_chat_completion( def get_chat_workspaces( self, *, - offset: Optional[int] = None, - limit: Optional[int] = None, - ) -> Dict[str, Any]: + offset: int | None = None, + limit: int | None = None, + ) -> dict[str, Any]: """Get all chat workspaces. Parameters @@ -1121,7 +1106,7 @@ def get_chat_workspaces( path = "chats" + ("?" + parse.urlencode(params) if params else "") return self.http.get(path) - def get_chat_workspace_settings(self, workspace_uid: str) -> Dict[str, Any]: + def get_chat_workspace_settings(self, workspace_uid: str) -> dict[str, Any]: """Get the settings for a specific chat workspace. Parameters @@ -1151,7 +1136,7 @@ def get_chat_workspace_settings(self, workspace_uid: str) -> Dict[str, Any]: def update_chat_workspace_settings( self, workspace_uid: str, settings: Mapping[str, Any] - ) -> Dict[str, Any]: + ) -> dict[str, Any]: """Update the settings for a specific chat workspace. Parameters @@ -1197,7 +1182,7 @@ def _valid_uuid(uuid: str) -> bool: match = uuid4hex.match(uuid) return bool(match) - def get_experimental_features(self) -> Dict[str, Any]: + def get_experimental_features(self) -> dict[str, Any]: """Retrieve the current settings for all experimental features. Returns @@ -1213,7 +1198,7 @@ def get_experimental_features(self) -> Dict[str, Any]: """ return self.http.get(self.config.paths.experimental_features) - def update_experimental_features(self, features: Dict[str, bool]) -> Dict[str, Any]: + def update_experimental_features(self, features: dict[str, bool]) -> dict[str, Any]: """Update one or more experimental features. Parameters diff --git a/meilisearch/config.py b/meilisearch/config.py index 3b9fa457..9c311a64 100644 --- a/meilisearch/config.py +++ b/meilisearch/config.py @@ -1,7 +1,5 @@ from __future__ import annotations -from typing import Optional, Tuple - class Config: """ @@ -55,9 +53,9 @@ class Paths: def __init__( self, url: str, - api_key: Optional[str] = None, - timeout: Optional[int] = None, - client_agents: Optional[Tuple[str, ...]] = None, + api_key: str | None = None, + timeout: int | None = None, + client_agents: tuple[str, ...] | None = None, ) -> None: """ Parameters diff --git a/meilisearch/errors.py b/meilisearch/errors.py index 57ca2bc2..c8ea8209 100644 --- a/meilisearch/errors.py +++ b/meilisearch/errors.py @@ -1,16 +1,12 @@ from __future__ import annotations import json +from collections.abc import Callable from functools import wraps -from typing import TYPE_CHECKING, Any, Callable, TypeVar +from typing import Any, TypeVar from requests import Response -if TYPE_CHECKING: # pragma: no cover - from meilisearch.client import Client - from meilisearch.index import Index - from meilisearch.task import TaskHandler - T = TypeVar("T") diff --git a/meilisearch/index.py b/meilisearch/index.py index 6c65874a..db525a77 100644 --- a/meilisearch/index.py +++ b/meilisearch/index.py @@ -1,18 +1,10 @@ from __future__ import annotations +from collections.abc import Generator, Mapping, MutableMapping, Sequence from datetime import datetime from typing import ( TYPE_CHECKING, Any, - Dict, - Generator, - List, - Mapping, - MutableMapping, - Optional, - Sequence, - Type, - Union, ) from urllib import parse from warnings import warn @@ -50,7 +42,6 @@ from json import JSONEncoder -# pylint: disable=too-many-public-methods, too-many-lines class Index: """ Indexes routes wrapper. @@ -63,10 +54,10 @@ def __init__( self, config: Config, uid: str, - primary_key: Optional[str] = None, - created_at: Optional[Union[datetime, str]] = None, - updated_at: Optional[Union[datetime, str]] = None, - custom_headers: Optional[Mapping[str, str]] = None, + primary_key: str | None = None, + created_at: datetime | str | None = None, + updated_at: datetime | str | None = None, + custom_headers: Mapping[str, str] | None = None, ) -> None: """ Parameters @@ -86,7 +77,7 @@ def __init__( self.created_at = iso_to_date_time(created_at) self.updated_at = iso_to_date_time(updated_at) - def delete(self, *, metadata: Optional[str] = None) -> TaskInfo: + def delete(self, *, metadata: str | None = None) -> TaskInfo: """Delete the index. Parameters @@ -115,10 +106,10 @@ def delete(self, *, metadata: Optional[str] = None) -> TaskInfo: def update( self, - primary_key: Optional[str] = None, - new_uid: Optional[str] = None, + primary_key: str | None = None, + new_uid: str | None = None, *, - metadata: Optional[str] = None, + metadata: str | None = None, ) -> TaskInfo: """Update the index primary-key. @@ -198,10 +189,10 @@ def get_primary_key(self) -> str | None: def create( config: Config, uid: str, - options: Optional[Mapping[str, Any]] = None, - custom_headers: Optional[Mapping[str, str]] = None, + options: Mapping[str, Any] | None = None, + custom_headers: Mapping[str, str] | None = None, *, - metadata: Optional[str] = None, + metadata: str | None = None, ) -> TaskInfo: """Create the index. @@ -235,7 +226,7 @@ def create( return TaskInfo(**task) - def get_tasks(self, parameters: Optional[MutableMapping[str, Any]] = None) -> TaskResults: + def get_tasks(self, parameters: MutableMapping[str, Any] | None = None) -> TaskResults: """Get all tasks of a specific index from the last one. Parameters @@ -333,7 +324,7 @@ def get_stats(self) -> IndexStats: return IndexStats(**stats) @version_error_hint_message - def search(self, query: str, opt_params: Optional[Mapping[str, Any]] = None) -> Dict[str, Any]: + def search(self, query: str, opt_params: Mapping[str, Any] | None = None) -> dict[str, Any]: """Search in the index. https://www.meilisearch.com/docs/reference/api/search @@ -379,9 +370,9 @@ def search(self, query: str, opt_params: Optional[Mapping[str, Any]] = None) -> def facet_search( self, facet_name: str, - facet_query: Optional[str] = None, - opt_params: Optional[Mapping[str, Any]] = None, - ) -> Dict[str, Any]: + facet_query: str | None = None, + opt_params: Mapping[str, Any] | None = None, + ) -> dict[str, Any]: """ Perform a facet search based on the given facet query and facet name. @@ -409,7 +400,7 @@ def facet_search( ) def get_document( - self, document_id: Union[str, int], parameters: Optional[MutableMapping[str, Any]] = None + self, document_id: str | int, parameters: MutableMapping[str, Any] | None = None ) -> Document: """Get one document with given document identifier. @@ -441,9 +432,7 @@ def get_document( return Document(document) @version_error_hint_message - def get_documents( - self, parameters: Optional[MutableMapping[str, Any]] = None - ) -> DocumentsResults: + def get_documents(self, parameters: MutableMapping[str, Any] | None = None) -> DocumentsResults: """Get a set of documents from the index. Parameters @@ -481,7 +470,7 @@ def get_documents( ) return DocumentsResults(response) - def get_similar_documents(self, parameters: Mapping[str, Any]) -> Dict[str, Any]: + def get_similar_documents(self, parameters: Mapping[str, Any]) -> dict[str, Any]: """Get the documents similar to a document. Parameters @@ -510,11 +499,11 @@ def get_similar_documents(self, parameters: Mapping[str, Any]) -> Dict[str, Any] def add_documents( self, documents: Sequence[Mapping[str, Any]], - primary_key: Optional[str] = None, + primary_key: str | None = None, *, - serializer: Optional[Type[JSONEncoder]] = None, - skip_creation: Optional[bool] = None, - metadata: Optional[str] = None, + serializer: type[JSONEncoder] | None = None, + skip_creation: bool | None = None, + metadata: str | None = None, ) -> TaskInfo: """Add documents to the index. @@ -552,12 +541,12 @@ def add_documents_in_batches( self, documents: Sequence[Mapping[str, Any]], batch_size: int = 1000, - primary_key: Optional[str] = None, + primary_key: str | None = None, *, - serializer: Optional[Type[JSONEncoder]] = None, - skip_creation: Optional[bool] = None, - metadata: Optional[str] = None, - ) -> List[TaskInfo]: + serializer: type[JSONEncoder] | None = None, + skip_creation: bool | None = None, + metadata: str | None = None, + ) -> list[TaskInfo]: """Add documents to the index in batches. Parameters @@ -590,7 +579,7 @@ def add_documents_in_batches( Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors """ - tasks: List[TaskInfo] = [] + tasks: list[TaskInfo] = [] for document_batch in self._batch(documents, batch_size): task = self.add_documents( @@ -607,11 +596,11 @@ def add_documents_in_batches( def add_documents_json( self, str_documents: bytes, - primary_key: Optional[str] = None, + primary_key: str | None = None, *, - serializer: Optional[Type[JSONEncoder]] = None, - skip_creation: Optional[bool] = None, - metadata: Optional[str] = None, + serializer: type[JSONEncoder] | None = None, + skip_creation: bool | None = None, + metadata: str | None = None, ) -> TaskInfo: """Add documents to the index from a byte-encoded JSON string. @@ -653,11 +642,11 @@ def add_documents_json( def add_documents_csv( self, str_documents: bytes, - primary_key: Optional[str] = None, - csv_delimiter: Optional[str] = None, + primary_key: str | None = None, + csv_delimiter: str | None = None, *, - skip_creation: Optional[bool] = None, - metadata: Optional[str] = None, + skip_creation: bool | None = None, + metadata: str | None = None, ) -> TaskInfo: """Add documents to the index from a byte-encoded CSV string. @@ -698,10 +687,10 @@ def add_documents_csv( def add_documents_ndjson( self, str_documents: bytes, - primary_key: Optional[str] = None, + primary_key: str | None = None, *, - skip_creation: Optional[bool] = None, - metadata: Optional[str] = None, + skip_creation: bool | None = None, + metadata: str | None = None, ) -> TaskInfo: """Add documents to the index from a byte-encoded NDJSON string. @@ -739,13 +728,13 @@ def add_documents_ndjson( def add_documents_raw( self, str_documents: bytes, - primary_key: Optional[str] = None, - content_type: Optional[str] = None, - csv_delimiter: Optional[str] = None, + primary_key: str | None = None, + content_type: str | None = None, + csv_delimiter: str | None = None, *, - serializer: Optional[Type[JSONEncoder]] = None, - skip_creation: Optional[bool] = None, - metadata: Optional[str] = None, + serializer: type[JSONEncoder] | None = None, + skip_creation: bool | None = None, + metadata: str | None = None, ) -> TaskInfo: """Add documents to the index from a byte-encoded string. @@ -792,11 +781,11 @@ def add_documents_raw( def update_documents( self, documents: Sequence[Mapping[str, Any]], - primary_key: Optional[str] = None, + primary_key: str | None = None, *, - serializer: Optional[Type[JSONEncoder]] = None, - skip_creation: Optional[bool] = None, - metadata: Optional[str] = None, + serializer: type[JSONEncoder] | None = None, + skip_creation: bool | None = None, + metadata: str | None = None, ) -> TaskInfo: """Update documents in the index. @@ -833,10 +822,10 @@ def update_documents( def update_documents_ndjson( self, str_documents: str, - primary_key: Optional[str] = None, + primary_key: str | None = None, *, - skip_creation: Optional[bool] = None, - metadata: Optional[str] = None, + skip_creation: bool | None = None, + metadata: str | None = None, ) -> TaskInfo: """Update documents as a ndjson string in the index. @@ -874,11 +863,11 @@ def update_documents_ndjson( def update_documents_json( self, str_documents: str, - primary_key: Optional[str] = None, + primary_key: str | None = None, *, - serializer: Optional[Type[JSONEncoder]] = None, - skip_creation: Optional[bool] = None, - metadata: Optional[str] = None, + serializer: type[JSONEncoder] | None = None, + skip_creation: bool | None = None, + metadata: str | None = None, ) -> TaskInfo: """Update documents as a json string in the index. @@ -920,11 +909,11 @@ def update_documents_json( def update_documents_csv( self, str_documents: str, - primary_key: Optional[str] = None, - csv_delimiter: Optional[str] = None, + primary_key: str | None = None, + csv_delimiter: str | None = None, *, - skip_creation: Optional[bool] = None, - metadata: Optional[str] = None, + skip_creation: bool | None = None, + metadata: str | None = None, ) -> TaskInfo: """Update documents as a csv string in the index. @@ -965,13 +954,13 @@ def update_documents_csv( def update_documents_raw( self, str_documents: str, - primary_key: Optional[str] = None, - content_type: Optional[str] = None, - csv_delimiter: Optional[str] = None, + primary_key: str | None = None, + content_type: str | None = None, + csv_delimiter: str | None = None, *, - serializer: Optional[Type[JSONEncoder]] = None, - skip_creation: Optional[bool] = None, - metadata: Optional[str] = None, + serializer: type[JSONEncoder] | None = None, + skip_creation: bool | None = None, + metadata: str | None = None, ) -> TaskInfo: """Update documents as a string in the index. @@ -1019,12 +1008,12 @@ def update_documents_in_batches( self, documents: Sequence[Mapping[str, Any]], batch_size: int = 1000, - primary_key: Optional[str] = None, + primary_key: str | None = None, *, - serializer: Optional[Type[JSONEncoder]] = None, - skip_creation: Optional[bool] = None, - metadata: Optional[str] = None, - ) -> List[TaskInfo]: + serializer: type[JSONEncoder] | None = None, + skip_creation: bool | None = None, + metadata: str | None = None, + ) -> list[TaskInfo]: """Update documents to the index in batches. Parameters @@ -1071,9 +1060,7 @@ def update_documents_in_batches( return tasks - def delete_document( - self, document_id: Union[str, int], *, metadata: Optional[str] = None - ) -> TaskInfo: + def delete_document(self, document_id: str | int, *, metadata: str | None = None) -> TaskInfo: """Delete one document from the index. Parameters @@ -1103,12 +1090,10 @@ def delete_document( @version_error_hint_message def delete_documents( self, - ids: Optional[List[Union[str, int]]] = None, + ids: list[str | int] | None = None, *, - filter: Optional[ # pylint: disable=redefined-builtin - Union[str, List[Union[str, List[str]]]] - ] = None, - metadata: Optional[str] = None, + filter: str | list[str | list[str]] | None = None, + metadata: str | None = None, ) -> TaskInfo: """Delete multiple documents from the index by id or filter. @@ -1137,6 +1122,7 @@ def delete_documents( warn( "The use of ids is depreciated and will be removed in the future", DeprecationWarning, + stacklevel=2, ) url = f"{self.config.paths.index}/{self.uid}/{self.config.paths.document}/delete-batch" if metadata is not None: @@ -1155,7 +1141,7 @@ def delete_documents( ) return TaskInfo(**response) - def delete_all_documents(self, *, metadata: Optional[str] = None) -> TaskInfo: + def delete_all_documents(self, *, metadata: str | None = None) -> TaskInfo: """Delete all documents from the index. Parameters @@ -1182,7 +1168,7 @@ def delete_all_documents(self, *, metadata: Optional[str] = None) -> TaskInfo: # GENERAL SETTINGS ROUTES - def get_settings(self) -> Dict[str, Any]: + def get_settings(self) -> dict[str, Any]: """Get settings of the index. https://www.meilisearch.com/docs/reference/api/settings @@ -1222,7 +1208,7 @@ def get_settings(self) -> Dict[str, Any]: return settings def update_settings( - self, body: MutableMapping[str, Any], *, metadata: Optional[str] = None + self, body: MutableMapping[str, Any], *, metadata: str | None = None ) -> TaskInfo: """Update settings of the index. @@ -1281,7 +1267,7 @@ def update_settings( return TaskInfo(**task) - def reset_settings(self, *, metadata: Optional[str] = None) -> TaskInfo: + def reset_settings(self, *, metadata: str | None = None) -> TaskInfo: """Reset settings of the index to default values. https://www.meilisearch.com/docs/reference/api/settings#reset-settings @@ -1311,7 +1297,7 @@ def reset_settings(self, *, metadata: Optional[str] = None) -> TaskInfo: # RANKING RULES SUB-ROUTES - def get_ranking_rules(self) -> List[str]: + def get_ranking_rules(self) -> list[str]: """Get ranking rules of the index. Returns @@ -1326,7 +1312,7 @@ def get_ranking_rules(self) -> List[str]: """ return self.http.get(self.__settings_url_for(self.config.paths.ranking_rules)) - def update_ranking_rules(self, body: Union[List[str], None]) -> TaskInfo: + def update_ranking_rules(self, body: list[str] | None) -> TaskInfo: """Update ranking rules of the index. Parameters @@ -1371,7 +1357,7 @@ def reset_ranking_rules(self) -> TaskInfo: # DISTINCT ATTRIBUTE SUB-ROUTES - def get_distinct_attribute(self) -> Optional[str]: + def get_distinct_attribute(self) -> str | None: """Get distinct attribute of the index. Returns @@ -1431,7 +1417,7 @@ def reset_distinct_attribute(self) -> TaskInfo: # SEARCHABLE ATTRIBUTES SUB-ROUTES - def get_searchable_attributes(self) -> List[str]: + def get_searchable_attributes(self) -> list[str]: """Get searchable attributes of the index. Returns @@ -1446,7 +1432,7 @@ def get_searchable_attributes(self) -> List[str]: """ return self.http.get(self.__settings_url_for(self.config.paths.searchable_attributes)) - def update_searchable_attributes(self, body: Union[List[str], None]) -> TaskInfo: + def update_searchable_attributes(self, body: list[str] | None) -> TaskInfo: """Update searchable attributes of the index. Parameters @@ -1491,7 +1477,7 @@ def reset_searchable_attributes(self) -> TaskInfo: # DISPLAYED ATTRIBUTES SUB-ROUTES - def get_displayed_attributes(self) -> List[str]: + def get_displayed_attributes(self) -> list[str]: """Get displayed attributes of the index. Returns @@ -1506,7 +1492,7 @@ def get_displayed_attributes(self) -> List[str]: """ return self.http.get(self.__settings_url_for(self.config.paths.displayed_attributes)) - def update_displayed_attributes(self, body: Union[List[str], None]) -> TaskInfo: + def update_displayed_attributes(self, body: list[str] | None) -> TaskInfo: """Update displayed attributes of the index. Parameters @@ -1551,7 +1537,7 @@ def reset_displayed_attributes(self) -> TaskInfo: # STOP WORDS SUB-ROUTES - def get_stop_words(self) -> List[str]: + def get_stop_words(self) -> list[str]: """Get stop words of the index. Returns @@ -1566,7 +1552,7 @@ def get_stop_words(self) -> List[str]: """ return self.http.get(self.__settings_url_for(self.config.paths.stop_words)) - def update_stop_words(self, body: Union[List[str], None]) -> TaskInfo: + def update_stop_words(self, body: list[str] | None) -> TaskInfo: """Update stop words of the index. Parameters @@ -1611,7 +1597,7 @@ def reset_stop_words(self) -> TaskInfo: # SYNONYMS SUB-ROUTES - def get_synonyms(self) -> Dict[str, List[str]]: + def get_synonyms(self) -> dict[str, list[str]]: """Get synonyms of the index. Returns @@ -1626,7 +1612,7 @@ def get_synonyms(self) -> Dict[str, List[str]]: """ return self.http.get(self.__settings_url_for(self.config.paths.synonyms)) - def update_synonyms(self, body: Union[Dict[str, List[str]], None]) -> TaskInfo: + def update_synonyms(self, body: dict[str, list[str]] | None) -> TaskInfo: """Update synonyms of the index. Parameters @@ -1671,7 +1657,7 @@ def reset_synonyms(self) -> TaskInfo: # FILTERABLE ATTRIBUTES SUB-ROUTES - def get_filterable_attributes(self) -> List[str]: + def get_filterable_attributes(self) -> list[str]: """Get filterable attributes of the index. Returns @@ -1686,7 +1672,7 @@ def get_filterable_attributes(self) -> List[str]: """ return self.http.get(self.__settings_url_for(self.config.paths.filterable_attributes)) - def update_filterable_attributes(self, body: Union[List[str], None]) -> TaskInfo: + def update_filterable_attributes(self, body: list[str] | None) -> TaskInfo: """Update filterable attributes of the index. Parameters @@ -1731,7 +1717,7 @@ def reset_filterable_attributes(self) -> TaskInfo: # SORTABLE ATTRIBUTES SUB-ROUTES - def get_sortable_attributes(self) -> List[str]: + def get_sortable_attributes(self) -> list[str]: """Get sortable attributes of the index. Returns @@ -1746,7 +1732,7 @@ def get_sortable_attributes(self) -> List[str]: """ return self.http.get(self.__settings_url_for(self.config.paths.sortable_attributes)) - def update_sortable_attributes(self, body: Union[List[str], None]) -> TaskInfo: + def update_sortable_attributes(self, body: list[str] | None) -> TaskInfo: """Update sortable attributes of the index. Parameters @@ -1808,7 +1794,7 @@ def get_typo_tolerance(self) -> TypoTolerance: return TypoTolerance(**typo_tolerance) - def update_typo_tolerance(self, body: Union[Mapping[str, Any], None]) -> TaskInfo: + def update_typo_tolerance(self, body: Mapping[str, Any] | None) -> TaskInfo: """Update typo tolerance of the index. Parameters @@ -1868,7 +1854,7 @@ def get_pagination_settings(self) -> Pagination: return Pagination(**pagination) - def update_pagination_settings(self, body: Union[Dict[str, Any], None]) -> TaskInfo: + def update_pagination_settings(self, body: dict[str, Any] | None) -> TaskInfo: """Update the pagination settings of the index. Parameters @@ -1927,7 +1913,7 @@ def get_facet_search_settings(self) -> bool: return self.http.get(self.__settings_url_for(self.config.paths.facet_search)) - def update_facet_search_settings(self, body: Union[bool, None]) -> TaskInfo: + def update_facet_search_settings(self, body: bool | None) -> TaskInfo: """Update the facet search settings of the index. Parameters @@ -1980,7 +1966,7 @@ def get_faceting_settings(self) -> Faceting: return Faceting(**faceting) - def update_faceting_settings(self, body: Union[Mapping[str, Any], None]) -> TaskInfo: + def update_faceting_settings(self, body: Mapping[str, Any] | None) -> TaskInfo: """Update the faceting settings of the index. Parameters @@ -2024,7 +2010,7 @@ def reset_faceting_settings(self) -> TaskInfo: # USER DICTIONARY SUB-ROUTES - def get_dictionary(self) -> List[str]: + def get_dictionary(self) -> list[str]: """Get the dictionary entries of the index. Returns @@ -2039,7 +2025,7 @@ def get_dictionary(self) -> List[str]: """ return self.http.get(self.__settings_url_for(self.config.paths.dictionary)) - def update_dictionary(self, body: Union[List[str], None]) -> TaskInfo: + def update_dictionary(self, body: list[str] | None) -> TaskInfo: """Update the dictionary of the index. Parameters @@ -2084,7 +2070,7 @@ def reset_dictionary(self) -> TaskInfo: # TEXT SEPARATOR SUB-ROUTES - def get_separator_tokens(self) -> List[str]: + def get_separator_tokens(self) -> list[str]: """Get the additional text separator tokens set on this index. Returns @@ -2099,7 +2085,7 @@ def get_separator_tokens(self) -> List[str]: """ return self.http.get(self.__settings_url_for(self.config.paths.separator_tokens)) - def get_non_separator_tokens(self) -> List[str]: + def get_non_separator_tokens(self) -> list[str]: """Get the list of disabled text separator tokens on this index. Returns @@ -2114,7 +2100,7 @@ def get_non_separator_tokens(self) -> List[str]: """ return self.http.get(self.__settings_url_for(self.config.paths.non_separator_tokens)) - def update_separator_tokens(self, body: Union[List[str], None]) -> TaskInfo: + def update_separator_tokens(self, body: list[str] | None) -> TaskInfo: """Update the additional separator tokens of the index. Parameters @@ -2137,7 +2123,7 @@ def update_separator_tokens(self, body: Union[List[str], None]) -> TaskInfo: return TaskInfo(**task) - def update_non_separator_tokens(self, body: Union[List[str], None]) -> TaskInfo: + def update_non_separator_tokens(self, body: list[str] | None) -> TaskInfo: """Update the disabled separator tokens of the index. Parameters @@ -2244,7 +2230,7 @@ def get_embedders(self) -> Embedders | None: return Embedders(embedders=embedders) - def update_embedders(self, body: Union[MutableMapping[str, Any], None]) -> TaskInfo: + def update_embedders(self, body: MutableMapping[str, Any] | None) -> TaskInfo: """Update embedders of the index. Updates the embedder configuration for the index. The embedder configuration @@ -2332,7 +2318,7 @@ def get_search_cutoff_ms(self) -> int | None: """ return self.http.get(self.__settings_url_for(self.config.paths.search_cutoff_ms)) - def update_search_cutoff_ms(self, body: Union[int, None]) -> TaskInfo: + def update_search_cutoff_ms(self, body: int | None) -> TaskInfo: """Update the search cutoff in ms of the index. Parameters @@ -2394,7 +2380,7 @@ def get_prefix_search(self) -> PrefixSearch: return PrefixSearch[to_snake(prefix_search).upper()] - def update_prefix_search(self, body: Union[PrefixSearch, None]) -> TaskInfo: + def update_prefix_search(self, body: PrefixSearch | None) -> TaskInfo: """Update the prefix search settings of the index. Parameters @@ -2445,7 +2431,7 @@ def get_proximity_precision(self) -> ProximityPrecision: response = self.http.get(self.__settings_url_for(self.config.paths.proximity_precision)) return ProximityPrecision[to_snake(response).upper()] - def update_proximity_precision(self, body: Union[ProximityPrecision, None]) -> TaskInfo: + def update_proximity_precision(self, body: ProximityPrecision | None) -> TaskInfo: """Update the proximity_precision of the index. Parameters @@ -2490,7 +2476,7 @@ def reset_proximity_precision(self) -> TaskInfo: # LOCALIZED ATTRIBUTES SETTINGS - def get_localized_attributes(self) -> Union[List[LocalizedAttributes], None]: + def get_localized_attributes(self) -> list[LocalizedAttributes] | None: """Get the localized_attributes of the index. Returns @@ -2510,9 +2496,7 @@ def get_localized_attributes(self) -> Union[List[LocalizedAttributes], None]: return [LocalizedAttributes(**attrs) for attrs in response] - def update_localized_attributes( - self, body: Union[List[Mapping[str, List[str]]], None] - ) -> TaskInfo: + def update_localized_attributes(self, body: list[Mapping[str, list[str]]] | None) -> TaskInfo: """Update the localized_attributes of the index. Parameters @@ -2557,9 +2541,9 @@ def reset_localized_attributes(self) -> TaskInfo: def get_fields( self, - offset: Optional[int] = None, - limit: Optional[int] = None, - filter: Optional[MutableMapping[str, Any]] = None, # pylint: disable=redefined-builtin + offset: int | None = None, + limit: int | None = None, + filter: MutableMapping[str, Any] | None = None, ) -> FieldsResults: """Get all fields of the index. @@ -2600,7 +2584,7 @@ def get_fields( MeilisearchApiError An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors """ - body: Dict[str, Any] = {} + body: dict[str, Any] = {} if offset is not None: body["offset"] = offset if limit is not None: @@ -2628,10 +2612,10 @@ def __settings_url_for(self, sub_route: str) -> str: def _build_url( self, - primary_key: Optional[str] = None, - csv_delimiter: Optional[str] = None, - skip_creation: Optional[bool] = None, - metadata: Optional[str] = None, + primary_key: str | None = None, + csv_delimiter: str | None = None, + skip_creation: bool | None = None, + metadata: str | None = None, ) -> str: parameters = {} if primary_key: diff --git a/meilisearch/models/document.py b/meilisearch/models/document.py index 8fe72f2b..4af31111 100644 --- a/meilisearch/models/document.py +++ b/meilisearch/models/document.py @@ -1,8 +1,9 @@ -from typing import Any, Dict, Iterator, List +from collections.abc import Iterator +from typing import Any class Document: - def __init__(self, doc: Dict[str, Any]) -> None: + def __init__(self, doc: dict[str, Any]) -> None: self.__dict__.update(**doc) def __getattr__(self, attr: str) -> Any: @@ -15,8 +16,8 @@ def __iter__(self) -> Iterator: class DocumentsResults: - def __init__(self, resp: Dict[str, Any]) -> None: - self.results: List[Document] = [Document(doc) for doc in resp["results"]] + def __init__(self, resp: dict[str, Any]) -> None: + self.results: list[Document] = [Document(doc) for doc in resp["results"]] self.offset: int = resp["offset"] self.limit: int = resp["limit"] self.total: int = resp["total"] @@ -25,8 +26,8 @@ def __init__(self, resp: Dict[str, Any]) -> None: class FieldsResults: """Response object for get_fields containing pagination metadata and field list.""" - def __init__(self, resp: Dict[str, Any]) -> None: - self.results: List[Dict[str, Any]] = resp["results"] + def __init__(self, resp: dict[str, Any]) -> None: + self.results: list[dict[str, Any]] = resp["results"] self.offset: int = resp["offset"] self.limit: int = resp["limit"] self.total: int = resp["total"] diff --git a/meilisearch/models/embedders.py b/meilisearch/models/embedders.py index a58125ea..a451f49a 100644 --- a/meilisearch/models/embedders.py +++ b/meilisearch/models/embedders.py @@ -1,7 +1,7 @@ from __future__ import annotations from enum import Enum -from typing import Any, Dict, Optional, Union +from typing import Any from camel_converter.pydantic_base import CamelBase @@ -65,14 +65,14 @@ class OpenAiEmbedder(CamelBase): """ source: str = "openAi" - url: Optional[str] = None - api_key: Optional[str] = None - model: Optional[str] = None # Defaults to text-embedding-3-small - dimensions: Optional[int] = None # Uses the model default - document_template: Optional[str] = None - document_template_max_bytes: Optional[int] = None # Default to 400 - distribution: Optional[Distribution] = None - binary_quantized: Optional[bool] = None + url: str | None = None + api_key: str | None = None + model: str | None = None # Defaults to text-embedding-3-small + dimensions: int | None = None # Uses the model default + document_template: str | None = None + document_template_max_bytes: int | None = None # Default to 400 + distribution: Distribution | None = None + binary_quantized: bool | None = None class HuggingFaceEmbedder(CamelBase): @@ -103,15 +103,15 @@ class HuggingFaceEmbedder(CamelBase): """ source: str = "huggingFace" - url: Optional[str] = None - model: Optional[str] = None # Defaults to BAAI/bge-base-en-v1.5 - dimensions: Optional[int] = None - revision: Optional[str] = None - document_template: Optional[str] = None - document_template_max_bytes: Optional[int] = None # Default to 400 - distribution: Optional[Distribution] = None - binary_quantized: Optional[bool] = None - pooling: Optional[PoolingType] = PoolingType.USE_MODEL + url: str | None = None + model: str | None = None # Defaults to BAAI/bge-base-en-v1.5 + dimensions: int | None = None + revision: str | None = None + document_template: str | None = None + document_template_max_bytes: int | None = None # Default to 400 + distribution: Distribution | None = None + binary_quantized: bool | None = None + pooling: PoolingType | None = PoolingType.USE_MODEL class OllamaEmbedder(CamelBase): @@ -140,14 +140,14 @@ class OllamaEmbedder(CamelBase): """ source: str = "ollama" - url: Optional[str] = None - api_key: Optional[str] = None - model: Optional[str] = None - dimensions: Optional[int] = None - document_template: Optional[str] = None - document_template_max_bytes: Optional[int] = None - distribution: Optional[Distribution] = None - binary_quantized: Optional[bool] = None + url: str | None = None + api_key: str | None = None + model: str | None = None + dimensions: int | None = None + document_template: str | None = None + document_template_max_bytes: int | None = None + distribution: Distribution | None = None + binary_quantized: bool | None = None class RestEmbedder(CamelBase): @@ -186,18 +186,18 @@ class RestEmbedder(CamelBase): """ source: str = "rest" - url: Optional[str] = None - api_key: Optional[str] = None - dimensions: Optional[int] = None - document_template: Optional[str] = None - document_template_max_bytes: Optional[int] = None - indexing_fragments: Optional[Dict[str, Dict[str, Any]]] = None - search_fragments: Optional[Dict[str, Dict[str, Any]]] = None - request: Dict[str, Any] - response: Dict[str, Any] - headers: Optional[Dict[str, str]] = None - distribution: Optional[Distribution] = None - binary_quantized: Optional[bool] = None + url: str | None = None + api_key: str | None = None + dimensions: int | None = None + document_template: str | None = None + document_template_max_bytes: int | None = None + indexing_fragments: dict[str, dict[str, Any]] | None = None + search_fragments: dict[str, dict[str, Any]] | None = None + request: dict[str, Any] + response: dict[str, Any] + headers: dict[str, str] | None = None + distribution: Distribution | None = None + binary_quantized: bool | None = None class UserProvidedEmbedder(CamelBase): @@ -217,8 +217,8 @@ class UserProvidedEmbedder(CamelBase): source: str = "userProvided" dimensions: int - distribution: Optional[Distribution] = None - binary_quantized: Optional[bool] = None + distribution: Distribution | None = None + binary_quantized: bool | None = None class CompositeEmbedder(CamelBase): @@ -244,31 +244,23 @@ class CompositeEmbedder(CamelBase): ]""" source: str = "composite" - search_embedder: Union[ - OpenAiEmbedder, - HuggingFaceEmbedder, - OllamaEmbedder, - RestEmbedder, - UserProvidedEmbedder, - ] - indexing_embedder: Union[ - OpenAiEmbedder, - HuggingFaceEmbedder, - OllamaEmbedder, - RestEmbedder, - UserProvidedEmbedder, - ] + search_embedder: ( + OpenAiEmbedder | HuggingFaceEmbedder | OllamaEmbedder | RestEmbedder | UserProvidedEmbedder + ) + indexing_embedder: ( + OpenAiEmbedder | HuggingFaceEmbedder | OllamaEmbedder | RestEmbedder | UserProvidedEmbedder + ) # Type alias for the embedder union type -EmbedderType = Union[ - OpenAiEmbedder, - HuggingFaceEmbedder, - OllamaEmbedder, - RestEmbedder, - UserProvidedEmbedder, - CompositeEmbedder, -] +EmbedderType = ( + OpenAiEmbedder + | HuggingFaceEmbedder + | OllamaEmbedder + | RestEmbedder + | UserProvidedEmbedder + | CompositeEmbedder +) class Embedders(CamelBase): @@ -280,4 +272,4 @@ class Embedders(CamelBase): Dictionary of embedder configurations, where keys are embedder names """ - embedders: Dict[str, EmbedderType] + embedders: dict[str, EmbedderType] diff --git a/meilisearch/models/index.py b/meilisearch/models/index.py index bd60f848..3cd13bee 100644 --- a/meilisearch/models/index.py +++ b/meilisearch/models/index.py @@ -1,19 +1,20 @@ from __future__ import annotations +from collections.abc import Iterator from enum import Enum -from typing import Any, Dict, Iterator, List, Optional +from typing import Any from camel_converter.pydantic_base import CamelBase from pydantic import ConfigDict, field_validator class FieldDistribution: - __dict: Dict + __dict: dict - def __init__(self, dist: Dict[str, int]) -> None: + def __init__(self, dist: dict[str, int]) -> None: self.__dict = dist - for key in dist: - setattr(self, key, dist[key]) + for key, value in dist.items(): + setattr(self, key, value) def __getattr__(self, attr: str) -> str: if attr in self.__dict.keys(): @@ -42,7 +43,7 @@ def build_field_distribution(cls, v: Any) -> FieldDistribution: class Faceting(CamelBase): max_values_per_facet: int - sort_facet_values_by: Optional[Dict[str, str]] = None + sort_facet_values_by: dict[str, str] | None = None class Pagination(CamelBase): @@ -50,16 +51,16 @@ class Pagination(CamelBase): class MinWordSizeForTypos(CamelBase): - one_typo: Optional[int] = None - two_typos: Optional[int] = None + one_typo: int | None = None + two_typos: int | None = None class TypoTolerance(CamelBase): enabled: bool = True disable_on_numbers: bool = False - disable_on_attributes: Optional[List[str]] = None - disable_on_words: Optional[List[str]] = None - min_word_size_for_typos: Optional[MinWordSizeForTypos] = None + disable_on_attributes: list[str] | None = None + disable_on_words: list[str] | None = None + min_word_size_for_typos: MinWordSizeForTypos | None = None class PrefixSearch(str, Enum): @@ -85,5 +86,5 @@ class EmbedderDistribution(CamelBase): class LocalizedAttributes(CamelBase): - attribute_patterns: List[str] - locales: List[str] + attribute_patterns: list[str] + locales: list[str] diff --git a/meilisearch/models/key.py b/meilisearch/models/key.py index b5cb9d02..a9399d4f 100644 --- a/meilisearch/models/key.py +++ b/meilisearch/models/key.py @@ -1,5 +1,4 @@ from datetime import datetime -from typing import List, Optional, Union import pydantic from camel_converter.pydantic_base import CamelBase @@ -9,29 +8,25 @@ class _KeyBase(CamelBase): uid: str - name: Optional[str] = None - description: Optional[str] - actions: List[str] - indexes: List[str] - expires_at: Optional[datetime] = None + name: str | None = None + description: str | None + actions: list[str] + indexes: list[str] + expires_at: datetime | None = None if is_pydantic_2(): model_config = pydantic.ConfigDict(ser_json_timedelta="iso8601") # type: ignore[typeddict-unknown-key] @pydantic.field_validator("expires_at", mode="before") # type: ignore[attr-defined] @classmethod - def validate_expires_at( # pylint: disable=invalid-name - cls, v: str - ) -> Union[datetime, None]: + def validate_expires_at(cls, v: str) -> datetime | None: return iso_to_date_time(v) else: # pragma: no cover @pydantic.validator("expires_at", pre=True) @classmethod - def validate_expires_at( # pylint: disable=invalid-name - cls, v: str - ) -> Union[datetime, None]: + def validate_expires_at(cls, v: str) -> datetime | None: return iso_to_date_time(v) class Config: @@ -51,13 +46,13 @@ class Config: class Key(_KeyBase): key: str created_at: datetime - updated_at: Optional[datetime] = None + updated_at: datetime | None = None if is_pydantic_2(): @pydantic.field_validator("created_at", mode="before") # type: ignore[attr-defined] @classmethod - def validate_created_at(cls, v: str) -> datetime: # pylint: disable=invalid-name + def validate_created_at(cls, v: str) -> datetime: converted = iso_to_date_time(v) if not converted: @@ -67,16 +62,14 @@ def validate_created_at(cls, v: str) -> datetime: # pylint: disable=invalid-nam @pydantic.field_validator("updated_at", mode="before") # type: ignore[attr-defined] @classmethod - def validate_updated_at( # pylint: disable=invalid-name - cls, v: str - ) -> Union[datetime, None]: + def validate_updated_at(cls, v: str) -> datetime | None: return iso_to_date_time(v) else: # pragma: no cover @pydantic.validator("created_at", pre=True) @classmethod - def validate_created_at(cls, v: str) -> datetime: # pylint: disable=invalid-name + def validate_created_at(cls, v: str) -> datetime: converted = iso_to_date_time(v) if not converted: @@ -86,19 +79,17 @@ def validate_created_at(cls, v: str) -> datetime: # pylint: disable=invalid-nam @pydantic.validator("updated_at", pre=True) @classmethod - def validate_updated_at( # pylint: disable=invalid-name - cls, v: str - ) -> Union[datetime, None]: + def validate_updated_at(cls, v: str) -> datetime | None: return iso_to_date_time(v) class KeyUpdate(CamelBase): key: str - name: Optional[str] = None - description: Optional[str] = None - actions: Optional[List[str]] = None - indexes: Optional[List[str]] = None - expires_at: Optional[datetime] = None + name: str | None = None + description: str | None = None + actions: list[str] | None = None + indexes: list[str] | None = None + expires_at: datetime | None = None if is_pydantic_2(): model_config = pydantic.ConfigDict(ser_json_timedelta="iso8601") # type: ignore[typeddict-unknown-key] @@ -120,7 +111,7 @@ class Config: class KeysResults(CamelBase): - results: List[Key] + results: list[Key] offset: int limit: int total: int diff --git a/meilisearch/models/task.py b/meilisearch/models/task.py index 79643b6a..77ba34f9 100644 --- a/meilisearch/models/task.py +++ b/meilisearch/models/task.py @@ -1,7 +1,7 @@ from __future__ import annotations from datetime import datetime -from typing import Any, Dict, List, Optional, Union +from typing import Any import pydantic from camel_converter.pydantic_base import CamelBase @@ -11,24 +11,24 @@ class Task(CamelBase): uid: int - index_uid: Union[str, None] = None + index_uid: str | None = None status: str type: str - details: Union[Dict[str, Any], None] = None - error: Union[Dict[str, Any], None] = None - canceled_by: Union[int, None] = None - duration: Optional[str] = None + details: dict[str, Any] | None = None + error: dict[str, Any] | None = None + canceled_by: int | None = None + duration: str | None = None enqueued_at: datetime - started_at: Optional[datetime] = None - finished_at: Optional[datetime] = None - network: Optional[Dict[str, Any]] = None - custom_metadata: Optional[str] = None + started_at: datetime | None = None + finished_at: datetime | None = None + network: dict[str, Any] | None = None + custom_metadata: str | None = None if is_pydantic_2(): @pydantic.field_validator("enqueued_at", mode="before") # type: ignore[attr-defined] @classmethod - def validate_enqueued_at(cls, v: str) -> datetime: # pylint: disable=invalid-name + def validate_enqueued_at(cls, v: str) -> datetime: converted = iso_to_date_time(v) if not converted: # pragma: no cover @@ -37,23 +37,19 @@ def validate_enqueued_at(cls, v: str) -> datetime: # pylint: disable=invalid-na @pydantic.field_validator("started_at", mode="before") # type: ignore[attr-defined] @classmethod - def validate_started_at( # pylint: disable=invalid-name - cls, v: str - ) -> Union[datetime, None]: + def validate_started_at(cls, v: str) -> datetime | None: return iso_to_date_time(v) @pydantic.field_validator("finished_at", mode="before") # type: ignore[attr-defined] @classmethod - def validate_finished_at( # pylint: disable=invalid-name - cls, v: str - ) -> Union[datetime, None]: + def validate_finished_at(cls, v: str) -> datetime | None: return iso_to_date_time(v) else: # pragma: no cover @pydantic.validator("enqueued_at", pre=True) @classmethod - def validate_enqueued_at(cls, v: str) -> datetime: # pylint: disable=invalid-name + def validate_enqueued_at(cls, v: str) -> datetime: converted = iso_to_date_time(v) if not converted: @@ -63,22 +59,18 @@ def validate_enqueued_at(cls, v: str) -> datetime: # pylint: disable=invalid-na @pydantic.validator("started_at", pre=True) @classmethod - def validate_started_at( # pylint: disable=invalid-name - cls, v: str - ) -> Union[datetime, None]: + def validate_started_at(cls, v: str) -> datetime | None: return iso_to_date_time(v) @pydantic.validator("finished_at", pre=True) @classmethod - def validate_finished_at( # pylint: disable=invalid-name - cls, v: str - ) -> Union[datetime, None]: + def validate_finished_at(cls, v: str) -> datetime | None: return iso_to_date_time(v) class TaskInfo(CamelBase): task_uid: int - index_uid: Union[str, None] + index_uid: str | None status: str type: str enqueued_at: datetime @@ -87,7 +79,7 @@ class TaskInfo(CamelBase): @pydantic.field_validator("enqueued_at", mode="before") # type: ignore[attr-defined] @classmethod - def validate_enqueued_at(cls, v: str) -> datetime: # pylint: disable=invalid-name + def validate_enqueued_at(cls, v: str) -> datetime: converted = iso_to_date_time(v) if not converted: # pragma: no cover @@ -99,7 +91,7 @@ def validate_enqueued_at(cls, v: str) -> datetime: # pylint: disable=invalid-na @pydantic.validator("enqueued_at", pre=True) @classmethod - def validate_enqueued_at(cls, v: str) -> datetime: # pylint: disable=invalid-name + def validate_enqueued_at(cls, v: str) -> datetime: converted = iso_to_date_time(v) if not converted: @@ -109,51 +101,51 @@ def validate_enqueued_at(cls, v: str) -> datetime: # pylint: disable=invalid-na class TaskResults(CamelBase): - results: List[Task] + results: list[Task] limit: int total: int - from_: Optional[int] - next_: Optional[int] + from_: int | None + next_: int | None class Batch(CamelBase): uid: int - details: Optional[Dict[str, Any]] = None - stats: Optional[Dict[str, Union[int, Dict[str, Any]]]] = None - duration: Optional[str] = None - started_at: Optional[datetime] = None - finished_at: Optional[datetime] = None - progress: Optional[Dict[str, Union[float, List[Dict[str, Any]]]]] = None + details: dict[str, Any] | None = None + stats: dict[str, int | dict[str, Any]] | None = None + duration: str | None = None + started_at: datetime | None = None + finished_at: datetime | None = None + progress: dict[str, float | list[dict[str, Any]]] | None = None if is_pydantic_2(): @pydantic.field_validator("started_at", mode="before") # type: ignore[attr-defined] @classmethod - def validate_started_at(cls, v: str) -> Optional[datetime]: # pylint: disable=invalid-name + def validate_started_at(cls, v: str) -> datetime | None: return iso_to_date_time(v) @pydantic.field_validator("finished_at", mode="before") # type: ignore[attr-defined] @classmethod - def validate_finished_at(cls, v: str) -> Optional[datetime]: # pylint: disable=invalid-name + def validate_finished_at(cls, v: str) -> datetime | None: return iso_to_date_time(v) else: # pragma: no cover @pydantic.validator("started_at", pre=True) @classmethod - def validate_started_at(cls, v: str) -> Optional[datetime]: # pylint: disable=invalid-name + def validate_started_at(cls, v: str) -> datetime | None: return iso_to_date_time(v) @pydantic.validator("finished_at", pre=True) @classmethod - def validate_finished_at(cls, v: str) -> Optional[datetime]: # pylint: disable=invalid-name + def validate_finished_at(cls, v: str) -> datetime | None: return iso_to_date_time(v) class BatchResults(CamelBase): - results: List[Batch] + results: list[Batch] total: int limit: int from_: int # None means last page - next_: Optional[int] + next_: int | None diff --git a/meilisearch/models/webhook.py b/meilisearch/models/webhook.py index b20809fc..4a540eac 100644 --- a/meilisearch/models/webhook.py +++ b/meilisearch/models/webhook.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Optional +from typing import Any from camel_converter.pydantic_base import CamelBase from pydantic import ConfigDict @@ -11,7 +11,7 @@ class Webhook(CamelBase): uuid: str url: str - headers: Optional[Dict[str, Any]] = None + headers: dict[str, Any] | None = None isEditable: bool @@ -19,4 +19,4 @@ class WebhooksResults(CamelBase): """Model for webhooks list results.""" model_config = ConfigDict(arbitrary_types_allowed=True) - results: List[Webhook] + results: list[Webhook] diff --git a/meilisearch/task.py b/meilisearch/task.py index 998746b7..06cae8f9 100644 --- a/meilisearch/task.py +++ b/meilisearch/task.py @@ -1,8 +1,9 @@ from __future__ import annotations +from collections.abc import Mapping, MutableMapping from datetime import datetime from time import sleep -from typing import Any, Mapping, MutableMapping, Optional +from typing import Any from urllib import parse from meilisearch._httprequests import HttpRequests @@ -19,7 +20,7 @@ class TaskHandler: https://www.meilisearch.com/docs/reference/api/tasks """ - def __init__(self, config: Config, custom_headers: Optional[Mapping[str, str]] = None): + def __init__(self, config: Config, custom_headers: Mapping[str, str] | None = None): """Parameters ---------- config: Config object containing permission and location of Meilisearch. @@ -27,7 +28,7 @@ def __init__(self, config: Config, custom_headers: Optional[Mapping[str, str]] = self.config = config self.http = HttpRequests(config, custom_headers) - def get_batches(self, parameters: Optional[MutableMapping[str, Any]] = None) -> BatchResults: + def get_batches(self, parameters: MutableMapping[str, Any] | None = None) -> BatchResults: """Get all task batches. Parameters @@ -74,7 +75,7 @@ def get_batch(self, uid: int) -> Batch: batch = self.http.get(f"{self.config.paths.batch}/{uid}") return Batch(**batch) - def get_tasks(self, parameters: Optional[MutableMapping[str, Any]] = None) -> TaskResults: + def get_tasks(self, parameters: MutableMapping[str, Any] | None = None) -> TaskResults: """Get all tasks. Parameters @@ -123,7 +124,7 @@ def get_task(self, uid: int) -> Task: return Task(**task) def cancel_tasks( - self, parameters: MutableMapping[str, Any], *, metadata: Optional[str] = None + self, parameters: MutableMapping[str, Any], *, metadata: str | None = None ) -> TaskInfo: """Cancel a list of enqueued or processing tasks. @@ -154,7 +155,7 @@ def cancel_tasks( return TaskInfo(**response) def delete_tasks( - self, parameters: MutableMapping[str, Any], *, metadata: Optional[str] = None + self, parameters: MutableMapping[str, Any], *, metadata: str | None = None ) -> TaskInfo: """Delete a list of enqueued or processing tasks. Parameters diff --git a/pyproject.toml b/pyproject.toml index fd6779df..9ebe8502 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,9 +46,7 @@ test = [ lint = [ "mypy>=1.19.1", - "pylint>=v3.3.9", "ruff>=0.15.17", - "isort>=6.1.0", ] docs = [ @@ -73,58 +71,50 @@ meilisearch = ["py.typed"] [tool.ruff] line-length = 100 -[tool.isort] -profile = "black" -line_length = 100 -src_paths = ["meilisearch", "tests"] - -[tool.mypy] -disallow_untyped_defs = true - -[[tool.mypy.overrides]] -module = ["tests.*"] -disallow_untyped_defs = false -[tool.pylint.MASTER] -load-plugins = [ - 'pylint.extensions.bad_builtin', +[tool.ruff.lint] +select = [ + "E", # pycodestyle errors + "W", # pycodestyle warnings + "F", # pyflakes + "B", # flake8-bugbear + "I", # isort + "UP", # pyupgrade + "PL", # pylint + "T201", # flake8-print: disallow `print` + "T203", # flake8-print: disallow `pprint` + "RUF022", # Ruff: unsorted `__all__` + "RUF023", # Ruff: unsorted `__slots__` ] - -[tool.pylint.'DEPRECATED_BUILTINS'] -bad-functions=[ - "map", - "filter", - "input" +ignore = [ + # Recommended ignores by ruff when using the formatter + "E501", + "W191", + "E111", + "E114", + "E117", + "D206", + "D300", + "Q000", + "Q001", + "Q002", + "Q003", + "COM812", + "COM819", + "ISC001", + "ISC002", ] -[tool.pylint.'BASIC'] -const-rgx = "(([A-Z_][A-Z0-9_]*)|(__.*__))$" -attr-rgx = "[a-z_][a-z0-9_]{2,}$" -module-rgx = "(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$" -method-rgx = "[a-z_][a-z0-9_]{2,}$" - -[tool.pylint.'DESIGN'] +[tool.ruff.lint.pylint] max-args = 10 max-public-methods = 25 +allow-magic-value-types = ["int", "float", "str", "bytes"] -[tool.pylint.'FORMAT'] -max-module-lines=2000 - -[tool.pylint.'MESSAGES CONTROL'] -disable=[ - "attribute-defined-outside-init", - "duplicate-code", - "missing-docstring", - "too-few-public-methods", - "line-too-long", - "too-many-positional-arguments", -] -enable=[ - "use-symbolic-message-instead", - "fixme", -] +[tool.mypy] +disallow_untyped_defs = true -[tool.pylint.'REPORTS'] -reports=false +[[tool.mypy.overrides]] +module = ["tests.*"] +disallow_untyped_defs = false [tool.pytest.ini_options] minversion = "6.0" diff --git a/tests/__init__.py b/tests/__init__.py index b590dcda..9200a52f 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +1,3 @@ from .common import BASE_URL, MASTER_KEY + +__all__ = ["BASE_URL", "MASTER_KEY"] diff --git a/tests/client/test_chat_completions.py b/tests/client/test_chat_completions.py index c48418f7..280ee77f 100644 --- a/tests/client/test_chat_completions.py +++ b/tests/client/test_chat_completions.py @@ -1,5 +1,3 @@ -# pylint: disable=invalid-name - from unittest.mock import patch import pytest @@ -55,7 +53,7 @@ def test_create_chat_completion_basic_stream(client): assert len(chunks) == 2 assert chunks[0]["choices"][0]["delta"]["content"] == "Hello" assert chunks[1]["choices"][0]["delta"]["content"] == " world" - assert mock_resp._closed # pylint: disable=protected-access + assert mock_resp._closed def test_create_chat_completion_stream_false_raises_error(client): diff --git a/tests/client/test_client.py b/tests/client/test_client.py index 2450a396..e1d0f896 100644 --- a/tests/client/test_client.py +++ b/tests/client/test_client.py @@ -1,5 +1,3 @@ -# pylint: disable=invalid-name - import pytest import meilisearch diff --git a/tests/client/test_client_dumps.py b/tests/client/test_client_dumps.py index 3cb78c82..476957ef 100644 --- a/tests/client/test_client_dumps.py +++ b/tests/client/test_client_dumps.py @@ -1,6 +1,3 @@ -# pylint: disable=invalid-name - - def test_dump_creation(client, index_with_documents): """Tests the creation of a Meilisearch dump.""" index_with_documents("indexUID-dump-creation") diff --git a/tests/client/test_client_exports.py b/tests/client/test_client_exports.py index 856aa482..6071666f 100644 --- a/tests/client/test_client_exports.py +++ b/tests/client/test_client_exports.py @@ -11,7 +11,7 @@ ) -def test_export_creation(client, client2, index_with_documents, enable_vector_search): # pylint: disable=unused-argument +def test_export_creation(client, client2, index_with_documents, enable_vector_search): """Tests the creation of a Meilisearch export.""" index = index_with_documents() export_task = client.export(common.BASE_URL_2, api_key=common.MASTER_KEY) @@ -26,7 +26,7 @@ def test_export_creation(client, client2, index_with_documents, enable_vector_se def test_export_creation_with_index_filter( client, client2, index_with_documents, enable_vector_search -): # pylint: disable=unused-argument +): """Tests the creation of a Meilisearch export with specific index UIDs.""" index = index_with_documents() diff --git a/tests/client/test_client_key_meilisearch.py b/tests/client/test_client_key_meilisearch.py index 60c7744a..5916a84d 100644 --- a/tests/client/test_client_key_meilisearch.py +++ b/tests/client/test_client_key_meilisearch.py @@ -31,14 +31,13 @@ def test_get_key(client, test_key): def test_get_key_inexistent(client): """Tests getting a key that does not exists.""" - with pytest.raises(Exception): + with pytest.raises(MeilisearchApiError): client.get_key("No existing key") def test_create_keys_default(client, test_key_info): """Tests the creation of a key with no optional argument.""" key = client.create_key(test_key_info) - print(key) assert key.key is not None assert key.name is not None assert key.expires_at is None @@ -52,7 +51,6 @@ def test_create_keys_default(client, test_key_info): def test_create_keys_without_desc(client, test_nondescript_key_info): """Tests the creation of a key with no optional argument.""" key = client.create_key(test_nondescript_key_info) - print(key) assert key.name == "keyWithoutDescription" assert key.description is None diff --git a/tests/client/test_client_swap_meilisearch.py b/tests/client/test_client_swap_meilisearch.py index ae3b9914..056d3e75 100644 --- a/tests/client/test_client_swap_meilisearch.py +++ b/tests/client/test_client_swap_meilisearch.py @@ -1,5 +1,3 @@ -# pylint: disable=invalid-name - import pytest from meilisearch.errors import MeilisearchApiError diff --git a/tests/client/test_client_task_meilisearch.py b/tests/client/test_client_task_meilisearch.py index 1221a2d1..5c175a84 100644 --- a/tests/client/test_client_task_meilisearch.py +++ b/tests/client/test_client_task_meilisearch.py @@ -1,7 +1,6 @@ -# pylint: disable=invalid-name - import pytest +from meilisearch.errors import MeilisearchApiError from meilisearch.models.task import TaskInfo from tests import common @@ -82,7 +81,7 @@ def test_get_task(client): def test_get_task_inexistent(client): """Tests getting a task that does not exists.""" - with pytest.raises(Exception): + with pytest.raises(MeilisearchApiError): client.get_task("abc") @@ -131,7 +130,7 @@ def test_delete_tasks_by_uid(client, empty_index, small_movies): task_addition = index.add_documents(small_movies) task_deleted = client.delete_tasks({"uids": task_addition.task_uid}) client.wait_for_task(task_deleted.task_uid) - with pytest.raises(Exception): + with pytest.raises(MeilisearchApiError): client.get_task(task_addition.task_uid) task = client.get_task(task_deleted.task_uid) diff --git a/tests/client/test_client_tenant_token.py b/tests/client/test_client_tenant_token.py index 08f6dafe..f3f67652 100644 --- a/tests/client/test_client_tenant_token.py +++ b/tests/client/test_client_tenant_token.py @@ -1,5 +1,3 @@ -# pylint: disable=invalid-name - import datetime from copy import deepcopy @@ -89,7 +87,7 @@ def test_generate_tenant_token_with_empty_search_rules_in_list(get_private_key): """Tests create a tenant token without search rules.""" client = meilisearch.Client(BASE_URL, get_private_key.key) - with pytest.raises(Exception): + with pytest.raises(ValueError): client.generate_tenant_token(api_key_uid=get_private_key.uid, search_rules=[""]) @@ -97,7 +95,7 @@ def test_generate_tenant_token_without_search_rules_in_list(get_private_key): """Tests create a tenant token without search rules.""" client = meilisearch.Client(BASE_URL, get_private_key.key) - with pytest.raises(Exception): + with pytest.raises(ValueError): client.generate_tenant_token(api_key_uid=get_private_key.uid, search_rules=[]) @@ -105,7 +103,7 @@ def test_generate_tenant_token_without_search_rules_in_dict(get_private_key): """Tests create a tenant token without search rules.""" client = meilisearch.Client(BASE_URL, get_private_key.key) - with pytest.raises(Exception): + with pytest.raises(ValueError): client.generate_tenant_token(api_key_uid=get_private_key.uid, search_rules={}) @@ -113,7 +111,7 @@ def test_generate_tenant_token_with_empty_search_rules_in_dict(get_private_key): """Tests create a tenant token without search rules.""" client = meilisearch.Client(BASE_URL, get_private_key.key) - with pytest.raises(Exception): + with pytest.raises(TypeError): client.generate_tenant_token(api_key_uid=get_private_key.uid, search_rules={""}) @@ -123,7 +121,7 @@ def test_generate_tenant_token_with_bad_expires_at(client, get_private_key): yesterday = datetime.datetime.now(tz=datetime.timezone.utc) + datetime.timedelta(days=-1) - with pytest.raises(Exception): + with pytest.raises(ValueError): client.generate_tenant_token( api_key_uid=get_private_key.uid, search_rules=["*"], expires_at=yesterday ) @@ -133,13 +131,13 @@ def test_generate_tenant_token_with_no_api_key(client): """Tests create a tenant token with no api key.""" client = meilisearch.Client(BASE_URL) - with pytest.raises(Exception): - client.generate_tenant_token(search_rules=["*"]) # pylint: disable=no-value-for-parameter + with pytest.raises(TypeError): + client.generate_tenant_token(search_rules=["*"]) def test_generate_tenant_token_with_no_uid(client, get_private_key): """Tests create a tenant token with no uid.""" client = meilisearch.Client(BASE_URL, get_private_key.key) - with pytest.raises(Exception): + with pytest.raises(ValueError): client.generate_tenant_token(api_key_uid=None, search_rules=["*"]) diff --git a/tests/client/test_clinet_snapshots.py b/tests/client/test_clinet_snapshots.py index 7822dfa6..82d26d1c 100644 --- a/tests/client/test_clinet_snapshots.py +++ b/tests/client/test_clinet_snapshots.py @@ -1,6 +1,3 @@ -# pylint: disable=invalid-name - - def test_snapshot_creation(client, index_with_documents): """Tests the creation of a Meilisearch snapshot.""" index_with_documents("indexUID-snapshot-creation") diff --git a/tests/client/test_multimodal.py b/tests/client/test_multimodal.py index b04e6198..762a0205 100644 --- a/tests/client/test_multimodal.py +++ b/tests/client/test_multimodal.py @@ -1,6 +1,7 @@ import base64 import json import os +import warnings from pathlib import Path import pytest @@ -153,7 +154,10 @@ def clear_indexes(self, client): client.wait_for_task(task.task_uid) except MeilisearchApiError as exc: # Index may already have been deleted by another test run; log and continue. - print(f"Warning: failed to delete index {index.uid} during cleanup: {exc}") + warnings.warn( + f"failed to delete index {index.uid} during cleanup: {exc}", + stacklevel=2, + ) @pytest.fixture(scope="class", autouse=True) def setup_index(self, request): diff --git a/tests/client/test_version.py b/tests/client/test_version.py index 599fe47a..5ddf0e32 100644 --- a/tests/client/test_version.py +++ b/tests/client/test_version.py @@ -1,5 +1,3 @@ -# pylint: disable=invalid-name - import re from meilisearch.version import __version__, qualified_version diff --git a/tests/conftest.py b/tests/conftest.py index 7897f80d..5efde68d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,5 @@ -# pylint: disable=redefined-outer-name import json import os -from typing import Optional import requests from pytest import fixture @@ -140,7 +138,7 @@ def nested_movies(): @fixture(scope="function") -def empty_index(client, index_uid: Optional[str] = None): +def empty_index(client, index_uid: str | None = None): index_uid = index_uid if index_uid else common.INDEX_UID def index_maker(index_uid=index_uid): diff --git a/tests/errors/test_api_error_meilisearch.py b/tests/errors/test_api_error_meilisearch.py index 0c91aeeb..6edb2bc0 100644 --- a/tests/errors/test_api_error_meilisearch.py +++ b/tests/errors/test_api_error_meilisearch.py @@ -1,5 +1,3 @@ -# pylint: disable=invalid-name - from unittest.mock import patch import pytest diff --git a/tests/errors/test_communication_error_meilisearch.py b/tests/errors/test_communication_error_meilisearch.py index be67a673..3427501d 100644 --- a/tests/errors/test_communication_error_meilisearch.py +++ b/tests/errors/test_communication_error_meilisearch.py @@ -1,5 +1,3 @@ -# pylint: disable=invalid-name - from unittest.mock import patch import pytest diff --git a/tests/errors/test_timeout_error_meilisearch.py b/tests/errors/test_timeout_error_meilisearch.py index 3d1a7ffd..ba402199 100644 --- a/tests/errors/test_timeout_error_meilisearch.py +++ b/tests/errors/test_timeout_error_meilisearch.py @@ -4,7 +4,7 @@ import requests import meilisearch -from meilisearch.errors import MeilisearchTimeoutError +from meilisearch.errors import MeilisearchCommunicationError, MeilisearchTimeoutError from tests import BASE_URL, MASTER_KEY @@ -22,7 +22,7 @@ def test_client_timeout_set(): timeout = 1 client = meilisearch.Client("http://wrongurl:1234", MASTER_KEY, timeout=timeout) - with pytest.raises(Exception): + with pytest.raises(MeilisearchCommunicationError): client.health() assert client.config.timeout == timeout diff --git a/tests/index/test_index.py b/tests/index/test_index.py index 0894d3ae..58e99265 100644 --- a/tests/index/test_index.py +++ b/tests/index/test_index.py @@ -1,5 +1,3 @@ -# pylint: disable=invalid-name - from datetime import datetime import pytest @@ -92,7 +90,7 @@ def test_index_with_any_uid(client): def test_index_with_none_uid(client): - with pytest.raises(Exception): + with pytest.raises(ValueError): client.index(None) @@ -108,13 +106,13 @@ def test_get_index_with_valid_uid(client): def test_get_index_with_none_uid(client): """Test raising an exception if the index UID is None.""" - with pytest.raises(Exception): + with pytest.raises(MeilisearchApiError): client.get_index(uid=None) def test_get_index_with_wrong_uid(client): """Tests get_index with an non-existing index.""" - with pytest.raises(Exception): + with pytest.raises(MeilisearchApiError): client.get_index(uid="wrongUID") @@ -126,12 +124,12 @@ def test_get_raw_index_with_valid_uid(client): def test_get_raw_index_with_none_uid(client): - with pytest.raises(Exception): + with pytest.raises(MeilisearchApiError): client.get_raw_index(uid=None) def test_get_raw_index_with_wrong_uid(client): - with pytest.raises(Exception): + with pytest.raises(MeilisearchApiError): client.get_raw_index(uid="wrongUID") @@ -188,17 +186,17 @@ def test_delete_index_by_client(client): response = client.index(uid=common.INDEX_UID).delete() assert response.status == "enqueued" client.wait_for_task(response.task_uid) - with pytest.raises(Exception): + with pytest.raises(MeilisearchApiError): client.get_index(uid=common.INDEX_UID) response = client.index(uid=common.INDEX_UID2).delete() assert response.status == "enqueued" client.wait_for_task(response.task_uid) - with pytest.raises(Exception): + with pytest.raises(MeilisearchApiError): client.get_index(uid=common.INDEX_UID2) response = client.index(uid=common.INDEX_UID3).delete() assert response.status == "enqueued" client.wait_for_task(response.task_uid) - with pytest.raises(Exception): + with pytest.raises(MeilisearchApiError): client.get_index(uid=common.INDEX_UID3) assert len(client.get_indexes()["results"]) == 0 diff --git a/tests/index/test_index_document_meilisearch.py b/tests/index/test_index_document_meilisearch.py index a815de26..2448e501 100644 --- a/tests/index/test_index_document_meilisearch.py +++ b/tests/index/test_index_document_meilisearch.py @@ -1,5 +1,3 @@ -# pylint: disable=invalid-name - import json from datetime import datetime from json import JSONEncoder @@ -297,7 +295,7 @@ def test_get_documents_sort_fields(index_with_documents): # prepare expected order sorted_docs = sorted(documents, key=lambda d: (-d["rating"], d["release_date"])) - for resp_doc, expected_doc in zip(response.results, sorted_docs): + for resp_doc, expected_doc in zip(response.results, sorted_docs, strict=True): assert resp_doc.id == expected_doc["id"] assert resp_doc.rating == expected_doc["rating"] assert resp_doc.release_date == expected_doc["release_date"] @@ -334,7 +332,7 @@ def test_get_documents_sort_formats(index_with_documents, sort_param): sorted_docs = sorted(documents, key=lambda d: (-d["rating"], d["release_date"])) - for resp_doc, expected_doc in zip(response.results, sorted_docs): + for resp_doc, expected_doc in zip(response.results, sorted_docs, strict=True): assert resp_doc.id == expected_doc["id"] assert resp_doc.rating == expected_doc["rating"] assert resp_doc.release_date == expected_doc["release_date"] diff --git a/tests/index/test_index_facet_search_meilisearch.py b/tests/index/test_index_facet_search_meilisearch.py index 594b83b5..00ba0489 100644 --- a/tests/index/test_index_facet_search_meilisearch.py +++ b/tests/index/test_index_facet_search_meilisearch.py @@ -1,6 +1,3 @@ -# pylint: disable=invalid-name - - def test_basic_facet_search(index_with_documents_and_facets): """Tests facet search with a simple query.""" response = index_with_documents_and_facets().facet_search("genre", "cartoon") diff --git a/tests/index/test_index_search_meilisearch.py b/tests/index/test_index_search_meilisearch.py index 1bd6adb0..506f677b 100644 --- a/tests/index/test_index_search_meilisearch.py +++ b/tests/index/test_index_search_meilisearch.py @@ -1,5 +1,3 @@ -# pylint: disable=invalid-name - from collections import Counter import pytest @@ -11,7 +9,7 @@ def test_basic_search(index_with_documents): assert isinstance(response, dict) assert response["hits"][0]["id"] == "166428" assert response["estimatedTotalHits"] is not None - assert "hitsPerPage" is not response + assert "hitsPerPage" not in response def test_basic_search_with_empty_params(index_with_documents): @@ -93,7 +91,7 @@ def test_custom_search_params_with_simple_string(index_with_documents): assert len(response["hits"]) == 5 assert "_formatted" in response["hits"][0] assert "title" in response["hits"][0]["_formatted"] - assert not "release_date" in response["hits"][0]["_formatted"] + assert "release_date" not in response["hits"][0]["_formatted"] def test_custom_search_params_with_string_list(index_with_documents): @@ -110,7 +108,7 @@ def test_custom_search_params_with_string_list(index_with_documents): assert len(response["hits"]) == 5 assert "title" in response["hits"][0] assert "overview" in response["hits"][0] - assert not "release_date" in response["hits"][0] + assert "release_date" not in response["hits"][0] assert "title" in response["hits"][0]["_formatted"] assert "overview" in response["hits"][0]["_formatted"] @@ -445,7 +443,7 @@ def test_custom_search_params_with_pagination_parameters(index_with_documents): assert response["page"] == 1 assert response["totalPages"] is not None assert response["totalHits"] is not None - assert "estimatedTotalHits" is not response + assert "estimatedTotalHits" not in response def test_custom_search_params_with_pagination_parameters_at_zero(index_with_documents): @@ -458,7 +456,7 @@ def test_custom_search_params_with_pagination_parameters_at_zero(index_with_docu assert response["page"] == 0 assert response["totalPages"] is not None assert response["totalHits"] is not None - assert "estimatedTotalHits" is not response + assert "estimatedTotalHits" not in response def test_attributes_to_search_on_search(index_with_documents): diff --git a/tests/index/test_index_task_meilisearch.py b/tests/index/test_index_task_meilisearch.py index 53c968a4..c6d03477 100644 --- a/tests/index/test_index_task_meilisearch.py +++ b/tests/index/test_index_task_meilisearch.py @@ -1,7 +1,6 @@ -# pylint: disable=invalid-name - import pytest +from meilisearch.errors import MeilisearchApiError from meilisearch.models.task import Task, TaskResults from tests import common @@ -70,5 +69,5 @@ def test_get_task(client): def test_get_task_inexistent(empty_index): """Tests getting a task of an inexistent operation.""" - with pytest.raises(Exception): + with pytest.raises(MeilisearchApiError): empty_index().get_task("abc") diff --git a/tests/index/test_index_wait_for_task.py b/tests/index/test_index_wait_for_task.py index da79cf4b..a7f8bc5e 100644 --- a/tests/index/test_index_wait_for_task.py +++ b/tests/index/test_index_wait_for_task.py @@ -1,5 +1,3 @@ -# pylint: disable=invalid-name - from datetime import datetime import pytest diff --git a/tests/models/test_document.py b/tests/models/test_document.py index 8c0b9266..952c73ff 100644 --- a/tests/models/test_document.py +++ b/tests/models/test_document.py @@ -1,6 +1,3 @@ -# pylint: disable=unnecessary-dunder-call - - import pytest from meilisearch.models.document import Document diff --git a/tests/settings/test_settings.py b/tests/settings/test_settings.py index 7e278487..f33e8698 100644 --- a/tests/settings/test_settings.py +++ b/tests/settings/test_settings.py @@ -1,4 +1,3 @@ -# pylint: disable=redefined-outer-name import pytest from meilisearch.models.embedders import OpenAiEmbedder, UserProvidedEmbedder @@ -39,9 +38,9 @@ def test_get_settings_default(empty_index): response = empty_index().get_settings() for rule in DEFAULT_RANKING_RULES: assert rule in response["rankingRules"] - for typo in DEFAULT_TYPO_TOLERANCE: # pylint: disable=consider-using-dict-items + for typo, value in DEFAULT_TYPO_TOLERANCE.items(): assert typo in response["typoTolerance"] - assert DEFAULT_TYPO_TOLERANCE[typo] == response["typoTolerance"][typo] + assert value == response["typoTolerance"][typo] assert response["distinctAttribute"] is None assert response["searchableAttributes"] == ["*"] assert response["displayedAttributes"] == ["*"] @@ -92,9 +91,9 @@ def test_reset_settings(new_settings, empty_index): response = index.get_settings() for rule in DEFAULT_RANKING_RULES: assert rule in response["rankingRules"] - for typo in DEFAULT_TYPO_TOLERANCE: # pylint: disable=consider-using-dict-items + for typo, value in DEFAULT_TYPO_TOLERANCE.items(): assert typo in response["typoTolerance"] - assert DEFAULT_TYPO_TOLERANCE[typo] == response["typoTolerance"][typo] + assert value == response["typoTolerance"][typo] assert response["distinctAttribute"] is None assert response["displayedAttributes"] == ["*"] assert response["searchableAttributes"] == ["*"] diff --git a/tests/settings/test_settings_displayed_attributes_meilisearch.py b/tests/settings/test_settings_displayed_attributes_meilisearch.py index 1a7d421a..40a6bccd 100644 --- a/tests/settings/test_settings_displayed_attributes_meilisearch.py +++ b/tests/settings/test_settings_displayed_attributes_meilisearch.py @@ -1,5 +1,3 @@ -# pylint: disable=invalid-name - DISPLAYED_ATTRIBUTES = ["id", "release_date", "title", "poster", "overview", "genre"] diff --git a/tests/settings/test_settings_embedders.py b/tests/settings/test_settings_embedders.py index d7137dfb..5b3a50a7 100644 --- a/tests/settings/test_settings_embedders.py +++ b/tests/settings/test_settings_embedders.py @@ -1,5 +1,3 @@ -# pylint: disable=redefined-outer-name - import pytest from meilisearch.models.embedders import ( @@ -223,12 +221,6 @@ def test_composite_embedder_format(empty_index): assert isinstance(embedders.embedders["composite"].indexing_embedder, HuggingFaceEmbedder) # ensure search_embedder has no document_template - assert getattr(embedders.embedders["composite"].search_embedder, "document_template") is None - assert ( - getattr( - embedders.embedders["composite"].search_embedder, - "document_template_max_bytes", - ) - is None - ) - assert getattr(embedders.embedders["composite"].indexing_embedder, "document_template") + assert embedders.embedders["composite"].search_embedder.document_template is None + assert embedders.embedders["composite"].search_embedder.document_template_max_bytes is None + assert embedders.embedders["composite"].indexing_embedder.document_template diff --git a/tests/settings/test_settings_filterable_attributes_meilisearch.py b/tests/settings/test_settings_filterable_attributes_meilisearch.py index 14df6c19..756f928c 100644 --- a/tests/settings/test_settings_filterable_attributes_meilisearch.py +++ b/tests/settings/test_settings_filterable_attributes_meilisearch.py @@ -1,5 +1,3 @@ -# pylint: disable=invalid-name - FILTERABLE_ATTRIBUTES = ["title", "release_date"] diff --git a/tests/settings/test_settings_localized_attributes_meilisearch.py b/tests/settings/test_settings_localized_attributes_meilisearch.py index af6e1fcb..e9a494b3 100644 --- a/tests/settings/test_settings_localized_attributes_meilisearch.py +++ b/tests/settings/test_settings_localized_attributes_meilisearch.py @@ -1,11 +1,9 @@ -from typing import List - from meilisearch.models.index import LocalizedAttributes NEW_LOCALIZED_ATTRIBUTES = [{"attributePatterns": ["title"], "locales": ["eng"]}] -def unpack_loc_attrs_response(response: List[LocalizedAttributes]): +def unpack_loc_attrs_response(response: list[LocalizedAttributes]): return [loc_attrs.model_dump(by_alias=True) for loc_attrs in response] diff --git a/tests/settings/test_settings_searchable_attributes_meilisearch.py b/tests/settings/test_settings_searchable_attributes_meilisearch.py index 71d97458..e40c4bc0 100644 --- a/tests/settings/test_settings_searchable_attributes_meilisearch.py +++ b/tests/settings/test_settings_searchable_attributes_meilisearch.py @@ -1,5 +1,3 @@ -# pylint: disable=invalid-name - NEW_SEARCHABLE_ATTRIBUTES = ["something", "random"] diff --git a/tests/settings/test_settings_sortable_attributes_meilisearch.py b/tests/settings/test_settings_sortable_attributes_meilisearch.py index dcf0f5e4..9e682e6e 100644 --- a/tests/settings/test_settings_sortable_attributes_meilisearch.py +++ b/tests/settings/test_settings_sortable_attributes_meilisearch.py @@ -1,5 +1,3 @@ -# pylint: disable=invalid-name - SORTABLE_ATTRIBUTES = ["title", "release_date"] diff --git a/tests/settings/test_settings_typo_tolerance_meilisearch.py b/tests/settings/test_settings_typo_tolerance_meilisearch.py index 8d6f6f8d..be208197 100644 --- a/tests/settings/test_settings_typo_tolerance_meilisearch.py +++ b/tests/settings/test_settings_typo_tolerance_meilisearch.py @@ -38,12 +38,9 @@ def test_update_typo_tolerance(empty_index): response_get = index.get_typo_tolerance() assert update.status == "succeeded" - for typo_tolerance in NEW_TYPO_TOLERANCE: # pylint: disable=consider-using-dict-items + for typo_tolerance, value in NEW_TYPO_TOLERANCE.items(): assert typo_tolerance in response_get.model_dump(by_alias=True) - assert ( - NEW_TYPO_TOLERANCE[typo_tolerance] - == response_get.model_dump(by_alias=True)[typo_tolerance] - ) + assert value == response_get.model_dump(by_alias=True)[typo_tolerance] def test_reset_typo_tolerance(empty_index): @@ -62,11 +59,8 @@ def test_reset_typo_tolerance(empty_index): response_last = index.get_typo_tolerance() assert update1.status == "succeeded" - for typo_tolerance in NEW_TYPO_TOLERANCE: # pylint: disable=consider-using-dict-items - assert ( - NEW_TYPO_TOLERANCE[typo_tolerance] - == response_get.model_dump(by_alias=True)[typo_tolerance] - ) + for typo_tolerance, value in NEW_TYPO_TOLERANCE.items(): + assert value == response_get.model_dump(by_alias=True)[typo_tolerance] assert update2.status == "succeeded" assert response_last.model_dump(by_alias=True) == DEFAULT_TYPO_TOLERANCE diff --git a/tox.ini b/tox.ini index eba0122d..db3199c3 100644 --- a/tox.ini +++ b/tox.ini @@ -1,14 +1,8 @@ [tox] -envlist = pylint, mypy, py310, py311, py312, py313 +envlist = mypy, py310, py311, py312, py313 requires = tox-uv -[testenv:pylint] -runner = uv-venv-lock-runner -description = run linter via pylint -commands = - pylint meilisearch tests - [testenv:mypy] runner = uv-venv-lock-runner description = run type checker via mypy diff --git a/uv.lock b/uv.lock index 2b4f2732..ff032c96 100644 --- a/uv.lock +++ b/uv.lock @@ -69,18 +69,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/45/19/cc8bd127d28a43da249aa955cfd164cf8fd534e79e42cea96c4854d72fd0/ast_serialize-0.5.0-cp39-abi3-win_arm64.whl", hash = "sha256:92a31c9c20d25a076edaeec76b128a3535d74a24f340b9a8a7e96c9b86dc9642", size = 1081181, upload-time = "2026-05-17T17:48:28.122Z" }, ] -[[package]] -name = "astroid" -version = "4.0.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/07/63/0adf26577da5eff6eb7a177876c1cfa213856be9926a000f65c4add9692b/astroid-4.0.4.tar.gz", hash = "sha256:986fed8bcf79fb82c78b18a53352a0b287a73817d6dbcfba3162da36667c49a0", size = 406358, upload-time = "2026-02-07T23:35:07.509Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b0/cf/1c5f42b110e57bc5502eb80dbc3b03d256926062519224835ef08134f1f9/astroid-4.0.4-py3-none-any.whl", hash = "sha256:52f39653876c7dec3e3afd4c2696920e05c83832b9737afc21928f2d2eb7a753", size = 276445, upload-time = "2026-02-07T23:35:05.344Z" }, -] - [[package]] name = "babel" version = "2.18.0" @@ -354,15 +342,6 @@ toml = [ { name = "tomli", marker = "python_full_version <= '3.11'" }, ] -[[package]] -name = "dill" -version = "0.4.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/81/e1/56027a71e31b02ddc53c7d65b01e68edf64dea2932122fe7746a516f75d5/dill-0.4.1.tar.gz", hash = "sha256:423092df4182177d4d8ba8290c8a5b640c66ab35ec7da59ccfa00f6fa3eea5fa", size = 187315, upload-time = "2026-01-19T02:36:56.85Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl", hash = "sha256:1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d", size = 120019, upload-time = "2026-01-19T02:36:55.663Z" }, -] - [[package]] name = "distlib" version = "0.4.3" @@ -429,15 +408,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, ] -[[package]] -name = "isort" -version = "8.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ef/7c/ec4ab396d31b3b395e2e999c8f46dec78c5e29209fac49d1f4dace04041d/isort-8.0.1.tar.gz", hash = "sha256:171ac4ff559cdc060bcfff550bc8404a486fee0caab245679c2abe7cb253c78d", size = 769592, upload-time = "2026-02-28T10:08:20.685Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3e/95/c7c34aa53c16353c56d0b802fba48d5f5caa2cdee7958acbcb795c830416/isort-8.0.1-py3-none-any.whl", hash = "sha256:28b89bc70f751b559aeca209e6120393d43fbe2490de0559662be7a9787e3d75", size = 89733, upload-time = "2026-02-28T10:08:19.466Z" }, -] - [[package]] name = "jinja2" version = "3.1.6" @@ -620,15 +590,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, ] -[[package]] -name = "mccabe" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658, upload-time = "2022-01-24T01:14:51.113Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350, upload-time = "2022-01-24T01:14:49.62Z" }, -] - [[package]] name = "meilisearch" source = { editable = "." } @@ -646,9 +607,7 @@ docs = [ { name = "sphinx-rtd-theme" }, ] lint = [ - { name = "isort" }, { name = "mypy" }, - { name = "pylint" }, { name = "ruff" }, ] test = [ @@ -670,9 +629,7 @@ docs = [ { name = "sphinx-rtd-theme", specifier = ">=3.1.0" }, ] lint = [ - { name = "isort", specifier = ">=6.1.0" }, { name = "mypy", specifier = ">=1.19.1" }, - { name = "pylint", specifier = ">=3.3.9" }, { name = "ruff", specifier = ">=0.15.17" }, ] test = [ @@ -925,25 +882,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, ] -[[package]] -name = "pylint" -version = "4.0.6" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "astroid" }, - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "dill" }, - { name = "isort" }, - { name = "mccabe" }, - { name = "platformdirs" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, - { name = "tomlkit" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/7d/1d/3bb57f303701549550d74bf7ced2b07412be97125c167a0c9d216aa9f762/pylint-4.0.6.tar.gz", hash = "sha256:52f19191bee08bf103f9705ad1a0ece4aa5a0a4ef2bdcbd969375a1e6f6579d5", size = 1585588, upload-time = "2026-06-14T14:43:26.772Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ab/da/acb2e7d4dbd2dfb792d38c0d850481f29ad7049b356d23f56c687d35203b/pylint-4.0.6-py3-none-any.whl", hash = "sha256:d11a0e1fdb7b1cd46ec5d6fc78fee8b95f28695b2d6140e5809925f61e32ea54", size = 538389, upload-time = "2026-06-14T14:43:24.873Z" }, -] - [[package]] name = "pyproject-api" version = "1.10.1" @@ -1222,15 +1160,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/18/c86eb8e0202e32dd3df50d43d7ff9854f8e0603945ff398974c1d91ac1ef/tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", size = 6675, upload-time = "2025-01-15T12:07:22.074Z" }, ] -[[package]] -name = "tomlkit" -version = "0.15.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/51/db/03eaf4331631ef6b27d6e3c9b68c54dc6f0d63d87201fed600cc409307fd/tomlkit-0.15.0.tar.gz", hash = "sha256:7d1a9ecba3086638211b13814ea79c90dd54dd11993564376f3aa92271f5c7a3", size = 161875, upload-time = "2026-05-10T07:38:22.245Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/43/8bd850ee71a191bf072e31302c73a66be413fecdd98fdcd111ecbcce13ca/tomlkit-0.15.0-py3-none-any.whl", hash = "sha256:4dbc8f0fc024412b57ced8757ac7461305126a648ff8c2c807fcb8e133a78738", size = 41328, upload-time = "2026-05-10T07:38:23.517Z" }, -] - [[package]] name = "tox" version = "4.55.1"