@@ -73,8 +73,30 @@ class Version(object):
7373 version_re = re .compile (r'^(\d+)\.(\d+)\.(\d+)(?:-([0-9a-zA-Z.-]+))?(?:\+([0-9a-zA-Z.-]+))?$' )
7474 partial_version_re = re .compile (r'^(\d+)(?:\.(\d+)(?:\.(\d+))?)?(?:-([0-9a-zA-Z.-]*))?(?:\+([0-9a-zA-Z.-]*))?$' )
7575
76- def __init__ (self , version_string , partial = False ):
77- major , minor , patch , prerelease , build = self .parse (version_string , partial )
76+ def __init__ (
77+ self ,
78+ version_string = None ,
79+ * ,
80+ major = None ,
81+ minor = None ,
82+ patch = None ,
83+ prerelease = None ,
84+ build = None ,
85+ partial = False ,
86+ ):
87+ has_text = version_string is not None
88+ has_parts = not (major is minor is patch is prerelease is build is None )
89+ if not has_text ^ has_parts :
90+ raise ValueError ("Call either Version('1.2.3') or Version(major=1, ...)." )
91+
92+ if has_text :
93+ major , minor , patch , prerelease , build = self .parse (version_string , partial )
94+ else :
95+ # Convenience: allow to omit prerelease/build.
96+ if not partial :
97+ prerelease = prerelease or ()
98+ build = build or ()
99+ self ._validate_kwargs (major , minor , patch , prerelease , build , partial )
78100
79101 self .major = major
80102 self .minor = minor
@@ -254,6 +276,25 @@ def _validate_identifiers(cls, identifiers, allow_leading_zeroes=False):
254276 if item [0 ] == '0' and item .isdigit () and item != '0' and not allow_leading_zeroes :
255277 raise ValueError ("Invalid leading zero in identifier %r" % item )
256278
279+ @classmethod
280+ def _validate_kwargs (cls , major , minor , patch , prerelease , build , partial ):
281+ if (
282+ major != int (major )
283+ or minor != cls ._coerce (minor , partial )
284+ or patch != cls ._coerce (patch , partial )
285+ or prerelease is None and not partial
286+ or build is None and not partial
287+ ):
288+ raise ValueError (
289+ "Invalid kwargs to Version(major=%r, minor=%r, patch=%r, "
290+ "prerelease=%r, build=%r, partial=%r" % (
291+ major , minor , patch , prerelease , build , partial
292+ ))
293+ if prerelease is not None :
294+ cls ._validate_identifiers (prerelease , allow_leading_zeroes = False )
295+ if build is not None :
296+ cls ._validate_identifiers (build , allow_leading_zeroes = True )
297+
257298 def __iter__ (self ):
258299 return iter ((self .major , self .minor , self .patch , self .prerelease , self .build ))
259300
0 commit comments