lib.version.Version.next(): Step the last part

Range expansion needs a bound that steps the last existing part of a
version, add that.

next() increments the last part, whatever it is: next of '1' is '2', of
'1.0' is '1.1', of '1.2.3' is '1.2.4', of '1.2.3-45' is '1.2.3-46'.

Tests written by AI.

Signed-off-by: Jan Lindemann <jan@janware.com>
Assisted-by: unsloth/Qwen3.8-27B-GGUF:Q4_K_M with pi.dev v0.85.1
This commit is contained in:
Jan Lindemann 2026-09-15 19:57:08 +02:00
commit 83b5151f22
Signed by: Jan Lindemann
GPG key ID: 3750640C9E25DD61
2 changed files with 48 additions and 0 deletions

View file

@ -220,3 +220,28 @@ class Version: # export
f'{self.major}.{self.minor + 1}.0',
self.__lookup_version,
)
@property
def next(self) -> Version:
"""The next version in the series: the last part
incremented. next of '1' is '2', of '1.0' is '1.1', of
'1.2.3' is '1.2.4', of '1.2.3-45' is '1.2.3-46'. The
separators of the spec are kept. Like in
next_binary_compatible(), only the last part's leading
digits count: a suffixed part such as '4blah' steps to
'5'. A part without leading digits raises Version.Error.
"""
untemplated = self.__id(untemplate = True, throw = True)
parts = re.split('([.-])', untemplated)
m = re.match('[0-9]+', parts[-1])
if not m:
raise Version.Error(
f'Cannot step version "{self.__spec}": the last '
f'part "{parts[-1]}" has no leading digits'
)
parts[-1] = str(int(m.group()) + 1)
return Version(
self.__name,
''.join(parts),
self.__lookup_version,
)

View file

@ -193,6 +193,29 @@ for spec in ['1.2.3-rc1', '1.2.3']:
except Version.Error:
pass
# next steps the last existing part, whatever it is
for spec, expected in [
('1', '2'),
('1.0', '1.1'),
('1.2.3', '1.2.4'),
('1.2.3-45', '1.2.3-46'),
('1.2.3-4blah', '1.2.3-5'),
('1.2.3.4', '1.2.3.5'),
('1.2.3rc1', '1.2.4'),
('VERSION', '1.2.4'),
]:
v = Version('foo', spec, app.get_version)
assert str(v.next) == expected, spec
# A last part without leading digits cannot be stepped
for spec in ['1.0-rc1', '1.2.alpha']:
v = Version('foo', spec)
try:
v.next
assert False, f'Should have raised for {spec!r}'
except Version.Error:
pass
# constructor
d = Dependency('foo-devel = 1.0')
assert d.base_name == 'foo'