From ee42c7fea847b26a8560a6ee66faa2cb4d1dc6d4 Mon Sep 17 00:00:00 2001 From: Dan LaManna Date: Fri, 30 Oct 2026 07:49:31 -0400 Subject: [PATCH 1/2] Build release binaries with a uv-managed Python MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The macOS and Windows packaging jobs resolve "3.12" to the python.org build that ships on the GitHub runners (/usr/local/bin/python3.12) rather than downloading a python-build-standalone interpreter. python.org builds keep the stdlib's C extensions as ~50 separate lib-dynload/*.so files plus libssl and libcrypto, while python-build-standalone compiles them into libpython. That matters on macOS because the onefile binary extracts every shared library into a fresh temp directory on each launch, and the first load of a freshly written Mach-O file costs ~120ms (dyld blocks in fcntl while the kernel runs its first-execution checks). The released v12.7.0 macOS binary loads 49 such files before printing --version. Timing of `isic --version` (hyperfine, 10 runs after 2 warmups, Apple M2 Max, macOS 15.8). Homebrew's Python 3.14 has the same split-stdlib layout as the python.org build and stands in for it: | build | libs loaded | median | mean ± sd | min | max | |-------------------------------------------------|-------------|--------|---------------|-------|-------| | master, Homebrew Python 3.14 (split stdlib) | 51 | 6.51s | 6.50s ± 0.02 | 6.47s | 6.55s | | master, uv-managed Python 3.14 (this change) | 6 | 1.48s | 1.49s ± 0.02 | 1.45s | 1.51s | For reference the released v12.7.0 macOS binary measures 6.3s on the same machine. --- .github/workflows/package.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 26a6a7e..bb2fa60 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -35,6 +35,7 @@ jobs: - name: Run packaging step env: UV_PYTHON: "3.12" + UV_PYTHON_PREFERENCE: only-managed ISIC_CLI_SENTRY_DSN: ${{ secrets.ISIC_CLI_SENTRY_DSN }} run: | uv run tox -e package @@ -71,6 +72,11 @@ jobs: uv run tox -e package env: ISIC_CLI_SENTRY_DSN: ${{ secrets.ISIC_CLI_SENTRY_DSN }} + # the runners ship a python.org build of Python on PATH, which uv picks over downloading + # a managed one. python.org builds split the stdlib into ~50 separate extension modules, + # and on macOS every freshly extracted shared library costs ~120ms per launch of the + # onefile binary. python-build-standalone compiles them into libpython. + UV_PYTHON_PREFERENCE: only-managed - name: Zip and upload binary run: | .github/zip_and_upload_package.sh ${{ runner.os }} ${{ github.event.release.tag_name }} From 2f48fb2e449be0cd1ec717d9903e4e1ae33c31a8 Mon Sep 17 00:00:00 2001 From: Dan LaManna Date: Fri, 30 Oct 2026 07:54:19 -0400 Subject: [PATCH 2/2] Build charset_normalizer from source for the PyInstaller bundle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit charset_normalizer wheels ship two mypyc-compiled extension modules (cd and md) alongside their pure python fallbacks. On macOS, every shared library the onefile binary extracts costs ~120ms on each launch (the first load of a freshly written Mach-O file blocks in dyld while the kernel runs its first-execution checks), and the size of the library barely matters: these two total under 1MB but cost ~240ms in `-X importtime` inside the frozen binary versus ~4ms unfrozen. Installing charset_normalizer from its sdist in the package env gives the pure python modules (the sdist only builds the mypyc extensions when CHARSET_NORMALIZER_USE_MYPYC=1). Only requests uses it, for guessing the encoding of responses without a charset, which isn't on any hot path here. Timing of `isic --version` (hyperfine, 10 runs after 2 warmups, two rounds each, Apple M2 Max, macOS 15.8, uv-managed Python 3.14): | build | libs loaded | median | mean ± sd | min | max | |--------------------------------|-------------|--------|--------------|-------|-------| | previous commit | 6 | 1.53s | 1.55s ± 0.07 | 1.47s | 1.70s | | previous commit, second round | 6 | 1.51s | 1.52s ± 0.04 | 1.46s | 1.61s | | this commit | 4 | 1.23s | 1.23s ± 0.02 | 1.19s | 1.27s | | this commit, second round | 4 | 1.23s | 1.23s ± 0.02 | 1.18s | 1.26s | --- tox.ini | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tox.ini b/tox.ini index 32c910f..4ac6edc 100644 --- a/tox.ini +++ b/tox.ini @@ -45,6 +45,12 @@ passenv = ISIC_CLI_SENTRY_DSN dependency_groups = package +# charset_normalizer ships mypyc-compiled extensions with pure python fallbacks. on macOS, each +# shared library extracted by the onefile binary costs ~120ms per launch, so build it from source +# to get the pure python version instead. +uv_sync_flags = + --no-binary-package + charset-normalizer commands = python scripts/write_sentry_dsn_module.py {env_tmp_dir}/sentry_dsn/_isic_cli_sentry_dsn.py pyinstaller \