Skip to content

add a script to find and apply package updates#1159

Open
jjhelmus wants to merge 1 commit into
mainfrom
jjh/update-script
Open

add a script to find and apply package updates#1159
jjhelmus wants to merge 1 commit into
mainfrom
jjh/update-script

Conversation

@jjhelmus

@jjhelmus jjhelmus commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Add scripts/update_downloads.py, which finds updates to the entries in pythonbuild/downloads.py. The optional --write argument write any updates, including calculated metadata to the file.

Run using:

uv run scripts/update_downloads.py

Add scripts/update_downloads.py, which finds updates to the entries
to pythonbuild/downloads.py. The optional --write argument will write
the necessary updates to the file.

Run using:

    uv run scripts/update_downloads.py
@jjhelmus

Copy link
Copy Markdown
Contributor Author

This script was largely AI generated using Codex. The prompt that began the session was:

Write a Python script that can find possible updated versions of the packages in pythonbuild/downloads.py. The script should have options to list update new versions and then optionally make the necessary changes to pythonbuild/downloads.py. Have the process that checks for new versions be flexible as the projects have different constraints on versions and some are sourced from mirrors and the upstream URL must be checked rather than the mirror.

I have used this script to kick off many of the recent update including #1153, #1156, and #1157.

I plan on testing it with the upcoming 3.15.0b3 release.

@jjhelmus

Copy link
Copy Markdown
Contributor Author

Should have tagged this with ci:skip but CI is already running.

This work could be expanded to include tests and an actions to run + apply changes on a regular schedule. That can be done later if needed.

@jjhelmus

Copy link
Copy Markdown
Contributor Author

Example results:

❯ uv run scripts/update_downloads.py 
autoconf: 2.72 -> 2.73 (mirrored)
  https://ftp.gnu.org/gnu/autoconf/autoconf-2.73.tar.gz
binutils: 2.43 -> 2.46.1 (mirrored)
  https://ftp.gnu.org/gnu/binutils/binutils-2.46.1.tar.xz
bzip2: 1.0.8 (current)
cpython-3.10: 3.10.20 (current)
cpython-3.11: 3.11.15 (current)
cpython-3.12: 3.12.13 (current)
cpython-3.13: 3.13.14 (current)
cpython-3.14: 3.14.6 (current)
cpython-3.15: 3.15.0b2 (current)
expat: 2.8.1 (current)
libedit: 20240808-3.1 -> 20260512-3.1
  https://thrysoee.dk/editline/libedit-20260512-3.1.tar.gz
libffi: 3.4.6 -> 3.4.8
  https://github.com/libffi/libffi/releases/download/v3.4.8/libffi-3.4.8.tar.gz
libpthread-stubs: 0.5 (current)
libX11: 1.8.13 (current)
libXau: 1.0.12 (current)
libxcb: 1.17.0 (current)
m4: 1.4.19 -> 1.4.21 (mirrored)
  https://ftp.gnu.org/gnu/m4/m4-1.4.21.tar.xz
mpdecimal: 4.0.0 -> 4.0.1 (mirrored)
  https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-4.0.1.tar.gz
nasm-windows-bin: 2.16.03 -> 3.01 (mirrored)
  https://www.nasm.us/pub/nasm/releasebuilds/3.01/win64/nasm-3.01-win64.zip
ncurses: 6.5 -> 6.6 (mirrored)
  https://ftp.gnu.org/gnu/ncurses/ncurses-6.6.tar.gz
openssl-3.5: 3.5.7 (current)
patchelf: 0.13.1 -> 0.18.0
  https://github.com/NixOS/patchelf/releases/download/0.18.0/patchelf-0.18.0.tar.bz2
pip: 26.1.2 (current)
setuptools: 82.0.1 (current)
tcl: 9.0.3 (current)
tk: 9.0.3 (current)
x11-util-macros: 1.20.2 (current)
xcb-proto: 1.17.0 (current)
xorgproto: 2025.1 (current)
xtrans: 1.6.0 (current)
xz: 5.8.3 (current)
zlib: 1.3.2 (current)

@jjhelmus jjhelmus requested a review from zanieb June 18, 2026 17:01
@jjhelmus

Copy link
Copy Markdown
Contributor Author

This worked well to start the 3.15.0b3 update:

❯ uv run scripts/update_downloads.py cpython-3.15 --write
cpython-3.15: 3.15.0b2 -> 3.15.0b3
  https://www.python.org/ftp/python/3.15.0/Python-3.15.0b3.tar.xz
downloading cpython-3.15 3.15.0b3
updated /Users/jjhelmus/oss/again/python-build-standalone/pythonbuild/downloads.py: cpython-3.15

❯ git diff
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 11ec23d..d592f7a 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -93,10 +93,10 @@ DOWNLOADS = {
         "python_tag": "cp314",
     },
     "cpython-3.15": {
-        "url": "https://www.python.org/ftp/python/3.15.0/Python-3.15.0b2.tar.xz",
-        "size": 35381676,
-        "sha256": "d14f474ab679e90bc734b02ff58447b6ec99a821af61d6ff0c1da0f86e341a71",
-        "version": "3.15.0b2",
+        "url": "https://www.python.org/ftp/python/3.15.0/Python-3.15.0b3.tar.xz",
+        "size": 35459584,
+        "sha256": "6a935ae234a67e6549894373b0cfeb8361182d03b21442328ae9598ab7422127",
+        "version": "3.15.0b3",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp315",

@geofft geofft left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This generally seems good to me, although I only applied the level of review I would to human-authored code.

Can you extend it to 1) push to the mirror with GITHUB_TOKEN if it needs to mirror something and 2) update wanted_version in the OpenSSL test case, as the comments on the OpenSSL downloads instruct (or do something equivalent, like have the test case import this file)?

Comment on lines +473 to +480
def artifact_metadata(client: HttpClient, url: str) -> tuple[int, str]:
digest = hashlib.sha256()
size = 0
with client.open(url) as response:
while chunk := response.read(1024 * 1024):
size += len(chunk)
digest.update(chunk)
return size, digest.hexdigest()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some upstreams have .sha256 files etc. that we can optionally use to make the process a little faster.

return urllib.parse.urljoin(MIRROR_BASE_URL, filename)


def _line_offsets(source: str) -> list[int]:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole next section to handle modifying the Python source in place is clever, and I suppose harmless in the brave new world, but I would have been inclined to do something like
a) turn inline comments into actual data
b) ensure that the file is formatted in some predictable way right now, and regenerate the file in that same way (either by generating it that way in the first place, or running ruff after outputting, or whatever)

I think it also would be reasonable to turn the file into JSON or YAML or something instead of Python, if that's helpful, but I suppose ast is fine with Python.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants