如何在 Python 包元数据中指定要求
How to specify requirements in Python packages metadata
Core metadata specification 记录了元数据字段 Requires-External,它似乎用于指定系统(非 python)依赖项。
你实际上是如何指定这个字段的?这是我试过的:
.
├── mypackage
│ └── __init__.py
└── setup.py
setup.py
的内容
from setuptools import setup
setup(
name="mypackage",
description="blah blah",
url='https://example.org',
version="0.1",
packages=["mypackage"],
requires_external=[
"C",
"libpng (>=1.5)",
'make; sys_platform != "win32"',
],
)
当我构建这个包时,没有包含那个元数据
Metadata-Version: 2.1
Name: mypackage
Version: 0.1
Summary: blah blah
Home-page: https://example.org
License: UNKNOWN
Platform: UNKNOWN
UNKNOWN
那么将 Requires-External 传递给 setuptools/distutils 的语法是什么?注意:这个问题不是询问 Requires-Dist 元数据。
So what is the syntax to pass Requires-External to setuptools/distutils?
默认有none,因为distutils
和setuptools
都不支持该字段。此外,requires_external
关键字 arg 也不受支持 - 它会被静默忽略,就像任何其他未知关键字 arg 一样。
要添加对 requires_external
kwarg 的本地支持,您需要提供自己的分发实现。最小示例(需要 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()
)。这个 IMO 最简单的方法是通过自定义 egg_info
impl:
修改 PKG-INFO
post factum
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())
通过 setup()
中的 cmdclass
参数传递您自己的 egg_info
impl:
setup(
...,
requires_external=[
'C',
'libpng (>=1.5)',
'make; sys_platform != "win32"',
],
distclass=Distribution,
cmdclass={'egg_info': egg_info},
)
Core metadata specification 记录了元数据字段 Requires-External,它似乎用于指定系统(非 python)依赖项。
你实际上是如何指定这个字段的?这是我试过的:
.
├── mypackage
│ └── __init__.py
└── setup.py
setup.py
from setuptools import setup
setup(
name="mypackage",
description="blah blah",
url='https://example.org',
version="0.1",
packages=["mypackage"],
requires_external=[
"C",
"libpng (>=1.5)",
'make; sys_platform != "win32"',
],
)
当我构建这个包时,没有包含那个元数据
Metadata-Version: 2.1
Name: mypackage
Version: 0.1
Summary: blah blah
Home-page: https://example.org
License: UNKNOWN
Platform: UNKNOWN
UNKNOWN
那么将 Requires-External 传递给 setuptools/distutils 的语法是什么?注意:这个问题不是询问 Requires-Dist 元数据。
So what is the syntax to pass Requires-External to setuptools/distutils?
默认有none,因为distutils
和setuptools
都不支持该字段。此外,requires_external
关键字 arg 也不受支持 - 它会被静默忽略,就像任何其他未知关键字 arg 一样。
要添加对 requires_external
kwarg 的本地支持,您需要提供自己的分发实现。最小示例(需要 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()
)。这个 IMO 最简单的方法是通过自定义 egg_info
impl:
PKG-INFO
post factum
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())
通过 setup()
中的 cmdclass
参数传递您自己的 egg_info
impl:
setup(
...,
requires_external=[
'C',
'libpng (>=1.5)',
'make; sys_platform != "win32"',
],
distclass=Distribution,
cmdclass={'egg_info': egg_info},
)