[Checkins] SVN: grok/branches/darrylcousins-branch/src/grok/ Merged
trunk/src into this branch
Darryl Cousins
darryl at darrylcousins.net.nz
Mon Jul 2 22:01:37 EDT 2007
Log message for revision 77322:
Merged trunk/src into this branch
Changed:
D grok/branches/darrylcousins-branch/src/grok/__init__.py
A grok/branches/darrylcousins-branch/src/grok/__init__.py
D grok/branches/darrylcousins-branch/src/grok/components.py
A grok/branches/darrylcousins-branch/src/grok/components.py
D grok/branches/darrylcousins-branch/src/grok/meta.py
A grok/branches/darrylcousins-branch/src/grok/meta.py
D grok/branches/darrylcousins-branch/src/grok/tests/adapter/adapterdecorator.py
A grok/branches/darrylcousins-branch/src/grok/tests/adapter/adapterdecorator.py
D grok/branches/darrylcousins-branch/src/grok/tests/adapter/functionasargument_fixture.py
A grok/branches/darrylcousins-branch/src/grok/tests/adapter/functionasargument_fixture.py
D grok/branches/darrylcousins-branch/src/grok/tests/adapter/noarguments_fixture.py
A grok/branches/darrylcousins-branch/src/grok/tests/adapter/noarguments_fixture.py
-=-
Deleted: grok/branches/darrylcousins-branch/src/grok/__init__.py
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/__init__.py 2007-07-03 02:00:16 UTC (rev 77321)
+++ grok/branches/darrylcousins-branch/src/grok/__init__.py 2007-07-03 02:01:37 UTC (rev 77322)
@@ -1,54 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2006-2007 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.
-#
-##############################################################################
-"""Grok
-"""
-
-from zope.interface import implements
-from zope.component import adapts
-from zope.event import notify
-from zope.app.component.hooks import getSite
-from zope.lifecycleevent import (
- IObjectCreatedEvent, ObjectCreatedEvent,
- IObjectModifiedEvent, ObjectModifiedEvent,
- IObjectCopiedEvent, ObjectCopiedEvent)
-
-from zope.app.container.contained import (
- IObjectAddedEvent, ObjectAddedEvent,
- IObjectMovedEvent, ObjectMovedEvent,
- IObjectRemovedEvent, ObjectRemovedEvent,
- IContainerModifiedEvent, ContainerModifiedEvent)
-
-from martian import ClassGrokker, InstanceGrokker, GlobalGrokker
-from grok.components import Model, Adapter, MultiAdapter, View, XMLRPC, JSON
-from grok.components import PageTemplate, PageTemplateFile, Container, Traverser
-from grok.components import Site, GlobalUtility, LocalUtility, Annotation
-from grok.components import Application, Form, AddForm, EditForm, DisplayForm
-from grok.components import Indexes
-from grok.directive import (context, name, template, templatedir, provides,
- baseclass, global_utility, local_utility,
- define_permission, require, site)
-from grok._grok import do_grok as grok # Avoid name clash within _grok
-from grok._grok import grok_component
-from grok._grok import SubscribeDecorator as subscribe
-from grok._grok import adapter, implementer
-from martian.error import GrokError, GrokImportError
-
-from grok.formlib import action, AutoFields, Fields
-from grok.util import url
-
-# Our __init__ provides the grok API directly so using 'import grok' is enough.
-from grok.interfaces import IGrokAPI
-from zope.interface import moduleProvides
-moduleProvides(IGrokAPI)
-__all__ = list(IGrokAPI)
Copied: grok/branches/darrylcousins-branch/src/grok/__init__.py (from rev 77321, grok/branches/darrylcousins-branch/src/grok/__init__.py)
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/__init__.py (rev 0)
+++ grok/branches/darrylcousins-branch/src/grok/__init__.py 2007-07-03 02:01:37 UTC (rev 77322)
@@ -0,0 +1,54 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 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.
+#
+##############################################################################
+"""Grok
+"""
+
+from zope.interface import implements
+from zope.component import adapts
+from zope.event import notify
+from zope.app.component.hooks import getSite
+from zope.lifecycleevent import (
+ IObjectCreatedEvent, ObjectCreatedEvent,
+ IObjectModifiedEvent, ObjectModifiedEvent,
+ IObjectCopiedEvent, ObjectCopiedEvent)
+
+from zope.app.container.contained import (
+ IObjectAddedEvent, ObjectAddedEvent,
+ IObjectMovedEvent, ObjectMovedEvent,
+ IObjectRemovedEvent, ObjectRemovedEvent,
+ IContainerModifiedEvent, ContainerModifiedEvent)
+
+from martian import ClassGrokker, InstanceGrokker, GlobalGrokker
+from grok.components import Model, Adapter, MultiAdapter, View, XMLRPC, JSON
+from grok.components import PageTemplate, PageTemplateFile, Container, Traverser
+from grok.components import Site, GlobalUtility, LocalUtility, Annotation
+from grok.components import Application, Form, AddForm, EditForm, DisplayForm
+from grok.components import Indexes
+from grok.directive import (context, name, template, templatedir, provides,
+ baseclass, global_utility, local_utility,
+ define_permission, require, site)
+from grok._grok import do_grok as grok # Avoid name clash within _grok
+from grok._grok import grok_component
+from grok._grok import SubscribeDecorator as subscribe
+from grok._grok import adapter, implementer
+from martian.error import GrokError, GrokImportError
+
+from grok.formlib import action, AutoFields, Fields
+from grok.util import url
+
+# Our __init__ provides the grok API directly so using 'import grok' is enough.
+from grok.interfaces import IGrokAPI
+from zope.interface import moduleProvides
+moduleProvides(IGrokAPI)
+__all__ = list(IGrokAPI)
Property changes on: grok/branches/darrylcousins-branch/src/grok/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Deleted: grok/branches/darrylcousins-branch/src/grok/components.py
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/components.py 2007-07-03 02:00:16 UTC (rev 77321)
+++ grok/branches/darrylcousins-branch/src/grok/components.py 2007-07-03 02:01:37 UTC (rev 77322)
@@ -1,465 +0,0 @@
-##############################################################################
-#
-# 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.
-#
-##############################################################################
-"""Grok components
-"""
-
-import os
-import persistent
-import urllib
-import datetime
-import warnings
-import pytz
-import simplejson
-
-from zope import component
-from zope import interface
-from zope import schema
-from zope import event
-from zope.interface.common import idatetime
-from zope.lifecycleevent import ObjectModifiedEvent
-from zope.publisher.browser import BrowserPage
-from zope.publisher.interfaces import NotFound
-from zope.publisher.interfaces.browser import (IBrowserPublisher,
- IBrowserRequest)
-from zope.publisher.publish import mapply
-from zope.pagetemplate import pagetemplate, pagetemplatefile
-from zope.formlib import form
-from zope.traversing.browser.interfaces import IAbsoluteURL
-from zope.traversing.browser.absoluteurl import AbsoluteURL
-from zope.traversing.browser.absoluteurl import _safe as SAFE_URL_CHARACTERS
-from zope.annotation.interfaces import IAttributeAnnotatable
-
-from zope.app.pagetemplate.engine import TrustedAppPT
-from zope.app.publisher.browser import getDefaultViewName
-from zope.app.publisher.browser import directoryresource
-from zope.app.publisher.browser.pagetemplateresource import \
- PageTemplateResourceFactory
-from zope.app.container.btree import BTreeContainer
-from zope.app.container.contained import Contained
-from zope.app.container.interfaces import IReadContainer
-from zope.app.component.site import SiteManagerContainer
-
-from martian import util
-
-from grok import interfaces, formlib
-from grok.util import url
-
-class Model(Contained, persistent.Persistent):
- # XXX Inheritance order is important here. If we reverse this,
- # then containers can't be models anymore because no unambigous MRO
- # can be established.
- interface.implements(IAttributeAnnotatable)
-
-
-class Container(BTreeContainer):
- interface.implements(IAttributeAnnotatable)
-
-
-class Site(SiteManagerContainer):
- pass
-
-
-class Application(Site):
- """A top-level application object."""
- interface.implements(interfaces.IApplication)
-
-class Adapter(object):
-
- def __init__(self, context):
- self.context = context
-
-
-class GlobalUtility(object):
- pass
-
-
-class LocalUtility(Model):
- pass
-
-
-class MultiAdapter(object):
- pass
-
-
-class Annotation(persistent.Persistent):
- pass
-
-
-class View(BrowserPage):
- interface.implements(interfaces.IGrokView)
-
- def __init__(self, context, request):
- super(View, self).__init__(context, request)
- self.static = component.queryAdapter(
- self.request,
- interface.Interface,
- name=self.module_info.package_dotted_name
- )
-
- @property
- def response(self):
- return self.request.response
-
- def __call__(self):
- mapply(self.update, (), self.request)
- if self.request.response.getStatus() in (302, 303):
- # A redirect was triggered somewhere in update(). Don't
- # continue rendering the template or doing anything else.
- return
-
- template = getattr(self, 'template', None)
- if template is not None:
- return self._render_template()
- return mapply(self.render, (), self.request)
-
- def _render_template(self):
- namespace = self.template.pt_getContext()
- namespace['request'] = self.request
- namespace['view'] = self
- namespace['context'] = self.context
- # XXX need to check whether we really want to put None here if missing
- namespace['static'] = self.static
- return self.template.pt_render(namespace)
-
- def __getitem__(self, key):
- # XXX give nice error message if template is None
- return self.template.macros[key]
-
- def url(self, obj=None, name=None):
- # if the first argument is a string, that's the name. There should
- # be no second argument
- if isinstance(obj, basestring):
- if name is not None:
- raise TypeError(
- 'url() takes either obj argument, obj, string arguments, '
- 'or string argument')
- name = obj
- obj = None
-
- if name is None and obj is None:
- # create URL to view itself
- obj = self
- elif name is not None and obj is None:
- # create URL to view on context
- obj = self.context
- return url(self.request, obj, name)
-
- def application_url(self, name=None):
- obj = self.context
- while obj is not None:
- if isinstance(obj, Application):
- return self.url(obj, name)
- obj = obj.__parent__
- raise ValueError("No application found.")
-
- def redirect(self, url):
- return self.request.response.redirect(url)
-
- def update(self):
- pass
-
-class GrokViewAbsoluteURL(AbsoluteURL):
-
- def _getContextName(self, context):
- return getattr(context, '__view_name__', None)
- # XXX breadcrumbs method on AbsoluteURL breaks as it does not use
- # _getContextName to get to the name of the view. What does breadcrumbs do?
-
-
-class XMLRPC(object):
- pass
-
-class JSON(BrowserPage):
-
- def __call__(self):
- view_name = self.__view_name__
- method = getattr(self, view_name)
- method_result = mapply(method, (), self.request)
- return simplejson.dumps(method_result)
-
-class GrokPageTemplate(object):
-
- def __repr__(self):
- return '<%s template in %s>' % (self.__grok_name__,
- self.__grok_location__)
-
- def _annotateGrokInfo(self, name, location):
- self.__grok_name__ = name
- self.__grok_location__ = location
-
-
-class PageTemplate(GrokPageTemplate, TrustedAppPT, pagetemplate.PageTemplate):
- expand = 0
-
- def __init__(self, template):
- super(PageTemplate, self).__init__()
- if util.not_unicode_or_ascii(template):
- raise ValueError("Invalid page template. Page templates must be "
- "unicode or ASCII.")
- self.write(template)
-
- # __grok_module__ is needed to make defined_locally() return True for
- # inline templates
- # XXX unfortunately using caller_module means that
- # PageTemplate cannot be subclassed
- self.__grok_module__ = util.caller_module()
-
-
-class PageTemplateFile(GrokPageTemplate, TrustedAppPT,
- pagetemplatefile.PageTemplateFile):
-
- def __init__(self, filename, _prefix=None):
- _prefix = self.get_path_from_prefix(_prefix)
- super(PageTemplateFile, self).__init__(filename, _prefix)
-
- # __grok_module__ is needed to make defined_locally() return True for
- # inline templates
- # XXX unfortunately using caller_module means that
- # PageTemplateFile cannot be subclassed
- self.__grok_module__ = util.caller_module()
-
-
-class DirectoryResource(directoryresource.DirectoryResource):
- # We subclass this, because we want to override the default factories for
- # the resources so that .pt and .html do not get created as page
- # templates
-
- resource_factories = {}
- for type, factory in (directoryresource.DirectoryResource.
- resource_factories.items()):
- if factory is PageTemplateResourceFactory:
- continue
- resource_factories[type] = factory
-
-
-class DirectoryResourceFactory(object):
- # We need this to allow hooking up our own GrokDirectoryResource
- # and to set the checker to None (until we have our own checker)
-
- def __init__(self, path, name):
- # XXX we're not sure about the checker=None here
- self.__dir = directoryresource.Directory(path, None, name)
- self.__name = name
-
- def __call__(self, request):
- resource = DirectoryResource(self.__dir, request)
- resource.__name__ = self.__name
- return resource
-
-
-class Traverser(object):
- interface.implements(IBrowserPublisher)
-
- def __init__(self, context, request):
- self.context = context
- self.request = request
-
- def browserDefault(self, request):
- view_name = getDefaultViewName(self.context, request)
- view_uri = "@@%s" % view_name
- return self.context, (view_uri,)
-
- def publishTraverse(self, request, name):
- subob = self.traverse(name)
- if subob is not None:
- return subob
-
- # XXX Special logic here to deal with containers. It would be
- # good if we wouldn't have to do this here. One solution is to
- # rip this out and make you subclass ContainerTraverser if you
- # wanted to override the traversal behaviour of containers.
- if IReadContainer.providedBy(self.context):
- item = self.context.get(name)
- if item is not None:
- return item
-
- view = component.queryMultiAdapter((self.context, request), name=name)
- if view is not None:
- return view
-
- raise NotFound(self.context, name, request)
-
- def traverse(self, name):
- # this will be overridden by subclasses
- pass
-
-
-class ModelTraverser(Traverser):
- component.adapts(Model, IBrowserRequest)
-
- def traverse(self, name):
- traverse = getattr(self.context, 'traverse', None)
- if traverse:
- return traverse(name)
-
-
-class ContainerTraverser(Traverser):
- component.adapts(Container, IBrowserRequest)
-
- def traverse(self, name):
- traverse = getattr(self.context, 'traverse', None)
- if traverse:
- result = traverse(name)
- if result is not None:
- return result
- # try to get the item from the container
- return self.context.get(name)
-
-default_form_template = PageTemplateFile(os.path.join(
- 'templates', 'default_edit_form.pt'))
-default_form_template.__grok_name__ = 'default_edit_form'
-default_display_template = PageTemplateFile(os.path.join(
- 'templates', 'default_display_form.pt'))
-default_display_template.__grok_name__ = 'default_display_form'
-
-class GrokForm(object):
- """Mix-in to console zope.formlib's forms with grok.View and to
- add some more useful methods.
-
- The consolation needs to happen because zope.formlib's Forms have
- update/render methods which have different meanings than
- grok.View's update/render methods. We deal with this issue by
- 'renaming' zope.formlib's update() to update_form() and by
- disallowing subclasses to have custom render() methods."""
-
- def update(self):
- """Subclasses can override this method just like on regular
- grok.Views. It will be called before any form processing
- happens."""
-
- def update_form(self):
- """Update the form, i.e. process form input using widgets.
-
- On zope.formlib forms, this is what the update() method is.
- In grok views, the update() method has a different meaning.
- That's why this method is called update_form() in grok forms."""
- super(GrokForm, self).update()
-
- def render(self):
- """Render the form, either using the form template or whatever
- the actions returned in form_result."""
- # if the form has been updated, it will already have a result
- if self.form_result is None:
- if self.form_reset:
- # we reset, in case data has changed in a way that
- # causes the widgets to have different data
- self.resetForm()
- self.form_reset = False
- self.form_result = self._render_template()
-
- return self.form_result
-
- # Mark the render() method as a method from the base class. That
- # way we can detect whether somebody overrides render() in a
- # subclass (which we don't allow).
- render.base_method = True
-
- def __call__(self):
- mapply(self.update, (), self.request)
- if self.request.response.getStatus() in (302, 303):
- # A redirect was triggered somewhere in update(). Don't
- # continue rendering the template or doing anything else.
- return
-
- self.update_form()
- return self.render()
-
-class Form(GrokForm, form.FormBase, View):
- # We're only reusing the form implementation from zope.formlib, we
- # explicitly don't want to inherit the interface semantics (mostly
- # for the different meanings of update/render).
- interface.implementsOnly(interfaces.IGrokForm)
-
- template = default_form_template
-
- def applyData(self, obj, **data):
- return formlib.apply_data_event(obj, self.form_fields, data,
- self.adapters)
-
- # BBB -- to be removed in June 2007
- def applyChanges(self, obj, **data):
- warnings.warn("The 'applyChanges' method on forms is deprecated "
- "and will disappear by June 2007. Please use "
- "'applyData' instead.", DeprecationWarning, 2)
- return bool(self.applyData(obj, **data))
-
-class AddForm(Form):
- pass
-
-class EditForm(GrokForm, form.EditFormBase, View):
- # We're only reusing the form implementation from zope.formlib, we
- # explicitly don't want to inherit the interface semantics (mostly
- # for the different meanings of update/render).
- interface.implementsOnly(interfaces.IGrokForm)
-
- template = default_form_template
-
- def applyData(self, obj, **data):
- return formlib.apply_data_event(obj, self.form_fields, data,
- self.adapters, update=True)
-
- # BBB -- to be removed in June 2007
- def applyChanges(self, obj, **data):
- warnings.warn("The 'applyChanges' method on forms is deprecated "
- "and will disappear by June 2007. Please use "
- "'applyData' instead.", DeprecationWarning, 2)
- return bool(self.applyData(obj, **data))
-
- @formlib.action("Apply")
- def handle_edit_action(self, **data):
- if self.applyData(self.context, **data):
- formatter = self.request.locale.dates.getFormatter(
- 'dateTime', 'medium')
-
- try:
- time_zone = idatetime.ITZInfo(self.request)
- except TypeError:
- time_zone = pytz.UTC
-
- self.status = "Updated on %s" % formatter.format(
- datetime.datetime.now(time_zone)
- )
- else:
- self.status = 'No changes'
-
-class DisplayForm(GrokForm, form.DisplayFormBase, View):
- # We're only reusing the form implementation from zope.formlib, we
- # explicitly don't want to inherit the interface semantics (mostly
- # for the different meanings of update/render).
- interface.implementsOnly(interfaces.IGrokForm)
-
- template = default_display_template
-
-class IndexesClass(object):
- def __init__(self, name, bases=(), attrs=None):
- if attrs is None:
- return
- # make sure we take over a bunch of possible attributes
- for name in ['__grok_context__', '__grok_name__',
- '__grok_site__']:
- value = attrs.get(name)
- if value is not None:
- setattr(self, name, value)
- # now read and store indexes
- indexes = {}
- for name, value in attrs.items():
- if not interfaces.IIndexDefinition.providedBy(value):
- continue
- indexes[name] = value
- self.__grok_indexes__ = indexes
- # __grok_module__ is needed to make defined_locally() return True for
- # inline templates
- self.__grok_module__ = util.caller_module()
-
-Indexes = IndexesClass('Indexes')
Copied: grok/branches/darrylcousins-branch/src/grok/components.py (from rev 77321, grok/branches/darrylcousins-branch/src/grok/components.py)
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/components.py (rev 0)
+++ grok/branches/darrylcousins-branch/src/grok/components.py 2007-07-03 02:01:37 UTC (rev 77322)
@@ -0,0 +1,465 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Grok components
+"""
+
+import os
+import persistent
+import urllib
+import datetime
+import warnings
+import pytz
+import simplejson
+
+from zope import component
+from zope import interface
+from zope import schema
+from zope import event
+from zope.interface.common import idatetime
+from zope.lifecycleevent import ObjectModifiedEvent
+from zope.publisher.browser import BrowserPage
+from zope.publisher.interfaces import NotFound
+from zope.publisher.interfaces.browser import (IBrowserPublisher,
+ IBrowserRequest)
+from zope.publisher.publish import mapply
+from zope.pagetemplate import pagetemplate, pagetemplatefile
+from zope.formlib import form
+from zope.traversing.browser.interfaces import IAbsoluteURL
+from zope.traversing.browser.absoluteurl import AbsoluteURL
+from zope.traversing.browser.absoluteurl import _safe as SAFE_URL_CHARACTERS
+from zope.annotation.interfaces import IAttributeAnnotatable
+
+from zope.app.pagetemplate.engine import TrustedAppPT
+from zope.app.publisher.browser import getDefaultViewName
+from zope.app.publisher.browser import directoryresource
+from zope.app.publisher.browser.pagetemplateresource import \
+ PageTemplateResourceFactory
+from zope.app.container.btree import BTreeContainer
+from zope.app.container.contained import Contained
+from zope.app.container.interfaces import IReadContainer
+from zope.app.component.site import SiteManagerContainer
+
+from martian import util
+
+from grok import interfaces, formlib
+from grok.util import url
+
+class Model(Contained, persistent.Persistent):
+ # XXX Inheritance order is important here. If we reverse this,
+ # then containers can't be models anymore because no unambigous MRO
+ # can be established.
+ interface.implements(IAttributeAnnotatable)
+
+
+class Container(BTreeContainer):
+ interface.implements(IAttributeAnnotatable)
+
+
+class Site(SiteManagerContainer):
+ pass
+
+
+class Application(Site):
+ """A top-level application object."""
+ interface.implements(interfaces.IApplication)
+
+class Adapter(object):
+
+ def __init__(self, context):
+ self.context = context
+
+
+class GlobalUtility(object):
+ pass
+
+
+class LocalUtility(Model):
+ pass
+
+
+class MultiAdapter(object):
+ pass
+
+
+class Annotation(persistent.Persistent):
+ pass
+
+
+class View(BrowserPage):
+ interface.implements(interfaces.IGrokView)
+
+ def __init__(self, context, request):
+ super(View, self).__init__(context, request)
+ self.static = component.queryAdapter(
+ self.request,
+ interface.Interface,
+ name=self.module_info.package_dotted_name
+ )
+
+ @property
+ def response(self):
+ return self.request.response
+
+ def __call__(self):
+ mapply(self.update, (), self.request)
+ if self.request.response.getStatus() in (302, 303):
+ # A redirect was triggered somewhere in update(). Don't
+ # continue rendering the template or doing anything else.
+ return
+
+ template = getattr(self, 'template', None)
+ if template is not None:
+ return self._render_template()
+ return mapply(self.render, (), self.request)
+
+ def _render_template(self):
+ namespace = self.template.pt_getContext()
+ namespace['request'] = self.request
+ namespace['view'] = self
+ namespace['context'] = self.context
+ # XXX need to check whether we really want to put None here if missing
+ namespace['static'] = self.static
+ return self.template.pt_render(namespace)
+
+ def __getitem__(self, key):
+ # XXX give nice error message if template is None
+ return self.template.macros[key]
+
+ def url(self, obj=None, name=None):
+ # if the first argument is a string, that's the name. There should
+ # be no second argument
+ if isinstance(obj, basestring):
+ if name is not None:
+ raise TypeError(
+ 'url() takes either obj argument, obj, string arguments, '
+ 'or string argument')
+ name = obj
+ obj = None
+
+ if name is None and obj is None:
+ # create URL to view itself
+ obj = self
+ elif name is not None and obj is None:
+ # create URL to view on context
+ obj = self.context
+ return url(self.request, obj, name)
+
+ def application_url(self, name=None):
+ obj = self.context
+ while obj is not None:
+ if isinstance(obj, Application):
+ return self.url(obj, name)
+ obj = obj.__parent__
+ raise ValueError("No application found.")
+
+ def redirect(self, url):
+ return self.request.response.redirect(url)
+
+ def update(self):
+ pass
+
+class GrokViewAbsoluteURL(AbsoluteURL):
+
+ def _getContextName(self, context):
+ return getattr(context, '__view_name__', None)
+ # XXX breadcrumbs method on AbsoluteURL breaks as it does not use
+ # _getContextName to get to the name of the view. What does breadcrumbs do?
+
+
+class XMLRPC(object):
+ pass
+
+class JSON(BrowserPage):
+
+ def __call__(self):
+ view_name = self.__view_name__
+ method = getattr(self, view_name)
+ method_result = mapply(method, (), self.request)
+ return simplejson.dumps(method_result)
+
+class GrokPageTemplate(object):
+
+ def __repr__(self):
+ return '<%s template in %s>' % (self.__grok_name__,
+ self.__grok_location__)
+
+ def _annotateGrokInfo(self, name, location):
+ self.__grok_name__ = name
+ self.__grok_location__ = location
+
+
+class PageTemplate(GrokPageTemplate, TrustedAppPT, pagetemplate.PageTemplate):
+ expand = 0
+
+ def __init__(self, template):
+ super(PageTemplate, self).__init__()
+ if util.not_unicode_or_ascii(template):
+ raise ValueError("Invalid page template. Page templates must be "
+ "unicode or ASCII.")
+ self.write(template)
+
+ # __grok_module__ is needed to make defined_locally() return True for
+ # inline templates
+ # XXX unfortunately using caller_module means that
+ # PageTemplate cannot be subclassed
+ self.__grok_module__ = util.caller_module()
+
+
+class PageTemplateFile(GrokPageTemplate, TrustedAppPT,
+ pagetemplatefile.PageTemplateFile):
+
+ def __init__(self, filename, _prefix=None):
+ _prefix = self.get_path_from_prefix(_prefix)
+ super(PageTemplateFile, self).__init__(filename, _prefix)
+
+ # __grok_module__ is needed to make defined_locally() return True for
+ # inline templates
+ # XXX unfortunately using caller_module means that
+ # PageTemplateFile cannot be subclassed
+ self.__grok_module__ = util.caller_module()
+
+
+class DirectoryResource(directoryresource.DirectoryResource):
+ # We subclass this, because we want to override the default factories for
+ # the resources so that .pt and .html do not get created as page
+ # templates
+
+ resource_factories = {}
+ for type, factory in (directoryresource.DirectoryResource.
+ resource_factories.items()):
+ if factory is PageTemplateResourceFactory:
+ continue
+ resource_factories[type] = factory
+
+
+class DirectoryResourceFactory(object):
+ # We need this to allow hooking up our own GrokDirectoryResource
+ # and to set the checker to None (until we have our own checker)
+
+ def __init__(self, path, name):
+ # XXX we're not sure about the checker=None here
+ self.__dir = directoryresource.Directory(path, None, name)
+ self.__name = name
+
+ def __call__(self, request):
+ resource = DirectoryResource(self.__dir, request)
+ resource.__name__ = self.__name
+ return resource
+
+
+class Traverser(object):
+ interface.implements(IBrowserPublisher)
+
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+
+ def browserDefault(self, request):
+ view_name = getDefaultViewName(self.context, request)
+ view_uri = "@@%s" % view_name
+ return self.context, (view_uri,)
+
+ def publishTraverse(self, request, name):
+ subob = self.traverse(name)
+ if subob is not None:
+ return subob
+
+ # XXX Special logic here to deal with containers. It would be
+ # good if we wouldn't have to do this here. One solution is to
+ # rip this out and make you subclass ContainerTraverser if you
+ # wanted to override the traversal behaviour of containers.
+ if IReadContainer.providedBy(self.context):
+ item = self.context.get(name)
+ if item is not None:
+ return item
+
+ view = component.queryMultiAdapter((self.context, request), name=name)
+ if view is not None:
+ return view
+
+ raise NotFound(self.context, name, request)
+
+ def traverse(self, name):
+ # this will be overridden by subclasses
+ pass
+
+
+class ModelTraverser(Traverser):
+ component.adapts(Model, IBrowserRequest)
+
+ def traverse(self, name):
+ traverse = getattr(self.context, 'traverse', None)
+ if traverse:
+ return traverse(name)
+
+
+class ContainerTraverser(Traverser):
+ component.adapts(Container, IBrowserRequest)
+
+ def traverse(self, name):
+ traverse = getattr(self.context, 'traverse', None)
+ if traverse:
+ result = traverse(name)
+ if result is not None:
+ return result
+ # try to get the item from the container
+ return self.context.get(name)
+
+default_form_template = PageTemplateFile(os.path.join(
+ 'templates', 'default_edit_form.pt'))
+default_form_template.__grok_name__ = 'default_edit_form'
+default_display_template = PageTemplateFile(os.path.join(
+ 'templates', 'default_display_form.pt'))
+default_display_template.__grok_name__ = 'default_display_form'
+
+class GrokForm(object):
+ """Mix-in to console zope.formlib's forms with grok.View and to
+ add some more useful methods.
+
+ The consolation needs to happen because zope.formlib's Forms have
+ update/render methods which have different meanings than
+ grok.View's update/render methods. We deal with this issue by
+ 'renaming' zope.formlib's update() to update_form() and by
+ disallowing subclasses to have custom render() methods."""
+
+ def update(self):
+ """Subclasses can override this method just like on regular
+ grok.Views. It will be called before any form processing
+ happens."""
+
+ def update_form(self):
+ """Update the form, i.e. process form input using widgets.
+
+ On zope.formlib forms, this is what the update() method is.
+ In grok views, the update() method has a different meaning.
+ That's why this method is called update_form() in grok forms."""
+ super(GrokForm, self).update()
+
+ def render(self):
+ """Render the form, either using the form template or whatever
+ the actions returned in form_result."""
+ # if the form has been updated, it will already have a result
+ if self.form_result is None:
+ if self.form_reset:
+ # we reset, in case data has changed in a way that
+ # causes the widgets to have different data
+ self.resetForm()
+ self.form_reset = False
+ self.form_result = self._render_template()
+
+ return self.form_result
+
+ # Mark the render() method as a method from the base class. That
+ # way we can detect whether somebody overrides render() in a
+ # subclass (which we don't allow).
+ render.base_method = True
+
+ def __call__(self):
+ mapply(self.update, (), self.request)
+ if self.request.response.getStatus() in (302, 303):
+ # A redirect was triggered somewhere in update(). Don't
+ # continue rendering the template or doing anything else.
+ return
+
+ self.update_form()
+ return self.render()
+
+class Form(GrokForm, form.FormBase, View):
+ # We're only reusing the form implementation from zope.formlib, we
+ # explicitly don't want to inherit the interface semantics (mostly
+ # for the different meanings of update/render).
+ interface.implementsOnly(interfaces.IGrokForm)
+
+ template = default_form_template
+
+ def applyData(self, obj, **data):
+ return formlib.apply_data_event(obj, self.form_fields, data,
+ self.adapters)
+
+ # BBB -- to be removed in June 2007
+ def applyChanges(self, obj, **data):
+ warnings.warn("The 'applyChanges' method on forms is deprecated "
+ "and will disappear by June 2007. Please use "
+ "'applyData' instead.", DeprecationWarning, 2)
+ return bool(self.applyData(obj, **data))
+
+class AddForm(Form):
+ pass
+
+class EditForm(GrokForm, form.EditFormBase, View):
+ # We're only reusing the form implementation from zope.formlib, we
+ # explicitly don't want to inherit the interface semantics (mostly
+ # for the different meanings of update/render).
+ interface.implementsOnly(interfaces.IGrokForm)
+
+ template = default_form_template
+
+ def applyData(self, obj, **data):
+ return formlib.apply_data_event(obj, self.form_fields, data,
+ self.adapters, update=True)
+
+ # BBB -- to be removed in June 2007
+ def applyChanges(self, obj, **data):
+ warnings.warn("The 'applyChanges' method on forms is deprecated "
+ "and will disappear by June 2007. Please use "
+ "'applyData' instead.", DeprecationWarning, 2)
+ return bool(self.applyData(obj, **data))
+
+ @formlib.action("Apply")
+ def handle_edit_action(self, **data):
+ if self.applyData(self.context, **data):
+ formatter = self.request.locale.dates.getFormatter(
+ 'dateTime', 'medium')
+
+ try:
+ time_zone = idatetime.ITZInfo(self.request)
+ except TypeError:
+ time_zone = pytz.UTC
+
+ self.status = "Updated on %s" % formatter.format(
+ datetime.datetime.now(time_zone)
+ )
+ else:
+ self.status = 'No changes'
+
+class DisplayForm(GrokForm, form.DisplayFormBase, View):
+ # We're only reusing the form implementation from zope.formlib, we
+ # explicitly don't want to inherit the interface semantics (mostly
+ # for the different meanings of update/render).
+ interface.implementsOnly(interfaces.IGrokForm)
+
+ template = default_display_template
+
+class IndexesClass(object):
+ def __init__(self, name, bases=(), attrs=None):
+ if attrs is None:
+ return
+ # make sure we take over a bunch of possible attributes
+ for name in ['__grok_context__', '__grok_name__',
+ '__grok_site__']:
+ value = attrs.get(name)
+ if value is not None:
+ setattr(self, name, value)
+ # now read and store indexes
+ indexes = {}
+ for name, value in attrs.items():
+ if not interfaces.IIndexDefinition.providedBy(value):
+ continue
+ indexes[name] = value
+ self.__grok_indexes__ = indexes
+ # __grok_module__ is needed to make defined_locally() return True for
+ # inline templates
+ self.__grok_module__ = util.caller_module()
+
+Indexes = IndexesClass('Indexes')
Property changes on: grok/branches/darrylcousins-branch/src/grok/components.py
___________________________________________________________________
Name: svn:keywords
+ Id
Deleted: grok/branches/darrylcousins-branch/src/grok/meta.py
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/meta.py 2007-07-03 02:00:16 UTC (rev 77321)
+++ grok/branches/darrylcousins-branch/src/grok/meta.py 2007-07-03 02:01:37 UTC (rev 77322)
@@ -1,595 +0,0 @@
-import os
-
-import zope.component.interface
-from zope import interface, component
-from zope.publisher.interfaces.browser import (IDefaultBrowserLayer,
- IBrowserRequest,
- IBrowserPublisher)
-from zope.publisher.interfaces.xmlrpc import IXMLRPCRequest
-from zope.security.permission import Permission
-from zope.security.interfaces import IPermission
-from zope.annotation.interfaces import IAnnotations
-
-from zope.app.publisher.xmlrpc import MethodPublisher
-from zope.app.container.interfaces import IContainer
-from zope.app.container.interfaces import INameChooser
-from zope.app.container.contained import contained
-
-from zope.app.intid import IntIds
-from zope.app.intid.interfaces import IIntIds
-from zope.app.catalog.catalog import Catalog
-from zope.app.catalog.interfaces import ICatalog
-
-from zope.exceptions.interfaces import DuplicationError
-
-import martian
-from martian.error import GrokError
-from martian import util
-
-import grok
-from grok import components, formlib
-from grok.util import check_adapts, get_default_permission, make_checker
-
-class ModelGrokker(martian.ClassGrokker):
- component_class = grok.Model
-
- def grok(self, name, factory, context, module_info, templates):
- for field in formlib.get_context_schema_fields(factory):
- setattr(factory, field.__name__, field.default)
- return True
-
-class ContainerGrokker(ModelGrokker):
- component_class = grok.Container
-
-
-class LocalUtilityGrokker(ModelGrokker):
- component_class = grok.LocalUtility
-
-
-class AdapterGrokker(martian.ClassGrokker):
- component_class = grok.Adapter
-
- def grok(self, name, factory, context, module_info, templates):
- adapter_context = util.determine_class_context(factory, context)
- provides = util.class_annotation(factory, 'grok.provides', None)
- if provides is None:
- util.check_implements_one(factory)
- name = util.class_annotation(factory, 'grok.name', '')
- component.provideAdapter(factory, adapts=(adapter_context,),
- provides=provides,
- name=name)
- return True
-
-class MultiAdapterGrokker(martian.ClassGrokker):
- component_class = grok.MultiAdapter
-
- def grok(self, name, factory, context, module_info, templates):
- provides = util.class_annotation(factory, 'grok.provides', None)
- if provides is None:
- util.check_implements_one(factory)
- check_adapts(factory)
- name = util.class_annotation(factory, 'grok.name', '')
- component.provideAdapter(factory, provides=provides, name=name)
- return True
-
-class GlobalUtilityGrokker(martian.ClassGrokker):
- component_class = grok.GlobalUtility
-
- def grok(self, name, factory, context, module_info, templates):
- provides = util.class_annotation(factory, 'grok.provides', None)
- if provides is None:
- util.check_implements_one(factory)
- name = util.class_annotation(factory, 'grok.name', '')
- component.provideUtility(factory(), provides=provides, name=name)
- return True
-
-class XMLRPCGrokker(martian.ClassGrokker):
- component_class = grok.XMLRPC
-
- def grok(self, name, factory, context, module_info, templates):
- view_context = util.determine_class_context(factory, context)
- # XXX We should really not make __FOO__ methods available to
- # the outside -- need to discuss how to restrict such things.
- methods = util.methods_from_class(factory)
-
- default_permission = get_default_permission(factory)
-
- for method in methods:
- # Make sure that the class inherits MethodPublisher, so that the
- # views have a location
- method_view = type(
- factory.__name__, (factory, MethodPublisher),
- {'__call__': method}
- )
- component.provideAdapter(
- method_view, (view_context, IXMLRPCRequest),
- interface.Interface,
- name=method.__name__)
-
- # Protect method_view with either the permission that was
- # set on the method, the default permission from the class
- # level or zope.Public.
- permission = getattr(method, '__grok_require__',
- default_permission)
- make_checker(factory, method_view, permission)
- return True
-
-class ViewGrokker(martian.ClassGrokker):
- component_class = grok.View
-
- def grok(self, name, factory, context, module_info, templates):
- view_context = util.determine_class_context(factory, context)
-
- factory.module_info = module_info
- factory_name = factory.__name__.lower()
-
- if util.check_subclass(factory, components.GrokForm):
- # setup form_fields from context class if we've encountered a form
- if getattr(factory, 'form_fields', None) is None:
- factory.form_fields = formlib.get_auto_fields(view_context)
-
- if not getattr(factory.render, 'base_method', False):
- raise GrokError(
- "It is not allowed to specify a custom 'render' "
- "method for form %r. Forms either use the default "
- "template or a custom-supplied one." % factory,
- factory)
-
- # find templates
- template_name = util.class_annotation(factory, 'grok.template',
- factory_name)
- template = templates.get(template_name)
-
- if factory_name != template_name:
- # grok.template is being used
- if templates.get(factory_name):
- raise GrokError("Multiple possible templates for view %r. It "
- "uses grok.template('%s'), but there is also "
- "a template called '%s'."
- % (factory, template_name, factory_name),
- factory)
-
- if template:
- if (getattr(factory, 'render', None) and not
- util.check_subclass(factory, components.GrokForm)):
- # we do not accept render and template both for a view
- # (unless it's a form, they happen to have render.
- raise GrokError(
- "Multiple possible ways to render view %r. "
- "It has both a 'render' method as well as "
- "an associated template." % factory, factory)
-
- templates.markAssociated(template_name)
- factory.template = template
- else:
- if not getattr(factory, 'render', None):
- # we do not accept a view without any way to render it
- raise GrokError("View %r has no associated template or "
- "'render' method." % factory, factory)
-
- view_name = util.class_annotation(factory, 'grok.name',
- factory_name)
- # __view_name__ is needed to support IAbsoluteURL on views
- factory.__view_name__ = view_name
- component.provideAdapter(factory,
- adapts=(view_context, IDefaultBrowserLayer),
- provides=interface.Interface,
- name=view_name)
-
- # protect view, public by default
- default_permission = get_default_permission(factory)
- make_checker(factory, factory, default_permission)
-
- # safety belt: make sure that the programmer didn't use
- # @grok.require on any of the view's methods.
- methods = util.methods_from_class(factory)
- for method in methods:
- if getattr(method, '__grok_require__', None) is not None:
- raise GrokError('The @grok.require decorator is used for '
- 'method %r in view %r. It may only be used '
- 'for XML-RPC methods.'
- % (method.__name__, factory), factory)
- return True
-
-
-class JSONGrokker(martian.ClassGrokker):
- component_class = grok.JSON
-
- def grok(self, name, factory, context, module_info, templates):
- view_context = util.determine_class_context(factory, context)
- methods = util.methods_from_class(factory)
-
- default_permission = get_default_permission(factory)
-
- for method in methods:
- # Create a new class with a __view_name__ attribute so the
- # JSON class knows what method to call.
- method_view = type(
- factory.__name__, (factory,),
- {'__view_name__': method.__name__}
- )
- component.provideAdapter(
- method_view, (view_context, IDefaultBrowserLayer),
- interface.Interface,
- name=method.__name__)
-
- # Protect method_view with either the permission that was
- # set on the method, the default permission from the class
- # level or zope.Public.
-
- permission = getattr(method, '__grok_require__',
- default_permission)
- make_checker(factory, method_view, permission)
- return True
-
-class TraverserGrokker(martian.ClassGrokker):
- component_class = grok.Traverser
-
- def grok(self, name, factory, context, module_info, templates):
- factory_context = util.determine_class_context(factory, context)
- component.provideAdapter(factory,
- adapts=(factory_context, IBrowserRequest),
- provides=IBrowserPublisher)
- return True
-
-class ModulePageTemplateGrokker(martian.InstanceGrokker):
- # this needs to happen before any other grokkers execute that actually
- # use the templates
- priority = 1000
-
- component_class = grok.PageTemplate
-
- def grok(self, name, instance, context, module_info, templates):
- templates.register(name, instance)
- instance._annotateGrokInfo(name, module_info.dotted_name)
- return True
-
-class ModulePageTemplateFileGrokker(ModulePageTemplateGrokker):
- priority = 1000
- component_class = grok.PageTemplateFile
-
-class FilesystemPageTemplateGrokker(martian.GlobalGrokker):
- # do this early on, but after ModulePageTemplateGrokker, as
- # findFilesystem depends on module-level templates to be
- # already grokked for error reporting
- priority = 999
-
- def grok(self, name, module, context, module_info, templates):
- templates.findFilesystem(module_info)
- return True
-
-class SubscriberGrokker(martian.GlobalGrokker):
-
- def grok(self, name, module, 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)
- return True
-
-class AdapterDecoratorGrokker(martian.GlobalGrokker):
-
- def grok(self, name, module, context, module_info, templates):
- implementers = module_info.getAnnotation('implementers', [])
- for function in implementers:
- interfaces = getattr(function, '__component_adapts__', None)
- if interfaces is None:
- # There's no explicit interfaces defined, so we assume the
- # module context to be the thing adapted.
- util.check_context(module_info.getModule(), context)
- interfaces = (context, )
- component.provideAdapter(
- function, adapts=interfaces, provides=function.__implemented__)
- return True
-
-class StaticResourcesGrokker(martian.GlobalGrokker):
-
- def grok(self, name, module, context, module_info, templates):
- # we're only interested in static resources if this module
- # happens to be a package
- if not module_info.isPackage():
- return False
-
- resource_path = module_info.getResourcePath('static')
- if os.path.isdir(resource_path):
- static_module = module_info.getSubModuleInfo('static')
- if static_module is not None:
- if static_module.isPackage():
- raise GrokError(
- "The 'static' resource directory must not "
- "be a python package.",
- module_info.getModule())
- else:
- raise GrokError(
- "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)
- return True
-
-class GlobalUtilityDirectiveGrokker(martian.GlobalGrokker):
-
- def grok(self, name, module, 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)
- if info.direct:
- obj = info.factory
- else:
- obj = info.factory()
- component.provideUtility(obj,
- provides=info.provides,
- name=info.name)
- return True
-
-class SiteGrokker(martian.ClassGrokker):
- component_class = grok.Site
- priority = 500
-
- def grok(self, name, factory, context, module_info, templates):
- infos = util.class_annotation_list(factory, 'grok.local_utility', None)
- if infos is None:
- return False
-
- for info in infos:
- if info.public and not IContainer.implementedBy(factory):
- raise GrokError(
- "Cannot set public to True with grok.local_utility as "
- "the site (%r) is not a container." %
- factory, factory)
- if info.provides is None:
- if util.check_subclass(info.factory, grok.LocalUtility):
- baseInterfaces = interface.implementedBy(grok.LocalUtility)
- utilityInterfaces = interface.implementedBy(info.factory)
- provides = list(utilityInterfaces - baseInterfaces)
-
- if len(provides) == 0 and len(list(utilityInterfaces)) > 0:
- raise GrokError(
- "Cannot determine which interface to use "
- "for utility registration of %r in site %r. "
- "It implements an interface that is a specialization "
- "of an interface implemented by grok.LocalUtility. "
- "Specify the interface by either using grok.provides "
- "on the utility or passing 'provides' to "
- "grok.local_utility." % (info.factory, factory),
- info.factory)
- else:
- provides = list(interface.implementedBy(info.factory))
-
- 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()
- class_infos = util.class_annotation(factory, 'grok.local_utility',
- [])
- for info in class_infos:
- key = (info.provides, info.name)
- if key in used:
- raise GrokError(
- "Conflicting local utility registration %r in "
- "site %r. Local utilities are registered multiple "
- "times for interface %r and name %r." %
- (info.factory, factory, info.provides, info.name),
- factory)
- used.add(key)
-
- # Make sure that local utilities from subclasses override
- # utilities from base classes if the registration (provided
- # interface, name) is identical.
- overridden_infos = []
- used = set()
- for info in reversed(infos):
- key = (info.provides, info.name)
- if key in used:
- continue
- used.add(key)
- overridden_infos.append(info)
- overridden_infos.reverse()
-
- # store infos on site class
- factory.__grok_utilities_to_install__ = overridden_infos
- component.provideHandler(localUtilityRegistrationSubscriber,
- adapts=(factory, grok.IObjectAddedEvent))
-
- return True
-
-def localUtilityRegistrationSubscriber(site, event):
- """A subscriber that fires to set up local utilities.
- """
- installed = getattr(site, '__grok_utilities_installed__', False)
- if installed:
- return
-
- for info in util.class_annotation(site.__class__,
- 'grok.utilities_to_install', []):
- setupUtility(site, info.factory(), info.provides, name=info.name,
- name_in_container=info.name_in_container,
- public=info.public, setup=info.setup)
-
- # we are done. If this subscriber gets fired again, we therefore
- # do not register utilities anymore
- site.__grok_utilities_installed__ = True
-
-def setupUtility(site, utility, provides, name=u'',
- name_in_container=None, public=False, setup=None):
- """Set up a utility in a site.
-
- site - the site to set up the utility in
- utility - the utility to set up
- provides - the interface the utility should be registered with
- name - the name the utility should be registered under, default
- the empty string (no name)
- name_in_container - if given it will be used to add the utility
- object to its container. Otherwise a name will be made up
- public - if False, the utility will be stored in the site manager. If
- True, the utility will be storedin the site (it is assumed the
- site is a container)
- setup - if not None, it will be called with the utility as its first
- argument. This function can then be used to further set up the
- utility.
- """
- site_manager = site.getSiteManager()
-
- if not public:
- container = site_manager
- else:
- container = site
-
- if name_in_container is None:
- name_in_container = INameChooser(container).chooseName(
- utility.__class__.__name__, utility)
- container[name_in_container] = utility
-
- if setup is not None:
- setup(utility)
-
- site_manager.registerUtility(utility, provided=provides,
- name=name)
-
-class DefinePermissionGrokker(martian.GlobalGrokker):
-
- priority = 1500
-
- def grok(self, name, module, context, module_info, templates):
- permissions = module_info.getAnnotation('grok.define_permission', [])
- for permission in permissions:
- # IPermission.title says that permission ids (and titles,
- # descriptions) *must* be unicode objects. Good news is
- # that the directive handler already made sure we either
- # got pure ASCII or unicode here:
- permission = unicode(permission)
- # TODO permission title and description
- component.provideUtility(Permission(permission, title=permission),
- name=permission)
-
- return True
-
-class AnnotationGrokker(martian.ClassGrokker):
- component_class = grok.Annotation
-
- def grok(self, name, factory, context, module_info, templates):
- adapter_context = util.determine_class_context(factory, context)
- provides = util.class_annotation(factory, 'grok.provides', None)
- if provides is None:
- base_interfaces = interface.implementedBy(grok.Annotation)
- factory_interfaces = interface.implementedBy(factory)
- real_interfaces = list(factory_interfaces - base_interfaces)
- util.check_implements_one_from_list(real_interfaces, factory)
- provides = real_interfaces[0]
-
- key = util.class_annotation(factory, 'grok.name', None)
- if key is None:
- key = factory.__module__ + '.' + factory.__name__
-
- @component.adapter(adapter_context)
- @interface.implementer(provides)
- def getAnnotation(context):
- annotations = IAnnotations(context)
- try:
- result = annotations[key]
- except KeyError:
- result = factory()
- annotations[key] = result
-
- # Containment has to be set up late to allow containment
- # proxies to be applied, if needed. This does not trigger
- # an event and is idempotent if containment is set up
- # already.
- contained_result = contained(result, context, key)
- return contained_result
-
- component.provideAdapter(getAnnotation)
- return True
-
-class ApplicationGrokker(martian.ClassGrokker):
- component_class = grok.Application
- priority = 500
-
- def grok(self, name, factory, context, 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))
- return True
-
-class IndexesGrokker(martian.InstanceGrokker):
- component_class = components.IndexesClass
-
- def grok(self, name, factory, context, module_info, templates):
- site = util.class_annotation(factory, 'grok.site', None)
- if site is None:
- raise GrokError("No site specified for grok.Indexes "
- "subclass in module %r. "
- "Use grok.site() to specify." % module_info.getModule(),
- factory)
- indexes = util.class_annotation(factory, 'grok.indexes', None)
- if indexes is None:
- return False
- context = util.determine_class_context(factory, context)
- catalog_name = util.class_annotation(factory, 'grok.name', u'')
- zope.component.provideHandler(
- IndexesSetupSubscriber(catalog_name, indexes,
- context, module_info),
- adapts=(site,
- grok.IObjectAddedEvent))
- return True
-
-class IndexesSetupSubscriber(object):
- def __init__(self, catalog_name, indexes, context, module_info):
- self.catalog_name = catalog_name
- self.indexes = indexes
- self.context = context
- self.module_info = module_info
-
- def __call__(self, site, event):
- # make sure we have an intids
- self._createIntIds(site)
- # get the catalog
- catalog = self._createCatalog(site)
- # now install indexes
- for name, index in self.indexes.items():
- try:
- index.setup(catalog, name, self.context, self.module_info)
- except DuplicationError:
- raise GrokError(
- "grok.Indexes in module %r causes "
- "creation of catalog index %r in catalog %r, "
- "but an index with that name is already present." %
- (self.module_info.getModule(), name, self.catalog_name),
- None)
-
- def _createCatalog(self, site):
- """Create the catalog if needed and return it.
-
- If the catalog already exists, return that.
- """
- catalog = zope.component.queryUtility(
- ICatalog, name=self.catalog_name, context=site, default=None)
- if catalog is not None:
- return catalog
- catalog = Catalog()
- setupUtility(site, catalog, ICatalog, name=self.catalog_name)
- return catalog
-
- def _createIntIds(self, site):
- """Create intids if needed, and return it.
- """
- intids = zope.component.queryUtility(
- IIntIds, context=site, default=None)
- if intids is not None:
- return intids
- intids = IntIds()
- setupUtility(site, intids, IIntIds)
- return intids
Copied: grok/branches/darrylcousins-branch/src/grok/meta.py (from rev 77321, grok/branches/darrylcousins-branch/src/grok/meta.py)
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/meta.py (rev 0)
+++ grok/branches/darrylcousins-branch/src/grok/meta.py 2007-07-03 02:01:37 UTC (rev 77322)
@@ -0,0 +1,595 @@
+import os
+
+import zope.component.interface
+from zope import interface, component
+from zope.publisher.interfaces.browser import (IDefaultBrowserLayer,
+ IBrowserRequest,
+ IBrowserPublisher)
+from zope.publisher.interfaces.xmlrpc import IXMLRPCRequest
+from zope.security.permission import Permission
+from zope.security.interfaces import IPermission
+from zope.annotation.interfaces import IAnnotations
+
+from zope.app.publisher.xmlrpc import MethodPublisher
+from zope.app.container.interfaces import IContainer
+from zope.app.container.interfaces import INameChooser
+from zope.app.container.contained import contained
+
+from zope.app.intid import IntIds
+from zope.app.intid.interfaces import IIntIds
+from zope.app.catalog.catalog import Catalog
+from zope.app.catalog.interfaces import ICatalog
+
+from zope.exceptions.interfaces import DuplicationError
+
+import martian
+from martian.error import GrokError
+from martian import util
+
+import grok
+from grok import components, formlib
+from grok.util import check_adapts, get_default_permission, make_checker
+
+class ModelGrokker(martian.ClassGrokker):
+ component_class = grok.Model
+
+ def grok(self, name, factory, context, module_info, templates):
+ for field in formlib.get_context_schema_fields(factory):
+ setattr(factory, field.__name__, field.default)
+ return True
+
+class ContainerGrokker(ModelGrokker):
+ component_class = grok.Container
+
+
+class LocalUtilityGrokker(ModelGrokker):
+ component_class = grok.LocalUtility
+
+
+class AdapterGrokker(martian.ClassGrokker):
+ component_class = grok.Adapter
+
+ def grok(self, name, factory, context, module_info, templates):
+ adapter_context = util.determine_class_context(factory, context)
+ provides = util.class_annotation(factory, 'grok.provides', None)
+ if provides is None:
+ util.check_implements_one(factory)
+ name = util.class_annotation(factory, 'grok.name', '')
+ component.provideAdapter(factory, adapts=(adapter_context,),
+ provides=provides,
+ name=name)
+ return True
+
+class MultiAdapterGrokker(martian.ClassGrokker):
+ component_class = grok.MultiAdapter
+
+ def grok(self, name, factory, context, module_info, templates):
+ provides = util.class_annotation(factory, 'grok.provides', None)
+ if provides is None:
+ util.check_implements_one(factory)
+ check_adapts(factory)
+ name = util.class_annotation(factory, 'grok.name', '')
+ component.provideAdapter(factory, provides=provides, name=name)
+ return True
+
+class GlobalUtilityGrokker(martian.ClassGrokker):
+ component_class = grok.GlobalUtility
+
+ def grok(self, name, factory, context, module_info, templates):
+ provides = util.class_annotation(factory, 'grok.provides', None)
+ if provides is None:
+ util.check_implements_one(factory)
+ name = util.class_annotation(factory, 'grok.name', '')
+ component.provideUtility(factory(), provides=provides, name=name)
+ return True
+
+class XMLRPCGrokker(martian.ClassGrokker):
+ component_class = grok.XMLRPC
+
+ def grok(self, name, factory, context, module_info, templates):
+ view_context = util.determine_class_context(factory, context)
+ # XXX We should really not make __FOO__ methods available to
+ # the outside -- need to discuss how to restrict such things.
+ methods = util.methods_from_class(factory)
+
+ default_permission = get_default_permission(factory)
+
+ for method in methods:
+ # Make sure that the class inherits MethodPublisher, so that the
+ # views have a location
+ method_view = type(
+ factory.__name__, (factory, MethodPublisher),
+ {'__call__': method}
+ )
+ component.provideAdapter(
+ method_view, (view_context, IXMLRPCRequest),
+ interface.Interface,
+ name=method.__name__)
+
+ # Protect method_view with either the permission that was
+ # set on the method, the default permission from the class
+ # level or zope.Public.
+ permission = getattr(method, '__grok_require__',
+ default_permission)
+ make_checker(factory, method_view, permission)
+ return True
+
+class ViewGrokker(martian.ClassGrokker):
+ component_class = grok.View
+
+ def grok(self, name, factory, context, module_info, templates):
+ view_context = util.determine_class_context(factory, context)
+
+ factory.module_info = module_info
+ factory_name = factory.__name__.lower()
+
+ if util.check_subclass(factory, components.GrokForm):
+ # setup form_fields from context class if we've encountered a form
+ if getattr(factory, 'form_fields', None) is None:
+ factory.form_fields = formlib.get_auto_fields(view_context)
+
+ if not getattr(factory.render, 'base_method', False):
+ raise GrokError(
+ "It is not allowed to specify a custom 'render' "
+ "method for form %r. Forms either use the default "
+ "template or a custom-supplied one." % factory,
+ factory)
+
+ # find templates
+ template_name = util.class_annotation(factory, 'grok.template',
+ factory_name)
+ template = templates.get(template_name)
+
+ if factory_name != template_name:
+ # grok.template is being used
+ if templates.get(factory_name):
+ raise GrokError("Multiple possible templates for view %r. It "
+ "uses grok.template('%s'), but there is also "
+ "a template called '%s'."
+ % (factory, template_name, factory_name),
+ factory)
+
+ if template:
+ if (getattr(factory, 'render', None) and not
+ util.check_subclass(factory, components.GrokForm)):
+ # we do not accept render and template both for a view
+ # (unless it's a form, they happen to have render.
+ raise GrokError(
+ "Multiple possible ways to render view %r. "
+ "It has both a 'render' method as well as "
+ "an associated template." % factory, factory)
+
+ templates.markAssociated(template_name)
+ factory.template = template
+ else:
+ if not getattr(factory, 'render', None):
+ # we do not accept a view without any way to render it
+ raise GrokError("View %r has no associated template or "
+ "'render' method." % factory, factory)
+
+ view_name = util.class_annotation(factory, 'grok.name',
+ factory_name)
+ # __view_name__ is needed to support IAbsoluteURL on views
+ factory.__view_name__ = view_name
+ component.provideAdapter(factory,
+ adapts=(view_context, IDefaultBrowserLayer),
+ provides=interface.Interface,
+ name=view_name)
+
+ # protect view, public by default
+ default_permission = get_default_permission(factory)
+ make_checker(factory, factory, default_permission)
+
+ # safety belt: make sure that the programmer didn't use
+ # @grok.require on any of the view's methods.
+ methods = util.methods_from_class(factory)
+ for method in methods:
+ if getattr(method, '__grok_require__', None) is not None:
+ raise GrokError('The @grok.require decorator is used for '
+ 'method %r in view %r. It may only be used '
+ 'for XML-RPC methods.'
+ % (method.__name__, factory), factory)
+ return True
+
+
+class JSONGrokker(martian.ClassGrokker):
+ component_class = grok.JSON
+
+ def grok(self, name, factory, context, module_info, templates):
+ view_context = util.determine_class_context(factory, context)
+ methods = util.methods_from_class(factory)
+
+ default_permission = get_default_permission(factory)
+
+ for method in methods:
+ # Create a new class with a __view_name__ attribute so the
+ # JSON class knows what method to call.
+ method_view = type(
+ factory.__name__, (factory,),
+ {'__view_name__': method.__name__}
+ )
+ component.provideAdapter(
+ method_view, (view_context, IDefaultBrowserLayer),
+ interface.Interface,
+ name=method.__name__)
+
+ # Protect method_view with either the permission that was
+ # set on the method, the default permission from the class
+ # level or zope.Public.
+
+ permission = getattr(method, '__grok_require__',
+ default_permission)
+ make_checker(factory, method_view, permission)
+ return True
+
+class TraverserGrokker(martian.ClassGrokker):
+ component_class = grok.Traverser
+
+ def grok(self, name, factory, context, module_info, templates):
+ factory_context = util.determine_class_context(factory, context)
+ component.provideAdapter(factory,
+ adapts=(factory_context, IBrowserRequest),
+ provides=IBrowserPublisher)
+ return True
+
+class ModulePageTemplateGrokker(martian.InstanceGrokker):
+ # this needs to happen before any other grokkers execute that actually
+ # use the templates
+ priority = 1000
+
+ component_class = grok.PageTemplate
+
+ def grok(self, name, instance, context, module_info, templates):
+ templates.register(name, instance)
+ instance._annotateGrokInfo(name, module_info.dotted_name)
+ return True
+
+class ModulePageTemplateFileGrokker(ModulePageTemplateGrokker):
+ priority = 1000
+ component_class = grok.PageTemplateFile
+
+class FilesystemPageTemplateGrokker(martian.GlobalGrokker):
+ # do this early on, but after ModulePageTemplateGrokker, as
+ # findFilesystem depends on module-level templates to be
+ # already grokked for error reporting
+ priority = 999
+
+ def grok(self, name, module, context, module_info, templates):
+ templates.findFilesystem(module_info)
+ return True
+
+class SubscriberGrokker(martian.GlobalGrokker):
+
+ def grok(self, name, module, 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)
+ return True
+
+class AdapterDecoratorGrokker(martian.GlobalGrokker):
+
+ def grok(self, name, module, context, module_info, templates):
+ implementers = module_info.getAnnotation('implementers', [])
+ for function in implementers:
+ interfaces = getattr(function, '__component_adapts__', None)
+ if interfaces is None:
+ # There's no explicit interfaces defined, so we assume the
+ # module context to be the thing adapted.
+ util.check_context(module_info.getModule(), context)
+ interfaces = (context, )
+ component.provideAdapter(
+ function, adapts=interfaces, provides=function.__implemented__)
+ return True
+
+class StaticResourcesGrokker(martian.GlobalGrokker):
+
+ def grok(self, name, module, context, module_info, templates):
+ # we're only interested in static resources if this module
+ # happens to be a package
+ if not module_info.isPackage():
+ return False
+
+ resource_path = module_info.getResourcePath('static')
+ if os.path.isdir(resource_path):
+ static_module = module_info.getSubModuleInfo('static')
+ if static_module is not None:
+ if static_module.isPackage():
+ raise GrokError(
+ "The 'static' resource directory must not "
+ "be a python package.",
+ module_info.getModule())
+ else:
+ raise GrokError(
+ "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)
+ return True
+
+class GlobalUtilityDirectiveGrokker(martian.GlobalGrokker):
+
+ def grok(self, name, module, 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)
+ if info.direct:
+ obj = info.factory
+ else:
+ obj = info.factory()
+ component.provideUtility(obj,
+ provides=info.provides,
+ name=info.name)
+ return True
+
+class SiteGrokker(martian.ClassGrokker):
+ component_class = grok.Site
+ priority = 500
+
+ def grok(self, name, factory, context, module_info, templates):
+ infos = util.class_annotation_list(factory, 'grok.local_utility', None)
+ if infos is None:
+ return False
+
+ for info in infos:
+ if info.public and not IContainer.implementedBy(factory):
+ raise GrokError(
+ "Cannot set public to True with grok.local_utility as "
+ "the site (%r) is not a container." %
+ factory, factory)
+ if info.provides is None:
+ if util.check_subclass(info.factory, grok.LocalUtility):
+ baseInterfaces = interface.implementedBy(grok.LocalUtility)
+ utilityInterfaces = interface.implementedBy(info.factory)
+ provides = list(utilityInterfaces - baseInterfaces)
+
+ if len(provides) == 0 and len(list(utilityInterfaces)) > 0:
+ raise GrokError(
+ "Cannot determine which interface to use "
+ "for utility registration of %r in site %r. "
+ "It implements an interface that is a specialization "
+ "of an interface implemented by grok.LocalUtility. "
+ "Specify the interface by either using grok.provides "
+ "on the utility or passing 'provides' to "
+ "grok.local_utility." % (info.factory, factory),
+ info.factory)
+ else:
+ provides = list(interface.implementedBy(info.factory))
+
+ 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()
+ class_infos = util.class_annotation(factory, 'grok.local_utility',
+ [])
+ for info in class_infos:
+ key = (info.provides, info.name)
+ if key in used:
+ raise GrokError(
+ "Conflicting local utility registration %r in "
+ "site %r. Local utilities are registered multiple "
+ "times for interface %r and name %r." %
+ (info.factory, factory, info.provides, info.name),
+ factory)
+ used.add(key)
+
+ # Make sure that local utilities from subclasses override
+ # utilities from base classes if the registration (provided
+ # interface, name) is identical.
+ overridden_infos = []
+ used = set()
+ for info in reversed(infos):
+ key = (info.provides, info.name)
+ if key in used:
+ continue
+ used.add(key)
+ overridden_infos.append(info)
+ overridden_infos.reverse()
+
+ # store infos on site class
+ factory.__grok_utilities_to_install__ = overridden_infos
+ component.provideHandler(localUtilityRegistrationSubscriber,
+ adapts=(factory, grok.IObjectAddedEvent))
+
+ return True
+
+def localUtilityRegistrationSubscriber(site, event):
+ """A subscriber that fires to set up local utilities.
+ """
+ installed = getattr(site, '__grok_utilities_installed__', False)
+ if installed:
+ return
+
+ for info in util.class_annotation(site.__class__,
+ 'grok.utilities_to_install', []):
+ setupUtility(site, info.factory(), info.provides, name=info.name,
+ name_in_container=info.name_in_container,
+ public=info.public, setup=info.setup)
+
+ # we are done. If this subscriber gets fired again, we therefore
+ # do not register utilities anymore
+ site.__grok_utilities_installed__ = True
+
+def setupUtility(site, utility, provides, name=u'',
+ name_in_container=None, public=False, setup=None):
+ """Set up a utility in a site.
+
+ site - the site to set up the utility in
+ utility - the utility to set up
+ provides - the interface the utility should be registered with
+ name - the name the utility should be registered under, default
+ the empty string (no name)
+ name_in_container - if given it will be used to add the utility
+ object to its container. Otherwise a name will be made up
+ public - if False, the utility will be stored in the site manager. If
+ True, the utility will be storedin the site (it is assumed the
+ site is a container)
+ setup - if not None, it will be called with the utility as its first
+ argument. This function can then be used to further set up the
+ utility.
+ """
+ site_manager = site.getSiteManager()
+
+ if not public:
+ container = site_manager
+ else:
+ container = site
+
+ if name_in_container is None:
+ name_in_container = INameChooser(container).chooseName(
+ utility.__class__.__name__, utility)
+ container[name_in_container] = utility
+
+ if setup is not None:
+ setup(utility)
+
+ site_manager.registerUtility(utility, provided=provides,
+ name=name)
+
+class DefinePermissionGrokker(martian.GlobalGrokker):
+
+ priority = 1500
+
+ def grok(self, name, module, context, module_info, templates):
+ permissions = module_info.getAnnotation('grok.define_permission', [])
+ for permission in permissions:
+ # IPermission.title says that permission ids (and titles,
+ # descriptions) *must* be unicode objects. Good news is
+ # that the directive handler already made sure we either
+ # got pure ASCII or unicode here:
+ permission = unicode(permission)
+ # TODO permission title and description
+ component.provideUtility(Permission(permission, title=permission),
+ name=permission)
+
+ return True
+
+class AnnotationGrokker(martian.ClassGrokker):
+ component_class = grok.Annotation
+
+ def grok(self, name, factory, context, module_info, templates):
+ adapter_context = util.determine_class_context(factory, context)
+ provides = util.class_annotation(factory, 'grok.provides', None)
+ if provides is None:
+ base_interfaces = interface.implementedBy(grok.Annotation)
+ factory_interfaces = interface.implementedBy(factory)
+ real_interfaces = list(factory_interfaces - base_interfaces)
+ util.check_implements_one_from_list(real_interfaces, factory)
+ provides = real_interfaces[0]
+
+ key = util.class_annotation(factory, 'grok.name', None)
+ if key is None:
+ key = factory.__module__ + '.' + factory.__name__
+
+ @component.adapter(adapter_context)
+ @interface.implementer(provides)
+ def getAnnotation(context):
+ annotations = IAnnotations(context)
+ try:
+ result = annotations[key]
+ except KeyError:
+ result = factory()
+ annotations[key] = result
+
+ # Containment has to be set up late to allow containment
+ # proxies to be applied, if needed. This does not trigger
+ # an event and is idempotent if containment is set up
+ # already.
+ contained_result = contained(result, context, key)
+ return contained_result
+
+ component.provideAdapter(getAnnotation)
+ return True
+
+class ApplicationGrokker(martian.ClassGrokker):
+ component_class = grok.Application
+ priority = 500
+
+ def grok(self, name, factory, context, 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))
+ return True
+
+class IndexesGrokker(martian.InstanceGrokker):
+ component_class = components.IndexesClass
+
+ def grok(self, name, factory, context, module_info, templates):
+ site = util.class_annotation(factory, 'grok.site', None)
+ if site is None:
+ raise GrokError("No site specified for grok.Indexes "
+ "subclass in module %r. "
+ "Use grok.site() to specify." % module_info.getModule(),
+ factory)
+ indexes = util.class_annotation(factory, 'grok.indexes', None)
+ if indexes is None:
+ return False
+ context = util.determine_class_context(factory, context)
+ catalog_name = util.class_annotation(factory, 'grok.name', u'')
+ zope.component.provideHandler(
+ IndexesSetupSubscriber(catalog_name, indexes,
+ context, module_info),
+ adapts=(site,
+ grok.IObjectAddedEvent))
+ return True
+
+class IndexesSetupSubscriber(object):
+ def __init__(self, catalog_name, indexes, context, module_info):
+ self.catalog_name = catalog_name
+ self.indexes = indexes
+ self.context = context
+ self.module_info = module_info
+
+ def __call__(self, site, event):
+ # make sure we have an intids
+ self._createIntIds(site)
+ # get the catalog
+ catalog = self._createCatalog(site)
+ # now install indexes
+ for name, index in self.indexes.items():
+ try:
+ index.setup(catalog, name, self.context, self.module_info)
+ except DuplicationError:
+ raise GrokError(
+ "grok.Indexes in module %r causes "
+ "creation of catalog index %r in catalog %r, "
+ "but an index with that name is already present." %
+ (self.module_info.getModule(), name, self.catalog_name),
+ None)
+
+ def _createCatalog(self, site):
+ """Create the catalog if needed and return it.
+
+ If the catalog already exists, return that.
+ """
+ catalog = zope.component.queryUtility(
+ ICatalog, name=self.catalog_name, context=site, default=None)
+ if catalog is not None:
+ return catalog
+ catalog = Catalog()
+ setupUtility(site, catalog, ICatalog, name=self.catalog_name)
+ return catalog
+
+ def _createIntIds(self, site):
+ """Create intids if needed, and return it.
+ """
+ intids = zope.component.queryUtility(
+ IIntIds, context=site, default=None)
+ if intids is not None:
+ return intids
+ intids = IntIds()
+ setupUtility(site, intids, IIntIds)
+ return intids
Property changes on: grok/branches/darrylcousins-branch/src/grok/meta.py
___________________________________________________________________
Name: svn:keywords
+ Id
Deleted: grok/branches/darrylcousins-branch/src/grok/tests/adapter/adapterdecorator.py
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/tests/adapter/adapterdecorator.py 2007-07-03 02:00:16 UTC (rev 77321)
+++ grok/branches/darrylcousins-branch/src/grok/tests/adapter/adapterdecorator.py 2007-07-03 02:01:37 UTC (rev 77322)
@@ -1,71 +0,0 @@
-"""
- >>> grok.grok(__name__)
- >>>
- >>> cave = Cave()
- >>> home = IHome(cave)
- >>> IHome.providedBy(home)
- True
- >>>
- >>> isinstance(home, Home)
- True
- >>> morehome = IMoreHome(cave)
- >>> IHome.providedBy(morehome)
- True
- >>> isinstance(morehome, Home)
- True
- >>> yetanotherhome = IYetAnotherHome(cave)
- >>> IHome.providedBy(yetanotherhome)
- True
- >>> isinstance(yetanotherhome, Home)
- True
-
- >>> from grok.tests.adapter import noarguments_fixture
- Traceback (most recent call last):
- ...
- GrokImportError: @grok.adapter requires at least one argument.
-
- >>> from grok.tests.adapter import functionasargument_fixture
- Traceback (most recent call last):
- ...
- GrokImportError: @grok.adapter requires at least one argument.
-
-"""
-
-import grok
-from zope import interface
-
-class IDummy(interface.Interface):
- pass
-
-class ICave(interface.Interface):
- pass
-
-class IHome(interface.Interface):
- pass
-
-class IMoreHome(interface.Interface):
- pass
-
-class IYetAnotherHome(interface.Interface):
- pass
-
-class Cave(grok.Model):
- grok.implements(ICave)
- pass
-
-class Home(object):
- grok.implements(IHome)
-
- at grok.adapter(Cave)
- at grok.implementer(IHome)
-def home_for_cave(cave):
- return Home()
-
- at grok.adapter(ICave)
- at grok.implementer(IMoreHome)
-def more_home_for_cave(cave):
- return Home()
-
- at grok.implementer(IYetAnotherHome)
-def yet_another_home_for_cave(cave):
- return Home()
Copied: grok/branches/darrylcousins-branch/src/grok/tests/adapter/adapterdecorator.py (from rev 77321, grok/branches/darrylcousins-branch/src/grok/tests/adapter/adapterdecorator.py)
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/tests/adapter/adapterdecorator.py (rev 0)
+++ grok/branches/darrylcousins-branch/src/grok/tests/adapter/adapterdecorator.py 2007-07-03 02:01:37 UTC (rev 77322)
@@ -0,0 +1,71 @@
+"""
+ >>> grok.grok(__name__)
+ >>>
+ >>> cave = Cave()
+ >>> home = IHome(cave)
+ >>> IHome.providedBy(home)
+ True
+ >>>
+ >>> isinstance(home, Home)
+ True
+ >>> morehome = IMoreHome(cave)
+ >>> IHome.providedBy(morehome)
+ True
+ >>> isinstance(morehome, Home)
+ True
+ >>> yetanotherhome = IYetAnotherHome(cave)
+ >>> IHome.providedBy(yetanotherhome)
+ True
+ >>> isinstance(yetanotherhome, Home)
+ True
+
+ >>> from grok.tests.adapter import noarguments_fixture
+ Traceback (most recent call last):
+ ...
+ GrokImportError: @grok.adapter requires at least one argument.
+
+ >>> from grok.tests.adapter import functionasargument_fixture
+ Traceback (most recent call last):
+ ...
+ GrokImportError: @grok.adapter requires at least one argument.
+
+"""
+
+import grok
+from zope import interface
+
+class IDummy(interface.Interface):
+ pass
+
+class ICave(interface.Interface):
+ pass
+
+class IHome(interface.Interface):
+ pass
+
+class IMoreHome(interface.Interface):
+ pass
+
+class IYetAnotherHome(interface.Interface):
+ pass
+
+class Cave(grok.Model):
+ grok.implements(ICave)
+ pass
+
+class Home(object):
+ grok.implements(IHome)
+
+ at grok.adapter(Cave)
+ at grok.implementer(IHome)
+def home_for_cave(cave):
+ return Home()
+
+ at grok.adapter(ICave)
+ at grok.implementer(IMoreHome)
+def more_home_for_cave(cave):
+ return Home()
+
+ at grok.implementer(IYetAnotherHome)
+def yet_another_home_for_cave(cave):
+ return Home()
Deleted: grok/branches/darrylcousins-branch/src/grok/tests/adapter/functionasargument_fixture.py
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/tests/adapter/functionasargument_fixture.py 2007-07-03 02:00:16 UTC (rev 77321)
+++ grok/branches/darrylcousins-branch/src/grok/tests/adapter/functionasargument_fixture.py 2007-07-03 02:01:37 UTC (rev 77322)
@@ -1,10 +0,0 @@
-import grok
-from zope import interface
-
-class IDummy(interface.Interface):
- pass
-
- at grok.adapter
- at grok.implementer(IDummy)
-def decorator_called_with_function_as_argument(cave):
- pass
Copied: grok/branches/darrylcousins-branch/src/grok/tests/adapter/functionasargument_fixture.py (from rev 77321, grok/branches/darrylcousins-branch/src/grok/tests/adapter/functionasargument_fixture.py)
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/tests/adapter/functionasargument_fixture.py (rev 0)
+++ grok/branches/darrylcousins-branch/src/grok/tests/adapter/functionasargument_fixture.py 2007-07-03 02:01:37 UTC (rev 77322)
@@ -0,0 +1,10 @@
+import grok
+from zope import interface
+
+class IDummy(interface.Interface):
+ pass
+
+ at grok.adapter
+ at grok.implementer(IDummy)
+def decorator_called_with_function_as_argument(cave):
+ pass
Deleted: grok/branches/darrylcousins-branch/src/grok/tests/adapter/noarguments_fixture.py
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/tests/adapter/noarguments_fixture.py 2007-07-03 02:00:16 UTC (rev 77321)
+++ grok/branches/darrylcousins-branch/src/grok/tests/adapter/noarguments_fixture.py 2007-07-03 02:01:37 UTC (rev 77322)
@@ -1,10 +0,0 @@
-import grok
-from zope import interface
-
-class IDummy(interface.Interface):
- pass
-
- at grok.adapter()
- at grok.implementer(IDummy)
-def decorator_called_with_no_arguments(cave):
- pass
Copied: grok/branches/darrylcousins-branch/src/grok/tests/adapter/noarguments_fixture.py (from rev 77321, grok/branches/darrylcousins-branch/src/grok/tests/adapter/noarguments_fixture.py)
===================================================================
--- grok/branches/darrylcousins-branch/src/grok/tests/adapter/noarguments_fixture.py (rev 0)
+++ grok/branches/darrylcousins-branch/src/grok/tests/adapter/noarguments_fixture.py 2007-07-03 02:01:37 UTC (rev 77322)
@@ -0,0 +1,10 @@
+import grok
+from zope import interface
+
+class IDummy(interface.Interface):
+ pass
+
+ at grok.adapter()
+ at grok.implementer(IDummy)
+def decorator_called_with_no_arguments(cave):
+ pass
More information about the Checkins
mailing list