Skip to content

Commit 52c05c3

Browse files
committed
First attempt to update urllib3
1 parent e8bbdd8 commit 52c05c3

2 files changed

Lines changed: 110 additions & 11 deletions

File tree

.pre-commit-hooks/copyright_headers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/env python3
2-
# Copyright 2025 Broadcom.
2+
# Copyright 2025-2026 Broadcom.
33
# SPDX-License-Identifier: Apache-2.0
44
#
55
# pylint: disable=invalid-name,missing-module-docstring,missing-function-docstring

relenv/build/common/install.py

Lines changed: 109 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
# Copyright 2022-2025 Broadcom.
1+
# Copyright 2022-2026 Broadcom.
22
# SPDX-License-Identifier: Apache-2.0
33
"""
44
Installation and finalization functions for the build process.
55
"""
66
from __future__ import annotations
77

8+
import base64
89
import fnmatch
910
import hashlib
1011
import io
@@ -18,6 +19,7 @@
1819
import shutil
1920
import sys
2021
import tarfile
22+
import zipfile
2123
from types import ModuleType
2224
from typing import IO, MutableMapping, Optional, Sequence, Union, TYPE_CHECKING
2325

@@ -27,6 +29,7 @@
2729
MissingDependencyError,
2830
Version,
2931
download_url,
32+
extract_archive,
3033
format_shebang,
3134
runcmd,
3235
)
@@ -246,8 +249,22 @@ def update_ensurepip(directory: pathlib.Path) -> None:
246249

247250
# Detect existing whl. Later versions of python don't include setuptools. We
248251
# only want to update whl files that python expects to be there
249-
pip_version = "25.2"
252+
pip_version = "25.3"
253+
pip_whl = f"pip-{pip_version}-py3-none-any.whl"
254+
pip_whl_path = "44/3c/d717024885424591d5376220b5e836c2d5293ce2011523c9de23ff7bf068"
255+
250256
setuptools_version = "80.9.0"
257+
setuptools_whl = f"setuptools-{setuptools_version}-py3-none-any.whl"
258+
setuptools_whl_path = (
259+
"a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772"
260+
)
261+
262+
urllib3_version = "2.6.2"
263+
urllib3_tarball = f"urllib3-{urllib3_version}.tar.gz"
264+
urllib3_tarball_path = (
265+
"1e/24/a2a2ed9addd907787d7aa0355ba36a6cadf1768b934c652ea78acbd59dcd"
266+
)
267+
251268
update_pip = False
252269
update_setuptools = False
253270
for file in bundle_dir.glob("*.whl"):
@@ -275,11 +292,9 @@ def update_ensurepip(directory: pathlib.Path) -> None:
275292
# Download whl files and update __init__.py
276293
init_file = directory / "ensurepip" / "__init__.py"
277294
if update_pip:
278-
whl = f"pip-{pip_version}-py3-none-any.whl"
279-
whl_path = "b7/3f/945ef7ab14dc4f9d7f40288d2df998d1837ee0888ec3659c813487572faa"
280-
url = f"https://files.pythonhosted.org/packages/{whl_path}/{whl}"
295+
url = f"https://files.pythonhosted.org/packages/{pip_whl_path}/{pip_whl}"
281296
download_url(url=url, dest=bundle_dir)
282-
assert (bundle_dir / whl).exists()
297+
assert (bundle_dir / pip_whl).exists()
283298

284299
# Update __init__.py
285300
old = "^_PIP_VERSION.*"
@@ -288,11 +303,9 @@ def update_ensurepip(directory: pathlib.Path) -> None:
288303

289304
# setuptools
290305
if update_setuptools:
291-
whl = f"setuptools-{setuptools_version}-py3-none-any.whl"
292-
whl_path = "a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772"
293-
url = f"https://files.pythonhosted.org/packages/{whl_path}/{whl}"
306+
url = f"https://files.pythonhosted.org/packages/{setuptools_whl_path}/{setuptools_whl}"
294307
download_url(url=url, dest=bundle_dir)
295-
assert (bundle_dir / whl).exists()
308+
assert (bundle_dir / setuptools_whl).exists()
296309

297310
# setuptools
298311
old = "^_SETUPTOOLS_VERSION.*"
@@ -302,6 +315,92 @@ def update_ensurepip(directory: pathlib.Path) -> None:
302315
log.debug("ensurepip __init__.py contents:")
303316
log.debug(init_file.read_text())
304317

318+
# TODO: unpack the pip whl using zipfile (wheel isn't installed yet)
319+
pip_whl_extracted = bundle_dir / "pip_whl_extracted"
320+
with zipfile.ZipFile(bundle_dir / pip_whl) as whl_file:
321+
whl_file.extractall(path=pip_whl_extracted)
322+
323+
# TODO: pull down urllib3 tarball
324+
url = f"https://files.pythonhosted.org/packages/{urllib3_tarball_path}/{urllib3_tarball}"
325+
download_url(url=url, dest=bundle_dir)
326+
assert (bundle_dir / urllib3_tarball).exists()
327+
328+
# TODO: Extract the tarball
329+
urllib3_extracted = bundle_dir / "urllib3_extracted"
330+
extract_archive(to_dir=urllib3_extracted, archive=bundle_dir / urllib3_tarball)
331+
332+
# TODO: replace urllib3 in pip
333+
# Delete target urllib3
334+
urllib3_target_dir = (
335+
bundle_dir
336+
/ pip_whl_extracted
337+
/ f"pip-{pip_version}"
338+
/ "pip"
339+
/ "_vendor"
340+
/ "urllib3"
341+
)
342+
urllib3_source_dir = urllib3_extracted / "src" / "urllib3"
343+
try:
344+
shutil.rmtree(urllib3_target_dir)
345+
log.debug("Removed urllib3 target directory: %s", urllib3_target_dir)
346+
except OSError:
347+
log.debug("Failed to remove urllib3 target directory: %s", urllib3_target_dir)
348+
349+
# Move source urllib3 to target
350+
urllib3_source_dir.rename(urllib3_target_dir)
351+
352+
# Cleanup urllib3 source and tarball
353+
shutil.rmtree(urllib3_extracted)
354+
(bundle_dir / urllib3_tarball).unlink(missing_ok=True)
355+
356+
# TODO: recompute the hashes and update dist-info\RECORD
357+
def get_record_entry(file_path, root_dir):
358+
# 1. Calculate SHA256 and Size
359+
sha256 = hashlib.sha256()
360+
size = os.path.getsize(file_path)
361+
362+
with open(file_path, "rb") as f:
363+
while chunk := f.read(8192):
364+
sha256.update(chunk)
365+
366+
# 2. Encode to URL-safe Base64 and remove padding '='
367+
hash_base64 = (
368+
base64.urlsafe_b64encode(sha256.digest()).decode("latin1").rstrip("=")
369+
)
370+
371+
# 3. Create relative path for RECORD
372+
rel_path = os.path.relpath(file_path, root_dir).replace(os.sep, "/")
373+
374+
return f"{rel_path},sha256={hash_base64},{size}"
375+
376+
pip_src_dir = pip_whl_extracted / f"pip-{pip_version}"
377+
# delete existing RECORD file
378+
records_file = pip_src_dir / f"pip-{pip_version}.dist-info" / "RECORD"
379+
records_file.unlink(missing_ok=True)
380+
# create new RECORD file
381+
files_list = [f for f in pip_src_dir.rglob("*") if f.is_file()]
382+
with open(records_file, "w") as f:
383+
for file in files_list:
384+
f.write(get_record_entry(file, root_dir=pip_src_dir) + "\n")
385+
# This is the last line. It shouldn't be there because we removed the
386+
# RECORD file before we listed all files
387+
f.write(f"pip-{pip_version}.dist-info/RECORD,,")
388+
assert records_file.exists()
389+
390+
# TODO: pack the pip whl
391+
(bundle_dir / pip_whl).unlink(missing_ok=True)
392+
# We need to do this again so we include the RECORD file
393+
files_list = [f for f in pip_src_dir.rglob("*") if f.is_file()]
394+
with zipfile.ZipFile(bundle_dir / pip_whl, "w", zipfile.ZIP_DEFLATED) as whl_file:
395+
for file in files_list:
396+
arc_name = file.relative_to(pip_src_dir)
397+
whl_file.write(file, arc_name)
398+
assert (bundle_dir / pip_whl).exists()
399+
400+
# TODO: Clean up extracted pip
401+
shutil.rmtree(pip_whl_extracted)
402+
assert not pip_whl_extracted.exists()
403+
305404

306405
def install_sysdata(
307406
mod: ModuleType,

0 commit comments

Comments
 (0)