[英]How to include license file in setup.py script?
我用 C++ 编写了一个 Python 扩展模块。 我计划使用 setuptools 分发模块。 将有 32 位和 64 位 Windows 的二进制分发版(使用setup.py bdist_egg
)和类 UNIX 平台的源代码分发版(使用setup.py sdist
构建)。
我计划在 BSD 许可证下授权该模块。 在我的源代码树中,文件 LICENSE.txt 与 setup.py 一起位于顶部文件夹中。 我应该如何将它包含在安装包中?
我尝试了以下 setup.py 脚本:
from setuptools import setup, Extension
from glob import glob
setup(
name = 'Foo',
version = '0.1.0',
ext_modules = [Extension('Foo', glob('Source/*.cpp'))],
package_data = {'': ['LICENSE.txt']}
)
它不起作用,许可证文件不包含在安装包中。 可能是因为 setup.py 文件没有定义任何包,只有一个扩展模块。
我该如何解决?
编写一个setup.cfg
文件并在其中指定:
[metadata]
license_files = LICENSE.txt
为此,似乎需要安装轮子。 那是:
pip install wheel
如果您已经安装了wheel
并且它不起作用,请尝试更新它:
pip install --upgrade wheel
然后,当通过pip install <path>
安装软件包时,将包含 LICENSE 文件。
使用data_files
:
setup(
name = "Foo",
version = "0.1.0",
ext_modules = [Extension("Foo", glob("Source/*.cpp"))],
data_files = [("", ["LICENSE.txt"])]
)
两个评论:
无需直接向您的产品发送许可证,您可以使用distutils中的许可证元数据来指定此项。
不要在代码中使用混合的单引号和双引号:)
从setuptools
42.0.0 开始,您可以使用license_files
键来指定要包含在分发中的许可证文件列表。 从 56.0.0 版开始,它支持模式匹配,默认为('LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*')
。
请注意,由于实现细节,实际上不需要将此密钥放入setup.cfg
文件中(正如另一个答案所暗示的那样)。 您可以将其作为参数提供给setup()
函数:
(在撰写本文时文档尚不清楚)
from setuptools import setup
setup(
...
license_files = ('LICENSE.txt',),
...
)
另请注意,虽然这些文件将包含在二进制(wheel)和源代码分发中,但如果用户没有安装wheel
包,它们将不会与您的setup.py
风格的源代码分发包一起安装!
为确保许可证文件将与您的软件包一起安装,您需要对安装脚本进行一些额外的修改:
from setuptools import setup
from setuptools.command.egg_info import egg_info
class egg_info_ex(egg_info):
"""Includes license file into `.egg-info` folder."""
def run(self):
# don't duplicate license into `.egg-info` when building a distribution
if not self.distribution.have_run.get('install', True):
# `install` command is in progress, copy license
self.mkpath(self.egg_info)
self.copy_file('LICENSE.txt', self.egg_info)
egg_info.run(self)
setup(
...
license_files = ('LICENSE.txt',),
cmdclass = {'egg_info': egg_info_ex},
...
)
如果您的项目是pyproject.toml
风格的项目,并且您认为它将由 PEP 517 兼容的前端(例如pip>=19
)安装,则会从您的源代码强制构建一个轮子,并且许可证文件将安装到.dist-info
文件夹自动。
使用 METADATA.in 文件,许可证可以自动包含在源包和轮子中:
METADATA.in include README.md include COPYING
在此处查看示例: https ://github.com/node40/smsh
新的 setuptools (40.x) 允许将元数据(包括许可证)存储在setup.cfg 的“元数据”部分中。 如果您使用较旧的 setuptools,您可以使用 setup() 中的“license”命名参数提供许可证:
def read_text(file_name: str):
return open(os.path.join(base_path, file_name)).read()
setup(
name = 'Foo',
version = '0.1.0',
ext_modules = [Extension('Foo', glob('Source/*.cpp'))],
# package_data = {'': ['LICENSE.txt']}
license=read_text("LICENSE.txt")
)
您必须将 LICENSE.txt 文件移动到项目的包目录中。 它不能驻留在顶层。 部署 Python 目录,而不是部署工件。 如果您创建一个 python 包,该包实际上包含许多子包。 每个子包必须包含与部署相关的所有文件。
不要使用data_files
,因为它实际上会将文件作为单独的包分发。 (我听说package_files
有效,但我还没有看到一个可行的例子来做到这一点)。
例如:
setup(
...
license="ZPL",
classifiers=[
...
'License :: OSI Approved :: Zope Public License',
...
],
...)
此外,您可以将许可证文本插入“long_description”:
setup(
...
long_description="Package description. \nLicense Text",
...)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.