From d43ddbf1aeaef4b31ca3f3026e05b58280014c75 Mon Sep 17 00:00:00 2001 From: Thomas Schraitle Date: Mon, 30 Sep 2019 09:34:45 +0200 Subject: [PATCH 1/5] Change titles to using verb instead of noun --- docs/development.rst | 4 ++-- docs/install.rst | 4 ++-- docs/usage.rst | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/development.rst b/docs/development.rst index 000b2f65..43442618 100644 --- a/docs/development.rst +++ b/docs/development.rst @@ -1,5 +1,5 @@ -How to Contribute ------------------ +Contributing to semver +====================== When you make changes to the code please run the tests before pushing your code to your fork and opening a `pull request`_: diff --git a/docs/install.rst b/docs/install.rst index 26f4e1c0..1abb7ed7 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -1,5 +1,5 @@ -Installation ------------- +Installing semver +================= For Python 2: diff --git a/docs/usage.rst b/docs/usage.rst index c30ffefb..3f9eae11 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -1,5 +1,5 @@ -Usage ------ +Using semver +============ This module provides just couple of functions, main of which are: From a56fff854fd0be437cbd2749574bc85b4de65421 Mon Sep 17 00:00:00 2001 From: Thomas Schraitle Date: Mon, 30 Sep 2019 09:36:09 +0200 Subject: [PATCH 2/5] Adding version information in docs/conf.py Currently, the version of semver is imported (using from semver import __version__). To avoid importing semver, version string could be managed through bumpversion2. However, this is out of scope for this PR. --- docs/conf.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 1afd8e7f..9b85583a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -20,6 +20,7 @@ import sys sys.path.insert(0, os.path.abspath('..')) +from semver import __version__ # -- General configuration ------------------------------------------------ @@ -57,9 +58,9 @@ # built documents. # # The short X.Y version. -version = '' +version = __version__ # The full version, including alpha/beta/rc tags. -release = '' +release = version # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. From 4d15b25d35a5d5f00166f890c23996a2028deee4 Mon Sep 17 00:00:00 2001 From: Thomas Schraitle Date: Mon, 30 Sep 2019 09:44:52 +0200 Subject: [PATCH 3/5] Improve entry page * Improve main title with semver's version and a catchy phrase * Move the |latest-version| placeholder to the other placeholders like build status, downloads etc. * Remove the "Welcome bla" heading as it introduces a lonly section and it is mostly useless * Add a short explanation about the "version style" major.minor.patch (cited from semver.org) * Reference the other parts with just the filename (with the .rst extension) and without the title. The title is automatically retrieved from the file, no need to repeat it. This makes the overall doc more consistent. * Change py.test -> pytest --- docs/development.rst | 4 ++-- docs/index.rst | 33 ++++++++++++++++++++------------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/docs/development.rst b/docs/development.rst index 43442618..05542d29 100644 --- a/docs/development.rst +++ b/docs/development.rst @@ -8,7 +8,7 @@ code to your fork and opening a `pull request`_: python setup.py test -We use `py.test`_ and `tox`_ to run tests against all supported Python +We use `pytest`_ and `tox`_ to run tests against all supported Python versions. All test dependencies are resolved automatically, apart from virtualenv, which for the moment you still may have to install manually: @@ -24,5 +24,5 @@ You can use the ``clean`` command to remove build and test files and folders: .. _pull request: https://github.com/k-bx/python-semver/pulls -.. _py.test: http://pytest.org/ +.. _pytest: http://pytest.org/ .. _tox: http://tox.testrun.org/ diff --git a/docs/index.rst b/docs/index.rst index 84136292..1c15abab 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,26 +1,33 @@ -Semver |latest-version| -======================= +Semver |version| -- Semantic Versioning +======================================= -|build-status| |python-support| |downloads| |license| +|build-status| |latest-version| |python-support| |downloads| |license| .. python-semver documentation master file, created by sphinx-quickstart on Tue May 1 16:51:19 2018. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Welcome to python-semver's documentation! -========================================= +A Python module for `semantic versioning`_. Simplifies comparing versions. + +The module follows the ``MAJOR.MINOR.PATCH`` style: + +* ``MAJOR`` version when you make incompatible API changes, +* ``MINOR`` version when you add functionality in a backwards compatible manner, and +* ``PATCH`` version when you make backwards compatible bug fixes. + +Additional labels for pre-release and build metadata are supported. + + .. toctree:: :maxdepth: 2 - :caption: Contents: + :caption: Contents - Install - Usage - Development - API - -A Python module for `semantic versioning`_. Simplifies comparing versions. + install + usage + development + api .. |latest-version| image:: https://img.shields.io/pypi/v/semver.svg @@ -41,7 +48,7 @@ A Python module for `semantic versioning`_. Simplifies comparing versions. .. _semantic versioning: http://semver.org/ -Indices and tables +Indices and Tables ================== * :ref:`genindex` From 7c43e63a8175672d7b4b8453c70c69aa0f96fe79 Mon Sep 17 00:00:00 2001 From: Thomas Schraitle Date: Mon, 30 Sep 2019 14:42:52 +0200 Subject: [PATCH 4/5] Fix #142: Improve usage documentation * Use descriptive titles (verb+ing) to better find the topic * Structure the content with (sub)sections * Try to structure the different sections with list if there are different options to make it more readable * Document other, possible unknown features --- docs/usage.rst | 278 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 252 insertions(+), 26 deletions(-) diff --git a/docs/usage.rst b/docs/usage.rst index 3f9eae11..795cb3ae 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -1,46 +1,272 @@ Using semver ============ -This module provides just couple of functions, main of which are: +The ``semver`` module can store a version in different types: + +* as a string. +* as :class:`semver.VersionInfo`, a dedicated class for a version type. +* as a dictionary. + +Each type can be converted into the other, if the minimum requirements +are met. + + +Creating a Version +------------------ + +A version can be created in different ways: + +* as a complete version string:: + + >>> semver.parse_version_info("3.4.5-pre.2+build.4") + VersionInfo(major=3, minor=4, patch=5, prerelease='pre.2', build='build.4') + >>> semver.VersionInfo.parse("3.4.5-pre.2+build.4") + VersionInfo(major=3, minor=4, patch=5, prerelease='pre.2', build='build.4') + +* with individual parts:: + + >>> semver.format_version(3, 4, 5, 'pre.2', 'build.4') + '3.4.5-pre.2+build.4' + >>> semver.VersionInfo(3, 5) + VersionInfo(major=3, minor=5, patch=0, prerelease=None, build=None) + + You can pass either an integer or a string for ``major``, ``minor``, or + ``patch``:: + + >>> semver.VersionInfo("3", "5") + VersionInfo(major=3, minor=5, patch=0, prerelease=None, build=None) + + In the simplest form, ``prerelease`` and ``build`` can also be + integers:: + + >>> semver.VersionInfo(1, 2, 3, 4, 5) + VersionInfo(major=1, minor=2, patch=3, prerelease=4, build=5) + + +Parsing a Version String +------------------------ + +"Parsing" in this context means to identify the different parts in a string. + + +* With :func:`semver.parse_version_info`:: + + >>> semver.parse_version_info("3.4.5-pre.2+build.4") + VersionInfo(major=3, minor=4, patch=5, prerelease='pre.2', build='build.4') + +* With :func:`semver.VersionInfo.parse` (basically the same as + :func:`semver.parse_version_info`):: + + >>> semver.VersionInfo.parse("3.4.5-pre.2+build.4") + VersionInfo(major=3, minor=4, patch=5, prerelease='pre.2', build='build.4') + +* With :func:`semver.parse`:: + + >>> semver.parse("3.4.5-pre.2+build.4") + {'major': 3, 'minor': 4, 'patch': 5, 'prerelease': 'pre.2', 'build': 'build.4'} + + +Accessing Parts of a Version +---------------------------- + +The :class:`semver.VersionInfo` contains attributes to access the different +parts of a version: .. code-block:: python - >>> import semver + >>> v = VersionInfo.parse("3.4.5-pre.2+build.4") + >>> v.major + 3 + >>> v.minor + 4 + >>> v.patch + 5 + >>> v.prerelease + 'pre.2' + >>> v.build + 'build.4' + +However, the attributes are read-only. You cannot change an attribute. +If you do, you get an ``AttributeError``:: + + >>> v.minor = 5 + Traceback (most recent call last) + ... + AttributeError: attribute 'minor' is readonly + +In case you need the different parts of a version stepwise, iterate over the :class:`semver.VersionInfo` instance:: + + >>> for item in VersionInfo.parse("3.4.5-pre.2+build.4"): + ... print(item) + 3 + 4 + 5 + pre.2 + build.4 + >>> list(VersionInfo.parse("3.4.5-pre.2+build.4")) + [3, 4, 5, 'pre.2', 'build.4'] + + +.. _sec.convert.versions: + +Converting Different Version Types +---------------------------------- + +Depending which function you call, you get different types +(as explained in the beginning of this chapter). + +* From a string into :class:`semver.VersionInfo`:: + + >>> semver.VersionInfo.parse("3.4.5-pre.2+build.4") + VersionInfo(major=3, minor=4, patch=5, prerelease='pre.2', build='build.4') + +* From :class:`semver.VersionInfo` into a string:: + + >>> str(semver.VersionInfo.parse("3.4.5-pre.2+build.4")) + '3.4.5-pre.2+build.4' + +* From a dictionary into :class:`semver.VersionInfo`:: + + >>> d = {'major': 3, 'minor': 4, 'patch': 5, 'prerelease': 'pre.2', 'build': 'build.4'} + >>> semver.VersionInfo(**d) + VersionInfo(major=3, minor=4, patch=5, prerelease='pre.2', build='build.4') + + As a minimum requirement, your dictionary needs at least the ``major`` + key, others can be omitted. You get a ``TypeError`` if your + dictionary contains invalid keys. + Only ``major``, ``minor``, ``patch``, ``prerelease``, and ``build`` + are allowed. + +* From a tuple into :class:`semver.VersionInfo`:: + + >>> t = (3, 5, 6) + >>> semver.VersionInfo(*t) + VersionInfo(major=3, minor=5, patch=6, prerelease=None, build=None) + +* From a :class:`semver.VersionInfo` into a dictionary:: + + >>> v = semver.VersionInfo(major=3, minor=4, patch=5) + >>> semver.parse(str(v)) + {'major': 3, 'minor': 4, 'patch': 5, 'prerelease': None, 'build': None} + + +Increasing Parts of a Version +----------------------------- + +The ``semver`` module contains the following functions to raise parts of +a version: + +* :func:`semver.bump_major`: raises the major part and set all other parts to + zero. Set ``prerelease`` and ``build`` to ``None``. +* :func:`semver.bump_minor`: raises the minor part and sets ``patch`` to zero. + Set ``prerelease`` and ``build`` to ``None``. +* :func:`semver.bump_patch`: raises the patch part. Set ``prerelease`` and + ``build`` to ``None``. +* :func:`semver.bump_prerelease`: raises the prerelease part and set + ``build`` to ``None``. +* :func:`semver.bump_build`: raises the build part. + +.. code-block:: python + + >>> semver.bump_major("3.4.5-pre.2+build.4") + '4.0.0' + >>> semver.bump_minor("3.4.5-pre.2+build.4") + '3.5.0' + >>> semver.bump_patch("3.4.5-pre.2+build.4") + '3.4.6' + >>> semver.bump_prerelease("3.4.5-pre.2+build.4") + '3.4.5-pre.3' + >>> semver.bump_build("3.4.5-pre.2+build.4") + '3.4.5-pre.2+build.5' + + +Comparing Versions +------------------ + +To compare two versions depends on your type: + +* **Two strings** + + Use :func:`semver.compare`:: + >>> semver.compare("1.0.0", "2.0.0") -1 >>> semver.compare("2.0.0", "1.0.0") 1 >>> semver.compare("2.0.0", "2.0.0") 0 - >>> semver.match("2.0.0", ">=1.0.0") + + The return value is negative if ``version1 < version2``, zero if + ``version1 == version2`` and strictly positive if ``version1 > version2``. + +* **Two** :class:`semver.VersionInfo` **types** + + Use the specific operator. Currently, the operators ``<``, + ``<=``, ``>``, ``>=``, ``==``, and ``!=`` are supported:: + + >>> v1 = VersionInfo.parse("3.4.5") + >>> v2 = VersionInfo.parse("3.5.1") + >>> v1 < v2 True - >>> semver.match("1.0.0", ">1.0.0") + >>> v1 > v2 False - >>> semver.format_version(3, 4, 5, 'pre.2', 'build.4') - '3.4.5-pre.2+build.4' - >>> version_parts = semver.parse("3.4.5-pre.2+build.4") - >>> version_parts == { - ... 'major': 3, 'minor': 4, 'patch': 5, - ... 'prerelease': 'pre.2', 'build': 'build.4'} + +* **A** :class:`semver.VersionInfo` **type and a** ``tuple`` + + Use the operator as with two :class:`semver.VersionInfo` types:: + + >>> v = VersionInfo.parse("3.4.5") + >>> v > (1, 0) True - >>> version_info = semver.parse_version_info("3.4.5-pre.2+build.4") - >>> # or using static method parse - >>> from semver import VersionInfo - >>> version_info = VersionInfo.parse("3.4.5-pre.2+build.4") - >>> version_info - VersionInfo(major=3, minor=4, patch=5, prerelease='pre.2', build='build.4') - >>> version_info.major - 3 - >>> version_info > (1, 0) + >>> v < (3, 5) True - >>> version_info < (3, 5) + + The opposite does also work:: + + >>> (1, 0) < v True - >>> semver.bump_major("3.4.5") - '4.0.0' - >>> semver.bump_minor("3.4.5") - '3.5.0' - >>> semver.bump_patch("3.4.5") - '3.4.6' + >>> (3, 5) > v + True + +Other types cannot be compared (like dictionaries, lists etc). + +If you need to convert some types into other, refer to :ref:`sec.convert.versions`. + + + +Comparing Versions through an Expression +--------------------------------------- + +If you need a more fine-grained approach of comparing two versions, +use the :func:`semver.match` function. It expects two arguments: + +1. a version string +2. a match expression + +Currently, the match expression supports the following operators: + +* ``<`` smaller than +* ``>`` greater than +* ``>=`` greater or equal than +* ``<=`` smaller or equal than +* ``==`` equal +* ``!=`` not equal + +That gives you the following possibilities to express your condition: + +.. code-block:: python + + >>> semver.match("2.0.0", ">=1.0.0") + True + >>> semver.match("1.0.0", ">1.0.0") + False + + +Getting Minimum and Maximum of two Versions +------------------------------------------- + +.. code-block:: python + >>> semver.max_ver("1.0.0", "2.0.0") '2.0.0' >>> semver.min_ver("1.0.0", "2.0.0") From bcd451c9a8927d91b3f37b435a13b2f745dc2ed3 Mon Sep 17 00:00:00 2001 From: Thomas Schraitle Date: Mon, 30 Sep 2019 21:12:30 +0200 Subject: [PATCH 5/5] Silence flake8 with "noqa: E402" --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 9b85583a..786d444e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -20,7 +20,7 @@ import sys sys.path.insert(0, os.path.abspath('..')) -from semver import __version__ +from semver import __version__ # noqa: E402 # -- General configuration ------------------------------------------------