Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
keewenaw
GitHub Repository: keewenaw/ethereum-wallet-cracker
Path: blob/main/test/lib/python3.9/site-packages/pip/_internal/index/sources.py
4804 views
1
import logging
2
import mimetypes
3
import os
4
import pathlib
5
from typing import Callable, Iterable, Optional, Tuple
6
7
from pip._internal.models.candidate import InstallationCandidate
8
from pip._internal.models.link import Link
9
from pip._internal.utils.urls import path_to_url, url_to_path
10
from pip._internal.vcs import is_url
11
12
logger = logging.getLogger(__name__)
13
14
FoundCandidates = Iterable[InstallationCandidate]
15
FoundLinks = Iterable[Link]
16
CandidatesFromPage = Callable[[Link], Iterable[InstallationCandidate]]
17
PageValidator = Callable[[Link], bool]
18
19
20
class LinkSource:
21
@property
22
def link(self) -> Optional[Link]:
23
"""Returns the underlying link, if there's one."""
24
raise NotImplementedError()
25
26
def page_candidates(self) -> FoundCandidates:
27
"""Candidates found by parsing an archive listing HTML file."""
28
raise NotImplementedError()
29
30
def file_links(self) -> FoundLinks:
31
"""Links found by specifying archives directly."""
32
raise NotImplementedError()
33
34
35
def _is_html_file(file_url: str) -> bool:
36
return mimetypes.guess_type(file_url, strict=False)[0] == "text/html"
37
38
39
class _FlatDirectorySource(LinkSource):
40
"""Link source specified by ``--find-links=<path-to-dir>``.
41
42
This looks the content of the directory, and returns:
43
44
* ``page_candidates``: Links listed on each HTML file in the directory.
45
* ``file_candidates``: Archives in the directory.
46
"""
47
48
def __init__(
49
self,
50
candidates_from_page: CandidatesFromPage,
51
path: str,
52
) -> None:
53
self._candidates_from_page = candidates_from_page
54
self._path = pathlib.Path(os.path.realpath(path))
55
56
@property
57
def link(self) -> Optional[Link]:
58
return None
59
60
def page_candidates(self) -> FoundCandidates:
61
for path in self._path.iterdir():
62
url = path_to_url(str(path))
63
if not _is_html_file(url):
64
continue
65
yield from self._candidates_from_page(Link(url))
66
67
def file_links(self) -> FoundLinks:
68
for path in self._path.iterdir():
69
url = path_to_url(str(path))
70
if _is_html_file(url):
71
continue
72
yield Link(url)
73
74
75
class _LocalFileSource(LinkSource):
76
"""``--find-links=<path-or-url>`` or ``--[extra-]index-url=<path-or-url>``.
77
78
If a URL is supplied, it must be a ``file:`` URL. If a path is supplied to
79
the option, it is converted to a URL first. This returns:
80
81
* ``page_candidates``: Links listed on an HTML file.
82
* ``file_candidates``: The non-HTML file.
83
"""
84
85
def __init__(
86
self,
87
candidates_from_page: CandidatesFromPage,
88
link: Link,
89
) -> None:
90
self._candidates_from_page = candidates_from_page
91
self._link = link
92
93
@property
94
def link(self) -> Optional[Link]:
95
return self._link
96
97
def page_candidates(self) -> FoundCandidates:
98
if not _is_html_file(self._link.url):
99
return
100
yield from self._candidates_from_page(self._link)
101
102
def file_links(self) -> FoundLinks:
103
if _is_html_file(self._link.url):
104
return
105
yield self._link
106
107
108
class _RemoteFileSource(LinkSource):
109
"""``--find-links=<url>`` or ``--[extra-]index-url=<url>``.
110
111
This returns:
112
113
* ``page_candidates``: Links listed on an HTML file.
114
* ``file_candidates``: The non-HTML file.
115
"""
116
117
def __init__(
118
self,
119
candidates_from_page: CandidatesFromPage,
120
page_validator: PageValidator,
121
link: Link,
122
) -> None:
123
self._candidates_from_page = candidates_from_page
124
self._page_validator = page_validator
125
self._link = link
126
127
@property
128
def link(self) -> Optional[Link]:
129
return self._link
130
131
def page_candidates(self) -> FoundCandidates:
132
if not self._page_validator(self._link):
133
return
134
yield from self._candidates_from_page(self._link)
135
136
def file_links(self) -> FoundLinks:
137
yield self._link
138
139
140
class _IndexDirectorySource(LinkSource):
141
"""``--[extra-]index-url=<path-to-directory>``.
142
143
This is treated like a remote URL; ``candidates_from_page`` contains logic
144
for this by appending ``index.html`` to the link.
145
"""
146
147
def __init__(
148
self,
149
candidates_from_page: CandidatesFromPage,
150
link: Link,
151
) -> None:
152
self._candidates_from_page = candidates_from_page
153
self._link = link
154
155
@property
156
def link(self) -> Optional[Link]:
157
return self._link
158
159
def page_candidates(self) -> FoundCandidates:
160
yield from self._candidates_from_page(self._link)
161
162
def file_links(self) -> FoundLinks:
163
return ()
164
165
166
def build_source(
167
location: str,
168
*,
169
candidates_from_page: CandidatesFromPage,
170
page_validator: PageValidator,
171
expand_dir: bool,
172
cache_link_parsing: bool,
173
) -> Tuple[Optional[str], Optional[LinkSource]]:
174
175
path: Optional[str] = None
176
url: Optional[str] = None
177
if os.path.exists(location): # Is a local path.
178
url = path_to_url(location)
179
path = location
180
elif location.startswith("file:"): # A file: URL.
181
url = location
182
path = url_to_path(location)
183
elif is_url(location):
184
url = location
185
186
if url is None:
187
msg = (
188
"Location '%s' is ignored: "
189
"it is either a non-existing path or lacks a specific scheme."
190
)
191
logger.warning(msg, location)
192
return (None, None)
193
194
if path is None:
195
source: LinkSource = _RemoteFileSource(
196
candidates_from_page=candidates_from_page,
197
page_validator=page_validator,
198
link=Link(url, cache_link_parsing=cache_link_parsing),
199
)
200
return (url, source)
201
202
if os.path.isdir(path):
203
if expand_dir:
204
source = _FlatDirectorySource(
205
candidates_from_page=candidates_from_page,
206
path=path,
207
)
208
else:
209
source = _IndexDirectorySource(
210
candidates_from_page=candidates_from_page,
211
link=Link(url, cache_link_parsing=cache_link_parsing),
212
)
213
return (url, source)
214
elif os.path.isfile(path):
215
source = _LocalFileSource(
216
candidates_from_page=candidates_from_page,
217
link=Link(url, cache_link_parsing=cache_link_parsing),
218
)
219
return (url, source)
220
logger.warning(
221
"Location '%s' is ignored: it is neither a file nor a directory.",
222
location,
223
)
224
return (url, None)
225
226