[Checkins] SVN: zc.recipe.zope3instance/branches/dev/ Refactored to
not use mkzopeinstance. Need to update doctest.
Jim Fulton
jim at zope.com
Mon Oct 30 07:13:58 EST 2006
Log message for revision 70995:
Refactored to not use mkzopeinstance. Need to update doctest.
Changed:
U zc.recipe.zope3instance/branches/dev/buildout.cfg
U zc.recipe.zope3instance/branches/dev/setup.py
U zc.recipe.zope3instance/branches/dev/src/zc/recipe/zope3instance/README.txt
U zc.recipe.zope3instance/branches/dev/src/zc/recipe/zope3instance/__init__.py
A zc.recipe.zope3instance/branches/dev/src/zc/recipe/zope3instance/ctl.py
A zc.recipe.zope3instance/branches/dev/src/zc/recipe/zope3instance/zope3scripts.py
-=-
Modified: zc.recipe.zope3instance/branches/dev/buildout.cfg
===================================================================
--- zc.recipe.zope3instance/branches/dev/buildout.cfg 2006-10-30 12:10:22 UTC (rev 70994)
+++ zc.recipe.zope3instance/branches/dev/buildout.cfg 2006-10-30 12:13:58 UTC (rev 70995)
@@ -1,5 +1,5 @@
[buildout]
-develop =
+develop = .
parts = test
[test]
Modified: zc.recipe.zope3instance/branches/dev/setup.py
===================================================================
--- zc.recipe.zope3instance/branches/dev/setup.py 2006-10-30 12:10:22 UTC (rev 70994)
+++ zc.recipe.zope3instance/branches/dev/setup.py 2006-10-30 12:13:58 UTC (rev 70995)
@@ -19,5 +19,9 @@
install_requires = ['zc.buildout', 'zope.testing', 'setuptools',
'zc.recipe.egg'],
dependency_links = ['http://download.zope.org/distribution/'],
- entry_points = {'zc.buildout': ['default = %s:Recipe' % name]},
+ entry_points = {
+ 'zc.buildout': [
+ 'default = %s:Recipe' % name,
+ ]
+ },
)
Modified: zc.recipe.zope3instance/branches/dev/src/zc/recipe/zope3instance/README.txt
===================================================================
--- zc.recipe.zope3instance/branches/dev/src/zc/recipe/zope3instance/README.txt 2006-10-30 12:10:22 UTC (rev 70994)
+++ zc.recipe.zope3instance/branches/dev/src/zc/recipe/zope3instance/README.txt 2006-10-30 12:13:58 UTC (rev 70995)
@@ -2,9 +2,53 @@
======================
The zc.recipe.zope3instance recipe creates a Zope 3 instance. A Zope
-3 instance is a collection of scripts and configure that define a Zope
-server process.
+3 instance is a collection of scripts and configuration that define a Zope
+server process. This recipe is likely to evolve quite a bit as our
+knowledge of how to deploy applications with eggs evolves. For
+example, we now need to know the location of a Zope 3 installation,
+however, in the future, we may be able to express our dependence on
+Zope3 soley via eggs.
+Note that, currently, this recipe is fairly unix-centric. Windows
+support will be added in the future.
+
+The zope3 instance recipe takes a number of options:
+
+eggs
+ Specify one or more distribution requirements, on separate lines,
+ for software to be included in the Zope instance.
+
+zope3
+ The name of a section defining a Zope3 installation location (as a
+ location option). This can be either a checkout or a release
+ installtion. (Unfortunately, we have to do some introspection to
+ determine whether a checkout or release installation is
+ provided.) Hopefully, this option will be unnecessary in the
+ future and we'll use egg depedencies to define the Zope software
+ used.
+
+database
+ The names of one or more sections defining databases to be used.
+ These sections must contain zconfig options giving configurations
+ for individual databases.
+
+address
+ One or more addresses to listed for HTTP connections on. Each
+ address of of the form "host:port" or just "port".
+
+user
+ A global management user of the form:
+ user:encyption:encrypted-password.
+
+zcml
+ Specifications for one or more zcml files to be loaded.
+
+options
+ Top-level ZConfig options to be used for the instance.
+
+In addition, the find-links, index, python, interpreter, and
+extra-paths options of the zc.recipe.egg recipe are honored.
+
Let's start with a minimal example. We have a sample buildout. Let's
write a buildout.cfg file that defines a zope instance:
@@ -35,9 +79,12 @@
The Zope3 instance recipe needs to be told the location of a Zope 3
installation. This can be done in two ways:
-1. Use a zope3checkout recipe to install Zope 3 from subversion, or
+1. Use a zope3checkout recipe to install Zope 3 from subversion,
-2. Create a section with an option that provides the location of a
+2. Use the configure-make-make-install recipe to install a Zope
+ release, or
+
+3. Create a section with an option that provides the location of a
Zope 3 installation.
@@ -52,7 +99,7 @@
Let's run the buildout:
>>> print system(join('bin', 'buildout')),
-xs
+
We'll get a directory created in the buildout parts directory
containing configuration files and some directories to contain og
files, pid files, and so on.
Modified: zc.recipe.zope3instance/branches/dev/src/zc/recipe/zope3instance/__init__.py
===================================================================
--- zc.recipe.zope3instance/branches/dev/src/zc/recipe/zope3instance/__init__.py 2006-10-30 12:10:22 UTC (rev 70994)
+++ zc.recipe.zope3instance/branches/dev/src/zc/recipe/zope3instance/__init__.py 2006-10-30 12:13:58 UTC (rev 70995)
@@ -1,138 +1,311 @@
-import os, re, shutil
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+import logging, os, re, shutil
+from xml.sax.saxutils import quoteattr
+
+import pkg_resources
+
import zc.buildout
import zc.recipe.egg
+logger = logging.getLogger('zc.recipe.zope3instance')
+
class Recipe:
# Need to think about the inheritence interface
# it *is* reasonable to think about instances as an
# extension of the basic egg/script-generation model.
def __init__(self, buildout, name, options):
- self.egg = zc.recipe.egg.Egg(buildout, name, options)
self.options, self.name = options, name
- options['zope3'] = options.get('zope3', 'zope3')
- options['database-config'] = buildout[options['database']]['zconfig']
- python = buildout['buildout']['python']
- options['zope3-directory'] = buildout[options['zope3']]['location']
options['location'] = os.path.join(
buildout['buildout']['parts-directory'],
self.name,
)
- options['scripts'] = '' # suppress script generation.
+
+ z3 = options.get('zope3', 'zope3')
+ z3path = buildout[z3]['location']
+ self.zope3 = z3path
+ if not os.path.exists(z3path):
+ raise zc.buildout.UserError("No directory:", z3path)
+ path = os.path.join(z3path, 'lib', 'python')
+ if not os.path.exists(path):
+ path = os.path.join(z3path, 'src')
+ if not os.path.exists(path):
+ logger.error(
+ "The directory, %r, isn't a valid checkout or release."
+ % z3)
+ raise zc.buildout.UserError(
+ "Invalid Zope 3 installation:", z3path)
+
+ skel = os.path.join(z3path, 'zopeskel', 'etc')
+ if not os.path.exists(skel):
+ logger.error("%r does not exists.", skel)
+ raise UserError("Invalid Zope 3 Installation", src)
+
+ if len(options['user'].split(':')) not in (2,3):
+ logger.error(
+ "The user option must specify a login name,"
+ " a password manager and a password.")
+ raise UserError("Invalud user, %r", options['user'])
+
+ extra = options.get('extra-paths')
+ if extra:
+ extra += '\n' + path
+ else:
+ extra = path
+
+ options['database-config'] = '\n'.join([
+ buildout[section]['zconfig']
+ for section in options['database'].split()
+ ])
+
+ options['bin-directory'] = buildout['buildout']['bin-directory']
+
+ zope_options = {}
+ for option in options.get('zope-options', '').split('\n'):
+ option = option.strip()
+ if not option:
+ continue
+ option = option.split(' ', 1)
+ if (len(option) == 1) or not option[1].strip():
+ logger.error('%s: zope-option, %s, has no value',
+ self.name, option[0]
+ )
+ raise zc.buildout.UserError("Invalid zope-option", option[0])
+ zope_options[option[0]] = option[1]
+
+ if 'interrupt-check-interval' not in zope_options:
+ zope_options['interrupt-check-interval'] = '200'
+
+ self.zope_options = zope_options
+
+ # Let the egg recipe do much of the heavy lifting.
+ options['scripts'] = ''
+ options['extra-paths'] = extra
+ options.pop('entry-points', None)
+ self.egg = zc.recipe.egg.Egg(buildout, name, options)
+
def install(self):
-
options = self.options
- location = options['location']
-
+ dest = options['location']
requirements, ws = self.egg.working_set()
- if os.path.exists(location):
+ os.mkdir(dest)
+ log_dir = run_dir = subprogram_dir = config_dir = dest
- # See is we can stop. We need to see if the working set path
- # has changed.
- saved_path_path = os.path.join(location, 'etc', '.eggs')
- if os.path.isfile(saved_path_path):
- if (open(saved_path_path).read() ==
- '\n'.join([d.location for d in ws])
- ):
- return location
+ site_zcml_path = os.path.join(config_dir, 'site.zcml')
- # The working set has changed. Blow away the instance.
- shutil.rmtree(location)
+ zope_options = self.zope_options
+ zope_options['site-definition'] = site_zcml_path
- # What follows is a bit of a hack because the instance-setup mechanism
- # is a bit monolithic. We'll run mkzopeinstabce and then we'll
- # patch the result. A better approach might be to provide independent
- # instance-creation logic, but this raises lots of issues that
- # need to be stored out first.
- mkzopeinstance = os.path.join(options['zope3-directory'],
- 'bin', 'mkzopeinstance')
+ zope_options = '\n '.join([
+ ' '.join(option)
+ for option in zope_options.iteritems()
+ ])
- assert os.spawnl(
- os.P_WAIT, options['executable'], options['executable'],
- mkzopeinstance, '-d', location, '-u', options['user'],
- '--non-interactive',
- ) == 0
+ addresses = options.get('address', '8080').split()
+ for address in addresses:
+ zope_options += server_template % address
- try:
- # Save the working set:
- open(os.path.join(location, 'etc', '.eggs'), 'w').write(
- '\n'.join([d.location for d in ws]))
+ # Install zope.conf
+ zope_conf_path = os.path.join(config_dir, 'zope.conf')
+ open(zope_conf_path, 'w').write(zope_conf_template % dict(
+ options = zope_options,
+ database = options['database-config'],
+ log_dir = log_dir,
+ ))
- # Now, patch the zodb option in zope.conf
- zope_conf_path = os.path.join(location, 'etc', 'zope.conf')
- zope_conf = open(zope_conf_path).read()
- zope_conf = (
- zope_conf[:zope_conf.find('<zodb>')]
- +
- options['database-config']
- +
- zope_conf[zope_conf.find('</zodb>')+7:]
+ # Install zdaemon.conf
+ zdaemon_conf_path = os.path.join(config_dir, 'zdaemon.conf')
+ open(zdaemon_conf_path, 'w').write(zdaemon_conf_template % dict(
+ subprogram_dir = subprogram_dir,
+ log_dir = log_dir,
+ run_dir = run_dir,
+ user = ''
+ ))
+
+ # Install zcml files
+ self._zcml(self.zope3, config_dir, options)
+
+ # install subprohrams and ctl scripts
+ zc.buildout.easy_install.scripts(
+ [('runzope', 'zope.app.twisted.main', 'main')],
+ ws, options['executable'], subprogram_dir,
+ extra_paths = options['extra-paths'].split(),
+ arguments = ('\n ["-C", %r]'
+ '\n + sys.argv[1:]'
+ % zope_conf_path),
+ )
+
+ # Install the scripts defined by this recipe, which adds entry points
+ # missing frm Zope itself.
+ requirements, ws = self.egg.working_set(['zc.recipe.zope3instance'])
+ zc.buildout.easy_install.scripts(
+ [('debugzope', 'zc.recipe.zope3instance.zope3scripts', 'debug'),
+ ('scriptzope', 'zc.recipe.zope3instance.zope3scripts', 'script'),
+ ],
+ ws, options['executable'], subprogram_dir,
+ extra_paths = options['extra-paths'].split(),
+ arguments = ('\n ["-C", %r]'
+ '\n + sys.argv[1:]'
+ % zope_conf_path),
+ )
+
+ zc.buildout.easy_install.scripts(
+ [(self.name, 'zc.recipe.zope3instance.ctl', 'main')],
+ ws, options['executable'], options['bin-directory'],
+ extra_paths = options['extra-paths'].split(),
+ arguments = ('\n %r,'
+ '\n %r,'
+ '\n ["-C", %r]'
+ '\n + sys.argv[1:]'
+ % (os.path.join(subprogram_dir, 'debugzope'),
+ os.path.join(subprogram_dir, 'scriptzope'),
+ zdaemon_conf_path)
+ ),
+ )
+
+ return dest, os.path.join(options['bin-directory'], self.name)
+
+ def _zcml(self, src, dest, options):
+ skel = os.path.join(src, 'zopeskel', 'etc')
+ for name in os.listdir(skel):
+ if name.endswith(".zcml"):
+ shutil.copy(os.path.join(skel, name), dest)
+
+ pzi = os.path.join(skel, 'principals.zcml.in')
+ if os.path.exists(pzi):
+ userdata = options['user'].split(':')
+ if len(userdata) == 2:
+ login, pw = userdata
+ pwmanager = "Plain Text"
+ else:
+ login, pwmanager, pw = userdata
+
+ open(os.path.join(dest, 'principals.zcml'), 'w').write(
+ open(pzi).read()
+ .replace('<<USERNAME-XMLATTR>>', quoteattr(login))
+ .replace('<<PASSWORD_MANAGER>>', pwmanager)
+ .replace('<<PASSWORD-XMLATTR>>', quoteattr(pw))
)
- open(zope_conf_path, 'w').write(zope_conf)
+
+ # add zcml files to package-includes
+ zcml = options['zcml'] or '*' # Require zcml but allow it to be empty
+ package_includes = os.path.join(dest, 'package-includes')
+ if zcml:
+ zcml = zcml.split()
+ if '*' in zcml:
+ zcml.remove('*')
+ shutil.copytree(os.path.join(src, 'package-includes'), dest)
+ else:
+ os.mkdir(package_includes)
- # Patch extra paths into binaries
- path = "\n '" + "',\n '".join([
- dist.location for dist in ws]) + "'\n "
- for script_name in 'runzope', 'debugzope', 'scriptzope':
- script_path = os.path.join(location, 'bin', script_name)
- script = open(script_path).read()
- # don't look :/
- script = script.replace(
- 'sys.path[:] = [',
- 'sys.path[:] = ['+path+'] + ['
- )
- open(script_path, 'w').write(script)
+ n = 0
+ package_match = re.compile('\w+([.]\w+)*$').match
+ for package in zcml:
+ n += 1
+ orig = package
+ if ':' in package:
+ package, filename = package.split(':')
+ else:
+ filename = None
- # finally, add zcml files to package-includes
- zcml = options.get('zcml')
- if zcml:
- includes_path = os.path.join(
- location, 'etc', 'package-includes')
- zcml = zcml.split()
- if '*' in zcml:
- zcml.remove('*')
+ if '-' in package:
+ package, suff = package.split('-')
+ if suff not in ('configure', 'meta', 'overrides'):
+ raise ValueError('Invalid zcml', orig)
else:
- shutil.rmtree(includes_path)
- os.mkdir(includes_path)
+ suff = 'configure'
- n = 0
- package_match = re.compile('\w+([.]\w+)*$').match
- for package in zcml:
- n += 1
- orig = package
- if ':' in package:
- package, filename = package.split(':')
- else:
- filename = None
+ if filename is None:
+ filename = suff + '.zcml'
- if '-' in package:
- package, suff = package.split('-')
- if suff not in ('configure', 'meta', 'overrides'):
- raise ValueError('Invalid zcml', orig)
- else:
- suff = 'configure'
+ if not package_match(package):
+ raise ValueError('Invalid zcml', orig)
- if filename is None:
- filename = suff + '.zcml'
+ path = os.path.join(
+ package_includes,
+ "%3.3d-%s-%s.zcml" % (n, package, suff),
+ )
+ open(path, 'w').write(
+ '<include package="%s" file="%s" />\n'
+ % (package, filename)
+ )
+
+ def update(self):
+ pass
- if not package_match(package):
- raise ValueError('Invalid zcml', orig)
- path = os.path.join(
- includes_path,
- "%3.3d-%s-%s.zcml" % (n, package, suff),
- )
- open(path, 'w').write(
- '<include package="%s" file="%s" />\n'
- % (package, filename)
- )
-
- except:
- # clean up
- shutil.rmtree(location)
- raise
-
- return location
+
+zope_conf_template = """\
+# This is the configuration file for the Zope Application Server.
+#
+# This file is generated. If you edit this file, your edits could
+# easily be lost.
+
+%(options)s
+
+%(database)s
+
+<accesslog>
+ <logfile>
+ path %(log_dir)s/access.log
+ </logfile>
+
+ <logfile>
+ path STDOUT
+ </logfile>
+</accesslog>
+
+<eventlog>
+ <logfile>
+ path %(log_dir)s/z3.log
+ formatter zope.exceptions.log.Formatter
+ </logfile>
+ <logfile>
+ path STDOUT
+ formatter zope.exceptions.log.Formatter
+ </logfile>
+</eventlog>
+"""
+
+zdaemon_conf_template = """\
+# Configuration file for the daemon that manages a Zope 3 process
+#
+# This file is generated. If you edit this file, your edits could
+# easily be lost.
+<runner>
+ program %(subprogram_dir)s/runzope
+ %(user)sdaemon on
+ transcript %(log_dir)s/transcript.log
+ socket-name %(run_dir)s/zopectlsock
+</runner>
+
+<eventlog>
+ <logfile>
+ path %(log_dir)s/z3.log
+ </logfile>
+</eventlog>
+"""
+
+server_template = """
+<server>
+ type HTTP
+# type PostmortemDebuggingHTTP
+ address %s
+</server>
+"""
Added: zc.recipe.zope3instance/branches/dev/src/zc/recipe/zope3instance/ctl.py
===================================================================
--- zc.recipe.zope3instance/branches/dev/src/zc/recipe/zope3instance/ctl.py 2006-10-30 12:10:22 UTC (rev 70994)
+++ zc.recipe.zope3instance/branches/dev/src/zc/recipe/zope3instance/ctl.py 2006-10-30 12:13:58 UTC (rev 70995)
@@ -0,0 +1,44 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Top-level controller for 'zopectl'.
+"""
+
+import os
+import zdaemon.zdctl
+
+class ZopectlCmd(zdaemon.zdctl.ZDCmd):
+
+ def do_debug(self, rest):
+ os.system(self._debugzope)
+
+ def help_debug(self):
+ print "debug -- Initialize the Zope application, providing a"
+ print " debugger object at an interactive Python prompt."
+
+ def do_run(self, arg):
+ os.system(self._scriptzope + ' ' + arg)
+
+ def help_run(self):
+ print "run <script> [args] -- run a Python script with the Zope "
+ print " environment set up. The script has "
+ print " 'root' exposed as the root container."
+
+
+def main(debugzope, scriptzope, args):
+
+ class Cmd(ZopectlCmd):
+ _debugzope = debugzope
+ _scriptzope = scriptzope
+
+ zdaemon.zdctl.main(args, None, Cmd)
Property changes on: zc.recipe.zope3instance/branches/dev/src/zc/recipe/zope3instance/ctl.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.recipe.zope3instance/branches/dev/src/zc/recipe/zope3instance/zope3scripts.py
===================================================================
--- zc.recipe.zope3instance/branches/dev/src/zc/recipe/zope3instance/zope3scripts.py 2006-10-30 12:10:22 UTC (rev 70994)
+++ zc.recipe.zope3instance/branches/dev/src/zc/recipe/zope3instance/zope3scripts.py 2006-10-30 12:13:58 UTC (rev 70995)
@@ -0,0 +1,58 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Zope 3 program entry points
+
+The Zope 3 scripts, scriptzope, and debugzope are distributed
+as templates, rather than as entry points. Here we provide entry-point
+versions.
+
+$Id$
+"""
+
+import os, sys
+import zope.app.debug
+import zope.app.twisted.main
+
+def zglobals(args):
+ db = zope.app.twisted.main.debug(args)
+ if "PYTHONSTARTUP" in os.environ:
+ execfile(os.environ["PYTHONSTARTUP"])
+
+ app = zope.app.debug.Debugger.fromDatabase(db)
+ return dict(
+ app = app,
+ debugger = app,
+ root = app.root(),
+ __name__ = '__main__',
+ )
+
+
+def script(args):
+ globs = zglobals(args[:2])
+ sys.argv[:] = args[2:]
+ globs['__file__'] = sys.argv[0]
+ execfile(sys.argv[0], globs)
+ sys.exit()
+
+banner = """Welcome to the Zope 3 "debugger".
+The application root object is available as the root variable.
+A Zope debugger instance is available as the debugger (aka app) variable.
+"""
+
+def debug(args):
+ globs = zglobals(args)
+ import code
+ code.interact(banner=banner, local=globs)
+
+
Property changes on: zc.recipe.zope3instance/branches/dev/src/zc/recipe/zope3instance/zope3scripts.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
More information about the Checkins
mailing list