[FIX] install : compiler pykcs11 avec SWIG 4.3 et au-delà
Toute installation d'Odoo 14, 15 ou 17 échoue depuis que SWIG 4.5 est paru
sur PyPI : « ‘PyInt_FromLong’ was not declared in this scope », 55 fois.
pykcs11 — tiré par endesive — ne livre aucun wrapper pré-généré, et son
« requires = ["swig"] » n'est pas borné : c'est la DERNIÈRE version publiée
qui tourne, pas celle du système. Or SWIG 4.3 a retiré les alias Python 2
qu'il écrivait lui-même, et le typemap CK_RV de pykcs11 en utilise un.
On rend l'alias au préprocesseur, identique token pour token à celui de
SWIG 4.2. CPPFLAGS et non CFLAGS : un .cpp passe par compiler_so_cxx.
Vérifié sur la VM et ici : poetry install rend 0, import PyKCS11 passe.
--- EN ---
Every Odoo 14, 15 and 17 install has been failing since SWIG 4.5 landed on
PyPI: "'PyInt_FromLong' was not declared in this scope", 55 times. pykcs11
— pulled in by endesive — ships no pre-generated wrapper, and its
`requires = ["swig"]` is unbounded: the LATEST published version runs, not
the system one. SWIG 4.3 dropped the Python 2 aliases it used to emit
itself, and pykcs11's CK_RV typemap uses one of them.
We hand the alias back to the preprocessor, token for token identical to
SWIG 4.2's. CPPFLAGS, not CFLAGS: a .cpp goes through compiler_so_cxx.
Verified on the VM and here: poetry install returns 0, import PyKCS11 works.
Assisted-by: Claude Opus 5
2026-08-22 05:07:06 -04:00
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
# © 2026 TechnoLibre (http://www.technolibre.ca)
|
|
|
|
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
|
|
|
|
|
"""L'installation Poetry survit à SWIG >= 4.3.
|
|
|
|
|
|
|
|
|
|
|
|
pykcs11 — tiré par endesive, donc dans les locks Odoo 14, 15 et 17 — ne livre
|
|
|
|
|
|
aucun wrapper pré-généré : SWIG tourne à chaque installation. Son
|
|
|
|
|
|
« requires = ["setuptools", "swig"] » n'étant pas borné, Poetry prend la
|
|
|
|
|
|
DERNIÈRE version de PyPI. SWIG 4.3 a retiré les alias Python 2 que les
|
|
|
|
|
|
versions antérieures écrivaient dans le code généré, et le typemap CK_RV de
|
|
|
|
|
|
pykcs11 en utilise un : « ‘PyInt_FromLong’ was not declared in this scope »,
|
|
|
|
|
|
55 fois, et install_odoo_17 s'arrête.
|
|
|
|
|
|
|
|
|
|
|
|
Ces tests gardent les trois choses que l'enquête a coûté :
|
|
|
|
|
|
|
|
|
|
|
|
- CPPFLAGS, pas CFLAGS. Un .cpp est compilé par « compiler_so_cxx », qui lit
|
|
|
|
|
|
CXXFLAGS et CPPFLAGS ; CFLAGS ne l'atteint JAMAIS. Le premier correctif a
|
|
|
|
|
|
échoué exactement là.
|
|
|
|
|
|
- La définition doit être identique TOKEN POUR TOKEN à celle de SWIG 4.2,
|
|
|
|
|
|
sinon les hôtes qui ont encore un vieux SWIG récoltent un avertissement de
|
|
|
|
|
|
redéfinition à chaque fichier.
|
|
|
|
|
|
- Le drapeau doit être posé AVANT « poetry install », et s'ajouter à un
|
|
|
|
|
|
CPPFLAGS existant au lieu de l'écraser.
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
|
import re
|
|
|
|
|
|
import shutil
|
|
|
|
|
|
import subprocess
|
|
|
|
|
|
import sysconfig
|
|
|
|
|
|
import tempfile
|
|
|
|
|
|
import unittest
|
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
|
|
RACINE = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
SCRIPT = RACINE / "script/install/install_locally.sh"
|
|
|
|
|
|
SOURCE = SCRIPT.read_text(encoding="utf-8")
|
|
|
|
|
|
|
|
|
|
|
|
# La ligne que SWIG <= 4.2 plaçait lui-même dans le wrapper généré.
|
|
|
|
|
|
SWIG_42 = "#define PyInt_FromLong(x) PyLong_FromLong(x)"
|
|
|
|
|
|
|
|
|
|
|
|
# Ce que produit SWIG >= 4.3 : l'appel, sans l'alias.
|
|
|
|
|
|
APPEL_SWIG_43 = """
|
|
|
|
|
|
#include <Python.h>
|
|
|
|
|
|
PyObject *sonde(long v) { return PyInt_FromLong(v); }
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _drapeau():
|
|
|
|
|
|
"""Le -D tel qu'il est écrit dans le script — source unique."""
|
[REF] format : passer l'outillage et les tests sous ruff
Le formateur de ce dépôt est ruff depuis qu'il remplace black, qui ne connaît
aucune cible au-delà de py313 ; ce passage applique sa norme à l'arbre entier,
d'un coup, pour qu'aucun commit de fond n'ait à porter du style. L'écart tient
presque entièrement aux chaînes coupées à la main que ruff recolle quand elles
tiennent sur une ligne, et aux « with » multiples qu'il regroupe : aucune
valeur ne change, et les clés de traduction non plus.
Vérifié : la suite unitaire reste verte après le passage, et le contrôle de
syntaxe ne signale rien.
--- EN ---
This repository's formatter is ruff since it replaced black, which knows no
target beyond py313; this pass applies its standard to the whole tree at once,
so that no substantive commit has to carry style. The difference is almost
entirely the hand-split strings ruff joins back when they fit on one line, and
the multiple "with" it merges: no value changes, nor do the translation keys.
Checked: the unit suite stays green after the pass, and the syntax check
reports nothing.
Assisted-by: Claude Opus 5
2026-09-24 13:30:31 -04:00
|
|
|
|
m = re.search(
|
|
|
|
|
|
r"export CPPFLAGS=\"[^\"]*?(-DPyInt_FromLong[^\" ]*)\"", SOURCE
|
|
|
|
|
|
)
|
[FIX] install : compiler pykcs11 avec SWIG 4.3 et au-delà
Toute installation d'Odoo 14, 15 ou 17 échoue depuis que SWIG 4.5 est paru
sur PyPI : « ‘PyInt_FromLong’ was not declared in this scope », 55 fois.
pykcs11 — tiré par endesive — ne livre aucun wrapper pré-généré, et son
« requires = ["swig"] » n'est pas borné : c'est la DERNIÈRE version publiée
qui tourne, pas celle du système. Or SWIG 4.3 a retiré les alias Python 2
qu'il écrivait lui-même, et le typemap CK_RV de pykcs11 en utilise un.
On rend l'alias au préprocesseur, identique token pour token à celui de
SWIG 4.2. CPPFLAGS et non CFLAGS : un .cpp passe par compiler_so_cxx.
Vérifié sur la VM et ici : poetry install rend 0, import PyKCS11 passe.
--- EN ---
Every Odoo 14, 15 and 17 install has been failing since SWIG 4.5 landed on
PyPI: "'PyInt_FromLong' was not declared in this scope", 55 times. pykcs11
— pulled in by endesive — ships no pre-generated wrapper, and its
`requires = ["swig"]` is unbounded: the LATEST published version runs, not
the system one. SWIG 4.3 dropped the Python 2 aliases it used to emit
itself, and pykcs11's CK_RV typemap uses one of them.
We hand the alias back to the preprocessor, token for token identical to
SWIG 4.2's. CPPFLAGS, not CFLAGS: a .cpp goes through compiler_so_cxx.
Verified on the VM and here: poetry install returns 0, import PyKCS11 works.
Assisted-by: Claude Opus 5
2026-08-22 05:07:06 -04:00
|
|
|
|
return m.group(1) if m else ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _compilateur():
|
|
|
|
|
|
return shutil.which("c++") or shutil.which("g++")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _compile(source, drapeaux):
|
|
|
|
|
|
"""(succès, sortie) d'une compilation de syntaxe seule."""
|
|
|
|
|
|
inc = sysconfig.get_paths()["include"]
|
|
|
|
|
|
if not Path(inc, "Python.h").exists():
|
|
|
|
|
|
return None, "Python.h absent"
|
|
|
|
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
|
|
|
|
fichier = Path(tmp, "sonde.cpp")
|
|
|
|
|
|
fichier.write_text(source, encoding="utf-8")
|
|
|
|
|
|
res = subprocess.run(
|
[REF] format : passer l'outillage et les tests sous ruff
Le formateur de ce dépôt est ruff depuis qu'il remplace black, qui ne connaît
aucune cible au-delà de py313 ; ce passage applique sa norme à l'arbre entier,
d'un coup, pour qu'aucun commit de fond n'ait à porter du style. L'écart tient
presque entièrement aux chaînes coupées à la main que ruff recolle quand elles
tiennent sur une ligne, et aux « with » multiples qu'il regroupe : aucune
valeur ne change, et les clés de traduction non plus.
Vérifié : la suite unitaire reste verte après le passage, et le contrôle de
syntaxe ne signale rien.
--- EN ---
This repository's formatter is ruff since it replaced black, which knows no
target beyond py313; this pass applies its standard to the whole tree at once,
so that no substantive commit has to carry style. The difference is almost
entirely the hand-split strings ruff joins back when they fit on one line, and
the multiple "with" it merges: no value changes, nor do the translation keys.
Checked: the unit suite stays green after the pass, and the syntax check
reports nothing.
Assisted-by: Claude Opus 5
2026-09-24 13:30:31 -04:00
|
|
|
|
[
|
|
|
|
|
|
_compilateur(),
|
|
|
|
|
|
"-fsyntax-only",
|
|
|
|
|
|
*drapeaux,
|
|
|
|
|
|
"-I",
|
|
|
|
|
|
inc,
|
|
|
|
|
|
str(fichier),
|
|
|
|
|
|
],
|
[FIX] install : compiler pykcs11 avec SWIG 4.3 et au-delà
Toute installation d'Odoo 14, 15 ou 17 échoue depuis que SWIG 4.5 est paru
sur PyPI : « ‘PyInt_FromLong’ was not declared in this scope », 55 fois.
pykcs11 — tiré par endesive — ne livre aucun wrapper pré-généré, et son
« requires = ["swig"] » n'est pas borné : c'est la DERNIÈRE version publiée
qui tourne, pas celle du système. Or SWIG 4.3 a retiré les alias Python 2
qu'il écrivait lui-même, et le typemap CK_RV de pykcs11 en utilise un.
On rend l'alias au préprocesseur, identique token pour token à celui de
SWIG 4.2. CPPFLAGS et non CFLAGS : un .cpp passe par compiler_so_cxx.
Vérifié sur la VM et ici : poetry install rend 0, import PyKCS11 passe.
--- EN ---
Every Odoo 14, 15 and 17 install has been failing since SWIG 4.5 landed on
PyPI: "'PyInt_FromLong' was not declared in this scope", 55 times. pykcs11
— pulled in by endesive — ships no pre-generated wrapper, and its
`requires = ["swig"]` is unbounded: the LATEST published version runs, not
the system one. SWIG 4.3 dropped the Python 2 aliases it used to emit
itself, and pykcs11's CK_RV typemap uses one of them.
We hand the alias back to the preprocessor, token for token identical to
SWIG 4.2's. CPPFLAGS, not CFLAGS: a .cpp goes through compiler_so_cxx.
Verified on the VM and here: poetry install returns 0, import PyKCS11 works.
Assisted-by: Claude Opus 5
2026-08-22 05:07:06 -04:00
|
|
|
|
capture_output=True,
|
|
|
|
|
|
text=True,
|
|
|
|
|
|
timeout=120,
|
|
|
|
|
|
)
|
|
|
|
|
|
return res.returncode == 0, res.stdout + res.stderr
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestLeDrapeauDansLeScript(unittest.TestCase):
|
|
|
|
|
|
def test_it_is_exported(self):
|
|
|
|
|
|
self.assertTrue(_drapeau(), "aucun -DPyInt_FromLong dans le script")
|
|
|
|
|
|
|
|
|
|
|
|
def test_it_is_set_before_poetry_install(self):
|
|
|
|
|
|
"""Posé après, il n'atteindrait rien : c'est « poetry install » qui
|
|
|
|
|
|
lance les compilations."""
|
|
|
|
|
|
export = SOURCE.index("export CPPFLAGS=")
|
[REF] format : passer l'outillage et les tests sous ruff
Le formateur de ce dépôt est ruff depuis qu'il remplace black, qui ne connaît
aucune cible au-delà de py313 ; ce passage applique sa norme à l'arbre entier,
d'un coup, pour qu'aucun commit de fond n'ait à porter du style. L'écart tient
presque entièrement aux chaînes coupées à la main que ruff recolle quand elles
tiennent sur une ligne, et aux « with » multiples qu'il regroupe : aucune
valeur ne change, et les clés de traduction non plus.
Vérifié : la suite unitaire reste verte après le passage, et le contrôle de
syntaxe ne signale rien.
--- EN ---
This repository's formatter is ruff since it replaced black, which knows no
target beyond py313; this pass applies its standard to the whole tree at once,
so that no substantive commit has to carry style. The difference is almost
entirely the hand-split strings ruff joins back when they fit on one line, and
the multiple "with" it merges: no value changes, nor do the translation keys.
Checked: the unit suite stays green after the pass, and the syntax check
reports nothing.
Assisted-by: Claude Opus 5
2026-09-24 13:30:31 -04:00
|
|
|
|
install = SOURCE.index("install --no-root ${POETRY_VERBOSE}")
|
[FIX] install : compiler pykcs11 avec SWIG 4.3 et au-delà
Toute installation d'Odoo 14, 15 ou 17 échoue depuis que SWIG 4.5 est paru
sur PyPI : « ‘PyInt_FromLong’ was not declared in this scope », 55 fois.
pykcs11 — tiré par endesive — ne livre aucun wrapper pré-généré, et son
« requires = ["swig"] » n'est pas borné : c'est la DERNIÈRE version publiée
qui tourne, pas celle du système. Or SWIG 4.3 a retiré les alias Python 2
qu'il écrivait lui-même, et le typemap CK_RV de pykcs11 en utilise un.
On rend l'alias au préprocesseur, identique token pour token à celui de
SWIG 4.2. CPPFLAGS et non CFLAGS : un .cpp passe par compiler_so_cxx.
Vérifié sur la VM et ici : poetry install rend 0, import PyKCS11 passe.
--- EN ---
Every Odoo 14, 15 and 17 install has been failing since SWIG 4.5 landed on
PyPI: "'PyInt_FromLong' was not declared in this scope", 55 times. pykcs11
— pulled in by endesive — ships no pre-generated wrapper, and its
`requires = ["swig"]` is unbounded: the LATEST published version runs, not
the system one. SWIG 4.3 dropped the Python 2 aliases it used to emit
itself, and pykcs11's CK_RV typemap uses one of them.
We hand the alias back to the preprocessor, token for token identical to
SWIG 4.2's. CPPFLAGS, not CFLAGS: a .cpp goes through compiler_so_cxx.
Verified on the VM and here: poetry install returns 0, import PyKCS11 works.
Assisted-by: Claude Opus 5
2026-08-22 05:07:06 -04:00
|
|
|
|
self.assertLess(export, install)
|
|
|
|
|
|
|
|
|
|
|
|
def test_it_appends_instead_of_replacing(self):
|
|
|
|
|
|
"""Écraser CPPFLAGS jetterait ce que l'appelant y avait mis — sur
|
|
|
|
|
|
s390x et openSUSE, des chemins d'en-têtes y passent."""
|
[REF] format : passer l'outillage et les tests sous ruff
Le formateur de ce dépôt est ruff depuis qu'il remplace black, qui ne connaît
aucune cible au-delà de py313 ; ce passage applique sa norme à l'arbre entier,
d'un coup, pour qu'aucun commit de fond n'ait à porter du style. L'écart tient
presque entièrement aux chaînes coupées à la main que ruff recolle quand elles
tiennent sur une ligne, et aux « with » multiples qu'il regroupe : aucune
valeur ne change, et les clés de traduction non plus.
Vérifié : la suite unitaire reste verte après le passage, et le contrôle de
syntaxe ne signale rien.
--- EN ---
This repository's formatter is ruff since it replaced black, which knows no
target beyond py313; this pass applies its standard to the whole tree at once,
so that no substantive commit has to carry style. The difference is almost
entirely the hand-split strings ruff joins back when they fit on one line, and
the multiple "with" it merges: no value changes, nor do the translation keys.
Checked: the unit suite stays green after the pass, and the syntax check
reports nothing.
Assisted-by: Claude Opus 5
2026-09-24 13:30:31 -04:00
|
|
|
|
self.assertIn("${CPPFLAGS:+${CPPFLAGS} }", SOURCE)
|
[FIX] install : compiler pykcs11 avec SWIG 4.3 et au-delà
Toute installation d'Odoo 14, 15 ou 17 échoue depuis que SWIG 4.5 est paru
sur PyPI : « ‘PyInt_FromLong’ was not declared in this scope », 55 fois.
pykcs11 — tiré par endesive — ne livre aucun wrapper pré-généré, et son
« requires = ["swig"] » n'est pas borné : c'est la DERNIÈRE version publiée
qui tourne, pas celle du système. Or SWIG 4.3 a retiré les alias Python 2
qu'il écrivait lui-même, et le typemap CK_RV de pykcs11 en utilise un.
On rend l'alias au préprocesseur, identique token pour token à celui de
SWIG 4.2. CPPFLAGS et non CFLAGS : un .cpp passe par compiler_so_cxx.
Vérifié sur la VM et ici : poetry install rend 0, import PyKCS11 passe.
--- EN ---
Every Odoo 14, 15 and 17 install has been failing since SWIG 4.5 landed on
PyPI: "'PyInt_FromLong' was not declared in this scope", 55 times. pykcs11
— pulled in by endesive — ships no pre-generated wrapper, and its
`requires = ["swig"]` is unbounded: the LATEST published version runs, not
the system one. SWIG 4.3 dropped the Python 2 aliases it used to emit
itself, and pykcs11's CK_RV typemap uses one of them.
We hand the alias back to the preprocessor, token for token identical to
SWIG 4.2's. CPPFLAGS, not CFLAGS: a .cpp goes through compiler_so_cxx.
Verified on the VM and here: poetry install returns 0, import PyKCS11 works.
Assisted-by: Claude Opus 5
2026-08-22 05:07:06 -04:00
|
|
|
|
|
|
|
|
|
|
def test_it_is_cppflags_and_not_cflags(self):
|
|
|
|
|
|
"""Le piège qui a fait échouer le premier correctif : le fichier fautif
|
|
|
|
|
|
est un .cpp, et CFLAGS ne va qu'aux .c."""
|
|
|
|
|
|
self.assertNotIn("export CFLAGS=", SOURCE)
|
|
|
|
|
|
|
|
|
|
|
|
def test_the_shell_builds_the_value_it_claims(self):
|
|
|
|
|
|
"""Les parenthèses du -D sont des métacaractères du shell : mal
|
|
|
|
|
|
protégées, la variable serait tronquée ou le script casserait."""
|
|
|
|
|
|
for depart, attendu in (
|
|
|
|
|
|
("", "-DPyInt_FromLong(x)=PyLong_FromLong(x)"),
|
|
|
|
|
|
("-DDEJA=1", "-DDEJA=1 -DPyInt_FromLong(x)=PyLong_FromLong(x)"),
|
|
|
|
|
|
):
|
|
|
|
|
|
res = subprocess.run(
|
|
|
|
|
|
[
|
|
|
|
|
|
"bash",
|
|
|
|
|
|
"-c",
|
|
|
|
|
|
f'export CPPFLAGS="{depart}"; '
|
|
|
|
|
|
'export CPPFLAGS="${CPPFLAGS:+${CPPFLAGS} }'
|
|
|
|
|
|
f'{_drapeau()}"; printf %s "$CPPFLAGS"',
|
|
|
|
|
|
],
|
|
|
|
|
|
capture_output=True,
|
|
|
|
|
|
text=True,
|
|
|
|
|
|
timeout=30,
|
|
|
|
|
|
)
|
|
|
|
|
|
self.assertEqual(attendu, res.stdout)
|
|
|
|
|
|
|
|
|
|
|
|
def test_the_script_still_parses(self):
|
|
|
|
|
|
res = subprocess.run(
|
|
|
|
|
|
["bash", "-n", str(SCRIPT)], capture_output=True, text=True
|
|
|
|
|
|
)
|
|
|
|
|
|
self.assertEqual(0, res.returncode, res.stderr)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@unittest.skipUnless(_compilateur(), "aucun compilateur C++")
|
|
|
|
|
|
class TestLeDrapeauCompile(unittest.TestCase):
|
|
|
|
|
|
"""Le drapeau fait-il ce qu'on lui prête ? Compilé, pas supposé."""
|
|
|
|
|
|
|
|
|
|
|
|
def test_swig_43_output_fails_without_it(self):
|
|
|
|
|
|
"""Sans quoi le test suivant ne prouverait rien : c'est bien CE
|
|
|
|
|
|
symptôme que le drapeau soigne."""
|
|
|
|
|
|
ok, sortie = _compile(APPEL_SWIG_43, [])
|
|
|
|
|
|
if ok is None:
|
|
|
|
|
|
self.skipTest(sortie)
|
|
|
|
|
|
self.assertFalse(ok)
|
|
|
|
|
|
self.assertIn("PyInt_FromLong", sortie)
|
|
|
|
|
|
|
|
|
|
|
|
def test_the_same_source_compiles_with_it(self):
|
|
|
|
|
|
ok, sortie = _compile(APPEL_SWIG_43, [_drapeau()])
|
|
|
|
|
|
if ok is None:
|
|
|
|
|
|
self.skipTest(sortie)
|
|
|
|
|
|
self.assertTrue(ok, sortie[-400:])
|
|
|
|
|
|
|
|
|
|
|
|
def test_it_does_not_clash_with_an_older_swig(self):
|
|
|
|
|
|
"""Un hôte dont le SWIG écrit encore l'alias verrait, sinon, un
|
|
|
|
|
|
avertissement de redéfinition par fichier compilé. En -Werror, ce
|
|
|
|
|
|
serait un échec."""
|
[REF] format : passer l'outillage et les tests sous ruff
Le formateur de ce dépôt est ruff depuis qu'il remplace black, qui ne connaît
aucune cible au-delà de py313 ; ce passage applique sa norme à l'arbre entier,
d'un coup, pour qu'aucun commit de fond n'ait à porter du style. L'écart tient
presque entièrement aux chaînes coupées à la main que ruff recolle quand elles
tiennent sur une ligne, et aux « with » multiples qu'il regroupe : aucune
valeur ne change, et les clés de traduction non plus.
Vérifié : la suite unitaire reste verte après le passage, et le contrôle de
syntaxe ne signale rien.
--- EN ---
This repository's formatter is ruff since it replaced black, which knows no
target beyond py313; this pass applies its standard to the whole tree at once,
so that no substantive commit has to carry style. The difference is almost
entirely the hand-split strings ruff joins back when they fit on one line, and
the multiple "with" it merges: no value changes, nor do the translation keys.
Checked: the unit suite stays green after the pass, and the syntax check
reports nothing.
Assisted-by: Claude Opus 5
2026-09-24 13:30:31 -04:00
|
|
|
|
ok, sortie = _compile(SWIG_42 + APPEL_SWIG_43, ["-Werror", _drapeau()])
|
[FIX] install : compiler pykcs11 avec SWIG 4.3 et au-delà
Toute installation d'Odoo 14, 15 ou 17 échoue depuis que SWIG 4.5 est paru
sur PyPI : « ‘PyInt_FromLong’ was not declared in this scope », 55 fois.
pykcs11 — tiré par endesive — ne livre aucun wrapper pré-généré, et son
« requires = ["swig"] » n'est pas borné : c'est la DERNIÈRE version publiée
qui tourne, pas celle du système. Or SWIG 4.3 a retiré les alias Python 2
qu'il écrivait lui-même, et le typemap CK_RV de pykcs11 en utilise un.
On rend l'alias au préprocesseur, identique token pour token à celui de
SWIG 4.2. CPPFLAGS et non CFLAGS : un .cpp passe par compiler_so_cxx.
Vérifié sur la VM et ici : poetry install rend 0, import PyKCS11 passe.
--- EN ---
Every Odoo 14, 15 and 17 install has been failing since SWIG 4.5 landed on
PyPI: "'PyInt_FromLong' was not declared in this scope", 55 times. pykcs11
— pulled in by endesive — ships no pre-generated wrapper, and its
`requires = ["swig"]` is unbounded: the LATEST published version runs, not
the system one. SWIG 4.3 dropped the Python 2 aliases it used to emit
itself, and pykcs11's CK_RV typemap uses one of them.
We hand the alias back to the preprocessor, token for token identical to
SWIG 4.2's. CPPFLAGS, not CFLAGS: a .cpp goes through compiler_so_cxx.
Verified on the VM and here: poetry install returns 0, import PyKCS11 works.
Assisted-by: Claude Opus 5
2026-08-22 05:07:06 -04:00
|
|
|
|
if ok is None:
|
|
|
|
|
|
self.skipTest(sortie)
|
|
|
|
|
|
self.assertTrue(ok, sortie[-400:])
|
|
|
|
|
|
self.assertNotIn("redefined", sortie)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestHypotheseSetuptools(unittest.TestCase):
|
|
|
|
|
|
"""L'hypothèse dont dépend le choix de CPPFLAGS, écrite noir sur blanc.
|
|
|
|
|
|
|
|
|
|
|
|
Si un setuptools futur change de câblage, c'est ici qu'on l'apprend — pas
|
|
|
|
|
|
au milieu d'une installation de VM.
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
def test_cppflags_reaches_the_cxx_compiler_but_cflags_does_not(self):
|
|
|
|
|
|
try:
|
|
|
|
|
|
from setuptools._distutils.ccompiler import new_compiler
|
|
|
|
|
|
from setuptools._distutils.sysconfig import customize_compiler
|
|
|
|
|
|
except ImportError as exc: # pragma: no cover - setuptools trop vieux
|
|
|
|
|
|
self.skipTest(f"distutils vendu introuvable : {exc}")
|
|
|
|
|
|
garde = {v: os.environ.get(v) for v in ("CFLAGS", "CPPFLAGS")}
|
|
|
|
|
|
os.environ["CFLAGS"] = "-DVU_PAR_CFLAGS=1"
|
|
|
|
|
|
os.environ["CPPFLAGS"] = "-DVU_PAR_CPPFLAGS=1"
|
|
|
|
|
|
try:
|
|
|
|
|
|
compilateur = new_compiler()
|
|
|
|
|
|
customize_compiler(compilateur)
|
|
|
|
|
|
cxx = getattr(compilateur, "compiler_so_cxx", None)
|
|
|
|
|
|
if not cxx:
|
|
|
|
|
|
self.skipTest("pas de compiler_so_cxx dans ce setuptools")
|
|
|
|
|
|
self.assertIn("-DVU_PAR_CPPFLAGS=1", cxx)
|
|
|
|
|
|
self.assertNotIn("-DVU_PAR_CFLAGS=1", cxx)
|
|
|
|
|
|
finally:
|
|
|
|
|
|
for var, val in garde.items():
|
|
|
|
|
|
if val is None:
|
|
|
|
|
|
os.environ.pop(var, None)
|
|
|
|
|
|
else:
|
|
|
|
|
|
os.environ[var] = val
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
|
unittest.main(verbosity=1)
|