Repository navigation
v3.0.3 - NumPy 2.5.3 Upgrade — Complete Technical Explanation
① Overview of the NumPy latest-version upgrade
1. Background (state before the change)
- The NumPy in the venv was 2.4.6. The task was to update it to the latest release, 2.5.3.
- The requirement files
requirements_versions_py314*.txtwere already updated tonumpy==2.5.3in the working tree (HEAD isnumpy==2.4.6). - However,
modules/launch_utils.pyforcibly pinned NumPy to2.4.6at every startup, so even after raising the requirements the environment was reverted to 2.4.6 on each launch. That pin was the effective "setting", and it had to be raised together with the requirement files.
2. Latest versions (confirmed on PyPI)
| Package | Before | After | PyPI latest |
|---|---|---|---|
| numpy | 2.4.6 | 2.5.3 | 2.5.3 |
| numba | 0.66.0 | 0.67.0 | 0.67.0 |
| llvmlite | 0.48.0 | 0.49.0 | 0.49.0 |
pip index versions confirmed the latest NumPy is 2.5.3 and the latest numba is 0.67.0.
3. What was changed
- venv packages
- Installed
numpy==2.5.3(numpy-2.5.3-cp314-cp314-win_amd64.whl). - Upgraded numba to the latest:
numba 0.66.0 → 0.67.0(withllvmlite 0.48.0 → 0.49.0). - numba 0.67.0 requires
numpy<2.6,>=1.22, so it coexists with numpy 2.5.3. When resolved together with numpy 2.5.3, this combination is selected automatically (pip install --dry-runshowsWould install llvmlite-0.49.0 numba-0.67.0 numpy-2.5.3).
- Installed
- Configuration side (in-code pin) aligned
- Changed the NumPy force-pin in
modules/launch_utils.pyfrom2.4.6 → 2.5.3(three install sites plus related messages/comments).
- Changed the NumPy force-pin in
4. Verification results
numpy 2.5.3/numba 0.67.0/llvmlite 0.49.0all import successfully.facexlib 0.3.0(the package that depends on numba) imports successfully.python -m pip check: the numba/NumPy conflict is resolved.ast.parsesyntax check onlaunch_utils.pypasses.- No remaining
2.4.6in the file (0 occurrences). No line-ending (EOL) changes.
Note: The following two
pip checkitems are pre-existing and unrelated to the NumPy upgrade:
k-diffusion 0.0.16 → wandb not installedpydantic-settings 2.15.0 → requires pydantic>=2.7.0 (currently 1.10.25)
② Files created / modified
Modified files
| File | Change |
|---|---|
modules/launch_utils.py |
NumPy force-pin changed 2.4.6 → 2.5.3 |
requirements_versions_py314.txt |
numpy==2.4.6 → numpy==2.5.3 (updated in working tree) |
requirements_versions_py314_windows.txt |
numpy==2.4.6 → numpy==2.5.3 (updated in working tree) |
Created files
| File | Kind | Content |
|---|---|---|
md/NUMPY_253_PIN_UPDATE_2026-09-17.md |
Deliverable | This document |
Packages updated in the venv
venv/Lib/site-packages/numpy:2.4.6 → 2.5.3venv/Lib/site-packages/numba:0.66.0 → 0.67.0venv/Lib/site-packages/llvmlite:0.48.0 → 0.49.0
③ Full text of created / modified code
3-1. modules/launch_utils.py (modified, before → after)
Before (HEAD)
run_pip("install --upgrade packaging", "packaging")
# Pin numpy==2.4.6 before -r (numba / facexlib compatible; not 2.5.x).
# Install early so already-imported modules do not keep a stale numpy.
run(f'"{python}" -m pip uninstall numpy -y', "uninstalling numpy", "Couldn't uninstall numpy", live=False)
run(f'"{python}" -m pip install --no-cache-dir numpy==2.4.6', "Installing numpy 2.4.6", "Couldn't install numpy 2.4.6", live=False)
print("[INFO] Installed numpy==2.4.6 from PyPI")After
run_pip("install --upgrade packaging", "packaging")
# Pin numpy==2.5.3 before -r.
# Install early so already-imported modules do not keep a stale numpy.
run(f'"{python}" -m pip uninstall numpy -y', "uninstalling numpy", "Couldn't uninstall numpy", live=False)
run(f'"{python}" -m pip install --no-cache-dir numpy==2.5.3', "Installing numpy 2.5.3", "Couldn't install numpy 2.5.3", live=False)
print("[INFO] Installed numpy==2.5.3 from PyPI")Before (HEAD)
# scipy via PyPI to match numpy 2.4.6
run(f'"{python}" -m pip uninstall scipy -y', "uninstalling scipy", "Couldn't uninstall scipy", live=False)
run(f'"{python}" -m pip install --no-cache-dir scipy==1.16.1', "Installing scipy 1.16.1", "Couldn't install scipy 1.16.1", live=False)
print("[INFO] Installed scipy 1.16.1 from PyPI")After
# scipy via PyPI to match numpy 2.5.3
run(f'"{python}" -m pip uninstall scipy -y', "uninstalling scipy", "Couldn't uninstall scipy", live=False)
run(f'"{python}" -m pip install --no-cache-dir scipy==1.16.1', "Installing scipy 1.16.1", "Couldn't install scipy 1.16.1", live=False)
print("[INFO] Installed scipy 1.16.1 from PyPI")Before (HEAD)
if not args.skip_install:
run_extensions_installers(settings_file=args.ui_settings_file)
# Keep pin if an extension installer drifted numpy.
run(f'"{python}" -m pip install --force-reinstall --no-deps --no-cache-dir numpy==2.4.6', "re-pin: numpy 2.4.6", "Couldn't install numpy 2.4.6", live=False)
print("[INFO] Re-pinned numpy==2.4.6 after extensions")After
if not args.skip_install:
run_extensions_installers(settings_file=args.ui_settings_file)
# Keep pin if an extension installer drifted numpy.
run(f'"{python}" -m pip install --force-reinstall --no-deps --no-cache-dir numpy==2.5.3', "re-pin: numpy 2.5.3", "Couldn't install numpy 2.5.3", live=False)
print("[INFO] Re-pinned numpy==2.5.3 after extensions")Reference: git diff (actual diff)
@@ -730,11 +730,11 @@ def prepare_environment():
run_pip("install --upgrade packaging", "packaging")
- # Pin numpy==2.4.6 before -r (numba / facexlib compatible; not 2.5.x).
+ # Pin numpy==2.5.3 before -r.
# Install early so already-imported modules do not keep a stale numpy.
run(f'"{python}" -m pip uninstall numpy -y', "uninstalling numpy", "Couldn't uninstall numpy", live=False)
- run(f'"{python}" -m pip install --no-cache-dir numpy==2.4.6', "Installing numpy 2.4.6", "Couldn't install numpy 2.4.6", live=False)
- print("[INFO] Installed numpy==2.4.6 from PyPI")
+ run(f'"{python}" -m pip install --no-cache-dir numpy==2.5.3', "Installing numpy 2.5.3", "Couldn't install numpy 2.5.3", live=False)
+ print("[INFO] Installed numpy==2.5.3 from PyPI")
# Gradio from HF (METADATA version pins removed)
run_pip(f'install "{gradio_package}"', "gradio")
@@ -746,7 +746,7 @@ def prepare_environment():
run_pip(f"install -U --upgrade-strategy only-if-needed -r \"{requirements_file}\"", "requirements")
startup_timer.record("install requirements")
- # scipy via PyPI to match numpy 2.4.6
+ # scipy via PyPI to match numpy 2.5.3
run(f'"{python}" -m pip uninstall scipy -y', "uninstalling scipy", "Couldn't uninstall scipy", live=False)
run(f'"{python}" -m pip install --no-cache-dir scipy==1.16.1', "Installing scipy 1.16.1", "Couldn't install scipy 1.16.1", live=False)
print("[INFO] Installed scipy 1.16.1 from PyPI")
@@ -806,8 +806,8 @@ def prepare_environment():
if not args.skip_install:
run_extensions_installers(settings_file=args.ui_settings_file)
# Keep pin if an extension installer drifted numpy.
- run(f'"{python}" -m pip install --force-reinstall --no-deps --no-cache-dir numpy==2.4.6', "re-pin: numpy 2.4.6", "Couldn't install numpy 2.4.6", live=False)
- print("[INFO] Re-pinned numpy==2.4.6 after extensions")
+ run(f'"{python}" -m pip install --force-reinstall --no-deps --no-cache-dir numpy==2.5.3', "re-pin: numpy 2.5.3", "Couldn't install numpy 2.5.3", live=False)
+ print("[INFO] Re-pinned numpy==2.5.3 after extensions")
if args.update_check:
version_check(commit)3-2. requirements_versions_py314.txt / requirements_versions_py314_windows.txt (modified)
Before (HEAD)
numpy==2.4.6
After
numpy==2.5.3
3-3. Replacement script (local, not committed)
The pin strings in modules/launch_utils.py were replaced with a short local Python script (byte-safe: read as bytes, decode UTF-8, replace, write back, so line endings are preserved). It is kept outside the repository and is not part of the commit.
P = "modules/launch_utils.py"
with open(P, "rb") as f:
raw = f.read()
s = raw.decode("utf-8")
reps = [
# 1) comment line: drop the now-false "not 2.5.x" rationale, pin 2.5.3
(
" # Pin numpy==2.4.6 before -r (numba / facexlib compatible; not 2.5.x).",
" # Pin numpy==2.5.3 before -r.",
),
# 2) exact version specifiers
("numpy==2.4.6", "numpy==2.5.3"),
# 3) human-readable messages / comments that spell the version with a space
("numpy 2.4.6", "numpy 2.5.3"),
]
for old, new in reps:
print(old, s.count(old))
s = s.replace(old, new)
with open(P, "wb") as f:
f.write(s.encode("utf-8"))
print("remaining 2.4.6:", [l for l in s.splitlines() if "2.4.6" in l])3-4. Commands executed
# 1) Inspect current state
& 'venv\Scripts\python.exe' -c "import sys, numpy; print(sys.version); print(numpy.__version__)"
# 2) Upgrade numpy to 2.5.3
& 'venv\Scripts\python.exe' -m pip install "numpy==2.5.3"
# 3) Upgrade numba to latest (resolved together with numpy)
& 'venv\Scripts\python.exe' -m pip install -U numba
# 4) Verify
& 'venv\Scripts\python.exe' -c "import numpy, numba, llvmlite; print(numpy.__version__, numba.__version__, llvmlite.__version__)"
& 'venv\Scripts\python.exe' -m pip check④ What it means
1. The two layers of version control were aligned
- In this project, the NumPy version is decided in two places:
- Requirements (declarative dependency):
requirements_versions_py314*.txt - The effective pin in the startup script:
modules/launch_utils.py
- Requirements (declarative dependency):
launch_utils.pyuninstalls and reinstalls NumPy at startup and, after the extension installers run, re-pins it. So even if requirements say 2.5.3, as long as this file said 2.4.6 the environment would roll back to 2.4.6 on every launch.- Therefore, to make "NumPy 2.5.3" actually stick, both layers must be set to 2.5.3. That is what was done here.
2. Meaning of each code change
pip uninstall numpy -y→pip install --no-cache-dir numpy==2.5.3- Fixes NumPy before requirements
-ris applied. Installing it early prevents already-imported modules from holding a stale NumPy.--no-cache-diravoids cache-driven inconsistencies.
- Fixes NumPy before requirements
# scipy via PyPI to match numpy 2.5.3- scipy is also reinstalled from PyPI so the pairing with NumPy stays consistent. Only the comment was updated (
scipy==1.16.1is unchanged).
- scipy is also reinstalled from PyPI so the pairing with NumPy stays consistent. Only the comment was updated (
--force-reinstall --no-deps numpy==2.5.3(after extension installers)- A safety net so that extension installs cannot drift NumPy to another version; it re-fixes NumPy to 2.5.3 after extensions are installed.
- Resolving
numbatogether with NumPy- numba depends tightly on NumPy (0.66.0 requires
numpy<2.5; 0.67.0 requiresnumpy<2.6). Resolved together with NumPy 2.5.3, the newest satisfying numba 0.67.0 (with llvmlite 0.49.0) is chosen automatically. Upgrading NumPy alone leaves the old numba 0.66.0 in place and produces a conflict warning, so upgrading them together is the correct procedure.
- numba depends tightly on NumPy (0.66.0 requires
3. Impact and risk
- numpy 2.5.3 coexists with numba 0.67.0, so facexlib (which depends on numba) and its face-restoration paths remain functional.
- The old comment "numba / facexlib compatible; not 2.5.x" no longer holds once 2.5.x is the target, so it was updated to match the facts.
- If anything goes wrong, restore your local pre-change copy of
modules/launch_utils.pyand reinstall the previous versions withpip install "numpy==2.4.6" "numba==0.66.0" "llvmlite==0.48.0".
4. Rollback procedure
# Restore modules/launch_utils.py from your local pre-change copy, then:
# Restore packages
& 'venv\Scripts\python.exe' -m pip install "numpy==2.4.6" "numba==0.66.0" "llvmlite==0.48.0"