如何让 setuptools 忽略 subversion inventory?
-
13-09-2019 - |
题
当使用 setuptools 的 setup.py 打包 Python 包时:
from setuptools import setup
...
由以下人员创建的源发行版:
python setup.py sdist
像往常一样,它不仅包括 MANIFEST.in 中指定的文件,而且还无偿地包括 Subversion 在包目录下列出的受版本控制的所有文件。这非常烦人。这不仅使得对随我的包分发哪些文件进行任何类型的显式控制变得困难,而且这意味着当我按照“svn导出”而不是“svn签出”构建我的包时,我的包的内容包可能会完全不同,因为如果没有 .svn 元数据,安装工具将对要包含的内容做出不同的选择。
我的问题:我怎样才能关闭这种可怕的行为,以便“setuptools”以同样的方式对待我的项目,无论我使用的是Subversion,还是从未听说过的版本控制,或者是使用我创建的“svn导出”创建的裸树在我的项目结束时以确保它在我的工作目录之外的某个地方干净地构建?
到目前为止我做得最好的是一个丑陋的猴子补丁:
from setuptools.command import sdist
del sdist.finders[:]
但这是Python,而不是丛林,所以我当然想要一个完全不涉及猴子的更好的解决方案。我怎样才能驯服 setuptools,关闭它的魔力,并通过查看 MANIFEST.py 中可见的、可预测的规则来让它明智地运行?
解决方案
我知道你对此了解很多,布兰登,但为了其他人的利益,我会尽力给出完整的答案(尽管我不是安装工具专家)。
这里的问题是 setuptools 本身涉及相当多的黑魔法,包括使用名为 setuptools.file_finders 的入口点,您可以在其中添加插件来查找要包含的文件。然而,我完全不知道如何从中删除插件......
快速解决方法:svn 将包导出到临时目录并从那里运行 setup.py 。这意味着您没有 svn,因此 svn finder 找不到要包含的文件。:)
更长的解决方法:您真的需要安装工具吗?setuptools 有很多功能,所以答案可能是肯定的,但这些功能主要是依赖项(因此您的依赖项通过 easy_install 安装)、命名空间包 (foo.bar) 和入口点。实际上也可以在没有 setuptools 的情况下创建命名空间包。但如果你不使用这些,你实际上可能只使用 distutils 就可以逃脱惩罚。
丑陋的解决方法:您在问题中给 sdist 的 Monkeypatch,这只会使插件没有任何查找器,并快速退出。
所以正如你所看到的,这个答案虽然我能做到的尽可能完整,但仍然是令人尴尬的不完整。我实际上无法回答你的问题,尽管我认为答案是“你不能”。
其他提示
创建具有MANIFEST.in文件:
recursive-exclude .
# other MANIFEST.in commands go here
# to explicitly include whatever files you want
请参阅 http://docs.python.org/distutils/commandref.html #sdist-CMD ,在MANIFEST.in语法。
也许答案就在你的setup.py。你使用find_packages?该功能默认使用VCS(例如颠覆,HG,...)。如果你不喜欢它,只写其中仅收集你想要的东西不同的Python功能。
我认为,默认sdist行为是正确的。当你正在建设一个来源分布,我希望它包含的所有已签入颠覆。当然,这将是很好能够在特殊情况下干净地覆盖它。
比较sdist到bdist_egg;我敢打赌,只有那些明确规定得到包含的文件。
我做了一个简单的测试有三个文件,所有在SVN。空dummy.lkj和foobar.py并用setup.py看起来像这样:
import setuptools
setuptools.setup(name='foobar', version='0.1', py_modules=['foobar'])
sdist创建包括dummy.lkj压缩包。 bdist_egg创建一个鸡蛋不包括dummy.lkj。
您可能想是这样的:
from distutils.core import setup
def packages():
import os
packages = []
for path, dirs, files in os.walk("yourprogram"):
if ".svn" in dirs:
dirs.remove(".svn")
if "__init__.py" in files:
packages.append(path.replace(os.sep, "."))
return packages
setup(
# name, version, description, etc...
packages = packages(),
# pacakge_data, data_files, etc...
)