Verple is a ridiculously strict and ultra-conservative universal version format, comparator, serializer, and protocol.
- 🔒 Ultra-conservative equality: versions are considered different if any field differs (
release
,prerelease
,postrelease
,devrelease
,local
). - ⚖ Strict conservative ordering: ordering is only permitted when local metadata matches exactly; otherwise ordering raises
ValueError
to avoid ambiguity. - 🔎 Multi-standard input support: parses version strings from PEP 440, SemVer, Canonical, and Calendar Versioning (CalVer).
- 🔁 Canonical serialization: provides fully reversible serialization via
to_canonical_string()
and parsing viafrom_canonical_string()
. - 🧮 Hashable and set-safe: fully hashable and safe for use in sets and dictionaries, with hashes consistent with strict equality.
- 📦 JSON-LD serialization: supports semantic serialization with provenance (
sourceFormat
andsourceInput
fields). - 🔐 Versioned deserialization protocol: fully versioned serialization model allowing future-safe protocol evolution.
- 📚 Use Case Domains: reproducible builds, registries, deployment pipelines, archival systems, provenance tracking, scientific reproducibility.
- Python >= 3.10
pip install verple
from verple import Verple
# Parse version string
v1 = Verple.parse("1.2.3a1.post2.dev3+build99")
print(v1.to_canonical_string()) # 1.2.3-a1.post2.dev3+build99
# Strict equality
v2 = Verple.parse("1.2.3a1.post2.dev3+build99")
assert v1 == v2
# Hashable and set-safe
versions = {v1, v2}
assert len(versions) == 1
# Conservative ordering (only if local metadata matches)
v3 = Verple.parse("1.2.4+build99")
assert v1 < v3
# JSON-LD serialization
jsonld = v1.to_jsonld()
v1_roundtrip = Verple.from_jsonld(jsonld)
assert v1 == v1_roundtrip
Verple canonical strings follow this grammar:
<release>[-<prerelease>][.post<N>][.dev<N>][+<local>]
Example:
1.2.3-a1.post2.dev3+build99
Verple also supports semantic serialization:
{
"@context": "https://gitlab.com/willynilly/verple/-/raw/main/src/verple/context/v1.0.0.jsonld",
"@type": "Verple",
"verple": "1.0.0",
"sourceFormat": "pep440",
"sourceInput": "1.2.3a1.post2.dev3+build99",
"release": [1, 2, 3],
"prerelease": ["a", 1],
"postrelease": 2,
"devrelease": 3,
"local": "build99"
}
This allows full provenance and schema evolution.
This project uses pytest
:
pytest tests/
Verple normalizes versions into a fully structured model with the following fields:
release
: tuple of integers (major, minor, patch, or calendar parts)prerelease
: tuple of(label: str, num: int)
orNone
postrelease
: integer orNone
devrelease
: integer orNone
local
: string orNone
sourceInput
: original version stringsourceFormat
: the parsed format (pep440
,semver
,canonical
,calver
)
All formats (PEP 440, SemVer, Canonical, CalVer) are converted into this internal structure.
Two versions are equal if and only if all of the following fields are equal:
release
prerelease
postrelease
devrelease
local
Fields are compared strictly; any difference implies inequality.
Ordering is permitted only if both versions have identical local
metadata. If local
differs, ordering is refused.
If allowed, versions are compared using the tuple:
(
release,
prerelease_key(prerelease),
postrelease or -1,
devrelease or infinity
)
Where:
prerelease_key(None)
→(infinity,)
(normal releases sort after prereleases)prerelease_key((label, num))
→(label, num)
(string then numeric comparison)
The algorithm aligns with PEP 440 precedence where applicable.
Serialization via to_canonical_string()
reconstructs the version string as:
<release>[-<prerelease>][.post<N>][.dev<N>][+<local>]
Fields that are None
are omitted.
The full semantic model is serialized as JSON-LD, including provenance fields sourceFormat
and sourceInput
for full reproducibility.
The following fields are used throughout Verple's internal model, canonical serialization, and JSON-LD serialization:
Field | Type | Meaning |
---|---|---|
release |
tuple of int | Core version numbers: major.minor.patch or calendar parts |
prerelease |
tuple (str, int) or None | Pre-release stage (alpha, beta, rc, etc.) and stage number |
postrelease |
int or None | Post-release revision applied after final release |
devrelease |
int or None | Development release version for pre-release internal builds |
local |
str or None | Local build metadata identifier (build info, git hash, etc.) |
sourceInput |
str | The original version string provided as input |
sourceFormat |
str | The detected format: pep440 , semver , canonical , or calver |
verple |
str | Serialization format version (e.g. "1.0.0" ) |
@context |
URL | JSON-LD context URL defining linked data vocabulary |
@type |
str | Always "Verple" |
-
release: The main numeric version (e.g.
1.2.3
), structured as Major.Minor.Patch (SemVer, PEP 440) or Year.Month.[Day] (CalVer). -
prerelease: A pre-final release marker such as
alpha
,beta
, orrc
, optionally followed by a stage number (e.g.rc1
). -
postrelease: Identifies patches or hotfixes applied after a final release (
.postN
). -
devrelease: Development snapshots issued before formal releases (
.devN
), typically for internal or unstable builds. -
local: Build metadata or local identifiers following
+build
semantics, capturing build environment or other internal state. -
sourceInput: The raw version string provided by the caller.
-
sourceFormat: Indicates which parser was used to interpret the input (
pep440
,semver
,canonical
,calver
). -
verple: The version of the Verple serialization protocol used to encode the JSON-LD document.
-
@context / @type: JSON-LD linked data metadata used to enable semantic parsing of Verple objects.
Apache 2.0
- Will Riley
- Co-developed with ChatGPT-4o during protocol design.