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

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.