Python 如何使setuptools忽略subversion资源清册?

Python 如何使setuptools忽略subversion资源清册?,python,packaging,setuptools,egg,Python,Packaging,Setuptools,Egg,使用使用setuptools的setup.py打包Python包时: from setuptools import setup ... 由以下程序创建的源分发: python setup.py sdist 与往常一样,它不仅包括MANIFEST.in中指定的文件,而且还免费包括Subversion列出的所有文件,这些文件在包目录下受版本控制。这是非常恼人的。这不仅使我难以对随包分发的文件进行任何形式的显式控制,而且意味着当我按照“svn导出”而不是“svn签出”构建包时,包的内容可能会大不相

使用使用setuptools的setup.py打包Python包时:

from setuptools import setup
...
由以下程序创建的源分发:

python setup.py sdist
与往常一样,它不仅包括MANIFEST.in中指定的文件,而且还免费包括Subversion列出的所有文件,这些文件在包目录下受版本控制。这是非常恼人的。这不仅使我难以对随包分发的文件进行任何形式的显式控制,而且意味着当我按照“svn导出”而不是“svn签出”构建包时,包的内容可能会大不相同,因为如果没有.svn元数据,setuptools将对要包含的内容做出不同的选择

我的问题:我如何才能关闭这种可怕的行为,使“setuptools”以同样的方式对待我的项目,无论我使用的是Subversion、它从未听说过的版本控制,还是我在项目结束时创建的带有“svn导出”的裸树,以确保它在工作目录之外的某个地方干净地构建

到目前为止,我能做的最好的是一个丑陋的猴子补丁:

from setuptools.command import sdist
del sdist.finders[:]

但这是Python,而不是丛林,所以我当然想要一个更好的解决方案,不涉及任何猴子。我如何通过查看MANIFEST.py中可见的、可预测的规则来驯服setuptools,关闭它的魔力,并让它明智地运行?

答案可能在您的setup.py中。您是否使用find_软件包?此函数默认使用VCS(例如subversion、hg等)。如果您不喜欢它,只需编写一个不同的Python函数,它只收集您想要的东西。

您可能想要这样的东西:

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...
)
import setuptools
setuptools.setup(name='foobar', version='0.1', py_modules=['foobar'])

我知道你知道很多,布兰登,但我会尽我所能给出一个完整的答案(尽管我不是专家),以利于其他人

这里的问题是,setuptools本身涉及很多黑魔法,包括使用一个名为setuptools.file_finders的入口点,您可以在其中添加插件来查找要包含的文件。然而,我完全不知道如何从中删除插件

  • 快速解决方法:svn将包导出到临时目录,然后从那里运行setup.py。这意味着您没有svn,因此svn查找器找不到要包含的文件。:)

  • 更长的解决方法:您真的需要setuptools吗?Setuptools有很多特性,所以答案可能是肯定的,但这些特性主要是depredency(因此您的依赖项可以通过easy_install安装)、名称空间包(foo.bar)和入口点。命名空间包实际上也可以在没有setuptools的情况下创建。但是,如果您不使用这些,那么您实际上可能只使用distutils就可以逃脱惩罚

  • 丑陋的解决方法:在你的问题中,你给sdist的monkeypatch只是使插件没有任何查找程序,并快速退出


正如你们所看到的,这个答案,虽然尽我所能完整,但仍然令人尴尬地不完整。我不能回答你的问题,尽管我认为答案是“你不能”

我认为默认的sdist行为是正确的。当您构建发行版时,我希望它包含签入Subversion的所有内容。当然,在特殊情况下能够完全覆盖它会很好

将sdist与bdist进行比较;我打赌只有明确指定的文件才会被包括在内

我用三个文件做了一个简单的测试,都在svn中。空dummy.lkj和foobar.py,setup.py如下所示:

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...
)
import setuptools
setuptools.setup(name='foobar', version='0.1', py_modules=['foobar'])

sdist创建一个包含dummy.lkj的tarball。bdist_egg创建一个不包含dummy.lkj的egg。

创建一个MANIFEST.in文件,其中包含:

recursive-exclude .
# other MANIFEST.in commands go here
# to explicitly include whatever files you want

有关MANIFEST.in语法的信息,请参阅。

简单解决方案,不要使用setuptools创建源分发,请将该命令降级为distutils:

from distutils.command.sdist import sdist
from setuptools import setup

setup(
    # ... all the usual setup arguments ...
    cmdclass = {'sdist': sdist},
)

事实上,find_包本身只使用listdir,并查找名为
\uuuu init\uuuu.py
的文件!我发布了一个monkeypatch黑客,作为我自己问题的答案。我还没有找到更好的,是的,这对我来说是个错误。我不得不使用递归排除*+1:对于那些投反对票的人,请解释为什么这篇文章是无效的。这种方法似乎很有效。我不知道这个类可以根据命令定制!谢谢你指出这一点。