[Zope3-checkins] CVS: Zope3/src/zope/app/generations/browser - __init__.py:1.1 configure.zcml:1.1 ftests.py:1.1 managers.pt:1.1 managers.py:1.1 tests.py:1.1

Jim Fulton jim at zope.com
Fri Apr 23 15:39:30 EDT 2004


Update of /cvs-repository/Zope3/src/zope/app/generations/browser
In directory cvs.zope.org:/tmp/cvs-serv14528/src/zope/app/generations/browser

Added Files:
	__init__.py configure.zcml ftests.py managers.pt managers.py 
	tests.py 
Log Message:
Added a UI under process management for managing database
generations. It is uuuuuuuugly. :) I hope someone makes it pirty.


=== Added File Zope3/src/zope/app/generations/browser/__init__.py ===
#


=== Added File Zope3/src/zope/app/generations/browser/configure.zcml ===
<zope:configure 
   xmlns:zope="http://namespaces.zope.org/zope"
   xmlns="http://namespaces.zope.org/browser"
   >

<page
    name="generations.html"
    menu="zmi_views" title="Database Schemas"
    for="zope.app.applicationcontrol.interfaces.IApplicationControl"
    class=".managers.Managers"
    template="managers.pt"
    permission="zope.ManageApplication"
    />

</zope:configure>


=== Added File Zope3/src/zope/app/generations/browser/ftests.py ===
import unittest

from zope.app.tests import ztapi
from zope.app.tests.functional import BrowserTestCase
from zope.app.generations.generations import SchemaManager, generations_key
from zope.app.generations.interfaces import ISchemaManager

class TestDatabaseSchema(BrowserTestCase):

    def test(self):
        BrowserTestCase.setUp(self)
        
        root = self.getRootFolder()._p_jar.root()
        appkey = 'zope.app.generations.demo'
        root[generations_key][appkey] = 0
        self.commit()
        manager = SchemaManager(0, 3, 'zope.app.generations.demo')

        ztapi.provideUtility(ISchemaManager, manager, appkey)

        response = self.publish('/++etc++process/@@generations.html',
                                basic='mgr:mgrpw')
        body = response.getBody()
        body = ' '.join(body.split())
        expect = ('<td>zope.app.generations.demo</td> '
                  '<td>0</td> <td>3</td> <td>0</td> '
                  '<td> <input type="submit" value=" evolve " '
                  'name="evolve-app-zope.app.generations.demo"> </td>')
        self.assert_(body.find(expect) > 0)

        response = self.publish('/++etc++process/@@generations.html'
                                '?evolve-app-zope.app.generations.demo=evolve',
                                basic='mgr:mgrpw')
        body = response.getBody()
        body = ' '.join(body.split())
        expect = ('<td>zope.app.generations.demo</td> '
                  '<td>0</td> <td>3</td> <td>1</td> '
                  '<td> <input type="submit" value=" evolve " '
                  'name="evolve-app-zope.app.generations.demo"> </td>')
        self.assert_(body.find(expect) > 0)

        response = self.publish('/++etc++process/@@generations.html'
                                '?evolve-app-zope.app.generations.demo=evolve',
                                basic='mgr:mgrpw')
        body = response.getBody()
        body = ' '.join(body.split())
        expect = ('<td>zope.app.generations.demo</td> '
                  '<td>0</td> <td>3</td> <td>2</td> '
                  '<td> <input type="submit" value=" evolve " '
                  'name="evolve-app-zope.app.generations.demo"> </td>')
        self.assert_(body.find(expect) > 0)

        response = self.publish('/++etc++process/@@generations.html'
                                '?evolve-app-zope.app.generations.demo=evolve',
                                basic='mgr:mgrpw')
        body = response.getBody()
        body = ' '.join(body.split())
        expect = ('<td>zope.app.generations.demo</td> '
                  '<td>0</td> <td>3</td> <td>3</td> '
                  '<td> <span>')
        self.assert_(body.find(expect) > 0)

        ztapi.unprovideUtility(ISchemaManager, appkey)

        
def test_suite():
    return unittest.makeSuite(TestDatabaseSchema)


=== Added File Zope3/src/zope/app/generations/browser/managers.pt ===
<html metal:use-macro="context/@@standard_macros/view" i18n:domain="zope">
<head>
<title metal:fill-slot="title">Database Generations</title>
</head>
<body>
<div metal:fill-slot="body">

Database generations

<form tal:attributes="action request/URL"
      tal:define="status view/evolve" 
      >

<p tal:condition="status">
<span tal:condition="status/to" i18n:translate=""
      >The database was updated to generation <span
      i18n:name=generation
      tal:content="status/to">2</span> for <span
            i18n:name=application
            tal:content="status/app"
            >foo.bar</span>.</span>
<span tal:condition="not: status/to" i18n:translate=""
      >The database is up to date for <span 
      i18n:name=application
      tal:content="status/app"
      >foo.bar</span>.</span>
</p>

<table border="1">

<tr>
    <th>Application</th>
    <th>Minimum Generation</th>
    <th>Maximum Generation</th>
    <th>Current Database Generation</th>
    <th>Evolve?</th>
</tr>
<tr tal:repeat="app view/applications">
    <td tal:content="app/id">foo.bar</td>
    <td tal:content="app/min">1</td>
    <td tal:content="app/max">10</td>
    <td tal:content="app/generation">2</td>
    <td>
       <input type="submit" value=" evolve " name="evolve"
              tal:condition="app/evolve"
              tal:attributes="name app/evolve"
              >
       <span tal:condition="not: app/evolve"
             i18n:translate=""
             >No, up to date</span>
    </td>
</tr>
</table>
</form>
</div>
</body>
</html>


=== Added File Zope3/src/zope/app/generations/browser/managers.py ===
##############################################################################
#
# Copyright (c) 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""UI for browsing database schema managers

$Id: managers.py,v 1.1 2004/04/23 19:39:29 jim Exp $
"""

from zope.app import zapi
from zope.app.generations.interfaces import ISchemaManager
from zope.app.generations.generations import generations_key, Context
from zope.app.i18n import ZopeMessageIDFactory as _

request_key_format = "evolve-app-%s"

class Managers:

    def __init__(self, context, request):
        self.context = context
        self.request = request

    def _getdb(self):
        # XXX There needs to be a better api for this
        return self.request.publication.db

    def evolve(self):
        """Perform a requested evolution 

           This method needs to use the component architecture, so
           we'll set it up:

             >>> from zope.app.tests.placelesssetup import setUp, tearDown
             >>> setUp()

           We also need a test request:

             >>> from zope.publisher.browser import TestRequest
             >>> request = TestRequest()

           We also need to give it a publication with a database:

             >>> class Publication:
             ...     pass

             >>> request.setPublication(Publication())
             >>> from ZODB.tests.util import DB
             >>> db = DB()
             >>> request.publication.db = db

           We need to define some schema managers.  We'll define two
           using the demo package:

             >>> from zope.app.generations.generations import SchemaManager
             >>> from zope.app.tests import ztapi
             >>> app1 = SchemaManager(0, 1, 'zope.app.generations.demo')
             >>> ztapi.provideUtility(ISchemaManager, app1, 'foo.app1')
             >>> app2 = SchemaManager(0, 0, 'zope.app.generations.demo')
             >>> ztapi.provideUtility(ISchemaManager, app2, 'foo.app2')

           And we need to record some data for them in the database.

             >>> from zope.app.generations.generations import evolve
             >>> evolve(db)

           This sets up the data and actually evolves app1:

             >>> conn = db.open()
             >>> conn.root()[generations_key]['foo.app1']
             1
             >>> conn.root()[generations_key]['foo.app2']
             0

           To evolve a data base schema, the user clicks on a submit
           button. If they click on the button for add1, a item will
           be added to the request, which we simulate:

             >>> request.form['evolve-app-foo.app1'] = 'evolve'

           We'll also increase the generation of app1:

             >>> app1.generation = 2
             
           Now we can create our view:

             >>> view = Managers(None, request)

           Now, if we call it's evolve method, it should see that the
           app1 evolve button was pressed and evolve app1 the thect
           generation.

             >>> status = view.evolve()
             >>> conn.sync()
             >>> conn.root()[generations_key]['foo.app1']
             2

           The demo evolver just writes the generation to a database key:
           
             >>> from zope.app.generations.demo import key
             >>> conn.root()[key]
             (2,)

           Which the returned status should indicate:

             >>> status['app']
             u'foo.app1'
             >>> status['to']
             2

           Now, given that the database is at the maximum generation
           for app1, we can't evolve it further.  Calling evolve again
           won't evolve anything:

             >>> status = view.evolve()
             >>> conn.sync()
             >>> conn.root()[generations_key]['foo.app1']
             2
             >>> conn.root()[key]
             (2,)

           as the status will indicate by returning a 'to' generation
           of 0:

             >>> status['app']
             u'foo.app1'
             >>> status['to']
             0

           If the request doesn't have the key:

             >>> request.form.clear()

           Then calling evolve does nothing:

             >>> view.evolve()
             >>> conn.sync()
             >>> conn.root()[generations_key]['foo.app1']
             2
             >>> conn.root()[key]
             (2,)
           
           We'd better clean upp:

             >>> db.close()
             >>> tearDown()
           """

        self.managers = managers = dict(
            zapi.getUtilitiesFor(None, ISchemaManager))
        db = self._getdb()
        conn = db.open()
        try:
            generations = conn.root().get(generations_key, ())
            request = self.request
            for key in generations:
                generation = generations[key]
                rkey = request_key_format % key
                if rkey in request:
                    manager = managers[key]
                    if generation >= manager.generation:
                        return {'app': key, 'to': 0}
                    context = Context()
                    context.connection = conn
                    generation += 1
                    manager.evolve(context, generation)
                    generations[key] = generation
                    get_transaction().commit()
                    return {'app': key, 'to': generation}

            return None
        finally:
            get_transaction().abort()
            conn.close()

    def applications(self):
        """Get information about database-generation status

           This method needs to use the component architecture, so
           we'll set it up:

             >>> from zope.app.tests.placelesssetup import setUp, tearDown
             >>> setUp()

           We also need a test request:

             >>> from zope.publisher.browser import TestRequest
             >>> request = TestRequest()

           We also need to give it a publication with a database:

             >>> class Publication:
             ...     pass

             >>> request.setPublication(Publication())
             >>> from ZODB.tests.util import DB
             >>> db = DB()
             >>> request.publication.db = db

           We need to define some schema managers.  We'll define two
           using the demo package:

             >>> from zope.app.generations.generations import SchemaManager
             >>> from zope.app.tests import ztapi
             >>> app1 = SchemaManager(0, 1, 'zope.app.generations.demo')
             >>> ztapi.provideUtility(ISchemaManager, app1, 'foo.app1')
             >>> app2 = SchemaManager(0, 0, 'zope.app.generations.demo')
             >>> ztapi.provideUtility(ISchemaManager, app2, 'foo.app2')

           And we need to record some data for them in the database.

             >>> from zope.app.generations.generations import evolve
             >>> evolve(db)

           This sets up the data and actually evolves app1:

             >>> conn = db.open()
             >>> conn.root()[generations_key]['foo.app1']
             1
             >>> conn.root()[generations_key]['foo.app2']
             0

           Now, let's increment app1's generation:

             >>> app1.generation += 1

           so we can evolve it.
             
           Now we can create our view:

             >>> view = Managers(None, request)

           We call it's applications method to get data about
           application generations. We are required to call evolve
           first:

             >>> view.evolve()
             >>> data = list(view.applications())
             >>> data.sort(lambda d1, d2: cmp(d1['id'], d2['id']))

             >>> for info in data:
             ...     print info['id']
             ...     print info['min'], info['max'], info['generation']
             ...     print 'evolve?', info['evolve']
             foo.app1
             0 2 1
             evolve? evolve-app-foo.app1
             foo.app2
             0 0 0
             evolve? 

           We'd better clean upp:

             >>> db.close()
             >>> tearDown()
           """
        result = []

        db = self._getdb()
        conn = db.open()
        try:
            managers = self.managers
            generations = conn.root().get(generations_key, ())
            for key in generations:
                generation = generations[key]
                manager = managers.get(key)
                if manager is None:
                    continue
                
                result.append({
                    'id': key,
                    'min': manager.minimum_generation,
                    'max': manager.generation,
                    'generation': generation,
                    'evolve': (generation < manager.generation
                               and request_key_format % key
                               or ''
                               ),
                    })

            return result
        finally:
            conn.close()


=== Added File Zope3/src/zope/app/generations/browser/tests.py ===
##############################################################################
#
# Copyright (c) 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""Generation-browser tests

$Id: tests.py,v 1.1 2004/04/23 19:39:29 jim Exp $
"""
import unittest
from zope.testing.doctestunit import DocTestSuite


def test_suite():
    return unittest.TestSuite((
        DocTestSuite('zope.app.generations.browser.managers'),
        ))

if __name__ == '__main__':
    unittest.main(defaultTest='test_suite')





More information about the Zope3-Checkins mailing list