Skip to content

VersionRange.invert() returns a complement that excludes versions outside an enumerated range #213

Description

@sinagkh

Summary

For vers:pypi/1.0.0|2.0.0, version 1.5.0 is outside both the original range and the result of invert(). This violates the documented inverse/complement purpose of the method and can leave versions unclassified when a caller partitions them using a range and its complement.

Reproduction

Save the following as repro.py.

from univers.version_range import VersionRange
from univers.versions import PypiVersion

r = VersionRange.from_string("vers:pypi/1.0.0|2.0.0")
inverse = r.invert()
print("range:", r)
print("inverse:", inverse)
for text in ("1.0.0", "1.5.0", "2.0.0"):
    v = PypiVersion(text)
    print(text, "in range:", v in r, "in inverse:", v in inverse)

Run:

python -m pip install univers==32.0.1
python repro.py

Actual result

range: vers:pypi/1.0.0|2.0.0
inverse: vers:pypi/!=1.0.0|!=2.0.0
1.0.0 in range: True in inverse: False
1.5.0 in range: False in inverse: False
2.0.0 in range: True in inverse: False

Expected result and contract

For each version, membership in a range and its complement should be opposite. In particular, 1.5.0 should be in the inverse because it is not in the original enumerated range; the two enumerated versions should remain outside the inverse.

The API's complement purpose is described in issue #91 and the implementing PR #92:
#91
#92

Code-level observation

invert() produces an all-!= constraint list. In the containment path, after testing the explicitly excluded versions, the =/!= constraints are filtered out and the empty remainder returns false. As a result, a version that matches none of the exclusions is still rejected. The report concerns the semantics of the returned complement, irrespective of how the constraint list's connective is represented internally.

I also reviewed the related containment issue #137; I could not establish that it covers this enumerated-inverse case:
#137

Environment

  • Package: univers 32.0.1
  • Runtime: CPython 3.13.3
  • OS: macOS 26.6.2, Apple Silicon / arm64
  • Reproduced: 2026-09-11

univers-reproduction.zip

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions