Skip to main content

Language-agnostic version management across project files

Project description

vrzn

Author: Scott Arne Johnson (scott.arne.johnson@gmail.com)

Language-agnostic version management across project files.

Overview

Projects often store version numbers in multiple files: pyproject.toml, __init__.py, CMakeLists.txt, package.json, and others. When these fall out of sync, builds break and releases ship incorrect metadata.

vrzn solves this by letting you declare every file that contains a version number in a single configuration file. It can then read, set, and bump versions across all of them at once, with full PEP 440 support.

Installation

Requires Python 3.10 or later.

pip install vrzn

For YAML config file support:

pip install 'vrzn[yaml]'

Quick Start

Create a vrzn.toml in your project root:

[[locations]]
file = "pyproject.toml"
type = "pyproject-version"

[[locations]]
file = "src/mypackage/__init__.py"
type = "python-dunder"

Check that all version locations are in sync:

$ vrzn get

                       vrzn — version report
╭───────────────────────────┬───────────────────┬─────────┬────────╮
│ File                      │ Location          │ Version │ Status │
├───────────────────────────┼───────────────────┼─────────┼────────┤
│ pyproject.toml            │ pyproject-version │  1.0.0  │   ok   │
├───────────────────────────┼───────────────────┼─────────┼────────┤
│ src/mypackage/__init__.py │ python-dunder     │  1.0.0  │   ok   │
╰───────────────────────────┴───────────────────┴─────────┴────────╯

  Consensus version: 1.0.0
  All version numbers are consistent.

Set a specific version everywhere:

$ vrzn -y set 1.2.0

  Setting version to 1.2.0

                                updated files
╭───────────────────────────┬───────────────────┬─────────┬───────┬─────────╮
│ File                      │ Location          │ Current │  New  │ Result  │
├───────────────────────────┼───────────────────┼─────────┼───────┼─────────┤
│ pyproject.toml            │ pyproject-version │  1.0.0  │ 1.2.0 │ updated │
│ src/mypackage/__init__.py │ python-dunder     │  1.0.0  │ 1.2.0 │ updated │
╰───────────────────────────┴───────────────────┴─────────┴───────┴─────────╯

  All versions set to 1.2.0.

Bump the version:

$ vrzn -y bump patch

  Version bump: 1.2.0 → 1.2.1

                                updated files
╭───────────────────────────┬───────────────────┬─────────┬───────┬─────────╮
│ File                      │ Location          │ Current │  New  │ Result  │
├───────────────────────────┼───────────────────┼─────────┼───────┼─────────┤
│ pyproject.toml            │ pyproject-version │  1.2.0  │ 1.2.1 │ updated │
│ src/mypackage/__init__.py │ python-dunder     │  1.2.0  │ 1.2.1 │ updated │
╰───────────────────────────┴───────────────────┴─────────┴───────┴─────────╯

  Version bumped to 1.2.1.

Preview changes without writing files:

$ vrzn --dry-run bump minor

  Version bump: 1.2.1 → 1.3.0

                                    dry run
╭───────────────────────────┬───────────────────┬─────────┬───────┬──────────────╮
│ File                      │ Location          │ Current │  New  │    Result     │
├───────────────────────────┼───────────────────┼─────────┼───────┼──────────────┤
│ pyproject.toml            │ pyproject-version │  1.2.1  │ 1.3.0 │ would update │
│ src/mypackage/__init__.py │ python-dunder     │  1.2.1  │ 1.3.0 │ would update │
╰───────────────────────────┴───────────────────┴─────────┴───────┴──────────────╯

  Dry run — no files were modified.

Pre-release workflows:

vrzn -y bump major dev  # 1.2.3 -> 2.0.0.dev1
vrzn -y bump minor a    # 1.2.3 -> 1.3.0a1
vrzn -y bump patch rc   # 1.2.3 -> 1.2.4rc1
vrzn -y bump pre        # 1.2.4rc1 -> 1.2.4rc2
vrzn -y bump release    # 1.2.4rc2 -> 1.2.4
vrzn -y bump post       # 1.2.4 -> 1.2.4.post1

CLI Reference

Global Options

Global options must be placed before the subcommand (e.g., vrzn --dry-run bump patch).

Option Description
--dry-run Show what would change without writing files.
--yes, -y Skip confirmation prompts.
--quiet, -q Machine-readable output, no tables.
--config, -c PATH Path to config file (overrides discovery).

Commands

vrzn get

Display the current version in all configured files. Prints a table showing each location, its version, and whether it matches the consensus.

With --quiet, prints only the consensus version string.

Exit codes: 0 if all versions agree, 1 if mismatches exist, 2 if no config found.

vrzn set VERSION

Set all version numbers to VERSION. Accepts any PEP 440 version string (e.g., 1.0.0, 1.0.0rc1, 1.0.0.post1). Non-normalized forms are accepted and automatically normalized.

Prompts for confirmation unless --yes or --dry-run is set.

Exit codes: 1 for invalid version format, 2 if no config found.

vrzn bump PART [LABEL] [--pre LABEL]

Bump the version number. PART must be one of: major, minor, patch, pre, release, post.

Use a positional LABEL or --pre with a label (alpha, a, beta, b, dev, rc) to enter a pre-release or dev-release state. For example, vrzn bump minor rc moves 1.2.3 to 1.3.0rc1, and vrzn bump patch --pre dev moves 1.2.3 to 1.2.4.dev1.

Use bump pre to increment an existing pre-release or dev-release. Use bump release to finalize a pre-release to its stable version. Use bump post to start or increment a post-release suffix.

If versions are out of sync, vrzn warns and uses a consensus version (most common across locations). Prompts for confirmation unless --yes or --dry-run is set.

Exit codes: 1 for errors (no readable version, invalid bump operation), 2 if no config found.

Configuration

vrzn searches up the directory tree for config in this order:

  1. vrzn.toml
  2. vrzn.yaml
  3. vrzn.json
  4. pyproject.toml (under [tool.vrzn])

Built-in Presets

Each preset is a template string with a version placeholder that tells vrzn how to find and replace the version in a file.

Preset Matches Format
pyproject-version version = "X.Y.Z" in TOML full
python-dunder __version__ = "X.Y.Z" full
python-version-info __version_info__ = (X, Y, Z) base
cmake-project project(NAME VERSION X.Y.Z) base
c-define #define PREFIX_VERSION_MAJOR N component
cargo-toml version = "X.Y.Z" in Cargo.toml full
package-json "version": "X.Y.Z" in JSON full
maven-pom <version>X.Y.Z</version> full
gradle-version version = 'X.Y.Z' in Gradle full

Format types:

  • full — reads/writes a complete PEP 440 version string (e.g., 1.2.3rc1)
  • base — reads/writes only MAJOR.MINOR.PATCH (e.g., 1.2.3), ignoring pre-release suffixes
  • component — reads/writes a single integer (MAJOR, MINOR, or PATCH); excluded from agreement checking

The c-define preset requires a prefix parameter and expands to three component locations:

[[locations]]
file = "include/mylib.h"
type = "c-define"
prefix = "MYLIB"

Custom Locations

For files that don't match a built-in preset, use custom with a template string containing a version placeholder:

[[locations]]
file = "docs/conf.py"
type = "custom"
label = "Sphinx config"
template = 'release\s*=\s*"{version}"'

The template is a regex string with exactly one placeholder embedded in it. The text around the placeholder is standard regex that matches the surrounding context in the file.

Available placeholders:

Placeholder Writes Format
{version} Full PEP 440 version (e.g., 1.2.3rc1) full
{base} MAJOR.MINOR.PATCH only (e.g., 1.2.3) base
{info_tuple} Comma-separated tuple (e.g., 1, 2, 3) base
{major} Major version integer component
{minor} Minor version integer component
{patch} Patch version integer component

Development

pip install --config-settings editable_mode=compat -e ".[dev,yaml]"
pytest

License

MIT License. Copyright (c) 2026 Scott Arne Johnson. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vrzn-0.2.2-py3-none-any.whl (18.1 kB view details)

Uploaded Python 3

File details

Details for the file vrzn-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: vrzn-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 18.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.11

File hashes

Hashes for vrzn-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 924088e0395c2dc61db9425fec42a06881277667366a65a2fbf6ccf705c76e79
MD5 7bf3cdf738bd77310fc0a0967bc513c6
BLAKE2b-256 b37c2b4b918e14223c46b607ecd8d8e4960ee5e5b56295c305ca83351fd2dc08

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page