From 49eeacd14006176eac3ec495eedf0f4c2fbb145e Mon Sep 17 00:00:00 2001 From: gruebel Date: Wed, 12 Feb 2025 00:26:05 +0100 Subject: [PATCH] drop Python 3.8 support Signed-off-by: gruebel --- .github/workflows/build.yml | 8 +++---- .pre-commit-config.yaml | 2 +- CONTRIBUTING.md | 4 ++-- .../pyproject.toml | 4 ++-- .../openfeature-provider-flagd/pyproject.toml | 4 ++-- .../provider/flagd/resolvers/process/flags.py | 4 ++-- .../tests/e2e/file/test_flaqd.py | 7 +----- .../tests/e2e/rpc/test_flaqd.py | 7 +----- .../tests/e2e/step/flag_step.py | 4 +--- .../tests/e2e/step/provider_steps.py | 3 +-- .../tests/test_targeting.py | 4 ++-- .../openfeature-provider-flipt/pyproject.toml | 4 ++-- .../contrib/provider/flipt/__init__.py | 8 +++---- .../openfeature-provider-ofrep/pyproject.toml | 4 ++-- .../contrib/provider/ofrep/__init__.py | 22 +++++++++---------- ruff.toml | 2 +- 16 files changed, 39 insertions(+), 52 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ebb1524c..1c5c424f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] package: - "hooks/openfeature-hooks-opentelemetry" - "providers/openfeature-provider-flagd" @@ -50,7 +50,7 @@ jobs: working-directory: ${{ matrix.package }} - name: Type checking - if: matrix.python-version == '3.11' + if: matrix.python-version == '3.13' working-directory: ${{ matrix.package }} run: hatch run mypy:run @@ -58,7 +58,7 @@ jobs: run: hatch test -c working-directory: ${{ matrix.package }} - - if: matrix.python-version == '3.11' + - if: matrix.python-version == '3.13' name: Upload coverage to Codecov uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 with: @@ -75,7 +75,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5 with: - python-version: "3.11" + python-version: "3.13" cache: "pip" - name: Run pre-commit diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index edc8248e..bf1e1395 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,4 +1,4 @@ -default_stages: [commit] +default_stages: [pre-commit] repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.9.6 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 583f262f..0cde518a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,11 +4,11 @@ ### System Requirements -Python 3.8 and above are required. +Python 3.9 and above are required. ### Target version(s) -Python 3.8 and above are supported by the SDK. +Python 3.9 and above are supported by the SDK. ### Installation and Dependencies diff --git a/hooks/openfeature-hooks-opentelemetry/pyproject.toml b/hooks/openfeature-hooks-opentelemetry/pyproject.toml index b826dfeb..1607213a 100644 --- a/hooks/openfeature-hooks-opentelemetry/pyproject.toml +++ b/hooks/openfeature-hooks-opentelemetry/pyproject.toml @@ -20,7 +20,7 @@ dependencies = [ "openfeature-sdk>=0.6.0", "opentelemetry-api", ] -requires-python = ">=3.8" +requires-python = ">=3.9" [project.urls] Homepage = "https://github.com/open-feature/python-sdk-contrib" @@ -70,7 +70,7 @@ packages = ["src/openfeature"] mypy_path = "src" files = "src" -python_version = "3.8" # should be identical to the minimum supported version +python_version = "3.9" # should be identical to the minimum supported version namespace_packages = true explicit_package_bases = true local_partial_types = true diff --git a/providers/openfeature-provider-flagd/pyproject.toml b/providers/openfeature-provider-flagd/pyproject.toml index 97aa5957..af413347 100644 --- a/providers/openfeature-provider-flagd/pyproject.toml +++ b/providers/openfeature-provider-flagd/pyproject.toml @@ -26,7 +26,7 @@ dependencies = [ "pyyaml>=6.0.1", "cachebox" ] -requires-python = ">=3.8" +requires-python = ">=3.9" [project.urls] Homepage = "https://github.com/open-feature/python-sdk-contrib" @@ -113,7 +113,7 @@ omit = [ mypy_path = "src" files = "src" -python_version = "3.8" # should be identical to the minimum supported version +python_version = "3.9" # should be identical to the minimum supported version namespace_packages = true explicit_package_bases = true local_partial_types = true diff --git a/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/resolvers/process/flags.py b/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/resolvers/process/flags.py index d262f205..919fa8f2 100644 --- a/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/resolvers/process/flags.py +++ b/providers/openfeature-provider-flagd/src/openfeature/contrib/provider/flagd/resolvers/process/flags.py @@ -75,12 +75,12 @@ def from_dict(cls, key: str, data: dict) -> "Flag": return flag @property - def default(self) -> typing.Tuple[str, typing.Any]: + def default(self) -> tuple[str, typing.Any]: return self.get_variant(self.default_variant) def get_variant( self, variant_key: typing.Union[str, bool] - ) -> typing.Tuple[str, typing.Any]: + ) -> tuple[str, typing.Any]: if isinstance(variant_key, bool): variant_key = str(variant_key).lower() diff --git a/providers/openfeature-provider-flagd/tests/e2e/file/test_flaqd.py b/providers/openfeature-provider-flagd/tests/e2e/file/test_flaqd.py index 6ca4433b..3feb4c52 100644 --- a/providers/openfeature-provider-flagd/tests/e2e/file/test_flaqd.py +++ b/providers/openfeature-provider-flagd/tests/e2e/file/test_flaqd.py @@ -1,10 +1,5 @@ -# as soon as we support all the features, we can actually remove this limitation to not run on Python 3.8 -# Python 3.8 does not fully support tagging, hence that it will run all cases -import sys - from pytest_bdd import scenarios from tests.e2e.paths import TEST_HARNESS_PATH -if sys.version_info >= (3, 9): - scenarios(f"{TEST_HARNESS_PATH}/gherkin") +scenarios(f"{TEST_HARNESS_PATH}/gherkin") diff --git a/providers/openfeature-provider-flagd/tests/e2e/rpc/test_flaqd.py b/providers/openfeature-provider-flagd/tests/e2e/rpc/test_flaqd.py index 747d91ad..3feb4c52 100644 --- a/providers/openfeature-provider-flagd/tests/e2e/rpc/test_flaqd.py +++ b/providers/openfeature-provider-flagd/tests/e2e/rpc/test_flaqd.py @@ -1,10 +1,5 @@ -import sys - from pytest_bdd import scenarios from tests.e2e.paths import TEST_HARNESS_PATH -# as soon as we support all the features, we can actually remove this limitation to not run on Python 3.8 -# Python 3.8 does not fully support tagging, hence that it will run all cases -if sys.version_info >= (3, 9): - scenarios(f"{TEST_HARNESS_PATH}/gherkin") +scenarios(f"{TEST_HARNESS_PATH}/gherkin") diff --git a/providers/openfeature-provider-flagd/tests/e2e/step/flag_step.py b/providers/openfeature-provider-flagd/tests/e2e/step/flag_step.py index 821b3be9..cc4386e4 100644 --- a/providers/openfeature-provider-flagd/tests/e2e/step/flag_step.py +++ b/providers/openfeature-provider-flagd/tests/e2e/step/flag_step.py @@ -1,5 +1,3 @@ -import typing - import requests from asserts import assert_equal from pytest_bdd import given, parsers, then, when @@ -20,7 +18,7 @@ ) def setup_key_and_default( key: str, default: JsonPrimitive, type_info: str -) -> typing.Tuple[str, JsonPrimitive, str]: +) -> tuple[str, JsonPrimitive, str]: return key, default, type_info diff --git a/providers/openfeature-provider-flagd/tests/e2e/step/provider_steps.py b/providers/openfeature-provider-flagd/tests/e2e/step/provider_steps.py index b571aa0e..76d739d9 100644 --- a/providers/openfeature-provider-flagd/tests/e2e/step/provider_steps.py +++ b/providers/openfeature-provider-flagd/tests/e2e/step/provider_steps.py @@ -1,7 +1,6 @@ import logging import os import time -import typing from enum import Enum from pathlib import Path @@ -43,7 +42,7 @@ def setup_provider_old( def get_default_options_for_provider( provider_type: str, resolver_type: ResolverType, container -) -> typing.Tuple[dict, bool]: +) -> tuple[dict, bool]: launchpad = "default" t = TestProviderType(provider_type) options: dict = { diff --git a/providers/openfeature-provider-flagd/tests/test_targeting.py b/providers/openfeature-provider-flagd/tests/test_targeting.py index e9ac318f..2e5fd234 100644 --- a/providers/openfeature-provider-flagd/tests/test_targeting.py +++ b/providers/openfeature-provider-flagd/tests/test_targeting.py @@ -98,11 +98,11 @@ class VersionPrefixed(Enum): @dataclass class SemVerTest: title: str - rule: typing.List[str] + rule: list[str] result: typing.Optional[bool] -semver_operations: typing.List[SemVerTest] = [ +semver_operations: list[SemVerTest] = [ # Successful and working rules SemVerTest("equals", ["1.2.3", "=", "1.2.3"], True), SemVerTest("not equals", ["1.2.3", "!=", "1.2.4"], True), diff --git a/providers/openfeature-provider-flipt/pyproject.toml b/providers/openfeature-provider-flipt/pyproject.toml index 29a9e6e4..368362d0 100644 --- a/providers/openfeature-provider-flipt/pyproject.toml +++ b/providers/openfeature-provider-flipt/pyproject.toml @@ -20,7 +20,7 @@ dependencies = [ "openfeature-sdk>=0.7.0", "openfeature-provider-ofrep>=0.1.0", ] -requires-python = ">=3.8" +requires-python = ">=3.9" [project.urls] Homepage = "https://github.com/open-feature/python-sdk-contrib" @@ -75,7 +75,7 @@ omit = [ mypy_path = "src" files = "src" -python_version = "3.8" # should be identical to the minimum supported version +python_version = "3.9" # should be identical to the minimum supported version namespace_packages = true explicit_package_bases = true local_partial_types = true diff --git a/providers/openfeature-provider-flipt/src/openfeature/contrib/provider/flipt/__init__.py b/providers/openfeature-provider-flipt/src/openfeature/contrib/provider/flipt/__init__.py index 5a8215bf..b609394b 100644 --- a/providers/openfeature-provider-flipt/src/openfeature/contrib/provider/flipt/__init__.py +++ b/providers/openfeature-provider-flipt/src/openfeature/contrib/provider/flipt/__init__.py @@ -1,4 +1,4 @@ -from typing import Callable, Dict, Optional +from typing import Callable, Optional from openfeature.contrib.provider.ofrep import OFREPProvider from openfeature.provider import Metadata @@ -15,7 +15,7 @@ def __init__( base_url: str, namespace: str, *, - headers_factory: Optional[Callable[[], Dict[str, str]]] = None, + headers_factory: Optional[Callable[[], dict[str, str]]] = None, timeout: float = 5.0, ): """Override the OFREPProvider constructor to add a namespace parameter""" @@ -25,8 +25,8 @@ def __init__( super().__init__(base_url, headers_factory=headers_factory, timeout=timeout) def _resolve_header_factory( - self, namespace: str, headers_factory: Optional[Callable[[], Dict[str, str]]] - ) -> Callable[[], Dict[str, str]]: + self, namespace: str, headers_factory: Optional[Callable[[], dict[str, str]]] + ) -> Callable[[], dict[str, str]]: """ Resolves and returns a headers factory callable that includes the "X-Flipt-Namespace" header. diff --git a/providers/openfeature-provider-ofrep/pyproject.toml b/providers/openfeature-provider-ofrep/pyproject.toml index c3563d9c..f77df995 100644 --- a/providers/openfeature-provider-ofrep/pyproject.toml +++ b/providers/openfeature-provider-ofrep/pyproject.toml @@ -20,7 +20,7 @@ dependencies = [ "openfeature-sdk>=0.7.0", "requests>=2.27.0" ] -requires-python = ">=3.8" +requires-python = ">=3.9" [project.urls] Homepage = "https://github.com/open-feature/python-sdk-contrib" @@ -75,7 +75,7 @@ omit = [ mypy_path = "src" files = "src" -python_version = "3.8" # should be identical to the minimum supported version +python_version = "3.9" # should be identical to the minimum supported version namespace_packages = true explicit_package_bases = true local_partial_types = true diff --git a/providers/openfeature-provider-ofrep/src/openfeature/contrib/provider/ofrep/__init__.py b/providers/openfeature-provider-ofrep/src/openfeature/contrib/provider/ofrep/__init__.py index 8007afa7..7e663831 100644 --- a/providers/openfeature-provider-ofrep/src/openfeature/contrib/provider/ofrep/__init__.py +++ b/providers/openfeature-provider-ofrep/src/openfeature/contrib/provider/ofrep/__init__.py @@ -1,7 +1,7 @@ import re from datetime import datetime, timedelta, timezone from email.utils import parsedate_to_datetime -from typing import Any, Callable, Dict, List, NoReturn, Optional, Tuple, Type, Union +from typing import Any, Callable, NoReturn, Optional, Union from urllib.parse import urljoin import requests @@ -25,14 +25,14 @@ __all__ = ["OFREPProvider"] -TypeMap = Dict[ +TypeMap = dict[ FlagType, Union[ - Type[bool], - Type[int], - Type[float], - Type[str], - Tuple[Type[dict], Type[list]], + type[bool], + type[int], + type[float], + type[str], + tuple[type[dict], type[list]], ], ] @@ -42,7 +42,7 @@ def __init__( self, base_url: str, *, - headers_factory: Optional[Callable[[], Dict[str, str]]] = None, + headers_factory: Optional[Callable[[], dict[str, str]]] = None, timeout: float = 5.0, ): self.base_url = base_url @@ -54,7 +54,7 @@ def __init__( def get_metadata(self) -> Metadata: return Metadata(name="OpenFeature Remote Evaluation Protocol Provider") - def get_provider_hooks(self) -> List[Hook]: + def get_provider_hooks(self) -> list[Hook]: return [] def resolve_boolean_details( @@ -191,8 +191,8 @@ def _handle_error(self, exception: requests.RequestException) -> NoReturn: def _build_request_data( evaluation_context: Optional[EvaluationContext], -) -> Dict[str, Any]: - data: Dict[str, Any] = {} +) -> dict[str, Any]: + data: dict[str, Any] = {} if evaluation_context: data["context"] = {} if evaluation_context.targeting_key: diff --git a/ruff.toml b/ruff.toml index 55f93a89..4701804b 100644 --- a/ruff.toml +++ b/ruff.toml @@ -5,7 +5,7 @@ exclude = [ "venv", "providers/openfeature-provider-flagd/src/openfeature/schemas/**" ] -target-version = "py38" +target-version = "py39" [lint] select = [