Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Python: Modernize 3 quality queries for comparison methods#20038

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
joefarebrother wants to merge15 commits intogithub:main
base:main
Choose a base branch
Loading
fromjoefarebrother:python-qual-comparison

Conversation

joefarebrother
Copy link
Contributor

Modernizespy/incomplete-ordering,py/inconsistent-equality, andpy/equals-hash-mismatch
No longer uses pointsTo, removes python 2 specific cases, and updates documentation.

@CopilotCopilotAI review requested due to automatic review settingsJuly 14, 2025 10:18
@joefarebrotherjoefarebrother requested a review froma team as acode ownerJuly 14, 2025 10:18
Copy link
Contributor

@CopilotCopilotAI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Pull Request Overview

This PR modernizes three Python quality queries for comparison methods:py/incomplete-ordering,py/inconsistent-equality, andpy/equals-hash-mismatch. The modernization removes dependency on the legacy pointsTo analysis, eliminates Python 2-specific cases to focus on Python 3, and updates documentation with clearer examples and explanations.

Key changes include:

  • Complete rewrite of the three comparison queries using modern CodeQL libraries
  • Migration of query files fromClasses/ toClasses/Comparisons/ directory structure
  • Updated test cases with inline expectations format and comprehensive examples
  • Enhanced documentation with Python 3-focused guidance and improved examples

Reviewed Changes

Copilot reviewed 36 out of 37 changed files in this pull request and generated 4 comments.

Show a summary per file
FileDescription
python/ql/src/Classes/Comparisons/*.qlNew modernized query implementations using current CodeQL libraries
python/ql/src/Classes/Comparisons/*.qhelpUpdated documentation with Python 3 focus and clearer examples
python/ql/test/query-tests/Classes/*/**.pyEnhanced test cases with comprehensive comparison method scenarios
python/ql/src/Classes/Equality.qllExtended DelegatingEqualityMethod to handle method call delegation patterns
python/ql/lib/semmle/python/Class.qllAdded getMethod convenience predicate for retrieving methods by name

@github-actionsGitHub Actions
Copy link
Contributor

QHelp previews:

python/ql/src/Classes/Comparisons/EqualsOrHash.qhelp

Inconsistent equality and hashing

A hashable class has an__eq__ method, and a__hash__ method that agrees with equality. When a hash method is defined, an equality method should also be defined; otherwise object identity is used for equality comparisons which may not be intended.

Note that defining an__eq__ method without defining a__hash__ method automatically makes the class unhashable in Python 3. (even if a superclass defines a hash method).

Recommendation

If a__hash__ method is defined, ensure a compatible__eq__ method is also defined.

To explicitly declare a class as unhashable, set__hash__ = None, rather than defining a__hash__ method that always raises an exception. Otherwise, the class would be incorrectly identified as hashable by anisinstance(obj, collections.abc.Hashable) call.

Example

In the following example, theA class defines an hash method but no equality method. Equality will be determined by object identity, which may not be the expected behaviour.

classA:def__init__(self,a,b):self.a=aself.b=b# No equality method is defineddef__hash__(self):returnhash((self.a,self.b))

References

python/ql/src/Classes/Comparisons/EqualsOrNotEquals.qhelp

Inconsistent equality and inequality

In order to ensure the== and!= operators behave consistently as expected (i.e. they should be negations of each other), care should be taken when implementing the__eq__ and__ne__ special methods.

In Python 3, if the__eq__ method is defined in a class while the__ne__ is not, then the!= operator will automatically delegate to the__eq__ method in the expected way.

However, if the__ne__ method is defined without a corresponding__eq__ method, the== operator will still default to object identity (equivalent to theis operator), while the!= operator will use the__ne__ method, which may be inconsistent.

Additionally, if the__ne__ method is defined on a superclass, and the subclass defines its own__eq__ method without overriding the superclass__ne__ method, the!= operator will use this superclass__ne__ method, rather than automatically delegating to__eq__, which may be incorrect.

Recommendation

Ensure that when an__ne__ method is defined, the__eq__ method is also defined, and their results are consistent. In most cases, the__ne__ method does not need to be defined at all, as the default behavior is to delegate to__eq__ and negate the result.

Example

In the following example,A defines a__ne__ method, but not an__eq__ method. This leads to inconsistent results between equality and inequality operators.

classA:def__init__(self,a):self.a=a# BAD: ne is defined, but not eq.def__ne__(self,other):ifnotisinstance(other,A):returnNotImplementedreturnself.a!=other.ax=A(1)y=A(1)print(x==y)# Prints False (potentially unexpected - object identity is used)print(x!=y)# Prints False

In the following example,C defines an__eq__ method, but its__ne__ implementation is inherited fromB, which is not consistent with the equality operation.

classB:def__init__(self,b):self.b=bdef__eq__(self,other):returnself.b==other.bdef__ne__(self,other):returnself.b!=other.bclassC(B):def__init__(self,b,c):super().__init__(b)self.c=c# BAD: eq is defined, but != will use superclass ne method, which is not consistentdef__eq__(self,other):returnself.b==other.bandself.c==other.cprint(C(1,2)==C(1,3))# Prints Falseprint(C(1,2)!=C(1,3))# Prints False (potentially unexpected)

References

python/ql/src/Classes/Comparisons/IncompleteOrdering.qhelp

Incomplete ordering

A class that implements the rich comparison operators (__lt__,__gt__,__le__, or__ge__) should ensure that all four comparison operations<,<=,>, and>= function as expected, consistent with expected mathematical rules. In Python 3, this is ensured by implementing one of__lt__ or__gt__, and one of__le__ or__ge__. If the ordering is not consistent with default equality, then__eq__ should also be implemented.

Recommendation

Ensure that at least one of__lt__ or__gt__ and at least one of__le__ or__ge__ is defined.

Thefunctools.total_ordering class decorator can be used to automatically implement all four comparison methods from a single one, which is typically the cleanest way to ensure all necessary comparison methods are implemented consistently.

Example

In the following example, only the__lt__ operator has been implemented, which would lead to unexpected errors if the<= or>= operators are used onA instances. The__le__ method should also be defined, as well as__eq__ in this case.

classA:def__init__(self,i):self.i=i# BAD: le is not defined, so `A(1) <= A(2)` would result in an error.def__lt__(self,other):returnself.i<other.i

References

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

Copilot code reviewCopilotCopilot left review comments

At least 1 approving review is required to merge this pull request.

Assignees
No one assigned
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

1 participant
@joefarebrother

[8]ページ先頭

©2009-2025 Movatter.jp