From d5b9a53eb71ad4966cc23558d48dab95c32add5f Mon Sep 17 00:00:00 2001 From: Giovanni Condello Date: Sun, 18 Oct 2026 10:03:53 +0200 Subject: [PATCH] Require Python 3.12 and use PEP 695 type parameters --- .github/workflows/ci.yml | 4 ++-- poetry.lock | 9 +++------ pyproject.toml | 6 +++--- src/saic_ismart_client_ng/api/base.py | 14 ++++++-------- 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index caa702b..38e59eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ "3.11", "3.12", "3.13", "3.14" ] + python-version: [ "3.12", "3.13", "3.14" ] steps: - name: Checkout code @@ -113,7 +113,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v7 with: - python-version: '3.11' + python-version: '3.12' - name: Build and publish to pypi uses: JRubics/poetry-publish@v2.1 diff --git a/poetry.lock b/poetry.lock index 4875579..05c1930 100644 --- a/poetry.lock +++ b/poetry.lock @@ -916,10 +916,7 @@ files = [ [package.dependencies] astroid = ">=4.3.4,<=4.4" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -dill = [ - {version = ">=0.3.6", markers = "python_version == \"3.11\""}, - {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, -] +dill = {version = ">=0.3.7", markers = "python_version >= \"3.12\""} isort = ">=5,!=5.13,<10" mccabe = ">=0.6,<0.8" platformdirs = ">=2.2" @@ -1197,5 +1194,5 @@ python-discovery = ">=1.6.1" [metadata] lock-version = "2.1" -python-versions = ">=3.11" -content-hash = "0b330596baed6f555db723278b125fbeda80e0962727d482b9521a675e403cce" +python-versions = ">=3.12" +content-hash = "5ca6b02974f056c35c7dd3f6cbf09f320e807bcec8d3d5a2440cd37cf0b66dcf" diff --git a/pyproject.toml b/pyproject.toml index fbc85a5..7aa27b2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ classifiers = [ "Operating System :: OS Independent", ] -requires-python = ">=3.11" +requires-python = ">=3.12" dependencies = [ "pycryptodome (>=3.20.0,<4.0.0)", @@ -158,7 +158,7 @@ max-args = 10 [tool.mypy] files = ["./src", "./tests"] -python_version = 3.11 +python_version = 3.12 show_error_codes = true strict_equality = true warn_incomplete_stub = true @@ -177,7 +177,7 @@ warn_unreachable = true strict = true [tool.pylint.MAIN] -py-version = "3.11" +py-version = "3.12" ignore = ["tests"] fail-on = ["I"] diff --git a/src/saic_ismart_client_ng/api/base.py b/src/saic_ismart_client_ng/api/base.py index eb46db6..f341e2e 100644 --- a/src/saic_ismart_client_ng/api/base.py +++ b/src/saic_ismart_client_ng/api/base.py @@ -8,7 +8,6 @@ Any, ClassVar, Protocol, - TypeVar, ) import dacite @@ -38,7 +37,6 @@ class IsDataclass(Protocol): # the most reliable way to ascertain that something is a dataclass __dataclass_fields__: ClassVar[dict[str, Any]] - T = TypeVar("T", bound=IsDataclass) logger = logging.getLogger(__name__) @@ -111,7 +109,7 @@ async def login(self) -> LoginResp: ) return result - async def execute_api_call( + async def execute_api_call[T: IsDataclass]( self, method: str, path: str, @@ -137,7 +135,7 @@ async def execute_api_call( raise SaicApiException(msg) return result - async def execute_api_call_with_optional_result( + async def execute_api_call_with_optional_result[T: IsDataclass]( self, method: str, path: str, @@ -179,7 +177,7 @@ async def execute_api_call_no_result( allow_null_body=True, ) - async def __execute_api_call( + async def __execute_api_call[T: IsDataclass]( self, method: str, path: str, @@ -210,7 +208,7 @@ async def __execute_api_call( msg = f"API call {method} {path} failed unexpectedly" raise SaicApiException(msg, return_code=500) from e - async def execute_api_call_with_event_id( + async def execute_api_call_with_event_id[T: IsDataclass]( self, method: str, path: str, @@ -254,7 +252,7 @@ async def execute_api_call_with_event_id_no_result( delay=delay, ) - async def __execute_api_call_with_event_id( + async def __execute_api_call_with_event_id[T: IsDataclass]( self, method: str, path: str, @@ -286,7 +284,7 @@ async def execute_api_call_with_event_id_inner(*, event_id: str) -> T | None: return await execute_api_call_with_event_id_inner(event_id="0") - async def __deserialize( + async def __deserialize[T: IsDataclass]( self, request: httpx.Request, response: httpx.Response,