ZC Buildout配方,用于定义Zope 3应用程序
项目描述
创建具有独特特征的Zope 3实例的配方
不要使用骨架
分离应用程序和实例定义
不支持包包含
支持离线实例。
遗憾的是,目前仅部分支持Windows。曾经在某些时候工作过,但现在处于alpha版本,并未正式支持。欢迎志愿者加入!
版本
1.0 (2023-03-01)
添加对Python 3.9、3.10、3.11的支持。
放弃对Python 2.7、3.5、3.6的支持。
由于维护者兴趣不足,放弃对Windows的支持。
0.20.0 (2021-04-16)
添加对Python 3.8的支持。
修复了在由debugzope.py调用的脚本内部使用调试器的问题。
0.19.0 (2019-07-12)
修复了在Windows上zdaemon >= 3.0.0时出现的TypeError: <lambda>()不接受任何参数(给出了1个)。
支持Python 3.5至3.7。
0.18.0 (2013/02/05)
对于离线配方,检查有效UID而不是实际UID。
使测试通过现代buildout,包括buildout 2。
0.17.0 (2012/02/07)
在zopeconf食谱中添加了“位置”值作为输出,使其更容易替代zc.recipe.deployment:configuration使用。
0.16.0 (2012/01/15)
增加了使用Paste Deployment来指定基于zope.app的应用程序的WSGI栈的支持。
0.15.0 (2011/12/12)
添加了zopeconf食谱以生成格式良好的zope.conf文件,而不构建实例。
0.14.1 (2011/12/08)
修复了pypi页面的ReST。
0.14.0 (2011/12/08)
在zc.zope3recipes.debugzope用户将交互的环境中执行$PYTHONSTARTUP;这反映了交互式解释器中$PYTHONSTARTUP的使用方式。
添加了离线实例的食谱。
修复了测试,使其通过zc.buildout >= v1.5。
0.13.0 (2010/11/24)
通过使用initialization和debug-initialization,支持在runzope & debugzope脚本中插入额外的代码。
0.12.0 (2010/11/22)
提供了生成日志轮转配置的控制,包括在不需要时禁用它的能力。
0.11.1 (2010/11/12)
添加了一个环境钩子来启用debugzope的日志记录。
0.11.0 (2009/10/01)
添加了对相对路径buildout选项的支持和测试。
由于相对路径在这些版本中添加,因此将依赖性要求更改为>=1.2.0的zc.buildout和zc.recipe.egg。
为上一个版本(0.10.0)添加了缺失的发布日期。
0.10.0 (2009/09/16)
由于无法使用ZDaemons reopen_transacript重新打开日志,因此移除了对创建access.log的logrotate脚本的支持。然而,可以在日志文件部分声明何时以及如何轮转日志文件内部。
0.9.0 (2009/07/21)
更新测试以与最新软件包版本兼容。
0.8.0 (2009/04/03)
在setUp中添加了“newest=false”选项,以防止测试期间升级。
在部署食谱中使用时,添加了对创建logrotate脚本的支持。
0.7.0 (2008/02/01)
在生成实例文件名时,如果存在,则使用部署名称选项(由zc.recipe.deployment 0.6.0及以后版本提供)。
现在可以指定实例名称选项,以覆盖生成的文件的部分名称。
0.6.1 (2007/12/17)
修复了bug:无法覆盖zope.conf的site-definition选项。
0.6.0 (2007/11/03)
这是带有Windows支持的最终发布版本。
0.6b1 (2007/08/21)
添加了Windows支持。
0.5.5 (2007/07/26)
现在debugzope会考虑应用程序的服务器键。
0.5.3 (2007/07/14)
创建了一个名为“application”的另一个食谱,它仅从eggs安装Zope 3。‘app’食谱是一个扩展,它还支持从checkout或tarball安装Zope 3。
0.5.2 (2007/06/21)
使用ZConfig的schema-free配置解析功能以支持%import。
0.5.1 (2007/05/22)
支持ZConfig部分中的重复键。
0.5.0 (2007/03/21)
支持仅从eggs构建Zope 3应用程序。
详细文档
Zope 3食谱允许定义Zope应用程序及其应用程序的实例。Zope应用程序是一组软件和软件配置,以ZCML的形式表达。Zope实例使用特定的实例配置调用应用程序。单个应用程序可以有多个实例。
构建Zope 3应用程序(来自eggs)
“application”食谱可以用于定义Zope应用程序。它设计为仅与Zope从eggs一起使用。app食谱会导致创建一个部分。该部分将包含runzope和debugzope脚本以及应用程序的site.zcml。这两个脚本在运行时都需要提供-C选项和zope.conf文件的路径。debugzope脚本可以与脚本名称和参数一起运行,在这种情况下,它将运行该脚本而不是启动交互式会话。
“application”食谱接受以下选项
- site.zcml
site.zcml的内容。
- eggs
一个或多个eggs的名称,包括应包含在生成脚本Python路径中的依赖项。
让我们定义一些(伪造的)eggs,我们可以在应用程序中使用
>>> mkdir('demo1') >>> write('demo1', 'setup.py', ... ''' ... from setuptools import setup ... setup(name = 'demo1') ... ''')>>> mkdir('demo2') >>> write('demo2', 'setup.py', ... ''' ... from setuptools import setup ... setup(name = 'demo2', install_requires='demo1') ... ''')
我们将创建一个buildout.cfg文件来定义我们的应用程序
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = myapp ... ... [myapp] ... recipe = zc.zope3recipes:application ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ''' % globals())
现在,让我们运行buildout并看看我们会得到什么
>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Installing myapp. Generated script '/sample-buildout/parts/myapp/runzope'. Generated script '/sample-buildout/parts/myapp/debugzope'.
runzope脚本运行Web服务器
>>> cat('parts', 'myapp', 'runzope') #!/usr/local/bin/python2.4 <BLANKLINE> import sys sys.path[0:0] = [ '/sample-buildout/demo2', '/sample-buildout/demo1', ] <BLANKLINE> import zope.app.twisted.main <BLANKLINE> if __name__ == '__main__': sys.exit(zope.app.twisted.main.main())
在这里,与上面的示例不同,位置路径不包括在sys.path中。同样,debugzope脚本也发生了变化
>>> cat('parts', 'myapp', 'debugzope') #!/usr/local/bin/python2.4 <BLANKLINE> import sys sys.path[0:0] = [ '/sample-buildout/demo2', '/sample-buildout/demo1', '/site-packages', ] <BLANKLINE> import zope.app.twisted.main <BLANKLINE> <BLANKLINE> import zc.zope3recipes.debugzope <BLANKLINE> if __name__ == '__main__': sys.exit(zc.zope3recipes.debugzope.debug(main_module=zope.app.twisted.main))
初始化设置可以用来提供一段代码,这段代码将在调用服务器主函数之前被包含在runzope和debugzope脚本中
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = myapp ... ... [myapp] ... recipe = zc.zope3recipes:application ... site.zcml = <include package="demo2" /> ... eggs = demo2 ... initialization = ... print("Starting application server.") ... ''')
现在,让我们运行buildout并看看我们会得到什么
>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling myapp. Installing myapp. Generated script '/sample-buildout/parts/myapp/runzope'. Generated script '/sample-buildout/parts/myapp/debugzope'.
runzope和debugzope脚本现在在服务器启动之前包含了额外的代码
>>> cat('parts', 'myapp', 'runzope') #!/usr/local/bin/python2.4 <BLANKLINE> import sys sys.path[0:0] = [ '/sample-buildout/demo2', '/sample-buildout/demo1', ] <BLANKLINE> print("Starting application server.") <BLANKLINE> import zope.app.twisted.main <BLANKLINE> if __name__ == '__main__': sys.exit(zope.app.twisted.main.main())>>> cat('parts', 'myapp', 'debugzope') #!/usr/local/bin/python2.4 <BLANKLINE> import sys sys.path[0:0] = [ '/sample-buildout/demo2', '/sample-buildout/demo1', '/site-packages', ] <BLANKLINE> print("Starting application server.") import zope.app.twisted.main <BLANKLINE> <BLANKLINE> import zc.zope3recipes.debugzope <BLANKLINE> if __name__ == '__main__': sys.exit(zc.zope3recipes.debugzope.debug(main_module=zope.app.twisted.main))
如果需要对debugzope的额外初始化与runzope不同,可以使用debug-initialization设置。如果设置了该值,则用于debugzope而不是initialization的值。
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = myapp ... ... [myapp] ... recipe = zc.zope3recipes:application ... site.zcml = <include package="demo2" /> ... eggs = demo2 ... initialization = ... print("Starting application server.") ... debug-initialization = ... print("Starting debugging interaction.") ... ''')
现在,让我们运行buildout并看看我们会得到什么
>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling myapp. Installing myapp. Generated script '/sample-buildout/parts/myapp/runzope'. Generated script '/sample-buildout/parts/myapp/debugzope'.>>> cat('parts', 'myapp', 'debugzope') #!/usr/local/bin/python2.4 <BLANKLINE> import sys sys.path[0:0] = [ '/sample-buildout/demo2', '/sample-buildout/demo1', '/site-packages', ] <BLANKLINE> print("Starting debugging interaction.") import zope.app.twisted.main <BLANKLINE> <BLANKLINE> import zc.zope3recipes.debugzope <BLANKLINE> if __name__ == '__main__': sys.exit(zc.zope3recipes.debugzope.debug(main_module=zope.app.twisted.main))
runzope脚本仍然使用initialization设置
>>> cat('parts', 'myapp', 'runzope') #!/usr/local/bin/python2.4 <BLANKLINE> import sys sys.path[0:0] = [ '/sample-buildout/demo2', '/sample-buildout/demo1', ] <BLANKLINE> print("Starting application server.") <BLANKLINE> import zope.app.twisted.main <BLANKLINE> if __name__ == '__main__': sys.exit(zope.app.twisted.main.main())
将debug-initialization设置为空字符串将抑制debugzope脚本的initialization设置
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = myapp ... ... [myapp] ... recipe = zc.zope3recipes:application ... site.zcml = <include package="demo2" /> ... eggs = demo2 ... initialization = ... print("Starting application server.") ... debug-initialization = ... ''')
现在,让我们运行buildout并看看我们会得到什么
>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling myapp. Installing myapp. Generated script '/sample-buildout/parts/myapp/runzope'. Generated script '/sample-buildout/parts/myapp/debugzope'.>>> cat('parts', 'myapp', 'debugzope') #!/usr/local/bin/python2.4 <BLANKLINE> import sys sys.path[0:0] = [ '/sample-buildout/demo2', '/sample-buildout/demo1', '/site-packages', ] <BLANKLINE> import zope.app.twisted.main <BLANKLINE> <BLANKLINE> import zc.zope3recipes.debugzope <BLANKLINE> if __name__ == '__main__': sys.exit(zc.zope3recipes.debugzope.debug(main_module=zope.app.twisted.main))
相对路径
如果构建配置中请求,则脚本将使用相对路径而不是绝对路径生成。
让我们修改一个构建配置以包含relative-paths。
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = myapp ... relative-paths = true ... ... [myapp] ... recipe = zc.zope3recipes:application ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling myapp. Installing myapp. Generated script '/sample-buildout/parts/myapp/runzope'. Generated script '/sample-buildout/parts/myapp/debugzope'.
我们得到具有相对路径的runzope脚本。
>>> cat('parts', 'myapp', 'runzope') #!/usr/local/bin/python2.4 <BLANKLINE> import os <BLANKLINE> join = os.path.join base = os.path.dirname(os.path.abspath(os.path.realpath(__file__))) base = os.path.dirname(base) base = os.path.dirname(base) <BLANKLINE> import sys sys.path[0:0] = [ join(base, 'demo2'), join(base, 'demo1'), ] <BLANKLINE> import zope.app.twisted.main <BLANKLINE> if __name__ == '__main__': sys.exit(zope.app.twisted.main.main())
类似地,debugzope脚本也有相对路径。
>>> cat('parts', 'myapp', 'debugzope') #!/usr/local/bin/python2.4 <BLANKLINE> import os <BLANKLINE> join = os.path.join base = os.path.dirname(os.path.abspath(os.path.realpath(__file__))) base = os.path.dirname(base) base = os.path.dirname(base) <BLANKLINE> import sys sys.path[0:0] = [ join(base, 'demo2'), join(base, 'demo1'), '/site-packages', ] <BLANKLINE> import zope.app.twisted.main <BLANKLINE> <BLANKLINE> import zc.zope3recipes.debugzope <BLANKLINE> if __name__ == '__main__': sys.exit(zc.zope3recipes.debugzope.debug(main_module=zope.app.twisted.main))
构建Zope 3应用程序(来自Zope 3 checkouts/tarballs)
“app”配方的工作方式与“application”配方非常相似。它接受相同的配置选项,以及以下选项
- zope3
定义位置选项的节名称,该位置选项给出Zope安装的位置。这可以是检出或分发。如果位置有lib/python子目录,则被视为分发,否则,它必须有src子目录,并将被视为检出。此选项默认为“zope3”。如果位置为空,则应用程序将仅从egg运行。
让我们看一个例子。我们将创建一个模拟的zope安装
>>> zope3 = tmpdir('zope3') >>> mkdir(zope3, 'src')
现在我们将创建一个buildout.cfg文件来定义我们的应用程序
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = myapp ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ''' % globals())
注意,我们的site.zcml文件非常小。它期望应用程序zcml定义几乎所有内容。事实上,site.zcml文件通常只包含一个包含指令。我们不需要包含周围的配置元素,除非我们想要一个除zope命名空间以外的命名空间。一个配置指令将为我们包含。
让我们运行构建并看看我们得到什么
>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling myapp. Installing myapp. Generated script '/sample-buildout/parts/myapp/runzope'. Generated script '/sample-buildout/parts/myapp/debugzope'.
在部件目录中为我们的应用程序文件创建了一个目录。从zc.buildout >= v1.5和distribute开始,在部件文件夹中创建了一个“buildout”目录。由于我们支持的zc.buildout最低版本低于v1.5,我们使用一个自定义的“ls”功能称为“ls_optional”,我们将可能存在的文件夹列表传递给它。这些被函数忽略。
>>> from zc.zope3recipes.tests import ls_optional >>> ls_optional('parts', ignore=('buildout',)) d myapp>>> ls('parts', 'myapp') - debugzope - runzope - site.zcml
我们得到3个文件,两个脚本和一个site.zcml文件。site.zcml文件只是我们在构建配置中有的
>>> cat('parts', 'myapp', 'site.zcml') <configure xmlns='http://namespaces.zope.org/zope' xmlns:meta="http://namespaces.zope.org/meta" > <include package="demo2" /> <principal id="zope.manager" title="Manager" login="jim" password_manager="SHA1" password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" /> <grant role="zope.Manager" principal="zope.manager" /> </configure>
不幸的是,配置文件行的前导空格被删除了。这是ConfigParser工作方式的后果。
runzope脚本运行Web服务器
>>> cat('parts', 'myapp', 'runzope') #!/usr/local/bin/python2.4 <BLANKLINE> import sys sys.path[0:0] = [ '/sample-buildout/demo2', '/sample-buildout/demo1', '/zope3/src', ] <BLANKLINE> import zope.app.twisted.main <BLANKLINE> if __name__ == '__main__': sys.exit(zope.app.twisted.main.main())
它在其路径中包含了我们在配置文件中指定的egg,以及它们的依赖项。注意,我们还没有指定配置文件。当运行runzope时,必须使用-C选项提供配置文件。-X选项也可以提供以覆盖配置文件选项。
debugzope脚本提供了对对象系统的访问。当运行debugzope时,必须使用-C选项提供配置文件。-X选项也可以提供以覆盖配置文件选项。如果没有提供任何额外的参数,则将启动一个交互式解释器,数据库由配置文件指定打开,变量root设置为应用程序根对象。调试器变量设置为Zope 3调试器。如果提供了额外的参数,则第一个参数应该是脚本名称,其余参数是脚本参数。脚本将带有根和调试器变量作为全局变量运行。
>>> cat('parts', 'myapp', 'debugzope') #!/usr/local/bin/python2.4 <BLANKLINE> import sys sys.path[0:0] = [ '/sample-buildout/demo2', '/sample-buildout/demo1', '/zope3/src', '/site-packages', ] <BLANKLINE> import zope.app.twisted.main <BLANKLINE> <BLANKLINE> import zc.zope3recipes.debugzope <BLANKLINE> if __name__ == '__main__': sys.exit(zc.zope3recipes.debugzope.debug(main_module=zope.app.twisted.main))
请注意,上面显示的runzope使用的是默认的基于twisted的服务器组件。可以指定使用哪一套服务器组件:“服务器”设置可以设置为“zserver”或“twisted”。对于应用程序,这会影响runzope脚本;当我们创建应用程序实例时,我们将看到更多的差异。
让我们继续使用twisted服务器,但明确选择
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = myapp ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... servers = twisted ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Updating myapp.
请注意,这并不被视为对配置的更改;消息表明myapp已更新,而不是卸载后重新安装。
生成的runzope脚本与之前看到的一样
>>> cat('parts', 'myapp', 'runzope') #!/usr/local/bin/python2.4 <BLANKLINE> import sys sys.path[0:0] = [ '/sample-buildout/demo2', '/sample-buildout/demo1', '/zope3/src', ] <BLANKLINE> import zope.app.twisted.main <BLANKLINE> if __name__ == '__main__': sys.exit(zope.app.twisted.main.main())
我们也可以明确指定ZServer服务器
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = myapp ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... servers = zserver ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling myapp. Installing myapp. Generated script '/sample-buildout/parts/myapp/runzope'. Generated script '/sample-buildout/parts/myapp/debugzope'.
该部分已重新安装,生成的runzope脚本现在不同了。请注意,这次从不同的包中导入了main()函数
>>> cat('parts', 'myapp', 'runzope') #!/usr/local/bin/python2.4 <BLANKLINE> import sys sys.path[0:0] = [ '/sample-buildout/demo2', '/sample-buildout/demo1', '/zope3/src', ] <BLANKLINE> import zope.app.server.main <BLANKLINE> if __name__ == '__main__': sys.exit(zope.app.server.main.main())
debugzope脚本也进行了修改,以考虑这一点。
>>> cat('parts', 'myapp', 'debugzope') #!/usr/local/bin/python2.4 <BLANKLINE> import sys sys.path[0:0] = [ '/sample-buildout/demo2', '/sample-buildout/demo1', '/zope3/src', '/site-packages', ] <BLANKLINE> import zope.app.server.main <BLANKLINE> <BLANKLINE> import zc.zope3recipes.debugzope <BLANKLINE> if __name__ == '__main__': sys.exit(zc.zope3recipes.debugzope.debug(main_module=zope.app.server.main))
相对路径
我们还可以请求相对路径。
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = myapp ... relative-paths = true ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... servers = zserver ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling myapp. Installing myapp. Generated script '/sample-buildout/parts/myapp/runzope'. Generated script '/sample-buildout/parts/myapp/debugzope'.
runzope脚本具有相对路径。
>>> cat('parts', 'myapp', 'runzope') #!/usr/local/bin/python2.4 <BLANKLINE> import os <BLANKLINE> join = os.path.join base = os.path.dirname(os.path.abspath(os.path.realpath(__file__))) base = os.path.dirname(base) base = os.path.dirname(base) <BLANKLINE> import sys sys.path[0:0] = [ join(base, 'demo2'), join(base, 'demo1'), '/zope3/src', ] <BLANKLINE> import zope.app.server.main <BLANKLINE> if __name__ == '__main__': sys.exit(zope.app.server.main.main())
debugzope脚本也具有相对路径。
>>> cat('parts', 'myapp', 'debugzope') #!/usr/local/bin/python2.4 <BLANKLINE> import os <BLANKLINE> join = os.path.join base = os.path.dirname(os.path.abspath(os.path.realpath(__file__))) base = os.path.dirname(base) base = os.path.dirname(base) <BLANKLINE> import sys sys.path[0:0] = [ join(base, 'demo2'), join(base, 'demo1'), '/zope3/src', '/site-packages', ] <BLANKLINE> import zope.app.server.main <BLANKLINE> <BLANKLINE> import zc.zope3recipes.debugzope <BLANKLINE> if __name__ == '__main__': sys.exit(zc.zope3recipes.debugzope.debug(main_module=zope.app.server.main))
遗留功能测试支持
Zope 3的功能测试支持基于zope.testing测试层。有一个默认的功能测试层,旧的测试用例使用这个层。该层加载Zope应用程序服务器的默认配置。它存在是为了为在测试基础设施中添加层之前编写的旧的测试用例提供支持。默认测试层有一些缺点
它为大量包加载配置。这可能会引入对这些所有包的测试依赖。
它需要一个ftesting.zcml文件,并假设该文件的位置。特别是,它假设当测试运行时,该文件位于当前工作目录的相对位置。
较新的软件和受维护的软件应使用它们自己的功能测试层,这些层使用包中定义的测试配置文件。
为了支持使用默认层的旧包,提供了一个ftesting.zcml选项。如果使用它,则选项的内容将写入应用程序中的ftesting.zcml文件。此外,还会写入一个ftesting-base.zcml文件,它包含传统上在Zope 3 ftesting-base.zcml中找到的配置,不包括对package-includes的引用。
如果我们修改我们的buildout以包含一个ftesting.zcml选项
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = myapp ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... ftesting.zcml = ... <meta:provides feature="devmode" /> ... <include file="ftesting-base.zcml" /> ... <includeOverrides package="demo2" /> ... eggs = demo2 ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling myapp. Installing myapp. Generated script '/sample-buildout/parts/myapp/runzope'. Generated script '/sample-buildout/parts/myapp/debugzope'.
我们将在应用程序中创建ftesting.zcml文件和ftesting-base.zcml文件
>>> cat('parts', 'myapp', 'ftesting.zcml') <configure xmlns='http://namespaces.zope.org/zope' xmlns:meta="http://namespaces.zope.org/meta" > <BLANKLINE> <meta:provides feature="devmode" /> <include file="ftesting-base.zcml" /> <includeOverrides package="demo2" /> </configure>>>> cat('parts', 'myapp', 'ftesting-base.zcml') <BLANKLINE> <configure xmlns="http://namespaces.zope.org/zope" i18n_domain="zope" > <include package="zope.app" /> <include package="zope.app" file="ftesting.zcml" /> <include package="zope.app.securitypolicy" file="meta.zcml" /> <include package="zope.app.securitypolicy" /> <securityPolicy component="zope.app.securitypolicy.zopepolicy.ZopeSecurityPolicy" /> <role id="zope.Anonymous" title="Everybody" description="All users have this role implicitly" /> <role id="zope.Manager" title="Site Manager" /> <role id="zope.Member" title="Site Member" /> <grant permission="zope.View" role="zope.Anonymous" /> <grant permission="zope.app.dublincore.view" role="zope.Anonymous" /> <grantAll role="zope.Manager" /> <include package="zope.app.securitypolicy.tests" file="functional.zcml" /> <unauthenticatedPrincipal id="zope.anybody" title="Unauthenticated User" /> <unauthenticatedGroup id="zope.Anybody" title="Unauthenticated Users" /> <authenticatedGroup id="zope.Authenticated" title="Authenticated Users" /> <everybodyGroup id="zope.Everybody" title="All Users" /> <principal id="zope.mgr" title="Manager" login="mgr" password="mgrpw" /> <principal id="zope.globalmgr" title="Manager" login="globalmgr" password="globalmgrpw" /> <grant role="zope.Manager" principal="zope.globalmgr" /> </configure>
定义Zope3实例
定义了应用程序后,我们可以定义一个或多个应用程序实例。我们使用zc.zope3recipes实例配方来这样做。实例配方有2种模式,开发和生产模式。我们将从开发模式开始。在开发模式中,将为每个实例创建一个包含实例配置文件的目录。该目录还将包含实例创建的运行时文件,例如日志文件或zdaemon套接字文件。
定义实例时,我们需要指定一个zope.conf文件。配方可以为我们做大部分工作。让我们看看一个基本的例子
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... application = myapp ... zope.conf = ${database:zconfig} ... ... [database] ... recipe = zc.recipe.filestorage ... ''' % globals())
应用程序选项命名了一个应用程序部分。应用程序部分将用于确定site.zcml文件的位置和要运行的脚本的名称。
我们指定了一个zope.conf选项,它包含一个在我们最终的zope.conf文件中的启动。配方将添加我们省略的一些内容。我们真正需要的是数据库定义。我们只需包含数据库部分中的zconfig选项,我们使用zc.recipe.filestorage配方将其提供为文件存储部分。filestorage配方将创建一个目录来存储我们的数据库,并计算一个我们可以在实例部分中使用的zconfig选项。
请注意,我们已经用实例部分替换了myapp部分。myapp部分将通过实例部分的引用被包含。
让我们运行buildout,看看我们得到什么
>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling myapp. Installing database. Installing myapp. Generated script '/sample-buildout/parts/myapp/runzope'. Generated script '/sample-buildout/parts/myapp/debugzope'. Installing instance. Generated script '/sample-buildout/bin/instance'.
我们看到数据库和myapp部分是通过实例部分的引用被包含的。
我们得到了新的数据库和实例目录
>>> ls_optional('parts', ignore=('buildout',)) d database d instance d myapp
实例目录包含zdaemon.conf和zope.conf文件
>>> ls('parts', 'instance') - zdaemon.conf - zope.conf
让我们看看生成的zope.conf文件
>>> cat('parts', 'instance', 'zope.conf') site-definition /sample-buildout/parts/myapp/site.zcml <BLANKLINE> <zodb> <filestorage> path /sample-buildout/parts/database/Data.fs </filestorage> </zodb> <BLANKLINE> <server> address 8080 type HTTP </server> <BLANKLINE> <accesslog> <logfile> path /sample-buildout/parts/instance/access.log </logfile> </accesslog> <BLANKLINE> <eventlog> <logfile> formatter zope.exceptions.log.Formatter path STDOUT </logfile> </eventlog>
这个文件使用了twisted服务器类型,因为这是Zope 3的默认配置。如果我们指定使用ZServer服务器,则服务器类型的名称将相应调整
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... servers = zserver ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... application = myapp ... zope.conf = ${database:zconfig} ... ... [database] ... recipe = zc.recipe.filestorage ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling instance. Uninstalling myapp. Updating database. Installing myapp. Generated script '/sample-buildout/parts/myapp/runzope'. Generated script '/sample-buildout/parts/myapp/debugzope'. Installing instance. Generated script '/sample-buildout/bin/instance'.
现在生成的zope.conf文件使用的是ZServer服务器组件
>>> cat('parts', 'instance', 'zope.conf') site-definition /sample-buildout/parts/myapp/site.zcml <BLANKLINE> <zodb> <filestorage> path /sample-buildout/parts/database/Data.fs </filestorage> </zodb> <BLANKLINE> <server> address 8080 type WSGI-HTTP </server> <BLANKLINE> <accesslog> <logfile> path /sample-buildout/parts/instance/access.log </logfile> </accesslog> <BLANKLINE> <eventlog> <logfile> formatter zope.exceptions.log.Formatter path STDOUT </logfile> </eventlog>
也可以明确指定基于Twisted的服务器
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... servers = twisted ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... application = myapp ... zope.conf = ${database:zconfig} ... ... [database] ... recipe = zc.recipe.filestorage ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling instance. Uninstalling myapp. Updating database. Installing myapp. Generated script '/sample-buildout/parts/myapp/runzope'. Generated script '/sample-buildout/parts/myapp/debugzope'. Installing instance. Generated script '/sample-buildout/bin/instance'.
现在生成的zope.conf文件再次使用Twisted服务器组件
>>> cat('parts', 'instance', 'zope.conf') site-definition /sample-buildout/parts/myapp/site.zcml <BLANKLINE> <zodb> <filestorage> path /sample-buildout/parts/database/Data.fs </filestorage> </zodb> <BLANKLINE> <server> address 8080 type HTTP </server> <BLANKLINE> <accesslog> <logfile> path /sample-buildout/parts/instance/access.log </logfile> </accesslog> <BLANKLINE> <eventlog> <logfile> formatter zope.exceptions.log.Formatter path STDOUT </logfile> </eventlog>
它包含了我们在zope.conf选项中提供的数据库定义。它还有一个site-definition选项,指定了我们应用程序目录中的site.zcml文件。
我们没有指定任何服务器或日志ZConfig部分,因此生成了一些供我们使用。
请注意,默认情况下,事件日志输出到标准输出。我们将在稍后讨论zdaemon配置时详细介绍这一点。
如果我们自己指定服务器部分
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... application = myapp ... zope.conf = ${database:zconfig} ... <server> ... type PostmortemDebuggingHTTP ... address 8080 ... </server> ... ... [database] ... recipe = zc.recipe.filestorage ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling instance. Updating database. Updating myapp. Installing instance. Generated script '/sample-buildout/bin/instance'.
那么我们将使用的部分(或部分)将使用,而不会添加新的
>>> cat('parts', 'instance', 'zope.conf') site-definition /sample-buildout/parts/myapp/site.zcml <BLANKLINE> <zodb> <filestorage> path /sample-buildout/parts/database/Data.fs </filestorage> </zodb> <BLANKLINE> <server> address 8080 type PostmortemDebuggingHTTP </server> <BLANKLINE> <accesslog> <logfile> path /sample-buildout/parts/instance/access.log </logfile> </accesslog> <BLANKLINE> <eventlog> <logfile> formatter zope.exceptions.log.Formatter path STDOUT </logfile> </eventlog>
如果我们只想指定不同的端口或地址,我们可以使用地址选项,该选项接受零个或多个地址指定
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... application = myapp ... zope.conf = ${database:zconfig} ... address = 8081 foo.com:8082 ... ... [database] ... recipe = zc.recipe.filestorage ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling instance. Updating database. Updating myapp. Installing instance. Generated script '/sample-buildout/bin/instance'.>>> cat('parts', 'instance', 'zope.conf') site-definition /sample-buildout/parts/myapp/site.zcml <BLANKLINE> <zodb> <filestorage> path /sample-buildout/parts/database/Data.fs </filestorage> </zodb> <BLANKLINE> <server> address 8081 type HTTP </server> <BLANKLINE> <server> address foo.com:8082 type HTTP </server> <BLANKLINE> <accesslog> <logfile> path /sample-buildout/parts/instance/access.log </logfile> </accesslog> <BLANKLINE> <eventlog> <logfile> formatter zope.exceptions.log.Formatter path STDOUT </logfile> </eventlog>
我们可以指定自己的访问日志和事件日志配置。例如,将事件日志输出到文件并抑制访问日志
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... application = myapp ... zope.conf = ${database:zconfig} ... <eventlog> ... <logfile> ... path ${buildout:parts-directory}/instance/event.log ... formatter zope.exceptions.log.Formatter ... </logfile> ... </eventlog> ... <accesslog> ... </accesslog> ... ... address = 8081 ... ... [database] ... recipe = zc.recipe.filestorage ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling instance. Updating database. Updating myapp. Installing instance. Generated script '/sample-buildout/bin/instance'.>>> cat('parts', 'instance', 'zope.conf') site-definition /sample-buildout/parts/myapp/site.zcml <BLANKLINE> <zodb> <filestorage> path /sample-buildout/parts/database/Data.fs </filestorage> </zodb> <BLANKLINE> <eventlog> <logfile> formatter zope.exceptions.log.Formatter path /sample-buildout/parts/instance/event.log </logfile> </eventlog> <BLANKLINE> <accesslog> </accesslog> <BLANKLINE> <server> address 8081 type HTTP </server>
让我们看看zdaemon.conf文件
>>> cat('parts', 'instance', 'zdaemon.conf') <runner> daemon on directory /sample-buildout/parts/instance program /sample-buildout/parts/myapp/runzope -C /sample-buildout/parts/instance/zope.conf socket-name /sample-buildout/parts/instance/zdaemon.sock transcript /sample-buildout/parts/instance/z3.log </runner> <BLANKLINE> <eventlog> <logfile> path /sample-buildout/parts/instance/z3.log </logfile> </eventlog>
这里我们看到一个相当普通的zdaemon.conf文件。程序选项指向我们应用程序目录中的runzope脚本。用于zdaemon命令行脚本和zademon管理器之间通信的套接字文件放置在实例目录中。
如果您想覆盖生成的zdaemon输出的任何部分,只需在实例部分提供zdaemon.conf选项即可
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... application = myapp ... zope.conf = ${database:zconfig} ... address = 8081 ... zdaemon.conf = ... <runner> ... daemon off ... socket-name /sample-buildout/parts/instance/sock ... transcript /dev/null ... </runner> ... <eventlog> ... </eventlog> ... ... [database] ... recipe = zc.recipe.filestorage ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling instance. Updating database. Updating myapp. Installing instance. Generated script '/sample-buildout/bin/instance'.>>> cat('parts', 'instance', 'zdaemon.conf') <runner> daemon off directory /sample-buildout/parts/instance program /sample-buildout/parts/myapp/runzope -C /sample-buildout/parts/instance/zope.conf socket-name /sample-buildout/parts/instance/sock transcript /dev/null </runner> <BLANKLINE> <eventlog> </eventlog>
除了配置文件外,在buildout bin目录中还生成一个控制脚本
>>> ls('bin') - buildout - instance
>>> cat('bin', 'instance') #!/usr/local/bin/python2.4 <BLANKLINE> import sys sys.path[0:0] = [ '/site-packages', ] <BLANKLINE> import zc.zope3recipes.ctl <BLANKLINE> if __name__ == '__main__': sys.exit(zc.zope3recipes.ctl.main([ '/sample-buildout/parts/myapp/debugzope', '/sample-buildout/parts/instance/zope.conf', '-C', '/sample-buildout/parts/instance/zdaemon.conf', ]+sys.argv[1:] ))
某些配置部分可以包含一个键多次;ZEO客户端部分就是这样工作的。当键被多次给出时,所有值都按输入中的顺序包含在结果配置中
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... application = myapp ... zope.conf = ... <zodb> ... <zeoclient> ... server 127.0.0.1:8001 ... server 127.0.0.1:8002 ... </zeoclient> ... </zodb> ... address = 8081 ... zdaemon.conf = ... <runner> ... daemon off ... socket-name /sample-buildout/parts/instance/sock ... transcript /dev/null ... </runner> ... <eventlog> ... </eventlog> ... ... ''' % globals()) >>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling instance. Uninstalling database. Updating myapp. Installing instance. Generated script '/sample-buildout/bin/instance'. >>> cat('parts', 'instance', 'zope.conf') site-definition /sample-buildout/parts/myapp/site.zcml <BLANKLINE> <zodb> <zeoclient> server 127.0.0.1:8001 server 127.0.0.1:8002 </zeoclient> </zodb> <BLANKLINE> <server> address 8081 type HTTP </server> <BLANKLINE> <accesslog> <logfile> path /sample-buildout/parts/instance/access.log </logfile> </accesslog> <BLANKLINE> <eventlog> <logfile> formatter zope.exceptions.log.Formatter path STDOUT </logfile> </eventlog>
实例名称
实例配方根据其名称生成文件或目录,默认值为部分名称。我们可以使用name选项指定不同的名称。这不会影响使用哪个部分目录,但它会影响bin中运行脚本的名称
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... name = server ... application = myapp ... zope.conf = ... <zodb> ... <zeoclient> ... server 127.0.0.1:8001 ... server 127.0.0.1:8002 ... </zeoclient> ... </zodb> ... address = 8081 ... zdaemon.conf = ... <runner> ... daemon off ... socket-name /sample-buildout/parts/instance/sock ... transcript /dev/null ... </runner> ... <eventlog> ... </eventlog> ... ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling instance. Updating myapp. Installing instance. Generated script '/sample-buildout/bin/server'.
指定替代站点定义
理想情况下,ZCML用于配置应用程序使用的软件,而zope.conf用于提供特定实例的配置。由于历史原因,有一些ZCML指令提供进程配置。一个很好的例子是zope.sendmail包提供的smtpMailer指令。我们可以在zope.conf文件中覆盖site-definition选项来指定一个替代的zcml文件。在这里,我们将更新实例配置以使用替代的站点定义
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... application = myapp ... zope.conf = ... site-definition ${buildout:directory}/site.zcml ... <zodb> ... <zeoclient> ... server 127.0.0.1:8001 ... server 127.0.0.1:8002 ... </zeoclient> ... </zodb> ... address = 8081 ... zdaemon.conf = ... <runner> ... daemon off ... socket-name /sample-buildout/parts/instance/sock ... transcript /dev/null ... </runner> ... <eventlog> ... </eventlog> ... ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling instance. Updating myapp. Installing instance. Generated script '/sample-buildout/bin/instance'.>>> cat('parts', 'instance', 'zope.conf') site-definition /sample-buildout/site.zcml <BLANKLINE> <zodb> <zeoclient> server 127.0.0.1:8001 server 127.0.0.1:8002 </zeoclient> </zodb> <BLANKLINE> <server> address 8081 type HTTP </server> <BLANKLINE> <accesslog> <logfile> path /sample-buildout/parts/instance/access.log </logfile> </accesslog> <BLANKLINE> <eventlog> <logfile> formatter zope.exceptions.log.Formatter path STDOUT </logfile> </eventlog>
(请注意,在实际中,您通常会使用zc.recipe.deployment:configuration配方,http://pypi.python.org/pypi/zc.recipe.deployment#configuration-files,来定义site.zcml文件,使用buildout。)
日志文件
日志文件设置需要一些解释。Zope事件日志仅捕获日志调用输出。特别是,它不捕获写入标准错误的启动错误。zdaemon转储日志非常有用,可以捕获这种输出。如果没有它,以守护进程模式运行时,写入标准错误的错误就会丢失。过去Zope 3的默认配置是将Zope访问和事件日志输出到两个文件和标准输出,并定义转储日志。这导致转储重复了事件日志和访问日志的内容,同时还捕获了其他输出。这很不节省空间。
这个配方的方法是将zope和zdaemon事件日志信息以及Zope错误输出合并到一个日志文件中。我们通过将Zope的事件日志定向到标准输出来实现,这在Zope在前台模式下运行时很有用,并且可以被zdaemon转储日志捕获。
Unix部署
实例配方支持Unix部署,这是由zc.recipe.deployment配方提供的。部署部分定义了实例配方使用的一组选项。
- etc-directory
放置配置文件的目录名称。默认为/etc/NAME,其中NAME是部署名称。
- log-directory
应用实例写入日志文件的目录名称。默认为/var/log/NAME,其中NAME是部署名称。
- run-directory
应用实例放置运行时文件(如pid文件和进程间通信套接字文件)的目录名称。默认为/var/run/NAME,其中NAME是部署名称。
- rc-directory
安装运行控制脚本的目录名称。
- logrotate-directory
安装logrotate配置文件的目录名称。
- user
进程应运行的用户名称。
由于各种原因,部署配方必须以root身份运行,但我们可以通过提供包含所需数据的部分来创建一个虚拟部署。让我们更新我们的配置以使用部署。我们首先创建一个虚拟安装根目录
>>> root = tmpdir('root') >>> mkdir(root, 'etc') >>> mkdir(root, 'etc', 'myapp-run') >>> mkdir(root, 'etc', 'init.d') >>> mkdir(root, 'etc', 'logrotate.d')>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... application = myapp ... zope.conf = ${database:zconfig} ... address = 8081 ... deployment = myapp-deployment ... ... [database] ... recipe = zc.recipe.filestorage ... ... [myapp-deployment] ... name = myapp-run ... etc-directory = %(root)s/etc/myapp-run ... rc-directory = %(root)s/etc/init.d ... logrotate-directory = %(root)s/etc/logrotate.d ... log-directory = %(root)s/var/log/myapp-run ... run-directory = %(root)s/var/run/myapp-run ... user = zope ... ''' % globals())
在这里,我们添加了一个部署部分myapp-deployment,并添加了一个部署选项到我们的实例部分,告诉实例配方使用该部署。如果我们重新运行buildout
>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling instance. Installing database. Updating myapp. Installing instance. Generated script '/root/etc/init.d/myapp-run-instance'.
安装文件将移动。我们将不再有实例部分
>>> ls_optional('parts', ignore=('buildout',)) d database d myapp
或控制脚本
>>> ls('bin') - buildout
相反,我们的配置文件将位于/etc/myapp-run目录下
>>> ls(root, 'etc', 'myapp-run') - instance-zdaemon.conf - instance-zope.conf
请注意,实例名称已添加到文件名前缀,因为我们通常在部署中还有其他实例。
控制脚本位于init.d目录下
>>> ls(root, 'etc', 'init.d') - myapp-run-instance
请注意,部署名称已添加到控制脚本名称的前缀。
logrotate文件位于logrotate.d目录下
>>> ls(root, 'etc', 'logrotate.d') - myapp-run-instance
配置文件已更改以反映部署位置
>>> cat(root, 'etc', 'myapp-run', 'instance-zope.conf') site-definition /sample-buildout/parts/myapp/site.zcml <BLANKLINE> <zodb> <filestorage> path /sample-buildout/parts/database/Data.fs </filestorage> </zodb> <BLANKLINE> <server> address 8081 type HTTP </server> <BLANKLINE> <accesslog> <logfile> path /root/var/log/myapp-run/instance-access.log </logfile> </accesslog> <BLANKLINE> <eventlog> <logfile> formatter zope.exceptions.log.Formatter path STDOUT </logfile> </eventlog>>>> cat(root, 'etc', 'myapp-run', 'instance-zdaemon.conf') <runner> daemon on directory /root/var/run/myapp-run program /sample-buildout/parts/myapp/runzope -C /root/etc/myapp-run/instance-zope.conf socket-name /root/var/run/myapp-run/instance-zdaemon.sock transcript /root/var/log/myapp-run/instance-z3.log user zope </runner> <BLANKLINE> <eventlog> <logfile> path /root/var/log/myapp-run/instance-z3.log </logfile> </eventlog>>>> cat(root, 'etc', 'logrotate.d', 'myapp-run-instance') /root/var/log/myapp-run/instance-z3.log { rotate 5 weekly postrotate /root/etc/init.d/myapp-run-instance reopen_transcript endscript }
如果我们提供备用实例名称,它将反映在生成的文件中
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... name = server ... application = myapp ... zope.conf = ${database:zconfig} ... address = 8081 ... deployment = myapp-deployment ... ... [database] ... recipe = zc.recipe.filestorage ... ... [myapp-deployment] ... name = myapp-run ... etc-directory = %(root)s/etc/myapp-run ... rc-directory = %(root)s/etc/init.d ... logrotate-directory = %(root)s/etc/logrotate.d ... log-directory = %(root)s/var/log/myapp-run ... run-directory = %(root)s/var/run/myapp-run ... user = zope ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling instance. Updating database. Updating myapp. Installing instance. Generated script '/root/etc/init.d/myapp-run-server'.>>> cat(root, 'etc', 'myapp-run', 'server-zope.conf') site-definition /sample-buildout/parts/myapp/site.zcml <BLANKLINE> <zodb> <filestorage> path /sample-buildout/parts/database/Data.fs </filestorage> </zodb> <BLANKLINE> <server> address 8081 type HTTP </server> <BLANKLINE> <accesslog> <logfile> path /root/var/log/myapp-run/server-access.log </logfile> </accesslog> <BLANKLINE> <eventlog> <logfile> formatter zope.exceptions.log.Formatter path STDOUT </logfile> </eventlog>>>> cat(root, 'etc', 'myapp-run', 'server-zdaemon.conf') <runner> daemon on directory /root/var/run/myapp-run program /sample-buildout/parts/myapp/runzope -C /root/etc/myapp-run/server-zope.conf socket-name /root/var/run/myapp-run/server-zdaemon.sock transcript /root/var/log/myapp-run/server-z3.log user zope </runner> <BLANKLINE> <eventlog> <logfile> path /root/var/log/myapp-run/server-z3.log </logfile> </eventlog>
控制logrotate配置
某些应用程序控制自己的日志轮转策略。在这些情况下,我们不想生成日志轮转配置。
设置logrotate.conf设置会影响配置。显式设置它控制实例的logrotate文件内容;设置为空字符串则完全不会生成。
让我们直接将内容设置为非空值
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... application = myapp ... zope.conf = ${database:zconfig} ... address = 8081 ... deployment = myapp-deployment ... logrotate.conf = ... /root/var/log/myapp-run/instance-z3.log { ... rotate 10 ... daily ... postrotate ... /root/etc/init.d/myapp-run-instance reopen_transcript ... endscript ... } ... ... [database] ... recipe = zc.recipe.filestorage ... ... [myapp-deployment] ... name = myapp-run ... etc-directory = %(root)s/etc/myapp-run ... rc-directory = %(root)s/etc/init.d ... logrotate-directory = %(root)s/etc/logrotate.d ... log-directory = %(root)s/var/log/myapp-run ... run-directory = %(root)s/var/run/myapp-run ... user = zope ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling instance. Uninstalling myapp. Updating database. Installing myapp. Generated script '/sample-buildout/parts/myapp/runzope'. Generated script '/sample-buildout/parts/myapp/debugzope'. Installing instance. Generated script '/root/etc/init.d/myapp-run-instance'.>>> cat(root, 'etc', 'logrotate.d', 'myapp-run-instance') /root/var/log/myapp-run/instance-z3.log { rotate 10 daily postrotate /root/etc/init.d/myapp-run-instance reopen_transcript endscript }
如果我们将logrotate.conf设置为空字符串,则不会生成文件
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... application = myapp ... zope.conf = ${database:zconfig} ... address = 8081 ... deployment = myapp-deployment ... logrotate.conf = ... ... [database] ... recipe = zc.recipe.filestorage ... ... [myapp-deployment] ... name = myapp-run ... etc-directory = %(root)s/etc/myapp-run ... rc-directory = %(root)s/etc/init.d ... logrotate-directory = %(root)s/etc/logrotate.d ... log-directory = %(root)s/var/log/myapp-run ... run-directory = %(root)s/var/run/myapp-run ... user = zope ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling instance. Updating database. Updating myapp. Installing instance. Generated script '/root/etc/init.d/myapp-run-instance'.>>> ls(root, 'etc', 'logrotate.d')
定义多个类似实例
通常您想要定义多个实例,这些实例只有一个或两个选项(例如地址)不同。extends选项允许您命名一个部分,从该部分加载默认选项。源部分中未定义的任何选项都添加到扩展部分。
让我们更新我们的buildout以添加一个新的实例
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance instance2 ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... application = myapp ... zope.conf = ${database:zconfig} ... address = 8081 ... deployment = myapp-deployment ... ... [instance2] ... recipe = zc.zope3recipes:instance ... extends = instance ... address = 8082 ... ... [database] ... recipe = zc.recipe.filestorage ... ... [myapp-deployment] ... name = myapp-run ... etc-directory = %(root)s/etc/myapp-run ... rc-directory = %(root)s/etc/init.d ... logrotate-directory = %(root)s/etc/logrotate.d ... log-directory = %(root)s/var/log/myapp-run ... run-directory = %(root)s/var/run/myapp-run ... user = zope ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling instance. Uninstalling myapp. Updating database. Installing myapp. Generated script '/sample-buildout/parts/myapp/runzope'. Generated script '/sample-buildout/parts/myapp/debugzope'. Installing instance. Generated script '/root/etc/init.d/myapp-run-instance'. Installing instance2. Generated script '/root/etc/init.d/myapp-run-instance2'.
现在,我们有新的实例配置文件
>>> ls(root, 'etc', 'myapp-run') - instance-zdaemon.conf - instance-zope.conf - instance2-zdaemon.conf - instance2-zope.conf>>> cat(root, 'etc', 'myapp-run', 'instance2-zope.conf') site-definition /sample-buildout/parts/myapp/site.zcml <BLANKLINE> <zodb> <filestorage> path /sample-buildout/parts/database/Data.fs </filestorage> </zodb> <BLANKLINE> <server> address 8082 type HTTP </server> <BLANKLINE> <accesslog> <logfile> path /root/var/log/myapp-run/instance2-access.log </logfile> </accesslog> <BLANKLINE> <eventlog> <logfile> formatter zope.exceptions.log.Formatter path STDOUT </logfile> </eventlog>
相对路径
如果构建配置中请求,控制脚本将使用相对路径。
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance ... relative-paths = true ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... application = myapp ... zope.conf = ${database:zconfig} ... ... [database] ... recipe = zc.recipe.filestorage ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling instance2. Uninstalling instance. Uninstalling myapp. Updating database. Installing myapp. Generated script '/sample-buildout/parts/myapp/runzope'. Generated script '/sample-buildout/parts/myapp/debugzope'. Installing instance. Generated script '/sample-buildout/bin/instance'.现在sys.path和ctl的参数都使用相对路径。
>>> cat('bin', 'instance') #!/usr/local/bin/python2.4 <BLANKLINE> import os <BLANKLINE> join = os.path.join base = os.path.dirname(os.path.abspath(os.path.realpath(__file__))) base = os.path.dirname(base) <BLANKLINE> import sys sys.path[0:0] = [ '/site-packages', ] <BLANKLINE> import zc.zope3recipes.ctl <BLANKLINE> if __name__ == '__main__': sys.exit(zc.zope3recipes.ctl.main([ join(base, 'parts/myapp/debugzope'), join(base, 'parts/instance/zope.conf'), '-C', join(base, 'parts/instance/zdaemon.conf'), ]+sys.argv[1:] ))
zope.conf配方
zope.conf配方处理填充zope.conf文件中实例配方执行的隐含部分,而不会创建实例的其余部分。
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 ... parts = some.conf ... ... [myapp] ... recipe = zc.zope3recipes:application ... site.zcml = <include package="demo1" /> ... eggs = demo1 ... ... [some.conf] ... recipe = zc.zope3recipes:zopeconf ... application = myapp ... text = ... <zodb> ... <zeoclient> ... server 127.0.0.1:8001 ... </zeoclient> ... </zodb> ... ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Uninstalling instance. Uninstalling myapp. Uninstalling database. Installing myapp. Generated script '/sample-buildout/parts/myapp/runzope'. Generated script '/sample-buildout/parts/myapp/debugzope'. Installing some.conf.>>> cat('parts', 'some.conf') site-definition /sample-buildout/parts/myapp/site.zcml <BLANKLINE> <zodb> <zeoclient> server 127.0.0.1:8001 </zeoclient> </zodb> <BLANKLINE> <server> address 8080 type HTTP </server> <BLANKLINE> <accesslog> <logfile> path /sample-buildout/parts/some-access.log </logfile> </accesslog> <BLANKLINE> <eventlog> <logfile> formatter zope.exceptions.log.Formatter path STDOUT </logfile> </eventlog>
我们可以在部分中直接指定访问日志的位置
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 ... parts = some.conf ... ... [myapp] ... recipe = zc.zope3recipes:application ... site.zcml = <include package="demo1" /> ... eggs = demo1 ... ... [some.conf] ... recipe = zc.zope3recipes:zopeconf ... application = myapp ... access-log = ${buildout:directory}/access.log ... text = ... <zodb> ... <zeoclient> ... server 127.0.0.1:8001 ... </zeoclient> ... </zodb> ... ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/tmp/tmp2eRRw1buildoutSetUp/_TEST_/sample-buildout/demo1' Uninstalling some.conf. Updating myapp. Installing some.conf.>>> cat('parts', 'some.conf') site-definition /sample-buildout/parts/myapp/site.zcml <BLANKLINE> <zodb> <zeoclient> server 127.0.0.1:8001 </zeoclient> </zodb> <BLANKLINE> <server> address 8080 type HTTP </server> <BLANKLINE> <accesslog> <logfile> path /sample-buildout/access.log </logfile> </accesslog> <BLANKLINE> <eventlog> <logfile> formatter zope.exceptions.log.Formatter path STDOUT </logfile> </eventlog>
可以使用“address”设置设置服务器的地址
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 ... parts = some.conf ... ... [myapp] ... recipe = zc.zope3recipes:application ... site.zcml = <include package="demo1" /> ... eggs = demo1 ... ... [some.conf] ... recipe = zc.zope3recipes:zopeconf ... address = 4242 ... application = myapp ... text = ... <zodb> ... <zeoclient> ... server 127.0.0.1:8001 ... </zeoclient> ... </zodb> ... ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/tmp/tmp2eRRw1buildoutSetUp/_TEST_/sample-buildout/demo1' Uninstalling some.conf. Updating myapp. Installing some.conf.>>> cat('parts', 'some.conf') site-definition /sample-buildout/parts/myapp/site.zcml <BLANKLINE> <zodb> <zeoclient> server 127.0.0.1:8001 </zeoclient> </zodb> <BLANKLINE> <server> address 4242 type HTTP </server> <BLANKLINE> <accesslog> <logfile> path /sample-buildout/parts/some-access.log </logfile> </accesslog> <BLANKLINE> <eventlog> <logfile> formatter zope.exceptions.log.Formatter path STDOUT </logfile> </eventlog>
文件位置作为“location”设置提供。这类似于zc.recipe.deployment:configuration配方,这使得在某些情况下可能替代该配方。
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 ... parts = another.conf ... ... [myapp] ... recipe = zc.zope3recipes:application ... site.zcml = <include package="demo1" /> ... eggs = demo1 ... ... [some.conf] ... recipe = zc.zope3recipes:zopeconf ... application = myapp ... text = ... <zodb> ... <zeoclient> ... server 127.0.0.1:8001 ... </zeoclient> ... </zodb> ... ... [another.conf] ... recipe = zc.zope3recipes:zopeconf ... application = myapp ... text = ... ${some.conf:text} ... <product-config reference> ... config ${some.conf:location} ... </product-config> ... ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/tmp/tmp2eRRw1buildoutSetUp/_TEST_/sample-buildout/demo1' Uninstalling some.conf. Updating myapp. Installing some.conf. Installing another.conf.>>> cat('parts', 'another.conf') site-definition /sample-buildout/parts/myapp/site.zcml ... <product-config reference> config /sample-buildout/parts/some.conf </product-config> ...
离线配方
离线配方创建了一个脚本,从某种意义上说,这个脚本是对“bin/instance debug”或“bin/instance run <script>”的一种语法糖。使用离线脚本,你只需执行“bin/offline”或“bin/offline </script>”。这个脚本不会像Instance配方那样创建额外的文件夹;它期望存在两个选项:“application”和“zope.conf”,这两个选项必须是Zope3应用程序和配置文件(支持“location”选项)的部分。
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance offline ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... name = server ... application = myapp ... zope.conf = ... <zodb> ... <zeoclient> ... server 127.0.0.1:8001 ... server 127.0.0.1:8002 ... </zeoclient> ... </zodb> ... address = 8081 ... zdaemon.conf = ... <runner> ... daemon off ... socket-name /sample-buildout/parts/instance/sock ... transcript /dev/null ... </runner> ... <eventlog> ... </eventlog> ... ... [offline.conf] ... location = %(zope3)s ... ... [offline] ... recipe = zc.zope3recipes:offline ... application = myapp ... zope.conf = offline.conf ... ... [database] ... recipe = zc.recipe.filestorage ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling another.conf. Uninstalling some.conf. Uninstalling myapp. Installing myapp. Generated script '/sample-buildout/parts/myapp/runzope'. Generated script '/sample-buildout/parts/myapp/debugzope'. Installing instance. Generated script '/sample-buildout/bin/server'. Installing offline.>>> cat('bin', 'offline') #!/usr/local/bin/python2.4 <BLANKLINE> import os import sys import logging <BLANKLINE> argv = list(sys.argv) env = {} restart = False <BLANKLINE> if None: import pwd if pwd.getpwnam(None).pw_uid != os.geteuid(): restart = True argv[:0] = ["sudo", "-u", None] # print("switching to user %s" % None) del pwd <BLANKLINE> for k in env: if os.environ.get(k) != env[k]: os.environ[k] = env[k] restart = True del k <BLANKLINE> if restart: # print("restarting") os.execvpe(argv[0], argv, dict(os.environ)) <BLANKLINE> del argv del env del restart <BLANKLINE> sys.argv[1:1] = [ "-C", '/zope3', <BLANKLINE> ] <BLANKLINE> debugzope = '/sample-buildout/parts/myapp/debugzope' globals()["__file__"] = debugzope <BLANKLINE> zeo_logger = logging.getLogger('ZEO.zrpc') zeo_logger.addHandler(logging.StreamHandler()) <BLANKLINE> <BLANKLINE> # print("starting debugzope...") with open(debugzope) as f: exec(f.read())
初始化选项
配方还接受一个“初始化”选项
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance offline ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... name = server ... application = myapp ... zope.conf = ... <zodb> ... <zeoclient> ... server 127.0.0.1:8001 ... server 127.0.0.1:8002 ... </zeoclient> ... </zodb> ... address = 8081 ... zdaemon.conf = ... <runner> ... daemon off ... socket-name /sample-buildout/parts/instance/sock ... transcript /dev/null ... </runner> ... <eventlog> ... </eventlog> ... ... [offline.conf] ... location = %(zope3)s ... ... [offline] ... recipe = zc.zope3recipes:offline ... initialization = ... os.environ['ZC_DEBUG_LOGGING'] = 'on' ... application = myapp ... zope.conf = offline.conf ... ... [database] ... recipe = zc.recipe.filestorage ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling offline. Updating myapp. Updating instance. Installing offline.>>> cat('bin', 'offline') <BLANKLINE> import os import sys import logging <BLANKLINE> argv = list(sys.argv) env = {} restart = False <BLANKLINE> if None: import pwd if pwd.getpwnam(None).pw_uid != os.geteuid(): restart = True argv[:0] = ["sudo", "-u", None] # print("switching to user %s" % None) del pwd <BLANKLINE> for k in env: if os.environ.get(k) != env[k]: os.environ[k] = env[k] restart = True del k <BLANKLINE> if restart: # print("restarting") os.execvpe(argv[0], argv, dict(os.environ)) <BLANKLINE> del argv del env del restart <BLANKLINE> sys.argv[1:1] = [ "-C", '/zope3', <BLANKLINE> ] <BLANKLINE> debugzope = '/sample-buildout/parts/myapp/debugzope' globals()["__file__"] = debugzope <BLANKLINE> zeo_logger = logging.getLogger('ZEO.zrpc') zeo_logger.addHandler(logging.StreamHandler()) <BLANKLINE> os.environ['ZC_DEBUG_LOGGING'] = 'on' <BLANKLINE> # print("starting debugzope...") with open(debugzope) as f: exec(f.read())
脚本选项
以及一个“脚本”选项。
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance run-foo ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:app ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... name = server ... application = myapp ... zope.conf = ... <zodb> ... <zeoclient> ... server 127.0.0.1:8001 ... server 127.0.0.1:8002 ... </zeoclient> ... </zodb> ... address = 8081 ... zdaemon.conf = ... <runner> ... daemon off ... socket-name /sample-buildout/parts/instance/sock ... transcript /dev/null ... </runner> ... <eventlog> ... </eventlog> ... ... [offline.conf] ... location = %(zope3)s ... ... [run-foo] ... recipe = zc.zope3recipes:offline ... initialization = ... os.environ['ZC_DEBUG_LOGGING'] = 'on' ... application = myapp ... zope.conf = offline.conf ... script = %(zope3)s/foo.py ... ... [database] ... recipe = zc.recipe.filestorage ... ''' % globals())>>> print(system(join('bin', 'buildout'))) Develop: '/sample-buildout/demo1' Develop: '/sample-buildout/demo2' Uninstalling offline. Updating myapp. Updating instance. Installing run-foo.>>> cat('bin', 'run-foo') <BLANKLINE> import os import sys import logging <BLANKLINE> argv = list(sys.argv) env = {} restart = False <BLANKLINE> if None: import pwd if pwd.getpwnam(None).pw_uid != os.geteuid(): restart = True argv[:0] = ["sudo", "-u", None] # print("switching to user %s" % None) del pwd <BLANKLINE> for k in env: if os.environ.get(k) != env[k]: os.environ[k] = env[k] restart = True del k <BLANKLINE> if restart: # print("restarting") os.execvpe(argv[0], argv, dict(os.environ)) <BLANKLINE> del argv del env del restart <BLANKLINE> sys.argv[1:1] = [ "-C", '/zope3', '/zope3/foo.py' ] <BLANKLINE> debugzope = '/sample-buildout/parts/myapp/debugzope' globals()["__file__"] = debugzope <BLANKLINE> zeo_logger = logging.getLogger('ZEO.zrpc') zeo_logger.addHandler(logging.StreamHandler()) <BLANKLINE> os.environ['ZC_DEBUG_LOGGING'] = 'on' <BLANKLINE> # print("starting debugzope...") with open(debugzope) as f: exec(f.read())
Paste部署支持
你可以使用paste-deployment来控制WSGI服务器和中间件。你通过在servers选项中指定paste来表示这一点
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:application ... servers = paste ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... application = myapp ... zope.conf = ... threads 1 ... ${database:zconfig} ... ... ... [database] ... recipe = zc.recipe.filestorage ... ''' % globals())
当我们运行buildout时,我们会得到一个基于paste的runzope脚本和基于paste的实例启动脚本。
我们还在实例目录中得到了一个paste.ini文件,该文件定义了应用程序和服务器,并在运行paste时使用。
>>> cat('parts', 'instance', 'paste.ini') [app:main] use = egg:zope.app.wsgi config_file = /sample-buildout/parts/instance/zope.conf filter-with = translogger <BLANKLINE> [filter:translogger] use = egg:Paste#translogger setup_console_handler = False logger_name = accesslog <BLANKLINE> [server:main] use = egg:zope.server host = port = 8080 threads = 1
请注意,zope.conf中设置的线程设置已移动到paste.ini
请注意,还使用了past:translogger来提供访问日志。
如果你不想使用zope.server,或者如果你想自己控制服务器配置,你可以提供一个paste.init选项
>>> write('buildout.cfg', ... ''' ... [buildout] ... develop = demo1 demo2 ... parts = instance ... ... [zope3] ... location = %(zope3)s ... ... [myapp] ... recipe = zc.zope3recipes:application ... servers = paste ... site.zcml = <include package="demo2" /> ... <principal ... id="zope.manager" ... title="Manager" ... login="jim" ... password_manager="SHA1" ... password="40bd001563085fc35165329ea1ff5c5ecbdbbeef" ... /> ... <grant ... role="zope.Manager" ... principal="zope.manager" ... /> ... eggs = demo2 ... ... [instance] ... recipe = zc.zope3recipes:instance ... application = myapp ... zope.conf = ... threads 1 ... ${database:zconfig} ... paste.ini = test and not working :) ... ... ... [database] ... recipe = zc.recipe.filestorage ... ''' % globals())
在这个例子中,我们在paste.ini选项中给出了无用的文本,我们得到了一个无意义的paste.ini文件
>>> cat('parts', 'instance', 'paste.ini') [app:main] use = egg:zope.app.wsgi config_file = /sample-buildout/parts/instance/zope.conf <BLANKLINE> test and not working :)
这表明配方不关心你提供了什么。它使用它而不是提供zope.server和paste.translogger的定义,而是与应用程序定义一起使用。
项目详情
下载文件
下载适合您平台的文件。如果您不确定要选择哪一个,请了解更多关于安装包的信息。