Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Check if the code is up to date with the Grok trunk. Port over commen…
…ts which have been added. Clean unused imports.
- Loading branch information
1 parent
2057e34
commit dece0cd
Showing
7 changed files
with
370 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
############################################################################## | ||
# | ||
# Copyright (c) 2006-2009 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. | ||
# | ||
############################################################################## | ||
|
||
from grokcore.site.directive import local_utility | ||
from grokcore.component import provides | ||
from grokcore.site.components import Site, LocalUtility | ||
|
||
import grokcore.site.testing | ||
|
||
from grokcore.site.interfaces import IGrokcoreSiteAPI | ||
__all__ = list(IGrokcoreSiteAPI) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
############################################################################## | ||
# | ||
# Copyright (c) 2006-2009 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. | ||
# | ||
############################################################################## | ||
|
||
from grokcore.component.interfaces import IContext | ||
|
||
from persistent import Persistent | ||
|
||
from zope.interface import implements | ||
|
||
from zope.app.component.site import SiteManagerContainer | ||
|
||
from zope.app.container.contained import Contained | ||
|
||
|
||
class Site(SiteManagerContainer): | ||
"""Mixin for creating sites in Grok applications. | ||
When an application `grok.Model` or `grok.Container` also inherits | ||
from `grok.Site`, then it can additionally support the registration | ||
of local Component Architecture entities like `grok.LocalUtility` | ||
and `grok.Indexes` objects; see those classes for more information. | ||
""" | ||
|
||
|
||
class LocalUtility(Contained, Persistent): | ||
"""The base class for local utilities in Grok applications. | ||
Although application developers can create local utilies without | ||
actually subclassing `grok.LocalUtility`, they gain three benefits | ||
from doing so. First, their code is more readable because their | ||
classes "look like" local utilities to casual readers. Second, | ||
their utility will know how to persist itself to the Zope database, | ||
which means that they can set its object attributes and know that | ||
the values are getting automatically saved. Third, they can omit | ||
the `grok.provides()` directive naming the interface that the | ||
utility provides, if their class only `grok.implements()` a single | ||
interface (unless the interface is one that the `grok.LocalUtility` | ||
already implements, in which case Grok cannot tell them apart, and | ||
`grok.provides()` must be used explicitly anyway). | ||
""" | ||
implements(IContext) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
############################################################################## | ||
# | ||
# 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 directives. | ||
""" | ||
|
||
import grokcore.component | ||
|
||
from grokcore.site.components import LocalUtility | ||
|
||
from zope import interface | ||
from zope.interface.interfaces import IInterface | ||
|
||
import martian | ||
from martian import util | ||
from martian.error import GrokImportError | ||
|
||
class local_utility(martian.Directive): | ||
scope = martian.CLASS | ||
store = martian.DICT | ||
|
||
def factory(self, factory, provides=None, name=u'', | ||
setup=None, public=False, name_in_container=None): | ||
if provides is not None and not IInterface.providedBy(provides): | ||
raise GrokImportError("You can only pass an interface to the " | ||
"provides argument of %s." % self.name) | ||
|
||
if provides is None: | ||
provides = grokcore.component.provides.bind().get(factory) | ||
|
||
if provides is None: | ||
if util.check_subclass(factory, LocalUtility): | ||
baseInterfaces = interface.implementedBy(LocalUtility) | ||
utilityInterfaces = interface.implementedBy(factory) | ||
provides = list(utilityInterfaces - baseInterfaces) | ||
|
||
if len(provides) == 0 and len(list(utilityInterfaces)) > 0: | ||
raise GrokImportError( | ||
"Cannot determine which interface to use " | ||
"for utility registration of %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." % factory, factory) | ||
else: | ||
provides = list(interface.implementedBy(factory)) | ||
|
||
util.check_implements_one_from_list(provides, factory) | ||
provides = provides[0] | ||
|
||
if (provides, name) in self.frame.f_locals.get(self.dotted_name(), {}): | ||
raise GrokImportError( | ||
"Conflicting local utility registration %r. " | ||
"Local utilities are registered multiple " | ||
"times for interface %r and name %r." % | ||
(factory, provides, name), factory) | ||
|
||
info = LocalUtilityInfo(factory, provides, name, setup, public, | ||
name_in_container) | ||
return (provides, name), info | ||
|
||
|
||
class LocalUtilityInfo(object): | ||
"""The information about how to register a local utility. | ||
An instance of this class is created for each `grok.local_utility()` | ||
in a Grok application's code, to remember how the user wants their | ||
local utility registered. Later, whenever the application creates | ||
new instances of the site or application for which the local utility | ||
directive was supplied, this block of information is used as the | ||
parameters to the creation of the local utility which is created | ||
along with the new site in the Zope database. | ||
""" | ||
_order = 0 | ||
|
||
def __init__(self, factory, provides, name=u'', | ||
setup=None, public=False, name_in_container=None): | ||
self.factory = factory | ||
self.provides = provides | ||
self.name = name | ||
self.setup = setup | ||
self.public = public | ||
self.name_in_container = name_in_container | ||
|
||
self.order = LocalUtilityInfo._order | ||
LocalUtilityInfo._order += 1 | ||
|
||
def __cmp__(self, other): | ||
# LocalUtilityInfos have an inherit sort order by which the | ||
# registrations take place. | ||
return cmp(self.order, other.order) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
############################################################################## | ||
# | ||
# Copyright (c) 2006-2009 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. | ||
# | ||
############################################################################## | ||
|
||
from zope.interface import Interface, Attribute | ||
|
||
|
||
class IBaseClasses(Interface): | ||
Site = Attribute("Mixin class for sites.") | ||
LocalUtility = Attribute("Base class for local utilities.") | ||
|
||
|
||
class IDirectives(Interface): | ||
def local_utility(factory, provides=None, name=u'', | ||
setup=None, public=False, name_in_container=None): | ||
"""Register a local utility. | ||
factory - the factory that creates the local utility | ||
provides - the interface the utility should be looked up with | ||
name - the name of the utility | ||
setup - a callable that receives the utility as its single argument, | ||
it is called after the utility has been created and stored | ||
public - if False, the utility will be stored below ++etc++site | ||
if True, the utility will be stored directly in the site. | ||
The site should in this case be a container. | ||
name_in_container - the name to use for storing the utility | ||
""" | ||
|
||
def provides(interface): | ||
"""Explicitly specify with which interface a component will be | ||
looked up.""" | ||
|
||
|
||
class IGrokcoreSiteAPI(IBaseClasses, IDirectives): | ||
"""grokcore.site's public API.""" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
############################################################################# | ||
# | ||
# Copyright (c) 2006-2009 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. | ||
# | ||
############################################################################## | ||
|
||
from zope import component | ||
|
||
from zope.app.container.interfaces import IContainer, IObjectAddedEvent | ||
from zope.app.container.interfaces import INameChooser | ||
|
||
import martian | ||
from martian.error import GrokError | ||
|
||
import grokcore.site | ||
|
||
|
||
class SiteGrokker(martian.ClassGrokker): | ||
martian.component(grokcore.site.Site) | ||
martian.priority(500) | ||
martian.directive(grokcore.site.local_utility, name='infos') | ||
|
||
def execute(self, factory, config, infos, **kw): | ||
if not infos: | ||
return False | ||
|
||
infos = infos.values() | ||
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) | ||
|
||
# Store the list of info objects in their "natural" order on the | ||
# site class. They will be picked up by a subscriber doing the | ||
# actual registrations in definition order. | ||
factory.__grok_utilities_to_install__ = sorted(infos) | ||
adapts = (factory, IObjectAddedEvent) | ||
|
||
config.action( | ||
discriminator=None, | ||
callable=component.provideHandler, | ||
args=(localUtilityRegistrationSubscriber, adapts), | ||
) | ||
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 getattr(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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
############################################################################## | ||
# | ||
# Copyright (c) 2006-2009 Zope Corporation and Contributors. | ||
# All Rights Reserved. | ||
# | ||
# This software is subject to the provisions of the Zope Public License, | ||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. | ||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | ||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | ||
# FOR A PARTICULAR PURPOSE. | ||
# | ||
############################################################################## | ||
|
||
import grokcore.component | ||
from zope.app.component.site import LocalSiteManager | ||
from zope.app.container.interfaces import IObjectAddedEvent | ||
|
||
from grokcore.site.components import Site | ||
|
||
@grokcore.component.subscribe(Site, IObjectAddedEvent) | ||
def addSiteHandler(site, event): | ||
"""Add a local site manager to a Grok site object upon its creation. | ||
Grok registers this function so that it gets called each time a | ||
`grok.Site` instance is added to a container. It creates a local | ||
site manager and installs it on the newly created site. | ||
""" | ||
|
||
sitemanager = LocalSiteManager(site) | ||
# LocalSiteManager creates the 'default' folder in its __init__. | ||
# It's not needed anymore in new versions of Zope 3, therefore we | ||
# remove it | ||
del sitemanager['default'] | ||
site.setSiteManager(sitemanager) |