Version Utilities

The version utilities provide a small, focused API for representing, parsing, and comparing the package’s own version triple (major, minor, patch) programmatically.

The module lives at _errortools.version and is re-exported from the top-level errortools package so that downstream code can do::

from errortools import VersionInfo, get_version_tuple

Module-level constants

The _errortools.version module exposes the current release in three forms, each duplicated under both a dunder name (PEP 396 / packaging convention) and a lower-case alias:

Constant

Type

Description

__version__

str

Dotted-decimal string such as "3.5.1".

version

str

Lower-case alias of __version__ (same object).

__version_tuple__

tuple[int, int, int]

(major, minor, patch) triple.

version_tuple

tuple[int, int, int]

Lower-case alias of __version_tuple__.

__commit_id__

str | None

Git commit hash for source builds, else None.

commit_id

str | None

Lower-case alias of __commit_id__.

The lower-case names refer to the same objects as their dunder counterparts, so identity-based assertions (x is y) hold.

>>> import errortools
>>> errortools.version is errortools.__version__
True
>>> errortools.version_tuple is errortools.__version_tuple__
True
>>> errortools.commit_id is errortools.__commit_id__
True
>>> errortools.__version_tuple__
(3, 5, 1)

VersionInfo

class errortools.VersionInfo(major, minor, patch)[source]

Bases: object

A lightweight value object representing a dotted-decimal version.

The three components follow the standard major.minor.patch convention. Instances are fully comparable and hashable, so they can be used as dictionary keys or stored in sets.

Example

>>> v = VersionInfo(3, 5, 1)
>>> str(v)
'3.5.1'
>>> v < VersionInfo(4, 0, 0)
True

Added in version 3.5.

Parameters:
  • major (int)

  • minor (int)

  • patch (int)

major: int
minor: int
patch: int
classmethod from_str(version_str)[source]

Create a VersionInfo from a dotted-decimal string.

Missing components default to 0 and components past the third are silently discarded. A ValueError is raised when the string is empty, ends with a trailing dot, or contains a non-numeric component.

Example

>>> VersionInfo.from_str("3.5.1")
VersionInfo(major=3, minor=5, patch=1)
>>> VersionInfo.from_str("3.2")
VersionInfo(major=3, minor=2, patch=0)

Added in version 3.5.

Parameters:

version_str (str)

Return type:

VersionInfo

to_tuple()[source]

Return the version as an (major, minor, patch) tuple.

Return type:

tuple[int, int, int]

Overview

VersionInfo is a small @dataclass (with __slots__) that holds three integer components — major, minor, patch — and makes them fully comparable and hashable.

>>> from errortools import VersionInfo
>>> v = VersionInfo(3, 5, 1)
>>> v
VersionInfo(major=3, minor=5, patch=1)
>>> str(v)
'3.5.1'

Construction

The dataclass accepts any three integers; the values are stored verbatim (no range validation is performed):

>>> VersionInfo(3, 5, 1)
VersionInfo(major=3, minor=5, patch=1)
>>> VersionInfo(0, 0, 0)
VersionInfo(major=0, minor=0, patch=0)

The from_str classmethod parses a dotted-decimal string into a VersionInfo:

>>> VersionInfo.from_str("3.5.1")
VersionInfo(major=3, minor=5, patch=1)
>>> VersionInfo.from_str("3.2")            # missing patch -> 0
VersionInfo(major=3, minor=2, patch=0)
>>> VersionInfo.from_str("3")              # missing minor/patch -> 0/0
VersionInfo(major=3, minor=0, patch=0)
>>> VersionInfo.from_str("1.2.3.4.5")      # extra components discarded
VersionInfo(major=1, minor=2, patch=3)

A ValueError is raised for empty strings, trailing dots, or any non-numeric component:

>>> VersionInfo.from_str("")
Traceback (most recent call last):
...
ValueError: Invalid version string: ''
>>> VersionInfo.from_str("3.2.")
Traceback (most recent call last):
...
ValueError: Invalid version string: '3.2.'
>>> VersionInfo.from_str("3.2.a")
Traceback (most recent call last):
...
ValueError: Invalid version string: '3.2.a'

Conversion

to_tuple() returns the components as a plain (major, minor, patch) tuple of ints:

>>> VersionInfo(3, 5, 1).to_tuple()
(3, 5, 1)

Equality and hashing

Two VersionInfo instances are equal iff their three components are equal. Because the class defines __hash__, instances can be used as dictionary keys or stored in sets:

>>> VersionInfo(3, 5, 1) == VersionInfo(3, 5, 1)
True
>>> VersionInfo(3, 5, 1) != VersionInfo(3, 5, 2)
True
>>> {VersionInfo(1, 0, 0), VersionInfo(1, 0, 0), VersionInfo(2, 0, 0)}
{VersionInfo(major=1, minor=0, patch=0), VersionInfo(major=2, minor=0, patch=0)}
>>> mapping = {VersionInfo(1, 0, 0): "v1", VersionInfo(2, 0, 0): "v2"}
>>> mapping[VersionInfo(2, 0, 0)]
'v2'

Equality against an unrelated type returns False (Python’s standard fallback when both __eq__ methods return NotImplemented):

>>> VersionInfo(1, 0, 0) == "1.0.0"
False
>>> VersionInfo(1, 0, 0) == (1, 0, 0)
False

Ordering

VersionInfo is totally ordered, component by component, the same way Python compares integer tuples:

Operator

Meaning

<

strictly less (lexicographic on components)

<=

less than or equal

>

strictly greater (lexicographic on components)

>=

greater than or equal

>>> VersionInfo(1, 9, 9) < VersionInfo(2, 0, 0)        # by major
True
>>> VersionInfo(1, 2, 9) < VersionInfo(1, 3, 0)        # by minor
True
>>> VersionInfo(1, 2, 3) < VersionInfo(1, 2, 4)        # by patch
True

This makes VersionInfo work directly with the standard library:

>>> versions = [
...     VersionInfo(2, 0, 0),
...     VersionInfo(1, 1, 5),
...     VersionInfo(1, 2, 0),
...     VersionInfo(1, 2, 3),
... ]
>>> sorted(versions)
[VersionInfo(major=1, minor=1, patch=5), VersionInfo(major=1, minor=2, patch=0), VersionInfo(major=1, minor=2, patch=3), VersionInfo(major=2, minor=0, patch=0)]
>>> min(versions)
VersionInfo(major=1, minor=1, patch=5)
>>> max(versions)
VersionInfo(major=2, minor=0, patch=0)

Memory layout

VersionInfo declares __slots__ so instances do not carry a __dict__. This makes the class a good fit for representing versions in hot paths or in large in-memory collections:

>>> VersionInfo(1, 2, 3).__slots__
('major', 'minor', 'patch')

get_version_tuple

errortools.get_version_tuple(version)[source]

Parse a dotted-decimal version string into an integer triple.

Examples

>>> get_version_tuple("3.5.1")
(3, 5, 1)
>>> get_version_tuple("3.2")
(3, 2, 0)
>>> get_version_tuple("3")
(3, 0, 0)
>>> get_version_tuple("1.2.3.4.5")
(1, 2, 3)
Parameters:

version (str) – A dotted-decimal version string such as "3.5.1".

Returns:

A (major, minor, patch) tuple. Missing components default to 0 and components past the third are discarded.

Raises:

ValueError – If the string is empty, ends with a trailing dot, or contains a non-numeric component.

Return type:

tuple[int, int, int]

Changed in version 3.5: add it to the public API.

Overview

get_version_tuple is the parsing function that powers VersionInfo.from_str. It is exposed on its own so callers that only need the integer triple can skip the dataclass overhead.

>>> from errortools import get_version_tuple
>>> get_version_tuple("3.5.1")
(3, 5, 1)
>>> get_version_tuple("3.2")            # missing patch -> 0
(3, 2, 0)
>>> get_version_tuple("3")              # missing minor/patch -> 0/0
(3, 0, 0)
>>> get_version_tuple("1.2.3.4.5")      # extra components discarded
(1, 2, 3)

Error handling

A ValueError is raised when the input cannot be parsed. The error message includes the offending input for easier debugging:

>>> get_version_tuple("")
Traceback (most recent call last):
...
ValueError: Invalid version string: ''
>>> get_version_tuple("3.2.")
Traceback (most recent call last):
...
ValueError: Invalid version string: '3.2.'
>>> get_version_tuple("3.2.a")
Traceback (most recent call last):
...
ValueError: Invalid version string: '3.2.a'
>>> get_version_tuple("a.b.c")
Traceback (most recent call last):
...
ValueError: Invalid version string: 'a.b.c'

When to use which?

  • Need the live package version? Use errortools.__version__, errortools.__version_tuple__, or errortools.__commit_id__.

  • Need to parse an external version string? Use get_version_tuple (raw triple) or VersionInfo.from_str (object form, comparable / hashable).

  • Need to compare or sort a collection of versions? Use VersionInfo directly so you can rely on ==, <, <=, >, >=, sorted(), min(), max(), and hashable containers.

See also