Skip to content

Commit 73f3c1f

Browse files
committed
Move module level implementation into VersionInfo
Move implementations: * semver.format_version -> semver.VersionInfo.format_version * Move _REGEX into VersionInfo class * semver.parse -> semver.VersionInfo.parse * semver.bump_* -> semver.VersionInfo.bump_* Change implementation by calling VersionInfo methods: * semver.compare * semver.finalize_version * semver.replace * semver.parse_version_info
1 parent 34f038d commit 73f3c1f

File tree

1 file changed

+104
-82
lines changed

1 file changed

+104
-82
lines changed

semver.py

Lines changed: 104 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,6 @@
1414
__maintainer__ = ["Sebastien Celles", "Tom Schraitle"]
1515
__maintainer_email__ = "s.celles@gmail.com"
1616

17-
_REGEX = re.compile(
18-
r"""
19-
^
20-
(?P<major>0|[1-9]\d*)
21-
\.
22-
(?P<minor>0|[1-9]\d*)
23-
\.
24-
(?P<patch>0|[1-9]\d*)
25-
(?:-(?P<prerelease>
26-
(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)
27-
(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*
28-
))?
29-
(?:\+(?P<build>
30-
[0-9a-zA-Z-]+
31-
(?:\.[0-9a-zA-Z-]+)*
32-
))?
33-
$
34-
""",
35-
re.VERBOSE,
36-
)
3717

3818
_LAST_NUMBER = re.compile(r"(?:[^\d]*(\d+)[^\d]*)+")
3919

@@ -69,17 +49,7 @@ def parse(version):
6949
>>> ver['build']
7050
'build.4'
7151
"""
72-
match = _REGEX.match(version)
73-
if match is None:
74-
raise ValueError("%s is not valid SemVer string" % version)
75-
76-
version_parts = match.groupdict()
77-
78-
version_parts["major"] = int(version_parts["major"])
79-
version_parts["minor"] = int(version_parts["minor"])
80-
version_parts["patch"] = int(version_parts["patch"])
81-
82-
return version_parts
52+
return VersionInfo.parse(version)._asdict()
8353

8454

8555
def comparator(operator):
@@ -110,6 +80,26 @@ class VersionInfo(object):
11080
"""
11181

11282
__slots__ = ("_major", "_minor", "_patch", "_prerelease", "_build")
83+
_REGEX = re.compile(
84+
r"""
85+
^
86+
(?P<major>0|[1-9]\d*)
87+
\.
88+
(?P<minor>0|[1-9]\d*)
89+
\.
90+
(?P<patch>0|[1-9]\d*)
91+
(?:-(?P<prerelease>
92+
(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)
93+
(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*
94+
))?
95+
(?:\+(?P<build>
96+
[0-9a-zA-Z-]+
97+
(?:\.[0-9a-zA-Z-]+)*
98+
))?
99+
$
100+
""",
101+
re.VERBOSE,
102+
)
113103

114104
def __init__(self, major, minor=0, patch=0, prerelease=None, build=None):
115105
self._major = int(major)
@@ -195,7 +185,8 @@ def bump_major(self):
195185
>>> ver.bump_major()
196186
VersionInfo(major=4, minor=0, patch=0, prerelease=None, build=None)
197187
"""
198-
return parse_version_info(bump_major(str(self)))
188+
cls = type(self)
189+
return cls(self._major+1)
199190

200191
def bump_minor(self):
201192
"""
@@ -209,7 +200,8 @@ def bump_minor(self):
209200
>>> ver.bump_minor()
210201
VersionInfo(major=3, minor=5, patch=0, prerelease=None, build=None)
211202
"""
212-
return parse_version_info(bump_minor(str(self)))
203+
cls = type(self)
204+
return cls(self._major, self._minor+1)
213205

214206
def bump_patch(self):
215207
"""
@@ -223,7 +215,8 @@ def bump_patch(self):
223215
>>> ver.bump_patch()
224216
VersionInfo(major=3, minor=4, patch=6, prerelease=None, build=None)
225217
"""
226-
return parse_version_info(bump_patch(str(self)))
218+
cls = type(self)
219+
return cls(self._major, self._minor, self._patch+1)
227220

228221
def bump_prerelease(self, token="rc"):
229222
"""
@@ -239,7 +232,11 @@ def bump_prerelease(self, token="rc"):
239232
VersionInfo(major=3, minor=4, patch=5, prerelease='rc.2', \
240233
build=None)
241234
"""
242-
return parse_version_info(bump_prerelease(str(self), token))
235+
cls = type(self)
236+
prerelease = _increment_string(
237+
self._prerelease or (token or "rc") + ".0"
238+
)
239+
return cls(self._major, self._minor, self._patch, prerelease)
243240

244241
def bump_build(self, token="build"):
245242
"""
@@ -255,7 +252,11 @@ def bump_build(self, token="build"):
255252
VersionInfo(major=3, minor=4, patch=5, prerelease='rc.1', \
256253
build='build.10')
257254
"""
258-
return parse_version_info(bump_build(str(self), token))
255+
cls = type(self)
256+
build = _increment_string(
257+
self._build or (token or "build") + ".0"
258+
)
259+
return cls(self._major, self._minor, self._patch, self._prerelease, build)
259260

260261
@comparator
261262
def __eq__(self, other):
@@ -286,7 +287,7 @@ def __repr__(self):
286287
return "%s(%s)" % (type(self).__name__, s)
287288

288289
def __str__(self):
289-
return format_version(*(self._astuple()))
290+
return VersionInfo.format_version(*(self._astuple()))
290291

291292
def __hash__(self):
292293
return hash(self._astuple())
@@ -304,7 +305,17 @@ def parse(version):
304305
VersionInfo(major=3, minor=4, patch=5, \
305306
prerelease='pre.2', build='build.4')
306307
"""
307-
return parse_version_info(version)
308+
match = VersionInfo._REGEX.match(version)
309+
if match is None:
310+
raise ValueError("%s is not valid SemVer string" % version)
311+
312+
version_parts = match.groupdict()
313+
314+
version_parts["major"] = int(version_parts["major"])
315+
version_parts["minor"] = int(version_parts["minor"])
316+
version_parts["patch"] = int(version_parts["patch"])
317+
318+
return VersionInfo(**version_parts)
308319

309320
def replace(self, **parts):
310321
"""
@@ -350,6 +361,31 @@ def isvalid(cls, version):
350361
except ValueError:
351362
return False
352363

364+
@staticmethod
365+
def format_version(major, minor, patch, prerelease=None, build=None):
366+
"""
367+
Format a version according to the Semantic Versioning specification.
368+
369+
:param int major: the required major part of a version
370+
:param int minor: the required minor part of a version
371+
:param int patch: the required patch part of a version
372+
:param str prerelease: the optional prerelease part of a version
373+
:param str build: the optional build part of a version
374+
:return: the formatted string
375+
:rtype: str
376+
377+
>>> semver.VersionInfo.format_version(3, 4, 5, 'pre.2', 'build.4')
378+
'3.4.5-pre.2+build.4'
379+
"""
380+
version = "%d.%d.%d" % (major, minor, patch)
381+
if prerelease is not None:
382+
version = version + "-%s" % prerelease
383+
384+
if build is not None:
385+
version = version + "+%s" % build
386+
387+
return version
388+
353389

354390
def _to_dict(obj):
355391
if isinstance(obj, VersionInfo):
@@ -382,16 +418,7 @@ def parse_version_info(version):
382418
>>> version_info.build
383419
'build.4'
384420
"""
385-
parts = parse(version)
386-
version_info = VersionInfo(
387-
parts["major"],
388-
parts["minor"],
389-
parts["patch"],
390-
parts["prerelease"],
391-
parts["build"],
392-
)
393-
394-
return version_info
421+
return VersionInfo.parse(version)
395422

396423

397424
def _nat_cmp(a, b):
@@ -458,7 +485,8 @@ def compare(ver1, ver2):
458485
0
459486
"""
460487

461-
v1, v2 = parse(ver1), parse(ver2)
488+
v1 = VersionInfo.parse(ver1)._asdict()
489+
v2 = VersionInfo.parse(ver2)._asdict()
462490

463491
return _compare_by_keys(v1, v2)
464492

@@ -565,14 +593,7 @@ def format_version(major, minor, patch, prerelease=None, build=None):
565593
>>> semver.format_version(3, 4, 5, 'pre.2', 'build.4')
566594
'3.4.5-pre.2+build.4'
567595
"""
568-
version = "%d.%d.%d" % (major, minor, patch)
569-
if prerelease is not None:
570-
version = version + "-%s" % prerelease
571-
572-
if build is not None:
573-
version = version + "+%s" % build
574-
575-
return version
596+
return VersionInfo.format_version(major, minor, patch, prerelease, build)
576597

577598

578599
def _increment_string(string):
@@ -600,8 +621,7 @@ def bump_major(version):
600621
>>> semver.bump_major("3.4.5")
601622
'4.0.0'
602623
"""
603-
verinfo = parse(version)
604-
return format_version(verinfo["major"] + 1, 0, 0)
624+
return str(VersionInfo.parse(version).bump_major())
605625

606626

607627
def bump_minor(version):
@@ -615,8 +635,7 @@ def bump_minor(version):
615635
>>> semver.bump_minor("3.4.5")
616636
'3.5.0'
617637
"""
618-
verinfo = parse(version)
619-
return format_version(verinfo["major"], verinfo["minor"] + 1, 0)
638+
return str(VersionInfo.parse(version).bump_minor())
620639

621640

622641
def bump_patch(version):
@@ -630,8 +649,7 @@ def bump_patch(version):
630649
>>> semver.bump_patch("3.4.5")
631650
'3.4.6'
632651
"""
633-
verinfo = parse(version)
634-
return format_version(verinfo["major"], verinfo["minor"], verinfo["patch"] + 1)
652+
return str(VersionInfo.parse(version).bump_patch())
635653

636654

637655
def bump_prerelease(version, token="rc"):
@@ -646,13 +664,7 @@ def bump_prerelease(version, token="rc"):
646664
>>> semver.bump_prerelease('3.4.5', 'dev')
647665
'3.4.5-dev.1'
648666
"""
649-
verinfo = parse(version)
650-
verinfo["prerelease"] = _increment_string(
651-
verinfo["prerelease"] or (token or "rc") + ".0"
652-
)
653-
return format_version(
654-
verinfo["major"], verinfo["minor"], verinfo["patch"], verinfo["prerelease"]
655-
)
667+
return str(VersionInfo.parse(version).bump_prerelease(token))
656668

657669

658670
def bump_build(version, token="build"):
@@ -667,15 +679,7 @@ def bump_build(version, token="build"):
667679
>>> semver.bump_build('3.4.5-rc.1+build.9')
668680
'3.4.5-rc.1+build.10'
669681
"""
670-
verinfo = parse(version)
671-
verinfo["build"] = _increment_string(verinfo["build"] or (token or "build") + ".0")
672-
return format_version(
673-
verinfo["major"],
674-
verinfo["minor"],
675-
verinfo["patch"],
676-
verinfo["prerelease"],
677-
verinfo["build"],
678-
)
682+
return str(VersionInfo.parse(version).bump_build(token))
679683

680684

681685
def finalize_version(version):
@@ -692,8 +696,26 @@ def finalize_version(version):
692696
>>> semver.finalize_version('1.2.3-rc.5')
693697
'1.2.3'
694698
"""
695-
verinfo = parse(version)
696-
return format_version(verinfo["major"], verinfo["minor"], verinfo["patch"])
699+
verinfo = VersionInfo.parse(version)
700+
return VersionInfo.format_version(verinfo.major, verinfo.minor, verinfo.patch)
701+
702+
703+
def replace(version, **parts):
704+
"""
705+
Replace one or more parts of a version and return the new string.
706+
707+
:param str version: the version string to replace
708+
:param dict parts: the parts to be updated. Valid keys are:
709+
``major``, ``minor``, ``patch``, ``prerelease``, or ``build``
710+
:return: the replaced version string
711+
:raises: TypeError, if ``parts`` contains invalid keys
712+
:rtype: str
713+
714+
>>> import semver
715+
>>> semver.replace("1.2.3", major=2, patch=10)
716+
'2.2.10'
717+
"""
718+
return str(VersionInfo.parse(version).replace(**parts))
697719

698720

699721
def cmd_bump(args):
@@ -719,7 +741,7 @@ def cmd_bump(args):
719741
# print the help and exit
720742
args.parser.parse_args(["bump", "-h"])
721743

722-
ver = parse_version_info(args.version)
744+
ver = VersionInfo.parse(args.version)
723745
# get the respective method and call it
724746
func = getattr(ver, maptable[args.bump])
725747
return str(func())

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