Coverage for src / bioimageio / spec / _internal / version_type.py: 93%
61 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-23 10:51 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-23 10:51 +0000
1from __future__ import annotations
3from typing import Any, Optional, Tuple, Union
5import packaging.version
6from pydantic import PrivateAttr, RootModel
9class Version(RootModel[Union[str, int, float]]):
10 """wraps a packaging.version.Version instance for validation in pydantic models"""
12 _version: packaging.version.Version = PrivateAttr()
14 def __str__(self):
15 return str(self._version)
17 def model_post_init(self, __context: Any) -> None:
18 """set `_version` attribute @private"""
19 self._version = packaging.version.Version(str(self.root))
20 return super().model_post_init(__context)
22 def __lt__(self, other: Any):
23 if not isinstance(other, Version):
24 return NotImplemented
26 return self._version < other._version
28 def __eq__(self, other: Any):
29 if not isinstance(other, Version):
30 return NotImplemented
31 return self._version == other._version
33 # the properties below are adopted from and mirror properties of packaging.version.Version
34 @property
35 def epoch(self) -> int:
36 """The epoch of the version.
38 >>> Version("2.0.0").epoch
39 0
40 >>> Version("1!2.0.0").epoch
41 1
42 """
43 return self._version.epoch
45 @property
46 def release(self) -> Tuple[int, ...]:
47 """The components of the "release" segment of the version.
49 >>> Version("1.2.3").release
50 (1, 2, 3)
51 >>> Version("2.0.0").release
52 (2, 0, 0)
53 >>> Version("1!2.0.0.post0").release
54 (2, 0, 0)
56 Includes trailing zeroes but not the epoch or any pre-release / development /
57 post-release suffixes.
58 """
59 return self._version.release
61 @property
62 def pre(self) -> Optional[Tuple[str, int]]:
63 """The pre-release segment of the version.
65 >>> print(Version("1.2.3").pre)
66 None
67 >>> Version("1.2.3a1").pre
68 ('a', 1)
69 >>> Version("1.2.3b1").pre
70 ('b', 1)
71 >>> Version("1.2.3rc1").pre
72 ('rc', 1)
73 """
74 return self._version.pre
76 @property
77 def post(self) -> Optional[int]:
78 """The post-release number of the version.
80 >>> print(Version("1.2.3").post)
81 None
82 >>> Version("1.2.3.post1").post
83 1
84 """
85 return self._version.post
87 @property
88 def dev(self) -> Optional[int]:
89 """The development number of the version.
91 >>> print(Version("1.2.3").dev)
92 None
93 >>> Version("1.2.3.dev1").dev
94 1
95 """
96 return self._version.dev
98 @property
99 def local(self) -> Optional[str]:
100 """The local version segment of the version.
102 >>> print(Version("1.2.3").local)
103 None
104 >>> Version("1.2.3+abc").local
105 'abc'
106 """
107 return self._version.local
109 @property
110 def public(self) -> str:
111 """The public portion of the version.
113 >>> Version("1.2.3").public
114 '1.2.3'
115 >>> Version("1.2.3+abc").public
116 '1.2.3'
117 >>> Version("1.2.3+abc.dev1").public
118 '1.2.3'
119 """
120 return self._version.public
122 @property
123 def base_version(self) -> str:
124 """The "base version" of the version.
126 >>> Version("1.2.3").base_version
127 '1.2.3'
128 >>> Version("1.2.3+abc").base_version
129 '1.2.3'
130 >>> Version("1!1.2.3+abc.dev1").base_version
131 '1!1.2.3'
133 The "base version" is the public version of the project without any pre or post
134 release markers.
135 """
136 return self._version.base_version
138 @property
139 def is_prerelease(self) -> bool:
140 """Whether this version is a pre-release.
142 >>> Version("1.2.3").is_prerelease
143 False
144 >>> Version("1.2.3a1").is_prerelease
145 True
146 >>> Version("1.2.3b1").is_prerelease
147 True
148 >>> Version("1.2.3rc1").is_prerelease
149 True
150 >>> Version("1.2.3dev1").is_prerelease
151 True
152 """
153 return self._version.is_prerelease
155 @property
156 def is_postrelease(self) -> bool:
157 """Whether this version is a post-release.
159 >>> Version("1.2.3").is_postrelease
160 False
161 >>> Version("1.2.3.post1").is_postrelease
162 True
163 """
164 return self._version.is_postrelease
166 @property
167 def is_devrelease(self) -> bool:
168 """Whether this version is a development release.
170 >>> Version("1.2.3").is_devrelease
171 False
172 >>> Version("1.2.3.dev1").is_devrelease
173 True
174 """
175 return self._version.is_devrelease
177 @property
178 def major(self) -> int:
179 """The first item of :attr:`release` or ``0`` if unavailable.
181 >>> Version("1.2.3").major
182 1
183 """
184 return self._version.major
186 @property
187 def minor(self) -> int:
188 """The second item of :attr:`release` or ``0`` if unavailable.
190 >>> Version("1.2.3").minor
191 2
192 >>> Version("1").minor
193 0
194 """
195 return self._version.minor
197 @property
198 def micro(self) -> int:
199 """The third item of :attr:`release` or ``0`` if unavailable.
201 >>> Version("1.2.3").micro
202 3
203 >>> Version("1").micro
204 0
205 """
206 return self._version.micro