[Zope3-checkins] CVS: Zope3/src/zope/app/services - error.py:1.1.2.1 interface.zcml:1.1.2.1 README.txt:1.4.10.2 adapter.py:1.14.2.2 auth.py:1.15.10.2 cache.py:1.9.10.2 configure.zcml:1.29.2.2 connection.py:1.11.10.2 event.py:1.24.4.2 field.py:1.7.18.2 folder.py:1.6.10.2 hub.py:1.10.10.2 interface.py:1.5.4.1 module.py:1.2.26.2 pagefolder.py:1.5.10.2 queryfield.py:1.2.22.2 registration.py:1.1.2.2 role.py:1.4.18.2 service.py:1.18.10.2 utility.py:1.6.10.2 utility.txt:1.1.2.2 view.py:1.18.4.2 zpt.py:1.10.10.2
Albertas Agejevas
alga@codeworks.lt
Mon, 23 Jun 2003 10:20:53 -0400
Update of /cvs-repository/Zope3/src/zope/app/services
In directory cvs.zope.org:/tmp/cvs-serv16963/src/zope/app/services
Modified Files:
Tag: cw-mail-branch
README.txt adapter.py auth.py cache.py configure.zcml
connection.py event.py field.py folder.py hub.py interface.py
module.py pagefolder.py queryfield.py registration.py role.py
service.py utility.py utility.txt view.py zpt.py
Added Files:
Tag: cw-mail-branch
error.py interface.zcml
Log Message:
One more sync with HEAD.
=== Added File Zope3/src/zope/app/services/error.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Error reporting service
This is a port of the Zope 2 error reporting object
$Id: error.py,v 1.1.2.1 2003/06/23 14:20:21 alga Exp $
"""
from persistence import Persistent
from random import random
from thread import allocate_lock
from types import StringTypes
from zope.app.interfaces.services.error import IErrorReportingService
from zope.app.interfaces.services.error import ILocalErrorReportingService
from zope.app.interfaces.services.service import ISimpleService
from zope.context import ContextMethod
from zope.exceptions.exceptionformatter import format_exception
from zope.interface import implements
import logging
import time
#Restrict the rate at which errors are sent to the Event Log
_rate_restrict_pool = {}
# The number of seconds that must elapse on average between sending two
# exceptions of the same name into the the Event Log. one per minute.
_rate_restrict_period = 60
# The number of exceptions to allow in a burst before the above limit
# kicks in. We allow five exceptions, before limiting them to one per
# minute.
_rate_restrict_burst = 5
# _temp_logs holds the logs.
_temp_logs = {} # { oid -> [ traceback string ] }
cleanup_lock = allocate_lock()
class ErrorReportingService(Persistent):
"""Error Reporting Service
"""
implements(IErrorReportingService,
ILocalErrorReportingService,
ISimpleService,
)
keep_entries = 20
copy_to_zlog = 0
_ignored_exceptions = ('Unauthorized',)
def _getLog(self):
"""Returns the log for this object.
Careful, the log is shared between threads.
"""
log = _temp_logs.get(self._p_oid, None)
if log is None:
log = []
_temp_logs[self._p_oid] = log
return log
# Exceptions that happen all the time, so we dont need
# to log them. Eventually this should be configured
# through-the-web.
def raising(self, info, request=None):
"""Log an exception.
Called by ZopePublication.handleException method.
"""
now = time.time()
try:
tb_text = None
tb_html = None
strtype = str(getattr(info[0], '__name__', info[0]))
if strtype in self._ignored_exceptions:
return
if not isinstance(info[2], StringTypes):
tb_text = ''.join(
format_exception(*info, **{'as_html': 0}))
tb_html = ''.join(
format_exception(*info, **{'as_html': 1}))
else:
tb_text = info[2]
url = None
username = None
req_html = None
if request:
# XXX: Temporary fix, which Steve should undo. URL is
# just too HTTPRequest-specific.
if hasattr(request, 'URL'):
url = request.URL
try:
# XXX: UnauthenticatedPrincipal does not have getLogin()
if hasattr(request.user, 'getLogin'):
login = request.user.getLogin()
else:
login = 'unauthenticated'
username = ', '.join((login,
request.user.getId(),
request.user.getTitle(),
request.user.getDescription()
))
# When there's an unauthorized access, request.user is
# not set, so we get an AttributeError
# XXX is this right? Surely request.user should be set!
# XXX Answer: Catching AttributeError is correct for the
# simple reason that UnauthenticatedUser (which
# I always use during coding), has no 'getLogin()'
# method. However, for some reason this except
# does **NOT** catch these errors.
except AttributeError:
pass
req_html = ''.join(['%s : %s<br>' % item
for item in request.items()])
try:
strv = str(info[1])
# A call to str(obj) could raise anything at all.
# We'll ignore these errors, and print something
# useful instead, but also log the error.
except:
logging.getLogger('SiteError').exception(
'Error in ErrorReportingService while getting a str '
'representation of an object')
strv = '<unprintable %s object>' % (
str(type(info[1]).__name__)
)
log = self._getLog()
entry_id = str(now) + str(random()) # Low chance of collision
log.append({
'type': strtype,
'value': strv,
'time': time.ctime(now),
'id': entry_id,
'tb_text': tb_text,
'tb_html': tb_html,
'username': username,
'url': url,
'req_html': req_html,
})
cleanup_lock.acquire()
try:
if len(log) >= self.keep_entries:
del log[:-self.keep_entries]
finally:
cleanup_lock.release()
if self.copy_to_zlog:
self._do_copy_to_zlog(now, strtype, str(url), info)
finally:
info = None
raising = ContextMethod(raising)
def _do_copy_to_zlog(self, now, strtype, url, info):
# XXX info is unused; logging.exception() will call sys.exc_info()
# work around this with an evil hack
when = _rate_restrict_pool.get(strtype,0)
if now > when:
next_when = max(when,
now - _rate_restrict_burst*_rate_restrict_period)
next_when += _rate_restrict_period
_rate_restrict_pool[strtype] = next_when
try:
raise info[0], info[1], info[2]
except:
logging.getLogger('SiteError').exception(str(url))
def getProperties(self):
return {
'keep_entries': self.keep_entries,
'copy_to_zlog': self.copy_to_zlog,
'ignored_exceptions': self._ignored_exceptions,
}
getProperties = ContextMethod(getProperties)
def setProperties(self, keep_entries, copy_to_zlog=0,
ignored_exceptions=()):
"""Sets the properties of this site error log.
"""
copy_to_zlog = bool(copy_to_zlog)
self.keep_entries = int(keep_entries)
self.copy_to_zlog = copy_to_zlog
self._ignored_exceptions = tuple(
filter(None, map(str, ignored_exceptions))
)
setProperties = ContextMethod(setProperties)
def getLogEntries(self):
"""Returns the entries in the log, most recent first.
Makes a copy to prevent changes.
"""
res = [entry.copy() for entry in self._getLog()]
res.reverse()
return res
getLogEntries = ContextMethod(getLogEntries)
def getLogEntryById(self, id):
"""Returns the specified log entry.
Makes a copy to prevent changes. Returns None if not found.
"""
for entry in self._getLog():
if entry['id'] == id:
return entry.copy()
return None
getLogEntryById = ContextMethod(getLogEntryById)
def _cleanup_temp_log():
_temp_logs.clear()
_clear = _cleanup_temp_log
# Register our cleanup with Testing.CleanUp to make writing unit tests simpler.
from zope.testing.cleanup import addCleanUp
addCleanUp(_clear)
del addCleanUp
# XXX Pickle backward compatability
import sys
sys.modules['zope.app.services.errorr'
] = sys.modules['zope.app.services.error']
=== Added File Zope3/src/zope/app/services/interface.zcml ===
<zopeConfigure xmlns="http://namespaces.zope.org/zope">
<content class=".interface.LocalInterfaceService">
<factory
id="zope.app.services.LocalInterfaceService"
permission="zope.ManageServices"
/>
<require
permission="zope.ManageServices"
interface="zope.app.interfaces.component.IInterfaceService"
/>
</content>
</zopeConfigure>
=== Zope3/src/zope/app/services/README.txt 1.4.10.1 => 1.4.10.2 ===
--- Zope3/src/zope/app/services/README.txt:1.4.10.1 Sun Jun 22 10:23:26 2003
+++ Zope3/src/zope/app/services/README.txt Mon Jun 23 10:20:21 2003
@@ -8,7 +8,7 @@
This package includes implementations of several local services.
It also contains infrastructure for implementing local services.
-Implementing lolcal services is not too difficult, but there can be a
+Implementing local services is not too difficult, but there can be a
lot of details that are hard to remember.
A service is a component that implements a specific interface *and*
@@ -32,7 +32,7 @@
services by definition have nothing "above" them.
(Note that it's up to the service to decide what form the
- collaboration will take. An exceptable form of collaboration is to
+ collaboration will take. An acceptable form of collaboration is to
not collaborate at all.
Registration
@@ -46,9 +46,9 @@
An important feature of component registration services is that they
support multiple conflicting registrations for the same registration
-parameters. At most one of the registrations is active. A site
-developer can switch between alternate components by simply changing
-which one is active.
+parameters. At most one of the conflicting registrations is active.
+A site developer can switch between alternate components by simply
+changing which one is active.
Consider the following scenario. A product provides a utility. A
site manager gets a new version of the utility and installs
@@ -93,8 +93,8 @@
- Module-global registrations register objects stored in
modules. Objects in modules aren't managable directly, so we can't
- manage their registrations trough them. (The state of an object
- stored in a module must be respresented soley by the module source.)
+ manage their registrations through them. (The state of an object
+ stored in a module must be represented solely by the module source.)
Module-global objects are named using dotted names.
=== Zope3/src/zope/app/services/adapter.py 1.14.2.1 => 1.14.2.2 ===
--- Zope3/src/zope/app/services/adapter.py:1.14.2.1 Sun Jun 22 10:23:26 2003
+++ Zope3/src/zope/app/services/adapter.py Mon Jun 23 10:20:21 2003
@@ -31,7 +31,6 @@
from zope.app.services.registration import SimpleRegistration
from zope.app.context import ContextWrapper
from zope.context import ContextMethod
-from zope.app.services.registration import RegistrationStatusProperty
from zope.app.component.nextservice import getNextService
from zope.app.interfaces.services.service import ISimpleService
@@ -192,8 +191,6 @@
implements(IAdapterRegistration)
serviceType = Adapters
-
- status = RegistrationStatusProperty()
# XXX These should be positional arguments, except that forInterface
# isn't passed in if it is omitted. To fix this, we need a
=== Zope3/src/zope/app/services/auth.py 1.15.10.1 => 1.15.10.2 ===
=== Zope3/src/zope/app/services/cache.py 1.9.10.1 => 1.9.10.2 ===
--- Zope3/src/zope/app/services/cache.py:1.9.10.1 Sun Jun 22 10:23:27 2003
+++ Zope3/src/zope/app/services/cache.py Mon Jun 23 10:20:21 2003
@@ -24,7 +24,6 @@
from zope.app.interfaces.services.registration import INameComponentRegistry
from zope.app.interfaces.services.event import IEventChannel
from zope.app.interfaces.services.service import ISimpleService
-from zope.app.services.registration import RegistrationStatusProperty
from zope.app.services.registration import NameComponentRegistry
from zope.app.services.registration import NamedComponentRegistration
from zope.app.services.event import ServiceSubscriberEventChannel
@@ -97,8 +96,6 @@
implements(ICacheRegistration)
serviceType = 'Caching'
-
- status = RegistrationStatusProperty()
label = "Cache"
=== Zope3/src/zope/app/services/configure.zcml 1.29.2.1 => 1.29.2.2 ===
--- Zope3/src/zope/app/services/configure.zcml:1.29.2.1 Sun Jun 22 10:23:27 2003
+++ Zope3/src/zope/app/services/configure.zcml Mon Jun 23 10:20:21 2003
@@ -390,16 +390,23 @@
<serviceType
id="ErrorLogging"
- interface="zope.app.interfaces.services.error.IErrorReportingService" />
+ interface="zope.app.interfaces.services.error.IErrorReportingService"
+ />
- <content class='zope.app.services.errorr.ErrorReportingService'>
+ <content class='zope.app.services.error.ErrorReportingService'>
<require
permission="zope.Public"
interface="zope.app.interfaces.services.error.IErrorReportingService"
/>
+ <require
+ permission="zope.ManageServices"
+ interface="
+ zope.app.interfaces.services.error.ILocalErrorReportingService"
+ />
<factory
id='ErrorLogging'
- permission='zope.Public' />
+ permission='zope.Public'
+ />
</content>
<!-- Object Hub -->
@@ -559,5 +566,7 @@
permission="zope.ManageContent"
/>
+<!-- Local Interface Service -->
+<include file="interface.zcml" />
</zopeConfigure>
=== Zope3/src/zope/app/services/connection.py 1.11.10.1 => 1.11.10.2 ===
--- Zope3/src/zope/app/services/connection.py:1.11.10.1 Sun Jun 22 10:23:27 2003
+++ Zope3/src/zope/app/services/connection.py Mon Jun 23 10:20:21 2003
@@ -11,19 +11,20 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""
+"""Connection service
+
$Id$
"""
from persistence import Persistent
-from zope.context import ContextMethod
-
+from zope.app.component.nextservice import queryNextService
from zope.app.interfaces.rdb import IZopeDatabaseAdapter
+from zope.app.interfaces.services.connection import IConnectionRegistration
from zope.app.interfaces.services.connection import ILocalConnectionService
from zope.app.interfaces.services.service import ISimpleService
-
-from zope.app.component.nextservice import queryNextService
from zope.app.services.registration import NameComponentRegistry
+from zope.app.services.registration import NamedComponentRegistration
+from zope.context import ContextMethod
from zope.interface import implements
class ConnectionService(Persistent, NameComponentRegistry):
@@ -73,10 +74,6 @@
getAvailableConnections = ContextMethod(getAvailableConnections)
-from zope.app.interfaces.services.connection import IConnectionRegistration
-from zope.app.services.registration import NamedComponentRegistration
-from zope.app.services.registration import RegistrationStatusProperty
-
class ConnectionRegistration(NamedComponentRegistration):
__doc__ = IConnectionRegistration.__doc__
@@ -84,8 +81,6 @@
implements(IConnectionRegistration)
serviceType = 'SQLDatabaseConnections'
-
- status = RegistrationStatusProperty()
label = "Connection"
=== Zope3/src/zope/app/services/event.py 1.24.4.1 => 1.24.4.2 ===
=== Zope3/src/zope/app/services/field.py 1.7.18.1 => 1.7.18.2 ===
=== Zope3/src/zope/app/services/folder.py 1.6.10.1 => 1.6.10.2 ===
=== Zope3/src/zope/app/services/hub.py 1.10.10.1 => 1.10.10.2 ===
=== Zope3/src/zope/app/services/interface.py 1.5 => 1.5.4.1 ===
--- Zope3/src/zope/app/services/interface.py:1.5 Sat May 3 12:32:59 2003
+++ Zope3/src/zope/app/services/interface.py Mon Jun 23 10:20:21 2003
@@ -11,12 +11,24 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""Interfaces for persistent modules."""
+"""Code about services and interfaces.
+
+This module contains code for interfaces in persistent modules, and
+for the local interface service.
+"""
from persistence import Persistent
from zodb.code.patch import registerWrapper, Wrapper
from zope.interface.interface import InterfaceClass
+from zope.app.component.nextservice import getNextService
+from zope.app.interfaces.services.service import ISimpleService
+from zope.app.interfaces.component import IInterfaceService
+from zope.app import zapi
+from zope.app.services.servicenames import Interfaces
+from zope.component import ComponentLookupError
+from zope.interface import implements
+
class PersistentInterfaceClass(Persistent, InterfaceClass):
pass
@@ -30,8 +42,45 @@
def unwrap(self):
return PersistentInterfaceClass(self._obj.__name__)
-def register():
+def register(): # XXX has been refactored on a branch
registerWrapper(InterfaceClass, PersistentInterfaceWrapper,
lambda iface: (),
lambda iface: iface.__dict__,
)
+
+class LocalInterfaceService(object):
+ """I need a doc string."""
+
+ implements(IInterfaceService,
+ ISimpleService)
+
+ # All the methods defined here are context methods
+ zapi.ContextAwareDescriptors()
+
+ def getInterface(self, id):
+ # Return the interface registered for the given id
+ i = self.queryInterface(id)
+ if i is None:
+ raise ComponentLookupError(id)
+ return i
+
+ def queryInterface(self, id, default=None):
+ # Return the interface registered for the given id
+ next = getNextService(self, Interfaces)
+ return next.queryInterface(id, default)
+
+ def searchInterface(self, search_string="", base=None):
+ # Return the interfaces that match the search criteria
+ next = getNextService(self, Interfaces)
+ return next.searchInterface(search_string, base)
+
+ def searchInterfaceIds(self, search_string="", base=None):
+ # Return the ids of the interfaces that match the search criteria.
+ next = getNextService(self, Interfaces)
+ return next.searchInterfaceIds(search_string, base)
+
+ def items(self, search_string="", base=None):
+ # Return id, interface pairs for all items matching criteria.
+ next = getNextService(self, Interfaces)
+ return next.items(search_string, base)
+
=== Zope3/src/zope/app/services/module.py 1.2.26.1 => 1.2.26.2 ===
=== Zope3/src/zope/app/services/pagefolder.py 1.5.10.1 => 1.5.10.2 ===
=== Zope3/src/zope/app/services/queryfield.py 1.2.22.1 => 1.2.22.2 ===
=== Zope3/src/zope/app/services/registration.py 1.1.2.1 => 1.1.2.2 ===
--- Zope3/src/zope/app/services/registration.py:1.1.2.1 Sun Jun 22 10:23:27 2003
+++ Zope3/src/zope/app/services/registration.py Mon Jun 23 10:20:21 2003
@@ -66,9 +66,6 @@
sm = getServiceManager(registration)
service = sm.queryLocalService(registration.serviceType)
- # XXX The following may fail; there's a subtle bug here when
- # the returned service isn't in the same service manager as
- # the one owning the registration.
registry = service and service.queryRegistrationsFor(registration)
if registry:
@@ -325,6 +322,9 @@
# *think* we do. :)
IAttributeAnnotatable,
)
+
+
+ status = RegistrationStatusProperty()
# Methods from IRegistration
=== Zope3/src/zope/app/services/role.py 1.4.18.1 => 1.4.18.2 ===
=== Zope3/src/zope/app/services/service.py 1.18.10.1 => 1.18.10.2 ===
--- Zope3/src/zope/app/services/service.py:1.18.10.1 Sun Jun 22 10:23:27 2003
+++ Zope3/src/zope/app/services/service.py Mon Jun 23 10:20:21 2003
@@ -53,7 +53,6 @@
# (used as 2nd argument to isinstance() in method resolve() below)
ModuleType = type(IModuleService), PersistentModule
-from zope.app.services.registration import RegistrationStatusProperty
from zope.app.services.registration import NameComponentRegistry
from zope.app.services.registration import NamedComponentRegistration
from zope.app.services.folder import SiteManagementFolders
@@ -124,8 +123,9 @@
# This is rather tricky. Normally, getting a service requires
# the use of other services, like the adapter service. We
# need to be careful not to get into an infinate recursion by
- # getting out getService to be called while looking up
- # services, so we'll
+ # getting our getService to be called while looking up
+ # services, so we'll use _v_calling to prevent recursive
+ # getService calls.
if name == 'Services':
return wrapped_self # We are the service service
@@ -302,8 +302,6 @@
implements(IServiceRegistration)
serviceType = 'Services'
-
- status = RegistrationStatusProperty()
label = "Service"
=== Zope3/src/zope/app/services/utility.py 1.6.10.1 => 1.6.10.2 ===
--- Zope3/src/zope/app/services/utility.py:1.6.10.1 Sun Jun 22 10:23:27 2003
+++ Zope3/src/zope/app/services/utility.py Mon Jun 23 10:20:21 2003
@@ -26,7 +26,6 @@
from zope.app.interfaces.services.utility import IUtilityRegistration
from zope.app.interfaces.services.utility import ILocalUtilityService
from zope.app.services.registration import RegistrationStack
-from zope.app.services.registration import RegistrationStatusProperty
from zope.app.services.registration import ComponentRegistration
from zope.component.exceptions import ComponentLookupError
from zope.interface.implementor import ImplementorRegistry
@@ -115,8 +114,6 @@
"""
serviceType = 'Utilities'
-
- status = RegistrationStatusProperty()
implements(IUtilityRegistration)
=== Zope3/src/zope/app/services/utility.txt 1.1.2.1 => 1.1.2.2 ===
--- Zope3/src/zope/app/services/utility.txt:1.1.2.1 Sun Jun 22 10:23:27 2003
+++ Zope3/src/zope/app/services/utility.txt Mon Jun 23 10:20:21 2003
@@ -128,35 +128,33 @@
We'll start by updating the utility service to support registrations.
The updated local utility service implementation can be found in
-zope/app/services/utility.py.
+``zope/app/services/utility.py``. It's a good idea to refer to the
+source file as you read the description here.
First, we'll pick a data structure. We'll use a persistent dictionary
mapping utility names to implementor registries. An implementor
-registry implements a mapping from interfaces to objects; it's not
-quite the same as a mapping because it understands subclassing
-relationships between the interfaces used as keys. In this case, the
-implementor registries themselves map interfaces to
-RegistrationStacks::
+registry implements a mapping from interfaces to objects; it's a
+special mapping because it understands subclassing relationships
+between the interfaces used as keys. In this case, the implementor
+registries themselves map interfaces to RegistrationStacks. The
+overall data structure looks like::
{ utility_name -> { interface -> stack } }
-
We also need to implement
-zope.app.interfaces.services.registration.IRegistry. This defines two
-methods, ``queryRegistrationsFor`` and ``createRegistrationsFor``.
-
-A ``queryRegistrationsFor`` method is added to implement
-``IRegistry``. It takes a registration object and returns the
-corresponding registration registry. The registration object is
-used to provide an abstract way to represent registration parameters.
-Typically, the registration parameters are extracted and a more
-concrete method is called. In the local utility service, we extract
-the utility name and interface and call ``queryRegistrations`` with
-the name and interface.
+``zope.app.interfaces.services.registration.IRegistry``. This defines
+two methods, ``queryRegistrationsFor`` and ``createRegistrationsFor``.
+The ``queryRegistrationsFor`` method takes a registration object and
+returns the corresponding registration stack. The registration
+object is used to provide an abstract way to represent registration
+parameters. Typically, the registration parameters are extracted and
+a more concrete method is called. In the local utility service, we
+extract the utility name and interface and call ``queryRegistrations``
+with the name and interface.
-Similarly, we add a ``createRegistrationsFor`` method that takes a
+Similarly, the``createRegistrationsFor`` method takes a
registration object holding registration parameters and creates a
-registration registry for the parameters (if none already exists).
+registration stack for the parameters (if none already exists).
If we don't have a implementor registry for a utility name, we create
one and add it. When we create the implementor registry, we pass a
``PersistentDict`` for it to use to store registration data. This
@@ -164,17 +162,17 @@
data for the given interface, we create a registration registry and
register it for the interface.
-Finally, we modify ``queryUtility`` to use registered utility
-registrations. We try to get a registration registery by calling
-``queryRegistrations``. If we get one, we call its ``active``
-method to get the active registration, if any. Finally, we call
-``getComponent`` on the active registration to get the actual
-component. We leave it up to the registration object to take care of
-actually finding and returning the component.
-
-We need to provide utility registration objects. The
-utility registration objects need to manage several bits of
-information:
+Finally, we modify ``queryUtility`` to use registered utilities. We
+try to get a registration stack by calling ``queryRegistrations``. If
+we get one, we call its ``active`` method to get the active
+registration, if any. Finally, we call ``getComponent`` on the active
+registration to get the actual component. We leave it up to the
+registration object to take care of actually finding and returning the
+component.
+
+In addition to the utility service, We need to provide utility
+registration objects. The utility registration objects need to manage
+several bits of information:
- name
@@ -185,29 +183,30 @@
- The location of the actual component.
The registration objects provide access to the component through the
-getComponent method.
+``getComponent`` method.
To create the registration class, we'll start by defining a
-registration schema in
-``zope/app/interfaces/services/utility.py``. The schema should extend
-``zope.app.interfaces.services.registration.IRegistration``.
-There's a more specific interface,
+registration schema in ``zope/app/interfaces/services/utility.py``.
+The schema should extend
+``zope.app.interfaces.services.registration.IRegistration``. There's
+a more specific interface,
``zope.app.interfaces.services.registration.IComponentRegistration``
-that is much closer to what we need. (XXX Add footnote explaining why
-we can't use INamedComponentRegistration in this example.)
-We extend this interface as IUtilityRegistration, which adds a name
-field (which is required but may be empty -- note the subtle
-difference, because the empty string is still used as part of the
-lookup key) and an interface field. We also override the
-componentPath field to make it read-only (this is for the UI
-definition).
+that is much closer to what we need. [2]_ We extend this interface as
+IUtilityRegistration, which adds a name field (which is required but
+may be empty -- note the subtle difference, because the empty string
+is still used as part of the lookup key) and an interface field. We
+also override the componentPath field to make it read-only (this is
+for the UI definition).
A ``UtilityRegistration`` class is added to the ``utility`` module in
``zope/app/services`` that implements the registration interface. We
-can subclass ComponentRegistration, which does much of the work. Note
-that registration component includes two methods, defined in
+can subclass ComponentRegistration, which does much of the work. The
+class definition includes a ``serviceType`` attribute. This attribute
+is used by the registration framework to decide which service a
+registration is used with. The class includes two methods, defined in
``IRegistration``, giving summary information used by several
-predefined views. See the interface for a description of these methods.
+predefined views. See the interface for a description of these
+methods.
We need to provide user interfaces for:
@@ -355,3 +354,11 @@
.. [1] Of course, I initially forgot to include a nearly empty
``__init__.py`` file and had to add one later.
+
+.. [2] It's tempting to use ``INamedComponentRegistration`, but
+ ``INamedComponentRegistration`` is based on ``INamedRegistration``,
+ which is for registring components looked up by name alone.
+ ``INamedRegistration`` requires a non-empty name, but we want to
+ allow empty names, as we are looking up objects based on **both**
+ name and interface.
+
=== Zope3/src/zope/app/services/view.py 1.18.4.1 => 1.18.4.2 ===
--- Zope3/src/zope/app/services/view.py:1.18.4.1 Sun Jun 22 10:23:27 2003
+++ Zope3/src/zope/app/services/view.py Mon Jun 23 10:20:21 2003
@@ -29,7 +29,6 @@
from zope.app.services.registration import SimpleRegistration
from zope.app.context import ContextWrapper
from zope.context import ContextMethod
-from zope.app.services.registration import RegistrationStatusProperty
from zope.app.component.nextservice import getNextService
from zope.component import getSkin
from zope.interface import implements
@@ -220,8 +219,6 @@
implements(IViewRegistration)
serviceType = 'Views'
-
- status = RegistrationStatusProperty()
_what = "View" # For usageSummary(); subclass may override
=== Zope3/src/zope/app/services/zpt.py 1.10.10.1 => 1.10.10.2 ===