@@ -118,6 +118,7 @@ def bump(
118
118
prerelease_offset : int = 0 ,
119
119
devrelease : int | None = None ,
120
120
is_local_version : bool = False ,
121
+ force_bump : bool = False ,
121
122
) -> Self :
122
123
"""
123
124
Based on the given increment, generate the next bumped version according to the version scheme
@@ -164,6 +165,12 @@ def generate_prerelease(
164
165
if not prerelease :
165
166
return ""
166
167
168
+ # prevent down-bumping the pre-release phase, e.g. from 'b1' to 'a2'
169
+ # https://packaging.python.org/en/latest/specifications/version-specifiers/#pre-releases
170
+ # https://semver.org/#spec-item-11
171
+ if self .is_prerelease and self .pre :
172
+ prerelease = max (prerelease , self .pre [0 ])
173
+
167
174
# version.pre is needed for mypy check
168
175
if self .is_prerelease and self .pre and prerelease .startswith (self .pre [0 ]):
169
176
prev_prerelease : int = self .pre [1 ]
@@ -189,20 +196,15 @@ def increment_base(self, increment: str | None = None) -> str:
189
196
increments = [MAJOR , MINOR , PATCH ]
190
197
base = dict (zip_longest (increments , prev_release , fillvalue = 0 ))
191
198
192
- # This flag means that current version
193
- # must remove its prerelease tag,
194
- # so it doesn't matter the increment.
195
- # Example: 1.0.0a0 with PATCH/MINOR -> 1.0.0
196
- if not self .is_prerelease :
197
- if increment == MAJOR :
198
- base [MAJOR ] += 1
199
- base [MINOR ] = 0
200
- base [PATCH ] = 0
201
- elif increment == MINOR :
202
- base [MINOR ] += 1
203
- base [PATCH ] = 0
204
- elif increment == PATCH :
205
- base [PATCH ] += 1
199
+ if increment == MAJOR :
200
+ base [MAJOR ] += 1
201
+ base [MINOR ] = 0
202
+ base [PATCH ] = 0
203
+ elif increment == MINOR :
204
+ base [MINOR ] += 1
205
+ base [PATCH ] = 0
206
+ elif increment == PATCH :
207
+ base [PATCH ] += 1
206
208
207
209
return f"{ base [MAJOR ]} .{ base [MINOR ]} .{ base [PATCH ]} "
208
210
@@ -213,6 +215,7 @@ def bump(
213
215
prerelease_offset : int = 0 ,
214
216
devrelease : int | None = None ,
215
217
is_local_version : bool = False ,
218
+ force_bump : bool = False ,
216
219
) -> Self :
217
220
"""Based on the given increment a proper semver will be generated.
218
221
@@ -230,9 +233,34 @@ def bump(
230
233
local_version = self .scheme (self .local ).bump (increment )
231
234
return self .scheme (f"{ self .public } +{ local_version } " ) # type: ignore
232
235
else :
233
- base = self .increment_base (increment )
236
+ if not self .is_prerelease :
237
+ base = self .increment_base (increment )
238
+ elif force_bump :
239
+ base = self .increment_base (increment )
240
+ else :
241
+ base = f"{ self .major } .{ self .minor } .{ self .micro } "
242
+ if increment == PATCH :
243
+ pass
244
+ elif increment == MINOR :
245
+ if self .micro != 0 :
246
+ base = self .increment_base (increment )
247
+ elif increment == MAJOR :
248
+ if self .minor != 0 or self .micro != 0 :
249
+ base = self .increment_base (increment )
234
250
dev_version = self .generate_devrelease (devrelease )
235
- pre_version = self .generate_prerelease (prerelease , offset = prerelease_offset )
251
+ release = list (self .release )
252
+ if len (release ) < 3 :
253
+ release += [0 ] * (3 - len (release ))
254
+ current_base = "." .join (str (part ) for part in release )
255
+ if base == current_base :
256
+ pre_version = self .generate_prerelease (
257
+ prerelease , offset = prerelease_offset
258
+ )
259
+ else :
260
+ base_version = cast (BaseVersion , self .scheme (base ))
261
+ pre_version = base_version .generate_prerelease (
262
+ prerelease , offset = prerelease_offset
263
+ )
236
264
# TODO: post version
237
265
return self .scheme (f"{ base } { pre_version } { dev_version } " ) # type: ignore
238
266
0 commit comments