mafw.devtools.pyversions.identifiers

Python version-identifier parsing for the devtools python command group.

This module classifies the textual version tokens accepted by the Python version management feature (GitLab issue #247) into exactly one of three kinds and never consults the local machine for installed interpreters:

The free-threaded t suffix is a Hatch/uv interpreter selector that the standard packaging.version.Version parser does not model, therefore the parsing is implemented here with explicit, anchored regular expressions and packaging.version.Version is only used downstream for ordering and comparison of the base major.minor versions.

Added in version 2.4.

author:

Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu)

Functions

parse_identifier(token)

Classify a Python version token into a VersionIdentifier.

Classes

IdentifierKind(*values)

The three kinds of Python version identifier understood by the feature.

VersionIdentifier(kind, major, minor[, ...])

A parsed, immutable Python version identifier.

class mafw.devtools.pyversions.identifiers.IdentifierKind(*values)[source]

Bases: Enum

The three kinds of Python version identifier understood by the feature.

FREE_THREADED = 'free_threaded'

A free-threaded interpreter selector, e.g. 3.15t.

MINOR_TARGET = 'minor'

A stable CPython major.minor release target, e.g. 3.15.

PRERELEASE = 'prerelease'

A specific prerelease identifier, e.g. 3.16a1.

class mafw.devtools.pyversions.identifiers.VersionIdentifier(kind: IdentifierKind, major: int, minor: int, phase: str | None = None, serial: int | None = None)[source]

Bases: object

A parsed, immutable Python version identifier.

Instances are produced by parse_identifier(). They carry the parsed components so that callers can reason about the base major.minor version (shared by every kind) independently of the concrete selector.

Variables:
  • kind – The classification of the token.

  • major – The major version number (always 3 in practice, but parsed generically).

  • minor – The minor version number.

  • phase – For a prerelease, the phase marker (a, b or rc); None otherwise.

  • serial – For a prerelease, the serial number following the phase marker; None otherwise.

render() → str[source]

Reproduce the original textual token.

render(parse_identifier(token)) == token holds for every token that parse_identifier() accepts, which makes the parser a lossless round-trip for the three supported forms.

property base_version: str

Return the major.minor base version string shared by every kind.

For 3.15, 3.15t and 3.16a1 the base versions are 3.15, 3.15 and 3.16 respectively.

mafw.devtools.pyversions.identifiers.parse_identifier(token: str) → VersionIdentifier[source]

Classify a Python version token into a VersionIdentifier.

The patterns are tried in a fixed order — minor target, free-threaded selector, prerelease — each anchored with re.fullmatch so that only an exact whole-string match is accepted. The machine is never queried for installed interpreters; the result is a pure syntactic classification.

Parameters:

token (str) – The raw version token, e.g. "3.15", "3.15t" or "3.16a1".

Returns:

The parsed identifier.

Return type:

VersionIdentifier

Raises:

DevtoolsError – If token matches none of the supported forms. The error names the unrecognised token and no state is mutated.

mafw.devtools.pyversions.identifiers._FREE_THREADED_SUFFIX = 't'

Suffix identifying a free-threaded interpreter selector.