Pipenv: Proposition : patterns et antipatterns `pipenv` pour le projet de bibliothèque python

Créé le 5 avr. 2018  ·  74Commentaires  ·  Source: pypa/pipenv

Piratage de maya J'ai appris quelques leçons qui ont abouti à ma proposition suivante d'utilisation recommandée de pipenv dans les bibliothèques python. Je m'attends à ce que d'autres examinent la proposition et si nous parvenons à un accord, le texte (mis à jour) pourrait se retrouver dans des documents pipenv .

pipenv modèles et anti-modèles pour le projet de bibliothèque python

ÉDITER
Ce qui suit s'applique le mieux aux bibliothèques python générales (principalement Open Source), qui sont censées s'exécuter sur différentes versions de python et systèmes d'exploitation. Les bibliothèques développées dans un environnement d'entreprise strict peuvent être des cas différents (n'oubliez pas de consulter toutes les sections Problèmes de toute façon).

FIN DE MODIFICATION

TL;DR : L'ajout pipenv fichiers gardez Pipfile , Pipfile.lock et .env hors du contrôle des sources de la bibliothèque.

Vous pourrez utiliser toute la puissance de pipenv quels que soient les fichiers résidant dans .gitignore .

Bibliothèque Python versus application python

Par bibliothèque python setup.py , ciblé pour la distribution et l'utilisation sur diverses plates-formes différant par la version python et/ou le système d'exploitation.

Exemples : maya , requests , flask etc.

De l'autre côté (pas de bibliothèque python), il existe des applications ciblées pour un interpréteur python spécifique, un système d'exploitation et souvent déployées dans un environnement strictement cohérent.

pipfile décrit très bien ces différences dans Pipfile vs setup.py .

Qu'est-ce que pipenv (outil de déploiement)

Je suis tout à fait d'accord sur l'affirmation selon laquelle pipenv est un outil de déploiement car il permet de :

  • définir des exigences strictes ( Pipfile.lock ) pour le déploiement de l'environnement virtuel
  • appliquer ces exigences strictes de manière reproductible sur différentes machines

Cela aide lorsque l'on doit déployer une application ou développer dans un environnement python très cohérent entre plusieurs développeurs.

Appeler l'outil de packaging pipenv est trompeur si l'on s'attend à ce qu'il crée des bibliothèques python ou qu'il soit profondément impliqué dans leur création. Oui, pipenv peut aider beaucoup (dans le développement local de bibliothèques) mais peut éventuellement nuire (souvent dans les tests CI lorsqu'il est utilisé sans réflexion approfondie).

Appliquer des « raisons de sécurité » dans un mauvais contexte

TL;DR : pipenv fournit un environnement sécurisé via l' application de dépendances concrètes approuvées décrites dans le fichier Pipfile.lock et la bibliothèque python est uniquement autorisée à définir des dépendances abstraites (ne peut donc pas fournir Pipfile.lock ).

pipenv brille dans les scénarios de déploiement en suivant ces étapes :

  • définir des dépendances abstraites (via Pipfile )
  • générer à partir de celui-ci des dépendances concrètes résultant en Pipfile.lock
  • créer un environnement python (virtuel) reflétant ces dépendances concrètes
  • exécuter des tests pour vous assurer que l'environnement donné fonctionne comme prévu et est sécurisé
  • publier le "golden" testé Pipfile.lock comme définition de l'environnement python approuvé
  • d'autres peuvent utiliser pipenv sync pour appliquer "l'or" Pipfile.lock ailleurs en obtenant un environnement python identique.

Avec le développement de la bibliothèque python, on ne peut pas atteindre une telle sécurité, car les bibliothèques ne doivent pas définir de dépendances concrètes . Le non-respect de cette règle (en essayant ainsi de déclarer des dépendances concrètes par la bibliothèque python) entraîne des problèmes tels que :

  • problèmes pour trouver une version satisfaisante des bibliothèques partagées (chaque paquet strict définit la version exacte de la bibliothèque partagée et il est très probable que les versions diffèrent et empêchent de trouver une version communément acceptable)
  • les dépendances concrètes peuvent dépendre de la version de python, du système d'exploitation ou d'autres marqueurs d'environnement et essayer d'installer le package dans un contexte différent peut facilement échouer à satisfaire certaines des règles définies dans les dépendances abstraites d'origine.

Problème : Cacher les dépendances définies de setup.py brisées

setup.py doit définir toutes les dépendances abstraites via install_requires .

Si Pipfile définit également ces dépendances, cela peut facilement masquer des problèmes tels que :

  • dépendance manquante dans install_requires
  • Pipfile définit des règles spécifiques (plages de versions, etc.) pour une dépendance et pas install_requires .

Pour l'éviter, suivez ces règles :

  • les dépendances définies par la bibliothèque ne doivent pas apparaître dans Pipfile
  • la section [packages] dans Pipfile doit être soit vide, soit définir une seule dépendance sur la bibliothèque elle-même.

Problème : Pipfile.lock dans le référentiel

Conserver Pipfile.lock (généralement pour des « raisons de sécurité ») dans le référentiel de la bibliothèque est incorrect, car :

  • les dépendances décrites sont susceptibles d'être invalides pour différentes versions de python ou dans un autre système d'exploitation
  • les développeurs sont obligés de mettre à jour le fichier non seulement lorsqu'ils ajoutent/suppriment une dépendance, mais également lorsque d'autres bibliothèques sont mises à jour et peuvent être utilisables dans la bibliothèque.

Pour l'éviter, il faut :

  • supprimez Pipfile.lock du référentiel et ajoutez-le dans .gitignore

Problème : Concurrencer tox (cacher usedevelop )

Si tox.ini contient dans sa section commands entrées telles que :

  • pipenv install
  • pipenv install --dev
  • pipenv lock

c'est souvent un problème, car :

  • pipenv install n'installera que la bibliothèque elle-même, et tox fait (par défaut) aussi. En dehors de la duplicité, cela empêche également usedevelop=True et usedevelop=False dans tox.ini car Pipenv ne peut l'exprimer que dans une variante (et tox.ini permet des différences dans différents environnements).

Pour l'éviter, il faut :

Problème : casser les builds, si pipenv échoue

pipenv est en cours de développement et les choses se cassent parfois. Si un tel problème casse votre build CI, il y a un échec qui pourrait être évité en n'utilisant pas pipenv et en utilisant des outils traditionnels (qui sont souvent un peu plus matures).

Pour l'éviter, il faut :

  • réfléchissez à deux fois avant d'ajouter pipenv dans un script de construction CI, tox.ini ou un endroit similaire. Savez-vous quelle valeur vous obtenez en l'ajoutant? Le travail pourrait-il être fait avec l'outillage existant?
  • ne l'ajoutez pas "juste pour des raisons de sécurité" ou parce que "tout le monde le fait".

Sommaire

Les questions clés concernant le rôle de pipenv dans le développement de la bibliothèque Python sont :

  • Quelle valeur pipenv apporte vraiment ? R : Outil de gestion Virtualenv.
  • Quel est le cas d'utilisation pertinent pour pipenv ? R : Gérer virtualenv.
  • Apparaîtra-t-il dans le dépôt de la bibliothèque ? R : NON.

Quelques autres détails et astuces suivent.

pipenv n'ajoutera aucune sécurité à votre forfait

Ne le poussez pas dans le projet simplement parce que tout le monde le fait ou parce que vous attendez une sécurité supplémentaire. Cela vous décevra.

La sécurisation à l'aide de dépendances concrètes (et approuvées) aura lieu dans une phase ultérieure dans l'application qui va utiliser votre bibliothèque.

Conservez les fichiers Pipfile , Pipfile.lock et .env hors du référentiel

Mettez les fichiers dans .gitignore .

Pipfile est facile à recréer comme démontré ci-dessous car la plupart ou toutes les exigences sont déjà définies dans votre setup.py . Et le fichier .env contient probablement des informations privées, qui ne doivent pas être partagées.

Garder ces fichiers hors du référentiel évitera tous les problèmes qui peuvent survenir avec les builds CI lors de l'utilisation de pipenv dans des situations qui ne sont pas appropriées.

pipenv comme boîte à outils privée du développeur

pipenv peut simplifier le travail du développeur en tant qu'outil de gestion de virtualenv.

L'astuce consiste à apprendre comment recréer rapidement vos fichiers associés (privés) pipenv , par exemple :

$ cd <project_repository>
$ # your library will bring the dependencies (via install_requires in setup.py)
$ pipenv install -e .   
$ # add more dev tools you preffer 
$ pipenv install --dev ipython pdbpp
$ # start hacking
$ pipenv shell
...

Utilisez le fichier .env si vous avez besoin d'une méthode pratique pour configurer les variables d'environnement.

N'oubliez pas : gardez l'utilisation de pipenv hors de vos builds CI et votre vie sera plus simple.

Astuce : utilisez la capacité de setup.py pour déclarer des dépendances supplémentaires

Dans votre setup.py utilisez la section extras_requires :

from setuptools import setup

setup(
    name='mypackage',
    ....,
    install_requires=["jinja2", "simplejson"],
    extras_require={
        'tests': ['pytest', 'pyyaml'],
        'pg': ['psycopg2'],
    },
    ....
)

Pour installer toutes les dépendances déclarées pour tests supplémentaires :

$ pipenv install -e .[tests]

Notez qu'il inclura toujours les dépendances install_requires .

Cette méthode ne permet pas de diviser les dépendances en sections par défaut et dev, mais cela ne doit pas poser de réel problème dans les scénarios attendus.

Discussion Type

Commentaire le plus utile

@ Moritz90 Plusieurs listes de diffusion de Python seraient de bons endroits pour tenir cette discussion.

pypa-dev est le plus précis pour les discussions centrées sur l'emballage Python et l'écosystème qui l'entoure. Je commencerais probablement ici si je devais poster une discussion similaire.

python-ideas est un endroit pour discuter d'idées et a une visibilité assez élevée pour l'ensemble de la communauté Python. Ce serait également un bon point de départ si vous souhaitez pousser cela au niveau PEP (éventuellement, vous le feriez, je pense).

Tous les 74 commentaires

C'est très impressionnant, merci beaucoup pour la compilation. Je vais certainement revoir plus en détail dans un peu

/cc @uranusjr @jtratner @ncoghlan

Quelques références à des problèmes de maya :

  • kennethreitz/maya#138 (SupprimerPipfile.lock du référentiel)
  • kennethreitz/maya#139 (Ignorer l'exécution de pipenv dans tox.ini ...)
  • kennethreitz/maya#145 (correction de pendulum>=1.0 dans setup.py : la version était dans Pipfile mais manquait dans setup.py)
  • kennethreitz/maya#143 (PR montrant comment le problème pipenv cassé toute la course de Travis)
  • kennethreitz/maya#144 (PR Refactor utiliser pipenv selon les meilleures pratiques semi-officielles)

J'aime ça aussi. Peut-être devrions-nous ajouter cela à la documentation de Pipenv, ou même au Python Packaging User Guide .

Le corollaire du conseil ci-dessus semble être "renoncer aux constructions d'IC ​​déterministes/reproductibles", ce qui me semble être un très grand anti-modèle.

Que proposez-vous comme alternative qui permettrait encore le déterminisme ?

@tsiq-oliverc Les builds déterministes ont leur place en ce moment, une application est à construire.

Imaginez la tentative suivante d'effectuer des constructions vraiment déterministes de la bibliothèque python :

  • les versions doivent être basées sur Pipfile.lock
  • chaque contexte d'exécution (combinaison de chaque variante python et système d'exploitation) peut avoir des Pipfile.lock résultant des dépendances abstraites de la bibliothèque définies dans Pipfile
  • Le référentiel devrait fournir des instances Pipfile.lock distinctes définies dans le référentiel. Notez que la construction automatique de Pipfile.lock lors de la construction de CI n'ajoute aucun déterminisme

C'est beaucoup d'efforts supplémentaires. Et ce que vous obtenez est une bibliothèque, qui sera installée dans un contexte différent (par exemple, une semaine plus tard, l'installation standard prendra une dépendance mise à niveau ou deux) et qui n'obtiendra rien du fait que vous avez utilisé Pipfile.lock , qui est pour le moment obsolète.

Le conflit réside dans le fait que la bibliothèque ne doit jamais définir de dépendances strictes à l'intérieur.

Si vous pensez qu'il existe une autre alternative pour obtenir des constructions déterministes pour la bibliothèque python - décrivez-la.

@vlcinsky - Si un consommateur de votre bibliothèque utilise différentes versions de dépendances, etc., cela est hors de votre contrôle. Je suis donc d'accord qu'il n'y a aucun moyen possible pour un mainteneur de bibliothèque de gérer cela.

Mais l'objectif ici est vraisemblablement d'une portée beaucoup plus petite. En particulier, je considérerais les objectifs d'un mainteneur de bibliothèque comme les suivants (qui sont à peu près des équivalences) :

  1. Si vous exécutez votre CI deux fois, vous êtes assuré d'obtenir le même résultat (malgré les problèmes de réseau !).
  2. Vous pouvez recréer localement (et donc déboguer) le comportement que vous observez sur CI, même si cela signifie exécuter Docker/etc. localement.
  3. Vous pouvez dire en toute confiance "Ma bibliothèque se comporte comme prévu avec les versions de dépendance X, Y, Z" à vos consommateurs.

Si l'une de ces trois choses ne tient pas, cela me semble contraire au contrôle qualité.

Alors oui, je dirais que si vous garantissez la prise en charge des variantes Python A, B et C à votre consommateur, et qu'elles se comportent suffisamment différemment pour qu'un fichier de verrouillage (etc.) ne le coupe pas, alors vous devriez avoir trois fichiers de verrouillage (ou peu importe).

Cependant, je n'ai pas assez utilisé Pipenv pour savoir à quel point ce serait facile dans la pratique.

J'envisage actuellement d'ajouter des Pipfile s à quelques projets de bibliothèque pour le système CI également.

J'ai absolument besoin du verrouillage des dépendances (+ hachage) pour me conformer aux directives de sécurité à l'échelle de l'entreprise et je n'ai actuellement pas besoin de tester avec différentes versions de Python, car il n'y en a qu'une qui est officiellement prise en charge. Et le fait que pipenv simplifie la configuration d'un environnement de développement local, y compris virtualenv, est un bel effet secondaire.

Et ce que vous obtenez est une bibliothèque, qui sera installée dans un contexte différent (par exemple, une semaine plus tard, l'installation standard récupérera une dépendance mise à niveau ou deux) et qui n'obtiendra rien du fait que vous avez utilisé Pipfile.lock , qui est pour le moment obsolète.

Ce n'est pas universellement vrai. Dans le monde des logiciels d'entreprise, vous avez toujours des environnements très spécifiques qui sont officiellement pris en charge et un problème de sécurité dans une dépendance entraîne la mise à jour de votre produit plutôt que la mise à jour de la dépendance par le client lui-même.

(Oui, je parle d'une bibliothèque, pas d'une application ici...)

@ Moritz90, votre scénario concerne la bibliothèque python dans un environnement d'entreprise et pipenv peut aider car il s'agit d'un environnement beaucoup plus déterministe.

Ma description vise les bibliothèques python générales telles que flask , request , maya etc. où le contexte est beaucoup plus variable. En essayant de résoudre quelques problèmes dans maya j'ai été frustré d'apprendre que, dans de nombreux cas, l'utilisation de pipenv introduisait de vrais problèmes (cachant généralement des problèmes qui seraient normalement détectés) tout en n'apportant pas grand-chose ni aucun ajout valeur.

Obtenir des builds déterministes est une bonne chose, mais cela entraîne des coûts. Et si c'est mal fait, vous pouvez payer un supplément pour un résultat de qualité inférieure - et c'est ce que je voulais éviter.

Je dirais que c'est l'un des cas où nous ne voulons pas que les versions soient absolument déterministes. Si vous n'épinglez pas vos dépendances avec == , vous vous engagez à maintenir la prise en charge de plusieurs versions par défaut et devez concevoir la bibliothèque de cette façon. Une mise à niveau de dépendance interrompant la construction sur CI est en fait une bonne chose car elle expose un bogue dans la bibliothèque. Des dépendances complètement déterministes (telles que gérées par Pipenv) masqueraient cela. Il serait quand même avantageux de pouvoir être déterministe quand on le veut, ce n'est généralement pas le mieux.

@uranusjr - Bien sûr. Je suis d'accord que si le désir est "des constructions non déterministes", alors le conseil en haut peut bien avoir du sens. En fait, c'est presque une équivalence logique, et on pourrait l'énoncer beaucoup plus succinctement : "Si vous ne voulez pas de builds déterministes, alors n'utilisez pas d'outil ( pipenv ) dont le but est d'assurer des builds déterministes" .

Mais ce n'est certainement pas un objectif souhaitable en général.

@tsiq-oliverc belle définition de la portée - il prend en charge une discussion ciblée. J'ajouterais une autre exigence : le déterminisme CI ne doit pas masquer les problèmes possibles au sein de la bibliothèque testée.

Si nous utilisons Pipenv.lock , créons virtualenv sur cette base et exécutons le test CI de la bibliothèque, nous avons fait une partie de la fonctionnalité que la bibliothèque est censée faire - installer les dépendances appropriées. Si la bibliothèque est en quelque sorte cassée à cet égard, l'environnement préinstallé masquerait ce problème.

Il me semble plus important de détecter les problèmes au sein d'une bibliothèque que d'exécuter CI de manière déterministe. S'il existe un moyen de faire les deux (par exemple, exécuter le test derrière l'index pypi privé, qui pourrait également prendre en charge le déterminisme), je n'ai aucun problème, mais s'il y a un conflit, j'ai mes priorités.

Ne vous méprenez pas : il n'y a aucun désir d'exécuter des builds non déterministes, mon désir est d'exécuter des builds CI, qui détecteront autant de problèmes que possible.

@vlcinsky Bien sûr, je voulais juste partager mon expérience pour m'assurer que la documentation mise à jour le reflète également. La documentation actuelle explique très bien les compromis :

Pour les bibliothèques, définissez les dépendances abstraites via install_requires dans setup.py. [...]
Pour les applications, définissez les dépendances et où les obtenir dans le Pipfile et utilisez ce fichier pour mettre à jour l'ensemble des dépendances concrètes dans Pipfile.lock. [...]
Bien sûr, Pipfile et pipenv sont toujours utiles pour les développeurs de bibliothèques, car ils peuvent être utilisés pour définir un environnement de développement ou de test.
Et, bien sûr, il y a des projets pour lesquels la distinction entre bibliothèque et application n'est pas si claire.

(Souligné la partie qui s'applique dans mon cas.)

Je veux juste m'assurer que ça reste comme ça. Je pense que votre message d'origine contient trop de déclarations générales sans avertissement selon lequel vous parlez d'un projet open source qui va être publié sur PyPI.

@ Moritz90 Je suis tout à fait d'accord. J'essayais de mettre en évidence cet objectif, mais je peux le rendre encore plus visible.

@ Moritz90 J'ai ajouté une note d'introduction reflétant votre commentaire.

@vlcinsky - Cela a du sens. Je comprends que vous n'avez pas explicitement voulez construit non-déterministe, mais je pense qu'il est inéluctablement équivalent à ce que vous voulez ( par exemple à des problèmes de capture lorsque la mise à jour vos dépendances en amont).

En réfléchissant à voix haute, quelle est la meilleure façon de résoudre ces deux objectifs contradictoires ? Une possibilité est d'avoir un processus d'IC ​​en deux phases :

  1. La phase déterministe. Tire parti d'un Pipfile.lock dans votre repo, il est donc entièrement reproductible.
  2. La phase non déterministe. Exécute pipenv update puis exécute les tests, de sorte qu'il récupère la dernière de toutes vos dépendances (ce qui est fondamentalement le même que le comportement sans fichier de verrouillage, je pense?).

@tsiq-oliverc Pour obtenir des versions déterministes, je penserais à la configuration suivante :

  • build pypi cache job : exécuté une fois, produisant une forme de cache d'index pypi (en tant que répertoire de fichiers ou quelque chose de similaire)
  • travail de test de bibliothèque : en utilisant le cache pypi, mais en évitant pipenv

Utiliser pipenv pour effectuer l'installation est similaire à ce que l'installation de la bibliothèque elle-même doit faire, mais c'est définitivement différent car c'est un code différent qui fait le travail.

construire un travail de cache pypi

$ git clone <repo_url> <project_dir>
$ cd <project_dir>
$ pip install pipenv
$ $ # clean pypi cache and make it ready to cache somehow - not described here
$ pipenv install -e .[test]
$ # if we need extra testing packages in pipenv
$ pipenv install <extra_test_packages>
$ # record current requirements expressed in `Pipfile.lock`
$ pipenv lock
$ # if needed, record the `Pipfile.lock` somewhere

Les résultats d'un tel travail sont :

  • Pipfile.lock tant que dépendances enregistrées (peut aider les développeurs à reproduire facilement l'environnement)
  • cache pypi local pré-rempli

travail de test de bibliothèque

il y a des phases :

  • configurer l'environnement pour forcer tox , pip etc. en utilisant uniquement notre cache pypi local
  • exécuter les tests CI (éviter d'utiliser pipenv )

ce que nous obtenons

  • la bibliothèque est testée dans un environnement déterministe
  • la bibliothèque est testée incl. c'est sa capacité à s'installer tout seul
  • Pipfile.lock enregistre les packages pypi qui ont été utilisés pour installer la bibliothèque. Il peut être utilisé pour reproduire l'environnement sur le site du développeur.
  • l'adaptation aux packages mis à niveau sur pypi (éventuellement externe) est simple (réexécutez le "build pypi cache job) et se fait de manière contrôlée (le contenu de pypi est enregistré, y compris les hachages)

Un autre avantage est que cette configuration ne nécessite pas que les développeurs maintiennent Pipfile ou Pipfile.lock . De plus, l'exécution des tests dans différents contextes est toujours la même ( Pipfile.lock est toujours reconstruit dans un contexte donné).

Ce qui manque encore (et peut être fait)

Le cache pypi est la partie qui nécessite quelques recherches. Je suppose qu'un simple répertoire serait suffisant et peut-être que pipenv est déjà prêt à vous aider. Peut-être que le numéro 1731 est la partie manquante.

En tant que package qui résout les dépendances, bon nombre de nos propres tests reposent sur des constructions déterministes, c'est-à-dire en prenant des éléments connus et en s'attendant à un graphe résolu. Nous utilisons pytest-pypi pour cela.

J'adore la discussion animée sur ce sujet. Je pense que la nuance est importante et vous devriez toujours tester les dépendances connues ainsi que celles non épinglées

vous devriez toujours tester les dépendances connues ainsi que celles non épinglées

Je seconde cette suggestion. C'est une bonne idée de toujours avoir un "bon état connu" explicite pour les versions reproductibles et de simplifier le débogage au cas où une mise à jour casse quelque chose en plus de s'assurer que les nouvelles versions mineures/correctives de bogues fonctionnent également.

(À mon avis très personnel, la situation idéale serait que le gestionnaire de paquets installe les dernières versions mineures par défaut afin que les bibliothèques puissent toujours spécifier les versions de dépendances concrètes avec lesquelles elles ont été testées, mais je me rends compte que c'est une opinion très controversée et que tout le monde à suivre sever.)

@Moritz90 @techalchemy @uranusjr @tsiq-oliverc

Voici mon résumé de la discussion précédente.

Problèmes particuliers et solutions proposées

De nombreux contextes d'exécution - qui doit maintenir le(s) fichier(s) Pipfile.lock ?

Chaque système d'exploitation et interpréteur python pris en charge contribuent à la matrice des contextes d'exécution possibles.

Par exemple, Flask prend en charge (au moins les éléments CI visibles dans le référentiel):

  • Système d'exploitation Windows (python 2.7 et Python 3.6)
  • Linux (python 2.7, 3.4, 3.5, 3.6, tous les soirs, pypi)
  • OSX (py - je ne sais pas s'il y a plus de versions)

Il fait 9 contextes d'exécution différents qui peuvent différer.

Chaque contexte d'exécution peut avoir des Pipfile.lock .

Qui les entretiendra ?

Les options sont :

  • Laissez les développeurs le faire manuellement (NO WAY)
  • Ne conservez qu'un seul Pipfile.lock pour la plate-forme de développement principale (quelle plate-forme aime être ignorée ?)
  • Automatiser la création via CI (OUI)

Proposition : Laissez CI générer le fichier par pipenv install -e . . Ne l'incluez pas dans le dépôt, aidez les développeurs à choisir le bon Pipfile.lock à la suite des builds automatisés.

Les développeurs ont besoin d'un environnement prévisible

Lors de la résolution d'un problème, qui peut être causé par des changements de dépendances sur pypi, le développeur peut avoir besoin d'un moyen simple pour reproduire l'environnement à partir du test ayant échoué.

Proposition:

  • pour de nombreux packages, les changements de dépendances pypi sont si rares, qu'ils ne posent pas de réel problème
  • pour réparer l'environnement par lui-même, le développeur peut générer le Pipfile.lock par pipenv install -e . suivi de pipenv lock .
  • pour répliquer l'environnement du test ayant échoué, le développeur choisit le Pipfile.lock du test ayant échoué.
  • todo: montrer des exemples, comment appliquer Pipfile.lock dans tox.ini .

CI doit révéler setup.py cassé

La bibliothèque setup.py peut être cassée (dépendance manquante dans install_requires , spécificateur de version manquant, etc.) et le test CI ne doit pas masquer ce problème (en préinstallant les dépendances omises seules).

Proposition:

  • faites confiance à pipenv install -e . pour fournir le même résultat qu'une installation simple (il y a actuellement quelques problèmes avec cela).
  • exécutez un test d'installation simple (sans pipenv ) et comparez éventuellement que la sortie pip freeze résultante est un sous-ensemble de ce qui est installé par pipenv .

Les dépendances pypi mises à jour peuvent casser des choses, CI doit détecter de telles poursuites

Certaines mises à jour de dépendances peuvent casser la bibliothèque qui l'utilise. CI doit détecter l'échec sur un tel problème.

Proposition:

  • au moins un test doit être exécuté sur une version non épinglée
  • si CI génère toujours de nouveaux Pipfile.lock , ce n'est pas un problème (car nous fonctionnons de toute façon en mode non épinglé)

Modes CI pour différents types de bibliothèques

Dans tous les modes proposés, j'ai essayé d'éviter de garder des fichiers pipenv dans le référentiel, évitant ainsi aux développeurs de maintenir ce truc vraiment complexe (automatisation !!!).

Contrairement à mon texte d'origine, les 2e et 3e modes utilisent pipenv dans les scripts CI.

Mode : Courez, Forrest, Courez !

Package simple avec un plus petit nombre de dépendances qui ne changent pas souvent.

Exécutez simplement comme avant l'ère pipenv et gardez les choses simples pour nous.

Les rares cas où les dépendances causeront des problèmes sont faciles à résoudre et ne justifient pas de rendre CI plus complexe.

Mode : générer et sceller

Chaque fois que le test CI est exécuté, générez un nouveau Pipfile.lock qui décrit complètement l'environnement utilisé pour le moment.

Le Pipfile.lock deviendra l'artefact CI.

Si les choses tournent mal, le développeur peut choisir Pipfile.lock dans une version cassée, l'appliquer localement et effectuer les tests et les corrections.

Si quelqu'un veut déployer, Pipfile.lock du dernier build réussi peut être utilisé.

Mode : Âge de glace

Lorsque le changement de dépendances est un réel problème, CI doit créer Pipfile.lock une fois et le conserver pendant une certaine période (un mois ?).

Cela rend la configuration de CI plus difficile, car il doit y avoir au moins deux tâches différentes (une générant Pipfile.lock , l'autre l'appliquant et l'utilisant dans les tests).

Attention : Pipfile.lock doit être mis à jour également pour le moment, setup.py modifie les dépendances.

Notez que l'ère glaciaire nécessite Scrat le type de test écureuil qui ignore le statut gelé et vérifie les versions non épinglées.

Remarques de clôture

Comme on le voit, le déterminisme et la complexité croissent mode par mode.

Ma proposition serait :

  • démarrer simple ("Run, Forrest, Run"). Vous gagnez en efficacité et en rapidité.
  • si les choses deviennent trop complexes en raison de l'évolution des dépendances, passez à "Générer et sceller". Vous gagnez en répétabilité dans l'environnement local.
  • si les choses vont vraiment mal, passez en mode "L'âge de glace". Vous gagnez en déterminisme (temporaire).

Tous les gains coûtent quelque chose.

Si l'objectif ici est de mettre à jour les conseils contenus dans la documentation, alors honnêtement, il semble irresponsable de dire quelque chose de radicalement différent de "Suivez les meilleures pratiques (versions reproductibles) par défaut, jusqu'à ce que vous n'ayez pas le choix".

@vlcinsky Sous le titre "Mode: Générer et sceller", il peut être judicieux de mentionner que le dernier Pipfile.lock réussi doit toujours être conservé, par exemple en le déclarant comme un artefact Jenkins. Avec ce changement, il serait bon de recommander cette configuration pour la plupart des projets. Comme @tsiq-oliverc, je ne recommanderais jamais le premier mode.

Plus j'y pense, plus j'ai l'impression que cette documentation deviendra une section expliquant pourquoi l'utilisation de pipenv pour les builds CI est une excellente idée, même si vous développez une bibliothèque.

@tsiq-oliverc la grande majorité des packages python généraux sont en mode "Run, Forrest, Run". J'ai aidé quelques-uns de ces packages à introduire tox et pytest , car je sentais que cela contribuerait à la qualité du package et parce que j'avais une idée assez claire de la façon dont cela pourrait être bien fait.

Maintenant, il existe un autre excellent outil et je me demande comment utiliser correctement pipenv dans les projets python généraux pour contribuer à sa qualité. Je veux trouver une ou deux recettes qui fonctionnent bien, qui soient justifiées et faciles à suivre.

Que dirais-je au projet Flask ?

  1. Suivre les bonnes pratiques (builds reproductibles) par défaut, jusqu'à ce que vous n'ayez plus le choix ?
  2. Ajouter 9 Pipfile.lock fichiers et mettre en place une politique de mise à jour ?
  3. Refactoriser les scripts CI pour que Travis et Appveyor fonctionnent en deux phases après le mode Ice Age ?
  4. Modifier les scripts CI pour Travis et Appveyor afin de générer Pipfile.lock artefact
  5. aucun commentaire, à part "Merci beaucoup pour Flask."

L'objectif est de trouver un style de travail fonctionnel. Si ça se termine par doc, sympa, sinon pas de problème.

@vlcinsky Je dirais que (1) et (4) devraient être la recommandation pour de tels projets. Bien que sans Pipfile.lock préexistant, vous ne saurez pas à l'avance les versions utilisées dans la construction (ce qui est bien en dehors des environnements d'entreprise), vous obtiendrez toujours un résultat reproductible si vous générez et archivez le fichier de verrouillage pendant la construction.

Edit : La version tl; dr de ma recommandation serait :

  • Assurez-vous toujours que vos builds sont reproductibles, que vous développiez une bibliothèque ou une application. pipenv peut vous aider à atteindre cet objectif.
  • Si vous développez une application, validez Pipfile.lock dans votre référentiel et utilisez-le pour le déploiement. (Ceci est déjà couvert par la documentation existante.)
  • Si vous développez une bibliothèque open source, générez Pipfile.lock à la volée dans votre build CI et archivez-la pour plus tard.
  • Si vous développez une bibliothèque et travaillez dans un environnement d'entreprise restrictif, maintenez le nombre approprié de fichiers de verrouillage et utilisez-les dans vos builds CI.

(Bien sûr, la documentation réelle devrait avoir un peu plus de détails et d'exemples.)

@ Moritz90 J'ai modifié le "Générer et sceller" comme vous l'avez proposé.

Re (1) : facile à dire, impossible à exécuter sans être plus précis.

Re (4) : oui, je pense aussi que "Générer et sceller" est le mode le plus faisable. Mais en cas de Flask je n'oserai pas (du moins pas pour le moment).

Re préexistant Pipfile.lock dans un environnement d'entreprise : il doit être créé d'une manière ou d'une autre, (semi)manuellement ou automatiquement. Je suppose que dans un environnement d'entreprise, vous n'installez pas directement à partir de pypi public mais en utilisez un privé et qui ne fournit que des packages approuvés ( devpi-server fournit un excellent service en ce sens - plusieurs index, volatilité contrôlée des packages publiés, approbations pour les packages, etc.) Si le processus de construction de Pipfile.lock s'exécute dans un tel environnement, il ne peut utiliser que ce qui est approuvé, donc si une nouvelle version doit y apparaître, quelqu'un doit se lever et la faire approuver. La construction suivante de CI testera qu'elle ne casse pas les choses. Et avec pipenv check test des problèmes de sécurité peut également être automatisé.

Je suppose qu'un tel flux de travail serait plus sécurisé que quelqu'un qui le crée (semi) manuellement. Mais ma connaissance de l'environnement d'entreprise est très limitée.

Bonjour l'équipe pipenv. Je partage beaucoup de ce qui est dit dans ce texte, cela aide beaucoup tout développeur à mieux comprendre les limites de Pipfile/pipenv lors du développement d'une bibliothèque. Je veux voir ce texte ou une partie de ce texte intégré dans la documentation officielle de pipenv.

J'ai l'amendement suivant dont je voudrais discuter :

Pour notre package python interne, entièrement réutilisable, publié sur notre pypi interne, etc, et même pour mes propres packages python (ex: cfgtree , txrwlock , pipenv-to-requirements ), j'utilise un package que certains connaissent peut-être déjà ou même utilisent , qui résume ces détails et facilite la vie du développeur python : PBR.
PBR lit essentiellement requirements.txt trouvé dans le dossier racine d'un paquet de distribution et l'injecte dans le install_requires du setup.py . Le développeur doit simplement maintenir un requirements.txt avec des déclarations de dépendance lâches. Jusqu'à ce que le support de Pipfile soit intégré officiellement dans PBR, je dois utiliser pipenv-to-requirements qui génère automatiquement requirements.txt partir de Pipfile afin qu'ils soient tous les deux synchronisés et tous les deux engagés dans la source, et PBR effectue l'injection correctement une fois le package de distribution construit. Je pense que l'on pourrait utiliser pipenv pour générer ce requirements.txt

Je travaille sur un support de Pipfile pour PBR, afin qu'il puisse lire le Pipfile (et non le fichier de verrouillage) et l'injecter dans install_requires comme il le fait avec requirements.txt .

Je ne sais pas si d'autres packages similaires existent, car il fait également d'autres choses que les gens pourraient ne pas vouloir (version de l'historique de git, génération automatique d'AUTEURS et de ChangLog).

Mais à la fin, je pense vraiment qu'il est tellement plus facile d'écrire, de maintenir et de gérer la gestion des versions d'une bibliothèque Python, je serais triste de ne pas partager cette expérience. Je le promeut comme le moyen "recommandé" d'écrire des bibliothèques python modernes sur mon entreprise.

Je reconnais que c'est comme "tricher" sur toutes les difficultés concernant la bibliothèque et pipenv, mais à la fin, le travail est terminé et les développeurs sont heureux de l'utiliser jusqu'à présent. Une partie de la formation python, que je donne au nouveau développeur python de mon entreprise, consiste à écrire d'abord une bibliothèque python en maintenant install_requires manuellement, puis à passer à PBR pour voir comment cela devient plus facile ( et franchement je suis fan de la fonctionnalité de

Une partie de la raison de déclarer les dépendances des bibliothèques à l'aide d'un fichier dédié également aux bibliothèques est de pouvoir utiliser des outils tels que readthedocs ou pyup (même si pyup a plus de sens lorsqu'il est lié à une application).

Je ne veux pas nécessairement promouvoir cette méthode comme la manière "standard" de faire un package python, c'est en fait la manière "OpenStack", mais je partagerais mon expérience, et si d'autres ont une expérience similaire ou contradictoire, je serai heureux de les entendre et de mettre à jour mon point de vue.

Equipe, que pensez-vous d'une sorte de rubrique "communauté" sur la documentation ? Pour que des utilisateurs comme moi puissent partager son expérience sur la façon dont il utilise pipenv, sans nécessairement l'aval complet de l'équipe pipenv ?

PS: je peux déplacer ceci vers un problème dédié si vous ne voulez pas polluer ce fil

@vlcinsky (1) est très facile à exécuter - placez votre fichier de verrouillage dans votre référentiel.

Je pense que ce que vous voulez dire à la place, c'est qu'il est impossible de donner des conseils précis une fois que cette stratégie de base n'est plus suffisante. C'est certainement vrai, mais c'est parce que le problème spécifique diffère probablement au cas par cas.

Ou pour le dire autrement, la solution dépend des garanties supplémentaires que vous souhaitez que votre flux de travail CI fournisse.

@gsemet tu sais quoi ? Tous mes packages python créés au cours des deux dernières années sont basés sur pbr - c'est vraiment génial. Et je suis vos tentatives pour prendre en charge Pipfile dans pbr chaque fois que je le peux (un pouce levé, des votes, etc.).

En cas de problème (recherche de pipenv modèles et anti-modèles pour les bibliothèques python générales), j'ai intentionnellement omis pbr pour deux raisons :

  • cela rendrait la discussion conceptuelle plus complexe
  • certaines personnes n'aiment pas pbr pour d'autres raisons (vous les avez mentionnées) et cela détournerait probablement la discussion

D'un autre côté, j'attends avec impatience votre recette pour les amateurs de pbr. je vais le lire.

@tsiq-oliverc vous avez mis le doigt sur le clou :

C'est exactement le problème qui m'a motivé à commencer ce numéro. Si vous relisez le début de ce problème, vous trouverez une description de quelques cas, où l'ajout de Pipfile.lock peut casser vos tests CI (soit casser l'exécution de la construction, soit masquer les problèmes, qui seraient autrement détectés, soit installer de mauvaises dépendances pour un contexte donné...).

Si vous me montrez un dépôt, où cela est fait correctement (bibliothèque générale de python), je serais heureux. Ou je démontrerais quels risques il y a ou quelles choses sont inachevées.

Frais ! Je maintiens également cet emporte-pièce :)

@vlcinsky D'accord ,

Pour autant que je sache, voici les symptômes spécifiques de votre message d'origine :

  • Cacher les dépendances cassées de setup.py. Cela ressemble à un non-problème - pipenv install -e . , n'est-ce pas ?
  • Les dépendances sont susceptibles d'être invalides pour différentes versions de python ou dans un autre système d'exploitation. Je peux voir que cela pourrait être un problème, mais pourriez-vous fournir un exemple concret où cela a eu de l'importance dans la pratique? (dans le contexte d'un fichier de verrouillage)
  • Les développeurs sont obligés de mettre à jour... lorsque d'autres bibliothèques sont mises à jour et peuvent être utilisables au sein de la bibliothèque. Ils ne sont pas obligés de le faire. Ils le font s'ils veulent garantir que leur bibliothèque fonctionne avec la version n+1 plutôt que la version n de leur dépendance. Mais notez que j'ai déjà proposé une alternative qui offre le meilleur des deux mondes.
  • Concurrencer Tox. Je ne connais vraiment rien à Tox. Mais oui, utiliser deux outils simultanément pour gérer vos dépendances ressemble à une recette pour un désastre. Je dirais d'utiliser celui qui est supérieur pour cette tâche particulière.
  • Pipenv échoue. Cela ressemble à un autre non-problème - vous pouvez simplement épingler la version de Pipenv (c'est ma solution actuelle, tout comme j'épingle mon image Docker, ma version de Pip, etc.)

@tsiq-oliverc Je dois dire que vos commentaires m'ont inspiré et je sais qu'ils ont contribué à un niveau plus élevé de reproductibilité de la solution proposée.

Ce qui suit est lié à votre proposition de placer le fichier de verrouillage ( Pipfile.lock ) dans le référentiel pour assurer la répétabilité :

re Cacher les dépendances de setup.py cassées. . Les pipenv install -e . suivent ce que je propose, mais notez que ce n'est pas l'utilisation de Pipfile.lock , c'est une méthode pour le (re)créer. Si quelqu'un garde Pipenv.lock et l'utilise pour créer virtualenv avant d'installer le package, le problème est présent.

re Les dépendances sont susceptibles d'être invalides pour différentes versions de python ou dans un autre système d'exploitation . Les exemples sont nombreux : doit installé pour Python 2.7 doit être une ancienne version car la plus récente a abandonné la prise en charge de Python 2.x. watchdog dépendance de

re Les développeurs sont obligés de mettre à jour .. Imaginez la bibliothèque Open Source avec 15 contributeurs. Il est si facile d'oublier de régénérer Pipfile.lock par un nouveau venu ou un développeur de base fatigué. Par exemple, dans le package maya , on m'a demandé de régénérer le Pipfile.lock car une nouvelle dépendance a été ajoutée à setup.py . Était-ce nécessaire ? L'ai-je bien mis à jour ? L'ai-je mis à jour pour tous les contextes d'exécution pris en charge ? Les réponses sont non, pas sûr, non. Quoi qu'il en soit, merci pour votre proposition (elle m'a inspiré pour la solution décrite à côté de votre commentaire).

re Concurrence avec tox : Tox permet la création de plusieurs virtualenvs et l'automatisation de l'exécution des tests en leur sein. Typique tox.ini définit différents virtualenvs pour python 2.7, 3.4, 3.5, 3.6 et tout autre dont vous avez besoin, et permet d'y installer le package et d'exécuter la suite de tests. C'est un outil puissant de testeurs sérieux. pipenv n'est pas l'outil à cet effet, mais peut interférer dans l'installation des éléments nécessaires. D'une certaine manière, j'ai suivi vos conseils et j'ai proposé d'utiliser un outil supérieur (tox) sur pipenv dans la mesure du possible.

re Pipenv échoue. C'est vraiment malheureux. J'ai eu un test CI (basé sur tox) qui fonctionnait bien sur localhost, mais lorsqu'il était exécuté via Travis, il échouait en raison d'un problème pipenv . Si je veux l'utiliser maintenant, l'épinglage n'aide pas tant que le correctif n'est pas publié. Mais c'est comme ça que ça se passe - j'attendrai.

Notez que certaines parties de mon message d'origine devront être mises à jour comme il semble, en utilisant pipenv dans les scripts CI a sa place justifiée (configuration virtualenv "scellant" pour une éventuelle utilisation ultérieure).

@tsiq-oliverc Alors que j'ai d'abord aimé votre suggestion de tester à la fois le "bien connu" et les dernières versions, je trouve de plus en plus difficile de justifier l'effort à mesure que j'y pense. Je pense que vous devriez décider de faire l'un ou l'autre, pas les deux.

La seule chose que vous gagnez est que vous saurez immédiatement si un échec a été causé par une mise à jour de dépendance ou un changement de code. Mais vous pouvez obtenir la même chose en effectuant simplement des commits séparés (lors de la mise à jour manuelle des dépendances verrouillées) ou en essayant de reproduire le bogue avec le dernier fichier de verrouillage produit par une construction réussie (en utilisant toujours les dernières versions). Et dans les environnements restreints, vous ne pouvez pas « simplement mettre à jour » de toute façon...

@vlcinsky Bien que je sois d'accord avec votre point de vue général sur les différences entre les environnements, l'argument "un fichier de verrouillage par configuration" me semble être un homme de paille. En pratique, vous pourrez partager les fichiers de verrouillage entre au moins certains des environnements.

Une question en suspens à laquelle personne n'a encore répondu est de savoir comment traiter le cas où vous devez tous les deux tester dans un environnement différent et verrouiller vos dépendances. Je dois admettre que je ne connais rien à propos de tox part que ça existe, mais il semble qu'il y ait un besoin d'une sorte de colle entre tox et pipenv cela résout ce problème en quelque sorte.

@Moritz90

Rencontrer l'homme de paille

Concernant les trop nombreuses variantes de Pipfile.lock servant d'homme de paille (pour garder les autres hors de mon champ) :

Ballon

J'ai pris le projet flask (le considérant comme très mature) et j'ai effectué des tests toxicologiques :

Ici, vous voyez la liste des variantes testées (juste localement sur Linux, multipliez-la par 3 car Windows et OSX feront le même ensemble de tests mais peuvent entraîner des environnements différents).

Il y a 16 tests différents sur un système d'exploitation, 5 d'entre eux ont échoué car je ne les ai pas installés (c'est bien), l'un traite de la documentation de construction (cela nécessite une bibliothèque imporable) et un autre une couverture (qui nécessite également une bibliothèque importable ):

  coverage-report: commands succeeded
  docs-html: commands succeeded
  py27-devel: commands succeeded
  py27-lowest: commands succeeded
  py27-simplejson: commands succeeded
  py27: commands succeeded
  py35: commands succeeded
  py36-devel: commands succeeded
  py36-lowest: commands succeeded
  py36-simplejson: commands succeeded
  py36: commands succeeded
ERROR:   py34: InterpreterNotFound: python3.4
ERROR:   pypy-devel: InterpreterNotFound: pypy
ERROR:   pypy-lowest: InterpreterNotFound: pypy
ERROR:   pypy-simplejson: InterpreterNotFound: pypy
ERROR:   pypy: InterpreterNotFound: pypy

Pour chacun des virtualenvs créés, j'ai créé requirements.txt fichier pip freeze > {venv_name}.txt

Ensuite, les hachages calculés pour les fichiers, triés en fonction des valeurs de hachage, de sorte que tous les mêmes seront regroupés. Voici l'homme de paille :

b231a4cc8f30e3fd1ca0bfb0397c4918f5ab5ec3e56575c15920809705eb815e  py35.txt
b231a4cc8f30e3fd1ca0bfb0397c4918f5ab5ec3e56575c15920809705eb815e  py36.txt
cdf69aa2a87ffd0291ea65265a7714cc8c417805d613701af7b22c8ff2b5c0e4  py27-devel.txt
dfe27df6451f10a825f4a82dfe5bd58bd91c7e515240e1b102ffe46b4c358cdf  py36-simplejson.txt
e48cd24ea944fc9d8472d989ef0094bf42eb55cc28d7b59ee00ddcbee66ea69f  py36-lowest.txt
f8c745d16a20390873d146ccb50cf5689deb01aad6d157b77be203b407e6195d  py36-devel.txt
053e107ac856bc8845a1c8095aff6737dfb5d7718b081432f7a67f2125dc87ef  docs-html.txt
45b90aa0885182b883b16cb61091f754b2d889036c94eae0f49953aa6435ece5  py27-simplejson.txt
48bd0f6e66a6374a56b9c306e1c14217d224f9d42490328076993ebf490d61b5  coverage-report.txt
564580dad87c793c207a7cc6692554133e21a65fd4dd6fc964e5f819f9ab249c  py27.txt
8b8ff4633af0897652630903ba7155feee543a823e09ced63a14959b653a7340  py27-lowest.txt

Effrayant, n'est-ce pas ? De tous les tests, seuls deux partagent les mêmes dépendances figées.

C'est la réalité de la bibliothèque python générale avec une bonne suite de tests. Vous admettrez probablement maintenant qu'il s'agit de quelque chose de très différent de la bibliothèque python testée dans un environnement d'entreprise.

Jinja2

Vérification de jinja2 , qui semble être une bête beaucoup plus simple :

  coverage-report: commands succeeded
  py26: commands succeeded
  py27: commands succeeded
  py33: commands succeeded
  py35: commands succeeded
  py36: commands succeeded
ERROR:   docs-html: commands failed
ERROR:   py34: InterpreterNotFound: python3.4
ERROR:   pypy: InterpreterNotFound: pypy

En voyant les sommes de contrôle, je suis surpris que py27.txt et py26.txt diffèrent :

047a880804009107999888a3198f319e5bbba2fa461b74cfdfdc81384499864e  py26.txt
047a880804009107999888a3198f319e5bbba2fa461b74cfdfdc81384499864e  py33.txt
047a880804009107999888a3198f319e5bbba2fa461b74cfdfdc81384499864e  py35.txt
047a880804009107999888a3198f319e5bbba2fa461b74cfdfdc81384499864e  py36.txt
48bd0f6e66a6374a56b9c306e1c14217d224f9d42490328076993ebf490d61b5  coverage-report.txt
743ad9e4b59d19e97284e9a5be7839e39e5c46f0b9653c39ef8ca89c7b0bc417  py27.txt

@vlcinsky C'est vraiment effrayant. Je me demande si Flask est un cas spécial ou si c'est en fait la norme, mais vous m'avez définitivement prouvé que j'avais tort.

J'espère maintenant que notre bibliothèque Python ne souffrira pas du même problème un jour et que les différences y seront plus gérables.

@ Moritz90 Votre bibliothèque interne dessert un public complètement différent, vous pouvez donc vous permettre de garder le contexte d'exécution beaucoup plus étroit.

Les bibliothèques python générales sont souvent flexibles et configurables, par exemple Flask permet d'installer et d'utiliser des analyseurs json alternatifs, ce qui est couvert par un test séparé.

On peut en apprendre beaucoup sur les tests et la toxicité grâce aux tox.ini de Flask

les variantes de test les plus basses prennent soin de tester par rapport à la version de dépendance la plus ancienne.

devel teste la version de développement des dépendances principales.

Je dirais que Flask est au niveau de complexité le plus élevé et présente une suite de tests minutieuse.

Le tox.ini de la pyramide montre un nombre similaire d'environnements (ils visent également une couverture de code à 100%).

Le tox.ini de maya est très frais (2 jours) et simple, même ici, il y a 4 environnements différents et py27 diffère en termes d'exigences gelées de py35 et py36.

@Moritz90
Concernant la colle entre pipenv et tox

  • pipenv --man montre quelques instructions, comment utiliser pipenv dans les commandes tox.ini
  • tox-pipenv essaie de fournir une intégration supplémentaire, mais cela me

tox.ini fichier pipenv .

pipenv a une grande fonctionnalité, que lorsqu'il est exécuté dans virtualenv déjà activé (ce qui est le cas dans le test basé sur la toxicité), il s'installe dans un environnement virtuel donné. C'est vraiment sympa.

Comme nous avons probablement besoin de Pipfile.lock générés, un effort supplémentaire doit être fait pour l'obtenir et le déplacer au bon endroit (ag in .tox/py36/Pipfile.lock pour éviter l'écrasement en suivant le test. Cela sera possible, mais une certaine simplification serait peut-être une astuce avec une variable d'environnement pour l'emplacement de Pipfile le rendrait encore plus simple.

@vlcinsky

  • setup.py - Je ne suis toujours pas sûr de comprendre le problème. Vous exécutez pipenv install -e . une fois afin que setup.py soit maintenant suivi via votre fichier de verrouillage. Et puis exécutez pipenv install chaque fois que vous ajoutez de nouveaux packages à setup.py.
  • Les développeurs oubliant de mettre à jour le fichier de verrouillage - pipenv --deploy est conçu pour attraper cela. Exécutez-le dans votre CI !
  • Pipenv échoue - d'accord, s'il y a des bogues dans l'outil, ça craint. Mais les bugs sont généralement corrigés. Ce n'est pas une raison pour jeter toute une philosophie
  • Tox

    • Si Tox est bon pour gérer les tests, tant mieux. Si c'est aussi génial pour gérer les packages et les builds déterministes , c'est encore mieux.

    • Mais si cela était vrai, il n'y aurait aucune raison pour que Pipenv existe. Je ne peux donc que supposer qu'il y a une sorte de limitation avec Tox.

    • De même que ci-dessus, l'état du monde aujourd'hui (le manque d'une bonne interopérabilité) ne semble pas être une raison pour rejeter la philosophie.

  • Plusieurs environnements

    • Il est clair qu'il y a au moins quelques cas particuliers ici, comme Flask.

    • Je n'ai pas de meilleure suggestion que plusieurs fichiers de verrouillage (bien qu'il y ait peut-être une future fonctionnalité pour Pipenv à cet égard ?)

    • Mais même dans ce cas, je ne suis toujours pas convaincu que la gestion de plusieurs fichiers de verrouillage soit un problème dans la pratique. Dans le pire des cas, il semble que vous puissiez créer un script simple update-all-lockfiles.sh localement et exécuter pipenv --deploy sur votre CI pour détecter les erreurs.


@ Moritz90 - D'accord, l'approche "en deux phases" peut être excessive dans la plupart des cas. En particulier, si vous effectuez des mises à jour « manuelles » délibérées/intentionnelles de votre fichier de verrouillage, cela est totalement inutile.


Plus généralement, il serait bon de s'assurer que cette "proposition" se concentre sur les choses qui sont en fait des problèmes difficiles (à mon avis, c'est (A) desservant plusieurs environnements, (B) voulant détecter les changements dans les dépendances en amont). Cela ne devrait pas être basé sur des choses transitoires (bugs dans Pipenv) ou des malentendus potentiels sur la façon dont l'outil est destiné à être utilisé.

Mais même pour ces problèmes "difficiles", le cadrage devrait ressembler à "dans certains cas complexes, vous pouvez trouver qu'un flux de travail Pipenv de base est insuffisant, alors voici quelques points à considérer". OMI, cela ne devrait pas être présenté comme l'approche par défaut (car la plupart des gens n'auront pas ces préoccupations).

L'exemple de documentation fourni par @vlcinsky deviendrait plus simple et moins déroutant si Pipenv/Pipfile permettait la gestion de lib-dependencies , app-dependencies et dev-dependencies . Les documents pourraient ressembler à ceci :

Utilisez l'option lib-dependencies si votre package est une bibliothèque partagée. Exemple Pipfile :

[lib-dependencies]
some-lib=="*"
another-lib=="*"
yet-another-one==">=1.0"

[dev-dependencies]
some-dev-tool=="1.1"

Pour les bibliothèques partagées, il est important de garder les plages de versions inférieures à [lib-dependencies] aussi larges que possible, afin d'éviter les conflits de versions sur le système consommateur.

Si votre package est une application (destinée à être installée par pipenv sur le système cible) qui nécessite des versions de dépendance exactes, vous devez utiliser l'option [app-dependencies] . Exemple Pipfile :

[app-dependencies]
some-lib=="1.0.12"
another-lib=="1.*"
yet-another-one=="2.0"

[dev-dependencies]
some-dev-tool=="1.1"

/Fin de l'exemple de document

Une autre approche pourrait être un Pipfile.lib et un Pipfile.app .

Je pense que quelque chose comme ça omettrait le besoin d'un morceau de sections anti-modèle et d'outils tiers pour combler le vide.

Appeler l'outil d'emballage pipenv est trompeur si l'on s'attend à ce qu'il crée des bibliothèques python ou qu'il soit profondément impliqué dans leur création.

Je pense qu'il s'agit d'un vrai problème, ce qui entraîne beaucoup de confusion. Surtout parmi les personnes habituées aux gestionnaires de packages dans d'autres langages de programmation (par exemple, JS, Rust, Elm). Cela m'a pris plusieurs mois et une lecture occasionnelle des problèmes de GIthub, jusqu'à ce que je réalise que j'utilisais Pipenv et setup.py dans le mauvais sens.

@féluxe

Votre [lib-dependencies] ou Pipfile.lib est ce que nous avons aujourd'hui en Pipfile (en tant que dépendances abstraites - en étant aussi larges que possible).

Votre [app-dependencies] ou Pipfile.app est ce que nous avons dans Pipfile.lock (en tant que dépendances spécifiques).

pipenv et ses fichiers peuvent être utilisés dans deux situations différentes : développer une bibliothèque ou préparer le déploiement d'une application, mais probablement pas pour les deux à la fois. Pour cette raison, je ne vois pas de bonnes raisons d'ajouter des sections supplémentaires dans Pipenv . Il est de la responsabilité des développeurs de savoir quel type d'objectif le Pipfile va servir.

Je pense qu'il s'agit d'un vrai problème, ce qui entraîne beaucoup de confusion. Surtout parmi les personnes habituées aux gestionnaires de packages dans d'autres langages de programmation (par exemple, JS, Rust, Elm). Cela m'a pris plusieurs mois et une lecture occasionnelle des problèmes de GIthub, jusqu'à ce que je réalise que j'utilisais Pipenv et setup.py dans le mauvais sens.

D'accord. La solution en trois sections est également une solution très intéressante que je n'ai jamais envisagée, et elle semble correcte et (étonnamment !) simple.

Venant moi-même d'un environnement Python, j'ai toujours eu l'impression que le package.json de Node le faisait mal (Rust est meilleur car il a un compilateur et un éditeur de liens, et peut résoudre ce problème à un stade ultérieur). Traiter les dépendances app et lib de la même manière ne fonctionnera tout simplement pas pour un langage de script comme Python, du moins dans un sens abstrait, c'est-à-dire que cela pourrait fonctionner pour vous, mais un outil générique comme Pipenv ne peut pas le faire car il doit être générique.

Bien que j'aime la solution en trois sections dans son concept, il s'agit toujours d'un changement plutôt incompatible avec l'écosystème existant. Il y a déjà setup.py, setup.cfg et (potentiellement) pyproject.toml remplissant cet espace. Si Pipenv (Pipfile, pour être exact) veut se déplacer dans l'espace, il doit se consolider avec des projets connexes, tels que pip (le support de la bibliothèque devrait idéalement être pris en charge directement par celui-ci) et flit .

Comme je l'ai mentionné dans d'autres problèmes concernant la gestion des dépendances lib/app, cette discussion doit être transmise à pypa-dev (la liste de diffusion) et/ou au processus PEP, afin qu'elle puisse être mieux entendue par les autres parties et les personnes concernées, avant Pipenv (Pipfile) peut se déplacer dans toutes les directions.

@vlcinsky

Votre [lib-dependencies] ou Pipfile.lib est ce que nous avons aujourd'hui dans Pipfile (en tant que dépendances abstraites - aussi larges que possible).

Désolé si ce n'était pas clair. Mes lib-dependencies sont censés être ce que les gens mettent actuellement dans setup.py / install_requires . Peut-être que pypi-dependencies serait un meilleur nom pour ce que je voulais dire.

@uranusjr

Il y a déjà setup.py, setup.cfg et (potentiellement) pyproject.toml remplissant cet espace.

Pipenv (l'outil de ligne de commande) pourrait interfacer setup.py . Seule la section de dépendance de setup.py devrait être déplacée vers Pipfile. Du moins dans mon imagination :)

Comme je l'ai mentionné dans d'autres problèmes concernant la gestion des dépendances lib/app, cette discussion doit être transmise à pypa-dev (la liste de diffusion) et/ou au processus PEP, afin qu'elle puisse être mieux entendue par les autres parties et les personnes concernées, avant Pipenv (Pipfile) peut se déplacer dans toutes les directions.

Ok, désolé de déranger ;) Si je trouve un peu de temps, j'écrirai quelque chose pour la liste de diffusion.

Dans le cadre de cette proposition, cependant, je suggérerais qu'elle se concentre sur les meilleures pratiques actuellement possibles, au lieu d'entrer dans le trou du lapin de l'élaboration d'un nouveau flux de travail pour l'ensemble de la communauté d'emballage Python. Il serait plus productif de proposer une meilleure pratique dans les contraintes actuelles, puis de lancer la discussion pour des améliorations.

@uranusjr - Je viens d'un milieu "compilé", donc je suis curieux de savoir pourquoi c'est le cas ?

Traiter les dépendances app et lib de la même manière ne fonctionnera tout simplement pas pour un langage de script comme Python

@tsiq-oliverc Étant donné que les meilleures pratiques d'application vous obligent à épingler vos dépendances, les bibliothèques commenceraient également à épingler les leurs, si elles utilisent la même source de fichiers d'exigences. Cela conduirait à des problèmes de résolution des dépendances.

Supposons que mon application a deux dépendances A et B, les deux dépendent de C, mais A épingle v1, tandis que B épingle v2. Les langages compilés permettent à la chaîne d'outils de détecter cela au moment de la compilation et de le résoudre de plusieurs manières. Rust, par exemple, le fait pendant le temps de liaison : l'exécutable de fin contiendrait deux copies de C (v1 et v2), avec A et B liés à chacun d'eux. Dans le pays C++, cela serait résolu avec des bibliothèques dynamiques ; la recherche de symboles est effectuée encore plus tard (au moment de l'exécution), mais l'idée est la même : le compilateur sait ce dont vous avez besoin (à partir de l'interface que vous utilisez) et peut agir en conséquence.

Les langages de script ne peuvent pas faire cela car ils ne savent pas ce que vous voulez vraiment faire jusqu'à ce qu'ils atteignent réellement l'appel. Node contourne cela en supposant toujours que les dépendances sont incompatibles (A et B obtiennent toujours leur propre C, même si les deux copies sont identiques), mais cela conduit à une nouvelle classe de problèmes et entraîne des hacks gênants comme des dépendances entre pairs que tout le monde (J'espère ?) d'accord sont terribles. Python ne veut probablement pas y aller (il ne le peut pas, de toute façon, car cela casserait probablement toutes les installations Python existantes).

Une autre façon de contourner ce problème est de faire quelque chose d'intelligent dans les outils d'empaquetage qui "détache" la version de dépendance. Bundler (de Ruby) le fait en quelque sorte, en recommandant aux gens de ne pas inclure le fichier de verrouillage dans la gem, afin que Bundler puisse utiliser les versions non épinglées dans Gemfile, au lieu des versions épinglées dans Gemfile.lock. Mais les gens ont tendance à ignorer les conseils et à faire ce qu'ils veulent, vous obtenez donc toujours des versions épinglées partout.

J'étais probablement un peu trop fort pour dire que cela ne fonctionnera tout simplement pas . Mais au moins tous les essais précédents ont échoué, et beaucoup de ceux qui ont essayé sont des gens très intelligents, beaucoup plus intelligents que moi. Je ne pense pas que cela puisse être fait, personnellement, et je continuerais à penser de cette façon jusqu'à ce que je voie la proposition très brillante qui le fait réellement.

@tsiq-oliverc Pieter Hintjens a écrit quelque part un concept de "Les commentaires sont les bienvenus sous forme de pull request"

J'aime ça parce que ça déplace l'attention des conseils philosophiques vers des choses vraiment tangibles et pratiques. Et cela limite également le nombre de commentaires car un commentateur apprend souvent au passage que l'idée est incomplète ou en quelque sorte brisée dans l'usage réel.

Je vous ai demandé un exemple de bibliothèque python, où pipenv est utilisé correctement (ou du moins utilisé) et vous n'en avez fourni aucun.

Vous commentez les qualités tox mais admettez que vous ne les connaissez pas, répétant encore quelque chose sur les meilleures pratiques dans le monde du développement de packages python.

Vous dites que Flask est peut-être un cas spécial. J'ai donc cherché sur Github des projets python en utilisant le mot "bibliothèque", triés en fonction du nombre de fourches (car cela reflète probablement le nombre de personnes qui font du développement avec), ignoré toutes les "listes de quelque chose" et compté le nombre d'environnements pour un OS (généralement Linux) :

Le nombre réel d'environnements dans lesquels exécuter des tests sera principalement 2 (+Windows) ou 3 (+OSX) fois plus élevé.

tox est utilisé dans 2 projets sur 3 (je ne le compare pas à Travis ou Appveyor car ils font un autre niveau de test à côté).

Le nombre d'environnements à tester est assez élevé, Flask n'est certainement pas le plus sauvage.

Le nombre d'environnements pour lesquels définir des dépendances fixes n'est vraiment pas gérable manuellement.

Déposer simplement Pipfile.lock dans un référentiel est assez facile, mais cela n'apporte aucune amélioration magique (si oui, montrez-moi un scénario réel, quand cela améliorera la situation).

Peut-être connaissez-vous la règle d'or du monde "compilé" et pensez-vous que le déterminisme (ou la répétabilité) est également un must pour Python. Comme vous le voyez, de nombreux projets Python vivent plutôt bien sans cela, il se peut donc que la règle d'or ne s'applique pas aussi strictement ici.

Je serai heureux si nous trouvons l'utilisation de pipenv pour les bibliothèques python, ce qui améliorera la situation. Et je veux empêcher l'utilisation, qui nuirait à la qualité globale.

Pour atteindre cet objectif, mon approche consiste à itérer sur les questions :

  • Dois-je utiliser l'outil ?
  • Comment?
  • Pourquoi, quelle valeur ai-je obtenu ?
  • Cela a-t-il introduit des problèmes ? (travail supplémentaire, erreurs cachées...)

@féluxe

Désolé si ce n'était pas clair. Mes dépendances lib sont censées être ce que les gens mettent actuellement dans setup.py / install_requires. Peut-être que les dépendances pypi seraient un meilleur nom pour ce que je voulais dire.

Voir pbr discussion dans ce numéro. C'est l'effort de prendre en charge les dépendances de bibliothèque par Pipfile.

Je pense qu'un Pipfile ne doit pas être utilisé à deux fins (lib et app), ces choses doivent être faites séparément. Si vous pensez que c'est vraiment nécessaire, pourriez-vous décrire le but d'un projet qui l'utilise ? J'essaie généralement de séparer les projets de développement et de déploiement de bibliothèques car ils ont une utilisation assez différente dans le temps.

@vlcinsky Je ne sais pas vraiment où vous voulez en venir (je ne sais pas quel genre de relations publiques vous demandez !), alors je vais me retirer de cette conversation pour le moment.

Pour reformuler le TL;DR de ma position :

  1. Les versions déterministes sont hautement souhaitables, courantes ailleurs dans l'industrie du logiciel et faciles à réaliser avec Pipenv.
  2. Il existe certainement des cas extrêmes, et quelqu'un devrait y faire progresser l'état de l'art (via des solutions de contournement ou via un meilleur outillage).
  3. Il serait irresponsable que la documentation de Pipenv ne recommande pas (1) simplement parce que (2) affecte un petit sous-ensemble de cas.

@uranusjr Compris . Bien que je ne pense pas qu'il y ait quelque chose de spécifique à la langue ici, c'est simplement que différentes communautés se sont installées sur différentes heuristiques pour traiter un problème sans solution générique - si vous avez des conflits de version, vous avez un problème.

Maven/Java (par exemple) vous oblige à y penser au moment de la construction. La méthode NPM signifie que vous rencontrez des problèmes d'exécution si les versions incompatibles traversent une interface. La résolution d'exécution (par exemple, Python, les bibliothèques dynamiques) signifie qu'un dépendant peut planter/etc. si la version de dépendance n'est pas ce à quoi elle s'attendait.

@vlcinsky

Voir la discussion pbr dans ce numéro. C'est l'effort de prendre en charge les dépendances de bibliothèque par Pipfile.

pbr semble gentil et tout, mais il entre dans la catégorie que j'essayais d'aborder avec ceci:

Je pense que quelque chose comme ça omettrait le besoin d'un morceau de sections anti-modèle et d'outils tiers pour combler le vide.

Je pense que de tels outils ne devraient pas être nécessaires en premier lieu.

Si vous pensez que c'est vraiment nécessaire, pourriez-vous décrire le but d'un projet qui l'utilise ? J'essaie généralement de séparer les projets de développement et de déploiement de bibliothèques car ils ont une utilisation assez différente dans le temps.

En ce qui concerne les packages pypi, j'ai fini par utiliser Pipenv pour gérer les dépendances de développement, Pipfile pour décrire les dépendances de développement, setup.py pour décrire les dépendances de lib avec install_requires et setuptools dans setup.py pour publier mon package exécutant pipenv run python setup.py bdist_wheel upload . C'est ce que je considère comme compliqué.

Dans d'autres langues modernes, je dois apprendre un outil de ligne de commande (gestionnaire de packages) et un format de fichier de dépendance. La documentation est en un seul endroit et plus facile à suivre et un nouveau venu résoudra tout cela en quelques heures. Il s'agit de npm init , npm install foo --dev , npm publish . Pipenv/Pipfile peut déjà en faire la plupart, s'il pouvait tout faire, des problèmes comme celui-ci n'existeraient pas.

Je réitère mon appel à une sorte de section/wiki "communauté" pour cette discussion. Il y a plusieurs "modèles" qui peuvent être légitimes et certains d'entre nous pourraient vouloir partager leur "façon de faire des bibliothèques python", certains comme moi avec pbr, et d'autres pourraient avoir un très bon modèle. Mais une page à l'intérieur du document pipenv, je ne sais pas si c'est une bonne idée.

PS : pour préparer la migration vers le nouveau pypi, vous devez utiliser de la ficelle et non python setup.py upload. L'utilisation de "upload" doit être considérée comme un anti-modèle.

Peut-être que pipenv peut développer une commande "publier" ?

@feluxe Vous voudrez peut-être jeter un œil à la poésie . Je viens de tomber dessus et il semble que c'est ce que vous cherchez.

Il fait ce que fait pipenv et plus et il semble qu'ils le fassent mieux, notamment en ce qui concerne la gestion des dépendances (du moins c'est ce qu'ils prétendent). Il fait la gestion des dépendances, l'empaquetage et la publication d'un seul outil poetry .

Je me demande si pipenv et poetry pourraient rassembler leurs efforts pour enfin donner à Python un véritable gestionnaire de paquets.

Je tiens à me répéter avant que cette discussion n'aille trop loin. Pipenv ne peut pas simplement développer une commande publish , ou faire quoi que ce soit qui essaie de prendre en charge le devoir d'emballage. Cela ne ferait que fragmenter davantage l'écosystème, car tout le monde ne le fait pas de cette façon, et les dépendances des applications et des bibliothèques étant théoriquement différentes, vous ne pouvez pas dire à quelqu'un de les fusionner une fois la distinction faite dans son flux de travail.

Il peut sembler que presque tout le monde est d'accord avec cette fusion, mais la vérité est qu'il y a beaucoup plus de gens qui ne se joignent pas à cette discussion parce que les choses fonctionnent pour eux et qu'ils font autre chose. Je l'ai dit à plusieurs reprises : les discussions sur l'amélioration de la conception des chaînes d'outils et des formats de fichiers devraient avoir lieu quelque part plus haut dans la hiérarchie des emballages Python, de sorte qu'elles soient davantage exposées aux personnes qui conçoivent des éléments plus fondamentaux sur lesquels Pipenv s'appuie. S'il vous plaît, prenez la discussion là-bas. Il ne sert à rien de le suggérer ici, car Pipenv n'est pas en mesure de le changer.

Je l'ai dit à plusieurs reprises : les discussions sur l'amélioration de la conception des chaînes d'outils et des formats de fichiers devraient avoir lieu quelque part plus haut dans la hiérarchie des emballages Python, de sorte qu'elles soient davantage exposées aux personnes qui conçoivent des éléments plus fondamentaux sur lesquels Pipenv s'appuie.

Je suis d'accord pour dire que la discussion sur ce bogue devient incontrôlable maintenant que l'empaquetage et la publication sont apparus (ce bogue ne concerne que la gestion des dépendances !), mais pourriez-vous s'il vous plaît nous indiquer le bon endroit pour avoir cette discussion ? Les gens l'ont ici parce que pipenv est considéré comme un pas indispensable dans la bonne direction, pas parce qu'ils veulent imposer des responsabilités supplémentaires aux mainteneurs de pipenv.

Edit : Désolé, j'ai dû manquer le post dans lequel tu as fait exactement ça en lisant les nouveaux commentaires la première fois.

Dans le cadre de cette proposition, cependant, je suggérerais qu'elle se concentre sur les meilleures pratiques actuellement possibles, au lieu d'entrer dans le trou du lapin de l'élaboration d'un nouveau flux de travail pour l'ensemble de la communauté d'emballage Python. Il serait plus productif de proposer une meilleure pratique dans les contraintes actuelles, puis de lancer la discussion pour des améliorations.

Je suis tout à fait d'accord avec cela. Nous devons d'abord déterminer quel est le meilleur flux de travail possible pour les responsables de bibliothèque en ce moment avant de proposer de grands projets. Concentrons-nous à nouveau sur cela, comme nous l'avons fait au début de ce fil. Je ne pense pas que nous ayons encore atteint une conclusion.

Retour au sujet : citant le message de

Une autre façon de contourner ce problème est de faire quelque chose d'intelligent dans les outils d'empaquetage qui "détache" la version de dépendance. Bundler (de Ruby) le fait en quelque sorte, en recommandant aux gens de ne pas inclure le fichier de verrouillage dans la gem, afin que Bundler puisse utiliser les versions non épinglées dans Gemfile, au lieu des versions épinglées dans Gemfile.lock. Mais les gens ont tendance à ignorer les conseils et à faire ce qu'ils veulent, vous obtenez donc toujours des versions épinglées partout.

J'étais probablement un peu trop fort pour dire que cela ne fonctionnera tout simplement pas. Mais au moins tous les essais précédents ont échoué

Je ne vois toujours pas pourquoi la recommandation officielle pour les bibliothèques pour l'instant ne peut pas être d'utiliser pipenv pour leurs builds CI, mais gardez le Pipfile.lock hors du contrôle de source. Puisque, comme quelques personnes l'ont souligné, pipenv n'a actuellement rien à voir avec le processus d'empaquetage, nous ne devrions pas rencontrer le problème que vous avez décrit ci-dessus.

Et je ne vois pas non plus pourquoi c'est un argument contre la définition de vos dépendances abstraites dans le même fichier que les applications utilisent pour définir leurs dépendances abstraites. Ce n'est pas grave si pipenv ne veut pas implémenter une solution élaborée pour intégrer le Pipfile avec setup.py , mais je ne vois pas pourquoi c'est une mauvaise idée en général.

@vlcinsky

Je pense qu'un Pipfile ne doit pas être utilisé à deux fins (lib et app), ces choses doivent être faites séparément.

Voir mon post ci-dessus. Pourriez-vous s'il vous plaît expliquer pourquoi vous pensez cela? Je ne vois tout simplement aucun inconvénient en principe. À l'heure actuelle, ce peut être une mauvaise idée d'inclure un Pipfile , car vous devrez alors définir les dépendances de la même manière dans deux fichiers différents, mais je n'ai encore vu aucun argument qui explique pourquoi ce serait une mauvaise idée d'utiliser le Pipfile pour les déclarations de dépendances en général.

Notez que j'ai déjà convenu que Pipfile.lock ne devrait pas être dans le contrôle de source pour les bibliothèques, sauf si vous êtes dans la même situation que moi.

Edit : De plus, s'il s'avère que pipenv lui-même a réellement besoin de connaître la différence, vous pouvez simplement introduire quelque chose comme le champ crate-type cargo avant de commencer à introduire app-dependencies et lib-dependencies - cela semble trop compliqué.

@ Moritz90 Plusieurs listes de diffusion de Python seraient de bons endroits pour tenir cette discussion.

pypa-dev est le plus précis pour les discussions centrées sur l'emballage Python et l'écosystème qui l'entoure. Je commencerais probablement ici si je devais poster une discussion similaire.

python-ideas est un endroit pour discuter d'idées et a une visibilité assez élevée pour l'ensemble de la communauté Python. Ce serait également un bon point de départ si vous souhaitez pousser cela au niveau PEP (éventuellement, vous le feriez, je pense).

@tsiq-oliverc

Par relations publiques, je veux dire : montrez un exemple prouvant que votre concept est viable.

Alors récupérez une bibliothèque existante, forkez-la, appliquez votre (1) - vous dites que ce sera facile avec pipenv et montrez-moi. J'ai essayé assez fort et j'ai des difficultés.

Si votre (2) signifie "quelqu'un d'autre doit faire le travail", votre PR n'existera pas.

En (3) vous parlez de "petit sous-ensemble de cas" sans donner de nombre réel. Toutes les meilleures bibliothèques que j'ai décrites en ce qui concerne le nombre de virtualenvs sont-elles considérées comme un "petit sous-ensemble" ?

Pour conclure cette discussion, j'ai créé un bref résumé de ce qui a été trouvé au cours de la discussion.

Focus : pipenv (anti)motifs pour les bibliothèques et applications python

J'ai un peu changé d'orientation : il ne parle pas seulement des bibliothèques Python (générales), mais aussi des applications car il était plutôt bon marché de les inclure et cela montre bien les différences.

J'ai intentionnellement exclu tout ce qui proposait des changements dans l'outillage existant tel que pipenv , tox etc.

Qu'est-ce que pipenv et qu'est-ce que ce n'est pas

  • c'est un outil de déploiement, permettant de définir et d'appliquer des dépendances concrètes au moyen de Pipfile.lock .
  • c'est un outil de gestion virtualenv.
  • ce n'est PAS un outil d'emballage dans le sens de générer un package python.

Bibliothèques et applications

Le produit (logiciel python) est soit prêt à être utilisé dans un autre produit (donc une bibliothèque), soit il s'agit d'une application finale prête à être exécutée.

Personnellement, je pense que même les "bibliothèques d'entreprise" entrent dans la catégorie des bibliothèques (les mêmes règles s'appliquent, seul le nombre de contextes d'exécution est plus petit).

Types de produits logiciels

  • bibliothèque : à utiliser dans un autre produit (bibliothèque ou application)
  • application : à déployer et à exécuter

Méthodes d'installation :

  • bibliothèque : pipenv install <package> donc "mettre le paquet en jeu (résolution des versions pour les autres bibliothèques)"
  • application : pipenv sync donc "appliquer des dépendances concrètes"

Dépendances abstraites et concrètes

dépendances de produits logiciels

  • dépendances abstraites : doit nommer les bibliothèques utilisées, peut restreindre les versions ou l'utilisation, mais doit rester suffisamment flexible (ne doit pas épingler les versions)
  • dépendances concrètes : doit épingler les versions, idéalement avec les hachages des bibliothèques utilisées

    pipenv artefacts :

  • Pipfile : dépendances abstraites

  • Pipfile.lock : dépendances concrètes (verrouillées)"

Contextes d'exécution

Nombre typique de contextes d'exécution différents

  • une bibliothèque:

    • python virtualenvs sur un seul système d'exploitation : 3 à 9 (tornade utilisant 30)

    • nombre d'OS : 1 à 3 (Linux, OSX, Windows)

    • nombre total : 3 à 18

  • application:

    • python virtualenvs sur un seul système d'exploitation : 1

    • nombre d'OS : 1

    • nombre total : 1 (ou très peu)

Objectifs, priorités et déterminisme de l'IC

Objectif CI

  • une bibliothèque:

    • le code incl. ses dépendances abstraites permettent l'installation et la fonction attendue dans toutes les variantes attendues des contextes d'exécution.

    • quand (privé/public) pypi obtient la mise à jour de la bibliothèque de dépendances, échoue, si cela affecte l'installation de la bibliothèque testée de la fonction.

  • application:

    • une fois installé (en utilisant des dépendances concrètes/épinglées), toutes les fonctionnalités attendues sont fournies dans un contexte d'exécution prédéfini

Objectifs particuliers de CI concernant la fonctionnalité :

  • une bibliothèque:

    • les dépendances abstraites déclarées par la bibliothèque sont complètes et incluent toutes les restrictions nécessaires (uniquement là où elles sont nécessaires) : la bibliothèque s'installe correctement

    • tous les cas d'utilisation attendus fonctionnent correctement

  • application:

    • les dépendances concrètes sont complètes et toutes sont épinglées, le meilleur incl. hachages : l'application s'installe correctement

    • tous les cas d'utilisation attendus fonctionnent correctement

Différents modes de test CI

  • Mode : "Courir, Forrest, Courir"

    • De nos jours, la grande majorité des bibliothèques python sont testées de cette façon.

    • utilisez tox ou un logiciel de test similaire

    • Pas d'utilisation de pipenv et de dépendances concrètes (peut convenir aux bibliothèques)

  • Mode : "Générer et sceller"

    • Pas de Pipfile dans le référentiel

    • Pipfile.lock créé par pipenv install -e .

    • Pipfile.lock documente (scelle) l'environnement et permet la reproduction ultérieure de virtualenv pour analyser les problèmes.

  • Mode : "L'âge de glace"

    • essai en deux phases

      • lorsque les dépendances abstraites (définies dans setup.py install_requires ) le changement ou le package dépendant sur pypi est mis à jour, régénérer Pipfile.lock par pipenv install -e .

    • exécution de test de fonction : s'exécute lorsque le code de la bibliothèque change. Est exécuté dans virtualenv créé par pipenv sync Pipfile.lock

      Comment et par qui peut être créé Pipfile.lock

  • manuellement par le développeur (peut fonctionner pour les applications)

  • automatiquement par CI build (et en réussissant tous les tests, le déclarer artefact vérifié)

Priorité du déterminisme versus flexibilité

  • bibliothèque : flexibilité (exécuter chaque fois que possible)
  • application : déterminisme (exécuté exactement de la même manière dans le contexte d'exécution sélectionné)

    Ce qui peut affecter le déterminisme du produit installé :

  • public pypi (faible déterminisme, les packages sont mis à jour à tout moment)

  • pypi privé (déterminisme supérieur, les mises à jour des packages peuvent être contrôlées)
  • exigences abstraites dans les bibliothèques (ne doit pas être utilisé pour le déterminisme)
  • exigences concrètes ( Pipfile.lock ) : déterminisme total

Divers

Quelques cas d'utilisation pour Pipfile.lock :

  • (antipattern) définit les dépendances abstraites de la bibliothèque (car elle doit être abstraite)
  • (antipattern) configurer virtualenv pour la bibliothèque testée (peut masquer les dépendances abstraites de la bibliothèque cassée)
  • documenter exactement virtualenv ("seal"), où un test a été exécuté (permettant ainsi au développeur de le recréer plus tard pour les tests cassés et de l'expérimenter)
  • configurer virtualenv pour l'application testée
  • déployer l'application en production

    Autres conseils

  • pbr bibliothèque requirements.txt . La mise à jour de la lecture Pipfile est en route.

  • poetry package essaie quelque chose de similaire à pyenv

    Problèmes courants

  • "drop lockfile into repo" et vous obtenez des builds déterministes :

    • Doit travailler pour les applications.
    • Ne fonctionnera pas pour les bibliothèques, car il existe de nombreux contextes d'exécution et chacun a un bon potentiel pour générer différents Pipfile.lock . Sérieusement : flask montre sur ses 11 environnements virtuels différents (sur un seul système d'exploitation) 10 dépendances verrouillées différentes. Qui va les créer et les engager ?
    • Notez qu'avec le mode CI "Générer et sceller", vous pouvez toujours obtenir Pipfile.lock (mais généré par le script CI) permettant de régénérer le virtualenv ailleurs.
  • Pipfile.lock dans le référentiel de la bibliothèque

    • s'il est utilisé pour créer virtualenv, il peut masquer la définition cassée des dépendances de la bibliothèque dans setup.py .

  • Pipfile dans le référentiel de la bibliothèque

    • s'il répète des dépendances abstraites (qui doivent être définies dans setup.py ), il peut masquer une déclaration de dépendance setup.py cassée.

    • recommandé : générez Pipfile par pipenv install -e . ou pipenv install -e .[tests] si vous avez également besoin de tester les dépendances et qu'elles sont déclarées comme des extras "tests" dans le setup.py

  • ajout de pipenv install <something> dans les scripts CI

    • cela n'améliore pas beaucoup le déterminisme en lui-même

    • voir le mode CI "Générer et sceller" (alors toute l'installation dans virtualenv doit passer par pipenv ).

Conclusion

Les bibliothèques Python (en particulier les plus générales) présentent un nombre étonnamment élevé de contextes d'exécution. La raison en est qu'avec les bibliothèques, l'objectif est une flexibilité éprouvée dans différentes conditions. La flexibilité semble plus importante que les constructions déterministes. Pour les personnes venant du monde de la "compilation", cela peut sembler être un très mauvais anti-modèle. Le fait est que la plupart (éventuellement toutes) des bibliothèques python ne fournissent pas de versions déterministes (si vous en connaissez, faites-le moi savoir) et Python se débrouille toujours très bien. Les raisons pour lesquelles les applications Python sont toujours vivantes peuvent être : python en tant que langage de script diffère du monde compilé. L'autre raison pourrait être que le déterminisme peut (doit) être résolu une étape plus tard dès que l'application (construite à partir d'un ensemble de bibliothèques) résoudra l'exigence (naturelle et justifiée) de déterminisme.

Pour les applications, la situation est juste à l'opposé et ici le déterminisme est vraiment facile à atteindre avec des outils tels que pipenv .

Que faire ensuite?

  • Je n'aurai pas le temps de m'en occuper la semaine prochaine ou les deux.
  • Je peux imaginer créer une série d'entrées de blog quelque part (je ne sais pas où). Si vous connaissez l'endroit (idéalement permettant une certaine discussion), ce serait un endroit naturel pour laisser le contenu être référencé, discuté et enfin éventuellement (s'il survit) mis quelque part dans la pierre :-).
  • Je propose à @uranusjr de prendre le contrôle de ce problème (fermez-le, décidez quoi faire ensuite, redirigez les gens ailleurs ou tout ce qui semble pratique)

Merci à tous pour la discussion très inspirante - je me sens comme un message "Je suis totalement perdu dans ce sujet" remanié trois fois - ce qui signifie naturellement que nous nous sommes améliorés.

@vlcinsky poetry n'a rien à voir avec pyenv . C'est un peu comme pipenv (mais avec une bien meilleure implémentation concernant la gestion des bibliothèques et des applications, IMO) mais avec la partie packaging et publication.

Vous avez un fichier pyproject.toml qui définit votre projet et ses dépendances (dépendances abstraites) et un pyproject.lock qui décrit les dépendances épinglées et sont épinglés pour toute version de python et plate-forme le pyproject.toml fichier a spécifié afin de n'avoir qu'un seul fichier de verrouillage déterministe pour éviter les problèmes auxquels pipenv est confronté. Uniquement lors de l'installation, poetry vérifiera les packages à installer en les comparant à l'environnement.

Et lorsqu'il packagera votre bibliothèque, il utilisera les dépendances abstraites (et non celles épinglées) afin que vous conserviez la flexibilité lors de la distribution de votre package (via PyPI par exemple).

L'avantage de ceci est qu'il utilisera des dépendances abstraites pour les bibliothèques et le fichier de verrouillage pour les applications. C'est le meilleur des deux mondes.

La poésie

Essentiellement, nous consacrons beaucoup de temps et d'efforts à la résilience pour que les petits projets qui font des revendications élevées n'aient pas à consacrer autant d'efforts parce que les gens ne frappent pas les cas extrêmes. Si vous pensez vraiment qu'un autre outil vous offre le meilleur de tous les mondes, alors je vous encourage à l'utiliser - pipenv lui-même ne va pas gérer l'emballage pour vous à court terme, voire jamais.

@techalchemy Je ne vends rien, vraiment, je pipenv .

Et poetry fait des dépendances d'épingles dans pyproject.lock , tout comme pipenv dans Pipfile.lock . Vous avez donc une reproduction exactement comme le fournit pipenv . Si vous avez un fichier de verrouillage, il sera utilisé et installera une dépendance épinglée et si je ne me trompe pas, c'est aussi ce que fait pipenv .

La seule fois où il utilise des dépendances abstraites, c'est lorsqu'il conditionne le projet pour la distribution (donc essentiellement pour les bibliothèques) car dans ce cas, vous ne voulez pas de dépendances épinglées.

@vlcinsky Il reste encore quelques points à régler, corriger ou développer, mais je tiens toujours à ce que cela se fasse sous forme de documentation, Pipenv ou autre. Seriez-vous intéressé par l'envoi d'une pull request ? Je serais plus qu'heureux d'aider à étoffer l'article.

Concernant la poésie, je ne suis pas personnellement un fan dans son ensemble, mais elle fait beaucoup de choses correctes. Il ne devrait probablement pas être mentionné dans la documentation de Pipenv car il viole quelques bonnes pratiques que les développeurs de Pipenv veulent inciter les gens vers, mais il devrait être mentionné si la discussion a lieu dans pypa-dev ou similaire, pour fournir une image complète de la façon dont l'emballage l'écosystème l'est actuellement.

la poésie peut également utiliser plus d'attention et de contribution. Ce serait le mieux pour la communauté, y compris Pipenv. Avec des choix viables, les gens peuvent peser sur leurs choix au lieu d'entrer dans Pipenv la tête la première et de se plaindre de ne pas faire ce qu'ils attendent. Une bonne concurrence entre les bibliothèques peut également stimuler des améliorations techniques sur le front de la résolution des dépendances, ce que Pipenv et la poésie font tous les deux (et ni parfaitement). Nous pouvons apprendre beaucoup les uns des autres.

@uranusjr Oui, je pense que peu de choses ont été clarifiées et méritent d'être partagées avec un public plus large. Votre aide est vraiment la bienvenue.

Qu'en est-il de la « rédaction de la documentation en binôme » ? Je pense qu'en ce moment il serait plus efficace de travailler dessus à petite échelle de deux personnes seulement.

Les réflexions à faire sont (éventuellement avec une ou deux itérations) :

  • où exactement on pourrait publier ça
  • identifier les éléments de documentation (articles, sections)
  • clarifier la portée et l'objectif de chaque élément
  • d'accord sur le plan
  • identifier les problèmes ouverts
  • les travailler
  • écrire la doc
  • publier (et j'espère qu'il sera accepté)

Si vous avez envie de l'écrire vous-même (sur la base de ce qui a été discuté) et de m'avoir comme critique, je ne me plaindrais pas.

Je vous contacterai par e-mail pour convenir des prochaines actions.

@vlcinsky Je suis également disponible en tant que @uranusjr sur PySlackers (un espace de travail Slack) si vous préférez l'interaction en temps réel. Pipenv y a un canal ( #pipenv ).

@uranusjr C'est ce que je voulais dire par rassembler des efforts. Python a désespérément besoin d'un bon gestionnaire de paquets comme cargo. L'écosystème Python est pâle par rapport aux autres langages en raison de l'absence d'une façon standard de faire les choses. Et pipenv n'aidera pas avec ça, je pense.

Ce qui me dérange, c'est que pipenv s'annonce comme the officially recommended Python packaging tool alors que ce n'est pas un outil de packaging, loin de là, ce qui est trompeur pour les utilisateurs. C'est simplement un gestionnaire de dépendances couplé à un gestionnaire virtualenv.

De plus, vous dites qu'il a été inspiré par cargo, npm, fil qui sont des outils d'emballage avec des gestionnaires de dépendances alors que la tuyauterie ne l'est pas.

Et voici le défaut de pipenv , cela brouille les cartes puisque les gens feront toujours les mêmes erreurs qu'avant avec requirements.txt vs setup.py . Les projets seront toujours mal emballés avec des dépendances mal définies dans leurs setup.py cause de cela. C'est ce que des projets comme cargo ont bien fait : ils gèrent tous les aspects du développement de projets/d'applications pour assurer une cohérence alors qu'un projet comme pipenv ne le fait pas.

Et quand tu dis :

ce que Pipenv et la poésie font tous les deux (et ni parfaitement)

Que veux-tu dire? D'après ce que j'ai vu, leur gestionnaire de dépendances est beaucoup plus résistant que celui fourni par pipenv . Le seul inconvénient est qu'ils utilisent l'API PyPI JSON qui n'a parfois pas d'informations de dépendance en raison de packages mal publiés.

Quoi qu'il en soit, je pense, comme vous l'avez dit, que les deux projets peuvent apprendre l'un de l'autre.

Et, encore une chose, quel est l'avenir de pipenv si, finalement, pip gère les Pipfile ? Sera-ce juste un gestionnaire de virtualenv?

Si le gestionnaire de dépendances de poésie s'appuie sur l'API json, ce n'est pas seulement parfois faux en raison de « packages mal publiés », il sera très limité dans ce qu'il peut réellement résoudre correctement. L'api de l'entrepôt json publie les dépendances _les plus récentes_ même si vous avez affaire à une ancienne version, et c'est s'il contient ces informations. Nous avions aussi l'habitude d'intégrer l'API json, c'était super car c'était rapide, mais l'équipe d'infrastructure nous a dit de ne pas lui faire confiance. Il semble un peu fallacieux d'appeler quelque chose de résilient s'il s'appuie sur une source peu fiable pour commencer.

En fin de compte, les défis consistent à créer un graphe de dépendances qui a exécuté un fichier d'installation car actuellement, c'est ainsi que fonctionne l'empaquetage. Il n'y a tout simplement aucun moyen de contourner cela. Un graphique de dépendance qui se résout sur ma machine peut être différent de celui qui se résout sur votre machine, même pour le même package.

Il est facile de faire signe à la main et de dire "Eh bien, cela ne fait-il pas de pipenv un gestionnaire de virtualenv si pip peut lire un pipfile ?" Non. Pipenv est un gestionnaire de dépendances. Il gère les environnements idempotents et génère un fichier de verrouillage reproductible. Je me rends compte que cela doit vous sembler trivial parce que vous le supprimez et réduisez cet outil à un gestionnaire de virtualenv, mais ce n'est pas le cas. Nous résolvons les fichiers de verrouillage et incluons des marqueurs pour les versions de python que vous n'avez pas, que vous n'utilisez pas, et les gardons disponibles afin que vous puissiez déployer et reproduire avec précision sur les plates-formes et les versions de python. Nous utilisons plusieurs méthodes de résolution, notamment la gestion des roues et des fichiers locaux, des référentiels vcs (nous résolvons également le graphique là-bas), des artefacts distants, des packages pypi, des index privés, etc.

À la fin de la journée, pip _sera_ gérer les fichiers pip, c'est le plan, c'est le plan depuis que le format a été créé. Mais c'est la même chose que de demander « mais qu'en est-il du moment où pip peut gérer les fichiers d'exigences ? » La question est fondamentalement identique. Pip peut installer ce format. Cela ne concerne pas vraiment les fonctionnalités que j'ai décrites, à part le fait que nous installons également les fichiers (en utilisant pip, soit dit en passant).

@techalchimie

L'api de l'entrepôt json publie les dépendances les plus récentes même si vous avez affaire à une ancienne version, et c'est s'il a cette information du tout

C'est tout simplement faux, vous pouvez obtenir des dépendances de version spécifiques en appelant https://pypi.org/pypi/{project}/{release}/json . Si vous appelez simplement https://pypi.org/pypi/{project}/json vous n'obtiendrez que les dernières dépendances, mais vous pouvez en fait obtenir le bon ensemble de dépendances.

Et la partie packaging/publication des projets python a vraiment besoin d'être améliorée car au final elle profitera à tout le monde, puisqu'elle permettra d'utiliser l'API JSON de manière fiable.

Il gère les environnements idempotents et génère un fichier de verrouillage reproductible.
Nous résolvons les fichiers de verrouillage et incluons des marqueurs pour les versions de python que vous n'avez pas, que vous n'utilisez pas, et les gardons disponibles afin que vous puissiez déployer et reproduire avec précision sur les plates-formes et les versions de python.

Et il en va de même pour poetry . Et vous pouvez l'empêcher d'utiliser l'API JSON pour utiliser la même méthode de résolution que pipenv (à l'aide de pip-tools). Voir https://github.com/sdispater/poetry/issues/37#issuecomment -379071989 et il sera toujours plus résistant que pipenv (https://github.com/sdispater/poetry#dependency-resolution )

@zface Je dirai ceci une dernière fois, veuillez le porter quelque part plus haut dans la hiérarchie. Pipenv ne prétend pas être l'outil d'empaquetage Python officiellement recommandé ; il dit cela parce que dites-le aux responsables qui recommandent Pipenv . S'il vous plaît, ne mettez pas ces choses sur Pipenv dev. Ce n'est pas le bon endroit pour se plaindre, et vous ne pouvez pas obtenir de résolutions pour vos plaintes ici. Vous pouvez également obtenir de meilleures réponses aux questions techniques que vous vous posez. Il s'agit d'un outil de suivi des problèmes pour Pipenv, et non d'un forum de discussion pour les outils d'empaquetage Python et comment l'empaquetage Python est fait.

Pipenv ne s'appuie pas uniquement sur des outils pip pour la résolution, veuillez arrêter de réduire notre logiciel à une seule doublure qui démontre un manque de compréhension. Je connais très bien le fonctionnement de l'api PyPI, j'ai parlé directement à l'équipe qui l'a implémentée.

C'est tout simplement faux,

Ce genre d'attitude n'est pas le bienvenu ici. Ne présumez pas que nous ne comprenons pas de quoi nous parlons. Veuillez pratiquer la courtoisie.

il sera toujours plus résistant que pipenv (https://github.com/sdispater/poetry#dependency-resolution)

Pipenv n'aplatit actuellement pas les graphiques de dépendance. Souligner un problème spécifique où un arbre a été aplati et prétendre que l'ensemble de l'outil est donc à la fois meilleur et plus résistant est insensé, vous prouvez encore et encore que vous êtes simplement là pour insulter pipenv et promouvoir la poésie. S'il vous plaît, passez votre chemin, ce comportement n'est pas le bienvenu.

Je suis d'accord que la discussion est hors sujet, qui essayait de capitaliser les "bonnes pratiques" autour de pipenv.

Cependant,

[...] vous ferez toujours les mêmes erreurs qu'avant avec requirements.txt vs setup.py. Les projets seront toujours mal emballés avec des dépendances mal définies dans leur setup.py à cause de cela.

Je partage cet avis, amener de nouveaux développeurs à packager avec succès leur propre code Python est en fait complexe, trop complexe, nécessite de lire beaucoup de documentation en ligne.
Mais ce n'est pas à pipenv ou à toute autre dépendance de package de gérer cela entièrement. Nous ne pouvions pas réécrire l'histoire. Nous, en tant que communauté, devons trouver un moyen de moderniser la chaîne d'outils Python, étape par étape.

Et pipenv (et probablement la poésie) est un très bon pas en avant.

Avoir à maintenir d'un côté Pipfile pour l'application et setup.py pour les bibliothèques de l'autre côté, est une évidence. Peu importe à quel point nous expliquons avec beaucoup de mots et de longs articles et guides de bonnes pratiques, c'est trop complexe pour ce que c'est. Je suis tout à fait d'accord que c'est comme ça pour le moment, mais cela ne devrait pas nous empêcher d'imaginer une voie meilleure et plus sûre.
Au final, en tant que développeur, je veux un seul outil, peut-être avec deux modes différents, pour m'aider et me simplifier la vie au maximum.

Cela devrait être un moyen d'extraire uniquement la partie qui effectue le requirements.txt/Pipfile partir de bibliothèques telles que PBR pour proposer une sorte de 'easy setup.py', un wrapper compatible avec Pipfile autour de install_requires , sans tous les comportements indésirables apportés par pbr, et emballez-les dans un wrapper setuptools dédié qui ne fait que cela.

Ainsi, nous serions en mesure d'avoir le meilleur de chaque monde :

  • pipenv pour maintenir Pipfile (versionné dans les bibliothèques et les applications)
  • pipenv pour maintenir Pipfile.lock (versionné uniquement pour les applications)
  • on utiliserait ce package de wrapper magique ( pipfile_setuptools , install_requires_pipfile ?) qui serait une dépendance de premier niveau dont le travail consiste uniquement à injecter Pipfile dans install_requires .

C'est un autre projet qui ne serait pas lié à pipenv , mais qui nécessite toujours une bibliothèque d'analyseur générique Pipfile . Qu'est-ce que tu penses?

@gsemet D'après ce que j'ai compris, PyPA a essayé de remplir cela avec pyproject.toml à la place, dirigé par flit . Vous devrez d'abord leur en parler (sur pypa-dev ou distutils-sig) avant de continuer à utiliser Pipfile comme format source. En ce qui concerne l'analyse de Pipfile (et le fichier de verrouillage), elle est gérée dans pypa/pipfile (que les fournisseurs de Pipenv fournissent la logique d'analyse de base).


Edit : Veuillez m'envoyer un message si vous décidez de démarrer une discussion à ce sujet dans l'une ou l'autre liste de diffusion. J'ai quelques idées sur la façon dont nous pouvons réunir les deux parties de la distribution d'emballage Python.

Je dois admettre que je suis un peu triste de voir les dépendances déclarées dans pyproject.toml (qui prend les rôles de setup.cfg fait par PBR), alors que PyPa prend également en charge Pipfile ....

Merci pour le pointeur vers flit et pipfile. Il y a aussi le pipenvlib de Kennethreitz qui semble plus léger.

Le setup.cfg de PBR semble plus complet par rapport à la documentation officielle (ex : data_files ) et réutiliser un fichier déjà partagé avec plusieurs outils (flake8, pytest, ...) peut utiliser le même fichier, réduisant le nombre de fichier à la racine d'un projet python)

Cette page vous a été utile?
0 / 5 - 0 notes