Skip to content

[capycli] Fix ComparableVersion.__ne__ returning False for non-ComparableVersion objects#223

Open
prajakta128 wants to merge 1 commit into
sw360:mainfrom
prajakta128:fix/comparable-version-ne
Open

[capycli] Fix ComparableVersion.__ne__ returning False for non-ComparableVersion objects#223
prajakta128 wants to merge 1 commit into
sw360:mainfrom
prajakta128:fix/comparable-version-ne

Conversation

@prajakta128

Copy link
Copy Markdown

Problem

ComparableVersion.__ne__ incorrectly returns False when the right-hand
operand is not a ComparableVersion instance (e.g. a plain str, int,
or None).

This means expressions like:

ComparableVersion("1.0") != "1.0"   # returns False  ← wrong
ComparableVersion("1.0") != 42      # returns False  ← wrong
ComparableVersion("1.0") != None    # returns False  ← wrong

All of these should return True because the objects are clearly not equal.
This is a silent correctness bug — no exception is raised, just a wrong answer.

Root Cause

The __ne__ method copied the early-return guard from __eq__:

if not isinstance(other, self.__class__):
    return False  # correct in __eq__ (not equal = False)
                  # WRONG in __ne__  (not equal should = True)

In __eq__, returning False for a type mismatch is correct — two objects
of different types are not equal. But __ne__ is the logical inverse, so it
must return True for the same case.

Fix

Changed return Falsereturn True in the isinstance guard of __ne__:

def __ne__(self, other: ComparableVersion | object) -> bool:
    if not isinstance(other, self.__class__):
        return True  # different types are never equal
    try:
        return self.compare(other) != 0
    except IncompatibleVersionError:
        return self.version.__ne__(other.version)

Test Added

Added test_ne_with_non_comparable_version in tests/test_comparable_version.py
covering comparison against str, int, and None — all cases that previously
returned the wrong result.

Impact

Any code that uses != to compare a ComparableVersion against a plain string
or other type would silently get the wrong result. Since version values commonly
arrive as plain strings from JSON or CLI arguments, this bug could cause
incorrect filtering or deduplication of components without any visible error.

@gernot-h gernot-h force-pushed the fix/comparable-version-ne branch from b48f5b4 to 00517f0 Compare June 12, 2026 09:21
@gernot-h

Copy link
Copy Markdown
Collaborator

@prajakta128, thanks for your contribution! The change itself looks good to me, I agree that default return value of ne should be negated compared to eq! It was however still failing flake8 tests, so I pushed a small fix and squased your two commits into one.

Just one question, did you find this by pure code anaylsis or did this cause some real problems when using CaPyCli? In the latter case, we should mention them in the ChangeLog.

@tngraf, assigning to you for final decision, from my side it can be merged.

@gernot-h gernot-h self-requested a review June 12, 2026 09:23
@prajakta128

Copy link
Copy Markdown
Author

@prajakta128, thanks for your contribution! The change itself looks good to me, I agree that default return value of ne should be negated compared to eq! It was however still failing flake8 tests, so I pushed a small fix and squased your two commits into one.

Just one question, did you find this by pure code anaylsis or did this cause some real problems when using CaPyCli? In the latter case, we should mention them in the ChangeLog.

@tngraf, assigning to you for final decision, from my side it can be merged.

@gernot-h Thank you for the review, and for fixing the flake8 issue and
squashing the commits.

To answer your question — I identified this issue through code review of
comparable_version.py, not from a reported bug while using CaPyCli. The
ne method copied the isinstance check from eq but did not invert
the return value to match the logical inverse semantics of "not equal."
Since this wasn't causing a known issue in practice, I don't think a
ChangeLog entry is necessary, but I'm happy to add one if you feel it
would be useful for future reference.

Thank you for taking the time to review this contribution.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants