[Checkins] SVN: grok/trunk/ - added application object
Christian Theune
ct at gocept.com
Wed Feb 7 01:20:15 EST 2007
Log message for revision 72409:
- added application object
- added *very* minimal admin ui
Changed:
D grok/trunk/grokwiki/src/grokwiki/configure.zcml
U grok/trunk/grokwiki/src/grokwiki/wiki.py
U grok/trunk/ldapaddressbook/src/ldapaddressbook/addressbook.py
U grok/trunk/src/grok/__init__.py
A grok/trunk/src/grok/admin/
A grok/trunk/src/grok/admin/README.txt
A grok/trunk/src/grok/admin/__init__.py
A grok/trunk/src/grok/admin/configure.zcml
A grok/trunk/src/grok/admin/manage.pt
A grok/trunk/src/grok/admin/view.py
U grok/trunk/src/grok/components.py
U grok/trunk/src/grok/configure.zcml
A grok/trunk/src/grok/ftests/admin/
A grok/trunk/src/grok/ftests/admin/__init__.py
A grok/trunk/src/grok/ftests/admin/admin.py
U grok/trunk/src/grok/ftests/form/templateform.py
U grok/trunk/src/grok/ftests/test_grok_functional.py
U grok/trunk/src/grok/interfaces.py
U grok/trunk/src/grok/meta.py
A grok/trunk/src/grok/tests/application/
A grok/trunk/src/grok/tests/application/__init__.py
A grok/trunk/src/grok/tests/application/application.py
U grok/trunk/src/grok/tests/test_grok.py
-=-
Deleted: grok/trunk/grokwiki/src/grokwiki/configure.zcml
===================================================================
--- grok/trunk/grokwiki/src/grokwiki/configure.zcml 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/grokwiki/src/grokwiki/configure.zcml 2007-02-07 06:20:13 UTC (rev 72409)
@@ -1,15 +0,0 @@
-<configure
- xmlns="http://namespaces.zope.org/zope"
- xmlns:browser="http://namespaces.zope.org/browser"
- xmlns:grok="http://namespaces.zope.org/grok"
- i18n_domain="grok"
- >
- <grok:grok package="."/>
-
- <browser:addMenuItem
- class=".wiki.Wiki"
- title="GROK WIKI"
- description="GROK NOW WIKI"
- permission="zope.ManageContent"
- />
-</configure>
Modified: grok/trunk/grokwiki/src/grokwiki/wiki.py
===================================================================
--- grok/trunk/grokwiki/src/grokwiki/wiki.py 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/grokwiki/src/grokwiki/wiki.py 2007-02-07 06:20:13 UTC (rev 72409)
@@ -17,7 +17,7 @@
import grok
import grokwiki.page
-class Wiki(grok.Container):
+class Wiki(grok.Application):
"""This is our wiki application wich contains all wiki pages."""
class Index(grok.View):
Modified: grok/trunk/ldapaddressbook/src/ldapaddressbook/addressbook.py
===================================================================
--- grok/trunk/ldapaddressbook/src/ldapaddressbook/addressbook.py 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/ldapaddressbook/src/ldapaddressbook/addressbook.py 2007-02-07 06:20:13 UTC (rev 72409)
@@ -30,7 +30,7 @@
-class AddressBook(grok.Model):
+class AddressBook(grok.Application):
def traverse(self, name):
contact = Contact(name)
Modified: grok/trunk/src/grok/__init__.py
===================================================================
--- grok/trunk/src/grok/__init__.py 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/src/grok/__init__.py 2007-02-07 06:20:13 UTC (rev 72409)
@@ -33,6 +33,7 @@
from grok.components import Model, Adapter, MultiAdapter, View, XMLRPC
from grok.components import PageTemplate, PageTemplateFile, Container, Traverser
from grok.components import Site, GlobalUtility, LocalUtility, Annotation
+from grok.components import Application
from grok.components import EditForm, DisplayForm, AddForm
from grok.directive import (context, name, template, templatedir, provides,
baseclass, global_utility, local_utility,
Added: grok/trunk/src/grok/admin/README.txt
===================================================================
--- grok/trunk/src/grok/admin/README.txt 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/src/grok/admin/README.txt 2007-02-07 06:20:13 UTC (rev 72409)
@@ -0,0 +1,9 @@
+A basic grok admin UI.
+
+- Overview
+
+ - list of all instanciated applications (grouped by application?)
+
+ - "Add new application" form: drop down for selecting the application and
+ a field for the id.
+
Property changes on: grok/trunk/src/grok/admin/README.txt
___________________________________________________________________
Name: svn:keywords
+ Id Rev Date
Name: svn:eol-style
+ native
Added: grok/trunk/src/grok/admin/__init__.py
===================================================================
--- grok/trunk/src/grok/admin/__init__.py 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/src/grok/admin/__init__.py 2007-02-07 06:20:13 UTC (rev 72409)
@@ -0,0 +1 @@
+#make this a package
Property changes on: grok/trunk/src/grok/admin/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id Rev Date
Name: svn:eol-style
+ native
Added: grok/trunk/src/grok/admin/configure.zcml
===================================================================
--- grok/trunk/src/grok/admin/configure.zcml 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/src/grok/admin/configure.zcml 2007-02-07 06:20:13 UTC (rev 72409)
@@ -0,0 +1,19 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:browser="http://namespaces.zope.org/browser">
+
+ <browser:pages
+ for="zope.app.folder.interfaces.IRootFolder"
+ class=".view.Admin"
+ permission="zope.ManageApplication">
+ <browser:page
+ template="manage.pt"
+ name="index.html"
+ />
+ <browser:page
+ name="add"
+ attribute="add"
+ />
+ </browser:pages>
+
+</configure>
Property changes on: grok/trunk/src/grok/admin/configure.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: grok/trunk/src/grok/admin/manage.pt
===================================================================
--- grok/trunk/src/grok/admin/manage.pt 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/src/grok/admin/manage.pt 2007-02-07 06:20:13 UTC (rev 72409)
@@ -0,0 +1,40 @@
+<html>
+ <head>
+ <title>grok administration interface</title>
+ </head>
+
+ <body>
+ <h1>Installed applications</h1>
+
+ <ul>
+ <li tal:repeat="app context/values">
+ <a tal:attributes="href string:${context/@@absolute_url}/${app/__name__}">
+ <span tal:replace="app/__name__"/>
+ (<span tal:replace="app/__class__/__name__"/>)
+ </a>
+ </li>
+ </ul>
+
+ <form tal:attributes="action string:${context/@@absolute_url}/add">
+ <fieldset>
+ <legend>Add application</legend>
+
+ <p>
+ <label>Application:
+ <select height="1" name="application">
+ <option tal:repeat="app view/applications"
+ tal:attributes="value app"
+ tal:content="app"
+ />
+ </select>
+ </label>
+ </p>
+
+ <p><label>Name: <input type="text" name="name"/></label></p>
+
+ <p><input type="submit" value="Add"/></p>
+
+ </fieldset>
+ </form>
+ </body>
+</html>
Property changes on: grok/trunk/src/grok/admin/manage.pt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: grok/trunk/src/grok/admin/view.py
===================================================================
--- grok/trunk/src/grok/admin/view.py 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/src/grok/admin/view.py 2007-02-07 06:20:13 UTC (rev 72409)
@@ -0,0 +1,25 @@
+import zope.component
+import grok.interfaces
+
+from zope.app import zapi
+
+
+class Admin(object):
+
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+
+ @property
+ def applications(self):
+ apps = zope.component.getAllUtilitiesRegisteredFor(
+ grok.interfaces.IApplication)
+ return ["%s.%s" % (x.__module__, x.__name__)
+ for x in apps]
+
+ def add(self, application, name):
+ app = zope.component.getUtility(grok.interfaces.IApplication,
+ name=application)
+ self.context[name] = app()
+ self.request.response.redirect(zapi.absoluteURL(self.context,
+ self.request))
Property changes on: grok/trunk/src/grok/admin/view.py
___________________________________________________________________
Name: svn:keywords
+ Id Rev Date
Name: svn:eol-style
+ native
Modified: grok/trunk/src/grok/components.py
===================================================================
--- grok/trunk/src/grok/components.py 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/src/grok/components.py 2007-02-07 06:20:13 UTC (rev 72409)
@@ -111,6 +111,10 @@
pass
+class Application(Site, Container):
+ """A top-level application object."""
+
+
class Adapter(object):
def __init__(self, context):
Modified: grok/trunk/src/grok/configure.zcml
===================================================================
--- grok/trunk/src/grok/configure.zcml 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/src/grok/configure.zcml 2007-02-07 06:20:13 UTC (rev 72409)
@@ -42,4 +42,6 @@
priority="11"
/>
+ <include package=".admin"/>
+
</configure>
Added: grok/trunk/src/grok/ftests/admin/__init__.py
===================================================================
--- grok/trunk/src/grok/ftests/admin/__init__.py 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/src/grok/ftests/admin/__init__.py 2007-02-07 06:20:13 UTC (rev 72409)
@@ -0,0 +1 @@
+# this is a package
Property changes on: grok/trunk/src/grok/ftests/admin/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id Rev Date
Name: svn:eol-style
+ native
Added: grok/trunk/src/grok/ftests/admin/admin.py
===================================================================
--- grok/trunk/src/grok/ftests/admin/admin.py 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/src/grok/ftests/admin/admin.py 2007-02-07 06:20:13 UTC (rev 72409)
@@ -0,0 +1,43 @@
+"""
+ >>> import grok
+ >>> grok.grok('grok.ftests.admin.admin')
+
+ >>> from zope.testbrowser.testing import Browser
+ >>> browser = Browser()
+ >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+ >>> browser.handleErrors = False
+ >>> browser.open("http://localhost/")
+ >>> print browser.contents
+ <html>
+ ...
+ <h1>Installed applications</h1>
+ ...
+ <legend>Add application</legend>
+ ...
+ >>> browser.getControl('Application').displayValue = ['grok.ftests.admin.admin.MammothManager']
+ >>> browser.getControl('Name').value = 'my-mammoth-manager'
+ >>> browser.getControl('Add').click()
+ >>> print browser.contents
+ <html>
+ ...
+ <li>
+ <a href="http://localhost/my-mammoth-manager">
+ my-mammoth-manager
+ (MammothManager)
+ </a>
+ </li>
+ ...
+ >>> browser.getLink('my-mammoth-manager').click()
+ >>> print browser.contents
+ Let's manage some mammoths!
+
+"""
+import grok
+
+class MammothManager(grok.Application):
+ pass
+
+class Index(grok.View):
+
+ def render(self):
+ return u"Let's manage some mammoths!"
Property changes on: grok/trunk/src/grok/ftests/admin/admin.py
___________________________________________________________________
Name: svn:keywords
+ Id Rev Date
Name: svn:eol-style
+ native
Modified: grok/trunk/src/grok/ftests/form/templateform.py
===================================================================
--- grok/trunk/src/grok/ftests/form/templateform.py 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/src/grok/ftests/form/templateform.py 2007-02-07 06:20:13 UTC (rev 72409)
@@ -45,7 +45,7 @@
class Edit(grok.EditForm):
pass
-
+
class Edit2(grok.EditForm):
pass
Modified: grok/trunk/src/grok/ftests/test_grok_functional.py
===================================================================
--- grok/trunk/src/grok/ftests/test_grok_functional.py 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/src/grok/ftests/test_grok_functional.py 2007-02-07 06:20:13 UTC (rev 72409)
@@ -58,7 +58,7 @@
def test_suite():
suite = unittest.TestSuite()
for name in ['view', 'static', 'xmlrpc', 'traversal', 'form', 'url',
- 'security', 'utility', 'catalog']:
+ 'security', 'utility', 'catalog', 'admin']:
suite.addTest(suiteFromPackage(name))
return suite
Modified: grok/trunk/src/grok/interfaces.py
===================================================================
--- grok/trunk/src/grok/interfaces.py 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/src/grok/interfaces.py 2007-02-07 06:20:13 UTC (rev 72409)
@@ -26,6 +26,7 @@
"(models).")
Container = interface.Attribute("Base class for containers.")
Site = interface.Attribute("Mixin class for sites.")
+ Application = interface.Attribute("Base class for applications.")
Adapter = interface.Attribute("Base class for adapters.")
MultiAdapter = interface.Attribute("Base class for multi-adapters.")
Annotation = interface.Attribute("Base class for persistent annotations.")
@@ -37,7 +38,8 @@
EditForm = interface.Attribute("Base class for edit forms.")
DisplayForm = interface.Attribute("Base class for display forms.")
AddForm = interface.Attribute("Base class for add forms.")
-
+
+
class IGrokErrors(interface.Interface):
def GrokError(message, component):
@@ -47,6 +49,7 @@
def GrokImportError(*args):
"""Error indicating a problem at import time."""
+
class IGrokDirectives(interface.Interface):
def implements(*interfaces):
@@ -91,7 +94,7 @@
This means it won't be grokked, though if it's a possible context,
it can still serve as a context.
"""
-
+
def global_utility(factory, provides=None, name=u''):
"""Register a global utility.
@@ -127,6 +130,7 @@
grok.require can be used as a class-level directive or as a
method decorator."""
+
class IGrokDecorators(interface.Interface):
def subscribe(*classes_or_interfaces):
@@ -139,6 +143,7 @@
traverse = interface.Attribute("Specify a method to be used for "
"traversing URL paths.")
+
class IGrokEvents(interface.Interface):
IObjectCreatedEvent = interface.Attribute("")
@@ -169,6 +174,7 @@
ContainerModifiedEvent = interface.Attribute("")
+
class IGrokAPI(IGrokBaseClasses, IGrokDirectives, IGrokDecorators,
IGrokEvents, IGrokErrors):
@@ -197,11 +203,12 @@
def AutoFields(context):
"""Return a list of fields for context autogenerated by grok.
"""
-
+
def action(label, actions=None, **options):
"""grok-specific action decorator.
"""
+
class IGrokView(interface.Interface):
"""Grok views all provide this interface.
"""
@@ -221,3 +228,12 @@
If both object and name arguments are supplied, construct
URL to obj/name.
"""
+
+
+class IApplication(interface.Interface):
+ """Marker-interface for grok application factories.
+
+ Used to register applications as utilities to look them up and
+ provide a list of grokked applications.
+
+ """
Modified: grok/trunk/src/grok/meta.py
===================================================================
--- grok/trunk/src/grok/meta.py 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/src/grok/meta.py 2007-02-07 06:20:13 UTC (rev 72409)
@@ -26,14 +26,17 @@
def register(self, context, name, factory, module_info, templates):
for field in formlib.get_context_schema_fields(factory):
- setattr(factory, field.__name__, field.default)
+ setattr(factory, field.__name__, field.default)
+
class ContainerGrokker(ModelGrokker):
component_class = grok.Container
-
+
+
class LocalUtilityGrokker(ModelGrokker):
component_class = grok.LocalUtility
-
+
+
class AdapterGrokker(grok.ClassGrokker):
component_class = grok.Adapter
@@ -47,9 +50,10 @@
provides=provides,
name=name)
+
class MultiAdapterGrokker(grok.ClassGrokker):
component_class = grok.MultiAdapter
-
+
def register(self, context, name, factory, module_info, templates):
provides = util.class_annotation(factory, 'grok.provides', None)
if provides is None:
@@ -58,6 +62,7 @@
name = util.class_annotation(factory, 'grok.name', '')
component.provideAdapter(factory, provides=provides, name=name)
+
class GlobalUtilityGrokker(grok.ClassGrokker):
component_class = grok.GlobalUtility
@@ -68,6 +73,7 @@
name = util.class_annotation(factory, 'grok.name', '')
component.provideUtility(factory(), provides=provides, name=name)
+
class XMLRPCGrokker(grok.ClassGrokker):
component_class = grok.XMLRPC
@@ -111,6 +117,7 @@
checker = NamesChecker(['__call__'], permission)
defineChecker(method_view, checker)
+
class ViewGrokker(grok.ClassGrokker):
component_class = grok.View
@@ -219,6 +226,7 @@
'for XML-RPC methods.'
% (method.__name__, factory), factory)
+
class TraverserGrokker(grok.ClassGrokker):
component_class = grok.Traverser
@@ -227,7 +235,8 @@
component.provideAdapter(factory,
adapts=(factory_context, IBrowserRequest),
provides=IBrowserPublisher)
-
+
+
class ModulePageTemplateGrokker(grok.InstanceGrokker):
# this needs to happen before any other grokkers execute that actually
# use the templates
@@ -239,25 +248,28 @@
templates.register(name, instance)
instance._annotateGrokInfo(name, module_info.dotted_name)
+
class FilesystemPageTemplateGrokker(grok.ModuleGrokker):
# do this early on, but after ModulePageTemplateGrokker, as
# findFilesystem depends on module-level templates to be
# already grokked for error reporting
priority = 999
-
+
def register(self, context, module_info, templates):
templates.findFilesystem(module_info)
+
class SubscriberGrokker(grok.ModuleGrokker):
def register(self, context, module_info, templates):
subscribers = module_info.getAnnotation('grok.subscribers', [])
-
+
for factory, subscribed in subscribers:
component.provideHandler(factory, adapts=subscribed)
for iface in subscribed:
zope.component.interface.provideInterface('', iface)
+
class StaticResourcesGrokker(grok.ModuleGrokker):
def register(self, context, module_info, templates):
@@ -265,7 +277,7 @@
# happens to be a package
if not module_info.isPackage():
return
-
+
resource_path = module_info.getResourcePath('static')
if os.path.isdir(resource_path):
static_module = module_info.getSubModuleInfo('static')
@@ -280,18 +292,19 @@
"A package can not contain both a 'static' "
"resource directory and a module named "
"'static.py'", module_info.getModule())
-
+
resource_factory = components.DirectoryResourceFactory(
resource_path, module_info.dotted_name)
component.provideAdapter(
resource_factory, (IDefaultBrowserLayer,),
interface.Interface, name=module_info.dotted_name)
+
class GlobalUtilityDirectiveGrokker(grok.ModuleGrokker):
def register(self, context, module_info, templates):
infos = module_info.getAnnotation('grok.global_utility', [])
-
+
for info in infos:
if info.provides is None:
util.check_implements_one(info.factory)
@@ -299,6 +312,7 @@
provides=info.provides,
name=info.name)
+
class SiteGrokker(grok.ClassGrokker):
component_class = grok.Site
priority = 500
@@ -336,7 +350,7 @@
util.check_implements_one_from_list(provides, info.factory)
info.provides = provides[0]
-
+
# raise an error in case of any duplicate registrations
# on the class level (subclassing overrides, see below)
used = set()
@@ -371,6 +385,7 @@
component.provideHandler(localUtilityRegistrationSubscriber,
adapts=(factory, grok.IObjectAddedEvent))
+
def localUtilityRegistrationSubscriber(site, event):
"""A subscriber that fires to set up local utilities.
"""
@@ -406,7 +421,8 @@
# we are done. If this subscriber gets fired again, we therefore
# do not register utilities anymore
site.__grok_utilities_installed__ = True
-
+
+
class DefinePermissionGrokker(grok.ModuleGrokker):
priority = 1500
@@ -417,6 +433,7 @@
# TODO permission title and description
component.provideUtility(Permission(permission), name=permission)
+
class AnnotationGrokker(grok.ClassGrokker):
component_class = grok.Annotation
@@ -452,3 +469,16 @@
return contained_result
component.provideAdapter(getAnnotation)
+
+
+class ApplicationGrokker(grok.ClassGrokker):
+ component_class = grok.Application
+ priority = 500
+ continue_scanning = True
+
+ def register(self, context, name, factory, module_info, templates):
+ # XXX fail loudly if the same application name is used twice.
+ zope.component.provideUtility(factory,
+ provides=grok.interfaces.IApplication,
+ name='%s.%s' % (module_info.dotted_name,
+ name))
Added: grok/trunk/src/grok/tests/application/__init__.py
===================================================================
--- grok/trunk/src/grok/tests/application/__init__.py 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/src/grok/tests/application/__init__.py 2007-02-07 06:20:13 UTC (rev 72409)
@@ -0,0 +1 @@
+# this is a package
Property changes on: grok/trunk/src/grok/tests/application/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id Rev Date
Name: svn:eol-style
+ native
Added: grok/trunk/src/grok/tests/application/application.py
===================================================================
--- grok/trunk/src/grok/tests/application/application.py 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/src/grok/tests/application/application.py 2007-02-07 06:20:13 UTC (rev 72409)
@@ -0,0 +1,35 @@
+"""
+
+After grokking a module that defines an application, the application factory is
+available as a utility::
+
+ >>> grok.grok(__name__)
+ >>> import zope.component
+ >>> import grok.interfaces
+ >>> calendar_app = zope.component.getUtility(grok.interfaces.IApplication,
+ ... name='grok.tests.application.application.Calendar')
+ >>> calendar_app
+ <class 'grok.tests.application.application.Calendar'>
+
+Applications are both containers and sites::
+
+ >>> issubclass(calendar_app, grok.Container)
+ True
+ >>> issubclass(calendar_app, grok.Site)
+ True
+
+Applications can be instanciated without any arguments::
+
+ >>> calendar = calendar_app()
+ >>> calendar
+ <grok.tests.application.application.Calendar object at 0x...>
+
+"""
+
+import grok
+
+
+class Calendar(grok.Application):
+ """A calendar application that knows about ancient
+ calendar systems from the stone age.
+ """
Property changes on: grok/trunk/src/grok/tests/application/application.py
___________________________________________________________________
Name: svn:keywords
+ Id Rev Date
Name: svn:eol-style
+ native
Modified: grok/trunk/src/grok/tests/test_grok.py
===================================================================
--- grok/trunk/src/grok/tests/test_grok.py 2007-02-06 23:19:06 UTC (rev 72408)
+++ grok/trunk/src/grok/tests/test_grok.py 2007-02-07 06:20:13 UTC (rev 72409)
@@ -35,7 +35,7 @@
for name in ['adapter', 'error', 'view', 'scan', 'event', 'security',
'zcml', 'static', 'utility', 'xmlrpc', 'container',
'traversal', 'form', 'site', 'grokker', 'directive', 'util',
- 'baseclass', 'annotation']:
+ 'baseclass', 'annotation', 'application']:
suite.addTest(suiteFromPackage(name))
return suite
More information about the Checkins
mailing list