@@ -334,3 +334,75 @@ Getting Minimum and Maximum of two Versions
334
334
' 2.0.0'
335
335
>> > semver.min_ver(" 1.0.0" , " 2.0.0" )
336
336
' 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