Skip to content

Commit 09ef970

Browse files
tomschrppktscls19fr
committed
Fix #225: Deprecate module level functions
* Add test cases - Add additional test case for "check" - test_should_process_check_iscalled_with_valid_version - Test also missing finalize_version - Test the warning more thouroughly with pytest.warns instead of just pytest.deprecated_call * In `setup.cfg`, add deprecation warnings filter for pytest * Implement DeprecationWarning with warnings module and the new decorator `deprecated` * Output a DeprecationWarning for the following functions: - semver.bump_{major,minor,patch,prerelease,build} - semver.format_version - semver.finalize_version - semver.parse - semver.parse_version_info - semver.replace - semver.VersionInfo._asdict - semver.VersionInfo._astuple Add also a deprecation notice in the docstrings of these functions * Introduce new public functions: - semver.VersionInfo.to_dict (from former _asdict) - semver.VersionInfo.to_tuple (from former _astuple) - Keep _asdict and _astuple as a (deprecated) function for compatibility reasons * Update CHANGELOG.rst * Update usage documentation: - Move some information to make them more useful for for the reader - Add deprecation warning - Explain how to replace deprecated functions - Explain how to display deprecation warnings from semver * Improve documentation of deprecated functions - List deprecated module level functions - Make recommendation and show equivalent code - Mention that deprecated functions will be replaced in semver 3. That means, all deprecated function will be still available in semver 2.x.y. * Move _increment_string into VersionInfo class - Makes removing deprecating functions easier as, for example, bump_prerelease is no longer dependant from an "external" function. - Move _LAST_NUMBER regex into VersionInfo class - Implement _increment_string as a staticmethod Co-authored-by: Karol <karol@ppkt.eu> Co-authored-by: scls19fr <scls19fr@users.noreply.github.com>
1 parent 34f038d commit 09ef970

File tree

6 files changed

+549
-190
lines changed

6 files changed

+549
-190
lines changed

.gitignore

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
# Files
1+
# Patch/Diff Files
22
*.patch
33
*.diff
4-
*.kate-swp
54

65
# Byte-compiled / optimized / DLL files
76
__pycache__/
87
*.py[cod]
98
.pytest_cache/
9+
*$py.class
1010

1111
# Distribution / packaging
1212
.cache
@@ -72,3 +72,7 @@ docs/_build/
7272

7373
# PyBuilder
7474
target/
75+
76+
# Backup files
77+
*~
78+
*.kate-swp

CHANGELOG.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,24 @@ Additions
2727

2828
* :pr:`228`: Added better doctest integration
2929

30+
3031
Removals
3132
--------
33+
* :gh:`225` (:pr:`229`): Output a DeprecationWarning for the following functions:
34+
35+
- ``semver.parse``
36+
- ``semver.parse_version_info``
37+
- ``semver.format_version``
38+
- ``semver.bump_{major,minor,patch,prerelease,build}``
39+
- ``semver.finalize_version``
40+
- ``semver.replace``
41+
- ``semver.VersionInfo._asdict`` (use the new, public available
42+
function ``semver.VersionInfo.to_dict()``)
43+
- ``semver.VersionInfo._astuple`` (use the new, public available
44+
function ``semver.VersionInfo.to_tuple()``)
45+
46+
These deprecated functions will be removed in semver 3.
47+
3248

3349

3450
Version 2.9.1

docs/usage.rst

Lines changed: 205 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ are met.
1414
Knowing the Implemented semver.org Version
1515
------------------------------------------
1616

17-
The semver.org is the authorative specification of how semantical versioning is
18-
definied. To know which version of semver.org is implemented in the semver
19-
libary, use the following constant::
17+
The semver.org page is the authorative specification of how semantical
18+
versioning is definied.
19+
To know which version of semver.org is implemented in the semver libary,
20+
use the following constant::
2021

2122
>>> semver.SEMVER_SPEC_VERSION
2223
'2.0.0'
@@ -25,35 +26,81 @@ libary, use the following constant::
2526
Creating a Version
2627
------------------
2728

28-
A version can be created in different ways:
29+
Due to historical reasons, the semver project offers two ways of
30+
creating a version:
2931

30-
* as a complete version string::
32+
* through an object oriented approach with the :class:`semver.VersionInfo`
33+
class. This is the preferred method when using semver.
34+
35+
* through module level functions and builtin datatypes (usually strings
36+
and dicts).
37+
These method are still available for compatibility reasons, but are
38+
marked as deprecated. Using one of these will emit a DeprecationWarning.
39+
40+
41+
.. warning:: **Deprecation Warning**
42+
43+
Module level functions are marked as *deprecated* in version 2.9.2 now.
44+
These functions will be removed in semver 3.
45+
For details, see the sections :ref:`sec_replace_deprecated_functions` and
46+
:ref:`sec_display_deprecation_warnings`.
47+
48+
49+
A :class:`semver.VersionInfo` instance can be created in different ways:
50+
51+
52+
* From a string::
3153

32-
>>> semver.parse_version_info("3.4.5-pre.2+build.4")
33-
VersionInfo(major=3, minor=4, patch=5, prerelease='pre.2', build='build.4')
3454
>>> semver.VersionInfo.parse("3.4.5-pre.2+build.4")
3555
VersionInfo(major=3, minor=4, patch=5, prerelease='pre.2', build='build.4')
3656

37-
* with individual parts::
57+
* From individual parts by a dictionary::
3858

39-
>>> semver.format_version(3, 4, 5, 'pre.2', 'build.4')
40-
'3.4.5-pre.2+build.4'
41-
>>> semver.VersionInfo(3, 5)
42-
VersionInfo(major=3, minor=5, patch=0, prerelease=None, build=None)
59+
>>> d = {'major': 3, 'minor': 4, 'patch': 5, 'prerelease': 'pre.2', 'build': 'build.4'}
60+
>>> semver.VersionInfo(**d)
61+
VersionInfo(major=3, minor=4, patch=5, prerelease='pre.2', build='build.4')
62+
63+
As a minimum requirement, your dictionary needs at least the ``major``
64+
key, others can be omitted. You get a ``TypeError`` if your
65+
dictionary contains invalid keys.
66+
Only the keys ``major``, ``minor``, ``patch``, ``prerelease``, and ``build``
67+
are allowed.
68+
69+
* From a tuple::
70+
71+
>>> t = (3, 5, 6)
72+
>>> semver.VersionInfo(*t)
73+
VersionInfo(major=3, minor=5, patch=6, prerelease=None, build=None)
4374

4475
You can pass either an integer or a string for ``major``, ``minor``, or
4576
``patch``::
4677

47-
>>> semver.VersionInfo("3", "5")
48-
VersionInfo(major=3, minor=5, patch=0, prerelease=None, build=None)
78+
>>> semver.VersionInfo("3", "5", 6)
79+
VersionInfo(major=3, minor=5, patch=6, prerelease=None, build=None)
80+
81+
The old, deprecated module level functions are still available. If you
82+
need them, they return different builtin objects (string and dictionary).
83+
Keep in mind, once you have converted a version into a string or dictionary,
84+
it's an ordinary builtin object. It's not a special version object like
85+
the :class:`semver.VersionInfo` class anymore.
86+
87+
Depending on your use case, the following methods are available:
88+
89+
* From individual version parts into a string
90+
91+
In some cases you only need a string from your version data::
92+
93+
>>> semver.format_version(3, 4, 5, 'pre.2', 'build.4')
94+
'3.4.5-pre.2+build.4'
95+
96+
* From a string into a dictionary
4997

50-
In the simplest form, ``prerelease`` and ``build`` can also be
51-
integers::
98+
To access individual parts, you can use the function :func:`semver.parse`::
5299

53-
>>> semver.VersionInfo(1, 2, 3, 4, 5)
54-
VersionInfo(major=1, minor=2, patch=3, prerelease='4', build='5')
100+
>>> semver.parse("3.4.5-pre.2+build.4")
101+
OrderedDict([('major', 3), ('minor', 4), ('patch', 5), ('prerelease', 'pre.2'), ('build', 'build.4')])
55102

56-
If you pass an invalid version string you will get a ``ValueError``::
103+
If you pass an invalid version string you will get a ``ValueError``::
57104

58105
>>> semver.parse("1.2")
59106
Traceback (most recent call last):
@@ -172,45 +219,30 @@ If you pass invalid keys you get an exception::
172219

173220
.. _sec.convert.versions:
174221

175-
Converting Different Version Types
176-
----------------------------------
222+
Converting a VersionInfo instance into Different Types
223+
------------------------------------------------------
177224

178-
Depending which function you call, you get different types
179-
(as explained in the beginning of this chapter).
225+
Sometimes it is needed to convert a :class:`semver.VersionInfo` instance into
226+
a different type. For example, for displaying or to access all parts.
180227

181-
* From a string into :class:`semver.VersionInfo`::
182-
183-
>>> semver.VersionInfo.parse("3.4.5-pre.2+build.4")
184-
VersionInfo(major=3, minor=4, patch=5, prerelease='pre.2', build='build.4')
228+
It is possible to convert a :class:`semver.VersionInfo` instance:
185229

186-
* From :class:`semver.VersionInfo` into a string::
230+
* Into a string with the builtin function :func:`str`::
187231

188232
>>> str(semver.VersionInfo.parse("3.4.5-pre.2+build.4"))
189233
'3.4.5-pre.2+build.4'
190234

191-
* From a dictionary into :class:`semver.VersionInfo`::
235+
* Into a dictionary with :func:`semver.VersionInfo.to_dict`::
192236

193-
>>> d = {'major': 3, 'minor': 4, 'patch': 5, 'prerelease': 'pre.2', 'build': 'build.4'}
194-
>>> semver.VersionInfo(**d)
195-
VersionInfo(major=3, minor=4, patch=5, prerelease='pre.2', build='build.4')
196-
197-
As a minimum requirement, your dictionary needs at least the ``major``
198-
key, others can be omitted. You get a ``TypeError`` if your
199-
dictionary contains invalid keys.
200-
Only ``major``, ``minor``, ``patch``, ``prerelease``, and ``build``
201-
are allowed.
202-
203-
* From a tuple into :class:`semver.VersionInfo`::
204-
205-
>>> t = (3, 5, 6)
206-
>>> semver.VersionInfo(*t)
207-
VersionInfo(major=3, minor=5, patch=6, prerelease=None, build=None)
237+
>>> v = semver.VersionInfo(major=3, minor=4, patch=5)
238+
>>> v.to_dict()
239+
OrderedDict([('major', 3), ('minor', 4), ('patch', 5), ('prerelease', None), ('build', None)])
208240

209-
* From a :class:`semver.VersionInfo` into a dictionary::
241+
* Into a tuple with :func:`semver.VersionInfo.to_tuple`::
210242

211-
>>> v = semver.VersionInfo(major=3, minor=4, patch=5)
212-
>>> semver.parse(str(v)) == {'major': 3, 'minor': 4, 'patch': 5, 'prerelease': None, 'build': None}
213-
True
243+
>>> v = semver.VersionInfo(major=5, minor=4, patch=2)
244+
>>> v.to_tuple()
245+
(5, 4, 2, None, None)
214246

215247

216248
Increasing Parts of a Version
@@ -362,8 +394,132 @@ For example:
362394

363395
.. code-block:: python
364396
365-
>>> coerce("v1.2")
397+
>>> coerce("v1.2")
366398
(VersionInfo(major=1, minor=2, patch=0, prerelease=None, build=None), '')
367399
>>> coerce("v2.5.2-bla")
368400
(VersionInfo(major=2, minor=5, patch=2, prerelease=None, build=None), '-bla')
369401
402+
403+
.. _sec_replace_deprecated_functions:
404+
405+
Replacing Deprecated Functions
406+
------------------------------
407+
408+
The development team of semver has decided to deprecate certain functions on
409+
the module level. The preferred way of using semver is through the
410+
:class:`semver.VersionInfo` class.
411+
412+
The deprecated functions can still be used in version 2.x.y. In version 3 of
413+
semver, the deprecated functions will be removed.
414+
415+
The following list shows the deprecated functions and how you can replace
416+
them with code which is compatible for future versions:
417+
418+
419+
* :func:`semver.bump_major`, :func:`semver.bump_minor`, :func:`semver.bump_patch`, :func:`semver.bump_prerelease`, :func:`semver.bump_build`
420+
421+
Replace them with the respective methods of the :class:`semver.VersionInfo`
422+
class.
423+
For example, the function :func:`semver.bump_major` is replaced by
424+
:func:`semver.VersionInfo.bump_major` and calling the ``str(versionobject)``:
425+
426+
.. code-block:: python
427+
428+
>>> s1 = semver.bump_major("3.4.5")
429+
>>> s2 = str(semver.VersionInfo.parse("3.4.5").bump_major())
430+
>>> s1 == s2
431+
True
432+
433+
Likewise with the other module level functions.
434+
435+
* :func:`semver.finalize_version`
436+
437+
Replace it with :func:`semver.VersionInfo.finalize_version`:
438+
439+
.. code-block:: python
440+
441+
>>> s1 = semver.finalize_version('1.2.3-rc.5')
442+
>>> s2 = str(semver.VersionInfo.parse('1.2.3-rc.5').finalize_version())
443+
>>> s1 == s2
444+
True
445+
446+
* :func:`semver.format_version`
447+
448+
Replace it with ``str(versionobject)``:
449+
450+
.. code-block:: python
451+
452+
>>> s1 = semver.format_version(5, 4, 3, 'pre.2', 'build.1')
453+
>>> s2 = str(semver.VersionInfo(5, 4, 3, 'pre.2', 'build.1'))
454+
>>> s1 == s2
455+
True
456+
457+
* :func:`semver.parse`
458+
459+
Replace it with :func:`semver.VersionInfo.parse` and
460+
:func:`semver.VersionInfo.to_dict`:
461+
462+
.. code-block:: python
463+
464+
>>> v1 = semver.parse("1.2.3")
465+
>>> v2 = semver.VersionInfo.parse("1.2.3").to_dict()
466+
>>> v1 == v2
467+
True
468+
469+
* :func:`semver.parse_version_info`
470+
471+
Replace it with :func:`semver.VersionInfo.parse`:
472+
473+
.. code-block:: python
474+
475+
>>> v1 = semver.parse_version_info("3.4.5")
476+
>>> v2 = semver.VersionInfo.parse("3.4.5")
477+
>>> v1 == v2
478+
True
479+
480+
* :func:`semver.replace`
481+
482+
Replace it with :func:`semver.VersionInfo.replace`:
483+
484+
.. code-block:: python
485+
486+
>>> s1 = semver.replace("1.2.3", major=2, patch=10)
487+
>>> s2 = str(semver.VersionInfo.parse('1.2.3').replace(major=2, patch=10))
488+
>>> s1 == s2
489+
True
490+
491+
492+
.. _sec_display_deprecation_warnings:
493+
494+
Displaying Deprecation Warnings
495+
-------------------------------
496+
497+
By default, deprecation warnings are `ignored in Python <https://docs.python.org/3/library/warnings.html#warning-categories>`_.
498+
This also affects semver's own warnings.
499+
500+
It is recommended that you turn on deprecation warnings in your scripts. Use one of
501+
the following methods:
502+
503+
* Use the option `-Wd <https://docs.python.org/3/using/cmdline.html#cmdoption-w>`_
504+
to enable default warnings:
505+
506+
* Directly running the Python command::
507+
508+
$ python3 -Wd scriptname.py
509+
510+
* Add the option in the shebang line (something like ``#!/usr/bin/python3``)
511+
after the command::
512+
513+
#!/usr/bin/python3 -Wd
514+
515+
* In your own scripts add a filter to ensure that *all* warnings are displayed:
516+
517+
.. code-block:: python
518+
519+
import warnings
520+
warnings.simplefilter("default")
521+
# Call your semver code
522+
523+
For further details, see the section
524+
`Overriding the default filter <https://docs.python.org/3/library/warnings.html#overriding-the-default-filter>`_
525+
of the Python documentation.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy