Skip to content

Commit b5ccad6

Browse files
tomschrscls19fr
and
scls19fr
committed
Fix python-semver#210: how to deal with invalid versions (python-semver#215)
* Document how to deal with invalid versions * Use coerce(version) as an example * Update CHANGELOG.rst Co-authored-by: scls19fr <[email protected]>
1 parent 5755f9a commit b5ccad6

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

Diff for: CHANGELOG.rst

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Features
2222
* :gh:`201` (:pr:`202`): Reformatted source code with black
2323
* :gh:`208` (:pr:`209`): Introduce new function :func:`semver.VersionInfo.isvalid`
2424
and extend :command:`pysemver` with :command:`check` subcommand
25+
* :gh:`210` (:pr:`215`): Document how to deal with invalid versions
2526
* :pr:`212`: Improve docstrings according to PEP257
2627

2728
Bug Fixes

Diff for: docs/usage.rst

+72
Original file line numberDiff line numberDiff line change
@@ -334,3 +334,75 @@ Getting Minimum and Maximum of two Versions
334334
'2.0.0'
335335
>>> semver.min_ver("1.0.0", "2.0.0")
336336
'1.0.0'
337+
338+
339+
Dealing with Invalid Versions
340+
-----------------------------
341+
342+
As semver follows the semver specification, it cannot parse version
343+
strings which are considered "invalid" by that specification. The semver
344+
library cannot know all the possible variations so you need to help the
345+
library a bit.
346+
347+
For example, if you have a version string ``v1.2`` would be an invalid
348+
semver version.
349+
However, "basic" version strings consisting of major, minor,
350+
and patch part, can be easy to convert. The following function extract this
351+
information and returns a tuple with two items:
352+
353+
.. code-block:: python
354+
355+
import re
356+
357+
BASEVERSION = re.compile(
358+
r"""[vV]?
359+
(?P<major>0|[1-9]\d*)
360+
(\.
361+
(?P<minor>0|[1-9]\d*)
362+
(\.
363+
(?P<patch>0|[1-9]\d*)
364+
)?
365+
)?
366+
""",
367+
re.VERBOSE,
368+
)
369+
def coerce(version):
370+
"""
371+
Convert an incomplete version string into a semver-compatible VersionInfo
372+
object
373+
374+
* Tries to detect a "basic" version string (``major.minor.patch``).
375+
* If not enough components can be found, missing components are
376+
set to zero to obtain a valid semver version.
377+
378+
:param str version: the version string to convert
379+
:return: a tuple with a :class:`VersionInfo` instance (or ``None``
380+
if it's not a version) and the rest of the string which doesn't
381+
belong to a basic version.
382+
:rtype: tuple(:class:`VersionInfo` | None, str)
383+
"""
384+
match = BASEVERSION.search(version)
385+
if not match:
386+
return (None, version)
387+
388+
ver = {
389+
key: 0 if value is None else value
390+
for key, value in match.groupdict().items()
391+
}
392+
ver = semver.VersionInfo(**ver)
393+
rest = match.string[match.end() :]
394+
return ver, rest
395+
396+
The function returns a *tuple*, containing a :class:`VersionInfo`
397+
instance or None as the first element and the rest as the second element.
398+
The second element (the rest) can be used to make further adjustments.
399+
400+
For example:
401+
402+
.. code-block:: python
403+
404+
>>> coerce("v1.2")
405+
(VersionInfo(major=1, minor=2, patch=0, prerelease=None, build=None), '')
406+
>>> coerce("v2.5.2-bla")
407+
(VersionInfo(major=2, minor=5, patch=2, prerelease=None, build=None), '-bla')
408+

0 commit comments

Comments
 (0)