Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/incremental/__init__.py: 36%
167 statements
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-07 06:38 +0000
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-07 06:38 +0000
1# Copyright (c) Twisted Matrix Laboratories.
2# See LICENSE for details.
4"""
5Versions for Python packages.
7See L{Version}.
8"""
10from __future__ import division, absolute_import
12import sys
13import warnings
14from typing import TYPE_CHECKING, Any, TypeVar, Union, Optional, Dict
16#
17# Compat functions
18#
20_T = TypeVar("_T", contravariant=True)
23if TYPE_CHECKING:
24 from typing_extensions import Literal
25 from distutils.dist import Distribution as _Distribution
28else:
29 _Distribution = object
31if sys.version_info > (3,):
33 def _cmp(a, b): # type: (Any, Any) -> int
34 """
35 Compare two objects.
37 Returns a negative number if C{a < b}, zero if they are equal, and a
38 positive number if C{a > b}.
39 """
40 if a < b:
41 return -1
42 elif a == b:
43 return 0
44 else:
45 return 1
48else:
49 _cmp = cmp # noqa: F821
52#
53# Versioning
54#
57class _Inf(object):
58 """
59 An object that is bigger than all other objects.
60 """
62 def __cmp__(self, other): # type: (object) -> int
63 """
64 @param other: Another object.
65 @type other: any
67 @return: 0 if other is inf, 1 otherwise.
68 @rtype: C{int}
69 """
70 if other is _inf:
71 return 0
72 return 1
74 if sys.version_info >= (3,):
76 def __lt__(self, other): # type: (object) -> bool
77 return self.__cmp__(other) < 0
79 def __le__(self, other): # type: (object) -> bool
80 return self.__cmp__(other) <= 0
82 def __gt__(self, other): # type: (object) -> bool
83 return self.__cmp__(other) > 0
85 def __ge__(self, other): # type: (object) -> bool
86 return self.__cmp__(other) >= 0
89_inf = _Inf()
92class IncomparableVersions(TypeError):
93 """
94 Two versions could not be compared.
95 """
98class Version(object):
99 """
100 An encapsulation of a version for a project, with support for outputting
101 PEP-440 compatible version strings.
103 This class supports the standard major.minor.micro[rcN] scheme of
104 versioning.
105 """
107 def __init__(
108 self,
109 package, # type: str
110 major, # type: Union[Literal["NEXT"], int]
111 minor, # type: int
112 micro, # type: int
113 release_candidate=None, # type: Optional[int]
114 prerelease=None, # type: Optional[int]
115 post=None, # type: Optional[int]
116 dev=None, # type: Optional[int]
117 ):
118 """
119 @param package: Name of the package that this is a version of.
120 @type package: C{str}
121 @param major: The major version number.
122 @type major: C{int} or C{str} (for the "NEXT" symbol)
123 @param minor: The minor version number.
124 @type minor: C{int}
125 @param micro: The micro version number.
126 @type micro: C{int}
127 @param release_candidate: The release candidate number.
128 @type release_candidate: C{int}
129 @param prerelease: The prerelease number. (Deprecated)
130 @type prerelease: C{int}
131 @param post: The postrelease number.
132 @type post: C{int}
133 @param dev: The development release number.
134 @type dev: C{int}
135 """
136 if release_candidate and prerelease:
137 raise ValueError("Please only return one of these.")
138 elif prerelease and not release_candidate:
139 release_candidate = prerelease
140 warnings.warn(
141 "Passing prerelease to incremental.Version was "
142 "deprecated in Incremental 16.9.0. Please pass "
143 "release_candidate instead.",
144 DeprecationWarning,
145 stacklevel=2,
146 )
148 if major == "NEXT":
149 if minor or micro or release_candidate or post or dev:
150 raise ValueError(
151 "When using NEXT, all other values except Package must be 0."
152 )
154 self.package = package
155 self.major = major
156 self.minor = minor
157 self.micro = micro
158 self.release_candidate = release_candidate
159 self.post = post
160 self.dev = dev
162 @property
163 def prerelease(self): # type: () -> Optional[int]
164 warnings.warn(
165 "Accessing incremental.Version.prerelease was "
166 "deprecated in Incremental 16.9.0. Use "
167 "Version.release_candidate instead.",
168 DeprecationWarning,
169 stacklevel=2,
170 ),
171 return self.release_candidate
173 def public(self): # type: () -> str
174 """
175 Return a PEP440-compatible "public" representation of this L{Version}.
177 Examples:
179 - 14.4.0
180 - 1.2.3rc1
181 - 14.2.1rc1dev9
182 - 16.04.0dev0
183 """
184 if self.major == "NEXT":
185 return self.major
187 if self.release_candidate is None:
188 rc = ""
189 else:
190 rc = ".rc%s" % (self.release_candidate,)
192 if self.post is None:
193 post = ""
194 else:
195 post = ".post%s" % (self.post,)
197 if self.dev is None:
198 dev = ""
199 else:
200 dev = ".dev%s" % (self.dev,)
202 return "%r.%d.%d%s%s%s" % (self.major, self.minor, self.micro, rc, post, dev)
204 base = public
205 short = public
206 local = public
208 def __repr__(self): # type: () -> str
210 if self.release_candidate is None:
211 release_candidate = ""
212 else:
213 release_candidate = ", release_candidate=%r" % (self.release_candidate,)
215 if self.post is None:
216 post = ""
217 else:
218 post = ", post=%r" % (self.post,)
220 if self.dev is None:
221 dev = ""
222 else:
223 dev = ", dev=%r" % (self.dev,)
225 return "%s(%r, %r, %d, %d%s%s%s)" % (
226 self.__class__.__name__,
227 self.package,
228 self.major,
229 self.minor,
230 self.micro,
231 release_candidate,
232 post,
233 dev,
234 )
236 def __str__(self): # type: () -> str
237 return "[%s, version %s]" % (self.package, self.short())
239 def __cmp__(self, other): # type: (Version) -> int
240 """
241 Compare two versions, considering major versions, minor versions, micro
242 versions, then release candidates, then postreleases, then dev
243 releases. Package names are case insensitive.
245 A version with a release candidate is always less than a version
246 without a release candidate. If both versions have release candidates,
247 they will be included in the comparison.
249 Likewise, a version with a dev release is always less than a version
250 without a dev release. If both versions have dev releases, they will
251 be included in the comparison.
253 @param other: Another version.
254 @type other: L{Version}
256 @return: NotImplemented when the other object is not a Version, or one
257 of -1, 0, or 1.
259 @raise IncomparableVersions: when the package names of the versions
260 differ.
261 """
262 if not isinstance(other, self.__class__):
263 return NotImplemented
264 if self.package.lower() != other.package.lower():
265 raise IncomparableVersions("%r != %r" % (self.package, other.package))
267 if self.major == "NEXT":
268 major = _inf # type: Union[int, _Inf]
269 else:
270 major = self.major
272 if self.release_candidate is None:
273 release_candidate = _inf # type: Union[int, _Inf]
274 else:
275 release_candidate = self.release_candidate
277 if self.post is None:
278 post = -1
279 else:
280 post = self.post
282 if self.dev is None:
283 dev = _inf # type: Union[int, _Inf]
284 else:
285 dev = self.dev
287 if other.major == "NEXT":
288 othermajor = _inf # type: Union[int, _Inf]
289 else:
290 othermajor = other.major
292 if other.release_candidate is None:
293 otherrc = _inf # type: Union[int, _Inf]
294 else:
295 otherrc = other.release_candidate
297 if other.post is None:
298 otherpost = -1
299 else:
300 otherpost = other.post
302 if other.dev is None:
303 otherdev = _inf # type: Union[int, _Inf]
304 else:
305 otherdev = other.dev
307 x = _cmp(
308 (major, self.minor, self.micro, release_candidate, post, dev),
309 (othermajor, other.minor, other.micro, otherrc, otherpost, otherdev),
310 )
311 return x
313 if sys.version_info >= (3,):
315 def __eq__(self, other): # type: (Any) -> bool
316 c = self.__cmp__(other)
317 if c is NotImplemented:
318 return c # type: ignore[return-value]
319 return c == 0
321 def __ne__(self, other): # type: (Any) -> bool
322 c = self.__cmp__(other)
323 if c is NotImplemented:
324 return c # type: ignore[return-value]
325 return c != 0
327 def __lt__(self, other): # type: (Version) -> bool
328 c = self.__cmp__(other)
329 if c is NotImplemented:
330 return c # type: ignore[return-value]
331 return c < 0
333 def __le__(self, other): # type: (Version) -> bool
334 c = self.__cmp__(other)
335 if c is NotImplemented:
336 return c # type: ignore[return-value]
337 return c <= 0
339 def __gt__(self, other): # type: (Version) -> bool
340 c = self.__cmp__(other)
341 if c is NotImplemented:
342 return c # type: ignore[return-value]
343 return c > 0
345 def __ge__(self, other): # type: (Version) -> bool
346 c = self.__cmp__(other)
347 if c is NotImplemented:
348 return c # type: ignore[return-value]
349 return c >= 0
352def getVersionString(version): # type: (Version) -> str
353 """
354 Get a friendly string for the given version object.
356 @param version: A L{Version} object.
357 @return: A string containing the package and short version number.
358 """
359 result = "%s %s" % (version.package, version.short())
360 return result
363def _get_version(dist, keyword, value): # type: (_Distribution, object, object) -> None
364 """
365 Get the version from the package listed in the Distribution.
366 """
367 if not value:
368 return
370 from distutils.command import build_py
372 sp_command = build_py.build_py(dist)
373 sp_command.finalize_options()
375 for item in sp_command.find_all_modules(): # type: ignore[attr-defined]
376 if item[1] == "_version":
377 version_file = {} # type: Dict[str, Version]
379 with open(item[2]) as f:
380 exec(f.read(), version_file)
382 dist.metadata.version = version_file["__version__"].public()
383 return None
385 raise Exception("No _version.py found.")
388from ._version import __version__ # noqa: E402
391def _setuptools_version(): # type: () -> str
392 return __version__.public()
395__all__ = ["__version__", "Version", "getVersionString"]