J'ouvre ce numéro pour tenter de consolider la discussion sur les versions hors de l'arbre, les problèmes connexes et les solutions possibles.
Quel est le problème que cette fonctionnalité résoudra ?
Lors de la création de projets à partir de répertoires locaux, pip les copie d' abord
Cette approche a soulevé un certain nombre de problèmes au fil du temps :
Pourquoi pip copie-t-il dans un répertoire temporaire avant la construction ? Avertissement : ce n'est pas clair pour moi - voici ce que j'ai collecté jusqu'à présent :
Solutions possibles
Contexte supplémentaire
Plus de discussions sur la construction via sdist sur discute.python.org .
En regardant cela du point de vue du back-end, l'idée d'une "construction hors de l'arborescence" n'a en fait aucun sens. Le back-end reçoit une « arborescence source » sous la forme du répertoire courant du processus, et il lui est demandé d'exécuter un build. Il n'a aucun moyen de savoir si ce répertoire a été extrait d'un sdist, extrait d'un VCS ou copié d'un autre endroit. Tout ce qu'il peut faire, c'est construire, et s'il n'a pas ce dont il a besoin pour construire, signaler l'échec.
Donc , cette jolie tue beaucoup solution possible (3) OMI - le back - end ne dispose pas d' un concept de ce qu'est une construction en place est, il ne peut pas dire si une telle construction est sûre 1.
En ce qui concerne (2), je suis généralement opposé à des options supplémentaires comme celle-ci. Si nous savons quelle est la meilleure chose à faire, nous devons le faire, et si nous ne le savons pas, alors transmettre le problème à l'utilisateur n'est pas une option particulièrement conviviale. Le problème ici est suffisamment subtil pour que peu d'utilisateurs sachent quel est le bon choix, nous verrions donc probablement des gens essayer les 2 options et utiliser aveuglément "tout ce qui fonctionne". De plus, les implications de support sont importantes - offrir une option implique clairement que nous nous attendons à ce que les résultats de la construction soient différents dans au moins certains cas, alors comment tester que les différences sont comme prévu ? Sommes-nous chargés d'informer les utilisateurs sur le moment où l'indicateur de construction sur place serait nécessaire ou non (soit via notre documentation, soit à la suite de problèmes soulevés par des utilisateurs qui ne savent pas lequel utiliser) ?
Cela dit, je ne suis pas contre le fait que pip se contente de construire sur place. Je crois que la raison pour laquelle nous ne le faisons pas est que nous avons eu des cas où des artefacts laissés par une version précédente ont été utilisés dans une version ultérieure, mais ont été construits avec des options différentes (par exemple, des fichiers objet construits en mode débogage étant liés à une version de version fait à partir du même arbre). Il est, cependant, raisonnable de dire que les backends devraient s'assurer que de tels problèmes ne se produisent pas, et s'ils se produisent, c'est un bug du backend et non pas à essayer de s'en défendre. Cependant, je ne suis pas sûr qu'une telle position soit particulièrement conviviale - cela a été soulevé lors des discussions sur le PEP 517 sous le thème des versions incrémentielles, et était suffisamment controversé pour qu'il soit reporté à l'époque.
Ma préférence a été de construire un sdist, puis de construire la roue à partir de cela, depuis longtemps maintenant (votre option 1). Je suis d'accord avec la construction de pip en place (si nous pouvons convenir que cela est sûr, étant donné que, comme je l'ai noté ci-dessus, nous ne pouvons pas nous attendre à ce que le back-end nous le fasse savoir), mais je pense que cela aurait besoin d'une communauté discussion pour débattre des implications plus larges (sur les backends, les pip/frontends et les utilisateurs finaux).
1 Il serait bien sûr possible de mettre à jour le PEP 517 pour définir ce qui constitue une arborescence source "sur place" par opposition à une construction "hors arborescence", mais je soupçonne que ce serait un concept très difficile à cerner.
J'ai ajouté les solutions 4. (Changer pip pour toujours construire en place) et 5. (Changer pip pour construire en place par défaut avec une option pour construire hors de l'arbre).
J'ai des sentiments mitigés concernant la construction via sdist (solution 1.) pour les raisons suivantes :
UnsupportedOperation
pour build_sdist
.Cet article sur discuter résume également des arguments similaires.
Je suis d'accord que le chemin de la solution 3. est loin d'être évident.
Je suis également d'accord que nous devrions éviter les options supplémentaires si nous le pouvons.
Je note également qu'il y a eu des voix en faveur des constructions sur place dans le fil de discussion lié, mais en effet, une discussion communautaire ciblée sur ce sujet spécifique est nécessaire si nous voulons explorer cette approche.
- Construisez un sdist en place, décompressez le sdist dans un emplacement temporaire, puis construisez à partir de là.
Je pense que c'est une bonne approche.
Il est probable que l'OMI soit exécuté pour un seul package dans la plupart des exécutions de pip install
impliquant des répertoires locaux - le plus souvent, j'imagine pip install .
. Cela serait probablement fait dans le cadre du flux de travail de développement du package.
Voici ce que je pense que ce comportement devrait être:
En faisant local-dir -> sdist -> wheel, nous avons un ensemble supplémentaire d'appels. Cependant, je pense qu'il est raisonnable de valider que les sdists générés sont sains, en particulier pendant le développement. tox le fait déjà dans le cadre de son flux de travail, check-manifest pour couvrir les interfaces pas si conviviales de setuptools ici.
Dans l'ensemble, je pense que les coûts de construction d'un sdist lorsqu'on lui donne un répertoire local en valent la peine pour éviter de telles erreurs dans les projets, d'autant plus que les personnes qui installent à partir de répertoires locaux sont probablement les développeurs du projet eux-mêmes.
En ce qui concerne le déploiement, je pense que nous voudrions attendre et voir comment le #6536 se présente. Nous apprendrions certainement quelques choses qui peuvent être transférées.
Je préfère construire/installer sur place sans sdist (donc setup.py install
ou setup.py bdist_wheel
ou appeler build_wheel
sur le backend PEP 517, selon le cas) plutôt que de construire un sdist, de le déballer et de l'installer à partir de ce. Mes raisons spécifiques sont :
setup.py install
). Les utilisateurs qui souhaitent passer de local-dir -> installé peuvent exécuter pip install local-dir
. Les utilisateurs souhaitant passer de local-dir -> sdist -> installé sont libres de créer un sdist, puis d'exécuter pip install ./path/to/sdist
. Il existe de nombreux outils alternatifs qui peuvent créer un sdist, et c'est quelque chose que les utilisateurs seront plus susceptibles d'avoir déjà à moins qu'ils ne créent à la main les distributions qu'ils téléchargent sur PyPI.pip install local-dir
. Les utilisateurs sans options demanderont à pip des options pour contrôler le comportement ou devront trouver un autre outil dont ils n'auraient pas eu besoin autrement.Quelle que soit l'approche, le seul problème que je vois à faire les choses sur place est que pour les builds setuptools (je pense que cela s'applique à l'héritage et au PEP 517), nous nous retrouverions avec .egg-info
dans le répertoire du projet qui se trompera en tant que "paquet installé" lorsque pip est invoqué avec python -m pip
dans ce répertoire. Cela serait corrigé par # 4575 qui n'inclurait vraisemblablement PAS le répertoire actuel dans la requête pour les packages installés pour n'importe quel schéma.
Notant que je suis devenu d'accord pour dire que l'idée de sauter la construction sdist et de faire directement une construction dans l'arborescence est une meilleure approche pour pip à prendre par défaut, et de ne pas essayer de faire local-dir -> sdist -> wheel.
Dans Fedora, lorsque nous construisons des packages Python RPM, nous sommes des dinosaures et la façon standard de procéder est d'utiliser python setup.py build
. Avec PEP 517, nous avons ajouté une manière "provisoire" d'utiliser pip wheel
place. Cependant, avec les modules d'extension, nous avons un problème avec l'approche "déplacer les sources vers tmp, construire à partir de là" que pip utilise pour les construire.
Notre machine de construction injecte des drapeaux de compilateur afin que les artefacts de construction (les modules d'extension .so
dans ce cas) contiennent des métadonnées sur leurs sources. Plus tard, un script shell parcourt les artefacts de construction, extrait ces informations et copie les sources dans /usr/src/debug
pour être installé via un RPM spécial *-debugsource
. La mahcinery s'attend à ce que tout soit construit dans l'arbre de travail et cela ne fonctionne pas vraiment bien lorsqu'il est construit à l'extérieur. Voici les choses qui peuvent être faites (ensemble) pour atténuer le problème de notre côté :
$TMPDIR
pour l'avoir à l'endroit où le script RPM l'attend (c'est- export TMPDIR=%{_builddir}/.tmp
dire pip wheel
avec l'option --no-clean
pour conserver les sources copiées dans $TMPDIR
find %{buildroot} -iname '*.so' -print0 | xargs --no-run-if-empty -0 -n1 /usr/lib/rpm/debugedit -b "%{_builddir}/.tmp/pip-req-build-"* -d "$PWD"
$TMPDIR
manuellement.)Nous n'aimons pas particulièrement la troisième étape car elle repose sur trop de détails d'implémentation :
/usr/lib/rpm/debugedit
API et emplacement (et existence)pip-req-build
Si pip était toujours construit en place ou s'il y avait un commutateur de ligne de commande pour cela, le problème disparaîtrait.
Rapport en aval : https://bugzilla.redhat.com/show_bug.cgi?id=1806625
Notant que je suis devenu d'accord pour dire que l'idée de sauter la construction sdist et de faire directement une construction dans l'arborescence est une meilleure approche pour pip à prendre par défaut, et de ne pas essayer de faire local-dir -> sdist -> wheel.
Je suis également de plus en plus enclin à accepter l'idée de construire une roue sur place. Mes réservations restantes sont :
... et bien sûr, quelqu'un devra rédiger un PR mettant en œuvre ce changement (avec des tests, des documents, etc. - les trucs habituels) sinon tout ce que nous faisons c'est parler
Nous comptons sur le comportement du backend "correctement" - par exemple, ne donnant pas de résultats différents en fonction des données restantes des versions précédentes, ou autre. Je suis d'accord pour faire cette hypothèse, mais je suis préoccupé par le coût du support si nous commençons à faire dire aux gens "pip a mal construit ma roue" et nous devons déboguer seulement pour découvrir qu'il s'agit d'un problème de backend.
Serait-il judicieux d'étendre l'interface PEP 517 pour inclure un crochet « propre » ? Nous voudrions probablement que ce soit un point de toute façon pour permettre d'autres efforts (par exemple, implémenter une installation modifiable, créer un outil de développement de packages qui construit n'importe quel projet PEP 517). pip peut l'appeler ici pour s'assurer qu'il n'y a pas de déchets indésirables avant de faire la construction dans l'arborescence.
Serait-il judicieux d'étendre l'interface PEP 517 pour inclure un crochet « propre » ?
Peut-être? Mais si pip appelle automatiquement clean
, il y a forcément quelqu'un qui veut ne pas le faire, faire des builds incrémentiels ou quelque chose du genre. Et puis nous nous retrouvons avec une autre option.
Mon inclination est de rester avec ma position "nous devons être en mesure de supposer qu'il est de la responsabilité du backend de s'assurer que les builds sur place fonctionnent correctement". Même si cela s'avère intenable, obtenir des exemples concrets des raisons pour lesquelles cela ne fonctionne pas nous aidera à mieux comprendre ce qu'il faut faire à propos du problème, plutôt que de simplement deviner.
- Nous comptons sur le comportement du backend "correctement" - par exemple, ne donnant pas de résultats différents en fonction des données restantes des versions précédentes, ou autre.
Je serais tenté d'étendre PEP-517 pour en faire une exigence explicite.
Je serais tenté d'étendre PEP-517 pour en faire une exigence explicite.
Il dit déjà ceci :
Le backend peut stocker des artefacts intermédiaires dans des emplacements de cache ou des répertoires temporaires. La présence ou l'absence de caches ne devrait pas avoir d'incidence importante sur le résultat final de la construction.
Ce n'est pas tant que les backends sont susceptibles de violer délibérément cette exigence, car les utilisateurs signaleront naturellement le problème comme un problème de pip et seront redirigés vers le projet backend, ce qui représente un peu plus de frais généraux.
En essayant de trouver une solution de contournement pour Fedora, nous avons été touchés par https://github.com/pypa/pip/issues/7872
Depuis que nous avons résolu le problème ".egg-info in cwd" avec #7731 et ses amis, c'est une chose de moins à se soucier lors de la construction en place.
Ainsi, l'option 4 (toujours construite en place) a été implémentée dans #7882 .
Nous avons maintenant (par #7951) publié une version bêta de pip, pip 20.1b1. Cette version inclut #7882, qui a mis en œuvre une solution à ce problème.
J'espère que les participants à ce numéro nous aideront en testant la version bêta et en recherchant de nouveaux bogues. Nous aimerions identifier et résoudre tout problème potentiel avant la sortie de la version principale 20.1 mardi.
J'accueille également les commentaires positifs du type « yay, ça marche mieux maintenant ! » aussi, puisque le traqueur de problèmes est généralement plein de "problèmes". :)
Nous prévoyons totalement de le tester dans Fedora (nous l'avions déjà prévu avant votre commentaire), cependant la date limite de mardi n'est probablement pas réaliste.
@hroncok Une idée de quand Fedora pourra-t-il tester ces changements ?
Je ferai de mon mieux pour le faire d'une manière ou d'une autre lundi, mais je ne peux faire aucune promesse.
En effet, 20.1b1 fait disparaître nos problèmes.
Commentaires plus généraux 20.1b1 dans https://mail.python.org/archives/list/[email protected]/message/5EAUIYYIRKXEHTAG5GQ7EJHSXGZIW2F7/
Hourra! Merci beaucoup d'avoir essayé la version bêta de @hroncok ! Très appréciée! ^>^
Un résultat de la construction en place : j'avais construit des roues pour plusieurs versions de python en parallèle (à l'intérieur d'un conteneur docker manylinux). Avec les builds sur place, les builds parallèles ne fonctionnent pas car les différentes versions sont en conflit. Avec les versions hors de l'arborescence, chaque version créait une arborescence distincte et n'avait pas de problème.
@manthey cette discussion est sous #8168
Cela fait donc plus de 10 jours maintenant. Quelques problèmes ont été soulevés à propos du changement (tous attendus, je dirais - #8165, #8168, #8196). Il y avait aussi des gens qui mentionnaient explicitement que le changement les aidait.
bdist_wheel
a --bdist-dir
, mais écrit toujours .egg-info
dans place, voir aussi https://github.com/pypa/setuptools/issues/1816, https://github.com/pypa/setuptools/issues/1825). Alors maintenant que pip se comporte correctement, la discussion peut changer pour voir si, par exemple, setuptools peut faire évoluer une option pour faire une construction sans toucher au répertoire source, puis regarder si une modification PEP 517 est nécessaire ou non pour contrôler cette option.Je déteste donc interrompre les changements, mais celui-ci n'a pas été fait à la légère, et pour ces raisons, je suis personnellement enclin à le garder.
Je ne suis pas d'accord pour dire que le nouveau comportement est que pip se comporte "correctement", différemment à coup sûr, et apparemment dans certains cas différemment cassé et je pense que le cadrer comme tel est incorrect. Cela représente un compromis pour un ensemble d'utilisateurs cassés pour un ensemble différent, dans les deux cas, des solutions de contournement pouvaient être effectuées.
Je n'aurais pas fusionné ce changement et je l'aurais manqué ou je me serais opposé à cela (et je pense que maintenant, l'ayant fusionné, cela rend certains l'utilisation de pip comme fonction de forçage pour aider à empêcher certains types de paquets cassés de manière beaucoup plus difficile ). Cela étant dit, je ne sais pas vraiment si revenir en arrière est la bonne chose ici. Cela peut devenir encore plus déroutant pour les utilisateurs si le comportement change beaucoup. Si nous voulons revenir en arrière, nous devons le faire rapidement, sinon le comportement actuel devrait probablement être meilleur ou pire.
J'ai utilisé le terme "correctement", car avant pip wheel <localdir>
et pip install <localdir>
généraient une roue différente de cd <localdir> ; setup.py bdist_wheel
dans certains cas : avec différents fichiers manquants en présence de liens symboliques (# 3500) ou une version différente avec setuptools_scm (#7549), ou https://github.com/pypa/pip/issues/7555#issuecomment -595180864, ou #6276, ou de simples erreurs. Je ne pense pas que le pip 20.1 génère de si mauvaises roues/installations, donc dans ce sens, je pense que c'est en effet plus correct.
Bien sûr, nous savions que le changement interromprait certains flux de travail et le compromis doit être réévalué maintenant que nous avons des commentaires, et être annulé ou confirmé pour de bon.
Et il peut toujours produire des roues différentes de setup.py sdist && pip install dist/*.tar.gz
.
Ma suggestion serait de rétablir le PR et de mettre en œuvre le correctif en parcourant d'abord un sdist, puis en créant une roue à partir du sdist résultant.
Cela devrait résoudre tous les problèmes d'exactitude, sauf dans les cas où le projet est incapable de créer correctement un sdist et qui, selon l'OMI, n'est pas un cas d'utilisation important à résoudre.
Le compromis est que ce sera plus lent. Cependant, une fois cela mis en œuvre, nous pouvons ensuite affiner davantage l'interface PEP 517 pour ajouter des API facultatives qui permettent des accélérations. Cela ne sera probablement jamais aussi rapide que ce changement, mais nous pouvons certainement nous en rapprocher.
Ce changement tel quel rend effectivement impossible de pousser plus loin l'exactitude sans introduire des régressions de performances dont les utilisateurs ne seront probablement pas satisfaits. Cependant, si nous corrigeons et améliorons les performances, nous pouvons arriver à un juste milieu qui satisfasse les deux parties.
Comme le dit le vieil adage, corrigez d'abord les choses, puis faites vite. Je crains qu'avec cette RP nous l'ayons accélérée et bloqué notre capacité à la corriger.
Je suis toujours d'accord pour que la validation des sdists soit souhaitable, mais pas au moment de l'installation de pip. C'est peut-être une fonctionnalité d'un futur outil de création de sdist ou d'une commande de construction pip.
De plus, setup.py sdist
crée .egg-info dans le répertoire local, de sorte que les problèmes signalés avec le répertoire source en lecture seule ou les versions simultanées resteraient.
Si cela ne se produit pas au moment de l'installation du pip, cela ne se produit fonctionnellement qu'au moment de l'installation du pip de quelqu'un d'autre. Le sauter signifie simplement que nous avons plusieurs chemins qu'un projet peut suivre pour aller de VCS au package installé et chaque chemin est une autre chance de différences. Ce n'est pas une nouveauté, fondamentalement, chaque option que nous avons qui modifie le chemin d'installation se retrouve avec un ensemble différent d'octets sur le disque, même pour les projets les plus rigoureux. Des différences subtiles existent toujours et vous espérez simplement que ces différences ne sont pas significatives - ou vous pouvez faire ce que vous pouvez pour supprimer ces différences en rendant structurellement impossible de les avoir dès le départ.
Certains problèmes de performances pourraient en effet réapparaître si/lors de la construction via sdist mais ils seraient probablement d'un ordre de grandeur inférieur à ce que nous avions dans pip < 20,1. En effet, la plupart d'entre eux résultaient souvent de la copie de .git
, ou d'un venv
, ou d'autres éléments volumineux sans rapport qui ne seraient pas dans le sdist.
Indépendamment de ce que pip
finira par finir, pourrions-nous faire de l'autre une option, car il est peu probable que l'un ou l'autre soit capable de satisfaire tout le monde ? J'imagine que si l'approche actuelle doit être conservée (je n'ai pas vraiment d'avis sur laquelle devrait être la valeur par défaut), nous devrions être en mesure de fournir un dernier résultat de secours où un utilisateur peut choisir de créer un sdist et d'installer le paquet à partir de là.
De plus,
setup.py sdist
crée.egg-info
dans le répertoire local, de sorte que les problèmes signalés avec le répertoire source en lecture seule ou les builds simultanés resteraient.
Je pense (au moins un test rapide est d'accord avec moi) que seul setuptools
(pas distutils
) le fait, et ce comportement est configurable pour créer le répertoire ailleurs. Semblable à d'autres backends, nous devrions être en mesure de leur recommander de faire une génération de sdist propre .
FWIW, je ne pense pas que nous aurions besoin de vider le répertoire sdist-generation --egg-info
dans le répertoire de travail, si nous adoptons l'approche generate-sdist-unpack-it-build-wheel, puisque nous pouvons déchargez-le dans un répertoire temporaire, comme nous le faisons pour generate_metadata
.
@pradyunsg cela ne nécessite-t-il pas un changement dans les outils de configuration ? La dernière fois que j'ai vérifié la commande sdist
n'avait pas d'option pour spécifier l'emplacement de base .egg-info
, contrairement à egg_info
qui a une option --egg-base
que nous avons exploitée dans #7978.
En effet! Je regardais le mauvais fichier dans setuptools. Je suis corrigé.
Pourquoi tout est-il si complexe dans cet espace ? :(
$ ls -la
total 8
drwxr-xr-x 3 dstufft staff 96 May 6 14:26 .
drwxr-xr-x 9 dstufft staff 288 Apr 28 15:46 ..
-rw-r--r-- 1 dstufft staff 85 Apr 23 16:23 setup.py
$ py setup.py egg_info --egg-base /tmp/foo sdist
/Users/dstufft/.pyenv/versions/3.8.2/lib/python3.8/site-packages/setuptools/dist.py:471: UserWarning: Normalizing '2020.04.23.3' to '2020.4.23.3'
warnings.warn(
running egg_info
creating /tmp/foo/dstufft.testpkg.egg-info
writing /tmp/foo/dstufft.testpkg.egg-info/PKG-INFO
writing dependency_links to /tmp/foo/dstufft.testpkg.egg-info/dependency_links.txt
writing top-level names to /tmp/foo/dstufft.testpkg.egg-info/top_level.txt
writing manifest file '/tmp/foo/dstufft.testpkg.egg-info/SOURCES.txt'
reading manifest file '/tmp/foo/dstufft.testpkg.egg-info/SOURCES.txt'
writing manifest file '/tmp/foo/dstufft.testpkg.egg-info/SOURCES.txt'
running sdist
warning: sdist: standard file not found: should have one of README, README.rst, README.txt, README.md
running check
warning: Check: missing required meta-data: url
warning: Check: missing meta-data: either (author and author_email) or (maintainer and maintainer_email) must be supplied
creating dstufft.testpkg-2020.4.23.3
copying files to dstufft.testpkg-2020.4.23.3...
copying setup.py -> dstufft.testpkg-2020.4.23.3
Writing dstufft.testpkg-2020.4.23.3/setup.cfg
creating dist
Creating tar archive
removing 'dstufft.testpkg-2020.4.23.3' (and everything under it)
$ ls -la
total 8
drwxr-xr-x 4 dstufft staff 128 May 6 14:28 .
drwxr-xr-x 9 dstufft staff 288 Apr 28 15:46 ..
drwxr-xr-x 3 dstufft staff 96 May 6 14:28 dist
-rw-r--r-- 1 dstufft staff 85 Apr 23 16:23 setup.py
https://github.com/pypa/pip/issues/8165#issuecomment -624669107 cela ressemble à un joli bogue d'arrêt, sans doute pas notre bogue mais c'est un type de bogues qui, selon moi, se produirait lors de la discussion PEP 517 lorsque faire sur place des versions par défaut est venu.
bdist_wheel
a été invité à nettoyer automatiquement son répertoire de construction dans le passé. Cette fonctionnalité devrait être intégrée. Les autres versions de distutils sont-elles propres ?
S'il s'agissait de SCons, il se souviendrait des fichiers dont il se souciait et omettrait les fichiers supplémentaires du répertoire build/ de la roue, même s'ils étaient présents dans le système de fichiers.
Je crois que le problème ci-dessus n'affecte pas seulement manylinux. Cela devrait arriver chaque fois que le répertoire de construction n'est pas assez spécifique pour capturer l'ABI (dans le cas de setuptools, il apparaît que la plate-forme et la version python sont tout ce qui est capturé dans la balise ABI du répertoire de construction). Je pense que cela s'étend au-delà de l'ABI avec l'interpréteur actuel aussi, si quelque chose est lié à NumPy par exemple, je pense qu'il a une ABI qui fonctionnera sur les NumPy plus récents, mais pas plus anciens, et à moins qu'ils ne codent cela dans le nom du répertoire de construction, cela fonctionnera effet utilise comme ça aussi.
Nettoyer automatiquement le répertoire de construction ne résout pas le problème, cela le rend juste moins probable (par exemple, exécuter deux invocations pip wheel
en parallèle pourrait toujours déclencher le problème), en plus de cela l'une des raisons supposées de l'implémentation de cette manière (au moins pendant la discussion PEP 517) était que cela fournirait plus de performances en permettant la mise en cache entre les appels pour les builds incrémentiels. IOW, le comportement actuel est ce que certains sous-ensembles voulaient, en réutilisant les artefacts de construction entre les exécutions, il se trouve que le backend de construction de loin le plus courant se trompe (et sans doute, dans certains cas, n'a pas assez d'informations pour bien faire les choses sans par personnalisation du package).
Bien sûr, avec suffisamment d'indicateurs pour la commande setuptools
sous-jacente, vous pouvez y remédier (quelque chose comme py setup.py egg_info --egg-base /tmp/foo build --build-base /tmp/foo/build-base bdist_wheel --bdist-dir /tmp/foo/bdist
ferait).
Je répète cependant que le problème ne vient pas des fichiers supplémentaires, c'est que l'ABI attendue avec laquelle la roue était compatible a changé et que le .so
n'a pas été reconstruit. Si SCons est suffisamment intelligent pour savoir que Python construit avec pymalloc a besoin d'un répertoire de construction et Python construit avec un autre (y compris des choses comme les versions NumPy auxquelles le .so
pourrait être lié), alors cela n'est pas affecté. S'il réutilise un artefact précédemment construit avec une ABI différente, il est affecté.
J'ai essayé de tester enscons mais je n'ai pas réussi à faire construire la rsalette sans erreur.
J'ai essayé de tester scikit-build pour voir comment il gérait les versions incrémentielles, et peu importe ce que j'ai fait, il a vomi sur lui-même lors de la 2ème version et j'ai dû supprimer manuellement le répertoire _skbuild
chaque fois pour l'obtenir exécuter sans erreur.
Frais. Désolé malheureusement, enscons a mis à jour et pas rsalette.
Le mercredi 6 mai 2020 à 16h18, Donald Stufft a écrit :
J'ai essayé de tester enscons mais je n'ai pas réussi à faire construire la rsalette sans erreur.
J'ai essayé de tester scikit-build pour voir comment il gérait les versions incrémentielles, et peu importe ce que j'ai fait, il a vomi sur lui-même lors de la 2ème version et j'ai dû supprimer manuellement le répertoire
_skbuild
chaque fois pour l'obtenir exécuter sans erreur.
-
Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, consultez-le sur GitHub https://github.com/pypa/pip/issues/7555#issuecomment-624867490 , ou désabonnez-vous https://github.com/notifications/unsubscribe-auth/AABSZERIEDAPUIXCPAKBBUDRQHAXRANCNFSM4KCV5MHQ .
Désolé malheureusement, enscons a mis à jour et pas rsalette.
Existe-t-il un bon poste C qui utilise des enscons mis à jour ? J'ai juste choisi rsalette parce qu'elle était la première de la liste et je n'avais pas envie de la déboguer, contente d'essayer avec autre chose.
Le seul problème avec rsalette
est qu'il ne devrait pas passer ROOT_IS_PURELIB
à Environment dans SConstruct. Il n'a pas d'extension C. cryptacular
semble correct.
Sur ce, je pense que je suis d'accord pour dire que nous devrions annuler ce changement.
Je pense que les nouveaux problèmes sont beaucoup plus importants que prévu. Peut-être un rapide 20.1.1 pour revenir et ensuite nous pourrons avoir une discussion plus longue sur la façon de résoudre les problèmes de builds in-tree et out-of-tree ?
Je vote également pour revenir et poursuivre https://discuss.python.org/t/proposal-adding-a-persistent-cache-directory-to-pep-517-hooks/2303/15 comme solution pour cela (ce serait permettre aux backends de se construire pas en place, donc ne pas exposer de tels problèmes). Chim dans ce fil aussi si vous êtes d'accord avec la suggestion là-bas.
Cela me semble également judicieux. Je pense qu'une approche in-tree (ou build-from-sdist) présente des avantages extrêmement importants (je suis presque sûr que nous aurons des plaintes d'une partie de la base d'utilisateurs lorsque nous reviendrons 🙂) mais les inconvénients sont également important.
Je ne sais pas ce que l'interface utilisateur devrait être ici (à quelle approche par défaut ? quel type d'options devrions-nous avoir ?) mais je pense que nous devrions prendre un peu plus de temps pour décider cela, plutôt que de prendre des décisions tout en combattant les problèmes actuels .
D'accord ! Je pense que le consensus général est de revenir en arrière et de réévaluer. Je vais déposer un PR pour cela. :)
Chim dans ce fil aussi si vous êtes d'accord avec la suggestion là-bas.
S'il vous plaît faites - j'ai commenté, mais j'en suis au point où je n'en sais pas assez pour offrir des suggestions significatives, donc la contribution de personnes ayant plus d'expérience serait précieuse.
Je viens de déposer quelques gros blobs de texte dans https://github.com/pypa/pip/issues/8165#issuecomment -625401463. Je vais m'éloigner pour aujourd'hui... J'ai fini par me sentir un peu frustré en écrivant les notes personnelles à la fin. Se retrouver sur #5599 et lire les commentaires négatifs des utilisateurs n'a certainement pas aidé.
Salut les gens, j'ai réfléchi un peu plus à cela, voici mon point de vue actuel sur cette question.
- Construisez un sdist en place, décompressez le sdist dans un emplacement temporaire, puis construisez à partir de là.
Je pense toujours que pip install / pip wheel n'est pas le bon endroit pour essayer d'attraper les mauvais sdists. Cela ne devrait-il pas être une responsabilité en arrière-plan de ne pas créer de mauvais sdists en premier lieu ? De plus, je pense que la construction inconditionnelle via sdist est probablement aussi perturbatrice que la construction en place.
- Ajoutez une option de pip à construire sur place.
Celui que je préfère à court terme, puisque la solution 4 ne l'a pas fait. Est-il prématuré d'ajouter cela dans le pip 20.1.1 ?
- Mettez à jour PEP 517 avec une sorte de mécanisme permettant aux back-ends de communiquer avec les front-ends s'ils sont "sûrs" pour les builds sur place.
Avec ce pip, il faudrait encore se rabattre sur son copytree cassé et irréparable, donc je ne suis pas en faveur de celui-ci.
- Changez le pip pour toujours construire en place.
Celui-ci est donc jugé trop perturbateur et nous y reviendrons en 20.1.1.
- Changez le pip pour construire sur place par défaut avec une option pour construire hors de l'arbre.
Cela pourrait être l'objectif à long terme, l'option de créer un mélange hors de l'arbre avec le concept de répertoire de cache ?
Je n'aime vraiment pas les options CLI, en particulier celles comme celle-ci. Que se passe-t-il si je répertorie deux packages qui se trouvent sur mon FS local et que je dois en créer un en place et un non ? Si nous proposons une option pour faire l'un ou l'autre, il va se retrouver avec des packages existants qui ne peuvent être construits qu'avec l'un ou l'autre.
Cela me sent aussi comme le genre d'option qui existe entièrement parce qu'un projet n'a pas pu prendre de décision et a décidé de simplement repousser cette décision à l'utilisateur final.
Construire via sdist ne consiste pas exactement à attraper les mauvais sdist. Il s'agit en grande partie de réduire les variations possibles de "chemin" qu'un projet peut parcourir avant d'être installé. L'ajout d'un indicateur à certains égards aggrave ce problème, pas mieux.
Pour ce que je veux dire, nous avons quelques "chemins" par lesquels les installations peuvent passer :
Certains chemins supplémentaires sont en quelque sorte supprimés, mais en général, ce sont nos 3 (et idéalement, 3 sont également supprimés). Il existe également des installations modifiables, mais elles ne vont pas disparaître de sitôt.
Nous pouvons considérer qu'un sdist ou une roue sont téléchargés sur PyPI et installés à partir de là pour faire partie du même "chemin", vous le mettez simplement en pause et le terminez sur un autre ordinateur.
Le problème d'avoir plusieurs "chemins" comme celui-ci, c'est qu'il introduit des incohérences dans l'installation finale résultante. Ils ne se produisent pas toujours, mais c'est un cas facilement observable que cela se produit fréquemment. Souvent, ces incohérences ne sont pas importantes, mais parfois elles le sont.
Si nous faisons des constructions sur place comme celle-ci, alors nous disons en fait que nous ne pourrons jamais nous effondrer sur un seul chemin, et nous devrons toujours faire face à ce cas limite étrange où parfois les gens obtiendront des résultats différents en fonction de la façon dont l'installation a été effectuée.
En tant qu'avantage supplémentaire, cela peut également agir comme une fonction de forçage pour aider à garantir que le chemin heureux reste heureux.
La plupart du temps, je suis d'accord avec @dstufft , et en particulier je suis d'accord pour que l'approche build-from-sdist ne soit pas considérée comme "essayer de valider sdists" mais comme "tout suit l'arborescence des sources -> sdist -> wheel -> install route (juste certaines choses sautent certaines étapes initiales)".
Cependant, je veux revenir sur un point :
Que se passe-t-il si je répertorie deux packages qui se trouvent sur mon FS local et que je dois en créer un en place et un non ?
Exécutez simplement les deux packages dans deux séries de pip distinctes avec des options différentes ?!? Je sais qu'il est possible que l'un soit une dépendance de l'autre et votre point de vue est en général valable, mais il semble y avoir une tendance générale pour les gens à supposer que chaque scénario d'installation doit être réduit en une seule série de pip, et je ne ' Je pense que c'est raisonnable (nous avons eu de très bonnes solutions de contournement pour que les problèmes soient rejetés par l'utilisateur car "cela signifie que je devrais diviser ma liste d'exigences en deux")
Notez que lorsque (si) nous revenons, nous devrons rouvrir des problèmes comme #6276 qui a été fermé à la suite de la mise en œuvre de builds in-tree.
Une partie du problème est que pip ne tient pas compte de ce qui est déjà installé lors de la résolution des dépendances (je ne sais pas si le nouveau travail du résolveur change cela ?), vous devez donc avoir tout contenu dans une seule invocation pip si vous voulez le résoudre dépendances "correctement" (dans la mesure où notre résolveur actuel fait quelque chose correctement).
Si le nouveau résolveur prend en compte ce qui est déjà installé, alors pip install foo bar
et pip install foo && pip install bar
seraient à peu près égaux et n'auraient aucune importance, mais si ce n'est pas le cas (et c'est à peu près vrai maintenant) si les deux projets dépendaient de "spam" mais que foo requis < 2 et bar requis > 1, nous obtiendrions une installation invalide.
C'est une tangente cependant :)
(Je ne sais pas si le nouveau travail de résolution change cela ?)
Entrées bienvenues au #7744. :)
- Changez le pip pour toujours construire en place.
Celui-ci est donc jugé trop perturbateur et nous y reviendrons en 20.1.1.
Pour être clair, c'est aussi que nous l'avons "déployé trop vite" et l'approche de déploiement que nous avons adoptée explique certainement en partie pourquoi cela a fini par être trop perturbateur.
- Ajoutez une option de pip à construire sur place.
@dstufft @pfmoore Je vois ce type d'option comme un mécanisme d'inscription afin que nous puissions progressivement inciter les utilisateurs à se tourner vers des versions sur place dans le but d'en faire la valeur par défaut à un moment donné. Dans l'esprit de ce commentaire : https://github.com/pypa/pip/issues/8165#issuecomment -625501216
Je vais déposer un PR pour cela. :)
20.1.1 a été publié, contenant les modifications annulées.
Dans Fedora, lorsque nous construisons des packages Python RPM, nous sommes des dinosaures et la façon standard de procéder est d'utiliser
python setup.py build
. Avec PEP 517, nous avons ajouté une manière "provisoire" d'utiliserpip wheel
place. Cependant, avec les modules d'extension, nous avons un problème avec l'approche "déplacer les sources vers tmp, construire à partir de là" que pip utilise pour les construire.Notre machine de construction injecte des drapeaux de compilateur afin que les artefacts de construction (les modules d'extension
.so
dans ce cas) contiennent des métadonnées sur leurs sources. Plus tard, un script shell parcourt les artefacts de construction, extrait ces informations et copie les sources dans/usr/src/debug
pour être installé via un RPM spécial*-debugsource
. La mahcinery s'attend à ce que tout soit construit dans l'arbre de travail et cela ne fonctionne pas vraiment bien lorsqu'il est construit à l'extérieur. Voici les choses qui peuvent être faites (ensemble) pour atténuer le problème de notre côté :1. set the `$TMPDIR` environment variable to have it within the place where the RPM script expects it (i.e. `export TMPDIR=%{_builddir}/.tmp` (and create it)) 2. use `pip wheel` with the `--no-clean` option to keep the copied sources in `$TMPDIR` 3. run some shell kung fu to rewrite the "what is my source" information to the correct location: `find %{buildroot} -iname '*.so' -print0 | xargs --no-run-if-empty -0 -n1 /usr/lib/rpm/debugedit -b "%{_builddir}/.tmp/pip-req-build-"* -d "$PWD"` 4. (Optional: clean `$TMPDIR` manually.)
C'est effectivement le chemin que j'ai emprunté en cherchant l'intégration de pip, #6505, etc.
Les versions itératives avec pip sont effectivement cassées aujourd'hui, ce qui est une perte majeure pour les groupes qui ont une grande quantité de code python sous forme d'extension C, j'ai donc eu recours à la construction avec setup.py
.
pip
besoin d'une commande build
et le résultat final de la commande build
doit être transmissible à d'autres sous-commandes, comme wheel
, install
, etc.
À l'heure actuelle, pip
traite efficacement install
comme build
et install
, ce qui n'est _pas_ ce que veulent certaines personnes qui créent et mettent en cache des artefacts binaires, installant des binaires sur read -seulement les montures, etc.
Je souhaite vraiment qu'il y ait un moyen d'utiliser setup.py
pour construire les binaires, puis pip install
sans recourir à la création d'un bdist
, mais cela ne semble pas être possible aujourd'hui , puisque pip
et distutils
/ setuptools
ne sont pas d'accord sur l'endroit où trouver les artefacts binaires.
Je souhaite vraiment qu'il y ait un moyen d'utiliser setup.py pour construire les binaires, puis pip les installe sans avoir recours à la création d'un bdist, mais cela ne semble pas être possible aujourd'hui, car pip et distutils/setuptools ne sont pas d'accord sur où trouver les artefacts binaires.
Je ne suis pas sûr d'avoir suivi - vous dites que vous voulez un moyen d'utiliser des binaires mais que vous ne voulez pas utiliser les formats de distribution binaires qui existent déjà. Pourquoi donc?
Je souhaite vraiment qu'il y ait un moyen d'utiliser setup.py pour construire les binaires, puis pip les installe sans avoir recours à la création d'un bdist, mais cela ne semble pas être possible aujourd'hui, car pip et distutils/setuptools ne sont pas d'accord sur où trouver les artefacts binaires.
Je ne suis pas sûr d'avoir suivi - vous dites que vous voulez un moyen d'utiliser des binaires mais que vous ne voulez pas utiliser les formats de distribution binaires qui existent déjà. Pourquoi donc?
Les formats bdist sont extrêmement limitatifs. Mon groupe doit recourir à un format stupide, comme tar, puis le décompresser mot pour mot (aucun des BSD n'est pris en charge, Debian n'est pas pris en charge, etc.).
Ce que j'ai découvert hier soir, c'est que l'utilisation d'un bdist stupide n'est pas installable via pip
. Les binaires stupides ne disposent pas des métadonnées nécessaires pour être installés via pip
, AFAICT, c'est là que je suppose que les roues de pip entrent en jeu.
J'ai également essayé egg et zip, mais il leur manque les métadonnées nécessaires à l'installation à l'aide d'un URI file://
.
J'ai essayé d'essayer de construire via distutils, setuptools dans un système de construction plus large en utilisant make, donc je ne peux pas dire si j'ai fait "tout ce qu'il fallait" pour que les choses fonctionnent comme un bdist
standard
Venant de https://github.com/pypa/pip/issues/2195#issuecomment -664728481 je peux dire que je suis plus qu'heureux de refaire #7882 derrière --use-feature=in-tree-build
.
Hourra! Ça ma l'air bon!
Mettons également à jour la docstring de --build
cette fois. ;)
Venant de #2195 (commentaire), je peux dire que je suis plus qu'heureux de refaire #7882 derrière --use-feature=in-tree-build.
Curieux de savoir si cela aussi bien que par ligne de commande, il serait raisonnable d'avoir une option in-tree-build
définie dans pyproject.toml
? Ce serait plutôt sympa pour résoudre #6276 sans avoir besoin de créer un script bash ou un makefile pour envelopper pip. (Ce n'est pas un problème particulièrement important.)
avoir une option in-tree-build définie dans pyproject.toml
@davidhewitt c'est plus ou moins l'option 3 dans la description originale de ce problème. Je crois comprendre que le consensus actuel est qu'il vaut mieux éviter une option supplémentaire si nous le pouvons. Par conséquent, l'idée d'activer les builds in-tree avec --use-feature
pendant une période de transition, avec un objectif à plus long terme d'en faire le seul et unique mécanisme par défaut.
BTW, je ne pourrai pas implémenter cela à temps pour 20.3, mais j'ai toujours l'intention de le faire, j'espère en 20.4.
@sbidoul J'ai écrit un patch pour aider à
Commentaire le plus utile
Venant de https://github.com/pypa/pip/issues/2195#issuecomment -664728481 je peux dire que je suis plus qu'heureux de refaire #7882 derrière
--use-feature=in-tree-build
.