Skip to content
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

packages: make hash() consistent and incl features #438

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 10 additions & 10 deletions poetry/core/packages/dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,21 +395,21 @@ def __eq__(self, other): # type: (Any) -> bool
if not isinstance(other, Dependency):
return NotImplemented

return (
self.is_same_package_as(other)
and self._constraint == other.constraint
and self._extras == other.extras
)
is_direct_origin = self.is_vcs() or self.is_directory() or self.is_file() or self.is_url()

# "constraint" is implicitly given for direct origin dependencies and might not
# be set yet ("*"). Thus, it shouldn't be used to determine if two direct origin
# dependencies are equal.
# Checkoing is_direct_origin for one dependency is sufficient because
# super().__eq__() returns False for different origins.
return super().__eq__(other) and (is_direct_origin or self._constraint == other.constraint)

def __ne__(self, other): # type: (Any) -> bool
return not self == other

def __hash__(self): # type: () -> int
return (
super(Dependency, self).__hash__()
^ hash(self._constraint)
^ hash(self._extras)
)
# don't include _constraint in hash because it is mutable!
return super().__hash__()

def __str__(self): # type: () -> str
if self.is_root:
Expand Down
3 changes: 0 additions & 3 deletions poetry/core/packages/directory_dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,3 @@ def __str__(self): # type: () -> str
return "{} ({} {})".format(
self._pretty_name, self._pretty_constraint, self._path.as_posix()
)

def __hash__(self): # type: () -> int
return hash((self._name, self._full_path.as_posix()))
3 changes: 0 additions & 3 deletions poetry/core/packages/file_dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,3 @@ def __str__(self): # type: () -> str
return "{} ({} {})".format(
self._pretty_name, self._pretty_constraint, self._path
)

def __hash__(self): # type: () -> int
return hash((self._name, self._full_path))
8 changes: 4 additions & 4 deletions poetry/core/packages/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,14 +410,14 @@ def clone(self): # type: () -> "Package"
clone.__dict__ = copy.deepcopy(self.__dict__)
return clone

def __hash__(self): # type: () -> int
return super(Package, self).__hash__() ^ hash(self._version)

def __eq__(self, other): # type: (Package) -> bool
if not isinstance(other, Package):
return NotImplemented

return self.is_same_package_as(other) and self._version == other.version
return super().__eq__(other) and self._version == other.version

def __hash__(self) -> int:
return super().__hash__() ^ hash(self._version)

def __str__(self): # type: () -> str
return "{} ({})".format(self.complete_name, self.full_pretty_version)
Expand Down
29 changes: 18 additions & 11 deletions poetry/core/packages/specification.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from typing import Any
from typing import FrozenSet
from typing import List
from typing import Optional
Expand Down Expand Up @@ -101,18 +102,24 @@ def is_same_package_as(self, other): # type: ("PackageSpecification") -> bool

return True

def __eq__(self, other): # type: (Any) -> bool
if not isinstance(other, PackageSpecification):
return NotImplemented
return self.is_same_package_as(other)

def __hash__(self): # type: () -> int
if not self._source_type:
return hash(self._name)

return (
hash(self._name)
^ hash(self._source_type)
^ hash(self._source_url)
^ hash(self._source_reference)
^ hash(self._source_resolved_reference)
^ hash(self._features)
)
result = hash(self.complete_name) # complete_name includes features

if self._source_type:
# Don't include _source_reference and _source_resolved_reference in hash
# because two specs can be equal even if these attributes are not equal.
# (They must still meet certain conditions. See is_same_source_as().)
result ^= (
hash(self._source_type)
^ hash(self._source_url)
)

return result

def __str__(self): # type: () -> str
raise NotImplementedError()
3 changes: 0 additions & 3 deletions poetry/core/packages/url_dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,3 @@ def with_constraint(self, constraint): # type: ("BaseConstraint") -> URLDepende

def __str__(self): # type: () -> str
return "{} ({} url)".format(self._pretty_name, self._pretty_constraint)

def __hash__(self): # type: () -> int
return hash((self._name, self._url))
3 changes: 0 additions & 3 deletions poetry/core/packages/vcs_dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,3 @@ def __str__(self): # type: () -> str
reference += " rev {}".format(self._rev)

return "{} ({} {})".format(self._pretty_name, self._constraint, reference)

def __hash__(self): # type: () -> int
return hash((self._name, self._vcs, self._branch, self._tag, self._rev))