Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit b5ccad6

Browse filesBrowse files
tomschrscls19fr
and
scls19fr
committed
Fix #210: how to deal with invalid versions (#215)
* Document how to deal with invalid versions * Use coerce(version) as an example * Update CHANGELOG.rst Co-authored-by: scls19fr <scls19fr@users.noreply.github.com>
1 parent 5755f9a commit b5ccad6
Copy full SHA for b5ccad6

File tree

Expand file treeCollapse file tree

2 files changed

+73
-0
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+73
-0
lines changed

‎CHANGELOG.rst

Copy file name to clipboardExpand all lines: CHANGELOG.rst
+1Lines changed: 1 addition & 0 deletions
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

‎docs/usage.rst

Copy file name to clipboardExpand all lines: docs/usage.rst
+72Lines changed: 72 additions & 0 deletions
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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.