diff --git a/.github/workflows/_checks.yml b/.github/workflows/_checks.yml index cd96161..0e41bba 100644 --- a/.github/workflows/_checks.yml +++ b/.github/workflows/_checks.yml @@ -12,8 +12,8 @@ jobs: with: enable-cache: true cache-dependency-glob: "**/pyproject.toml" - - run: uv python install 3.10 - - run: uv python pin 3.10 + - run: uv python install 3.11 + - run: uv python pin 3.11 - run: just install lint-ci - run: just adr-check @@ -49,7 +49,6 @@ jobs: fail-fast: false matrix: python-version: - - "3.10" - "3.11" - "3.12" - "3.13" @@ -96,7 +95,7 @@ jobs: with: enable-cache: true cache-dependency-glob: "**/pyproject.toml" - - run: uv python install 3.10 + - run: uv python install 3.11 - name: Each extra installs and imports in isolation run: | set -uo pipefail @@ -110,12 +109,12 @@ jobs: faststream faststream-sentry faststream-otl faststream-logging faststream-metrics faststream-all \ fastmcp fastmcp-metrics fastmcp-all" failed="" - uv venv --python 3.10 .v-bare >/dev/null + uv venv --python 3.11 .v-bare >/dev/null if uv pip install --python .v-bare/bin/python . >/dev/null 2>&1 \ && .v-bare/bin/python -c "import lite_bootstrap"; then :; else failed="$failed __bare__"; fi rm -rf .v-bare for e in $extras; do - uv venv --python 3.10 ".v-$e" >/dev/null + uv venv --python 3.11 ".v-$e" >/dev/null if uv pip install --python ".v-$e/bin/python" ".[$e]" >/dev/null 2>&1 \ && ".v-$e/bin/python" -c "import lite_bootstrap"; then :; else failed="$failed $e"; fi rm -rf ".v-$e" @@ -138,7 +137,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] + python-version: ["3.11", "3.12", "3.13", "3.14"] target: [free, fastapi, litestar, faststream, fastmcp] # These `include` entries name an existing `target`, so each adds `extras` to that # target's five combinations rather than creating a job of its own. `free` carries diff --git a/.github/workflows/security-audit.yml b/.github/workflows/security-audit.yml index 187f535..284d339 100644 --- a/.github/workflows/security-audit.yml +++ b/.github/workflows/security-audit.yml @@ -18,7 +18,7 @@ jobs: with: enable-cache: true cache-dependency-glob: "**/pyproject.toml" - - run: uv python install 3.10 + - run: uv python install 3.11 - name: Export locked dependencies run: uv export --all-extras --no-hashes > /tmp/requirements.txt - name: Install pip-audit diff --git a/lite_bootstrap/instruments/base.py b/lite_bootstrap/instruments/base.py index c2c3d4f..8b151ec 100644 --- a/lite_bootstrap/instruments/base.py +++ b/lite_bootstrap/instruments/base.py @@ -1,8 +1,6 @@ import dataclasses import typing -import typing_extensions - @dataclasses.dataclass(kw_only=True, slots=True, frozen=True) class BaseConfig: @@ -21,13 +19,13 @@ def __post_init__(self) -> None: """ @classmethod - def from_dict(cls, data: dict[str, typing.Any]) -> typing_extensions.Self: + def from_dict(cls, data: dict[str, typing.Any]) -> typing.Self: """Build a config from a dict; unknown keys are silently dropped, explicit None overrides defaults.""" field_names = {f.name for f in dataclasses.fields(cls)} return cls(**{k: v for k, v in data.items() if k in field_names}) @classmethod - def from_object(cls, obj: object) -> typing_extensions.Self: + def from_object(cls, obj: object) -> typing.Self: """Build a config by merging non-None attributes from obj; None or missing attributes fall back to defaults.""" field_names = {f.name for f in dataclasses.fields(cls)} prepared_data = {field: value for field in field_names if (value := getattr(obj, field, None)) is not None} diff --git a/pyproject.toml b/pyproject.toml index 18ffea0..33b6c2c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,13 +5,12 @@ authors = [ { name = "Artur Shiriev", email = "me@shiriev.ru" }, ] readme = "README.md" -requires-python = ">=3.10,<4" +requires-python = ">=3.11,<4" license = "MIT" keywords = ["microservices", "bootstrap", "opentelemetry", "sentry", "prometheus", "healthcheck", "fastapi", "litestar", "faststream", "structlog", "fastmcp", "python"] classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", @@ -21,11 +20,9 @@ classifiers = [ ] version = "0" dependencies = [ - # Runtime use: `typing_extensions.Self` (base.py) and `typing_extensions.TypedDict` - # (healthchecks) — the latter is required by pydantic/FastAPI on Python < 3.12 - # (`typing.TypedDict` is rejected there). Pure Python, so ft-friendly. - # >=4.0 for `Self`; >=4.6 because 4.4 and 4.5 raise on import under Python >=3.12 - # (they subclass `typing.TypeVar`). The higher floor wins. + # Runtime use: `typing_extensions.TypedDict` (healthchecks), required by pydantic/FastAPI on + # Python < 3.12 (`typing.TypedDict` is rejected there). Pure Python, so ft-friendly. + # >=4.6 because 4.4 and 4.5 raise on import under Python >=3.12 (they subclass `typing.TypeVar`). "typing-extensions>=4.6", ] @@ -49,7 +46,7 @@ sentry = [ # >=1.31 for the `max_value_length` init option; >=2.1 for sentry_sdk.set_tags (plural, # SentryInstrument.bootstrap) -- the higher floor wins. # 2.1 predates Python 3.13's FrameLocalsProxy, which the SDK fails to pickle when capturing a - # request, and 3.14 needs later fixes again. Marked rather than raised, so 3.10-3.12 keep 2.1. + # request, and 3.14 needs later fixes again. Marked rather than raised, so 3.11-3.12 keep 2.1. # 2.69.0 signs `sentry-trace`/`baggage` into SigV4 SignedHeaders and then rewrites them after # signing, so every aiobotocore AWS call inside a transaction fails with SignatureDoesNotMatch # (getsentry/sentry-python#7426, fixed in 2.69.1).