From 737f571e8c476e0942418ca53c72658c7ca9d323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Clgen=20Sar=C4=B1kavak?= Date: Sun, 23 Nov 2025 22:36:21 +0300 Subject: [PATCH 1/3] Specify supported Python versions via trove classifiers --- pyproject.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 56fb095..59537c5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,10 @@ classifiers = [ "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ] dependencies = ["requests", "typing-extensions"] dynamic = ["version"] From 5461c8f313c5f6a2ad4bc07ffd61b399d2bf7010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Clgen=20Sar=C4=B1kavak?= Date: Sun, 23 Nov 2025 22:28:58 +0300 Subject: [PATCH 2/3] Enable pyupgrade in ruff config https://docs.astral.sh/ruff/rules/#pyupgrade-up --- ruff.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruff.toml b/ruff.toml index 25a54ba..1a7c5bd 100644 --- a/ruff.toml +++ b/ruff.toml @@ -33,7 +33,7 @@ indent-width = 4 target-version = "py39" [lint] -select = ["E4", "E7", "E9", "F", "B"] +select = ["E4", "E7", "E9", "F", "B", "UP"] ignore = ["E501"] From 73a6e7767e982ae6ac2fb95b88b81ecb21bf33e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Clgen=20Sar=C4=B1kavak?= Date: Sun, 23 Nov 2025 22:29:19 +0300 Subject: [PATCH 3/3] Apply pyupgrade fixes --- src/typesense/alias.py | 2 +- src/typesense/analytics_rules.py | 2 +- src/typesense/analytics_rules_v1.py | 2 +- src/typesense/analytics_v1.py | 2 +- src/typesense/api_call.py | 42 +++++++++++++-------------- src/typesense/client.py | 2 +- src/typesense/configuration.py | 28 +++++++++--------- src/typesense/conversations_models.py | 2 +- src/typesense/nl_search_models.py | 2 +- src/typesense/overrides.py | 2 +- src/typesense/request_handler.py | 10 +++---- src/typesense/stemming.py | 2 +- 12 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/typesense/alias.py b/src/typesense/alias.py index 6786d89..3ba7a13 100644 --- a/src/typesense/alias.py +++ b/src/typesense/alias.py @@ -24,7 +24,7 @@ from typesense.types.alias import AliasSchema -class Alias(object): +class Alias: """ Class for managing individual aliases in Typesense. diff --git a/src/typesense/analytics_rules.py b/src/typesense/analytics_rules.py index a95dc60..f308fca 100644 --- a/src/typesense/analytics_rules.py +++ b/src/typesense/analytics_rules.py @@ -16,7 +16,7 @@ ) -class AnalyticsRules(object): +class AnalyticsRules: resource_path: typing.Final[str] = "/analytics/rules" def __init__(self, api_call: ApiCall) -> None: diff --git a/src/typesense/analytics_rules_v1.py b/src/typesense/analytics_rules_v1.py index 2c93a98..d4991c9 100644 --- a/src/typesense/analytics_rules_v1.py +++ b/src/typesense/analytics_rules_v1.py @@ -50,7 +50,7 @@ ] -class AnalyticsRulesV1(object): +class AnalyticsRulesV1: """ Class for managing analytics rules in Typesense (V1). diff --git a/src/typesense/analytics_v1.py b/src/typesense/analytics_v1.py index 657af6c..bc409d7 100644 --- a/src/typesense/analytics_v1.py +++ b/src/typesense/analytics_v1.py @@ -24,7 +24,7 @@ @deprecated("AnalyticsV1 is deprecated on v30+. Use client.analytics instead.") -class AnalyticsV1(object): +class AnalyticsV1: """ Class for managing analytics in Typesense (V1). diff --git a/src/typesense/api_call.py b/src/typesense/api_call.py index 90e1929..a050456 100644 --- a/src/typesense/api_call.py +++ b/src/typesense/api_call.py @@ -59,14 +59,14 @@ _SERVER_ERRORS: typing.Final[ typing.Tuple[ - typing.Type[requests.exceptions.Timeout], - typing.Type[requests.exceptions.ConnectionError], - typing.Type[requests.exceptions.HTTPError], - typing.Type[requests.exceptions.RequestException], - typing.Type[requests.exceptions.SSLError], - typing.Type[HTTPStatus0Error], - typing.Type[ServerError], - typing.Type[ServiceUnavailable], + type[requests.exceptions.Timeout], + type[requests.exceptions.ConnectionError], + type[requests.exceptions.HTTPError], + type[requests.exceptions.RequestException], + type[requests.exceptions.SSLError], + type[HTTPStatus0Error], + type[ServerError], + type[ServiceUnavailable], ] ] = ( requests.exceptions.Timeout, @@ -108,7 +108,7 @@ def __init__(self, config: Configuration): def get( self, endpoint: str, - entity_type: typing.Type[TEntityDict], + entity_type: type[TEntityDict], as_json: typing.Literal[False], params: typing.Union[TParams, None] = None, ) -> str: @@ -129,7 +129,7 @@ def get( def get( self, endpoint: str, - entity_type: typing.Type[TEntityDict], + entity_type: type[TEntityDict], as_json: typing.Literal[True], params: typing.Union[TParams, None] = None, ) -> TEntityDict: @@ -149,7 +149,7 @@ def get( def get( self, endpoint: str, - entity_type: typing.Type[TEntityDict], + entity_type: type[TEntityDict], as_json: typing.Union[typing.Literal[True], typing.Literal[False]] = True, params: typing.Union[TParams, None] = None, ) -> typing.Union[TEntityDict, str]: @@ -177,7 +177,7 @@ def get( def post( self, endpoint: str, - entity_type: typing.Type[TEntityDict], + entity_type: type[TEntityDict], as_json: typing.Literal[False], params: typing.Union[TParams, None] = None, body: typing.Union[TBody, None] = None, @@ -199,7 +199,7 @@ def post( def post( self, endpoint: str, - entity_type: typing.Type[TEntityDict], + entity_type: type[TEntityDict], as_json: typing.Literal[True], params: typing.Union[TParams, None] = None, body: typing.Union[TBody, None] = None, @@ -220,7 +220,7 @@ def post( def post( self, endpoint: str, - entity_type: typing.Type[TEntityDict], + entity_type: type[TEntityDict], as_json: typing.Union[typing.Literal[True], typing.Literal[False]] = True, params: typing.Union[TParams, None] = None, body: typing.Union[TBody, None] = None, @@ -249,7 +249,7 @@ def post( def put( self, endpoint: str, - entity_type: typing.Type[TEntityDict], + entity_type: type[TEntityDict], body: TBody, params: typing.Union[TParams, None] = None, ) -> TEntityDict: @@ -276,7 +276,7 @@ def put( def patch( self, endpoint: str, - entity_type: typing.Type[TEntityDict], + entity_type: type[TEntityDict], body: TBody, params: typing.Union[TParams, None] = None, ) -> TEntityDict: @@ -303,7 +303,7 @@ def patch( def delete( self, endpoint: str, - entity_type: typing.Type[TEntityDict], + entity_type: type[TEntityDict], params: typing.Union[TParams, None] = None, ) -> TEntityDict: """ @@ -330,7 +330,7 @@ def _execute_request( self, fn: typing.Callable[..., requests.models.Response], endpoint: str, - entity_type: typing.Type[TEntityDict], + entity_type: type[TEntityDict], as_json: typing.Literal[True], last_exception: typing.Union[None, Exception] = None, num_retries: int = 0, @@ -369,7 +369,7 @@ def _execute_request( self, fn: typing.Callable[..., requests.models.Response], endpoint: str, - entity_type: typing.Type[TEntityDict], + entity_type: type[TEntityDict], as_json: typing.Literal[False], last_exception: typing.Union[None, Exception] = None, num_retries: int = 0, @@ -407,7 +407,7 @@ def _execute_request( self, fn: typing.Callable[..., requests.models.Response], endpoint: str, - entity_type: typing.Type[TEntityDict], + entity_type: type[TEntityDict], as_json: typing.Union[typing.Literal[True], typing.Literal[False]] = True, last_exception: typing.Union[None, Exception] = None, num_retries: int = 0, @@ -471,7 +471,7 @@ def _make_request_and_process_response( self, fn: typing.Callable[..., requests.models.Response], url: str, - entity_type: typing.Type[TEntityDict], + entity_type: type[TEntityDict], as_json: bool, **kwargs: SessionFunctionKwargs[TParams, TBody], ) -> typing.Union[TEntityDict, str]: diff --git a/src/typesense/client.py b/src/typesense/client.py index 19cae3a..a78bd76 100644 --- a/src/typesense/client.py +++ b/src/typesense/client.py @@ -133,7 +133,7 @@ def analyticsV1(self) -> AnalyticsV1: def typed_collection( self, *, - model: typing.Type[TDoc], + model: type[TDoc], name: typing.Union[str, None] = None, ) -> Collection[TDoc]: """ diff --git a/src/typesense/configuration.py b/src/typesense/configuration.py index d82408d..029a276 100644 --- a/src/typesense/configuration.py +++ b/src/typesense/configuration.py @@ -44,7 +44,7 @@ class NodeConfigDict(typing.TypedDict): host: str port: int path: typing.NotRequired[str] - protocol: typing.Union[typing.Literal["http", "https"], str] + protocol: typing.Literal["http", "https"] | str class ConfigDict(typing.TypedDict): @@ -84,18 +84,18 @@ class ConfigDict(typing.TypedDict): suppress_deprecation_warnings (bool): Whether to suppress deprecation warnings. """ - nodes: typing.List[typing.Union[str, NodeConfigDict]] - nearest_node: typing.NotRequired[typing.Union[str, NodeConfigDict]] + nodes: typing.List[str | NodeConfigDict] + nearest_node: typing.NotRequired[str | NodeConfigDict] api_key: str num_retries: typing.NotRequired[int] interval_seconds: typing.NotRequired[int] healthcheck_interval_seconds: typing.NotRequired[int] verify: typing.NotRequired[bool] timeout_seconds: typing.NotRequired[int] # deprecated - master_node: typing.NotRequired[typing.Union[str, NodeConfigDict]] # deprecated + master_node: typing.NotRequired[str | NodeConfigDict] # deprecated additional_headers: typing.NotRequired[typing.Dict[str, str]] read_replica_nodes: typing.NotRequired[ - typing.List[typing.Union[str, NodeConfigDict]] + typing.List[str | NodeConfigDict] ] # deprecated connection_timeout_seconds: typing.NotRequired[float] suppress_deprecation_warnings: typing.NotRequired[bool] @@ -116,9 +116,9 @@ class Node: def __init__( self, host: str, - port: typing.Union[str, int], + port: str | int, path: str, - protocol: typing.Union[typing.Literal["http", "https"], str], + protocol: typing.Literal["http", "https"] | str, ) -> None: """ Initialize a Node object with the specified host, port, path, and protocol. @@ -141,7 +141,7 @@ def __init__( self.last_access_ts: int = int(time.time()) @classmethod - def from_url(cls, url: str) -> "Node": + def from_url(cls, url: str) -> Node: """ Initialize a Node object from a URL string. @@ -227,8 +227,8 @@ def __init__( def _handle_nearest_node( self, - nearest_node: typing.Union[str, NodeConfigDict, None], - ) -> typing.Union[Node, None]: + nearest_node: str | NodeConfigDict | None, + ) -> Node | None: """ Handle the nearest node configuration. @@ -244,7 +244,7 @@ def _handle_nearest_node( def _initialize_nodes( self, - node: typing.Union[str, NodeConfigDict], + node: str | NodeConfigDict, ) -> Node: """ Handle the initialization of a node. @@ -305,7 +305,7 @@ def validate_required_config_fields(config_dict: ConfigDict) -> None: raise ConfigError("`api_key` is not defined.") @staticmethod - def validate_nodes(nodes: typing.List[typing.Union[str, NodeConfigDict]]) -> None: + def validate_nodes(nodes: typing.List[str | NodeConfigDict]) -> None: """ Validate the nodes in the configuration dictionary. @@ -328,7 +328,7 @@ def validate_nodes(nodes: typing.List[typing.Union[str, NodeConfigDict]]) -> Non ) @staticmethod - def validate_nearest_node(nearest_node: typing.Union[str, NodeConfigDict]) -> None: + def validate_nearest_node(nearest_node: str | NodeConfigDict) -> None: """ Validate the nearest node in the configuration dictionary. @@ -350,7 +350,7 @@ def validate_nearest_node(nearest_node: typing.Union[str, NodeConfigDict]) -> No ) @staticmethod - def validate_node_fields(node: typing.Union[str, NodeConfigDict]) -> bool: + def validate_node_fields(node: str | NodeConfigDict) -> bool: """ Validate the fields of a node in the configuration dictionary. diff --git a/src/typesense/conversations_models.py b/src/typesense/conversations_models.py index c333ccb..820d68e 100644 --- a/src/typesense/conversations_models.py +++ b/src/typesense/conversations_models.py @@ -43,7 +43,7 @@ from typesense.conversation_model import ConversationModel -class ConversationsModels(object): +class ConversationsModels: """ Class for managing conversation models in Typesense. diff --git a/src/typesense/nl_search_models.py b/src/typesense/nl_search_models.py index d184add..a4eb7fd 100644 --- a/src/typesense/nl_search_models.py +++ b/src/typesense/nl_search_models.py @@ -40,7 +40,7 @@ from typesense.nl_search_model import NLSearchModel -class NLSearchModels(object): +class NLSearchModels: """ Class for managing NL search models in Typesense. diff --git a/src/typesense/overrides.py b/src/typesense/overrides.py index 4f8bc80..7362c8b 100644 --- a/src/typesense/overrides.py +++ b/src/typesense/overrides.py @@ -133,7 +133,7 @@ def retrieve(self) -> OverrideRetrieveSchema: ) return response - def _endpoint_path(self, override_id: typing.Union[str, None] = None) -> str: + def _endpoint_path(self, override_id: str | None = None) -> str: """ Construct the API endpoint path for override operations. diff --git a/src/typesense/request_handler.py b/src/typesense/request_handler.py index e726379..cb762eb 100644 --- a/src/typesense/request_handler.py +++ b/src/typesense/request_handler.py @@ -50,7 +50,7 @@ TParams = typing.TypeVar("TParams") TBody = typing.TypeVar("TBody") -_ERROR_CODE_MAP: typing.Mapping[str, typing.Type[TypesenseClientError]] = ( +_ERROR_CODE_MAP: typing.Mapping[str, type[TypesenseClientError]] = ( MappingProxyType( { "0": HTTPStatus0Error, @@ -118,7 +118,7 @@ def make_request( self, fn: typing.Callable[..., requests.models.Response], url: str, - entity_type: typing.Type[TEntityDict], + entity_type: type[TEntityDict], as_json: typing.Literal[False], **kwargs: typing.Unpack[SessionFunctionKwargs[TParams, TBody]], ) -> str: @@ -151,7 +151,7 @@ def make_request( self, fn: typing.Callable[..., requests.models.Response], url: str, - entity_type: typing.Type[TEntityDict], + entity_type: type[TEntityDict], as_json: typing.Literal[True], **kwargs: typing.Unpack[SessionFunctionKwargs[TParams, TBody]], ) -> TEntityDict: @@ -180,7 +180,7 @@ def make_request( self, fn: typing.Callable[..., requests.models.Response], url: str, - entity_type: typing.Type[TEntityDict], + entity_type: type[TEntityDict], as_json: typing.Union[typing.Literal[True], typing.Literal[False]] = True, **kwargs: typing.Unpack[SessionFunctionKwargs[TParams, TBody]], ) -> typing.Union[TEntityDict, str]: @@ -267,7 +267,7 @@ def _get_error_message(response: requests.Response) -> str: return "API error." @staticmethod - def _get_exception(http_code: int) -> typing.Type[TypesenseClientError]: + def _get_exception(http_code: int) -> type[TypesenseClientError]: """ Map an HTTP status code to the appropriate exception type. diff --git a/src/typesense/stemming.py b/src/typesense/stemming.py index b6845da..46053b8 100644 --- a/src/typesense/stemming.py +++ b/src/typesense/stemming.py @@ -27,7 +27,7 @@ from typesense.stemming_dictionaries import StemmingDictionaries -class Stemming(object): +class Stemming: """ Class for managing stemming dictionaries in Typesense.