-
Notifications
You must be signed in to change notification settings - Fork 258
/
Copy pathspecification.py
138 lines (111 loc) · 4.3 KB
/
specification.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
from typing import FrozenSet
from typing import List
from typing import Optional
class PackageSpecification:
def __init__(
self,
name: str,
source_type: Optional[str] = None,
source_url: Optional[str] = None,
source_reference: Optional[str] = None,
source_resolved_reference: Optional[str] = None,
source_subdirectory: Optional[str] = None,
features: Optional[List[str]] = None,
):
from poetry.core.utils.helpers import canonicalize_name
self._pretty_name = name
self._name = canonicalize_name(name)
self._source_type = source_type
self._source_url = source_url
self._source_reference = source_reference
self._source_resolved_reference = source_resolved_reference
self._source_subdirectory = source_subdirectory
if not features:
features = []
self._features = frozenset(features)
@property
def name(self) -> str:
return self._name
@property
def pretty_name(self) -> str:
return self._pretty_name
@property
def complete_name(self) -> str:
name = self._name
if self._features:
features = ",".join(sorted(self._features))
name = f"{name}[{features}]"
return name
@property
def source_type(self) -> Optional[str]:
return self._source_type
@property
def source_url(self) -> Optional[str]:
return self._source_url
@property
def source_reference(self) -> Optional[str]:
return self._source_reference
@property
def source_resolved_reference(self) -> Optional[str]:
return self._source_resolved_reference
@property
def source_subdirectory(self) -> Optional[str]:
return self._source_subdirectory
@property
def features(self) -> FrozenSet[str]:
return self._features
def is_same_package_as(self, other: "PackageSpecification") -> bool:
if other.complete_name != self.complete_name:
return False
if self._source_type:
if self._source_type != other.source_type:
return False
if (
self._source_url or other.source_url
) and self._source_url != other.source_url:
return False
# We check the resolved reference first:
# if they match we assume equality regardless
# of their source reference.
# This is important when comparing a resolved branch VCS
# dependency to a direct commit reference VCS dependency
if (
self._source_resolved_reference
and other.source_resolved_reference
and self._source_resolved_reference == other.source_resolved_reference
):
return True
if self._source_reference or other.source_reference:
# special handling for packages with references
if not self._source_reference or not other.source_reference:
# case: one reference is defined and is non-empty, but other is not
return False
if not (
self._source_reference == other.source_reference
or self._source_reference.startswith(other.source_reference)
or other.source_reference.startswith(self._source_reference)
):
# case: both references defined, but one is not equal to or a short
# representation of the other
return False
if (
self._source_resolved_reference
and other.source_resolved_reference
and self._source_resolved_reference
!= other.source_resolved_reference
):
return False
return True
def __hash__(self) -> 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)
)
def __str__(self) -> str:
raise NotImplementedError()