1
+ from typing import Any
2
+
1
3
from pip ._vendor .packaging .specifiers import SpecifierSet
2
4
from pip ._vendor .packaging .utils import NormalizedName , canonicalize_name
3
5
@@ -17,6 +19,14 @@ def __str__(self) -> str:
17
19
def __repr__ (self ) -> str :
18
20
return f"{ self .__class__ .__name__ } ({ self .candidate !r} )"
19
21
22
+ def __hash__ (self ) -> int :
23
+ return hash (self .candidate )
24
+
25
+ def __eq__ (self , other : Any ) -> bool :
26
+ if not isinstance (other , ExplicitRequirement ):
27
+ return False
28
+ return self .candidate == other .candidate
29
+
20
30
@property
21
31
def project_name (self ) -> NormalizedName :
22
32
# No need to canonicalize - the candidate did this
@@ -49,6 +59,14 @@ def __str__(self) -> str:
49
59
def __repr__ (self ) -> str :
50
60
return f"{ self .__class__ .__name__ } ({ str (self ._ireq .req )!r} )"
51
61
62
+ def __eq__ (self , other : object ) -> bool :
63
+ if not isinstance (other , SpecifierRequirement ):
64
+ return NotImplemented
65
+ return str (self ._ireq ) == str (other ._ireq )
66
+
67
+ def __hash__ (self ) -> int :
68
+ return hash (str (self ._ireq ))
69
+
52
70
@property
53
71
def project_name (self ) -> NormalizedName :
54
72
assert self ._ireq .req , "Specifier-backed ireq is always PEP 508"
@@ -98,12 +116,21 @@ def __init__(self, ireq: InstallRequirement) -> None:
98
116
self ._ireq = install_req_drop_extras (ireq )
99
117
self ._extras = frozenset (canonicalize_name (e ) for e in self ._ireq .extras )
100
118
119
+ def __eq__ (self , other : object ) -> bool :
120
+ if not isinstance (other , SpecifierWithoutExtrasRequirement ):
121
+ return NotImplemented
122
+ return str (self ._ireq ) == str (other ._ireq )
123
+
124
+ def __hash__ (self ) -> int :
125
+ return hash (str (self ._ireq ))
126
+
101
127
102
128
class RequiresPythonRequirement (Requirement ):
103
129
"""A requirement representing Requires-Python metadata."""
104
130
105
131
def __init__ (self , specifier : SpecifierSet , match : Candidate ) -> None :
106
132
self .specifier = specifier
133
+ self ._specifier_string = str (specifier ) # for faster __eq__
107
134
self ._candidate = match
108
135
109
136
def __str__ (self ) -> str :
@@ -112,6 +139,17 @@ def __str__(self) -> str:
112
139
def __repr__ (self ) -> str :
113
140
return f"{ self .__class__ .__name__ } ({ str (self .specifier )!r} )"
114
141
142
+ def __hash__ (self ) -> int :
143
+ return hash ((self ._specifier_string , self ._candidate ))
144
+
145
+ def __eq__ (self , other : Any ) -> bool :
146
+ if not isinstance (other , RequiresPythonRequirement ):
147
+ return False
148
+ return (
149
+ self ._specifier_string == other ._specifier_string
150
+ and self ._candidate == other ._candidate
151
+ )
152
+
115
153
@property
116
154
def project_name (self ) -> NormalizedName :
117
155
return self ._candidate .project_name
@@ -148,6 +186,14 @@ def __str__(self) -> str:
148
186
def __repr__ (self ) -> str :
149
187
return f"{ self .__class__ .__name__ } ({ str (self ._name )!r} )"
150
188
189
+ def __eq__ (self , other : object ) -> bool :
190
+ if not isinstance (other , UnsatisfiableRequirement ):
191
+ return NotImplemented
192
+ return self ._name == other ._name
193
+
194
+ def __hash__ (self ) -> int :
195
+ return hash (self ._name )
196
+
151
197
@property
152
198
def project_name (self ) -> NormalizedName :
153
199
return self ._name
0 commit comments