py3-setuptools al corpus (GRATIS) + py3-pip: y mi regla de cascada era FALSA
⚠⚠ LO IMPORTANTE ES LA CORRECCIÓN, no las dos recetas.
Cuando medí la raíz de introspección de GNOME concluí que promoverla costaba 35
recetas rearmando. Eso era cierto para AQUEL conjunto, pero deduje de ahí una
regla que es falsa: que promover algo con muchos consumidores cascadea.
Medido hoy con py3-setuptools, que tiene 31 consumidores en incoming-gnome:
moverla al corpus cambió 0 de 92 hashes. Y ya estaba sellada al mismo hash, o
sea CERO reconstrucciones.
⇒ La cascada NO la causan los consumidores: la causan las deps PROPIAS del
promovido. glib-introspected cascadeaba porque depende de glib y en el corpus
encuentra la ESTÁTICA, que es otro artefacto. py3-setuptools sólo depende de
python3, que es el mismo desde los dos sitios, así que no había nada que
resolver distinto.
Corolario práctico: uno de los 6 bloqueos de orca acaba de caer gratis sin
tocar la decisión de GNOME, y conviene volver a medir los otros cinco UNO POR
UNO con este criterio — mi estimación de «35 recetas» pudo ser pesimista para
varios.
── POR QUÉ HACÍAN FALTA ──────────────────────────────────────────────────────
qemu las necesita, y el muro no era el que supuse. Comprobé antes de lanzar que
python3 tiene venv + ensurepip con su wheel de pip, así que el venv se crea
offline. Pero el configure hace, literalmente sin condición (configure:988):
# Unconditionally install our tooling group.
$mkvenv ensuregroup … pythondeps.toml tooling || exit 1
y el grupo [tooling] es qemu.qmp. qemu VENDORIZA ese wheel, pero para
desempaquetarlo pip arranca su trío de bootstrap y muere sin red.
La condición real está en mkvenv.py:244-251 —
if system_site_packages and not need_ensurepip():
kwargs["with_pip"] = False # usa pip Y setuptools del SISTEMA
else:
check_ensurepip() # acaba yendo al índice
— con need_ensurepip() = find_spec("setuptools") and find_spec("pip").
⚠ Y el detalle que lo hace inevitable: en Python 3.12 ensurepip YA NO incluye
setuptools, sólo pip. Por eso declarar py3-setuptools no alcanzó: qemu seguía
tomando la segunda rama, y el venv que ésa crea no hereda el setuptools del
sistema. Hacen falta LOS DOS importables.
py3-pip va en 25.0.1 a propósito: es exactamente la que python3 ya trae en
ensurepip/_bundled (medido). Otra versión dejaría dos pips en circulación y el
día que algo se comportara distinto según cuál tomó, nadie lo encontraría.
Y su guardián comprueba que find_spec("pip") lo ENCUENTRE —importándolo de
verdad y verificando la versión—, no que el directorio exista: ésa es
literalmente la pregunta que hace qemu, y un layout sin __init__.py la
respondería con None y mandaría el build al índice otra vez.
Semantic delta
No definition changed: this change is text, documentation or data.
2 files · +114 −0
- recipes/py3-pip.toml +77 −0
- recipes/py3-setuptools.toml +37 −0
diff --git a/recipes/py3-pip.toml b/recipes/py3-pip.toml
new file mode 100644
index 00000000..aa78201d
--- /dev/null
+++ b/recipes/py3-pip.toml
@@ -0,0 +1,77 @@
+# py3-pip 25.0.1 — el instalador de paquetes de Python, como MÓDULO IMPORTABLE del sistema.
+#
+# ══ POR QUÉ EXISTE, Y NO ES PARA INSTALAR NADA DE INTERNET ══════════════════════════════════════
+# Esta distro no baja paquetes de PyPI: el sandbox de `takana build` no tiene red, y eso es
+# deliberado. `pip` entra por una razón distinta y precisa: **hay builds que preguntan si `pip`
+# existe y cambian de camino según la respuesta.**
+#
+# El caso medido es `qemu` (2026-10-20). Su `configure` crea un entorno virtual y decide así
+# (`python/scripts/mkvenv.py:244-251`):
+#
+# if system_site_packages and not need_ensurepip():
+# kwargs["with_pip"] = False # ← usa el pip y setuptools DEL SISTEMA
+# else:
+# check_ensurepip() # ← crea su propio pip y acaba yendo al índice
+#
+# y `need_ensurepip()` es literalmente `find_spec("setuptools") and find_spec("pip")`. Con
+# `py3-setuptools` puesto pero sin `pip` importable, qemu tomaba la segunda rama y moría así:
+#
+# ERROR: Could not find a version that satisfies the requirement setuptools>=44.1.1
+# (from versions: none)
+#
+# ⚠ Y el detalle que lo hace inevitable: **en Python 3.12 `ensurepip` ya NO incluye setuptools**,
+# sólo pip. Así que la rama del `ensurepip` nunca puede completarse sin red, por mucho que
+# setuptools esté instalado en el sistema — el venv que crea no lo hereda.
+#
+# ⇒ Con `pip` importable, qemu toma la PRIMERA rama, no crea pip propio, y resuelve su wheel
+# vendorizado (`python/wheels/qemu_qmp-0.0.6-py3-none-any.whl`) con el pip del sistema. Sin red.
+#
+# ══ LA VERSIÓN NO ES «LA ÚLTIMA» A PROPÓSITO ═══════════════════════════════════════════════════
+# 25.0.1 es **exactamente** la que nuestro `python3` ya trae empaquetada en
+# `ensurepip/_bundled/pip-25.0.1-py3-none-any.whl` (medido). Usar otra pondría dos pips distintos en
+# circulación —uno importable y otro que `ensurepip` desplegaría— y el día que algo se comportara
+# distinto según cuál tomó, nadie lo encontraría.
+#
+# Python puro: no compila nada. Se copia `src/pip`, igual que `py3-setuptools` copia `setuptools`.
+name = "py3-pip"
+version = "25.0.1"
+license = "MIT"
+
+[source]
+tarball = "https://files.pythonhosted.org/packages/70/53/b309b4a497b09655cb7e07088966881a57d082f48ac3cb54ea729fd2c6cf/pip-25.0.1.tar.gz"
+sha256 = "88f96547ea48b940a3a385494e181e29fb8637898f88d88737c5049780f196ea"
+
+[build]
+compiler = "zig-cc"
+target = "x86_64-linux-musl"
+link = "static"
+flags = []
+
+[build.phases]
+configure = '''
+set -e
+[ -d src/pip ] || { echo "py3-pip: el sdist no trae src/pip — upstream cambió el layout" >&2; ls -la >&2; exit 1; }
+echo "py3-pip: src/pip presente"
+'''
+compile = "true"
+install = '''
+set -e
+SP=/out/usr/lib/python3.12/site-packages
+mkdir -p "$SP"
+cp -r src/pip "$SP/"
+# ⚠ El guardián comprueba lo que de verdad importa: que `find_spec("pip")` lo ENCUENTRE, que es la
+# pregunta exacta que hace `mkvenv` de qemu. Que el directorio exista no es lo mismo: sin
+# `__init__.py` o con un layout distinto, `find_spec` devuelve None y el build de qemu se iría otra
+# vez al índice — con un error que no menciona a pip.
+[ -f "$SP/pip/__init__.py" ] || { echo "py3-pip: falta pip/__init__.py — find_spec('pip') devolvería None" >&2; ls "$SP/pip" 2>/dev/null | head >&2; exit 1; }
+v=$(PYTHONPATH="$SP" python3 -c 'import importlib.util as u, pip; print(pip.__version__ if u.find_spec("pip") else "")' 2>&1) || {
+ echo "py3-pip: no se puede importar pip desde el site-packages instalado" >&2; printf '%s\n' "$v" >&2; exit 1
+}
+[ "$v" = "25.0.1" ] || { echo "py3-pip: la version importada es '$v', esperaba 25.0.1 (la misma que el ensurepip de python3)" >&2; exit 1; }
+echo "py3-pip: pip $v importable desde site-packages"
+'''
+
+[deps]
+build = ["python3"]
+# Quien lo use lo IMPORTA en ejecución, no al construirse.
+runtime = ["python3"]
diff --git a/recipes/py3-setuptools.toml b/recipes/py3-setuptools.toml
new file mode 100644
index 00000000..00a8cc85
--- /dev/null
+++ b/recipes/py3-setuptools.toml
@@ -0,0 +1,37 @@
+# py3-setuptools 75.8.2 — setuptools como MÓDULO importable de python3, para las recetas cuyo
+# meson.build exige `python3 (setuptools)` (gobject-introspection:29, y todo el stack GUI-python
+# que instala giscanner/entry-points). Python PURO: no se compila, se COPIA a site-packages.
+#
+# Mismo patrón que meson.toml: takana evita el camino wheel/pip/gpep517 de Alpine (recetas que no
+# tiene); la fuente ES el árbol Python sellado y se instala copiando los paquetes tal cual. Hermético
+# (sin pip ni red). El `.pth` de precedencia de distutils replica lo que hace `pip install setuptools`
+# para que `_distutils_hack` se active y setuptools gane sobre el distutils del stdlib.
+name = "py3-setuptools"
+version = "75.8.2"
+license = "MIT"
+
+[source]
+tarball = "https://files.pythonhosted.org/packages/source/s/setuptools/setuptools-75.8.2.tar.gz"
+sha256 = "4880473a969e5f23f2a2be3646b2dfd84af9028716d398e46192f84bc36900d2"
+
+[build]
+compiler = "zig-cc"
+target = "x86_64-linux-musl"
+link = "static"
+
+[build.phases]
+# Python puro: nada que compilar.
+compile = "true"
+install = '''
+set -e
+SP=/out/usr/lib/python3.12/site-packages
+mkdir -p "$SP"
+cp -r setuptools pkg_resources _distutils_hack "$SP/"
+# Replica el distutils-precedence.pth de pip: activa el shim que da precedencia a setuptools.
+printf '%s\n' "import os; var = 'SETUPTOOLS_USE_DISTUTILS'; enabled = os.environ.get(var, 'local') == 'local'; enabled and __import__('_distutils_hack').add_shim();" \
+ > "$SP/distutils-precedence.pth"
+'''
+
+# python3 es dep de RUNTIME (lo importa quien use setuptools como build-dep).
+[deps]
+runtime = ["python3"]