2. Rédaction du script "setup.py"
*********************************

Note:

  Ce document est conservé uniquement jusqu'à ce que la documentation
  de "setuptools", présente à l'adresse
  https://setuptools.readthedocs.io/en/latest/setuptools.html, couvre
  indépendamment toutes les informations pertinentes actuellement
  incluses ici.

Le script "setup.py" est au centre de toute opération de construction,
de distribution et d'installation des modules utilisant les
*Distutils*. L'objectif principal du script "setup.py" est de décrire
le module aux *Distutils*, de telle sorte que les diverses commandes
qui agissent sur votre module fassent les bonnes choses. Comme nous
avons vu dans la section Un exemple simple au-dessus, le script
"setup.py" consiste principalement à un appel à "setup()", et la
plupart des informations fournies aux *Distutils* par le développeur
du module sont fournies en tant qu'arguments nommés à "setup.py()".

Voici un exemple un peu plus concret, que nous allons suivre pour les
quelques sections suivantes : le propre script "setup.py" des
*Distutils* (gardez toujours à l'esprit qu'en dépit de l'inclusion des
*Distutils* dans python 1.6 et ses versions successives, ils ont aussi
une existence à part entière de telle sorte que les utilisateurs de
Python 1.5.2 puissent les utiliser pour installer d'autres modules. Le
propre script "setup.py" des *Distutils* montré ici est utilisé pour
installer le paquet dans Python 1.5.2). :

   #!/usr/bin/env python

   from distutils.core import setup

   setup(name='Distutils',
         version='1.0',
         description='Python Distribution Utilities',
         author='Greg Ward',
         author_email='gward@python.net',
         url='https://www.python.org/sigs/distutils-sig/',
         packages=['distutils', 'distutils.command'],
        )

Il y a seulement deux différences entre cet exemple et l'exemple
trivial de la distribution d'un unique fichier présenté dans la partie
Un exemple simple : plus de métadonnées, et la définition de modules
purement Python par paquet, plutôt que par module. C'est important car
les *Distutils* sont composés de quelques douzaines de modules séparés
(pour le moment) en deux paquets ; une liste explicite de chaque
module serait pénible à générer et difficile à maintenir. Pour plus
d'information sur les métadonnées supplémentaires, voir la partie
Métadonnées additionnelles.

À noter que chaque chemin d'accès fourni au script "setup.py" doit
être écrit selon la convention Unix. Autrement dit, séparé par des
barres obliques (slash). Les *Distutils* prendront soin de convertir
cette représentation indépendante de la plateforme en une
représentation adaptée à votre plateforme actuelle avant
d'effectivement utiliser le chemin d'accès. Cela rend votre script
"setup.py" portable d'un système d'exploitation à l'autre, ce qui
évidemment est l'un des buts majeurs des *Distutils*. Dans cet esprit,
tous les chemins d'accès dans ce document sont séparés par des barres
obliques (slash).

Cela, évidemment, s'applique uniquement aux chemins d'accès passés aux
fonctions de *Distutils*. Si vous, par exemple, vous utilisez les
fonctions standards de Python telles que "glob.glob()" or
"os.listdir()" pour définir des fichiers, vous devez prendre soin
d'écrire du code portable au lieu de coder en dur les séparateurs de
chemin :

   glob.glob(os.path.join('mydir', 'subdir', '*.html'))
   os.listdir(os.path.join('mydir', 'subdir'))


2.1. Lister l'ensemble des paquets
==================================

L'option "packages" dit aux *Distutils* de traiter (construire,
distribuer, installer, etc.) tous les modules en Python pur trouvés
dans chaque paquet mentionné dans la liste "packages". À cette fin,
évidemment, il faut une correspondance entre les noms des paquets et
des répertoires dans le système de fichiers. La correspondance par
défaut est la plus évidente. À savoir : le paquet "distutils" se
trouve dans le répertoire "distutils" situé à la racine de la
distribution. Ainsi, quand vous écrivez "packages = ['foo']" dans
votre script "setup.py", vous vous engagez à ce que les *Distutils*
trouvent un fichier "foo/__init__.py" (qui peut s'épeler différemment
sur votre système, mais vous voyez l'idée) à un emplacement relatif au
répertoire où se trouve le script "setup.py". Si ce n'est pas le cas,
les *Distutils* lèvent un avertissement mais traitent tout de même le
paquet défectueux.

Si vous utilisez une convention différente pour arranger votre
répertoire de sources, ce n'est pas un problème : vous avez seulement
à fournir l'option "package_dir" pour prévenir les *Distutils* de
l'usage de cette convention. Par exemple, supposons que vous gardez
toutes les sources Python sous "lib", de telle sorte que les modules
dans le « paquet racine » (c'est-à-dire dans aucun paquet du tout)
sont dans "lib", les modules dans le paquet "foo" sont dans "lib/foo",
et ainsi de suite. Alors, vous pouvez mettre :

   package_dir = {'': 'lib'}

dans votre script "setup.py". Les clés de ce dictionnaire sont les
noms des paquets, et un nom de paquet vide fait office de paquet
racine. Les valeurs sont des noms de répertoires relatifs à la racine
de votre distribution. Dans ce cas, lorsque vous dites "packages =
['foo']", vous vous engagez à ce que le fichier "lib/foo/__init__.py"
existe.

Une autre convention possible est de mettre le paquet "foo"
directement dans "lib", le paquet "foo.bar" dans "lib/bar", etc. Cela
s'écrirait ainsi dans le script "setup.py" : :

   package_dir = {'foo': 'lib'}

A "package: dir" entry in the "package_dir" dictionary implicitly
applies to all packages below *package*, so the "foo.bar" case is
automatically handled here.  In this example, having "packages =
['foo', 'foo.bar']" tells the Distutils to look for "lib/__init__.py"
and "lib/bar/__init__.py".  (Keep in mind that although "package_dir"
applies recursively, you must explicitly list all packages in
"packages": the Distutils will *not* recursively scan your source tree
looking for any directory with an "__init__.py" file.)


2.2. Lister chaque module indépendamment
========================================

Pour un petit projet, vous pouvez préférer lister tous les modules
plutôt que les paquets — surtout le cas d'un module seul qui va dans
le « paquet racine » (à savoir, aucun paquet du tout). Le cas le plus
simple a été montré dans la partie Un exemple simple ; voici un
exemple plus concret :

   py_modules = ['mod1', 'pkg.mod2']

Deux modules sont décrits, l'un dans le paquet « racine », l'autre
dans le paquet "pkg". Encore une fois, la structure paquet/répertoire
par défaut implique que ces deux modules peuvent être trouvés dans
"mod1.py" et "pkg/mod2.py", et que "pkg/__init__.py" existe aussi. Là
aussi, vous pouvez redéfinir la correspondance paquet/répertoire en
utilisant l'option "package_dir".


2.3. Description des modules d'extension
========================================

Tout comme écrire des modules d'extension Python est un peu plus
compliqué que d’écrire des modules purement en Python, les décrire aux
*Distutils* est un peu plus compliqué. Contrairement aux modules purs,
il ne suffit pas de simplement lister les modules ou les paquets et
d'attendre que les *Distutils* trouvent par eux-mêmes les bons
fichiers ; vous devez définir le nom de l'extension, du ou des
fichiers de sources, et les prérequis de compilation/lien (répertoires
à inclure, bibliothèques à lier, etc.).

Tout ceci est fait à l'aide d'un autre argument nommé passé à
"setup()", l'option "ext_modules". "ext_modules" est simplement une
liste de classes "Extension", chacune décrivant une seule extension de
module. Supposons que votre distribution inclut une seule extension
appelée "foo" et implémentée par "foo.c". Si aucune instruction
supplémentaire au compilateur/lieur n'est requise, décrire cette
extension est assez simple :

   Extension('foo', ['foo.c'])

La classe "Extension" peut être importée depuis "distutils.core" en
même temps que "setup()". Ainsi, le script "setup.py" pour un module
qui ne contient que cette seule extension et rien d'autre peut être :

   from distutils.core import setup, Extension
   setup(name='foo',
         version='1.0',
         ext_modules=[Extension('foo', ['foo.c'])],
         )

La classe "Extension" (en réalité, la machinerie sous-jacente
construisant les extensions implémentées par la commande
**build_ext**) permet une grande flexibilité dans la description des
extensions Python, ce qui est expliqué dans les parties suivantes.


2.3.1. Nom des extensions et paquets
------------------------------------

Le premier argument du constructeur "Extension" est toujours le nom de
l'extension, incluant tout nom de paquet. Par exemple :

   Extension('foo', ['src/foo1.c', 'src/foo2.c'])

décrit une extension qui se situe dans le paquet racine, tandis que :

   Extension('pkg.foo', ['src/foo1.c', 'src/foo2.c'])

décrit la même extension dans le paquet "pkg". Les fichiers sources et
le code objet résultant sont identiques dans les deux cas ; la seule
différence est où, dans le système de fichier (et conséquemment dans
la hiérarchie de l'espace de nommage de Python), l'extension
résultante se situe.

Si vous avez un certain nombre d'extensions toutes dans le même paquet
(ou toutes sous le même paquet de base), utilisez l'argument nommé
"ext_package" de "setup()". Par exemple :

   setup(...,
         ext_package='pkg',
         ext_modules=[Extension('foo', ['foo.c']),
                      Extension('subpkg.bar', ['bar.c'])],
        )

compile "foo.c" en l’extension "pkg.foo", et "bar.c" en
"pkg.subpkg.bar".


2.3.2. Fichiers sources d'extension
-----------------------------------

Le second argument du constructeur d' "Extension" est une liste de
fichiers sources. Puisque les *Distutils* ne gèrent que les extensions
en C, C++ et Objective-C, ce sont normalement des fichiers sources en
C/C++/Objective-C (assurez vous d'utiliser les extensions appropriées
pour détecter les fichiers sources en C++ : ".cc" et ".cpp" semblent
être reconnus tant par les compilateurs Unix que Windows).

Néanmoins, vous pouvez également inclure des fichiers d'interface SWIG
(".i") dans la liste ; la commande **build_ext** sait comment gérer
les extensions SWIG : il lancera SWIG sur un fichier d'interface et
compilera le fichier en C/C++ en une extension.

Malgré cet avertissement, les options peuvent être actuellement
passées à SWIG de la façon suivante :

   setup(...,
         ext_modules=[Extension('_foo', ['foo.i'],
                                swig_opts=['-modern', '-I../include'])],
         py_modules=['foo'],
        )

Ou en ligne de commande de cette façon :

   > python setup.py build_ext --swig-opts="-modern -I../include"

Sur certaines plateformes, vous pouvez inclure des fichiers autres que
des sources qui seront traités par le compilateur et inclus dans votre
extension. Pour l'instant, cela concerne seulement les fichiers de
messages texte Windows (".mc") et les fichiers de définition de
ressource pour Visual C++ (".rc"). Ils seront compilés en fichiers de
ressources binaires (".res") et liés à l'exécutable.


2.3.3. Options de préprocesseur
-------------------------------

Trois arguments optionnels de "Extension" aident si vous avez besoin
de préciser les dossiers d’en-têtes à chercher ou les macros de
préprocesseurs à charger ou ignorer : "include_dirs", "define_macros",
et "undef_macros".

Par exemple, si votre extension nécessite des fichiers d'en-tête dans
le répertoire "include" à la racine de votre distribution, utilisez
l'option "include_dirs" :

   Extension('foo', ['foo.c'], include_dirs=['include'])

Ici, vous pouvez définir le chemin absolu des répertoires ; si vous
savez que votre extension sera compilée sur un système Unix avec
"X11R6" installé dans "/usr", vous pouvez vous en sortir avec :

   Extension('foo', ['foo.c'], include_dirs=['/usr/include/X11'])

Il convient d'éviter ce type d'utilisation non portable si vous
envisagez de distribuer votre code : Il est probablement mieux
d'écrire du code C comme :

   #include <X11/Xlib.h>

Si vous avez besoin d'inclure des fichiers d'en-tête provenant
d'autres extensions Python, vous pouvez profiter du fait que les
fichiers d'en-têtes sont installés de façon cohérente par la commande
**install_headers** des *Distutils*. Par exemple, les fichiers d'en-
têtes de *Numerical Python* (NumPy) sont installés (dans le cas d'une
installation Unix standard) dans
"/usr/local/include/python1.5/Numerical" — l'emplacement exact diffère
selon votre plateforme et votre installation de Python. Vu que le
répertoire "include" de Python — "/usr/local/include/python1.5" dans
ce cas-ci — est toujours inclus dans le chemin de recherche quand vous
construisez des extensions Python, la meilleure approche est d'écrire
du code C comme :

   #include <Numerical/arrayobject.h>

Si vous devez mettre le répertoire "include" de "Numerical"
directement dans l'en-tête du chemin de recherche, cependant, vous
pouvez trouver ce répertoire en utilisant le module
"distutils.sysconfig" des *Distutils* :

   from distutils.sysconfig import get_python_inc
   incdir = os.path.join(get_python_inc(plat_specific=1), 'Numerical')
   setup(...,
         Extension(..., include_dirs=[incdir]),
         )

Même si c'est assez portable — ça marche sur la plupart des
installations de Python, indépendamment de la plateforme — il est
probablement plus facile d'écrire un code C un peu plus réfléchi.

Vous pouvez définir ou ignorer des macros de pré-processeur avec les
options "define_macros" et "undef_macros". "define_macros" prend une
liste de paires "(nom, valeur)", où "nom" est le nom de la macro à
définir (une chaîne de caractères) et "valeur" est sa valeur ; soit
une chaîne de caractères, soit "None" (définir une macro "FOO" à
"None" est équivalent à un simple "#define FOO" dans votre source en C
; pour la majorité des compilateurs, cela définit la valeur de "FOO" à
la chaîne de caractère "1"). "undef_macros" est juste une liste de
macros à supprimer.

Par exemple :

   Extension(...,
             define_macros=[('NDEBUG', '1'),
                            ('HAVE_STRFTIME', None)],
             undef_macros=['HAVE_FOO', 'HAVE_BAR'])

est équivalent à avoir ceci au début de chaque fichier source en C :

   #define NDEBUG 1
   #define HAVE_STRFTIME
   #undef HAVE_FOO
   #undef HAVE_BAR


2.3.4. Options des bibliothèques
--------------------------------

Vous pouvez aussi définir les bibliothèques à lier quand vous
construisez votre extension, ainsi que le répertoire de recherche pour
ces bibliothèques. L'option "libraries" est une liste de bibliothèques
à lier, "library_dirs" est une liste de répertoires dans lesquels
chercher des bibliothèques au moment de la liaison, et
"runtime_library_dirs" est une liste de répertoires pour la recherche
des bibliothèques partagées (chargées dynamiquement) à l'exécution.

Par exemple, pour lier des bibliothèques que l'on sait dans le chemin
des bibliothèques standards des systèmes cibles :

   Extension(...,
             libraries=['gdbm', 'readline'])

Pour lier une bibliothèque se trouvant à un emplacement non standard,
vous devez inclure son emplacement dans "library_dirs" :

   Extension(...,
             library_dirs=['/usr/X11R6/lib'],
             libraries=['X11', 'Xt'])

Là aussi, ce genre de construction non portable doit être évité si
vous avez l'intention de distribuer votre code.


2.3.5. Autres options
---------------------

Il y a encore d'autres options qui peuvent être utilisées pour gérer
des cas spéciaux.

L'option "optional" est un booléen ; s'il est vrai, un échec de la
construction dans l'extension n'annule pas le processus de
construction, mais à la place, l'extension en échec ne sera pas
installée.

L'option "extra_objects" est une liste d'objets fichiers à passer à
l'éditeur de liens. Ces fichiers ne doivent pas avoir d'extensions car
l'extension par défaut du compilateur est utilisée.

"extra_compile_args" et "extra_link_args" peuvent être utilisées pour
définir des options additionnelles en ligne de commande propres aux
lignes de commandes respectives du compilateur et de l'éditeur de
liens.

"export_symbols" est seulement utile sur Windows. Elle peut contenir
une liste de symboles (fonctions ou variables) à exporter. Cette
option n'est pas requise pour la construction d'extensions compilées :
*Distutils* ajoute automatiquement "initmodule" à la liste des
symboles exportés.

L'option "depends" est une liste de fichiers dont les extensions
dépendent (par exemple les fichiers d'en-têtes). La commande "build"
appelle le compilateur sur les sources pour reconstruire l'extension
si un de ces fichiers a été modifié depuis la dernière construction.


2.4. Relations entre distributions et paquets
=============================================

Une distribution peut se rapporter à des paquets de trois manières
spécifiques :

1. elle peut nécessiter des paquets ou des modules ;

2. elle peut fournir des paquets ou des modules ;

3. elle peut rendre obsolète des paquets ou des modules.

Ces relations peuvent être définies en utilisant des paramètres nommés
dans la fonction "distutils.core.setup()".

Les dépendances à d'autres modules et paquets Python peuvent être
définies en fournissant le paramètre nommé "requires" à "setup()". La
valeur doit être une liste de chaînes de caractères. Chaque chaîne de
caractères définit un paquet requis et, en option, les versions
minimales.

S'il n'est pas nécessaire de préciser la version d'un module ou d'un
paquet, la chaîne de caractères contient simplement les noms de
modules ou de paquets. Par exemple "mymodule" et
"'xml.parsers.expat'".

Si des versions spécifiques sont requises, une suite de qualificatifs
peut être fournie entre parenthèses. Chaque qualificatif peut contenir
un opérateur de comparaison et un numéro de version. Les opérateurs de
comparaison acceptés sont :

   <    >    ==
   <=   >=   !=

Ils peuvent être combinés en utilisant plusieurs qualificatifs séparés
par des virgules (et de façon optionnelle, des espaces). Dans ce cas,
tous les qualificatifs doivent être respectés ; un ET logique est
utilisé pour combiner les évaluations.

Jetons un œil à quelques exemples :

+---------------------------+------------------------------------------------+
| Valeur de "requires"      | Explication                                    |
|===========================|================================================|
| "==1.0"                   | Seule la version "1.0" est compatible.         |
+---------------------------+------------------------------------------------+
| ">1.0, !=1.5.1, <2.0"     | Toute version après "1.0" et avant "2.0" est   |
|                           | compatible, à l'exception de "1.5.1".          |
+---------------------------+------------------------------------------------+

Maintenant que nous pouvons définir des dépendances, nous devons
également être en mesure de définir ce que d'autres distributions
peuvent attendre de notre part. Cela est réalisé en utilisant
l'argument nommé *provides* dans "setup()". La valeur de cet argument
est une liste de chaînes de caractères, chacune d'entre elles étant un
module Python ou un paquet et, de façon optionnelle, identifie une
version. Si la version n'est pas définie, il est supposé qu'elle
correspond à celle de la distribution.

Quelques exemples :

+-----------------------+------------------------------------------------+
| Valeur de "provides"  | Explication                                    |
|=======================|================================================|
| "mypkg"               | Fournit "mypkg" en utilisant la version de la  |
|                       | distribution.                                  |
+-----------------------+------------------------------------------------+
| "mypkg (1.1)"         | Fournit "mypkg" en version 1.1, indépendamment |
|                       | de la version de la distribution.              |
+-----------------------+------------------------------------------------+

On peut déclarer d'autres paquets obsolètes dans un paquet en
utilisant l'argument nommé *obsoletes*. La valeur pour celui-ci est
similaire à celui de l'argument nommé *requires* : une liste de
chaînes de caractères donnant les spécifications du module ou du
paquet. Chaque spécification est constituée d'un nom de module ou de
paquet qui peut être suivi au choix par un ou plusieurs qualificateurs
de versions. Les qualificateurs de versions sont donnés entre
parenthèses après le nom de module ou de paquet.

Les versions identifiées par les qualificateurs sont celles qui sont
rendues obsolètes par la distribution décrite. Si aucun qualificateur
n'est donné, toutes les versions du module ou du paquet nommé sont
considérées comme obsolètes.


2.5. Installation des scripts
=============================

Jusqu'à présent nous avons interagi avec des modules Python purs ou
non, qui ne sont habituellement pas lancés par eux-mêmes mais importés
par des scripts.

Les scripts sont des fichiers contenant du code source Python prévus
pour être lancés en ligne de commande. Les scripts n'ont pas besoin
des *Distutils* pour faire quoi que ce soit de très compliqué. La
seule fonctionnalité astucieuse est que la première ligne du script
commence par "#!" et contient le mot « python », les *Distutils*
ajusteront la première ligne pour faire référence à l'emplacement
actuel de l'interpréteur. Par défaut, elle est remplacée par
l'emplacement de l'interpréteur en fonction. L'option "--executable"
(ou "-e") permet de définir explicitement le chemin vers
l'interpréteur.

L'option "scripts" est simplement une liste de fichiers à utiliser de
cette façon. Dans le script "setup.py" de PyML :

   setup(...,
         scripts=['scripts/xmlproc_parse', 'scripts/xmlproc_val']
         )

Modifié dans la version 3.1: Tous les scripts seront aussi ajoutés au
fichier "MANIFEST" si aucun modèle n'est fourni. Voir Spécifier les
fichiers à distribuer.


2.6. Installation de paquets de données
=======================================

Souvent, des fichiers additionnels doivent être installés dans le
paquet. Ces fichiers sont souvent de la donnée qui est intimement liée
à l'implémentation du paquet, ou des fichiers textes contenant de la
documentation intéressant le programmeur utilisant le paquet. Ces
fichiers sont appelés *paquets de données <package data>*.

Les paquets de données peuvent être ajoutés en utilisant l'argument
nommé "package_data" dans la fonction "setup()". La valeur doit être
un tableau de correspondances entre le nom du paquet et une liste de
chemins relatifs à copier dans le paquet. Les chemins sont interprétés
relativement au répertoire contenant le paquet (l'information du
mappage "package_dir" est utilisée le cas échéant) ; ceci étant, il
convient que les fichiers fassent partie du répertoire source du
paquet. Ils peuvent également contenir des motifs *glob*.

Les chemins d'accès peuvent contenir une hiérarchie de répertoires ;
tout répertoire nécessaire sera créé dans cette installation.

Par exemple, si un paquet doit inclure un sous-répertoire avec
plusieurs fichiers de donnée, les fichiers peuvent être organisés dans
l'arborescence de la façon suivante :

   setup.py
   src/
       mypkg/
           __init__.py
           module.py
           data/
               tables.dat
               spoons.dat
               forks.dat

L'appel correspondant à "setup()" peut s'écrire :

   setup(...,
         packages=['mypkg'],
         package_dir={'mypkg': 'src/mypkg'},
         package_data={'mypkg': ['data/*.dat']},
         )

Modifié dans la version 3.1: Tous les fichiers correspondant à
"package_data" seront ajoutés au fichier "MANIFEST" si aucun modèle
n'est fourni. Voir Spécifier les fichiers à distribuer.


2.7. Installation de fichiers additionnels
==========================================

L'option "data_files" peut être utilisée pour définir des fichiers
additionnels requis pour la distribution du module : fichiers de
configuration, catalogues de messages, fichiers de donnée, tout ce qui
ne rentre pas dans les catégories précédentes.

"data_files" définit une séquence de paires (*répertoires*,
*fichiers*) de la façon suivante :

   setup(...,
         data_files=[('bitmaps', ['bm/b1.gif', 'bm/b2.gif']),
                     ('config', ['cfg/data.cfg'])],
        )

Chaque paire (*répertoire*, *fichier*) dans la séquence définit le
répertoire d'installation et les fichiers à y installer.

Chaque nom de fichier dans *fichiers* est interprété relativement au
script "setup.py" à la racine du paquet de la distribution source.
Notez que vous pouvez définir un répertoire où les fichiers de donnée
seront installés, mais vous ne pouvez pas renommer les fichiers de
donnée eux-mêmes.

Le *répertoire* doit être un chemin relatif. Il est interprété
relativement au préfixe d'installation (le "sys.prefix" de Python pour
les installations "système" ; "site.USER_BASE" pour les installations
"utilisateur"). *Distutils* permet à *répertoire* d'être un chemin
d'installation absolu, mais cela est déconseillé dans la mesure où
c'est incompatible avec la mise au format *wheel* du paquet. Aucune
information de répertoire provenant de *fichiers* n'est utilisée pour
déterminer l’emplacement final d'installation du fichier ; seul le nom
du fichier est utilisé.

Vous pouvez définir les options "data_files" comme une simple
succession de fichiers sans définir de répertoire cible, mais cela
n'est pas recommandé, et la commande **install** affichera un message
d'alerte dans ce cas. Pour installer des fichiers de donnée
directement dans le répertoire cible, une chaîne de caractère vide
doit être donnée en tant que répertoire.

Modifié dans la version 3.1: Tous les fichiers correspondant à
"data_files" seront ajoutés au fichier "MANIFEST" si aucun modèle
n'est fourni. Voir Spécifier les fichiers à distribuer.


2.8. Métadonnées additionnelles
===============================

Le script "setup.py" peut inclure des métadonnées additionnelles en
plus du nom et de la version. Cela inclut les informations suivantes :

+------------------------+-----------------------------+-------------------+----------+
| Métadonnées            | Description                 | Valeur            | Notes    |
|========================|=============================|===================|==========|
| "name"                 | nom du paquet               | courte chaîne de  | (1)      |
|                        |                             | caractères        |          |
+------------------------+-----------------------------+-------------------+----------+
| "version"              | version de la publication   | courte chaîne de  | (1)(2)   |
|                        |                             | caractères        |          |
+------------------------+-----------------------------+-------------------+----------+
| "author"               | nom de l'auteur du paquet   | courte chaîne de  | (3)      |
|                        |                             | caractères        |          |
+------------------------+-----------------------------+-------------------+----------+
| "author_email"         | adresse courriel de         | adresse de        | (3)      |
|                        | l'auteur du paquet          | courriel          |          |
+------------------------+-----------------------------+-------------------+----------+
| "maintainer"           | nom du mainteneur du paquet | courte chaîne de  | (3)      |
|                        |                             | caractères        |          |
+------------------------+-----------------------------+-------------------+----------+
| "maintainer_email"     | adresse du courriel du      | adresse de        | (3)      |
|                        | mainteneur du paquet        | courriel          |          |
+------------------------+-----------------------------+-------------------+----------+
| "url"                  | page d’accueil du paquet    | URL               | (1)      |
+------------------------+-----------------------------+-------------------+----------+
| "description"          | bref résumé décrivant le    | courte chaîne de  |          |
|                        | paquet                      | caractères        |          |
+------------------------+-----------------------------+-------------------+----------+
| "long_description"     | description plus complète   | longue chaîne de  | (4)      |
|                        | du paquet                   | caractères        |          |
+------------------------+-----------------------------+-------------------+----------+
| "download_url"         | endroit où le paquet peut   | URL               |          |
|                        | être téléchargé             |                   |          |
+------------------------+-----------------------------+-------------------+----------+
| "classifiers"          | une liste de                | liste de chaînes  | (6)(7)   |
|                        | classificateurs             | de caractères     |          |
+------------------------+-----------------------------+-------------------+----------+
| "platforms"            | une liste de plateformes    | liste de chaînes  | (6)(8)   |
|                        |                             | de caractères     |          |
+------------------------+-----------------------------+-------------------+----------+
| "keywords"             | une liste de mots-clés      | liste de chaînes  | (6)(8)   |
|                        |                             | de caractères     |          |
+------------------------+-----------------------------+-------------------+----------+
| "license"              | licence du paquet           | courte chaîne de  | (5)      |
|                        |                             | caractères        |          |
+------------------------+-----------------------------+-------------------+----------+

Notes :

1. Ces champs sont requis.

2. Il est recommandé que les versions prennent la forme
   *majeure.mineure[.correctif[.sous-correctif]]*.

3. L'auteur ou un mainteneur doit être identifié. Si un mainteneur est
   fourni, *distutils* l'indique en tant qu'auteur dans le fichier
   "PKG-INFO".

4. Le champ "long_description" est utilisé par PyPI quand vous publiez
   un paquet pour construire sa page de projet.

5. Le champ "license" est un texte indiquant la licence du paquet
   quand la licence n'est pas indiquée dans les classificateurs de
   type « Licence » Trove. Voir le champ "Classifier". À noter qu'il y
   a une option de distribution "licence" qui est obsolète mais agit
   toujours comme un alias pour "license".

6. Ce champ doit être une liste.

7. Les classificateurs valides sont listés sur PyPI.

8. Pour préserver la rétrocompatibilité, ce champ accepte aussi une
   chaîne de caractères. Si vous passez une chaine de caractères
   séparée par des virgules "'truc, machin'", elle sera convertie en
   "['truc', 'machin']", Autrement, elle sera convertie en une liste
   d'une chaîne de caractères.

'courte chaîne de caractères'
   Une simple ligne de texte ne dépassant par 200 caractères.

'longue chaîne de caractères'
   De multiples lignes de texte au format ReStructuredText (voir
   http://docutils.sourceforge.net/).

'liste de chaînes de caractères'
   Voir ci-dessous.

Encoder les informations de version est un art en soi. Les paquets
Python adhèrent généralement au format de version
*majeure.mineure[.correctif][sous]*. Le numéro majeur 0 est utilisé
pour les publications expérimentales, initiales d'un logiciel. Il est
incrémenté pour les publications qui représentent des étapes majeures
pour le paquet. Le nombre mineur est incrémenté quand d'importantes
nouvelles fonctionnalités sont ajoutées au paquet. Le numéro de
correctif s'incrémente lors de la publication d'une correction de
bogue est faite. Celles-ci sont "*a1,a2,...,aN*" (pour les
publications alpha, où les fonctionnalités et l'API peut changer),
"*b1,b2,...,bN*" (pour les publications *beta*, qui corrigent
seulement les bogues) et "*pr1,pr2,...,prN*" (pour les ultimes
pré-publication et publications de test). Quelques exemples :

0.1.0
   la première, publication expérimentale du paquet

1.0.1a2
   la seconde publication alpha du premier correctif de la version 1.0

les "classifiers" doivent être définis dans une liste :

   setup(...,
         classifiers=[
             'Development Status :: 4 - Beta',
             'Environment :: Console',
             'Environment :: Web Environment',
             'Intended Audience :: End Users/Desktop',
             'Intended Audience :: Developers',
             'Intended Audience :: System Administrators',
             'License :: OSI Approved :: Python Software Foundation License',
             'Operating System :: MacOS :: MacOS X',
             'Operating System :: Microsoft :: Windows',
             'Operating System :: POSIX',
             'Programming Language :: Python',
             'Topic :: Communications :: Email',
             'Topic :: Office/Business',
             'Topic :: Software Development :: Bug Tracking',
             ],
         )

Modifié dans la version 3.7: "setup" alerte maintenant lorsque les
champs "classifiers", "keywords" ou "platforms" ne sont pas définis en
tant que liste ou chaîne de caractères.


2.9. Débogage du script "setup.py"
==================================

Parfois les choses tournent mal et le script "setup.py" ne fait pas ce
que le développeur veut.

*Distutils* intercepte toute exception lors de l'exécution du script
"setup.py" et affiche un message d'erreur simple avant d'arrêter le
script. L'idée est de ne pas embrouiller les administrateurs qui ne
savent pas grand-chose de Python et qui essayent d'installer un
paquet. S'ils reçoivent une grosse et longue trace d'appels provenant
des entrailles de *Distutils*, ils peuvent penser que le paquet ou que
l'installation de Python est corrompue car, ils ne lisent pas tout
jusqu'en bas alors que c'est un problème de droits.

D'un autre côté, cela n'aide pas le développeur à trouver la cause du
problème. À cette fin, la variable d'environnement "DISTUTILS_DEBUG"
peut être assignée à n'importe quoi sauf une chaîne de caractères
vide, et *distutils* affichera maintenant une information détaillée à
propos de ce qu'il fait, déversera la trace d'appels complète lors
d'une exception, et affichera la ligne de commande complète quand un
programme externe (comme un compilateur C) échoue.
