Coverage for src / bioimageio / spec / _internal / version_type.py: 86%
69 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-31 13:09 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-31 13:09 +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 def __ge__(self, other: Any):
34 if not isinstance(other, Version):
35 return NotImplemented
36 return self._version >= other._version
38 def __le__(self, other: Any):
39 if not isinstance(other, Version):
40 return NotImplemented
41 return self._version <= other._version
43 # the properties below are adopted from and mirror properties of packaging.version.Version
44 @property
45 def epoch(self) -> int:
46 """The epoch of the version.
48 >>> Version("2.0.0").epoch
49 0
50 >>> Version("1!2.0.0").epoch
51 1
52 """
53 return self._version.epoch
55 @property
56 def release(self) -> Tuple[int, ...]:
57 """The components of the "release" segment of the version.
59 >>> Version("1.2.3").release
60 (1, 2, 3)
61 >>> Version("2.0.0").release
62 (2, 0, 0)
63 >>> Version("1!2.0.0.post0").release
64 (2, 0, 0)
66 Includes trailing zeroes but not the epoch or any pre-release / development /
67 post-release suffixes.
68 """
69 return self._version.release
71 @property
72 def pre(self) -> Optional[Tuple[str, int]]:
73 """The pre-release segment of the version.
75 >>> print(Version("1.2.3").pre)
76 None
77 >>> Version("1.2.3a1").pre
78 ('a', 1)
79 >>> Version("1.2.3b1").pre
80 ('b', 1)
81 >>> Version("1.2.3rc1").pre
82 ('rc', 1)
83 """
84 return self._version.pre
86 @property
87 def post(self) -> Optional[int]:
88 """The post-release number of the version.
90 >>> print(Version("1.2.3").post)
91 None
92 >>> Version("1.2.3.post1").post
93 1
94 """
95 return self._version.post
97 @property
98 def dev(self) -> Optional[int]:
99 """The development number of the version.
101 >>> print(Version("1.2.3").dev)
102 None
103 >>> Version("1.2.3.dev1").dev
104 1
105 """
106 return self._version.dev
108 @property
109 def local(self) -> Optional[str]:
110 """The local version segment of the version.
112 >>> print(Version("1.2.3").local)
113 None
114 >>> Version("1.2.3+abc").local
115 'abc'
116 """
117 return self._version.local
119 @property
120 def public(self) -> str:
121 """The public portion of the version.
123 >>> Version("1.2.3").public
124 '1.2.3'
125 >>> Version("1.2.3+abc").public
126 '1.2.3'
127 >>> Version("1.2.3+abc.dev1").public
128 '1.2.3'
129 """
130 return self._version.public
132 @property
133 def base_version(self) -> str:
134 """The "base version" of the version.
136 >>> Version("1.2.3").base_version
137 '1.2.3'
138 >>> Version("1.2.3+abc").base_version
139 '1.2.3'
140 >>> Version("1!1.2.3+abc.dev1").base_version
141 '1!1.2.3'
143 The "base version" is the public version of the project without any pre or post
144 release markers.
145 """
146 return self._version.base_version
148 @property
149 def is_prerelease(self) -> bool:
150 """Whether this version is a pre-release.
152 >>> Version("1.2.3").is_prerelease
153 False
154 >>> Version("1.2.3a1").is_prerelease
155 True
156 >>> Version("1.2.3b1").is_prerelease
157 True
158 >>> Version("1.2.3rc1").is_prerelease
159 True
160 >>> Version("1.2.3dev1").is_prerelease
161 True
162 """
163 return self._version.is_prerelease
165 @property
166 def is_postrelease(self) -> bool:
167 """Whether this version is a post-release.
169 >>> Version("1.2.3").is_postrelease
170 False
171 >>> Version("1.2.3.post1").is_postrelease
172 True
173 """
174 return self._version.is_postrelease
176 @property
177 def is_devrelease(self) -> bool:
178 """Whether this version is a development release.
180 >>> Version("1.2.3").is_devrelease
181 False
182 >>> Version("1.2.3.dev1").is_devrelease
183 True
184 """
185 return self._version.is_devrelease
187 @property
188 def major(self) -> int:
189 """The first item of :attr:`release` or ``0`` if unavailable.
191 >>> Version("1.2.3").major
192 1
193 """
194 return self._version.major
196 @property
197 def minor(self) -> int:
198 """The second item of :attr:`release` or ``0`` if unavailable.
200 >>> Version("1.2.3").minor
201 2
202 >>> Version("1").minor
203 0
204 """
205 return self._version.minor
207 @property
208 def micro(self) -> int:
209 """The third item of :attr:`release` or ``0`` if unavailable.
211 >>> Version("1.2.3").micro
212 3
213 >>> Version("1").micro
214 0
215 """
216 return self._version.micro