“那么如何在setuptools/distutils中传递Requires-External的语法?”
默认情况下没有,因为既有的distutils也不支持该字段。此外,requires_external关键字参数也不受支持 - 它会被静默忽略,就像任何其他未知的关键字参数一样。
要添加对requires_external关键字参数的本地支持,您需要提供自己的分发实现。最小示例(需要Python 3.9):
from setuptools.dist import Distribution as DistributionOrig
class Distribution(DistributionOrig):
_DISTUTILS_UNSUPPORTED_METADATA = DistributionOrig._DISTUTILS_UNSUPPORTED_METADATA | {'requires_external': dict}
现在,当与
distclass
配对时,您可以将
requires_external
传递给
setup()
:
setup(
...,
requires_external=[
'C',
'libpng (>=1.5)',
'make; sys_platform != "win32"',
],
distclass=Distribution,
)
下一个目标是将
requires_external
的内容实际写入
PKG-INFO
。通过发行元数据本身进行此操作相当棘手,因为
setuptools
使用自己的单体实现来修补相关方法(
DistributionMetadata.read_pkg_file()
和
DistributionMetadata.write_pkg_file()
)。我认为最简单的方法是通过自定义的
egg_info
实现事后修改
PKG-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_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())
通过在setup()
中使用cmdclass
参数传递自己的egg_info
实现:
setup(
...,
requires_external=[
'C',
'libpng (>=1.5)',
'make; sys_platform != "win32"',
],
distclass=Distribution,
cmdclass={'egg_info': egg_info},
)
_DISTUTILS_UNSUPPORTED_METADATA
具有下划线前缀。 - platypuspython -c 'from setuptools import setup; setup()' sdist
也会在源分发文件中编写两个PKG-INFO
文件。 - hoeflingDistribution.__init__
方法,从attrs
中读取和验证自定义kwargs,并在元数据中重新分配它们。我只是为了演示目的而采取了捷径。 - hoefling