为zc.buildout提供的一套辅助食谱
项目描述
文件系统Buildout食谱
创建目录
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = data-dir ... find-links = http://download.zope.org/distribution ... ... [data-dir] ... recipe = lovely.recipe:mkdir ... path = ${buildout:directory}/mystuff ... """) >>> print system(buildout), Installing data-dir. data-dir: Creating directory /sample-buildout/mystuff>>> ls(sample_buildout) - .installed.cfg d bin - buildout.cfg d develop-eggs d eggs d mystuff d parts
如果我们更改目录名,旧目录(“mystuff”)不会被删除。
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = data-dir ... find-links = http://download.zope.org/distribution ... ... [data-dir] ... recipe = lovely.recipe:mkdir ... path = ${buildout:directory}/otherdir ... """) >>> print system(buildout), Uninstalling data-dir. Installing data-dir. data-dir: Creating directory /sample-buildout/otherdir>>> ls(sample_buildout) - .installed.cfg d bin - buildout.cfg d develop-eggs d eggs d mystuff d otherdir d parts
我们还可以创建一个完整路径。
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = data-dir ... find-links = http://download.zope.org/distribution ... ... [data-dir] ... recipe = lovely.recipe:mkdir ... path = ${buildout:directory}/with/subdir ... """) >>> print system(buildout), Uninstalling data-dir. Installing data-dir. data-dir: Cannot create /sample-buildout/with/subdir. /sample-buildout/with is not a directory. While: Installing data-dir. Error: Invalid Path
但我们需要显式激活此功能。
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = data-dir ... find-links = http://download.zope.org/distribution ... ... [data-dir] ... recipe = lovely.recipe:mkdir ... createpath = True ... path = ${buildout:directory}/with/subdir ... """) >>> print system(buildout), Installing data-dir. data-dir: Creating parent directory /sample-buildout/with data-dir: Creating directory /sample-buildout/with/subdir>>> ls(sample_buildout) - .installed.cfg d bin - buildout.cfg d develop-eggs d eggs d mystuff d otherdir d parts d with >>> ls(sample_buildout + '/with') d subdir
没有更新方法,因此在更新时使用安装方法,目录将被重新创建。
>>> rmdir(sample_buildout + '/with') >>> print system(buildout), Updating data-dir. The recipe for data-dir doesn't define an update method. Using its install method. data-dir: Creating parent directory /sample-buildout/with data-dir: Creating directory /sample-buildout/with/subdir
如果我们以root身份运行,可以更改创建的目录的所有者。这在mkdir-root.txt中进行了测试。
如果不是以root身份运行,设置所有者将是一个错误
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = data-dir ... find-links = http://download.zope.org/distribution ... ... [data-dir] ... recipe = lovely.recipe:mkdir ... createpath = True ... path = ${buildout:directory}/another/with/subdir ... owner = nobody ... """) >>> print system(buildout), While: Installing. Getting section data-dir. Initializing part data-dir. Error: Only root can change the owner to nobody.
当用户不存在时是一个错误
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = data-dir ... find-links = http://download.zope.org/distribution ... ... [data-dir] ... recipe = lovely.recipe:mkdir ... createpath = True ... path = ${buildout:directory}/another/with/subdir ... owner = someuser ... """) >>> print system(buildout), While: Installing. Getting section data-dir. Initializing part data-dir. Error: The user someuser does not exist.
创建文件
mkfile配方可以创建一个或多个具有给定路径、内容和权限的文件。
请注意,父目录必须存在,否则会引发用户错误。
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = script ... ... [script] ... recipe = lovely.recipe:mkfile ... path = /x/y/file.sh ... content = hoschi ... mode = 0755 ... """) >>> print system(buildout) Uninstalling data-dir. Installing script. script: Cannot create file /x/y/file.sh. /x/y is not a directory. While: Installing script. Error: Invalid path>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = script ... ... [script] ... recipe = lovely.recipe:mkfile ... path = file.sh ... content = hoschi ... mode = 0755 ... """) >>> print system(buildout) Installing script. script: Writing file /sample-buildout/file.sh <BLANKLINE>>>> ls(sample_buildout) - .installed.cfg d bin - buildout.cfg d develop-eggs d eggs - file.sh d mystuff d otherdir d parts d with
内容将被写入到文件中。
>>> cat(sample_buildout, 'file.sh') hoschi
并设置模式。
>>> import os, stat >>> path = os.path.join(sample_buildout, 'file.sh') >>> oct(stat.S_IMODE(os.stat(path)[stat.ST_MODE])) '0755'
如果我们更改文件名,旧文件将被删除。
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = script ... ... [script] ... recipe = lovely.recipe:mkfile ... path = newfile.sh ... content = hoschi ... mode = 0755 ... """) >>> print system(buildout) Uninstalling script. Installing script. script: Writing file /sample-buildout/newfile.sh <BLANKLINE>>>> ls(sample_buildout) - .installed.cfg d bin - buildout.cfg d develop-eggs d eggs d mystuff - newfile.sh d otherdir d parts d with
我们还可以指定为文件创建路径。
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = script ... ... [script] ... recipe = lovely.recipe:mkfile ... createpath = On ... path = subdir/for/file/file.sh ... content = hoschi ... mode = 0755 ... """) >>> print system(buildout) Uninstalling script. Installing script. script: Creating directory /sample-buildout/subdir/for/file script: Writing file /sample-buildout/subdir/for/file/file.sh>>> ls(sample_buildout + '/subdir/for/file') - file.sh
文件变体
一个常见的用例是具有文件的变体,例如如果需要创建初始化脚本。例如,我们创建两个具有“1”和“2”变体的文件。这些变体可以在文件路径和文件内容中通过正常的字符串格式化符号使用。
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = script ... ... [script] ... recipe = lovely.recipe:mkfile ... variations = 1 2 ... path = prod_%(variation)s.ini ... content = hoschi variation %(variation)s ... mode = 0755 ... """) >>> print system(buildout) Uninstalling script. Installing script. script: Writing file ...sample-buildout/prod_1.ini script: Writing file ...sample-buildout/prod_2.ini>>> cat(sample_buildout, 'prod_1.ini') hoschi variation 1 >>> cat(sample_buildout, 'prod_2.ini') hoschi variation 2
蛋盒构建配方
这个配方是从zc.recipe.egg派生出来的,但它不仅仅创建路径,还为每个顶级命名空间生成目录结构。还可能自动压缩生成的目录,这在Google Appengine环境中特别有用。配方路径选项填充了创建的路径,因此可以由其他可能想要使用该配方的构建部分引用。
>>> import os >>> lovely_recipy_loc = os.path.dirname(os.path.dirname(os.path.dirname( ... os.path.dirname(os.path.dirname(__file__)))))>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... develop = %(loc)s ... parts = packages ... find-links = %(server)s ... index = %(server)s/index ... ... [packages] ... recipe = lovely.recipe:eggbox ... eggs = demo ... lovely.recipe ... interpreter = py ... """ % dict(loc=lovely_recipy_loc, server=link_server))>>> print system(buildout) Develop: '...lovely.recipe' Getting distribution for 'demo'. Got demo 0.4c1. Getting distribution for 'demoneeded'. Got demoneeded 1.2c1. Installing packages. Generated script '...sample-buildout/bin/demo'. Generated interpreter '...sample-buildout/bin/py'.
现在每个顶级目录都有一个zip文件。请注意,zip文件以.egg结尾,以实现pkg_resources兼容性。
>>> ls(sample_buildout + '/parts/packages') - easy_install.py.egg - eggrecipedemo.py.egg - eggrecipedemoneeded.py.egg - lovely.egg - pkg_resources.py.egg - setuptools.egg - zc.egg
生成的解释器现在具有路径中的演示zip文件。
>>> cat(sample_buildout + '/bin/py') #!... sys.path[0:0] = [ '/sample-buildout/parts/packages/easy_install.py.egg', '/sample-buildout/parts/packages/eggrecipedemo.py.egg', '/sample-buildout/parts/packages/eggrecipedemoneeded.py.egg', '/sample-buildout/parts/packages/lovely.egg', '/sample-buildout/parts/packages/pkg_resources.py.egg', '/sample-buildout/parts/packages/setuptools.egg', '/sample-buildout/parts/packages/zc.egg', ]...
可以禁用压缩。还可以排除或包含文件模式。例如,我们可以删除不需要的setuptools egg。我们还可以创建一个脚本。
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... develop = %(loc)s ... parts = packages test ... find-links = %(server)s ... index = %(server)s/index ... ... [packages] ... zip = False ... recipe = lovely.recipe:eggbox ... eggs = demo ... lovely.recipe ... excludes = ^setuptools/.* ... ^easy_install.* ... ^pkg_resources.* ... ... [test] ... recipe = zc.recipe.egg:scripts ... eggs = lovely.recipe ... extra-paths = ${packages:path} ... interpreter = py ... """ % dict(loc=lovely_recipy_loc, server=link_server)) >>> print system(buildout), Develop: '/Users/bd/sandbox/lovely.recipe' Uninstalling packages. Installing packages. Generated script '/sample-buildout/bin/demo'. Installing test. Generated interpreter '/sample-buildout/bin/py'.
请注意,我们仍然与zip版本相同的目录结构,每个顶级命名空间都有一个目录。因为“lovely”目录是一个开发egg,并且我们已将zipped设置为false,所以它只添加到python路径中。
>>> ls(sample_buildout + '/parts/packages') d eggrecipedemo.py d eggrecipedemoneeded.py d zc>>> print system(join(sample_buildout, 'bin', 'py') + \ ... ' -c "import lovely.recipe; print lovely.recipe.__file__"') /.../src/lovely/recipe/__init__.py...
测试部分使用我们的包部分路径。请注意,由于lovely.recipe的开发路径,此路径实际上包含两次,因为脚本配方不检查重复项。
>>> cat(sample_buildout + '/bin/py') #!... sys.path[0:0] = [ '/...lovely.recipe/src', ... '/.../lovely.recipe/src', '/sample-buildout/parts/packages/eggrecipedemo.py', '/sample-buildout/parts/packages/eggrecipedemoneeded.py', '/sample-buildout/parts/packages/zc', ]...
国际化工具配方
此配方允许创建用于提取和合并po文件的国际化工具。
创建工具
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = i18n ... index = http://download.zope.org/zope3.4 ... offline = true ... ... [i18n] ... recipe = lovely.recipe:i18n ... package = lovely.recipe ... domain = recipe ... location = src/somewhere ... output = locales ... maker = z3c.csvvocabulary.csvStrings ... """) >>> print system(buildout), Installing i18n. i18n: setting up i18n tools Generated script 'bin/i18nextract'. Generated script 'bin/i18nmergeall'. Generated script 'bin/i18nstats'.>>> import os >>> ls(os.path.join(sample_buildout, 'bin')) - buildout - i18nextract - i18nmergeall - i18nstats
国际化提取器
>>> cat('bin', 'i18nextract') #!... <BLANKLINE> import sys sys.path[0:0] = [ ... ] <BLANKLINE> import lovely.recipe.i18n.i18nextract <BLANKLINE> if __name__ == '__main__': lovely.recipe.i18n.i18nextract.main(['i18nextract', '-d', 'recipe', '-s', '/sample-buildout/parts/i18n/configure.zcml', '-p', 'src/somewhere', '-o', 'locales', '-m', 'z3c.csvvocabulary.csvStrings'])
我们创建了一个configure.zcml。
>>> cat('parts', 'i18n', 'configure.zcml') <configure xmlns='http://namespaces.zope.org/zope'> <include package="lovely.recipe" /> </configure>
国际化合并
>>> cat('bin', 'i18nmergeall') #!... <BLANKLINE> import sys sys.path[0:0] = [ ... ] <BLANKLINE> import lovely.recipe.i18n.i18nmergeall <BLANKLINE> if __name__ == '__main__': lovely.recipe.i18n.i18nmergeall.main(['i18nmergeall', '-l', 'src/somewhere/locales'])
国际化统计
>>> cat('bin', 'i18nstats') #!... <BLANKLINE> import sys sys.path[0:0] = [ ... ] <BLANKLINE> import lovely.recipe.i18n.i18nstats <BLANKLINE> if __name__ == '__main__': lovely.recipe.i18n.i18nstats.main(['i18nstats', '-l', 'src/somewhere/locales'])
工具名称
创建的工具以部分名称命名。如果配方部分的名称为“translation”,则工具名称为“translationextract”和“translationmergeall”。
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... index = http://download.zope.org/zope3.4 ... parts = translation ... ... offline = true ... ... [translation] ... recipe = lovely.recipe:i18n ... package = lovely.recipe ... domain = recipe ... location = src/somewhere ... output = locales ... maker = z3c.csvvocabulary.csvStrings ... """) >>> print system(buildout), Uninstalling i18n. Installing translation. translation: setting up i18n tools Generated script 'bin/translationextract'. Generated script 'bin/translationmergeall'. Generated script 'bin/translationstats'.
添加自定义configure.zcml
创建的configure.zcml包含包并假定包包含configure.zcml。如果不是这种情况或需要额外的包包含,则可以使用zcml参数来定义生成的configure.zcml的内容。
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = i18n ... ... offline = true ... ... [i18n] ... recipe = lovely.recipe:i18n ... package = lovely.recipe ... domain = recipe ... location = src/somewhere ... output = locales ... maker = z3c.csvvocabulary.csvStrings ... zcml = ... <include package='zope.component' file='meta.zcml' /> ... <include package='lovely.recipe' /> ... ... """)>>> print system(buildout), Uninstalling translation. Installing i18n. i18n: setting up i18n tools Generated script 'bin/i18nextract'. Generated script 'bin/i18nmergeall'. Generated script 'bin/i18nstats'.>>> cat('bin', 'i18nextract') #!... <BLANKLINE> import sys sys.path[0:0] = [ ... ] <BLANKLINE> import lovely.recipe.i18n.i18nextract <BLANKLINE> if __name__ == '__main__': lovely.recipe.i18n.i18nextract.main(['i18nextract', '-d', 'recipe', '-s', '/sample-buildout/parts/i18n/configure.zcml', '-p', 'src/somewhere', '-o', 'locales', '-m', 'z3c.csvvocabulary.csvStrings'])
并且生成的configure-zcml包含我们的额外代码。
>>> cat('parts', 'i18n', 'configure.zcml') <configure xmlns='http://namespaces.zope.org/zope' xmlns:meta="http://namespaces.zope.org/meta" > <BLANKLINE> <BLANKLINE> <include package='zope.component' file='meta.zcml' /> <include package='lovely.recipe' /> <BLANKLINE> </configure>
导入检查器配方
此配方在bin目录中创建一个导入检查器实例。
创建脚本
>>> write(sample_buildout, 'buildout.cfg', ... """ ... [buildout] ... parts = checker ... ... offline = true ... ... [checker] ... recipe = lovely.recipe:importchecker ... path = src/lovely ... """) >>> print system(buildout), Installing checker. checker: setting up importchecker Generated script 'bin/importchecker'.>>> import os >>> ls(os.path.join(sample_buildout, 'bin')) - buildout - importchecker>>> cat('bin', 'importchecker') #!... <BLANKLINE> import sys sys.path[0:0] = [ ... ] <BLANKLINE> import lovely.recipe.importchecker.importchecker <BLANKLINE> if __name__ == '__main__': lovely.recipe.importchecker.importchecker.main(['importchecker', 'src/lovely'])