diff options
-rw-r--r-- | README.rst | 205 | ||||
-rw-r--r-- | docs/django.rst | 2 | ||||
-rw-r--r-- | docs/guide.rst | 346 | ||||
-rw-r--r--[l---------] | docs/index.rst | 31 | ||||
l--------- | docs/introduction.rst | 1 | ||||
-rw-r--r-- | docs/reference.rst | 34 |
6 files changed, 467 insertions, 152 deletions
@@ -1,5 +1,5 @@ -python-semanticversion -====================== +Introduction +============ This small python library provides a few tools to handle `SemVer`_ in Python. It follows strictly the 2.0.0 version of the SemVer scheme. @@ -57,20 +57,18 @@ Import it in your code: import semantic_version -.. currentmodule:: semantic_version - This module provides classes to handle semantic versions: -- :class:`Version` represents a version number (``0.1.1-alpha+build.2012-05-15``) -- :class:`BaseSpec`-derived classes represent requirement specifications (``>=0.1.1,<0.3.0``): +- ``Version`` represents a version number (``0.1.1-alpha+build.2012-05-15``) +- ``BaseSpec``-derived classes represent requirement specifications (``>=0.1.1,<0.3.0``): - - :class:`SimpleSpec` describes a natural description syntax - - :class:`NpmSpec` is used for NPM-style range descriptions. + - ``SimpleSpec`` describes a natural description syntax + - ``NpmSpec`` is used for NPM-style range descriptions. Versions -------- -Defining a :class:`Version` is quite simple: +Defining a ``Version`` is quite simple: .. code-block:: pycon @@ -90,7 +88,7 @@ Defining a :class:`Version` is quite simple: >>> list(v) [0, 1, 1, [], []] -If the provided version string is invalid, a :exc:`ValueError` will be raised: +If the provided version string is invalid, a ``ValueError`` will be raised: .. code-block:: pycon @@ -104,7 +102,39 @@ If the provided version string is invalid, a :exc:`ValueError` will be raised: ValueError: Invalid version string: '0.1' -Obviously, :class:`Versions <Version>` can be compared: +One may also create a ``Version`` with named components: + +.. 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') + + +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 + + >>> Version.coerce('0') + Version('0.0.0') + >>> Version.coerce('0.1.2.3.4') + Version('0.1.2+3.4') + >>> Version.coerce('0.1.2a3') + Version('0.1.2-a3') + +Working with versions +""""""""""""""""""""" + +Obviously, versions can be compared: .. code-block:: pycon @@ -133,38 +163,31 @@ You can also get a new version that represents a bump in one of the version leve >>> str(new_v) '1.1.2' -It is also possible to check whether a given string is a proper semantic version string: - - -.. code-block:: pycon - - >>> semantic_version.validate('0.1.3') - True - >>> semantic_version.validate('0a2') - False -Finally, one may create a :class:`Version` with named components instead: - -.. 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: +Requirement specification +------------------------- -.. code-block:: pycon +python-semanticversion provides a couple of ways to describe a range of accepted +versions: - >>> semantic_version.Version(major=0, minor=1, patch=2, prerelease=('alpha', '2')) - Version('0.1.2-alpha.2') +- The ``SimpleSpec`` class provides a simple, easily understood scheme -- + somewhat inspired from PyPI range notations; +- The ``NpmSpec`` class supports the whole NPM range specification scheme: + .. code-block:: pycon -Requirement specification -------------------------- + >>> Version('0.1.2') in NpmSpec('0.1.0-alpha.2 .. 0.2.4') + True + >>> Version('0.1.2') in NpmSpec('>=0.1.1 <0.1.3 || 2.x') + True + >>> Version('2.3.4') in NpmSpec('>=0.1.1 <0.1.3 || 2.x') + True -The :class:`SimpleSpec` object describes a range of accepted versions: +The ``SimpleSpec`` scheme +""""""""""""""""""""""""" +Basic usage is simply a comparator and a base version: .. code-block:: pycon @@ -176,6 +199,12 @@ The :class:`SimpleSpec` object describes a range of accepted versions: >>> s.match(Version('0.1.0')) False +Combining specifications can be expressed as follows: + + .. code-block:: pycon + + >>> SimpleSpec('>=0.1.1,<0.3.0') + Simpler test syntax is also available using the ``in`` keyword: .. code-block:: pycon @@ -189,17 +218,16 @@ Simpler test syntax is also available using the ``in`` keyword: False -Combining specifications can be expressed as follows: - - .. code-block:: pycon +Refer to the full documentation at +https://python-semanticversion.readthedocs.io/en/latest/ for more details on the +``SimpleSpec`` scheme. - >>> SimpleSpec('>=0.1.1,<0.3.0') Using a specification """"""""""""""""""""" -The :func:`SimpleSpec.filter` method filters an iterable of :class:`Version`: +The ``SimpleSpec.filter`` method filters an iterable of ``Version``: .. code-block:: pycon @@ -222,82 +250,6 @@ It is also possible to select the 'best' version from such iterables: Version('0.3.0') -Coercing an arbitrary version string -"""""""""""""""""""""""""""""""""""" - -Some user-supplied input might not match the semantic version scheme. -For such cases, the :meth:`Version.coerce` method will try to convert any -version-like string into a valid semver version: - -.. code-block:: pycon - - >>> Version.coerce('0') - Version('0.0.0') - >>> Version.coerce('0.1.2.3.4') - Version('0.1.2+3.4') - >>> Version.coerce('0.1.2a3') - Version('0.1.2-a3') - - -Including pre-release identifiers in specifications -""""""""""""""""""""""""""""""""""""""""""""""""""" - -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 - - -Including build metadata in specifications -"""""""""""""""""""""""""""""""""""""""""" - -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 - - -NPM-based ranges ----------------- - -The :class:`NpmSpec` class handles NPM-style ranges: - -.. code-block:: pycon - - >>> Version('1.2.3') in NpmSpec('1.2.2 - 1.4') - True - >>> Version('1.2.3') in NpmSpec('<1.x || >=1.2.3') - True - -Refer to https://docs.npmjs.com/misc/semver.html for a detailed description of NPM -range syntax. - - -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. - Contributing ============ @@ -323,26 +275,5 @@ When submitting patches or pull requests, you should respect the following rules # -*- encoding: utf-8 -*- # Copyright (c) The python-semanticversion project - -Contents -======== - -.. toctree:: - :maxdepth: 2 - - reference - django - changelog - credits - - .. _SemVer: http://semver.org/ .. _PyPI: http://pypi.python.org/ - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - diff --git a/docs/django.rst b/docs/django.rst index 34a0fe3..befa50a 100644 --- a/docs/django.rst +++ b/docs/django.rst @@ -37,4 +37,4 @@ with their :attr:`~django.db.models.CharField.max_length` defaulting to 200. The syntax to use for the field; defaults to ``'simple'``. - .. versionaddedd:: 2.7 + .. versionadded:: 2.7 diff --git a/docs/guide.rst b/docs/guide.rst new file mode 100644 index 0000000..7780a32 --- /dev/null +++ b/docs/guide.rst @@ -0,0 +1,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://docs.npmjs.com/misc/semver.html): + +.. 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. diff --git a/docs/index.rst b/docs/index.rst index 89a0106..135ee68 120000..100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1 +1,30 @@ -../README.rst
\ No newline at end of file +====================== +python-semanticversion +====================== + +.. include:: introduction.rst + + +Contents +======== + +.. toctree:: + :maxdepth: 2 + + introduction + guide + reference + django + changelog + credits + + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/docs/introduction.rst b/docs/introduction.rst new file mode 120000 index 0000000..89a0106 --- /dev/null +++ b/docs/introduction.rst @@ -0,0 +1 @@ +../README.rst
\ No newline at end of file diff --git a/docs/reference.rst b/docs/reference.rst index 951bd9a..93a29eb 100644 --- a/docs/reference.rst +++ b/docs/reference.rst @@ -66,6 +66,7 @@ Representing a version (the Version class) ------------------------------------------ .. class:: Version(version_string[, partial=False]) + :noindex: Object representation of a `SemVer`_-compliant version. @@ -90,15 +91,6 @@ Representing a version (the Version class) .. rubric:: Attributes - .. attribute:: partial - - ``bool``, whether this is a 'partial' or a complete version number. - Partial version number may lack :attr:`minor` or :attr:`patch` version numbers. - - .. deprecated:: 2.7 - The ability to define a partial version will be removed in version 3.0. - Use :class:`SimpleSpec` instead: ``SimpleSpec('1.x.x')``. - .. attribute:: major ``int``, the major version number @@ -140,6 +132,15 @@ Representing a version (the Version class) Note that the :attr:`~Version.build` isn't included in the precedence_key computatin. + .. attribute:: partial + + ``bool``, whether this is a 'partial' or a complete version number. + Partial version number may lack :attr:`minor` or :attr:`patch` version numbers. + + .. deprecated:: 2.7 + The ability to define a partial version will be removed in version 3.0. + Use :class:`SimpleSpec` instead: ``SimpleSpec('1.x.x')``. + .. rubric:: Methods @@ -173,7 +174,7 @@ Representing a version (the Version class) >>> Version('1.1.0-alpha').next_minor() Version('1.1.0') - .. method:: next_patch(self): + .. method:: next_patch(self) Return the next patch version, i.e the smallest version strictly greater than the current one with empty :attr:`prerelease` and :attr:`build`. @@ -231,6 +232,7 @@ Representing a version (the Version class) - For non-:attr:`partial` versions, compare using the `SemVer`_ scheme - If any compared object is :attr:`partial`: + - Begin comparison using the `SemVer`_ scheme - If a component (:attr:`minor`, :attr:`patch`, :attr:`prerelease` or :attr:`build`) was absent from the :attr:`partial` :class:`Version` -- represented with :obj:`None` @@ -472,7 +474,7 @@ Each of those ``Spec`` classes provides a shared set of methods to work with ver * A clause of ``>0.1.2-rc.3`` will match versions strictly above ``0.1.2-rc.3``, including matching prereleases of ``0.1.2``: ``0.1.2-rc.10`` is included; * A clause of ``>=XXX`` will match versions that match ``>XXX`` or ``==XXX`` - ..rubric:: Wildcards + .. rubric:: Wildcards * A clause of ``==0.1.*`` is equivalent to ``>=0.1.0,<0.2.0`` * A clause of ``>=0.1.*`` is equivalent to ``>=0.1.0`` @@ -554,7 +556,7 @@ Each of those ``Spec`` classes provides a shared set of methods to work with ver <SpecItem: != Version('1.1.13', partial=True)>, )> - Its keeps a list of :class:`SpecItem` objects, based on the initial expression + It keeps a list of :class:`SpecItem` objects, based on the initial expression components. .. method:: __iter__(self) @@ -705,7 +707,13 @@ Each of those ``Spec`` classes provides a shared set of methods to work with ver >>> Version('1.0.1') in Spec('!=1.0.1') False - The kind of 'Almost equal to' specifications + .. data:: KIND_COMPATIBLE + + The kind of `compatible release clauses`_ + specifications:: + + >>> Version('1.1.2') in Spec('~=1.1.0') + True |