Skip to content

Commit 69bfc1b

Browse files
committed
Merge remote-tracking branch 'skeleton/main' into prepare-release
2 parents 99d274d + 6a3c5b0 commit 69bfc1b

File tree

6 files changed

+488
-649
lines changed

6 files changed

+488
-649
lines changed

etc/scripts/check_thirdparty.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
@click.command()
1717
@click.option(
1818
"-d",
19-
"--dest_dir",
19+
"--dest",
2020
type=click.Path(exists=True, readable=True, path_type=str, file_okay=False),
2121
required=True,
2222
help="Path to the thirdparty directory to check.",
@@ -35,7 +35,7 @@
3535
)
3636
@click.help_option("-h", "--help")
3737
def check_thirdparty_dir(
38-
dest_dir,
38+
dest,
3939
wheels,
4040
sdists,
4141
):
@@ -45,7 +45,7 @@ def check_thirdparty_dir(
4545
# check for problems
4646
print(f"==> CHECK FOR PROBLEMS")
4747
utils_thirdparty.find_problems(
48-
dest_dir=dest_dir,
48+
dest_dir=dest,
4949
report_missing_sources=sdists,
5050
report_missing_wheels=wheels,
5151
)

etc/scripts/fetch_thirdparty.py

Lines changed: 80 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
import utils_thirdparty
1919
import utils_requirements
2020

21-
TRACE = True
21+
TRACE = False
22+
TRACE_DEEP = False
2223

2324

2425
@click.command()
@@ -99,11 +100,17 @@
99100
"index_urls",
100101
type=str,
101102
metavar="INDEX",
102-
default=utils_thirdparty.PYPI_INDEXES,
103+
default=utils_thirdparty.PYPI_INDEX_URLS,
103104
show_default=True,
104105
multiple=True,
105106
help="PyPI index URL(s) to use for wheels and sources, in order of preferences.",
106107
)
108+
@click.option(
109+
"--use-cached-index",
110+
is_flag=True,
111+
help="Use on disk cached PyPI indexes list of packages and versions and do not refetch if present.",
112+
)
113+
107114
@click.help_option("-h", "--help")
108115
def fetch_thirdparty(
109116
requirements_files,
@@ -115,26 +122,34 @@ def fetch_thirdparty(
115122
wheels,
116123
sdists,
117124
index_urls,
125+
use_cached_index,
118126
):
119127
"""
120-
Download to --dest-dir THIRDPARTY_DIR the PyPI wheels, source distributions,
128+
Download to --dest THIRDPARTY_DIR the PyPI wheels, source distributions,
121129
and their ABOUT metadata, license and notices files.
122130
123131
Download the PyPI packages listed in the combination of:
124132
- the pip requirements --requirements REQUIREMENT-FILE(s),
125133
- the pip name==version --specifier SPECIFIER(s)
126134
- any pre-existing wheels or sdsists found in --dest-dir THIRDPARTY_DIR.
127135
128-
Download wheels with the --wheels option for the ``--python-version`` PYVER(s)
129-
and ``--operating_system`` OS(s) combinations defaulting to all supported combinations.
136+
Download wheels with the --wheels option for the ``--python-version``
137+
PYVER(s) and ``--operating_system`` OS(s) combinations defaulting to all
138+
supported combinations.
130139
131140
Download sdists tarballs with the --sdists option.
132141
133-
Generate or Download .ABOUT, .LICENSE and .NOTICE files for all the wheels and sources fetched.
142+
Generate or Download .ABOUT, .LICENSE and .NOTICE files for all the wheels
143+
and sources fetched.
134144
135-
Download wheels and sdists the provided PyPI simple --index-url INDEX(s) URLs.
145+
Download from the provided PyPI simple --index-url INDEX(s) URLs.
136146
"""
147+
if not (wheels or sdists):
148+
print("Error: one or both of --wheels and --sdists is required.")
149+
sys.exit(1)
150+
137151
print(f"COLLECTING REQUIRED NAMES & VERSIONS FROM {dest_dir}")
152+
138153
existing_packages_by_nv = {
139154
(package.name, package.version): package
140155
for package in utils_thirdparty.get_local_packages(directory=dest_dir)
@@ -150,134 +165,88 @@ def fetch_thirdparty(
150165
required_name_versions.update(nvs)
151166

152167
for specifier in specifiers:
153-
nv = utils_requirements.get_name_version(
168+
nv = utils_requirements.get_required_name_version(
154169
requirement=specifier,
155170
with_unpinned=latest_version,
156171
)
157172
required_name_versions.add(nv)
158173

174+
if latest_version:
175+
names = set(name for name, _version in sorted(required_name_versions))
176+
required_name_versions = {(n, None) for n in names}
177+
159178
if not required_name_versions:
160179
print("Error: no requirements requested.")
161180
sys.exit(1)
162181

163-
if not os.listdir(dest_dir) and not (wheels or sdists):
164-
print("Error: one or both of --wheels and --sdists is required.")
165-
sys.exit(1)
166-
167-
if latest_version:
168-
latest_name_versions = set()
169-
names = set(name for name, _version in sorted(required_name_versions))
170-
for name in sorted(names):
171-
latests = utils_thirdparty.PypiPackage.sorted(
172-
utils_thirdparty.get_package_versions(
173-
name=name, version=None, index_urls=index_urls
174-
)
175-
)
176-
if not latests:
177-
print(f"No distribution found for: {name}")
178-
continue
179-
latest = latests[-1]
180-
latest_name_versions.add((latest.name, latest.version))
181-
required_name_versions = latest_name_versions
182-
183-
if TRACE:
184-
print("required_name_versions:", required_name_versions)
182+
if TRACE_DEEP:
183+
print("required_name_versions:")
184+
for n, v in required_name_versions:
185+
print(f" {n} @ {v}")
185186

187+
# create the environments matrix we need for wheels
188+
environments = None
186189
if wheels:
187-
# create the environments matrix we need for wheels
188190
evts = itertools.product(python_versions, operating_systems)
189191
environments = [utils_thirdparty.Environment.from_pyver_and_os(pyv, os) for pyv, os in evts]
190192

191-
wheels_not_found = {}
192-
sdists_not_found = {}
193-
# iterate over requirements, one at a time
193+
# Collect PyPI repos
194+
repos = []
195+
for index_url in index_urls:
196+
index_url = index_url.strip("/")
197+
existing = utils_thirdparty.DEFAULT_PYPI_REPOS_BY_URL.get(index_url)
198+
if existing:
199+
existing.use_cached_index = use_cached_index
200+
repos.append(existing)
201+
else:
202+
repo = utils_thirdparty.PypiSimpleRepository(
203+
index_url=index_url,
204+
use_cached_index=use_cached_index,
205+
)
206+
repos.append(repo)
207+
208+
wheels_fetched = []
209+
wheels_not_found = []
210+
211+
sdists_fetched = []
212+
sdists_not_found = []
213+
194214
for name, version in sorted(required_name_versions):
195215
nv = name, version
196-
existing_package = existing_packages_by_nv.get(nv)
216+
print(f"Processing: {name} @ {version}")
197217
if wheels:
198218
for environment in environments:
199-
if existing_package:
200-
existing_wheels = list(
201-
existing_package.get_supported_wheels(environment=environment)
202-
)
203-
else:
204-
existing_wheels = None
205-
206-
if existing_wheels:
207-
if TRACE:
208-
print(
209-
f"====> Wheels already available: {name}=={version} on: {environment}: {existing_package.wheels!r}"
210-
)
211-
if all(w.is_pure() for w in existing_wheels):
212-
break
213-
else:
214-
continue
215-
216219
if TRACE:
217-
print(f"Fetching wheel for: {name}=={version} on: {environment}")
218-
219-
try:
220-
(
221-
fetched_wheel_filenames,
222-
existing_wheel_filenames,
223-
) = utils_thirdparty.download_wheel(
224-
name=name,
225-
version=version,
226-
environment=environment,
227-
dest_dir=dest_dir,
228-
index_urls=index_urls,
229-
)
230-
if TRACE:
231-
if existing_wheel_filenames:
232-
print(
233-
f" ====> Wheels already available: {name}=={version} on: {environment}"
234-
)
235-
for whl in existing_wheel_filenames:
236-
print(f" {whl}")
237-
if fetched_wheel_filenames:
238-
print(f" ====> Wheels fetched: {name}=={version} on: {environment}")
239-
for whl in fetched_wheel_filenames:
240-
print(f" {whl}")
241-
242-
fwfns = fetched_wheel_filenames + existing_wheel_filenames
243-
244-
if all(utils_thirdparty.Wheel.from_filename(f).is_pure() for f in fwfns):
245-
break
246-
247-
except utils_thirdparty.DistributionNotFound as e:
248-
wheels_not_found[f"{name}=={version}"] = str(e)
249-
250-
if sdists:
251-
if existing_package and existing_package.sdist:
252-
if TRACE:
253-
print(
254-
f" ====> Sdist already available: {name}=={version}: {existing_package.sdist!r}"
255-
)
256-
continue
257-
258-
if TRACE:
259-
print(f" Fetching sdist for: {name}=={version}")
260-
261-
try:
262-
fetched = utils_thirdparty.download_sdist(
220+
print(f" ==> Fetching wheel for envt: {environment}")
221+
fwfns = utils_thirdparty.download_wheel(
263222
name=name,
264223
version=version,
224+
environment=environment,
265225
dest_dir=dest_dir,
266-
index_urls=index_urls,
226+
repos=repos,
267227
)
228+
if fwfns:
229+
wheels_fetched.extend(fwfns)
230+
else:
231+
wheels_not_found.append(f"{name}=={version} for: {environment}")
232+
if TRACE:
233+
print(f" NOT FOUND")
268234

235+
if sdists:
236+
if TRACE:
237+
print(f" ==> Fetching sdist: {name}=={version}")
238+
fetched = utils_thirdparty.download_sdist(
239+
name=name,
240+
version=version,
241+
dest_dir=dest_dir,
242+
repos=repos,
243+
)
244+
if fetched:
245+
sdists_fetched.append(fetched)
246+
else:
247+
sdists_not_found.append(f"{name}=={version}")
269248
if TRACE:
270-
if not fetched:
271-
print(
272-
f" ====> Sdist already available: {name}=={version}"
273-
)
274-
else:
275-
print(
276-
f" ====> Sdist fetched: {fetched} for {name}=={version}"
277-
)
278-
279-
except utils_thirdparty.DistributionNotFound as e:
280-
sdists_not_found[f"{name}=={version}"] = str(e)
249+
print(f" NOT FOUND")
281250

282251
if wheels and wheels_not_found:
283252
print(f"==> MISSING WHEELS")
@@ -290,7 +259,7 @@ def fetch_thirdparty(
290259
print(f" {sd}")
291260

292261
print(f"==> FETCHING OR CREATING ABOUT AND LICENSE FILES")
293-
utils_thirdparty.fetch_abouts_and_licenses(dest_dir=dest_dir)
262+
utils_thirdparty.fetch_abouts_and_licenses(dest_dir=dest_dir, use_cached_index=use_cached_index)
294263
utils_thirdparty.clean_about_files(dest_dir=dest_dir)
295264

296265
# check for problems

etc/scripts/gen_pypi_simple.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,26 +25,26 @@ class InvalidDistributionFilename(Exception):
2525

2626
def get_package_name_from_filename(filename):
2727
"""
28-
Return the package name extracted from a package ``filename``.
29-
Optionally ``normalize`` the name according to distribution name rules.
28+
Return the normalized package name extracted from a package ``filename``.
29+
Normalization is done according to distribution name rules.
3030
Raise an ``InvalidDistributionFilename`` if the ``filename`` is invalid::
3131
3232
>>> get_package_name_from_filename("foo-1.2.3_rc1.tar.gz")
3333
'foo'
34-
>>> get_package_name_from_filename("foo-bar-1.2-py27-none-any.whl")
34+
>>> get_package_name_from_filename("foo_bar-1.2-py27-none-any.whl")
3535
'foo-bar'
3636
>>> get_package_name_from_filename("Cython-0.17.2-cp26-none-linux_x86_64.whl")
3737
'cython'
3838
>>> get_package_name_from_filename("python_ldap-2.4.19-cp27-none-macosx_10_10_x86_64.whl")
3939
'python-ldap'
40-
>>> get_package_name_from_filename("foo.whl")
41-
Traceback (most recent call last):
42-
...
43-
InvalidDistributionFilename: ...
44-
>>> get_package_name_from_filename("foo.png")
45-
Traceback (most recent call last):
46-
...
47-
InvalidFilePackageName: ...
40+
>>> try:
41+
... get_package_name_from_filename("foo.whl")
42+
... except InvalidDistributionFilename:
43+
... pass
44+
>>> try:
45+
... get_package_name_from_filename("foo.png")
46+
... except InvalidDistributionFilename:
47+
... pass
4848
"""
4949
if not filename or not filename.endswith(dist_exts):
5050
raise InvalidDistributionFilename(filename)

etc/scripts/requirements.txt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
aboutcode_toolkit
2-
github-release-retry2
32
attrs
43
commoncode
54
click
65
requests
76
saneyaml
8-
romp
97
pip
108
setuptools
119
twine
12-
wheel
10+
wheel
11+
build

etc/scripts/utils_requirements.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,23 +41,23 @@ def get_required_name_versions(requirement_lines, with_unpinned=False):
4141
if req_line.startswith("-") or (not with_unpinned and not "==" in req_line):
4242
print(f"Requirement line is not supported: ignored: {req_line}")
4343
continue
44-
yield get_name_version(requirement=req_line, with_unpinned=with_unpinned)
44+
yield get_required_name_version(requirement=req_line, with_unpinned=with_unpinned)
4545

4646

47-
def get_name_version(requirement, with_unpinned=False):
47+
def get_required_name_version(requirement, with_unpinned=False):
4848
"""
4949
Return a (name, version) tuple given a`requirement` specifier string.
5050
Requirement version must be pinned. If ``with_unpinned`` is True, unpinned
5151
requirements are accepted and only the name portion is returned.
5252
5353
For example:
54-
>>> assert get_name_version("foo==1.2.3") == ("foo", "1.2.3")
55-
>>> assert get_name_version("fooA==1.2.3.DEV1") == ("fooa", "1.2.3.dev1")
56-
>>> assert get_name_version("foo==1.2.3", with_unpinned=False) == ("foo", "1.2.3")
57-
>>> assert get_name_version("foo", with_unpinned=True) == ("foo", "")
58-
>>> assert get_name_version("foo>=1.2", with_unpinned=True) == ("foo", ""), get_name_version("foo>=1.2")
54+
>>> assert get_required_name_version("foo==1.2.3") == ("foo", "1.2.3")
55+
>>> assert get_required_name_version("fooA==1.2.3.DEV1") == ("fooa", "1.2.3.dev1")
56+
>>> assert get_required_name_version("foo==1.2.3", with_unpinned=False) == ("foo", "1.2.3")
57+
>>> assert get_required_name_version("foo", with_unpinned=True) == ("foo", "")
58+
>>> assert get_required_name_version("foo>=1.2", with_unpinned=True) == ("foo", ""), get_required_name_version("foo>=1.2")
5959
>>> try:
60-
... assert not get_name_version("foo", with_unpinned=False)
60+
... assert not get_required_name_version("foo", with_unpinned=False)
6161
... except Exception as e:
6262
... assert "Requirement version must be pinned" in str(e)
6363
"""
@@ -110,6 +110,8 @@ def get_installed_reqs(site_packages_dir):
110110
Return the installed pip requirements as text found in `site_packages_dir`
111111
as a text.
112112
"""
113+
if not os.path.exists(site_packages_dir):
114+
raise Exception(f"site_packages directory: {site_packages_dir!r} does not exists")
113115
# Also include these packages in the output with --all: wheel, distribute,
114116
# setuptools, pip
115117
args = ["pip", "freeze", "--exclude-editable", "--all", "--path", site_packages_dir]

0 commit comments

Comments
 (0)