Skip to content

Gate the StrEnum fallback on sys.version_info instead of try/except - #769

Open
5point1 wants to merge 1 commit into
mobilityhouse:masterfrom
5point1:strenum-version-info-gate
Open

Gate the StrEnum fallback on sys.version_info instead of try/except#769
5point1 wants to merge 1 commit into
mobilityhouse:masterfrom
5point1:strenum-version-info-gate

Conversation

@5point1

@5point1 5point1 commented Jul 21, 2026

Copy link
Copy Markdown

Changes included in this PR

Compat chore: replace the try/except ImportError StrEnum fallback with a sys.version_info >= (3, 11) gate in the three enums.py modules (v16, v201, v21).

Current behavior

Static type checkers can't tell which branch of a try/except ImportError wins, so the StrEnum base — and with it the type of every enum member — is ambiguous to them. Checking a downstream codebase with ty reports invalid-argument-type every time an enum member is passed to a parameter annotated with its own enum type (e.g. RegistrationStatus.accepted against a status: RegistrationStatus field).

Minimal repro (ty 0.0.61)
try:
    from enum import StrEnum
except ImportError:
    from enum import Enum

    class StrEnum(str, Enum):
        pass


class Color(StrEnum):
    red = "RED"


def f(c: Color) -> None: ...


f(Color.red)  # error[invalid-argument-type]

The same snippet with if sys.version_info >= (3, 11): passes cleanly.

New behavior

None at runtime: enum.StrEnum is still used on 3.11+, and the fallback still covers 3.8–3.10. sys.version_info gates are the idiom type checkers special-case and prune (it's what typeshed uses throughout), so enum members type correctly again. On a downstream CSMS project, ty went from 43 to 24 diagnostics with this patch — all 19 removed were these false positives.

Impact

No breaking change; the import logic is identical at runtime. The # pragma: no cover moves onto the else: clause (ocpp/v16/enums.py still reports 100% coverage locally), and the CI matrix already exercises both branches (3.8–3.10 take the fallback, 3.11–3.13 the stdlib import).

Checklist

  1. Does your submission pass the existing tests? — 182 passed, via poetry install + the make tests commands
  2. Are there new tests that cover these additions/changes? — no behavior change to cover; both branches are already exercised by the 3.8–3.13 CI matrix
  3. Have you linted your code locally before submission? — black, isort and flake8 all clean

Static type checkers prune sys.version_info branches (the idiom used
throughout typeshed) but analyze both branches of a try/except
ImportError, so the fallback class made every enum member's type
ambiguous downstream. With ty, any enum member passed to a parameter
annotated with its enum type was reported as invalid-argument-type.

Runtime behavior is unchanged: enum.StrEnum exists on 3.11+, the
fallback keeps covering 3.8-3.10.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@5point1
5point1 requested review from mdwcrft and proelke as code owners July 21, 2026 17:35
@a-alak

a-alak commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Thought: since < 3.11 stops being supported in October, should this package maybe follow that?
Or are a lot of users expected to be on 3.8-3.10?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants