跳转到主要内容

zc.buildout下载和提取包的配方

项目描述

该食谱从网络下载软件包并在文件系统中提取它们。它基于gocept.download食谱,并增加了一些额外功能。

支持的Python版本:2.6、2.7、3.2、3.3

支持的zc.buildout版本:1.x、2.x

详细文档

支持的选项

hexagonit.recipe.download食谱可用于从网络下载和提取软件包。它支持以下选项

url

将要下载和提取的软件包的URL。支持的软件包格式包括.tar.gz.tar.bz2.zip。接受任何stdlib zipfiletarfile模块接受的格式(例如 .war.docx文件)。该值必须是完整的URL,例如https://pythonlang.cn/ftp/python/2.4.4/Python-2.4.4.tgz

strip-top-level-dir

切换以从提取的存档中移除顶级目录。这仅当存档恰好有一个顶级目录时才会工作。接受的值是‘true’或‘false’。默认为‘false’。

ignore-existing

切换以忽略现有的文件和/或目录。默认情况下,如果存在与存档中匹配的文件或目录,提取过程将失败。启用此选项将跳过存档中的这些文件/目录。当此食谱被卸载时,忽略的文件/目录将不会被删除。接受的值是‘true’或‘false’。默认为‘false’。

md5sum

软件包文件的MD5校验和。如果可用,将比较下载的软件包的MD5校验和与该值。如果值不匹配,则食谱的执行将失败。

destination

存放提取的软件包内容的目录的路径。如果省略,将在buildout['parts-directory']下创建一个目录,其名称使用该食谱的节名称。如果省略,将在buildout['parts-directory']下创建一个目录。

download-only

当设置为‘true’时,该食谱下载文件而不尝试提取它。这对于下载非tarball文件很有用。如果启用此选项,将忽略strip-top-level-dir选项。默认为false

mode

使用指定的八进制模式设置下载文件的文件模式。此选项仅在download-only设置为true时才有效。自版本1.7.0起引入。

filename

允许在download-only = true时重命名下载的文件。下载的文件将放置在destination目录中,并使用给定的文件名。如果download-only = false,则此选项将被忽略。默认使用原始文件名。自版本1.4.1起引入。

hash-name

当设置为‘true’时,将hash_name=True关键字参数传递给zc.buildout下载实用程序,后者反过来使用MD5哈希来命名下载的文件。有关详细信息,请参阅相应的文档。将参数设置为false将使用原始文件名。默认为true。自版本1.4.0起引入。

excludes

在解包过程中,用于过滤文件和目录的换行符分隔的路径规范列表。路径规范可能包含由 fnmatch.fnmatch 函数实现的 Unix shell 样式通配符。

例如,为了限制下载 Solr 软件包时的磁盘使用量,可以使用以下配置来排除文档和 contrib 目录的解包

excludes =
  apache-solr-*/contrib/*
  apache-solr-*/docs/*

on-update

当设置为 true 时,当 buildout 更新时,配方将重新运行。默认为 false。自版本 1.7.0 以来新增。

配方使用 zc.buildout 的 下载 API 来执行实际下载,这允许对下载过程进行额外的配置。您可以使用 下载缓存 选项可选地缓存下载的文件。

简单示例

>>> import os.path
>>> testdata = join(os.path.dirname(__file__), 'testdata')
>>> server = start_server(testdata)
>>> mkdir(sample_buildout, 'downloads')

在最简单的情况下,我们可以下载一个简单的软件包,并将其提取到 parts 目录中。

>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... newest = false
... parts = package1
...
... [package1]
... recipe = hexagonit.recipe.download
... url = {server}package1-1.2.3-final.tar.gz
... """.format(server=server))

好的,让我们运行 buildout

>>> print(system(buildout))
Installing package1.
Downloading http://test.server/package1-1.2.3-final.tar.gz
package1: Extracting package to /sample-buildout/parts/package1

现在让我们看看 buildout 的 parts 目录。

>>> ls(sample_buildout, 'parts')
d package1

包含目录以我们的部分名称命名。在这个目录内是提取的软件包内容。

>>> ls(sample_buildout, 'parts', 'package1')
d package1-1.2.3-final

软件包包含一个单独的顶级目录。让我们看看里面有什么。

>>> ls(sample_buildout, 'parts', 'package1', 'package1-1.2.3-final')
- CHANGES.txt
- README.txt
d src
>>> rmdir('downloads')

在构建之间共享包

在 buildout 中使用 download-cache 选项允许您在文件系统中中央位置存储下载的软件包。在多个 buildout 中使用相同的 download-cache 位置将有效地在它们之间共享软件包,并减少网络流量和存储需求。

让我们创建一个用作下载缓存的目录。

>>> cache = tmpdir('cache')

并创建一个新的 buildout,相应地设置 buildout-cache 选项。

>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... newest = false
... parts = sharedpackage
... download-cache = {cache}
...
... [sharedpackage]
... recipe = hexagonit.recipe.download
... url = {server}package1-1.2.3-final.tar.gz
... """.format(cache=cache, server=server))

好的,让我们运行 buildout

>>> print(system(buildout))
Uninstalling package1.
Installing sharedpackage.
Downloading http://test.server/package1-1.2.3-final.tar.gz
sharedpackage: Extracting package to /sample-buildout/parts/sharedpackage

我们可以看到,软件包被放置在共享容器下,而不是 buildout 目录下的默认位置。默认情况下,下载的软件包文件名会被哈希处理。

>>> rmdir(cache, 'dist')
>>> ls(cache)
-  dfb1e3136ba092f200be0f9c57cf62ec

通过将 hash-name 参数设置为 false,我们可以保留原始文件名。为了可读性,以下所有示例都将禁用哈希处理。

MD5校验和

可以通过 MD5 校验和验证下载的软件包。这有助于在文件被更改时发现问题。

如果校验和失败,我们将得到一个错误。

>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... newest = false
... parts = package1
...
... [package1]
... recipe = hexagonit.recipe.download
... url = {server}package1-1.2.3-final.tar.gz
... md5sum = invalid
... hash-name = false
... """.format(server=server))
>>> print(system(buildout))
Uninstalling sharedpackage.
Installing package1.
Downloading http://test.server/package1-1.2.3-final.tar.gz
While:
  Installing package1.
Error: MD5 checksum mismatch downloading 'http://test.server/package1-1.2.3-final.tar.gz'

使用有效的校验和允许配方继续执行。

>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... newest = false
... parts = package1
...
... [package1]
... recipe = hexagonit.recipe.download
... url = {server}package1-1.2.3-final.tar.gz
... md5sum = 821ecd681758d3fc03dcf76d3de00412
... hash-name = false
... """.format(server=server))
>>> print(system(buildout))
Installing package1.
Downloading http://test.server/package1-1.2.3-final.tar.gz
package1: Extracting package to /sample-buildout/parts/package1

控制提取过程

我们还可以将存档提取到任何任意位置,并取消顶级目录,这通常是一个有用的功能。

>>> tmpcontainer = tmpdir('otherplace')
>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... newest = false
... parts = package1
...
... [package1]
... recipe = hexagonit.recipe.download
... url = {server}package1-1.2.3-final.tar.gz
... md5sum = 821ecd681758d3fc03dcf76d3de00412
... destination = {dest}
... strip-top-level-dir = true
... hash-name = false
... """.format(server=server, dest=tmpcontainer))

现在重新运行 buildout 给我们

>>> print(system(buildout))
Uninstalling package1.
Installing package1.
Downloading http://test.server/package1-1.2.3-final.tar.gz
package1: Extracting package to /otherplace

查看提取的内容,我们还可以看到顶级目录已被取消。

>>> ls(tmpcontainer)
- CHANGES.txt
- README.txt
d src

部分提取现有内容

默认情况下,如果软件包将被提取的目的地已经包含软件包中也包含的文件或目录,配方将失败。

>>> container = tmpdir('existing')
>>> existingdir = mkdir(container, 'src')
>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... newest = false
... parts = package1
...
... [package1]
... recipe = hexagonit.recipe.download
... url = {server}package1-1.2.3-final.tar.gz
... md5sum = 821ecd681758d3fc03dcf76d3de00412
... destination = {dest}
... strip-top-level-dir = true
... hash-name = false
... """.format(server=server, dest=container))

现在运行 buildout 将失败,因为目的地中已存在 src 目录。

>>> print(system(buildout))
Uninstalling package1.
Installing package1.
Downloading http://test.server/package1-1.2.3-final.tar.gz
package1: Extracting package to /existing
package1: Target /existing/src already exists. Either remove it or set ``ignore-existing = true`` in your buildout.cfg to ignore existing files and directories.
While:
  Installing package1.
Error: File or directory already exists.

设置 ignore-existing 选项将允许配方继续执行。

>>> rmdir(container)
>>> container = tmpdir('existing')
>>> existingdir = mkdir(container, 'src')
>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... newest = false
... parts = package1
...
... [package1]
... recipe = hexagonit.recipe.download
... url = {server}package1-1.2.3-final.tar.gz
... md5sum = 821ecd681758d3fc03dcf76d3de00412
... destination = {dest}
... strip-top-level-dir = true
... ignore-existing = true
... hash-name = false
... """.format(server=server, dest=container))
>>> print(system(buildout))
Installing package1.
Downloading http://test.server/package1-1.2.3-final.tar.gz
package1: Extracting package to /existing
package1: Ignoring existing target: /existing/src
>>> ls(container)
- CHANGES.txt
- README.txt
d src

请注意,当配方被卸载时,被忽略的目标不会被删除,因为它们不是此配方输出的组成部分。我们可以通过在不同的目的地运行 buildout 不同的实例来验证这一点。

>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... newest = false
... parts = package1
...
... [package1]
... recipe = hexagonit.recipe.download
... url = {server}package1-1.2.3-final.tar.gz
... md5sum = 821ecd681758d3fc03dcf76d3de00412
... strip-top-level-dir = true
... ignore-existing = true
... hash-name = false
... """.format(server=server))
>>> print(system(buildout))
Uninstalling package1.
Installing package1.
Downloading http://test.server/package1-1.2.3-final.tar.gz
package1: Extracting package to /sample-buildout/parts/package1

现在当我们查看包含之前 buildout 的目录时,我们可以看到 src 目录仍然存在,但其余文件已消失。

>>> ls(container)
d src

排除包内容

可以从下载包中选择排除某些内容,以防止它们在文件系统中被提取。主要用例是在包包含不必要的文件时节省磁盘空间。

“排除”选项允许多个过滤定义,并支持Unix shell风格的通配符来匹配包内容。匹配使用fnmatch实现,并且以不区分大小写的方式进行。每个过滤定义必须单独一行给出。

以下示例中,我们将排除CHANGES.txt文件以及src目录下及其所有内容。

>>> mkdir(sample_buildout, 'downloads')
>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... newest = false
... parts = package1
... download-cache = downloads
...
... [package1]
... recipe = hexagonit.recipe.download
... url = {server}package1-1.2.3-final.tar.gz
... hash-name = false
... excludes =
...     package1-*/CHANGES.txt
...     package1-*/src*
... """.format(server=server))

运行构建将显示配置排除的文件数量。

>>> print(system(buildout))
Uninstalling package1.
Installing package1.
Downloading http://test.server/package1-1.2.3-final.tar.gz
package1: Excluding 3 file(s) matching the exclusion pattern.
package1: Extracting package to /sample-buildout/parts/package1

使用-vv选项增加构建的详细程度将显示被排除的各个文件。

>>> rmdir('parts', 'package1')
>>> print(system(buildout + ' -vv'))
<BLANKLINE>
...
Uninstalling package1.
...
Installing package1.
Searching cache at /sample-buildout/downloads/
Using cache file /sample-buildout/downloads/package1-1.2.3-final.tar.gz
package1: Excluding package1-1.2.3-final/CHANGES.txt
package1: Excluding package1-1.2.3-final/src
package1: Excluding package1-1.2.3-final/src/foo.txt
package1: Excluding 3 file(s) matching the exclusion pattern.
package1: Extracting package to /sample-buildout/parts/package1

查看解包后的包内容将显示排除的路径不存在。

>>> ls(sample_buildout, 'parts', 'package1', 'package1-1.2.3-final')
- README.txt

离线模式

如果在离线模式下运行构建,如果包在下载目录中缓存,则配方仍然有效。否则,用户将被告知在离线模式下无法下载文件。

>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... newest = false
... parts = package1
... offline = true
... download-cache = downloads
...
... [package1]
... recipe = hexagonit.recipe.download
... url = {server}package1-1.2.3-final.tar.gz
... md5sum = 821ecd681758d3fc03dcf76d3de00412
... strip-top-level-dir = true
... hash-name = false
... """.format(server=server))

让我们验证我们确实在我们的下载目录中有一个缓存副本。

>>> ls(sample_buildout, 'downloads')
d  dist
-  package1-1.2.3-final.tar.gz
>>> print(system(buildout))
Uninstalling package1.
Installing package1.
package1: Extracting package to /sample-buildout/parts/package1

当我们从文件系统中删除文件时,配方将无法工作。

>>> remove(sample_buildout, 'downloads', 'package1-1.2.3-final.tar.gz')
>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... newest = false
... parts = package1
... offline = true
...
... [package1]
... recipe = hexagonit.recipe.download
... url = {server}package1-1.2.3-final.tar.gz
... md5sum = 821ecd681758d3fc03dcf76d3de00412
... hash-name = false
... """.format(server=server))
>>> print(system(buildout))
Uninstalling package1.
Installing package1.
While:
  Installing package1.
Error: Couldn't download 'http://test.server/package1-1.2.3-final.tar.gz' in offline mode.

下载任意文件

当将download-only选项设置为true时,我们可以下载任何文件。这会将文件简单地放置在destination目录中。

>>> empty_download_cache(cache)
>>> downloads = tmpdir('my-downloads')
>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... newest = false
... parts = package
... download-cache = {cache}
...
... [package]
... recipe = hexagonit.recipe.download
... url = {server}package1-1.2.3-final.tar.gz
... md5sum = 821ecd681758d3fc03dcf76d3de00412
... destination = {dest}
... download-only = true
... """.format(server=server, dest=downloads, cache=cache))
>>> print(system(buildout))
Installing package.
Downloading http://test.server/package1-1.2.3-final.tar.gz

查看目标目录,我们可以看到文件已下载但未提取。使用download-only选项对任何类型的文件都适用。

>>> ls(downloads)
-  package1-1.2.3-final.tar.gz

如上所示,使用download-only时,原始文件名将被保留,无论是否使用文件名哈希。然而,缓存副本默认情况下将被哈希。

可以使用filename参数将下载的文件重命名为更好地反映其用途。

>>> empty_download_cache(cache)
>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... newest = false
... parts = package
... download-cache = {cache}
...
... [package]
... recipe = hexagonit.recipe.download
... url = {server}package1-1.2.3-final.tar.gz
... md5sum = 821ecd681758d3fc03dcf76d3de00412
... destination = {dest}
... download-only = true
... filename = renamed-package-1.2.3.tgz
... """.format(server=server, dest=downloads, cache=cache))
>>> print(system(buildout))
Uninstalling package.
Installing package.
Downloading http://test.server/package1-1.2.3-final.tar.gz
>>> ls(downloads)
-  renamed-package-1.2.3.tgz

还可以指定一个模式来设置下载文件的访问权限。这在Unix-like操作系统中相当于chmod shell命令,仅使用八进制模式。

>>> empty_download_cache(cache)
>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... newest = false
... parts = package
... download-cache = {cache}
...
... [package]
... recipe = hexagonit.recipe.download
... url = {server}package1-1.2.3-final.tar.gz
... md5sum = 821ecd681758d3fc03dcf76d3de00412
... destination = {dest}
... download-only = true
... mode = 0654
... """.format(server=server, dest=downloads, cache=cache))
>>> print(system(buildout))
Uninstalling package.
Installing package.
Downloading http://test.server/package1-1.2.3-final.tar.gz
>>> oct(os.stat(os.path.join(downloads, 'package1-1.2.3-final.tar.gz')).st_mode)[-4:]
'0654'

可以使用变量替换filename参数一起使用,以动态生成结果文件名。

>>> empty_download_cache(cache)
>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... newest = false
... parts = package
... download-cache = %(cache)s
... example = foobar-1.2.3
...
... [package]
... recipe = hexagonit.recipe.download
... url = %(server)spackage1-1.2.3-final.tar.gz
... md5sum = 821ecd681758d3fc03dcf76d3de00412
... destination = %(dest)s
... download-only = true
... filename = ${:_buildout_section_name_}-${buildout:example}.tgz
... """ % dict(server=server, dest=downloads, cache=cache))
>>> print(system(buildout))
Uninstalling package.
Installing package.
Downloading http://test.server/package1-1.2.3-final.tar.gz

在此示例中,我们已使用部分名称和[buildout]部分的值来演示动态命名。

>>> ls(downloads)
-  package-foobar-1.2.3.tgz

更新时重新运行安装

on-update标志设置为true将在构建更新时重新运行安装过程。

>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... newest = false
... parts = package
...
... [package]
... recipe = hexagonit.recipe.download
... url = {server}package1-1.2.3-final.tar.gz
... md5sum = 821ecd681758d3fc03dcf76d3de00412
... download-only = true
... on-update = true
... """.format(server=server))
>>> print(system(buildout))
Uninstalling package.
Installing package.
Downloading http://test.server/package1-1.2.3-final.tar.gz
>>> print(system(buildout))
Updating package.
Downloading http://test.server/package1-1.2.3-final.tar.gz

变更历史

1.7.1 (2016-02-13)

  • 当设置ignore-existing时,不要将源复制到目标 #30 [mgrbyte]

  • 修复Python 3.4的utf-8错误 #32 [thefunny42]

1.7 (2013-04-07)

1.6 (2012-11-14)

  • py3k支持 [iElectric]

1.5.1 (2012-07-13)

1.5.0 (2011-01-26)

  • 实现了在解包时排除路径的支持。[fschulze]

  • 恢复到使用 zope.testing.doctest,因为在 Python 2.4 中,使用 stdlib doctest 无法使用 __file__ 变量。[dokai]

  • 修复了一个假测试失败,因为由于随机的文件名哈希,ls() 的结果不可预测。[dokai]

  • 使用 stdlib doctest 模块而不是 zope.testing.doctest。[dokai]

1.4.1 (2010-04-08)

1.4.0 (2010-04-06)

1.3.0 (2009-09-20)

  • 删除了对已弃用的 download-directory 选项的支持。[dokai]

  • 重构了下载逻辑,以使用 zc.buildout 中的下载 API。我们现在需要 zc.buildout >= 1.4.0。[dokai]

1.2.2 (2009-08-17)

  • 合并了来自 Plone Collective Subversion 存储库的当前主干(修订版 79982)。现在,collective 存储库已被弃用,Github 存储库是官方存储库。[dokai]

  • 在计算 MD5 校验和时以二进制模式打开文件。这修复了 Windows 平台上的校验和错误。感谢 Alexander Ivanov 的错误报告和补丁。[dokai]

1.2.1 (2008-04-13)

  • 将 buildout 的 download-directory 选项重命名为 download-cache(这是 buildout 使用的名称)[thefunny]

  • download-directory 选项添加了 BBB 支持。它将发出弃用警告并相应地设置 download-cache 选项。[dokai]

1.2.0 (2008-01-19)

  • 添加了 download-only 选项,允许下载任意文件。[dokai]

1.1.0 (2007-10-14)

  • 重构了安装方法,以便配方子类可以重写基本目录。有关更多信息,请参阅 Recipe 类上的 calculate_base 方法。[hexsprite]

  • 配方现在是新的 Python 类,因此配方子类可以使用 super() 方法获取一些默认行为。[hexsprite]

1.0.1 (2007-08-14)

  • 为了与其他类似的配方保持一致,配方现在设置一个 location 选项,其他部分可以读取该选项以了解包提取的位置。这是 destination 选项的别名。

1.0.0

  • 首次公开发布。

贡献者

  • Kai Lautaportti(dokai),作者 - kai.lautaportti@hexagonit.fi

  • Jordan Baker(hexsprite)- jbb@scryent.com

  • Sylvain Viollon(thefunny)

  • Alexander Ivanov

  • Florian Schulze(fschulze)

  • Cédric de Saint Martin(desaintmartin)

  • Miano Njoka(miano)

  • Domen Kožar(iElectric)

  • Yusuke Tsutsumi(toumorokoshi)

下载

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源分布

hexagonit.recipe.download-1.7.1.tar.gz (25.6 kB 查看哈希值)

上传时间

构建分布

hexagonit.recipe.download-1.7.1-py2-none-any.whl (25.6 kB 查看哈希值)

上传时间 Python 2

支持