web-dev-qa-db-fra.com

Comment spécifier plusieurs auteur (s) / e-mail (s) dans setup.py

Nous avons écrit un petit wrapper pour une application Twitter et publié ces informations à http://pypi.python.org . Mais setup.py contenait juste un seul champ pour spécifier l'email/le nom de l'auteur. Comment puis-je spécifier plusieurs contributeurs/liste de diffusion, dans les champs suivants, car nous aimerions que ce package soit répertorié sous nos noms, très similaire à la façon dont il apparaît dans http://rubygems.org .

   author='foo',
   author_email='[email protected]',
67
priya

Pour autant que je sache, setuptools ne prend pas en charge l'utilisation d'une liste de chaînes afin de spécifier plusieurs auteurs. Votre meilleur pari est de répertorier les auteurs dans une seule chaîne:

author='Foo Bar, Spam Eggs',
author_email='[email protected], [email protected]',

Je ne sais pas si PyPI valide le author_email, vous pouvez donc rencontrer des problèmes avec celui-ci. Dans tous les cas, je vous recommande de les limiter à un seul auteur et de mentionner tous les contributeurs dans la documentation ou la description.

[Modifier] Quelques sources:

Cela a été enregistré en tant que bogue , en fait, mais il semble que la prise en charge de plusieurs auteurs n'ait pas été implémentée. Ici est une solution alternative. Ici est une idée sur la façon de fournir un e-mail de contact pour un projet avec plusieurs auteurs.

67
modocache

Je suis en quelque sorte en train de me greffer sur la réponse de @ modocache, au cas où vous voudriez des détails.

Tout au long de cette réponse, je ferai référence à une version python3.6 du FOO-PYTHON-ENV\Lib\distutils\dist.py fichier

Pour réitérer, vous ne pouvez pas utiliser une liste dans le champ author. Voici pourquoi:

Spoiler: Deux méthodes appartenant à la classe DistributionMetadata sont la raison -

def _read_field(name):
    value = msg[name]
    if value == 'UNKNOWN':
        return None
    return value

def _read_list(name):
    values = msg.get_all(name, None)
    if values == []:
        return None
    return values

Voici où vous rencontrerez une erreur si vous essayez de coller une liste dans le champ author:

class DistributionMetadata:

#*...(R E D A C T E D)...*#

    def read_pkg_file(self, file):
        """Reads the metadata values from a file object."""
    #*...(R E D A C T E D)...*#
        # ####################################
        # Note the usage of _read_field() here
        # ####################################
        self.name = _read_field('name')
        self.version = _read_field('version')
        self.description = _read_field('summary')
        # we are filling author only.
        self.author = _read_field('author')
        self.maintainer = None
        self.author_email = _read_field('author-email')
        self.maintainer_email = None
        self.url = _read_field('home-page')
        self.license = _read_field('license')
    #*...(R E D A C T E D)...*#
        # ###################################
        # Note the usage of _read_list() here
        # ###################################
        self.platforms = _read_list('platform')
        self.classifiers = _read_list('classifier')
    #*...(R E D A C T E D)...*#

& Voici le tout:

class DistributionMetadata:
        """Dummy class to hold the distribution meta-data: name, version,
        author, and so forth.
        """

        _METHOD_BASENAMES = ("name", "version", "author", "author_email",
                     "maintainer", "maintainer_email", "url",
                     "license", "description", "long_description",
                     "keywords", "platforms", "fullname", "contact",
                     "contact_email", "classifiers", "download_url",
                     # PEP 314
                     "provides", "requires", "obsoletes",
                     )

    def __init__(self, path=None):
        if path is not None:
            self.read_pkg_file(open(path))
        else:
            self.name = None
            self.version = None
            self.author = None
            self.author_email = None
            self.maintainer = None
            self.maintainer_email = None
            self.url = None
            self.license = None
            self.description = None
            self.long_description = None
            self.keywords = None
            self.platforms = None
            self.classifiers = None
            self.download_url = None
            # PEP 314
            self.provides = None
            self.requires = None
            self.obsoletes = None

    def read_pkg_file(self, file):
        """Reads the metadata values from a file object."""
        msg = message_from_file(file)

        def _read_field(name):
            value = msg[name]
            if value == 'UNKNOWN':
                return None
            return value

        def _read_list(name):
            values = msg.get_all(name, None)
            if values == []:
                return None
            return values

        metadata_version = msg['metadata-version']
        self.name = _read_field('name')
        self.version = _read_field('version')
        self.description = _read_field('summary')
        # we are filling author only.
        self.author = _read_field('author')
        self.maintainer = None
        self.author_email = _read_field('author-email')
        self.maintainer_email = None
        self.url = _read_field('home-page')
        self.license = _read_field('license')

        if 'download-url' in msg:
            self.download_url = _read_field('download-url')
        else:
            self.download_url = None

        self.long_description = _read_field('description')
        self.description = _read_field('summary')

        if 'keywords' in msg:
            self.keywords = _read_field('keywords').split(',')

        self.platforms = _read_list('platform')
        self.classifiers = _read_list('classifier')

        # PEP 314 - these fields only exist in 1.1
        if metadata_version == '1.1':
            self.requires = _read_list('requires')
            self.provides = _read_list('provides')
            self.obsoletes = _read_list('obsoletes')
        else:
            self.requires = None
            self.provides = None
            self.obsoletes = None
1
Rob Truxal