1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
|
Guide
=====
.. currentmodule:: semantic_version
This module covers the 2.0.0 version of the SemVer scheme, with additional
extensions:
- Coercing any version string into a SemVer version, through
:meth:`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 :class:`Version` instances
"""""""""""""""""""""""""""""""""""
The core of the module is the :class:`Version` class; it is usually instantiated
from a version string:
.. code-block:: pycon
>>> import semantic_version as semver
>>> v = semver.Version("0.1.1")
The version's components are available through its attributes:
* :attr:`~Version.major`, :attr:`~Version.minor`, :attr:`~Version.patch` are
integers:
.. code-block:: pycon
>>> v.major
0
>>> v.minor
1
>>> v.patch
1
* The :attr:`~Version.prerelease` and :attr:`~Version.build` attributes are
iterables of text elements:
.. code-block:: pycon
>>> v2 = semver.Version("0.1.1-dev+23.git2")
>>> v2.prerelease
["dev"]
>>> v2.build
["23", "git2"]
One may also build a :class:`Version` from named components directly:
.. code-block:: pycon
>>> 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:
.. code-block:: pycon
>>> 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 :exc:`ValueError` will be raised:
.. code-block:: pycon
>>> 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:
.. code-block:: pycon
>>> 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:
.. code-block:: pycon
>>> 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:
.. code-block:: pycon
>>> 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 :meth:`Version.next_major`, :meth:`Version.next_minor` or
:meth:`Version.next_patch` functions:
.. code-block:: pycon
>>> 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 :attr:`~Version.build` or
:attr:`~Version.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 :meth:`Version.truncate` method,
removing components beyond the selected level:
.. code-block:: pycon
>>> 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:
- :class:`SimpleSpec` is a simple implementation, with reasonable expectations;
- :class:`NpmSpec` sticks to the NPM specification.
Further schemes can be built in a similar manner, relying on the :class:`BaseSpec`
class for basics.
Core API
""""""""
The core API is provided by the :class:`BaseSpec` class.
.. note::
These examples use :class:`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 :class:`Version` matches a
:class:`BaseSpec` through :meth:`~BaseSpec.match`:
.. code-block:: pycon
>>> 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:
.. code-block:: pycon
>>> 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 :meth:`~BaseSpec.filter`:
.. code-block:: pycon
>>> 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
:meth:`~BaseSpec.select`:
.. code-block:: pycon
>>> 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 :class:`SimpleSpec` scheme
""""""""""""""""""""""""""""""
The :class:`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``
.. rubric:: Special matching rules
When testing a :class:`Version` against a :class:`SimpleSpec`, comparisons are
adjusted for common user expectations; thus, a pre-release version (``1.0.0-alpha``)
will not satisfy the ``==1.0.0`` :class:`SimpleSpec`.
Pre-release identifiers will only be compared if included in the :class:`BaseSpec`
definition or (for the empty pre-release number) if a single dash is appended
(``1.0.0-``):
.. code-block:: pycon
>>> 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:
.. code-block:: pycon
>>> 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 :class:`SimpleSpec` class.
The :class:`NpmSpec` scheme
"""""""""""""""""""""""""""
The :class:`NpmSpec` class implements the full NPM specification (from
https://github.com/npm/node-semver#ranges):
.. code-block:: pycon
>>> 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 :mod:`semantic_version.django_fields` module provides django fields to
store :class:`Version` or :class:`BaseSpec` objects.
More documentation is available in the :doc:`django` section.
|