# Guide

This module covers the 2.0.0 version of the SemVer scheme, with additional extensions:

- Coercing any version string into a SemVer version, through `Version.coerce()`;

- Comparing versions;

- Computing next versions;

- Modelling version range specifcations, and choosing the best match – for both its custom logic, and NPM semantics (custom range specification schemes can be added).

## Version basics

### Building `Version` instances

The core of the module is the `Version` class; it is usually instantiated from a version string:

    >>> import semantic_version as semver
    >>> v = semver.Version("0.1.1")

The version’s components are available through its attributes:

- `major`, `minor`, `patch` are integers:

      >>> v.major
      0
      >>> v.minor
      1
      >>> v.patch
      1

- The `prerelease` and `build` attributes are iterables of text elements:

      >>> v2 = semver.Version("0.1.1-dev+23.git2")
      >>> v2.prerelease
      ["dev"]
      >>> v2.build
      ["23", "git2"]

One may also build a `Version` from named components directly:

    >>> semantic_version.Version(major=0, minor=1, patch=2)
    Version('0.1.2')

In that case, `major`, `minor` and `patch` are mandatory, and must be integers. `prerelease` and `build`, if provided, must be tuples of strings:

    >>> semantic_version.Version(major=0, minor=1, patch=2, prerelease=('alpha', '2'))
    Version('0.1.2-alpha.2')

If the provided version string is invalid, a `ValueError` will be raised:

    >>> semver.Version('0.1')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/Users/rbarrois/dev/semantic_version/src/semantic_version/base.py", line 64, in __init__
        major, minor, patch, prerelease, build = self.parse(version_string, partial)
      File "/Users/rbarrois/dev/semantic_version/src/semantic_version/base.py", line 86, in parse
        raise ValueError('Invalid version string: %r' % version_string)
    ValueError: Invalid version string: '0.1'

### Working with non-SemVer version strings

Some user-supplied input might not match the semantic version scheme. For such cases, the `Version.coerce` method will try to convert any version-like string into a valid semver version:

    >>> semver.Version.coerce('0')
    Version('0.0.0')
    >>> semver.Version.coerce('0.1.2.3.4')
    Version('0.1.2+3.4')
    >>> semver.Version.coerce('0.1.2a3')
    Version('0.1.2-a3')

### Comparing versions

Versions can be compared, following the SemVer scheme:

    >>> semver.Version("0.1.0") < semver.Version("0.1.1")
    True
    >>> max(
    ...   semver.Version("0.1.0"),
    ...   semver.Version("0.2.2"),
    ...   semver.Version("0.1.1"),
    ...   semver.Version("0.2.2-rc1"),
    ... )
    Version("0.2.2")

Note

As defined in SemVer, build metadata is ignored in comparisons, but not in equalities:

    >>> semver.Version("0.1.2") <= semver.Version("0.1.2+git2")
    True
    >>> semver.Version("0.1.2") >= semver.Version("0.1.2+git2")
    True
    >>> semver.Version("0.1.2") == semver.Version("0.1.2+git2")
    False

### Iterating versions

One can get a new version that represents a bump in one of the version levels through the `Version.next_major()`, `Version.next_minor()` or `Version.next_patch()` functions:

    >>> v = semver.Version('0.1.1+build')
    >>> new_v = v.next_major()
    >>> str(new_v)
    '1.0.0'
    >>> v = semver.Version('1.1.1+build')
    >>> new_v = v.next_minor()
    >>> str(new_v)
    '1.2.0'
    >>> v = semver.Version('1.1.1+build')
    >>> new_v = v.next_patch()
    >>> str(new_v)
    '1.1.2'

Note

- If the version includes `build` or `prerelease` metadata, that value will be empty in the next version;

- The next patch following a version with a pre-release identifier is the same version with its prerelease and build identifiers removed: `Version("0.1.1-rc1").next_patch() == Version("0.1.1")`

- Pre-release and build naming schemes are often custom and specific to a project’s internal design; thus, the library can’t provide a `next_xxx` method for those fields.

One may also truncate versions through the `Version.truncate()` method, removing components beyond the selected level:

    >>> v = semver.Version("0.1.2-dev+git3")
    >>> v.truncate("prerelease")
    Version("0.1.2-dev")
    >>> v.truncate("minor")
    Version("0.1.0")

## Range specifications

Comparing version numbers isn’t always enough; in many situations, one needs to define a range of acceptable versions.

That notion is not defined in SemVer; moreover, several systems exists, with their own notations.

The `semantic_version` package provides a couple of implementations for these notions:

- `SimpleSpec` is a simple implementation, with reasonable expectations;

- `NpmSpec` sticks to the NPM specification.

Further schemes can be built in a similar manner, relying on the `BaseSpec` class for basics.

### Core API

The core API is provided by the `BaseSpec` class.

Note

These examples use `SimpleSpec` in order to be easily reproduced by users, but only exhibit the standard parts of the interface.

It is possible to check whether a given `Version` matches a `BaseSpec` through `match()`:

    >>> s = semver.SimpleSpec(">=0.1.1")
    >>> s.match(Version("0.1.1"))
    True
    >>> s.match(Version("0.1.0"))
    False

This feature is also available through the `in` keyword:

    >>> s = semver.SimpleSpec(">=0.1.1")
    >>> Version("0.1.1") in s
    True
    >>> Version("0.1.0") in s
    False

A specification can filter compatible values from an iterable of versions with `filter()`:

    >>> s = semver.SimpleSpec(">=0.2.1")
    >>> versions = [
    ...   Version("0.1.0"),
    ...   Version("0.2.0"),
    ...   Version("0.3.0"),
    ...   Version("0.4.0"),
    ... ]
    >>> list(s.filter(versions))
    [Version("0.3.0"), Version("0.4.0")]

It can also select the “best” version from such an iterable through `select()`:

    >>> s = semver.SimpleSpec(">=0.2.1")
    >>> versions = [
    ...   Version("0.1.0"),
    ...   Version("0.2.0"),
    ...   Version("0.3.0"),
    ...   Version("0.4.0"),
    ... ]
    >>> s.select(versions)
    Version("0.4.0")

### The `SimpleSpec` scheme

The `SimpleSpec` provides a hopefully intuitive version range specification scheme:

- A specification expression is composed of comma-separated clauses;

- Each clause can be:

  - An equality match (`==` or `!=`);

  - A comparison (`>`, `>=`, `<` , `<=`);

  - A compatible release clause, PyPI style (`~=2.2` for `>=2.2.0,<3.0.0`);

  - An NPM style clause:

    - `~1.2.3` for `>=1.2.3,<1.3.0`;

    - `^1.3.4` for `>=1.3.4,<2.0.0`;

- The range in each clause may include a wildcard:

  - `==0.1.*` maps to `>=0.1.0,<0.2.0`;

  - `==1.*` or `==1.*.*` map to `>=1.0.0,<2.0.0`

Special matching rules

When testing a `Version` against a `SimpleSpec`, comparisons are adjusted for common user expectations; thus, a pre-release version (`1.0.0-alpha`) will not satisfy the `==1.0.0` `SimpleSpec`.

Pre-release identifiers will only be compared if included in the `BaseSpec` definition or (for the empty pre-release number) if a single dash is appended (`1.0.0-`):

    >>> Version('0.1.0-alpha') in SimpleSpec('<0.1.0')  # No pre-release identifier
    False
    >>> Version('0.1.0-alpha') in SimpleSpec('<0.1.0-')  # Include pre-release in checks
    True

Build metadata has no ordering; thus, the only meaningful comparison including build metadata is equality:

    >>> Version('1.0.0+build2') in SimpleSpec('<=1.0.0')   # Build metadata ignored
    True
    >>> Version('1.0.0+build1') in SimpleSpec('==1.0.0+build2')  # Include build in checks
    False

Note

The full documentation is provided in the reference section for the `SimpleSpec` class.

### The `NpmSpec` scheme

The `NpmSpec` class implements the full NPM specification (from https://github.com/npm/node-semver#ranges):

    >>> semver.Version("0.1.2") in semver.NpmSpec("0.1.0-alpha.2 .. 0.2.4")
    True
    >>> semver.Version('0.1.2') in semver.NpmSpec('>=0.1.1 <0.1.3 || 2.x')
    True
    >>> semver.Version('2.3.4') in semver.NpmSpec('>=0.1.1 <0.1.3 || 2.x')
    True

## Using with Django

The `semantic_version.django_fields` module provides django fields to store `Version` or `BaseSpec` objects.

More documentation is available in the Interaction with Django section.