我用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文件没有定义任何包, 只有一个扩展模块。
我该如何解决这个问题?
答案 0 :(得分:14)
使用data_files
:
setup(
name = "Foo",
version = "0.1.0",
ext_modules = [Extension("Foo", glob("Source/*.cpp"))],
data_files = [("", ["LICENSE.txt"])]
)
两个评论:
无需直接向您的产品发送许可证,您可以使用distutils中的license metadata来指定此项。
请勿在代码中使用混合的单引号和双引号:)
答案 1 :(得分:4)
写一个setup.cfg
文件并在其中指定:
[metadata]
license_file = LICENSE.txt
为了使其工作,似乎需要安装车轮。那就是:
pip install wheel
然后,当通过pip install <path>
安装软件包时,将包含LICENSE文件。
答案 2 :(得分:4)
从 setuptools
42.0.0 开始,您可以使用 license_files
键指定要包含在分发中的许可文件列表。
请注意,由于 implementation details,您实际上不需要将此密钥放入 setup.cfg
文件中(如 documentation 和 another answer 建议的那样)。您可以简单地将其作为参数提供给 setup()
函数:
from setuptools import setup
setup(
...
license_files = ('LICENSE.txt',),
...
)
另请注意,虽然这些文件将包含在二进制(wheel)和源代码发行版中,但它们不会与来自 {{3} 的包一起安装 } 如果用户没有安装 wheel
包,则分发源代码!
为了确保许可证文件将与您的软件包一起安装,您需要对安装脚本进行一些额外的修改:
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},
...
)
如果您的项目是 setup.py
-style 并且您认为它将由 PEP 517 兼容的前端(例如 pip>=19
)安装,则将从您的源强制构建一个轮子,并且许可证文件将是自动安装到 .dist-info
文件夹中。
答案 3 :(得分:2)
使用METADATA.in文件,许可证可以自动包含在源包和轮子中:
METADATA.in
String str=null;
int rng=(int)(Math.random()*NumberOfTheLinesInYourFile);//generate a random number
for(int i =0; i<rng;i++){
str=strReader.readLine();//pick the line at rng variable;
}
System.out.println(srt);
点击此处查看示例: https://github.com/node40/smsh
答案 4 :(得分:1)
新的setuptools(40.x)允许将包括许可证在内的元数据存储在setup.cfg's "metadata" section中。如果您使用旧的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")
)
答案 5 :(得分:-1)
例如:
setup(
...
license="ZPL",
classifiers=[
...
'License :: OSI Approved :: Zope Public License',
...
],
...)
另外,您可以将许可文本插入'long_description':
setup(
...
long_description="Package description. \nLicense Text",
...)
答案 6 :(得分:-1)
您必须将LICENSE.txt文件移动到项目的程序包目录中。它不能位于顶层。 Python目录得到部署,而不是部署工件。如果创建python软件包,则该软件包实际上包含许多子软件包。每个子包都必须包含与部署相关的所有文件。
请勿使用data_files
,因为它实际上会将文件作为单独的软件包分发。 (我听说package_files
有用,但是我还没有看到一个可行的例子来做到这一点。)