使用使用setuptools的setup.py打包Python包时:
from setuptools import setup
...
由以下人员创建的源代码分发:
python setup.py sdist
不仅像往常一样包含MANIFEST.in中指定的文件,而且无偿地包含Subversion在包目录下列出的所有文件控制文件。这非常烦人。它不仅难以对我的包中分发的文件进行任何形式的显式控制,而且意味着当我按照“svn export”而不是“svn checkout”构建我的包时,我的内容包可能会有很大不同,因为没有.svn元数据setuptools会对包含的内容做出不同的选择。
我的问题:如何关闭这种可怕的行为,以便“setuptools”以同样的方式处理我的项目,无论我使用的是Subversion,还是从未听说过的版本控制,或者使用“svn export”创建的裸树“我在项目结束时创建的,以确保它在我的工作目录之外的某个地方干净地构建?
到目前为止,我所做的最好的是一个丑陋的猴子补丁:
from setuptools.command import sdist
del sdist.finders[:]
但这是Python,而不是丛林,所以当然我想要一个更好的解决方案,根本不涉及猴子。我怎样才能通过查看MANIFEST.py中可见的,可预测的规则来驯服setuptools,关闭它的魔力,让它表现得明智?
答案 0 :(得分:14)
我知道你对此很了解,布兰登,但我会尽力给出一个完整的答案(虽然我不是设置工具),以造福他人。
这里的问题是setuptools本身涉及很多黑魔法,包括使用名为setuptools.file_finders的入口点,你可以在其中添加插件来查找要包含的文件。但是,我完全不知道如何从中插入REMOVE ......
快速解决方法:将svn导出到临时目录并从那里运行setup.py。这意味着你没有svn,所以svn finder找不到要包含的文件。 :)
更长的解决方法:您真的需要setuptools吗? Setuptools有很多功能,所以答案可能是肯定的,但主要是那些功能是depdenencies(因此你的依赖项由easy_install安装),命名空间包(foo.bar)和入口点。实际上也可以在没有setuptools的情况下创建命名空间包。但是,如果你不使用这些,你实际上可能只是使用distutils。
丑陋的解决方法:你在问题中给sdist提供的monkeypatch,它简单地使插件没有任何查找器,并快速退出。
正如你所看到的,这个答案虽然尽我所能,但仍然是令人尴尬的不完整。我实际上无法回答你的问题,但我认为答案是“你做不到”。
答案 1 :(得分:9)
使用以下命令创建MANIFEST.in文件:
recursive-exclude .
# other MANIFEST.in commands go here
# to explicitly include whatever files you want
有关MANIFEST.in语法,请参阅http://docs.python.org/distutils/commandref.html#sdist-cmd。
答案 2 :(得分:1)
答案可能在你的setup.py中。你使用find_packages吗?默认情况下,此函数使用VCS(例如subversion,hg,...)。如果您不喜欢它,只需编写一个不同的Python函数,它只收集您想要的东西。
答案 3 :(得分:1)
简单的解决方案,请勿使用setuptools创建源代码发行版,而将该命令降级为distutils:
from distutils.command.sdist import sdist
from setuptools import setup
setup(
# ... all the usual setup arguments ...
cmdclass = {'sdist': sdist},
)
答案 4 :(得分:0)
我认为默认的sdist行为是正确的。当您构建源分发时,我希望它包含检入Subversion的所有内容。当然,在特殊情况下能够干净地覆盖它会很好。
将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的tarball。 bdist_egg创建一个不包含dummy.lkj的蛋。
答案 5 :(得分:-1)
你可能想要这样的东西:
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...
)