How to specify multiple author(s) / email(s) in setup.py

前端 未结 2 874
自闭症患者
自闭症患者 2021-01-31 01:19

We wrote a small wrapper to a twitter app and published this information to http://pypi.python.org. But setup.py just contained a single field for specifying email / name of the

相关标签:
2条回答
  • 2021-01-31 01:33

    As far as I know, setuptools doesn't support using a list of strings in order to specify multiple authors. Your best bet is to list the authors in a single string:

    author='Foo Bar, Spam Eggs',
    author_email='foobar@baz.com, spameggs@joe.org',
    

    I'm not sure if PyPI validates the author_email field, so you may run into trouble with that one. In any case, I would recommend you limit these to a single author and mention all contributors in the documentation or description.

    [Edit] Some sources:

    This has been registered as a bug, actually, but it seems like support for multiple authors was not implemented. Here is an alternative solution. Here is an idea for how to provide a contact email for a project with multiple authors.

    0 讨论(0)
  • 2021-01-31 01:42

    I'm sort of just piggybacking off of @modocache's answer, in case you want some specifics.

    Throughout this answer, I'll be refering to a python3.6 version of the FOO-PYTHON-ENV\Lib\distutils\dist.py file

    To reiterate, you cannot use a list in the author field. Here's why:

    Spoiler: Two methods belonging to the DistributionMetadata class are the reason --

    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
    

    Here's where you'll hit an error if you try to stick a list in the author field:

    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)...*#
    

    & Here's the whole thing:

    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
    
    0 讨论(0)
提交回复
热议问题