如何在 Python 包元数据中指定要求

pla*_*pus 6 python distutils metadata setuptools pypi

核心元数据规范记录了元数据字段Requires-External,它似乎用于指定系统(非 python)依赖项。

\n

但你实际上如何指定这个字段呢?这是我尝试过的:

\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 mypackage\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 __init__.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 setup.py\n
Run Code Online (Sandbox Code Playgroud)\n

内容setup.py

\n
from setuptools import setup\n\nsetup(\n    name="mypackage",\n    description="blah blah",\n    url=\'https://example.org\',\n    version="0.1",\n    packages=["mypackage"],\n    requires_external=[\n        "C",\n        "libpng (>=1.5)",\n        \'make; sys_platform != "win32"\',\n    ],\n)\n
Run Code Online (Sandbox Code Playgroud)\n

当我构建此包时,未包含元数据

\n
Metadata-Version: 2.1\nName: mypackage\nVersion: 0.1\nSummary: blah blah\nHome-page: https://example.org\nLicense: UNKNOWN\nPlatform: UNKNOWN\n\nUNKNOWN\n
Run Code Online (Sandbox Code Playgroud)\n

那么将Requires-External传递给 setuptools/distutils 的语法是什么?注意:这个问题不是询问Requires-Dist 元数据。

\n

hoe*_*ing 0

那么将 Requires-External 传递给 setuptools/distutils 的语法是什么?

默认情况下没有,因为既不distutils也不setuptools支持该字段。此外,requires_external也不支持关键字 arg - 它会被默默地忽略,就像任何其他未知关键字 arg 一样。

要添加对requires_externalkwarg 的本地支持,您需要提供自己的发行版实现。最小示例(需要 Python 3.9):

from setuptools.dist import Distribution as DistributionOrig

class Distribution(DistributionOrig):
    _DISTUTILS_UNSUPPORTED_METADATA = DistributionOrig._DISTUTILS_UNSUPPORTED_METADATA | {'requires_external': dict}
Run Code Online (Sandbox Code Playgroud)

现在,您可以在与 配对时传递requires_external到:setup()distclass

setup(
    ...,
    requires_external=[
        'C',
        'libpng (>=1.5)',
        'make; sys_platform != "win32"',
    ],
    distclass=Distribution,
)
Run Code Online (Sandbox Code Playgroud)

requires_external下一个目标是实际写入to的内容PKG-INFO。通过分发元数据本身来做到这一点非常棘手,因为用自己的整体setuptools实现修补相关方法(DistributionMetadata.read_pkg_file()DistributionMetadata.write_pkg_file())。对于这个 IMO,最简单的方法是PKG-INFO通过自定义 impl 修改事后事实egg_info

import email
from pathlib import Path
from setuptools.command.egg_info import egg_info as egg_info_orig


class egg_info(egg_info_orig):
    def run(self):
        super().run()
        # PKG-INFO is now guaranteed to exist
        pkg_info_file = Path(self.egg_info, 'PKG-INFO')
        pkg_info = email.message_from_bytes(pkg_info_file.read_bytes())
        for req in self.distribution.metadata.requires_external:
            pkg_info.add_header('Requires-External', req)
        pkg_info_file.write_bytes(pkg_info.as_bytes())
Run Code Online (Sandbox Code Playgroud)

通过以下参数传递您自己的egg_infoimpl :cmdclasssetup()

setup(
    ...,
    requires_external=[
        'C',
        'libpng (>=1.5)',
        'make; sys_platform != "win32"',
    ],
    distclass=Distribution,
    cmdclass={'egg_info': egg_info},
)
Run Code Online (Sandbox Code Playgroud)