Skip to content

next_version returns an older version when a legacy prerelease counter rolls over #499

Open

Description

@pabszero

Which version of Python is the problem with?

3.13

What semver version are you using?

master bcd151f

What OS are you using? (Add more in the Environment section)

Windows

Situation

Found by code inspection: next_version("prerelease") is documented to preserve natural order, but its same-token legacy counter path returns 1.2.3-rc10 from 1.2.3-rc9, which compares lower. The same happens at rc99 -> rc100 and with custom tokens such as beta9.

The comparison is correct under SemVer 11.4: identifiers containing letters are compared lexically in ASCII order. The generated next version violates the method's ordering guarantee.

How to reproduce

from semver import Version

original = Version.parse("1.2.3-rc9")
result = original.next_version("prerelease")
print(result)            # 1.2.3-rc10
print(result > original) # False

Controls: rc8 -> rc9 and dot-separated rc.9 -> rc.10 still move forward.

Expected behavior

The returned version should be newer. A proposed fix keeps the incremented legacy counter and advances the patch only when that candidate would not be newer: 1.2.3-rc9 -> 1.2.4-rc10. Ordinary increments retain the current patch.

This follows the patch-advance precedent from #497/#498, which address switching tokens; the legacy same-token path returns before that guard. #460/#462 addressed the concern for bump_prerelease. #484/#485 added old-style support to next_version, and test_issue_484_rc9_to_rc10 currently explicitly expects the lower version, so that expectation needs an explicit update.

Open #494/#496 concern integer-conversion limits for very long identifiers, a separate problem.

Environment

Reproduced on Windows CPython 3.12.14 and 3.13.5. A focused regression matrix against the original implementation has 8 failures and 5 passing controls. No production incident is claimed.

AI disclosure: found and reproduced with OpenAI Codex assistance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

SIze

None yet

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions