summaryrefslogtreecommitdiff
path: root/README.rst
blob: c50163a4cd2dfc86309129896da9cd2a7676fed0 (plain)
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
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.

.. image:: https://github.com/rbarrois/python-semanticversion/actions/workflows/test.yml/badge.svg
    :target: https://github.com/rbarrois/python-semanticversion/actions/workflows/test.yml

.. image:: https://img.shields.io/pypi/v/semantic_version.svg
    :target: https://python-semanticversion.readthedocs.io/en/latest/changelog.html
    :alt: Latest Version

.. image:: https://img.shields.io/pypi/pyversions/semantic_version.svg
    :target: https://pypi.python.org/pypi/semantic_version/
    :alt: Supported Python versions

.. image:: https://img.shields.io/pypi/wheel/semantic_version.svg
    :target: https://pypi.python.org/pypi/semantic_version/
    :alt: Wheel status

.. image:: https://img.shields.io/pypi/l/semantic_version.svg
    :target: https://pypi.python.org/pypi/semantic_version/
    :alt: License

Links
-----

- Package on `PyPI`_: https://pypi.org/project/semantic-version/
- Doc on `ReadTheDocs <http://readthedocs.org/>`_: https://python-semanticversion.readthedocs.io/
- Source on `GitHub <http://github.com/>`_: http://github.com/rbarrois/python-semanticversion/
- Build on Github Actions: https://github.com/rbarrois/python-semanticversion/actions
- Semantic Version specification: `SemVer`_


Getting started
===============

Install the package from `PyPI`_, using pip:

.. code-block:: sh

    pip install semantic-version

Or from GitHub:

.. code-block:: sh

    $ git clone git://github.com/rbarrois/python-semanticversion.git


Import it in your code:


.. code-block:: python

    import semantic_version


This module provides classes to handle semantic versions:

- ``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``):

  - ``SimpleSpec`` describes a natural description syntax
  - ``NpmSpec`` is used for NPM-style range descriptions.

Versions
--------

Defining a ``Version`` is quite simple:


.. code-block:: pycon

    >>> import semantic_version
    >>> v = semantic_version.Version('0.1.1')
    >>> v.major
    0
    >>> v.minor
    1
    >>> v.patch
    1
    >>> v.prerelease
    []
    >>> v.build
    []
    >>> list(v)
    [0, 1, 1, [], []]

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

.. code-block:: pycon

    >>> semantic_version.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'


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

    >>> semantic_version.Version('0.1.1') < semantic_version.Version('0.1.2')
    True
    >>> semantic_version.Version('0.1.1') > semantic_version.Version('0.1.1-alpha')
    True
    >>> semantic_version.Version('0.1.1') <= semantic_version.Version('0.1.1-alpha')
    False

You can also get a new version that represents a bump in one of the version levels:

.. code-block:: pycon

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



Requirement specification
-------------------------

python-semanticversion provides a couple of ways to describe a range of accepted
versions:

- 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

      >>> 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 ``SimpleSpec`` scheme
"""""""""""""""""""""""""

Basic usage is simply a comparator and a base version:

.. code-block:: pycon

    >>> s = SimpleSpec('>=0.1.1')  # At least 0.1.1
    >>> s.match(Version('0.1.1'))
    True
    >>> s.match(Version('0.1.1-alpha1'))  # pre-release doesn't satisfy version spec
    False
    >>> 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

    >>> s = SimpleSpec('==0.1.1')
    >>> Version('0.1.1+git7ccc72') in s  # build variants are equivalent to full versions
    True
    >>> Version('0.1.1-alpha1') in s     # pre-release variants don't match the full version.
    False
    >>> Version('0.1.2') in s
    False


Refer to the full documentation at
https://python-semanticversion.readthedocs.io/en/latest/ for more details on the
``SimpleSpec`` scheme.



Using a specification
"""""""""""""""""""""

The ``SimpleSpec.filter`` method filters an iterable of ``Version``:

.. code-block:: pycon

    >>> s = SimpleSpec('>=0.1.0,<0.4.0')
    >>> versions = (Version('0.%d.0' % i) for i in range(6))
    >>> for v in s.filter(versions):
    ...     print v
    0.1.0
    0.2.0
    0.3.0

It is also possible to select the 'best' version from such iterables:


.. code-block:: pycon

    >>> s = SimpleSpec('>=0.1.0,<0.4.0')
    >>> versions = (Version('0.%d.0' % i) for i in range(6))
    >>> s.select(versions)
    Version('0.3.0')



Contributing
============

In order to contribute to the source code:

- Open an issue on `GitHub`_: https://github.com/rbarrois/python-semanticversion/issues
- Fork the `repository <https://github.com/rbarrois/python-semanticversion>`_
  and submit a pull request on `GitHub`_
- Or send me a patch (mailto:raphael.barrois+semver@polytechnique.org)

When submitting patches or pull requests, you should respect the following rules:

- Coding conventions are based on :pep:`8`
- The whole test suite must pass after adding the changes
- The test coverage for a new feature must be 100%
- New features and methods should be documented in the ``reference`` section
  and included in the ``changelog``
- Include your name in the ``contributors`` section

.. note:: All files should contain the following header::

          # -*- encoding: utf-8 -*-
          # Copyright (c) The python-semanticversion project

.. _SemVer: http://semver.org/
.. _PyPI: http://pypi.python.org/