繁体   English   中英

如何在 setup.py 脚本中包含许可证文件?

[英]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"])]
)

两个评论:

  1. 无需直接向您的产品发送许可证,您可以使用distutils中的许可证元数据来指定此项。

  2. 不要在代码中使用混合的单引号和双引号:)

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文件夹自动。

从 61.0.0 版本开始,您可以改为pyproject.toml文件中指定项目元数据和其他配置选项

使用 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM