[Checkins] SVN: zc.zope3recipes/trunk/ svn merge -r123131:123630 svn+ssh://svn.zope.org/repos/main/zc.zope3recipes/branches/satchit-offline-recipe

Andrew Sung asung at zope.com
Thu Dec 8 17:00:58 UTC 2011


Log message for revision 123631:
  svn merge -r123131:123630 svn+ssh://svn.zope.org/repos/main/zc.zope3recipes/branches/satchit-offline-recipe
  

Changed:
  U   zc.zope3recipes/trunk/README.txt
  U   zc.zope3recipes/trunk/setup.py
  U   zc.zope3recipes/trunk/zc/zope3recipes/README.txt
  U   zc.zope3recipes/trunk/zc/zope3recipes/recipes.py
  U   zc.zope3recipes/trunk/zc/zope3recipes/tests.py

-=-
Modified: zc.zope3recipes/trunk/README.txt
===================================================================
--- zc.zope3recipes/trunk/README.txt	2011-12-08 16:49:27 UTC (rev 123630)
+++ zc.zope3recipes/trunk/README.txt	2011-12-08 17:00:58 UTC (rev 123631)
@@ -1,6 +1,6 @@
-**************************************
-Zope3 Application and Instance Recipes
-**************************************
+***********************************************
+Zope3 Application, Instance and Offline Recipes
+***********************************************
 
 Recipes for creating Zope 3 instances with distinguishing features:
 
@@ -10,6 +10,8 @@
 
 - Don't support package-includes
 
+- Support offline instance.
+
 Unfortunately, partial Windows support at this time. It works but it's alpha.
 
 .. contents::
@@ -25,6 +27,8 @@
 - Execute $PYTHONSTARTUP in the environment that the user will interact
   with in zc.zope3recipes.debugzope; this mirrors how $PYTHONSTARTUP is
   used with an interactive interpreter.
+- Added a recipe for offline instance.
+- Fixed tests to pass with zc.buildout >= v1.5
 
 ===================
 0.13.0 (2010/11/24)

Modified: zc.zope3recipes/trunk/setup.py
===================================================================
--- zc.zope3recipes/trunk/setup.py	2011-12-08 16:49:27 UTC (rev 123630)
+++ zc.zope3recipes/trunk/setup.py	2011-12-08 17:00:58 UTC (rev 123631)
@@ -39,6 +39,7 @@
              'application = %s.recipes:Application' % name,
              'app = %s.recipes:App' % name,
              'instance = %s.recipes:Instance' % name,
+             'offline = %s.recipes:Offline' %name,
              ]
         },
     extras_require = dict(

Modified: zc.zope3recipes/trunk/zc/zope3recipes/README.txt
===================================================================
--- zc.zope3recipes/trunk/zc/zope3recipes/README.txt	2011-12-08 16:49:27 UTC (rev 123630)
+++ zc.zope3recipes/trunk/zc/zope3recipes/README.txt	2011-12-08 17:00:58 UTC (rev 123631)
@@ -1,6 +1,6 @@
-=============
-Zope3 Recipes
-=============
+===============
+ Zope3 Recipes
+===============
 
 The Zope 3 recipes allow one to define Zope applications and instances
 of those applications.  A Zope application is a collection of software
@@ -456,9 +456,15 @@
     Generated script '/sample-buildout/parts/myapp/runzope'.
     Generated script '/sample-buildout/parts/myapp/debugzope'.
 
-A directory is created in the parts directory for our application files:
+A directory is created in the parts directory for our application
+files. Starting with zc.buildout >= v1.5, and distribute, a "buildout"
+directory is created in the parts folder. Since the minimum version we support
+for zc.buildout is lower than v1.5, we use a custom "ls" functional called
+"ls_optional" to which we pass a list of folders that may be present. These are
+ignore by the function.
 
-    >>> ls('parts')
+    >>> from zc.zope3recipes.tests import ls_optional
+    >>> ls_optional('parts', ignore=('buildout',))
     d  myapp
 
     >>> ls('parts', 'myapp')
@@ -1000,7 +1006,7 @@
 
 We get new directories for our database and instance:
 
-    >>> ls('parts')
+    >>> ls_optional('parts', ignore=('buildout',))
     d  database
     d  instance
     d  myapp
@@ -1949,7 +1955,7 @@
 
 The installer files will move.  We'll no-longer have the instance part:
 
-    >>> ls('parts')
+    >>> ls_optional('parts', ignore=('buildout',))
     d  database
     d  myapp
 
@@ -2458,3 +2464,383 @@
             '-C', join(base, 'parts/instance/zdaemon.conf'),
             ]+sys.argv[1:]
             )
+
+
+Offline recipe
+==============
+
+The offline recipe creates a script that in some ways is a syntactic sugar for
+"bin/instance debug" or "bin/instance run <script>". With the offline script,
+all you do is "bin/offline" or "bin/offline </script>". This script doesn't
+create additional folders like the ``Instance`` recipe; it expects two options:
+"application" and "zope.conf" that must be sections for a Zope3 application and
+a configuration file (that supports a "location" option) to exist.
+
+    >>> 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 instance.
+    Uninstalling myapp.
+    Uninstalling database.
+    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.getuid():
+            restart = True
+            argv[:0] = ["sudo", "-u", None]
+            # print "switching to user", 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..."
+    execfile(debugzope)
+
+
+``initialization`` option
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The recipe also accepts an "initialization" option:
+
+    >>> 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.getuid():
+            restart = True
+            argv[:0] = ["sudo", "-u", None]
+            # print "switching to user", 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..."
+    execfile(debugzope)
+
+
+``script`` option
+~~~~~~~~~~~~~~~~~
+
+as well as a "script" option.
+
+    >>> 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.getuid():
+            restart = True
+            argv[:0] = ["sudo", "-u", None]
+            # print "switching to user", 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>
+        ]
+    <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..."
+    execfile(debugzope)
+

Modified: zc.zope3recipes/trunk/zc/zope3recipes/recipes.py
===================================================================
--- zc.zope3recipes/trunk/zc/zope3recipes/recipes.py	2011-12-08 16:49:27 UTC (rev 123630)
+++ zc.zope3recipes/trunk/zc/zope3recipes/recipes.py	2011-12-08 17:00:58 UTC (rev 123631)
@@ -16,6 +16,7 @@
 
 import os, sys, shutil
 import logging
+import pprint
 import zc.buildout
 import zc.recipe.egg
 import pkg_resources
@@ -501,3 +502,118 @@
   <grant role="zope.Manager" principal="zope.globalmgr" />
 </configure>
 """
+
+
+class Offline(object):
+
+    def __init__(self, buildout, name, options):
+        self.name, self.options = name, options
+        deployment = options.get("deployment")
+        if deployment:
+            deployment = buildout[deployment]
+        if deployment is not None and "user" not in options:
+            options["user"] = deployment["user"]
+        if "directory" not in options:
+            if deployment is None:
+                directory = buildout["buildout"]["bin-directory"]
+            else:
+                directory = deployment["etc-directory"]
+            options["directory"] = directory
+        options["dest"] = os.path.join(directory, name)
+        env = options.get("environment")
+        if env:
+            self.environment = dict(buildout[env])
+        else:
+            self.environment = {}
+        app = buildout[options["application"]]
+        options["application-location"] = app["location"]
+        options["executable"] = app["executable"]
+        zope_conf = buildout[options["zope.conf"]]
+        options["zope.conf-location"] =  zope_conf["location"]
+        script = options.get("script")
+        if script:
+            script = os.path.join(buildout["buildout"]["directory"], script)
+            options["script"] = script
+
+    def update(self):
+        self.install()
+
+    def install(self):
+        options = self.options
+
+        debugzope = os.path.join(
+            options["application-location"], "debugzope")
+        config = options["zope.conf-location"]
+        script = options.get("script") or ""
+        if script:
+            script = repr(script)
+
+        initialization = options.get("initialization", "").strip()
+
+        script_content = template % dict(
+            config=config,
+            debugzope=debugzope,
+            executable=options["executable"],
+            environment=pprint.pformat(self.environment),
+            initialization=initialization,
+            script=script,
+            user=options.get("user"),
+            )
+
+        dest = options["dest"]
+        f = open(dest, "w")
+        f.write(script_content)
+        f.close()
+        os.chmod(dest, 0775)
+        return [dest]
+
+template = '''\
+#!%(executable)s
+
+import os
+import sys
+import logging
+
+argv = list(sys.argv)
+env = %(environment)s
+restart = False
+
+if %(user)r:
+    import pwd
+    if pwd.getpwnam(%(user)r).pw_uid != os.getuid():
+        restart = True
+        argv[:0] = ["sudo", "-u", %(user)r]
+        # print "switching to user", %(user)r
+    del pwd
+
+for k in env:
+    if os.environ.get(k) != env[k]:
+        os.environ[k] = env[k]
+        restart = True
+    del k
+
+if restart:
+    # print "restarting"
+    os.execvpe(argv[0], argv, dict(os.environ))
+
+del argv
+del env
+del restart
+
+sys.argv[1:1] = [
+    "-C",
+    %(config)r,
+    %(script)s
+    ]
+
+debugzope = %(debugzope)r
+globals()["__file__"] = debugzope
+
+zeo_logger = logging.getLogger('ZEO.zrpc')
+zeo_logger.addHandler(logging.StreamHandler())
+
+%(initialization)s
+
+# print "starting debugzope..."
+execfile(debugzope)
+'''

Modified: zc.zope3recipes/trunk/zc/zope3recipes/tests.py
===================================================================
--- zc.zope3recipes/trunk/zc/zope3recipes/tests.py	2011-12-08 16:49:27 UTC (rev 123630)
+++ zc.zope3recipes/trunk/zc/zope3recipes/tests.py	2011-12-08 17:00:58 UTC (rev 123631)
@@ -19,6 +19,21 @@
 import unittest
 from zope.testing import doctest, renormalizing
 
+def ls_optional(dir, ignore=(), *subs):
+    if subs:
+        dir = os.path.join(dir, *subs)
+    names = os.listdir(dir)
+    names.sort()
+    for name in names:
+        if name in ignore:
+            continue
+        if os.path.isdir(os.path.join(dir, name)):
+            print 'd ',
+        elif os.path.islink(os.path.join(dir, name)):
+            print 'l ',
+        else:
+            print '- ',
+        print name
 
 def test_ctl():
     """



More information about the checkins mailing list