| |
From: <svn-changes@pl...> - 2004-06-02 21:00
|
Author: tiran
Date: Wed Jun 2 16:09:24 2004
New Revision: 5311
Added:
CMFPlone/branches/tiran-z3iface-branch/interfaces/HTTPCache.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/ICMFTool.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/IContentType.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/IContentish.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/ICustomizationPolicy.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/IDiscussions.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/IDublinCore.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/IDynamic.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/IOrderedContainer.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/IPloneBaseTool.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/ISyndicatable.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/RAMCache.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/archetypes_tool.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/caching_policy_manager.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/common.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/content_type_registry.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/cookie_authentication.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/mimetypes_registry.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/plone_utils.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_actionicons.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_actions.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_calendar.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_catalog.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_controlpanel.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_discussion.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_factory.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_form.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_groupdata.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_groups.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_interface.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_memberdata.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_membership.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_metadata.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_migration.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_navigation.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_properties.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_quickinstaller.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_registration.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_skins.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_syndication.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_transforms.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_types.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_undo.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_url.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_workflow.py
CMFPlone/branches/tiran-z3iface-branch/zope3/
CMFPlone/branches/tiran-z3iface-branch/zope3/Makefile
CMFPlone/branches/tiran-z3iface-branch/zope3/__init__.py
CMFPlone/branches/tiran-z3iface-branch/zope3/setup.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/__init__.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/DEPENDENCIES.cfg
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/__init__.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/_duplicate.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/_forbidden.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/_notfounderror.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/_zope_error.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/exceptionformatter.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/interfaces.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/tests/
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/tests/__init__.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/tests/test_exceptionformatter.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/unauthorized.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/DEPENDENCIES.cfg
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/PUBLICATION.cfg
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/README.txt
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/SETUP.cfg
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/__init__.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/_flatten.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/_zope_interface_coptimizations.c
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/adapter.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/adapter.txt
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/advice.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/__init__.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/idatetime.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/interfaces.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/mapping.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/tests/
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/tests/__init__.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/tests/basemapping.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/tests/test_idatetime.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/declarations.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/document.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/exceptions.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/interface.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/interfaces.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/ro.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/__init__.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/docfilesuite.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/dummy.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/foodforthought.txt
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/ifoo.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/m1.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/m2.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/odd.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_adapter.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_advice.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_declarations.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_document.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_element.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_interface.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_odd_declarations.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_sorting.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_type.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_verify.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/unitfixtures.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/type.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/verify.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/DEPENDENCIES.cfg
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/__init__.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/cleanup.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/doctest.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/doctestunit.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/loggingsupport.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/loghandler.py
CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/tests.py
Removed:
CMFPlone/branches/tiran-z3iface-branch/interfaces/CustomizationPolicy.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/FactoryTool.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/FormTool.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/InterfaceTool.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/NavigationController.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/OrderedContainer.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/PloneBaseTool.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/PloneControlPanel.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/PropertiesTool.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/interface.py
Modified:
CMFPlone/branches/tiran-z3iface-branch/ActionIconsTool.py
CMFPlone/branches/tiran-z3iface-branch/ActionsTool.py
CMFPlone/branches/tiran-z3iface-branch/CalendarTool.py
CMFPlone/branches/tiran-z3iface-branch/CatalogTool.py
CMFPlone/branches/tiran-z3iface-branch/CustomizationPolicy.py
CMFPlone/branches/tiran-z3iface-branch/DiscussionTool.py
CMFPlone/branches/tiran-z3iface-branch/FactoryTool.py
CMFPlone/branches/tiran-z3iface-branch/FormTool.py
CMFPlone/branches/tiran-z3iface-branch/GroupDataTool.py
CMFPlone/branches/tiran-z3iface-branch/GroupsTool.py
CMFPlone/branches/tiran-z3iface-branch/InterfaceTool.py
CMFPlone/branches/tiran-z3iface-branch/LargePloneFolder.py
CMFPlone/branches/tiran-z3iface-branch/MemberDataTool.py
CMFPlone/branches/tiran-z3iface-branch/MembershipTool.py
CMFPlone/branches/tiran-z3iface-branch/MetadataTool.py
CMFPlone/branches/tiran-z3iface-branch/MigrationTool.py
CMFPlone/branches/tiran-z3iface-branch/NavigationTool.py
CMFPlone/branches/tiran-z3iface-branch/PloneBaseTool.py
CMFPlone/branches/tiran-z3iface-branch/PloneContent.py
CMFPlone/branches/tiran-z3iface-branch/PloneControlPanel.py
CMFPlone/branches/tiran-z3iface-branch/PloneFolder.py
CMFPlone/branches/tiran-z3iface-branch/PloneTool.py
CMFPlone/branches/tiran-z3iface-branch/Portal.py
CMFPlone/branches/tiran-z3iface-branch/PrivateSitePolicy.py
CMFPlone/branches/tiran-z3iface-branch/PropertiesTool.py
CMFPlone/branches/tiran-z3iface-branch/QuickInstallerTool.py
CMFPlone/branches/tiran-z3iface-branch/RegistrationTool.py
CMFPlone/branches/tiran-z3iface-branch/SkinsTool.py
CMFPlone/branches/tiran-z3iface-branch/SyndicationTool.py
CMFPlone/branches/tiran-z3iface-branch/TypesTool.py
CMFPlone/branches/tiran-z3iface-branch/URLTool.py
CMFPlone/branches/tiran-z3iface-branch/UndoTool.py
CMFPlone/branches/tiran-z3iface-branch/WorkflowTool.py
CMFPlone/branches/tiran-z3iface-branch/__init__.py
CMFPlone/branches/tiran-z3iface-branch/interfaces/__init__.py
CMFPlone/branches/tiran-z3iface-branch/skins/plone_scripts/breadcrumbs.py
CMFPlone/branches/tiran-z3iface-branch/skins/plone_templates/folder_contents.pt
Log:
Plone with zope.interface from Zope3 and new interfaces from tiran-interface-documentation-branch
With this branch the tiran-interface_documentation-branch is outdated and invalid
Modified: CMFPlone/branches/tiran-z3iface-branch/ActionIconsTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/ActionIconsTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/ActionIconsTool.py Wed Jun 2 16:09:24 2004
@@ -6,6 +6,9 @@ />
from Globals import InitializeClass
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_actionicons import IActionIconsTool
+from zope.interface import implements
+
from Products.CMFPlone.PloneTool import _icons as iconcache
def removeAICacheEntry(category, id):
@@ -18,8 +21,8 @@ />
security = ClassSecurityInfo()
toolicon = 'skins/plone_images/confirm_icon.gif'
- __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, )
-
+ implements(IActionIconsTool)
+
security.declareProtected(View, 'renderActionIcon')
def renderActionIcon( self,
category,
Modified: CMFPlone/branches/tiran-z3iface-branch/ActionsTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/ActionsTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/ActionsTool.py Wed Jun 2 16:09:24 2004
@@ -7,7 +7,11 @@ />
from Products.CMFCore.utils import _checkPermission
from Products.CMFPlone import ToolNames, FactoryTool
from setup.ConfigurationMethods import correctFolderContentsAction
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_actions import IActionsTool
+from zope.interface import implements
+
class ActionsTool(PloneBaseTool, BaseTool):
@@ -15,7 +19,7 @@ />
security = ClassSecurityInfo()
toolicon = 'skins/plone_images/confirm_icon.gif'
- __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, )
+ implements(IActionsTool)
# XXX __init__ is derived from the corresponding method in CMFCore.ActionsTool.
Modified: CMFPlone/branches/tiran-z3iface-branch/CalendarTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/CalendarTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/CalendarTool.py Wed Jun 2 16:09:24 2004
@@ -2,7 +2,10 @@ />
from Products.CMFPlone import ToolNames
from AccessControl import ClassSecurityInfo
from Globals import InitializeClass
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_calendar import ICalendarTool
+from zope.interface import implements
class CalendarTool(PloneBaseTool, BaseTool):
@@ -10,7 +13,7 @@ />
security = ClassSecurityInfo()
toolicon = 'skins/plone_images/event_icon.gif'
- __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, )
+ implements(ICalendarTool)
CalendarTool.__doc__ = BaseTool.__doc__
Modified: CMFPlone/branches/tiran-z3iface-branch/CatalogTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/CatalogTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/CatalogTool.py Wed Jun 2 16:09:24 2004
@@ -7,7 +7,10 @@ />
from Acquisition import aq_base
from Globals import InitializeClass
from DateTime import DateTime
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_catalog import ICatalogTool
+from zope.interface import implements
try:
import Products.TextIndexNG2
@@ -21,7 +24,7 @@ />
security = ClassSecurityInfo()
toolicon = 'skins/plone_images/book_icon.gif'
- __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, )
+ implements(ICatalogTool)
def __init__(self):
ZCatalog.__init__(self, self.getId())
Modified: CMFPlone/branches/tiran-z3iface-branch/CustomizationPolicy.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/CustomizationPolicy.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/CustomizationPolicy.py Wed Jun 2 16:09:24 2004
@@ -1,10 +1,11 @@ />
#These CustomizationPolicies *are not* persisted!!
from Products.CMFPlone.Portal import addPolicy, PloneGenerator
-from Products.CMFPlone.interfaces.CustomizationPolicy import ICustomizationPolicy
+from Products.CMFPlone.interfaces.ICustomizationPolicy import ICustomizationPolicy
+from zope.interface import implements
class DefaultCustomizationPolicy:
""" Customizes various actions on CMF tools """
- __implements__ = ICustomizationPolicy
+ implements(ICustomizationPolicy)
availableAtConstruction=1
Modified: CMFPlone/branches/tiran-z3iface-branch/DiscussionTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/DiscussionTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/DiscussionTool.py Wed Jun 2 16:09:24 2004
@@ -2,7 +2,10 @@ />
from Products.CMFPlone import ToolNames
from AccessControl import ClassSecurityInfo
from Globals import InitializeClass
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_discussion import IDiscussionTool
+from zope.interface import implements
from Products.CMFCore.utils import format_stx
from DocumentTemplate.DT_Util import html_quote
@@ -13,7 +16,7 @@ />
security = ClassSecurityInfo()
toolicon = 'skins/plone_images/discussionitem_icon.gif'
- __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, )
+ implements(IDiscussionTool)
security.declareProtected('Modify portal content', 'cookContent')
def cookReply(self, reply, text_format=None):
Modified: CMFPlone/branches/tiran-z3iface-branch/FactoryTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/FactoryTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/FactoryTool.py Wed Jun 2 16:09:24 2004
@@ -14,7 +14,10 @@ />
from Products.CMFCore.utils import UniqueObject, getToolByName, format_stx
from Products.CMFCore.Skinnable import SkinnableObjectManager
from Products.CMFPlone.PloneFolder import PloneFolder as TempFolderBase
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_factory import IFactoryTool
+from zope.interface import implements
# ##############################################################################
@@ -156,7 +159,7 @@ />
security = ClassSecurityInfo()
isPrincipiaFolderish = 0
- __implements__ = (PloneBaseTool.__implements__, SimpleItem.__implements__, )
+ implements(IFactoryTool)
manage_options = ( ({'label':'Overview', 'action':'manage_overview'}, \
{'label':'Documentation', 'action':'manage_docs'}, \
Modified: CMFPlone/branches/tiran-z3iface-branch/FormTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/FormTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/FormTool.py Wed Jun 2 16:09:24 2004
@@ -15,11 +15,14 @@ />
from ZPublisher.Publish import call_object, missing_name, dont_publish_class
from Products.CMFCore.utils import getToolByName
from PloneUtilities import log_decated
-from interfaces.FormTool import IFormTool, ICMFForm
+from Products.CMFPlone.interfaces.portal_form import IFormTool, ICMFForm
from PloneUtilities import log as debug_log
from NavigationTool import ScriptStatus
from ZODB.POSException import ConflictError
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_form import IFormTool
+from zope.interface import implements
validator_cache = {} # a place to stash cached validators
@@ -35,8 +38,7 @@ />
toolicon = 'skins/plone_images/error_icon.gif'
security = ClassSecurityInfo()
- __implements__ = (PloneBaseTool.__implements__, IFormTool,
- SimpleItem.__implements__, )
+ implements(IFormTool)
# special-purpose items used in the REQUEST
# a dictionary used for storing form validation errors
@@ -415,7 +417,7 @@ />
make BasicForms easier to work with from external methods."""
security = ClassSecurityInfo()
security.declareObjectPublic()
- __implements__ = ICMFForm,
+ # XXX __implements__ = ICMFForm,
security.declareProtected('View', 'get_field')
def get_field(self, id, include_disabled=0):
Modified: CMFPlone/branches/tiran-z3iface-branch/GroupDataTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/GroupDataTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/GroupDataTool.py Wed Jun 2 16:09:24 2004
@@ -3,7 +3,11 @@ />
from Products.CMFPlone import ToolNames
from AccessControl import ClassSecurityInfo
from Globals import InitializeClass
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_groupdata import IGroupDataTool
+from zope.interface import implements
+
class GroupDataTool(PloneBaseTool, BaseTool):
@@ -11,7 +15,7 @@ />
security = ClassSecurityInfo()
toolicon = 'skins/plone_images/group.gif'
- __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, )
+ implements(IGroupDataTool)
GroupDataTool.__doc__ = BaseTool.__doc__
Modified: CMFPlone/branches/tiran-z3iface-branch/GroupsTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/GroupsTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/GroupsTool.py Wed Jun 2 16:09:24 2004
@@ -3,7 +3,10 @@ />
from Products.CMFPlone import ToolNames
from AccessControl import ClassSecurityInfo
from Globals import InitializeClass
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_groups import IGroupsTool
+from zope.interface import implements
class GroupsTool(PloneBaseTool, BaseTool):
@@ -11,7 +14,7 @@ />
security = ClassSecurityInfo()
toolicon = 'skins/plone_images/group.gif'
- __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, )
+ implements(IGroupsTool)
GroupsTool.__doc__ = BaseTool.__doc__
Modified: CMFPlone/branches/tiran-z3iface-branch/InterfaceTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/InterfaceTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/InterfaceTool.py Wed Jun 2 16:09:24 2004
@@ -1,8 +1,8 @@ />
import sys
from types import ClassType, ModuleType
from zLOG import LOG, INFO, WARNING
-from Products.CMFPlone.interfaces.interface import Interface, Attribute
-from Products.CMFPlone.interfaces.InterfaceTool import IInterfaceTool
+#XXXfrom Products.CMFPlone.interfaces.interface import Interface, Attribute
+from Products.CMFPlone.interfaces.portal_interface import IInterfaceTool
from Acquisition import aq_inner, aq_parent, aq_base
from Products.CMFCore.utils import UniqueObject, getToolByName
from Products.CMFCore.utils import _checkPermission, \
@@ -11,7 +11,10 @@ />
from Globals import InitializeClass
from AccessControl import ClassSecurityInfo
from Products.CMFCore import CMFCorePermissions
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_interface import IInterfaceTool
+from zope.interface import implements, providedBy, implementedBy
def log(summary='', text='', log_level=INFO):
LOG('InterfaceTool', log_level, summary, text)
@@ -23,8 +26,7 @@ />
by accepting a dotted name of an interface and exporting the
IInterface API """
- __implements__ = (PloneBaseTool.__implements__, IInterfaceTool,
- SimpleItem.__implements__, )
+ implements(IInterfaceTool)
id = 'portal_interface'
meta_type= 'Portal Interface Tool'
@@ -35,14 +37,14 @@ />
""" Asserts if an object implements a given interface """
obj = aq_base(obj)
iface = resolveInterface(dotted_name)
- return iface.isImplementedBy(obj)
+ return iface.providedBy(obj)
security.declarePublic('classImplements')
def classImplements(self, obj, dotted_name):
""" Asserts if an object's class implements a given interface """
klass = aq_base(obj).__class__
iface = resolveInterface(dotted_name)
- return iface.isImplementedBy(klass)
+ return iface.implementedBy(klass)
security.declarePublic('namesAndDescriptions')
def namesAndDescriptions(self, dotted_name, all=0):
Modified: CMFPlone/branches/tiran-z3iface-branch/LargePloneFolder.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/LargePloneFolder.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/LargePloneFolder.py Wed Jun 2 16:09:24 2004
@@ -17,10 +17,6 @@ />
""" A large plone folder """
meta_type='Large Plone Folder'
- # BTreeFolder2Base has no __implements__
- __implements__ = BasePloneFolder.__implements__
-
-
def __init__(self, id, title=''):
BTreeFolder2Base.__init__(self, id)
BasePloneFolder.__init__(self, id, title)
Modified: CMFPlone/branches/tiran-z3iface-branch/MemberDataTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/MemberDataTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/MemberDataTool.py Wed Jun 2 16:09:24 2004
@@ -10,16 +10,21 @@ />
from BTrees.OOBTree import OOBTree
from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2
from Products.CMFCore.utils import getToolByName
-from Products.CMFPlone.PloneBaseTool import PloneBaseTool
from Products.CMFCore.CMFCorePermissions import SetOwnProperties, ManagePortal
+
+from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_memberdata import IMemberDataTool
+from zope.interface import implements
+
+
class MemberDataTool(PloneBaseTool, BaseTool):
meta_type = ToolNames.MemberDataTool
security = ClassSecurityInfo()
toolicon = 'skins/plone_images/user.gif'
- __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, )
+ implements(IMemberDataTool)
def __init__(self):
Modified: CMFPlone/branches/tiran-z3iface-branch/MembershipTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/MembershipTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/MembershipTool.py Wed Jun 2 16:09:24 2004
@@ -10,7 +10,10 @@ />
from Globals import InitializeClass
from Acquisition import aq_base, aq_parent, aq_inner
from Products.CMFCore.CMFCorePermissions import View
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_membership import IMembershipTool
+from zope.interface import implements
default_portrait = 'defaultUser.gif'
@@ -34,7 +37,7 @@ />
default_portrait = 'defaultUser.gif'
security = ClassSecurityInfo()
- __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, )
+ implements(IMembershipTool)
#XXX I'm not quite sure why getPortalRoles is declared 'Managed'
# in CMFCore.MembershipTool - but in Plone we are not so anal ;-)
Modified: CMFPlone/branches/tiran-z3iface-branch/MetadataTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/MetadataTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/MetadataTool.py Wed Jun 2 16:09:24 2004
@@ -2,7 +2,10 @@ />
from Products.CMFPlone import ToolNames
from Globals import InitializeClass
from AccessControl import ClassSecurityInfo
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_metadata import IMetadataTool
+from zope.interface import implements
class MetadataTool(PloneBaseTool, BaseTool):
@@ -10,7 +13,7 @@ />
security = ClassSecurityInfo()
toolicon = 'skins/plone_images/info_icon.gif'
- __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, )
+ implements(IMetadataTool)
MetadataTool.__doc__ = BaseTool.__doc__
Modified: CMFPlone/branches/tiran-z3iface-branch/MigrationTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/MigrationTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/MigrationTool.py Wed Jun 2 16:09:24 2004
@@ -5,7 +5,10 @@ />
from Products.CMFCore.utils import UniqueObject, getToolByName
from Products.CMFCore.CMFCorePermissions import ManagePortal
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_migration import IMigrationTool
+from zope.interface import implements
import zLOG
import traceback
@@ -25,7 +28,7 @@ />
meta_type = 'Plone Migration Tool'
toolicon = 'skins/plone_images/site_icon.gif'
- __implements__ = (PloneBaseTool.__implements__, SimpleItem.__implements__, )
+ implements(IMigrationTool)
_needRecatalog = 0
_needUpdateRole = 0
Modified: CMFPlone/branches/tiran-z3iface-branch/NavigationTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/NavigationTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/NavigationTool.py Wed Jun 2 16:09:24 2004
@@ -21,7 +21,11 @@ />
import sys
from ZODB.POSException import ConflictError
-from interfaces.NavigationController import INavigationController
+
+from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_navigation import INavigationTool
+from zope.interface import implements
+
debug = 0 # enable/disable logging
@@ -29,7 +33,7 @@ />
if name=='self': return request['PARENTS'][0]
raise 'Invalid request', 'The parameter %s is missing.' % name
-class NavigationTool(UniqueObject, SimpleItem):
+class NavigationTool(PloneBaseTool, UniqueObject, SimpleItem):
""" provides navigation related utilities """
id = 'portal_navigation'
@@ -38,7 +42,8 @@ />
security = ClassSecurityInfo()
plone_tool = 1
- __implements__ = INavigationController,
+
+ implements(INavigationTool)
security.declarePublic('getNext')
def getNext(self, context, script, status, trace=[], **kwargs):
Modified: CMFPlone/branches/tiran-z3iface-branch/PloneBaseTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/PloneBaseTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/PloneBaseTool.py Wed Jun 2 16:09:24 2004
@@ -2,7 +2,10 @@ />
from AccessControl import ClassSecurityInfo
from Acquisition import aq_base, aq_inner, aq_parent
from Products.CMFPlone import ToolNames
-from Products.CMFPlone.interfaces.PloneBaseTool import IPloneBaseTool
+
+from Products.CMFPlone.interfaces.IPloneBaseTool import IPloneBaseTool
+from zope.interface import implements
+
class PloneBaseTool:
"""Base class of all tools used in CMFPlone and Plone Core
@@ -10,6 +13,6 @@ />
security = ClassSecurityInfo()
- __implements__ = IPloneBaseTool
+ implements(IPloneBaseTool)
InitializeClass(PloneBaseTool)
Modified: CMFPlone/branches/tiran-z3iface-branch/PloneContent.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/PloneContent.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/PloneContent.py Wed Jun 2 16:09:24 2004
@@ -2,6 +2,8 @@ />
from AccessControl import ClassSecurityInfo
from Globals import InitializeClass
+# XXX interfaces
+
class PloneContent(PortalContent):
pass
Modified: CMFPlone/branches/tiran-z3iface-branch/PloneControlPanel.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/PloneControlPanel.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/PloneControlPanel.py Wed Jun 2 16:09:24 2004
@@ -14,12 +14,12 @@ />
from Products.CMFCore.utils import _checkPermission, _dtmldir, \
getToolByName, SimpleItemWithProperties, UniqueObject
-from Products.CMFCore.interfaces.portal_actions \
- import portal_actions as IActionsTool
-
import ToolNames
-from interfaces.PloneControlPanel import IControlPanel
+
+from Products.CMFPlone.interfaces.portal_actions import IActionsTool
+from Products.CMFPlone.interfaces.portal_controlpanel import IControlPanel
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from zope.interface import implements
class PloneConfiglet(ActionInformation):
@@ -159,10 +159,8 @@ />
are apropos to the current user and context.
"""
- __implements__ = (PloneBaseTool.__implements__,
- IControlPanel,
- ActionProviderBase.__implements__,
- SimpleItem.__implements__, )
+ # XXX ActionProvider interface
+ implements(IControlPanel)
security = ClassSecurityInfo()
Modified: CMFPlone/branches/tiran-z3iface-branch/PloneFolder.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/PloneFolder.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/PloneFolder.py Wed Jun 2 16:09:24 2004
@@ -11,8 +11,8 @@ />
AddPortalContent, ModifyPortalContent
from Products.CMFDefault.SkinnedFolder import SkinnedFolder
from Products.CMFDefault.DublinCore import DefaultDublinCoreImpl
-from Products.CMFCore.interfaces.DublinCore import DublinCore as IDublinCore
-from Products.CMFCore.interfaces.Contentish import Contentish as IContentish
+from Products.CMFPlone.interfaces.IDublinCore import IDublinCore
+from Products.CMFPlone.interfaces.IContentish import IContentish
from AccessControl import Permissions, getSecurityManager, \
ClassSecurityInfo, Unauthorized
from Products.CMFCore import CMFCorePermissions
@@ -30,7 +30,7 @@ />
except ImportError:
hasZopeOrderedSupport=0
# atm its safer defining an own
-from interfaces.OrderedContainer import IOrderedContainer
+from Products.CMFPlone.interfaces.IOrderedContainer import IOrderedContainer
# from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2Base
@@ -103,9 +103,11 @@ />
if hasZopeOrderedSupport:
# got the IOrderedContainer interface from zope 2.7, too
# make shure this implementation fullfilles both interfaces
- __implements__ = (IOrderedContainer, IZopeOrderedContainer)
+ # XXX __implements__ = (IOrderedContainer, IZopeOrderedContainer)
+ pass
else:
- __implements__ = (IOrderedContainer,)
+ # XXX __implements__ = (IOrderedContainer,)
+ pass
security = ClassSecurityInfo()
@@ -258,8 +260,8 @@ />
security=ClassSecurityInfo()
- __implements__ = DefaultDublinCoreImpl.__implements__ + \
- (SkinnedFolder.__implements__,WriteLockInterface)
+ # XXX__implements__ = DefaultDublinCoreImpl.__implements__ + \
+ X (SkinnedFolder.__implements__,WriteLockInterface)
manage_options = Folder.manage_options + \
CMFCatalogAware.manage_options
@@ -390,8 +392,8 @@ />
""" A Plone Folder """
meta_type = 'Plone Folder'
security=ClassSecurityInfo()
- __implements__ = BasePloneFolder.__implements__ + \
- OrderedContainer.__implements__
+ # XXX __implements__ = BasePloneFolder.__implements__ + \
+ # OrderedContainer.__implements__
manage_renameObject = OrderedContainer.manage_renameObject
security.declareProtected(Permissions.copy_or_move, 'manage_copyObjects')
Modified: CMFPlone/branches/tiran-z3iface-branch/PloneTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/PloneTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/PloneTool.py Wed Jun 2 16:09:24 2004
@@ -15,8 +15,8 @@ />
from Products.CMFCore.utils import getToolByName, _dtmldir
from Products.CMFCore.ActionInformation import ActionInformation
from Products.CMFCore import CMFCorePermissions
-from Products.CMFCore.interfaces.DublinCore import DublinCore, MutableDublinCore
-from Products.CMFCore.interfaces.Discussions import Discussable
+# XXX from Products.CMFCore.interfaces.DublinCore import DublinCore, MutableDublinCore
+# XXX from Products.CMFCore.interfaces.Discussions import Discussable
from Products.CMFCore.WorkflowCore import WorkflowException
from Products.CMFPlone import ToolNames
@@ -27,7 +27,10 @@ />
from StatelessTree import constructNavigationTreeViewBuilder, \
NavigationTreeViewBuilder as NTVB
from ZODB.POSException import ConflictError
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.plone_utils import IPloneTool
+from zope.interface import implements
_marker = ()
_icons = {}
@@ -61,8 +64,7 @@ />
plone_tool = 1
field_fix = 'field_' # Formulator fixes for forms
- __implements__ = (PloneBaseTool.__implements__,
- SimpleItem.__implements__, )
+ implements(IPloneTool)
security.declareProtected(CMFCorePermissions.ManagePortal,
'setMemberProperties')
Modified: CMFPlone/branches/tiran-z3iface-branch/Portal.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/Portal.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/Portal.py Wed Jun 2 16:09:24 2004
@@ -106,8 +106,8 @@ />
security=ClassSecurityInfo()
meta_type = portal_type = 'Plone Site'
manage_addPloneFolder = PloneFolder.addPloneFolder
- __implements__ = DublinCore.DefaultDublinCoreImpl.__implements__ + \
- OrderedContainer.__implements__
+ # XXX __implements__ = DublinCore.DefaultDublinCoreImpl.__implements__ + \
+ # OrderedContainer.__implements__
def __browser_default__(self, request):
""" Set default so we can return whatever we want instead
Modified: CMFPlone/branches/tiran-z3iface-branch/PrivateSitePolicy.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/PrivateSitePolicy.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/PrivateSitePolicy.py Wed Jun 2 16:09:24 2004
@@ -6,19 +6,21 @@ />
# which is letting anonymous members see some sort of content
from Products.CMFPlone.Portal import addPolicy
-from Products.CMFPlone.interfaces.CustomizationPolicy import ICustomizationPolicy
+from Products.CMFPlone.interfaces.ICustomizationPolicy import ICustomizationPolicy
from Products.CMFPlone.CustomizationPolicy import DefaultCustomizationPolicy
from Products.CMFCore.utils import getToolByName
from Products.CMFCore.Exssion import Exssion
from Products.CMFCore import CMFCorePermissions
from Products.CMFCore.CMFCorePermissions import AddPortalMember
+from zope.interface import implements
+
def register(context, app_state):
addPolicy('Private Plone site', PrivateSitePolicy())
class PrivateSitePolicy(DefaultCustomizationPolicy):
""" Customizes the Plone site so that its private """
- __implements__ = ICustomizationPolicy
+ implements(ICustomizationPolicy)
availableAtConstruction=0
Modified: CMFPlone/branches/tiran-z3iface-branch/PropertiesTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/PropertiesTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/PropertiesTool.py Wed Jun 2 16:09:24 2004
@@ -14,8 +14,11 @@ />
from OFS.PropertyManager import PropertyManager
from OFS.SimpleItem import SimpleItem
from AccessControl import ClassSecurityInfo
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
-from Products.CMFPlone.interfaces.PropertiesTool import IPropertiesTool
+from Products.CMFPlone.interfaces.portal_properties import IPropertiesTool
+from zope.interface import implements
+
class PropertiesTool(PloneBaseTool, Folder, BaseTool):
@@ -29,10 +32,9 @@ />
},
))
- __implements__ = ((IPropertiesTool,) +
- (PloneBaseTool.__implements__,
- ActionProviderBase.__implements__,
- Folder.__implements__, ))
+ # XXX ActionProvider
+
+ implements(IPropertiesTool)
manage_options = ((Folder.manage_options[0],) +
BaseTool.manage_options)
Modified: CMFPlone/branches/tiran-z3iface-branch/QuickInstallerTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/QuickInstallerTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/QuickInstallerTool.py Wed Jun 2 16:09:24 2004
@@ -1,7 +1,10 @@ />
from Products.CMFQuickInstallerTool import AlreadyInstalled
from Products.CMFQuickInstallerTool.QuickInstallerTool \
import QuickInstallerTool as BaseTool
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_quickinstaller import IQuickInstallerTool
+from zope.interface import implements
from Products.CMFPlone import ToolNames
from AccessControl import ClassSecurityInfo
@@ -14,7 +17,7 @@ />
security = ClassSecurityInfo()
toolicon = 'skins/plone_images/product_icon.gif'
- __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, )
+ implements(IQuickInstallerTool)
QuickInstallerTool.__doc__ = BaseTool.__doc__
Modified: CMFPlone/branches/tiran-z3iface-branch/RegistrationTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/RegistrationTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/RegistrationTool.py Wed Jun 2 16:09:24 2004
@@ -9,7 +9,10 @@ />
from Globals import InitializeClass
from AccessControl import ClassSecurityInfo
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_registration import IRegistrationTool
+from zope.interface import implements
# - remove '1', 'l', and 'I' to avoid confusion
# - remove '0', 'O', and 'Q' to avoid confusion
@@ -39,7 +42,9 @@ />
security = ClassSecurityInfo()
toolicon = 'skins/plone_images/pencil_icon.gif'
plone_tool = 1
- __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, )
+
+ implements(IRegistrationTool)
+
md5key = None
_v_md5base = None
email_regex="""^([0-9a-z_&.+-]+!)*[0-9a-z_&.+-]+@(([0-9a-z]([0-9a-z-]*[0-9a-z])?\.)+[a-z]{2,4}|([0-9]{1,3}\.){3}[0-9]{1,3})$""" />
Modified: CMFPlone/branches/tiran-z3iface-branch/SkinsTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/SkinsTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/SkinsTool.py Wed Jun 2 16:09:24 2004
@@ -3,7 +3,10 @@ />
from AccessControl import ClassSecurityInfo
from Globals import InitializeClass
from Products.CMFCore import DirectoryView
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_skins import ISkinsTool
+from zope.interface import implements
_skincache = {}
@@ -20,7 +23,7 @@ />
default_skin = ''
request_varname = 'plone_skin'
- __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, )
+ implements(ISkinsTool)
security.declarePrivate('getSkinByName')
def __getSkinByName(self, name):
Modified: CMFPlone/branches/tiran-z3iface-branch/SyndicationTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/SyndicationTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/SyndicationTool.py Wed Jun 2 16:09:24 2004
@@ -3,7 +3,10 @@ />
from Products.CMFCore.Exssion import Exssion
from AccessControl import ClassSecurityInfo
from Globals import InitializeClass
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_syndication import ISyndicationTool
+from zope.interface import implements
actions = tuple(BaseTool._actions)
for a in actions:
@@ -17,7 +20,7 @@ />
toolicon = 'skins/plone_images/rss.gif'
_actions = actions
- __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, )
+ implements(ISyndicationTool)
SyndicationTool.__doc__ = BaseTool.__doc__
Modified: CMFPlone/branches/tiran-z3iface-branch/TypesTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/TypesTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/TypesTool.py Wed Jun 2 16:09:24 2004
@@ -2,7 +2,11 @@ />
from Products.CMFPlone import ToolNames
from AccessControl import ClassSecurityInfo
from Globals import InitializeClass
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_types import ITypesTool
+from zope.interface import implements
+
class TypesTool(PloneBaseTool, BaseTool):
@@ -10,7 +14,7 @@ />
security = ClassSecurityInfo()
toolicon = 'skins/plone_images/document_icon.gif'
- __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, )
+ implements(ITypesTool)
TypesTool.__doc__ = BaseTool.__doc__
Modified: CMFPlone/branches/tiran-z3iface-branch/URLTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/URLTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/URLTool.py Wed Jun 2 16:09:24 2004
@@ -2,7 +2,10 @@ />
from Products.CMFPlone import ToolNames
from AccessControl import ClassSecurityInfo
from Globals import InitializeClass
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_url import IURLTool
+from zope.interface import implements
class URLTool(PloneBaseTool, BaseTool):
@@ -10,7 +13,7 @@ />
security = ClassSecurityInfo()
toolicon = 'skins/plone_images/link_icon.gif'
- __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, )
+ implements(IURLTool)
URLTool.__doc__ = BaseTool.__doc__
Modified: CMFPlone/branches/tiran-z3iface-branch/UndoTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/UndoTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/UndoTool.py Wed Jun 2 16:09:24 2004
@@ -2,7 +2,10 @@ />
from Products.CMFPlone import ToolNames
from AccessControl import ClassSecurityInfo
from Globals import InitializeClass
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_undo import IUndoTool
+from zope.interface import implements
class UndoTool(PloneBaseTool, BaseTool):
@@ -10,7 +13,7 @@ />
security = ClassSecurityInfo()
toolicon = 'skins/plone_images/undo_icon.gif'
- __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, )
+ implements(IUndoTool)
UndoTool.__doc__ = BaseTool.__doc__
Modified: CMFPlone/branches/tiran-z3iface-branch/WorkflowTool.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/WorkflowTool.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/WorkflowTool.py Wed Jun 2 16:09:24 2004
@@ -13,7 +13,10 @@ />
from Products.CMFCore import CMFCorePermissions
from Products.DCWorkflow.Transitions import TRIGGER_USER_ACTION
from PloneUtilities import log
+
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
+from Products.CMFPlone.interfaces.portal_workflow import IWorkflowTool
+from zope.interface import implements
class WorkflowTool(PloneBaseTool, BaseTool):
@@ -22,7 +25,7 @@ />
plone_tool = 1
toolicon = 'skins/plone_images/workflow_icon.gif'
- __implements__ = (PloneBaseTool.__implements__, BaseTool.__implements__, )
+ implements(IWorkflowTool)
security.declarePublic('doActionFor')
def doActionFor(self, ob, action, wf_id=None, *args, **kw):
Modified: CMFPlone/branches/tiran-z3iface-branch/__init__.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/__init__.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/__init__.py Wed Jun 2 16:09:24 2004
@@ -32,6 +32,16 @@ />
ob = aq_base(ob)
return hasattr(ob, name)
+try:
+ from zope.interface import Interface
+ print Interface
+except ImportError:
+ from Products.CMFPlone import zope3
+ path = zope3.wire()
+ print path
+ from zope.interface import Interface
+
+import Products.CMFPlone.Portal
def initialize(context):
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/HTTPCache.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/HTTPCache.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,12 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IHTTPCache(Interface):
+ """
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/ICMFTool.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/ICMFTool.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,12 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class ICMFTool(Interface):
+ """
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/IContentType.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/IContentType.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,32 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IDublinCore import IDublinCore
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+class IItem(Interface):
+ """A zopish item based on OFS.SimpleItem.SimpleItem
+ """
+
+class IFolderish(IItem):
+ """A zopish item based on OFS.Folder.Folder
+ """
+
+class IContentType(IItem):
+ """A CMF type object
+ """
+
+class IFolderishContentType(IContentType, IFolderish):
+ """A folderish CMF type object
+ """
+
+class IDCContentType(IContentType, IDublinCore):
+ """A CMF type object with Dublin Core support
+ """
+
+class IDCFolderishContentType(IFolderishContentType, IDublinCore):
+ """A folderish CMF type object with Dublin Core support
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/IContentish.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/IContentish.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,40 @@ />
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+""" Contentish type interface.
+
+$Id: Contentish.py,v 1.5.14.2 2004/04/23 21:11:34 sidnei Exp $
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IContentish(Interface):
+ """
+ General interface for "contentish" items.
+
+ These methods need to be implemented by any class that wants to be a
+ first-class citizen in the Portal Content world.
+
+ PortalContent implements this interface.
+ """
+
+ def SearchableText():
+ """
+ SearchableText is called to provide the Catalog with textual
+ information about your object. It is a string usually generated
+ by concatenating the string attributes of your content class. This
+ string can then be used by the catalog to index your document and
+ make it findable through the catalog.
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/ICustomizationPolicy.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/ICustomizationPolicy.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,29 @@ />
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+class ICustomizationPolicy(Interface):
+ """
+ A Customization Policy is responsible for setting up a raw
+ Plone instance according to the instruction provided for the
+ Policy. The Policy must register via
+ Products.CMFPlone.Portal.addPolicy
+ """
+
+ def customize(portal):
+ """
+ the customize method takes the portal object and massages
+ it. the only thing that really needs to be understood is that
+ the Policy itself is not persisted.
+
+ Most likely a
+ CustomizationPolicy would be derived from the
+ DefaultCustomizationPolicy, you would call its customize()
+ method and then continue on customization the portal.
+ """
+
+ def getPloneGenerator():
+ """ returns a PloneGenerator, can be overloaded,
+ this method is called _before_ the portal is instanciated
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/IDiscussions.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/IDiscussions.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,158 @@ />
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+""" Discussable interface.
+
+$Id: Discussions.py,v 1.3.14.2 2004/04/23 21:11:34 sidnei Exp $
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IDiscussable(Interface):
+ """ Discussable is the interface for things which can have responses.
+ """
+
+ def createReply(title, text, Creator=None):
+ """
+ Create a reply in the proper place.
+
+ Permission: Reply to item
+ Returns: HTML (directly or via redirect)
+ """
+
+ def getReplies():
+ """
+ Return a sequence of the DiscussionResponse objects which are
+ associated with this Discussable
+
+ Permissions: View
+ Returns: sequence of DiscussionResponses
+ """
+
+ def quotedContents():
+ """
+ Return this object's contents in a form suitable for inclusion
+ as a quote in a response. The default implementation returns
+ an empty string. It might be overridden to return a '>' quoted
+ version of the item.
+ """
+
+ def _getReplyResults():
+ """
+ Return the ZCatalog results that resent this object's replies.
+
+ Often, the actual objects are not needed. This is less expensive
+ than fetching the objects.
+
+ Permissions: View
+ Returns: sequence of ZCatalog results resenting DiscussionResponses
+ """
+
+
+class OldDiscussable(Interface):
+ """ Oldstyle discussable interface.
+ """
+
+ def createReply(title, text, REQUEST, RESPONSE):
+ """
+ Create a reply in the proper place.
+
+ Permission: Reply to item
+ Returns: HTML (directly or via redirect)
+ """
+
+ def getReplyLocationAndID(REQUEST):
+ """
+ This method determines where a user's reply should be stored, and
+ what it's ID should be.
+
+ You don't really want to force users to have to select a
+ unique ID each time they want to reply to something. The
+ sent implementation selects a folder in the Member's home
+ folder called 'Correspondence' (creating it if it is missing)
+ and finds a free ID in that folder.
+
+ createReply should use this method to determine what the reply
+ it creates should be called, and where it should be placed.
+
+ This method (and createReply, I expect) do not really belong in
+ this interface. There should be a DiscussionManager singleton
+ (probably the portal object itself) which handles this.
+
+ Permissions: None assigned
+ Returns: 2-tuple, containing the container object, and a string ID.
+ """
+
+ def getReplyResults():
+ """
+ Return the ZCatalog results that resent this object's replies.
+
+ Often, the actual objects are not needed. This is less expensive
+ than fetching the objects.
+
+ Permissions: View
+ Returns: sequence of ZCatalog results resenting DiscussionResponses
+ """
+
+ def getReplies():
+ """
+ Return a sequence of the DiscussionResponse objects which are
+ associated with this Discussable
+
+ Permissions: View
+ Returns: sequence of DiscussionResponses
+ """
+
+ def quotedContents():
+ """
+ Return this object's contents in a form suitable for inclusion
+ as a quote in a response. The default implementation returns
+ an empty string. It might be overridden to return a '>' quoted
+ version of the item.
+ """
+
+
+class IDiscussionResponse(Interface):
+ """ This interface describes the behaviour of a Discussion Response.
+ """
+
+ def inReplyTo(REQUEST=None):
+ """
+ Return the Discussable object which this item is associated with
+
+ Permissions: None assigned
+ Returns: a Discussable object
+ """
+
+ def setReplyTo(reply_to):
+ """
+ Make this object a response to the passed object. (Will also
+ accept a path in the form of a string.) If reply_to does not
+ support or accept replies, a ValueError will be raised. (This
+ does not seem like the right exception.)
+
+ Permissions: None assigned
+ Returns: None
+ """
+
+ def parentsInThread(size=0):
+ """
+ Return the list of object which are this object's parents, from the
+ point of view of the threaded discussion. Parents are ordered
+ oldest to newest.
+
+ If 'size' is not zero, only the closest 'size' parents will be
+ returned.
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/IDublinCore.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/IDublinCore.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,284 @@ />
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+""" Dublin Core interface.
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class DublinCore(Interface):
+ """Dublin Core metadata
+
+ Define which Dublin Core metadata elements are supported by the CMF,
+ and the semantics therof.
+ """
+
+ def Title():
+ """Dublin Core element - resource name
+
+ :return: The title of the resource
+ :rtype: string
+ :permission: View
+ """
+
+ def Creator():
+ """Dublin Core element - resource creator
+
+ :return: The full name(s) of the author(s) of the content object.
+ :rtype: string
+ :permission: View
+ """
+
+ def Subject():
+ """Dublin Core element - resource keywords
+
+ :return: Zero or more keywords associated with the content object.
+ :rtype: sequence of strings
+ :permission: View
+ """
+
+ def Description():
+ """Dublin Core element - resource summary
+
+ :return: A natural language description of this object.
+ :rtype: string
+ :permission: View
+ """
+
+ def Publisher():
+ """Dublin Core element - resource publisher
+
+ :return: The full formal name of the entity or person responsible for publishing the resource.
+ :rtype: string
+ :permission: View
+ """
+
+ def Contributors():
+ """Dublin Core element - resource collaborators
+
+ :return: Zero or more additional collaborators.
+ :rtype: sequence of strings
+ :permission: View
+ """
+
+ def Date():
+ """Dublin Core element - default date
+
+ :return: XXX
+ :rtype: string, formatted 'YYYY-MM-DD H24:MN:SS TZ'
+ :permission: View
+ """
+
+ def CreationDate():
+ """Dublin Core element - date resource created.
+
+ :rtype: string, formatted 'YYYY-MM-DD H24:MN:SS TZ'
+ :permission: View
+ """
+
+ def EffectiveDate():
+ """Dublin Core element - date resource becomes effective.
+
+ :rtype: string, formatted 'YYYY-MM-DD H24:MN:SS TZ'
+ :permission: View
+ """
+
+ def ExpirationDate():
+ """Dublin Core element - date resource expires.
+
+ :rtype: string, formatted 'YYYY-MM-DD H24:MN:SS TZ'
+ :permission: View
+ """
+
+ def ModificationDate():
+ """Dublin Core element - date resource last modified.
+
+ :rtype: string, formatted 'YYYY-MM-DD H24:MN:SS TZ'
+ :permission: View
+ """
+
+ def Type():
+ """Dublin Core element - resource type
+
+ :return: A human-readable type name for the resource (perhaps mapped from its Zope meta_type).
+ :rtype: string
+ :permission: View
+ """
+
+ def Format():
+ """Dublin Core element - resource format
+
+ :return: The resource's MIME type (e.g., 'text/html', 'image/png', etc.).
+ :rtype: string
+ :permission: View
+ """
+
+ def Identifier():
+ """Dublin Core element - resource ID
+
+ :return: A unique ID (a URL) for the resource.
+ :rtype: string
+ :permission: View
+ """
+
+ def Language():
+ """Dublin Core element - resource language
+
+ :return: The RFC language code (e.g., 'en-US', 'pt-BR') for the resource.
+ :rtype: string
+ :permission: View
+ """
+
+ def Rights():
+ """Dublin Core element - resource copyright
+
+ :return: A string describing the intellectual property status, if any, of the resource.
+ :rtype: string
+ :permission: View
+ """
+
+class CatalogableDublinCore(Interface):
+ """Provide Zope-internal date objects for cataloging purposes.
+
+ """
+
+ def created():
+ """Dublin Core element - date resource created,
+
+ :rtype: DateTime
+ :permission: View
+ """
+
+ def effective():
+ """Dublin Core element - date resource becomes effective,
+
+ :rtype: DateBound
+ :permission: View
+ """
+
+ def expires():
+ """Dublin Core element - date resource expires,
+
+ :rtype: DateBound
+ :permission: View
+ """
+
+ def modified():
+ """Dublin Core element - date resource last modified,
+
+ :rtype: DateTime
+ :permission: View
+ """
+
+class MutableDublinCore(Interface):
+ """Update interface for mutable metadata.
+
+ """
+
+ def setTitle(title):
+ """Dublin Core element - update resource name
+
+ :Parameters:
+ - `title`: Set title of the resource
+ :Types:
+ - `title`: string
+ :permission: ManageProperties
+ """
+
+ def setSubject(subject):
+ """Dublin Core element - update resource keywords
+
+ :Parameters:
+ - `subject`: Set subject of the resource
+ :Types:
+ - `subject`:
+ :permission: ManageProperties
+ """
+
+ def setDescription(description):
+ """Dublin Core element - update resource summary
+
+ :Parameters:
+ - `description`: Set description of the resource
+ :Types:
+ - `description`: comma seperated string or list or tuple
+ :permission: ManageProperties
+ """
+
+ def setContributors(contributors):
+ """Dublin Core element - update additional contributors to resource
+
+ :Parameters:
+ - `contributors`: Set contributors of the resource
+ :Types:
+ - `contributors`: comma seperated string or list or tuple
+ :permission: ManageProperties
+ """
+
+ def setEffectiveDate(effective_date):
+ """Dublin Core element - update date resource becomes effective.
+
+ :Parameters:
+ - `effective_date`: Set effective date of the resource
+ :Types:
+ - `effective_date`: DateTime instance or date string
+ :permission: ManageProperties
+ """
+
+ def setExpirationDate(expiration_date):
+ """Dublin Core element - update date resource expires.
+
+ :Parameters:
+ - `expiration_date`: Set expiration date of the resource
+ :Types:
+ - `expiration_date`: DateTime instance or date string
+ :permission: ManageProperties
+ """
+
+ def setFormat(format):
+ """Dublin Core element - update resource format
+
+ :Parameters:
+ - `format`: Set format of the resource
+ :Types:
+ - `format`: string
+ :permission: ManageProperties
+ """
+
+ def setLanguage(language):
+ """Dublin Core element - update resource language
+
+ :Parameters:
+ - `language`: Set language of the resource
+ :Types:
+ - `language`: string
+ :permission: ManageProperties
+ """
+
+ def setRights(rights):
+ """Dublin Core element - update resource copyright
+
+ :Parameters:
+ - `rights`: Set rights of the resource
+ :Types:
+ - `rights`: string
+ :permission: ManageProperties
+ """
+
+class IDublinCore(DublinCore, CatalogableDublinCore, MutableDublinCore):
+ """
+ """
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/IDynamic.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/IDynamic.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,41 @@ />
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+""" Dynamic type interface.
+
+$Id: Dynamic.py,v 1.2.14.2 2004/04/23 21:11:34 sidnei Exp $
+"""
+
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IDynamicType(Interface):
+ """ General interface for dynamic items.
+ """
+
+ def getIcon(relative_to_portal=0):
+ """
+ This method returns the path to an object's icon. It is used
+ in the folder_contents view to generate an appropriate icon
+ for the items found in the folder.
+
+ If the content item does not define an attribute named "icon"
+ this method will return the path "/misc_/dtmldoc.gif", which is
+ the icon used for DTML Documents.
+
+ If 'relative_to_portal' is true, return only the portion of
+ the icon's URL which finds it "within" the portal; otherwise,
+ return it as an absolute URL.
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/IOrderedContainer.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/IOrderedContainer.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,109 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+#Portions of this class was copy/pasted from the OFS.IOrderSupport from
+#Zope2.7. This class is licensed under the ZPL 2.0 as stated here:
+#http://www.zope.org/Resources/ZPL
+#Zope Public License (ZPL) Version 2.0
+#This software is Copyright (c) Zope Corporation (tm) and Contributors. All rights reserved.
+
+class IOrderedContainer(Interface):
+ """ Ordered Container interface.
+
+ This interface provides a common mechanism for maintaining ordered
+ collections.
+ """
+
+ def moveObjectsByDelta(ids, delta, subset_ids=None):
+ """ Move specified sub-objects by delta.
+
+ If delta is higher than the possible maximum, objects will be moved to
+ the bottom. If delta is lower than the possible minimum, objects will
+ be moved to the top.
+
+ If subset_ids is not None, delta will be interted relative to the
+ subset specified by a sequence of ids. The position of objects that
+ are not part of this subset will not be changed.
+
+ The order of the objects specified by ids will always be served. So
+ if you don't want to change their original order, make sure the order
+ of ids corresponds to their original order.
+
+ If an object with id doesn't exist an error will be raised.
+
+ Permission -- Manage properties
+
+ Returns -- Number of moved sub-objects
+ """
+
+ def moveObjectsUp(ids, delta=1):
+ """ Move specified sub-objects up by delta in container.
+
+ If no delta is specified, delta is 1. See moveObjectsByDelta for more
+ details.
+
+ Permission -- Manage properties
+
+ Returns -- Number of moved sub-objects
+ """
+
+ def moveObjectsDown(ids, delta=1):
+ """ Move specified sub-objects down by delta in container.
+
+ If no delta is specified, delta is 1. See moveObjectsByDelta for more
+ details.
+
+ Permission -- Manage properties
+
+ Returns -- Number of moved sub-objects
+ """
+
+ def moveObjectsToTop(ids):
+ """ Move specified sub-objects to top of container.
+
+ See moveObjectsByDelta for more details.
+
+ Permission -- Manage properties
+
+ Returns -- Number of moved sub-objects
+ """
+
+ def moveObjectsToBottom(ids):
+ """ Move specified sub-objects to bottom of container.
+
+ See moveObjectsByDelta for more details.
+
+ Permission -- Manage properties
+
+ Returns -- Number of moved sub-objects
+ """
+
+ def orderObjects(key, reverse=None):
+ """ Order sub-objects by key and direction.
+
+ Permission -- Manage properties
+
+ Returns -- Number of moved sub-objects
+ """
+
+ def getObjectPosition(id):
+ """ Get the position of an object by its id.
+
+ Permission -- Access contents information
+
+ Returns -- Position
+ """
+
+ def moveObjectToPosition(id, position):
+ """ Moves specified object to absolute position.
+
+ Permission -- Manage properties
+
+ Returns -- Number of moved sub-objects
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/IPloneBaseTool.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/IPloneBaseTool.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,13 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IPloneBaseTool(ICMFTool):
+ """Marker interface for plone tools
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/ISyndicatable.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/ISyndicatable.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,36 @@ />
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+""" Syndicatable interface.
+
+$Id: Syndicatable.py,v 1.3.14.2 2004/04/23 21:11:34 sidnei Exp $
+"""
+
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class ISyndicatable(Interface):
+ """\
+ Returns back a list of objects which implements the DublinCore.
+ """
+
+ def synContentValues(self):
+ """
+ Returns a list of results which is to be Syndicated. For example, the normal call
+ contentValues (on PortalFolders) returns a list of subObjects of the current object
+ (i.e. objectValues with filtering applied). For the case of a Topic, one would
+ return a sequence of objects from a catalog query, not the subObjects of the Topic.
+ What is returned must implement the DublinCore.
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/RAMCache.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/RAMCache.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,12 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IRAMCache(Interface):
+ """
+ """
Modified: CMFPlone/branches/tiran-z3iface-branch/interfaces/__init__.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/interfaces/__init__.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/__init__.py Wed Jun 2 16:09:24 2004
@@ -1 +1,9 @@ />
# interface definitions for use by Plone
+
+try:
+ from zope.interface import Interface
+except ImportError:
+ import os
+ import sys
+ zope3 = os.path.join(os.path.dirname(__file__), os.pardir, 'zope3')
+ sys.path.append(zope3)
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/archetypes_tool.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/archetypes_tool.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,14 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IArchetypesTool(Interface):
+ """
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/caching_policy_manager.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/caching_policy_manager.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,12 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class ICachingPolicyManager(Interface):
+ """
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/common.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/common.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,12 @@ />
+"""Common vars, classes and methods for all interfaces
+"""
+
+# used for __extra_epydoc_fields__
+EXTRA_EPYDOC_FIELDS = [
+ ('permission', 'Permission', 'Permissions'),
+ ]
+
+# docformat used for __docformat__
+DOCFORMAT = 'restructuredtext'
+
+__all__ = ('EXTRA_EPYDOC_FIELDS', 'DOCFORMAT', )
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/content_type_registry.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/content_type_registry.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,14 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IContentTypeRegistry(Interface):
+ """
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/cookie_authentication.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/cookie_authentication.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,12 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class ICookieAuthentication(Interface):
+ """
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/mimetypes_registry.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/mimetypes_registry.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,14 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IMimetypeRegistry(Interface):
+ """
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/plone_utils.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/plone_utils.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,133 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+_marker=[]
+
+class IPloneTool(Interface):
+ """
+ """
+
+ id = Attribute('id', 'Must be set to "plone_utils"')
+
+ def setMemberProperties(member, **properties):
+ """
+ """
+
+ def sendto(variables = {}):
+ """Sends a link of a page to someone
+ """
+
+ def editMetadata(obj
+ , allowDiscussion=None
+ , title=None
+ , subject=None
+ , description=None
+ , contributors=None
+ , effective_date=None
+ , expiration_date=None
+ , format=None
+ , language=None
+ , rights=None
+ , **kwargs):
+ """ responsible for setting metadata on a content object
+ we assume the obj implemented IDublinCoreMetadata
+ """
+
+ def contentEdit(obj, **kwargs):
+ """encapsulates how the editing of content occurs
+ """
+
+ def availableMIMETypes():
+ """Return a map of mimetypes
+ """
+
+ def getWorkflowChainFor(object):
+ """Proxy the request for the chain to the workflow
+ tool, as this method is private there.
+ """
+
+ def getIconFor(category, id, default=_marker):
+ """Cache point for actionicons.getActionIcon call
+ also we want to allow for a default icon id to be
+ passed in.
+ """
+
+ def getReviewStateTitleFor(obj):
+ """Utility method that gets the workflow state title for the
+ object's review_state. Returns None if no review_state found.
+ """
+
+ def setDefaultSkin(default_skin):
+ """sets the default skin
+ """
+
+ def setCurrentSkin(skin_name):
+ """sets the current skin
+ """
+
+ def getNextPageFor(context, action, status, **kwargs):
+ """
+ """
+
+ def getNextRequestFor(context, action, status, **kwargs):
+ """
+ """
+
+ def changeOwnershipOf(object, owner, recursive=0):
+ """changes the ownership of an object
+ """
+
+ def urlparse(url):
+ """returns the pieces of url
+ """
+
+ def exceptionString():
+ """
+ """
+
+ def logException():
+ """
+ """
+
+ def createNavigationTreeBuilder(tree_root,
+ navBatchStart=None,
+ showMyUserFolderOnly=None,
+ includeTop=None,
+ showFolderishSiblingsOnly=None,
+ showFolderishChildrenOnly=None,
+ showNonFolderishObject=None,
+ topLevel=None,
+ batchSize=None,
+ showTopicResults=None,
+ rolesSeeUnpublishedContent=None,
+ sortCriteria=None,
+ metaTypesNotToList=None,
+ parentMetaTypesNotToQuery=None,
+ forceParentsInBatch=None,
+ skipIndex_html=None,
+ rolesSeeHiddenContent=None,
+ bottomLevel=None):
+ """ Returns a structure that can be used by
+ navigation_tree_slot. We are being quite lazy because of
+ massive signature. """
+
+ def good_id(id):
+ """
+ """
+
+ def getInheritedLocalRoles(here):
+ """
+ """
+
+ def browserDefault(obj):
+ """Set default so we can return whatever we want instead of
+ index_html
+ """
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_actionicons.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_actionicons.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,156 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IActionIconsTool(Interface):
+ """
+ """
+
+ id = Attribute('id', 'Must be set to "portal_actionicons"')
+
+ def listActionIcons():
+ """ Return a sequence of mappings for action icons
+
+ o Mappings are in the form: ( category, action ) -> icon,
+ where category and action are strings and icon is an ActionIcon
+ instance.
+ """
+
+ def getActionInfo(category
+ , action_id
+ , context=None
+ ):
+ """ Return a tuple, '(title, priority, icon ID), for the given action.
+
+ o Raise a KeyError if no icon has been defined for the action.
+ """
+
+ def queryActionInfo(category
+ , action_id
+ , default=None
+ , context=None
+ ):
+ """ Return a tuple, '(title, priority, icon ID), for the given action.
+
+ o Return 'default' if no icon has been defined for the action.
+ """
+
+ def getActionIcon(category, action_id, context=None ):
+ """ Return an icon ID for the given action.
+
+ o Raise a KeyError if no icon has been defined for the action.
+
+ o Context is an Exssion context object, used to evaluate
+ TALES exssions.
+ """
+
+ def queryActionIcon(category, action_id
+ , default=None, context=None ):
+ """ Return an icon ID for the given action.
+
+ o Return 'default' if no icon has been defined for the action.
+
+ o Context is an Exssion context object, used to evaluate
+ TALES exssions.
+ """
+
+ def updateActionDicts(categorized_actions, context=None ):
+ """ Update a set of dictionaries, adding 'title, 'priority', and
+ 'icon' keys.
+
+ o S.b. passed a data structure like that returned from ActionsTool's
+ 'listFilteredActionsFor':
+
+ - Dict mapping category -> seq. of dicts, where each of the
+ leaf dicts must have 'category' and 'id' keys.
+
+ o *Will* overwrite the 'title' key, if title is defined on the tool.
+
+ o *Will* overwrite the 'priority' key.
+
+ o *Will* overwrite the 'icon' key, if icon is defined on the tool
+
+ o XXX: Don't have a way to pass Exssion context yet.
+ """
+
+ #
+ # Mutators
+ #
+ def addActionIcon(category
+ , action_id
+ , icon_expr
+ , title=None
+ , priority=0
+ ):
+ """ Add an icon for the given action.
+
+ o Raise KeyError if an icon has already been defined.
+ """
+
+ def updateActionIcon(category
+ , action_id
+ , icon_expr
+ , title=None
+ , priority=0
+ ):
+ """ Update the icon for the given action.
+
+ o Raise KeyError if an icon has not already been defined.
+ """
+
+ def removeActionIcon(category, action_id ):
+ """ Remove the icon for the given action.
+
+ o Raise KeyError if an icon has not already been defined.
+ """
+
+ def clearActionIcons():
+ """ Remove all mappings from the tool.
+ """
+
+
+class IActionIcon(Interface):
+ """
+ , category
+ , action_id
+ , icon_expr_text=''
+ , title=None
+ , priority=0
+ """
+
+ def getTitle():
+ """Simple accessor
+ """
+ return self._title
+
+ def getPriority():
+ """Simple accessor
+ """
+
+ def getCategory():
+ """Simple accessor
+ """
+
+ def getActionId():
+ """Simple accessor
+ """
+
+ def getExssion():
+ """Simple accessor
+ """
+
+ def getIconURL(context=None ):
+ """Simple accessor
+ """
+
+ def updateIconExssion(icon_expr_text ):
+ """Mutate icon exssion.
+ """
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_actions.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_actions.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,100 @@ />
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+""" Actions tool interface.
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IActionsTool(Interface):
+ '''Gathers a list of links which the user is allowed to view according to
+ the current context.
+ '''
+ id = Attribute('id', 'Must be set to "portal_actions"')
+
+ # listActionProviders__roles__ = ( 'Manager', )
+ def listActionProviders():
+ """ Lists all action provider names registered with the
+ actions tool.
+ """
+
+ # addActionProvider__roles__ = ( 'Manager', )
+ def addActionProvider( provider_name ):
+ """ Add a new action provider to the providers known by the actions
+ tool. A provider must implement listActions.
+ The provider is only added is the actions tool can find the
+ object corresponding to the provider_name
+ """
+
+ # deleteActionProvider__roles__ = ( 'Manager', )
+ def deleteActionProvider( provider_name ):
+ """ Deletes an action provider name from the providers known to
+ the actions tool. The deletion only takes place if provider_name
+ is actually found among the known action providers.
+ """
+
+ # listFilteredActionsFor__roles__ = None
+ def listFilteredActionsFor(object):
+ '''Gets all actions available to the user and returns a mapping
+ containing a list of user actions, folder actions, object actions,
+ and global actions. Each action has the following keys:
+ name: An identifying action name
+ url: The URL to visit to access the action
+ permissions: A list. The user must have at least of the listed
+ permissions to access the action. If the list is empty,
+ the user is allowed. (Note that listFilteredActions() filters
+ out actions according to this field.)
+ category: One of "user", "folder", "object", or "globals".
+ '''
+
+ # listFilteredActions__roles__ = None
+ def listFilteredActions():
+ '''Gets all actions available to the user in no particular context.
+ '''
+
+class ActionProvider(Interface):
+ '''The interface expected of an object that can provide actions.
+ '''
+
+ # listActions__roles__ = () # No permission.
+ def listActions(info=None):
+ """ Return all the actions defined by a provider.
+
+ The info argument is currently used by 'Oldstyle CMF Discussion Tool'
+ and 'CMF Workflow Tool'.
+
+ Returns -- Tuple of ActionInformation objects
+
+ Oldstyle dictionary actions are currently also supported:
+ Returns a list of mappings describing actions. Each action
+ should contain the keys "name", "url", "permissions", and
+ "category", conforming to the specs outlined in
+ portal_actions.listFilteredActionsFor(). The info argument
+ contains at least the following attributes, some of which
+ may be set to "None":
+
+ isAnonymous
+ portal
+ portal_url
+ folder
+ folder_url
+ content
+ content_url
+ The new way of doing this is....
+ """
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_calendar.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_calendar.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,14 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class ICalendarTool(IPloneBaseTool):
+ """
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_catalog.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_catalog.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,69 @@ />
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+""" Catalog tool interface.
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class ICatalogTool(Interface):
+ '''This tool interacts with a customized ZCatalog.
+ '''
+ id = Attribute('id', 'Must be set to "portal_catalog"')
+
+ # searchResults inherits security assertions from ZCatalog.
+ def searchResults(REQUEST=None, **kw):
+ '''Calls SiteIndex.searchResults() with extra arguments that
+ limit the results to what the user is allowed to see.
+ '''
+
+ # __call__ inherits security assertions from ZCatalog.
+ def __call__(REQUEST=None, **kw):
+ '''Same as searchResults().'''
+
+ # indexObject__roles__ = () # Called only by Python code.
+ def indexObject(object):
+ '''Add to catalog.
+ '''
+
+ # unindexObject__roles__ = ()
+ def unindexObject(object):
+ '''Remove from catalog.
+ '''
+
+ # reindexObject__roles__ = ()
+ def reindexObject(object, idxs=[]):
+ '''Update entry in catalog.
+ The optional idxs argument is a list of specific indexes
+ to update (all of them by default).
+ '''
+
+ # getpath inherits security assertions from ZCatalog.
+ def getpath(data_record_id_):
+ '''Calls ZCatalog.getpath().
+ '''
+
+class IndexableObjectWrapper(Interface):
+ """ Indexable object wrapper interface.
+ """
+
+ def allowedRolesAndUsers():
+ """
+ Return a list of roles and users with View permission.
+ Used by PortalCatalog to filter out items you're not allowed to see.
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_controlpanel.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_controlpanel.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,44 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IControlPanel(IPloneBaseTool):
+ """ Interface for the ControlPanel """
+
+ def registerConfiglet( id
+ , name
+ , action
+ , condition=''
+ , permission=''
+ , category='Plone'
+ , visible=1
+ , appId=None
+ , imageUrl=None
+ , description=''
+ , REQUEST=None
+ ):
+ """ Registration of a Configlet """
+
+ def unregisterConfiglet(id):
+ """ unregister Configlet """
+
+ def unregisterApplication(appId):
+ """ unregister Application with all configlets """
+
+ def getGroupIds():
+ """ list of the group ids """
+
+ def getGroups():
+ """ list of groups as dicts with id and title """
+
+ def enumConfiglets(group=None):
+ """ lists the Configlets of a group, returns them as dicts by
+ calling .getAction() on each of them """
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_discussion.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_discussion.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,59 @@ />
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+""" Discussion tool interface.
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class oldstyle_portal_discussion(Interface):
+ """ Links content to discussions.
+ """
+ id = Attribute('id', 'Must be set to "portal_discussion"')
+
+ #getDiscussionFor__roles__ = None
+ def getDiscussionFor(content):
+ """
+ Find / create the DiscussionItemContainer for 'content'.
+ """
+
+ #isDiscussionAllowedFor__roles__ = None
+ def isDiscussionAllowedFor(content):
+ """
+ Return a boolean indicating whether discussion is
+ allowed for the specified content; this may be looked
+ up via an object-specific value, or by place, or from
+ a site-wide policy.
+ """
+
+
+class IDiscussionTool(oldstyle_portal_discussion):
+ """ Links content to discussions.
+ """
+
+ #getDiscussionFor__roles__ = None
+ def overrideDiscussionFor(content, allowDiscussion):
+ """
+ if 'allowDiscussion' is None, then clear any overridden
+ setting for discussability, letting the site's default
+ policy apply. Otherwise, set the override to match
+ the boolean equivalent of 'allowDiscussion'.
+ """
+
+
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_factory.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_factory.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,43 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class ITempFolder(Interface):
+ """ """
+ def getPhysicalPath():
+ """ """
+ def __getitem__(id):
+ """ """
+
+class IFactoryTool(IPloneBaseTool):
+ """ """
+
+ def docs():
+ """ """
+ def getFactoryTypes():
+ """ """
+ def manage_setPortalFactoryTypes(REQUEST, listOfTypeIds):
+ """ """
+ def doCreate(obj):
+ """ """
+ def fixRequest():
+ """ """
+ def isTemporary(obj):
+ """ """
+ def __before_publishing_traverse__(other, REQUEST):
+ """ """
+ def __call__(*args, **kwargs):
+ """ """
+ def getTempFolder(type_name):
+ """ """
+ def __bobo_traverse__(REQUEST, name):
+ """ """
+
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_form.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_form.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,57 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class ICMFForm(Interface):
+ """ Wraps a Formulator BasicForm and provides convience methods to
+ ease validation """
+
+ def addField(field_id, fieldType, group=None, **kwargs):
+ """ Adds a Formulator Field to a Form object
+ The fieldType is referred to by the fix
+ before Field in a Formulator field. i.e.
+ fieldType String == StringField
+ """
+
+ def validate(REQUEST, errors=None):
+ """ Iterates through the fields on the Form object and validates them.
+ Errors can be passed in and will be appended to the errors dictionary.
+ We will also strip the fix of 'field_' in the REQUEST.form dictionary.
+ """
+
+class IFormTool(IPloneBaseTool):
+ """ FormTool handles Form validation, caching of Form validators and serves as a factory for portal_form objects.
+ """
+
+ def setValidators(form, validators=None):
+ """ Given a form id and a sequence of validators, update the validators.
+ """
+
+ def getValidators(form):
+ """ Get the sequence of validators for a form id """
+
+ def good_id(id):
+ """ determines if the id is usable by an ObjectManager """
+
+ def createForm():
+ """ return a CMFForm object that provides some convience methods """
+
+ def cacheValidator(key, validator):
+ """ cache a validator by a key """
+
+ def getCachedValidator(key):
+ """ returns a cached validator or None """
+
+ def setValidator(form, validator):
+ """ sets a validator to a form id """
+
+ def getValidator(form):
+ """ returns the first validator for the form id """
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_groupdata.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_groupdata.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,56 @@ />
+# Copyright (c) 2003 The Connexions Project, All Rights Reserved
+# initially written by J Cameron Cooper, 11 June 2003
+# concept with Brent Hendricks, George Runyan
+
+""" Group data tool interface
+
+Goes along the lines of portal_memberdata, but for groups.
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IGroupDataTool(Interface):
+ """ A helper tool for portal_groups that transparently adds
+ properties to groups and provides convenience methods"""
+
+ id = Attribute('id', "Must be set to 'portal_groupdata'")
+
+ def wrapGroup(g):
+ """ Returns an object implementing the GroupData interface"""
+
+class GroupData(Interface):
+ """ An abstract interface for accessing properties on a group object"""
+
+ def setProperties(properties=None, **kw):
+ """ Allows setting of group properties en masse """
+
+ def getProperty(id):
+ """ Returns the value of the property specified by 'id' """
+
+ def getProperties():
+ """ Returns the properties of this group. Properties are as usual in Zope."""
+
+ def getGroupId():
+ """ Returns the string id of this group."""
+
+ def getGroupName():
+ """ Returns the name of the group."""
+
+ def getGroupMembers():
+ """ Returns a list of the portal_memberdata-ish members of the group."""
+
+ def addMember(id):
+ """ Add the existing member with the given id to the group"""
+
+ def removeMember(id):
+ """ Remove the member with the provided id from the group """
+
+ def getGroup():
+ """ Returns the actual group implementation. Varies by group
+ implementation (GRUF/Nux/et al)."""
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_groups.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_groups.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,116 @@ />
+# Copyright (c) 2003 The Connexions Project, All Rights Reserved
+# initially written by J Cameron Cooper, 11 June 2003
+# concept with Brent Hendricks, George Runyan
+
+""" Groups tool interface
+
+Goes along the lines of portal_membership, but for groups.
+$Id: portal_groups.py 4908 2004-04-19 22:35:57Z tiran $
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IGroupsTool(Interface):
+ """Defines an interface for working with groups in an abstract manner.
+ Parallels the portal_membership interface of CMFCore"""
+ id = Attribute('id','Must be set to "portal_groups"')
+
+ def getGroupById(id):
+ """Returns the portal_groupdata-ish object for a group corresponding
+ to this id."""
+
+ def getGroupsByUserId(userid):
+ """Returns a list of the groups the user corresponding to 'userid' belongs to."""
+
+ def listGroups():
+ """Returns a list of the available portal_groupdata-ish objects."""
+
+ def listGroupIds():
+ """Returns a list of the available groups' ids."""
+
+ def getPureUserNames():
+ """Get the usernames (ids) of only users. """
+
+ def getPureUsers():
+ """Get the actual (unwrapped) user objects of only users. """
+
+ def searchForGroups(REQUEST, **kw): # maybe searchGroups()?
+ """Return a list of groups meeting certain conditions. """
+ # arguments need to be better refined?
+
+ def addGroup(id, password, roles, domains):
+ """Create a group with the supplied id, roles, and domains.
+
+ Underlying user folder must support adding users via the usual Zope API.
+ Passwords for groups seem to be currently irrelevant in GRUF."""
+
+ def editGroup(id, password, roles, permissions):
+ """Edit the given group with the supplied password, roles, and domains.
+
+ Underlying user folder must support editing users via the usual Zope API.
+ Passwords for groups seem to be currently irrelevant in GRUF."""
+
+ def removeGroups(ids, keep_workspaces=0):
+ """Remove the group in the provided list (if possible).
+
+ Will by default remove this group's GroupWorkspace if it exists. You may
+ turn this off by specifying keep_workspaces=true.
+ Underlying user folder must support removing users via the usual Zope API."""
+
+ def setGroupOwnership(group, object):
+ """Make the object 'object' owned by group 'group' (a portal_groupdata-ish object)"""
+
+ def setGroupWorkspacesFolder(id=""):
+ """ Set the location of the Group Workspaces folder by id.
+
+ The Group Workspaces Folder contains all the group workspaces, just like the
+ Members folder contains all the member folders.
+
+ If anyone really cares, we can probably make the id work as a path as well,
+ but for the moment it's only an id for a folder in the portal root, just like the
+ corresponding MembershipTool functionality. """
+
+ def getGroupWorkspacesFolderId():
+ """ Get the Group Workspaces folder object's id.
+
+ The Group Workspaces Folder contains all the group workspaces, just like the
+ Members folder contains all the member folders. """
+
+ def getGroupWorkspacesFolder():
+ """ Get the Group Workspaces folder object.
+
+ The Group Workspaces Folder contains all the group workspaces, just like the
+ Members folder contains all the member folders. """
+
+ def toggleGroupWorkspacesCreation():
+ """ Toggles the flag for creation of a GroupWorkspaces folder upon first
+ use of the group. """
+
+ def getGroupWorkspacesCreationFlag():
+ """Return the (boolean) flag indicating whether the Groups Tool will create a group workspace
+ upon the next use of the group (if one doesn't exist). """
+
+ def getGroupWorkspaceType():
+ """Return the Type (as in TypesTool) to make the GroupWorkspace."""
+
+ def setGroupWorkspaceType(type):
+ """Set the Type (as in TypesTool) to make the GroupWorkspace. Expects the name of a Type."""
+
+ def createGrouparea(id):
+ """Create a space in the portal for the given group, much like member home
+ folders."""
+
+ def getGroupareaFolder(id):
+ """Returns the object of the group's work area."""
+
+ def getGroupareaURL(id):
+ """Returns the full URL to the group's work area."""
+
+ # and various roles things...
+
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_interface.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_interface.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,28 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IInterfaceTool(IPloneBaseTool):
+ """ This tool exposes the interface package for TTW applications,
+ by accepting a dotted name of an interface and exporting the
+ IInterface API """
+
+ id = Attribute('id', 'Must be set to "portal_interface"')
+
+ def objectImplements(obj, dotted_name):
+ """ Asserts if an object implements a given interface """
+
+ def classImplements(obj, dotted_name):
+ """ Asserts if an object's class implements a given interface """
+
+ def namesAndDescriptions(dotted_name, all=0):
+ """ Returns a list of pairs (name, description) for a given
+ interface"""
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_memberdata.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_memberdata.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,65 @@ />
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+""" Memberdata storage tool interface.
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IMemberDataTool(Interface):
+ '''A helper for portal_membership that transparently adds
+ member data to user objects.
+ '''
+ id = Attribute('id', 'Must be set to "portal_memberdata"')
+
+ ## wrapUser__roles__ = () # Private.
+ def wrapUser(u):
+ '''
+ If possible, returns the Member object that corresponds
+ to the given User object.
+ '''
+ ## getMemberDataContents__roles__ = () # Private.
+ def getMemberDataContents():
+ '''
+ Returns a list containing a dictionary with information
+ about the _members BTree contents: member_count is the
+ total number of member instances stored in the memberdata-
+ tool while orphan_count is the number of member instances
+ that for one reason or another are no longer in the
+ underlying acl_users user folder.
+ The result is designed to be iterated over in a dtml-in
+ '''
+
+ ## pruneMemberDataContents__roles__ = () # Private.
+ def pruneMemberDataContents():
+ '''
+ Compare the user IDs stored in the member data
+ tool with the list in the actual underlying acl_users
+ and delete anything not in acl_users
+ '''
+
+
+class MemberData(Interface):
+ """ MemberData interface.
+ """
+
+ def setProperties(properties=None, **kw):
+ """ Allows the authenticated member to set his/her own properties.
+
+ Permission -- SetOwnProperties
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_membership.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_membership.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,150 @@ />
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+""" Membership tool interface.
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IMembershipTool(Interface):
+ '''Deals with the details of how and where to store and retrieve
+ members and their member folders.
+ '''
+ id = Attribute('id', 'Must be set to "portal_membership"')
+
+ def setPassword(password, domains=None):
+ """ Allows the authenticated member to set his/her own password.
+
+ Permission -- SetOwnPassword
+ """
+
+ #getAuthenticatedMember__roles__ = None # Allow all.
+ def getAuthenticatedMember():
+ '''
+ Returns the currently authenticated member object
+ or the Anonymous User.
+ '''
+
+ #isAnonymousUser__roles__ = None # Allow all.
+ def isAnonymousUser():
+ '''
+ Returns 1 if the user is not logged in.
+ '''
+
+ #checkPermission__roles__ = None # Allow all.
+ def checkPermission(permissionName, object, subobjectName=None):
+ '''
+ Checks whether the current user has the given permission on
+ the given object or subobject.
+ '''
+
+ #credentialsChanged__roles__ = None # Allow all.
+ def credentialsChanged(password):
+ '''
+ Notifies the authentication mechanism that this user has changed
+ passwords. This can be used to update the authentication cookie.
+ Note that this call should *not* cause any change at all to user
+ databases.
+ '''
+
+ # getHomeFolder__roles__ = None # Anonymous permission
+ def getHomeFolder(id=None, verifyPermission=0):
+ """Returns a member's home folder object or None.
+ Set verifyPermission to 1 to return None when the user
+ doesn't have the View permission on the folder.
+ """
+
+ # getHomeUrl__roles__ = None # Anonymous permission
+ def getHomeUrl(id=None, verifyPermission=0):
+ """Returns the URL to a member's home folder or None.
+ Set verifyPermission to 1 to return None when the user
+ doesn't have the View permission on the folder.
+ """
+
+ # permission: 'Manage portal'
+ def getMemberById(id):
+ '''
+ Returns the given member.
+ '''
+
+ # permission: 'Manage portal'
+ def listMemberIds():
+ '''Lists the ids of all members. This may eventually be
+ replaced with a set of methods for querying pieces of the
+ list rather than the entire list at once.
+ '''
+
+ # permission: 'Manage portal'
+ def listMembers():
+ '''Gets the list of all members.
+ '''
+
+ #addMember__roles__ = () # No permission.
+ def addMember(id, password, roles, domains):
+ '''Adds a new member to the user folder. Security checks will have
+ already been performed. Called by portal_registration.
+ '''
+
+ # getPortalRoles__roles__ = () # Private
+ def getPortalRoles():
+ """
+ Return all local roles defined by the portal itself,
+ which means roles that are useful and understood
+ by the portal object
+ """
+
+ # setRoleMapping__roles__ = () # Private
+ def setRoleMapping(portal_role, userfolder_role):
+ """
+ set the mapping of roles between roles understood by
+ the portal and roles coming from outside user sources
+ """
+
+ # getMappedRole__roles__ = () # Private
+ def getMappedRole(portal_role):
+ """
+ returns a role name if the portal role is mapped to
+ something else or an empty string if it is not
+ """
+
+ # getMemberareaCreationFlag__roles__ = () # Private
+ def getMemberareaCreationFlag():
+ """
+ Returns the flag indicating whether the membership tool
+ will create a member area if an authenticated user from
+ an underlying user folder logs in first without going
+ through the join process
+ """
+
+ # setMemberareaCreationFlag__roles__ = () # Private
+ def setMemberareaCreationFlag():
+ """
+ sets the flag indicating whether the membership tool
+ will create a member area if an authenticated user from
+ an underlying user folder logs in first without going
+ through the join process
+ """
+
+ # createMemberarea__roles__ = () # Private
+ def createMemberarea(member_id):
+ """
+ create a member area, only used if members are sourced
+ from an independent underlying user folder and not just
+ from the join process
+ """
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_metadata.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_metadata.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,107 @@ />
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+""" Metadata registration tool interface.
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IMetadataTool(Interface):
+ """
+ CMF metadata policies interface.
+ """
+ id = Attribute('id', 'Must be set to "portal_metadata"')
+
+ #
+ # Site-wide queries.
+ #
+ def getFullName(userid):
+ """
+ Convert an internal userid to a "formal" name, if
+ possible, perhaps using the 'portal_membership' tool.
+
+ Used to map userid's for Creator, Contributor DCMI
+ queries.
+ """
+
+ def getPublisher():
+ """
+ Return the "formal" name of the publisher of the
+ portal.
+ """
+
+ #
+ # Content-specific queries.
+ #
+ def listAllowedSubjects(content=None):
+ """
+ List the allowed values of the 'Subject' DCMI element
+ 'Subject' elements should be keywords categorizing
+ their resource.
+
+ Return only values appropriate for content's type, or
+ all values if None.
+ """
+
+ def listAllowedFormats(content=None):
+ """
+ List the allowed values of the 'Format' DCMI element.
+ These items should be usable as HTTP 'Content-type'
+ values.
+
+ Return only values appropriate for content's type, or
+ all values if None.
+ """
+
+ def listAllowedLanguages(content=None):
+ """
+ List the allowed values of the 'Language' DCMI element.
+ 'Language' element values should be suitable for generating
+ HTTP headers.
+
+ Return only values appropriate for content's type, or
+ all values if None.
+ """
+
+ def listAllowedRights(content=None):
+ """
+ List the allowed values of the 'Rights' DCMI element.
+ The 'Rights' element describes copyright or other IP
+ declarations pertaining to a resource.
+
+ Return only values appropriate for content's type, or
+ all values if None.
+ """
+
+ #
+ # Validation policy hooks.
+ #
+ def setInitialMetadata(content):
+ """
+ Set initial values for content metatdata, supplying
+ any site-specific defaults.
+ """
+
+ def validateMetadata(content):
+ """
+ Enforce portal-wide policies about DCI, e.g.,
+ requiring non-empty title/description, etc. Called
+ by the CMF immediately before saving changes to the
+ metadata of an object.
+ """
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_migration.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_migration.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,15 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IMigrationTool(IPloneBaseTool):
+ """
+ """
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_navigation.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_navigation.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,63 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class INavigationTool(Interface):
+ """ The NavigationController acts as a controller that controls complex states of the system.
+
+ The interface provides ways for getNext() transition (where to go next) as well as how
+ to add/remove transitions (complex states) from the object.
+ """
+
+ def getNext(context, script, status, trace, **kwargs):
+ """ Perform the next action specified by in portal_properties.navigation_properties.
+
+ context - the current context
+
+ script - the script/template currently being called
+
+ status - 'success' or 'failure' strings used in calculating destination
+
+ kwargs - additional keyword arguments are passed to subsequent pages either in
+ the REQUEST or as GET parameters if a redirection needs to be done
+
+ trace - navigation trace for internal use
+ """
+
+ def addTransitionFor(content, script, status, destination):
+ """ Adds a transition. When SCRIPT with context CONTENT returns STATUS, go to DESTINATION
+
+ content - is a object or a TypeInfo that you would like to register.
+ A None content object will register Default values.
+
+ script - the script/template that was just called
+
+ status - SUCCESS or FAILURE strings used in calculating destination
+
+ destination - is an action registed on the TypeInfo or a
+ free-form script that would be appended to
+ the url of the content Destinations are
+ specified as follows: action:ACTION_NAME
+ invokes the action ACTION_NAME on the
+ current context script:SCRIPT_NAME invokes
+ the python script SCRIPT_NAME on the current
+ context. The script should return a tuple
+ containing a status code (either 'success'
+ or 'failure') and optional kwargs.
+ getNext() will be called using the return
+ code to determine the next page to load.
+ url:URL redirects to the url specified by
+ URL. URL may be absolute or relative PAGE
+ invokes the page PAGE on the current context
+ """
+
+ def removeTransitionFrom(content, script=None, status=None):
+ """ Removes all participating transitions involvd with a content/script interaction """
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_properties.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_properties.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,48 @@ />
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+""" Properties tool interface.
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IPropertiesTool(Interface):
+ """ CMF Properties Tool interface.
+
+ This interface provides access to "portal-wide" properties.
+ """
+ id = Attribute('id', 'Must be set to "portal_properties"')
+
+ def editProperties(props):
+ """ Change portal settings.
+
+ Permission -- ManagePortal
+ """
+
+ def title():
+ """ Get portal title.
+
+ Returns -- String
+ """
+
+ def smtp_server():
+ """ Get local SMTP server.
+
+ Returns -- String
+ """
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_quickinstaller.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_quickinstaller.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,130 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IQuickInstallerTool(Interface):
+ ''' the QuickInstaller Tool
+ contains 'InstalledProduct' instances
+ '''
+
+ id = Attribute('id', 'Must be set to "portal_quickinstaller"')
+
+ def listInstallableProducts(skipInstalled=1):
+ ''' list candidate CMF products for installation -> list of dicts with
+ keys:(id,hasError,status)'''
+
+ def listInstalledProducts(showHidden=0):
+ ''' returns a list of products that are installed -> list of dicts with
+ keys:(id,hasError,status,,isLocked,isHidden)'''
+
+ def isProductInstallable(productname):
+ ''' is the product directory sent and ready for installation '''
+
+ def isProductAvailable(productname):
+ ''' is the product directory sent (to check if it has been deleted
+ from the Filesystem '''
+
+ def installProduct(p,locked=0,hidden=0,swallowExceptions=0):
+ ''' installs a product by name
+ throws AlreadyInstalled exception, if components of the product are
+ already installed
+
+ if swallowExceptions is true, exceptions are caught and logged
+ '''
+
+ def installProducts(products=[], stoponerror=0, REQUEST=None):
+ ''' installs the products specified in the products list'''
+
+ def getProductFile(p,fname='readme.txt'):
+ ''' returns the content of a file of the product case-insensitive, if it
+ does not exist -> None '''
+
+ def getProductReadme(p):
+ ''' returns the readme file of the product case-insensitive '''
+
+ def getProductVersion(p):
+ ''' returns the version string stored in version.txt'''
+
+ def isProductInstalled(productname):
+ ''' checks wether a product is installed (by name) '''
+
+ def notifyInstalled(p,locked=1, hidden=0, **kw):
+ ''' marks a product that has been installed without QuickInstaller
+ as installed
+ if locked is set -> the prod cannot be uninstalled
+ if hidden is set -> the prod is not listed in the UI
+ the **kw param is passed to the constructor of InstalledProduct
+ '''
+
+
+ def uninstallProducts( products, cascade=['types','skins','actions',
+ 'portalobjects','workflows','slots','registrydicates'],REQUEST=None):
+ ''' removes a list of products, cascade defines which items created by
+ the install shall be uninstalled '''
+
+ def reinstallProducts( products, REQUEST=None):
+ ''' reinstalls a list of products, the main difference to
+ ininstall/reinstall is that it does not remove portal objects
+ created during install (e.g. tools, etc.)'''
+
+class IInstalledProduct(Interface):
+ ''' resents the installed product
+ is contained inside the QuickInstallerTool '''
+
+ id = Attribute('id', 'Must be set to the same name as the product directory')
+
+ types = Attribute('types','default: []')
+ skins = Attribute('types','default: []')
+ actions = Attribute('types','default: []')
+ portalobjects = Attribute('types','default: []')
+ workflows = Attribute('types','default: []')
+ leftslots = Attribute('types','default: []')
+ rightslots = Attribute('types','default: []')
+
+ def __init__(id,types=[],skins=[],actions=[],portalobjects=[],
+ workflows=[],leftslots=[],rightslots=[],registrydicates=[],logmsg='',
+ status='installed', error=0, locked=0, hidden=0):
+ ''' constructor '''
+
+ def update(types=[],skins=[],actions=[],portalobjects=[],workflows=[],
+ leftslots=[],rightslots=[],registrydicates=[],logmsg='',
+ status='installed',error=0,locked=0,hidden=0):
+ ''' updates the product attributes '''
+
+ def log(logmsg):
+ ''' adds a log to the transcript '''
+
+ def hasError():
+ ''' returns if the prod is in error state '''
+
+ def isLocked():
+ ''' is the product locked for uninstall '''
+
+ def isHidden():
+ ''' is the product hidden'''
+
+ def isInstalled():
+ ''' determines if the product is in already installed '''
+
+ def getTranscriptAsText():
+ ''' return the product's install log as plain text '''
+
+ def uninstall(cascade=['types','skins','actions','portalobjects',
+ 'workflows','slots','registrydicates'],REQUEST=None):
+ '''uninstalls the prod and removes its deps
+ the parameter 'cascade' specifies what should be deleted while
+ uninstalling the product
+
+ if the Product has an uninstall() method in its Install.py it gets
+ called automatically
+ '''
+ def getInstalledVersion():
+ ''' returns the version of the prod in the moment of installation '''
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_registration.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_registration.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,81 @@ />
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+""" Registration tool interface.
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IRegistrationTool(Interface):
+ '''Establishes policies for member registration. Depends on
+ portal_membership. Is not aware of membership storage details.
+ '''
+ id = Attribute('id', 'Must be set to "portal_registration"')
+
+ #isRegistrationAllowed__roles__ = None # Anonymous permission
+ def isRegistrationAllowed(REQUEST):
+ '''Returns a boolean value indicating whether the user
+ is allowed to add a member to the portal.
+ '''
+
+ #testPasswordValidity__roles__ = None # Anonymous permission
+ def testPasswordValidity(password, confirm=None):
+ '''If the password is valid, returns None. If not, returns
+ a string explaining why.
+ '''
+
+ #testPropertiesValidity__roles__ = None # Anonymous permission
+ def testPropertiesValidity(new_properties, member=None):
+ '''If the properties are valid, returns None. If not, returns
+ a string explaining why.
+ '''
+
+ #generatePassword__roles__ = None # Anonymous permission
+ def generatePassword():
+ '''Generates a password which is guaranteed to comply
+ with the password policy.
+ '''
+
+ # permission: 'Add portal member'
+ def addMember(id, password, roles=('Member',), domains='',
+ properties=None):
+ '''Creates a PortalMember and returns it. The properties argument
+ can be a mapping with additional member properties. Raises an
+ exception if the given id already exists, the password does not
+ comply with the policy in effect, or the authenticated user is not
+ allowed to grant one of the roles listed (where Member is a special
+ role that can always be granted); these conditions should be
+ detected before the fact so that a cleaner message can be printed.
+ '''
+
+ # permission: 'Add portal member'
+ def isMemberIdAllowed(id):
+ '''Returns 1 if the ID is not in use and is not reserved.
+ '''
+
+ #afterAdd__roles__ = () # No permission.
+ def afterAdd(member, id, password, properties):
+ '''Called by portal_registration.addMember()
+ after a member has been added successfully.'''
+
+ # permission: 'Mail forgotten password'
+ def mailPassword(forgotten_userid, REQUEST):
+ '''Email a forgotten password to a member. Raises an exception
+ if user ID is not found.
+ '''
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_skins.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_skins.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,64 @@ />
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+""" Skins tool interface.
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class ISkinsTool(Interface):
+ '''An object that provides skins to a portal object.
+ '''
+ id = Attribute('id', 'Must be set to "portal_skins"')
+
+ # Private
+ def getSkinPath(name):
+ """Converts a skin name to a skin path.
+ """
+
+ # Public
+ def getDefaultSkin():
+ """Returns the default skin name.
+ """
+
+ # Public
+ def getRequestVarname():
+ """Returns the variable name to look for in the REQUEST.
+ """
+
+ # Private
+ def getSkinByPath(path, raise_exc=0):
+ """Returns a skin at the given path.
+
+ A skin path is of the format:
+ 'some/path, some/other/path, ...' The first part has cedence.
+
+ A skin is a specially wrapped object that looks through the layers
+ in the correct order.
+ """
+
+ # Private
+ def getSkinByName(name):
+ """Returns the named skin.
+ """
+
+ # Public
+ def getSkinSelections():
+ """Returns the sorted list of available skin names.
+ """
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_syndication.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_syndication.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,15 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class ISyndicationTool(IPloneBaseTool):
+ """
+ """
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_transforms.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_transforms.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,15 @@ />
+"""
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IPortalTransformsTool(Interface):
+ """
+ """
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_types.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_types.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,217 @@ />
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+""" Type registration tool interface.
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class ContentTypeInformation(Interface):
+ """Registry entry interface.
+
+ """
+
+ def Metatype():
+ """Return the Zope 'meta_type' for this content object.
+
+ :return: The metatype of the content object
+ :rtype: string
+ :permission: XXX
+ """
+
+ def Title():
+ """Return the "human readable" type name
+
+ :note: Note that it may not map exactly to the 'meta_type', e.g., for
+ l10n/i18n or where a single content class is being used twice,
+ under different names.
+ :return: The title of the content object
+ :rtype: string
+ :permission: XXX
+ """
+
+ def Description():
+ """Textual description of the class of objects
+
+ Intended for display in a "constructor list"
+
+ :return: The description of the content object
+ :rtype: string
+ :permission: XXX
+ """
+
+ def isConstructionAllowed(container):
+ """Check wether this type can be added to the container
+
+ Does the current user have the permission required in
+ order to construct an instance?
+
+ :Parameters:
+ - `container`: The container that will be checked for adding
+ :Types:
+ - `container`: A CMF based folder in an aquisition wrapper
+ :return: Is allowed?
+ :rtype: bool
+ :permission: XXX
+ """
+
+ def allowType(contentType):
+ """Can objects of 'contentType' be added to containers whose type object we are?
+
+ :Parameters:
+ - `container`: The content type id which will be checked
+ :Types:
+ - `container`: string
+ :return: Is allowed?
+ :rtype: bool
+ :permission: XXX
+
+ """
+
+ def constructInstance(container, id):
+ """Creates an instane
+
+ Build a "bare" instance of the appropriate type in
+ 'container', using 'id' as its id. Return the instance,
+ seated in the container.
+
+ :Parameters:
+ - `container`: The container in that the object will be created
+ - `id`: The id of the new object
+ :Types:
+ - `container`: A CMF based folder in an aquisition wrapper
+ - `id`: string
+ :return: The newly created object in an aquisition wrapper
+ :rtype: instance
+ :permission: XXX
+ """
+
+ def allowDiscussion():
+ """Can this type of object support discussion?
+
+ :return: Is allowed?
+ :rtype: bool
+ :permission: XXX
+ """
+
+ def getActionById(id):
+ """Return the URL of the action whose ID is id.
+
+ :Parameters:
+ - `id`: The id of the action
+ :Types:
+ - `id`: string
+ :return: The url of the action
+ :rtype: string
+ :permission: XXX
+ """
+
+ def getIcon():
+ """Returns the portal-relative icon for this type.
+
+ :return: The url of the icon XXX ?
+ :rtype: string
+ :permission: XXX
+ """
+
+
+class ITypesTool(Interface):
+ """Provides a configurable registry of portal content types.
+ """
+
+ id = Attribute('id', 'Must be set to "portal_types"')
+
+ def getTypeInfo(contentType):
+ """Return a ContentTypeInformation instance
+
+ Return an instance which implements the ContentTypeInformation
+ interface, corresponding to the specified 'contentType'. If contentType
+ is actually an object, rather than a string, attempt to look up the
+ appropriate type info using its portal_type.
+
+ :Parameters:
+ - `contentType`: The id of the content type
+ :Types:
+ - `contentType`: string
+ :return: A instance based on the ContentTypeInformation interface
+ :rtype: instance
+ :permission: public
+ """
+
+ def listTypeInfo(container=None):
+ """Return a list of ContentTypeInformation instances
+
+ Return a sequence of instances which implement the
+ ContentTypeInformation interface, one for each content type registered
+ in the portal. If the container is specified, the list will be
+ filtered according to the user's permissions.
+
+ :Parameters:
+ - `container`: Optional the container XXX
+ :Types:
+ - `container`: A CMF based folder in an aquisition wrapper
+ :return: A instance based on the ContentTypeInformation interface
+ :rtype: instance
+ :permission: XXX
+ """
+
+ def listContentTypes(container=None, by_metatype=0):
+ """Return a list of content type names resp. metatype names
+
+ Return list of content types, or the equivalent metatypes; if
+ 'container' is passed, then filter the list to include only types which
+ are addable in 'container'.
+
+ :Parameters:
+ - `container`: Optional the container XXX
+ - `by_metatype`: Return metatype instead of content type name?
+ :Types:
+ - `container`: A CMF based folder in an aquisition wrapper
+ - `by_metatype`: boolean
+ :return: A list of content type names
+ :rtype: tuple
+ :permission: public
+ """
+
+ def constructContent(contentType, container, id, RESPONSE=None
+ , *args, **kw):
+ """Create an instance of the content type
+
+ Build an instance of the appropriate content class in 'container', using
+ 'id'. If RESPONSE is provided, redirect to the new object's
+ "initial view".
+
+ :Parameters:
+ - `contentType`: The id of the content type that will be created
+ - `container`: The folder where the content type will be created
+ - `id`: The id of the newly created content type
+ - `RESPONSE`: XXX
+ - `arg`: Optional arguments which are passed to the content type
+ - `kw`: Optional keyword arguments which are passed to the content type
+ :Types:
+ - `contentType`: string
+ - `container`: A CMF based folder in an aquisition wrapper
+ - `id`: string
+ - `RESPONSE`: HTTPResponse instance
+ - `arg`: tuple
+ - `kw`: dict
+ :return: XXX
+ :rtype: XXX
+ :permission: XXX
+ """
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_undo.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_undo.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,41 @@ />
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+""" Undo tool interface.
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IUndoTool(Interface):
+ '''Provides access to Zope undo functions.
+ '''
+ id = Attribute('id', 'Must be set to "portal_undo"')
+
+ # permission: 'Undo changes'
+ def listUndoableTransactionsFor(object,
+ first_transaction=None,
+ last_transaction=None,
+ PrincipiaUndoBatchSize=None):
+ '''Lists all transaction IDs the user is allowed to undo.
+ '''
+
+ # permission: 'Undo changes'
+ def undo(object, transaction_info):
+ '''Performs an undo operation.
+ '''
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_url.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_url.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,86 @@ />
+##############################################################################
+#
+# Copyright (c) 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
+#
+##############################################################################
+""" URL tool interface.
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+
+class IURLTool(Interface):
+ """ CMF URL Tool interface.
+
+ This interface provides a common mechanism for finding the 'root'
+ object of a CMFSite, and for computing paths to objects relative to
+ that root.
+ """
+ id = Attribute('id', 'Must be set to "portal_url"')
+
+ def __call__(relative=0, *args, **kw):
+ """ Get by default the absolute URL of the portal.
+
+ Permission -- Always available
+
+ Returns -- Slash-separated string
+ """
+
+ def getPortalObject():
+ """ Get the portal object itself.
+
+ Permission -- Always available
+
+ Returns -- CMFSite object
+ """
+
+ def getRelativeContentPath(content):
+ """ Get the path for an object, relative to the portal root.
+
+ Permission -- Always available
+
+ Returns -- Tuple of IDs
+ """
+
+ def getRelativeContentURL(content):
+ """ Get the URL for an object, relative to the portal root.
+
+ This is helpful for virtual hosting situations.
+ Same method as 'getRelativeURL()'
+
+ Permission -- Always available
+
+ Returns -- Slash-separated string
+ """
+
+ def getRelativeUrl(content):
+ """ Get the URL for an object, relative to the portal root.
+
+ This is helpful for virtual hosting situations.
+ Same method as 'getRelativeContentURL()'
+
+ Permission -- Always available
+
+ Returns -- Slash-separated string
+ """
+
+ def getPortalPath():
+ """ Get the portal object's URL without the server URL component.
+
+ Permission -- Always available
+
+ Returns -- Slash-separated string
+ """
+
Added: CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_workflow.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/interfaces/portal_workflow.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,218 @@ />
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+""" Workflow tool interface.
+
+"""
+from zope.interface import Interface, Attribute
+from common import EXTRA_EPYDOC_FIELDS, DOCFORMAT
+from IPloneBaseTool import IPloneBaseTool
+from ICMFTool import ICMFTool
+__extra_epydoc_fields__ = EXTRA_EPYDOC_FIELDS
+__docformat__ = DOCFORMAT
+
+_marker = []
+
+
+class IWorkflowTool(Interface):
+ '''This tool accesses and changes the workflow state of content.
+ '''
+ id = Attribute('id', 'Must be set to "portal_workflow"')
+
+ # security.declarePrivate('getCatalogVariablesFor')
+ def getCatalogVariablesFor(ob):
+ '''
+ Invoked by portal_catalog. Allows workflows
+ to add variables to the catalog based on workflow status,
+ making it possible to implement queues.
+ Returns a mapping containing the catalog variables
+ that apply to ob.
+ '''
+
+ # security.declarePublic('getActionsFor')
+ def getActionsFor(ob):
+ '''
+ Return a list of action dictionaries for 'ob', just as though
+ queried via 'ActionsTool.listFilteredActionsFor'.
+ '''
+
+ # security.declarePublic('doActionFor')
+ def doActionFor(ob, action, wf_id=None, *args, **kw):
+ '''
+ Invoked by user interface code.
+ Allows the user to request a workflow action. The workflow object
+ must perform its own security checks.
+ '''
+
+ # security.declarePublic('getInfoFor')
+ def getInfoFor(ob, name, default=_marker, wf_id=None, *args, **kw):
+ '''
+ Invoked by user interface code. Allows the user to request
+ information provided by the workflow. The workflow object
+ must perform its own security checks.
+ '''
+
+ # security.declarePrivate('notifyCreated')
+ def notifyCreated(ob):
+ '''
+ Notifies all applicable workflows after an object has been created
+ and put in its new place.
+ '''
+
+ # security.declarePrivate('notifyBefore')
+ def notifyBefore(ob, action):
+ '''
+ Notifies all applicable workflows of an action before it happens,
+ allowing veto by exception. Unless an exception is thrown, either
+ a notifySuccess() or notifyException() can be expected later on.
+ The action usually corresponds to a method name.
+ '''
+
+ # security.declarePrivate('notifySuccess')
+ def notifySuccess(ob, action, result=None):
+ '''
+ Notifies all applicable workflows that an action has taken place.
+ '''
+
+ # security.declarePrivate('notifyException')
+ def notifyException(ob, action, exc):
+ '''
+ Notifies all applicable workflows that an action failed.
+ '''
+
+ # security.declarePrivate('getHistoryOf')
+ def getHistoryOf(wf_id, ob):
+ '''
+ Invoked by workflow definitions. Returns the history
+ of an object.
+ '''
+
+ # security.declarePrivate('getStatusOf')
+ def getStatusOf(wf_id, ob):
+ '''
+ Invoked by workflow definitions. Returns the last element of a
+ history.
+ '''
+
+ # security.declarePrivate('setStatusOf')
+ def setStatusOf(wf_id, ob, status):
+ '''
+ Invoked by workflow definitions. Appends to the workflow history.
+ '''
+
+
+class WorkflowDefinition(Interface):
+ '''The interface expected of workflow definitions objects.
+ Accesses and changes the workflow state of objects.
+ '''
+
+ # security.declarePrivate('getCatalogVariablesFor')
+ def getCatalogVariablesFor(ob):
+ '''
+ Invoked by the portal_workflow tool.
+ Allows this workflow to make workflow-specific variables
+ available to the catalog, making it possible to implement
+ queues in a simple way.
+ Returns a mapping containing the catalog variables
+ that apply to ob.
+ '''
+
+ #security.declarePrivate('updateRoleMappingsFor')
+ def updateRoleMappingsFor(ob):
+ '''
+ Updates the object permissions according to the current
+ workflow state.
+ '''
+
+ # security.declarePrivate('listObjectActions')
+ def listObjectActions(info):
+ '''
+ Invoked by the portal_workflow tool.
+ Allows this workflow to
+ include actions to be displayed in the actions box.
+ Called only when this workflow is applicable to
+ info.content.
+ Returns the actions to be displayed to the user.
+ '''
+
+ # security.declarePrivate('listGlobalActions')
+ def listGlobalActions(info):
+ '''
+ Invoked by the portal_workflow tool.
+ Allows this workflow to
+ include actions to be displayed in the actions box.
+ Generally called on every request!
+ Returns the actions to be displayed to the user.
+ '''
+
+ # security.declarePrivate('isActionSupported')
+ def isActionSupported(ob, action):
+ '''
+ Invoked by the portal_workflow tool.
+ Returns a true value if the given action name is supported.
+ '''
+
+ # security.declarePrivate('doActionFor')
+ def doActionFor(ob, action, comment=''):
+ '''
+ Invoked by the portal_workflow tool.
+ Allows the user to request a workflow action. This method
+ must perform its own security checks.
+ '''
+
+ # security.declarePrivate('isInfoSupported')
+ def isInfoSupported(ob, name):
+ '''
+ Invoked by the portal_workflow tool.
+ Returns a true value if the given info name is supported.
+ '''
+
+ # security.declarePrivate('getInfoFor')
+ def getInfoFor(ob, name, default):
+ '''
+ Invoked by the portal_workflow tool.
+ Allows the user to request information provided by the
+ workflow. This method must perform its own security checks.
+ '''
+
+ # security.declarePrivate('notifyCreated')
+ def notifyCreated(ob):
+ '''
+ Invoked by the portal_workflow tool.
+ Notifies this workflow after an object has been created
+ and put in its new place.
+ '''
+
+ # security.declarePrivate('notifyBefore')
+ def notifyBefore(ob, action):
+ '''
+ Invoked by the portal_workflow tool.
+ Notifies this workflow of an action before it happens,
+ allowing veto by exception. Unless an exception is thrown, either
+ a notifySuccess() or notifyException() can be expected later on.
+ The action usually corresponds to a method name.
+ '''
+
+ # security.declarePrivate('notifySuccess')
+ def notifySuccess(ob, action, result):
+ '''
+ Invoked by the portal_workflow tool.
+ Notifies this workflow that an action has taken place.
+ '''
+
+ # security.declarePrivate('notifyException')
+ def notifyException(ob, action, exc):
+ '''
+ Invoked by the portal_workflow tool.
+ Notifies this workflow that an action failed.
+ '''
+
Modified: CMFPlone/branches/tiran-z3iface-branch/skins/plone_scripts/breadcrumbs.py
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/skins/plone_scripts/breadcrumbs.py (original)
+++ CMFPlone/branches/tiran-z3iface-branch/skins/plone_scripts/breadcrumbs.py Wed Jun 2 16:09:24 2004
@@ -9,7 +9,7 @@ />
##
from Products.CMFCore.utils import getToolByName
from AccessControl import Unauthorized
-dynamic_type = "Products.CMFCore.interfaces.Dynamic.DynamicType"
+dynamic_type = "Products.CMFPlone.interfaces.IDynamic.DynamicType"
# Some variables
url_tool = getToolByName(context, 'portal_url')
Modified: CMFPlone/branches/tiran-z3iface-branch/skins/plone_templates/folder_contents.pt
==============================================================================
--- CMFPlone/branches/tiran-z3iface-branch/skins/plone_templates/folder_contents.pt (original)
+++ CMFPlone/branches/tiran-z3iface-branch/skins/plone_templates/folder_contents.pt Wed Jun 2 16:09:24 2004
@@ -66,7 +66,7 @@ />
lock_tool portal/portal_lock|nothing;
getInfoFor python:wtool.getInfoFor;
iface_tool portal/portal_interface;
- orderable_iface string:Products.CMFPlone.interfaces.OrderedContainer.IOrderedContainer;
+ orderable_iface string:Products.CMFPlone.interfaces.IOrderedContainer.IOrderedContainer;
canModifyFolderContent python:checkPermission('Modify portal content', here);
isOrderable python:iface_tool.objectImplements(here, orderable_iface);
nosortclass python:test(isOrderable, 'nosort', '')">
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/Makefile
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/Makefile Wed Jun 2 16:09:24 2004
@@ -0,0 +1,77 @@ />
+PYTHON=python2.3
+TESTFLAGS=-p -v
+TESTOPTS=
+SETUPFLAGS=
+
+# XXX What should the default be?
+#XXX all: inplace runners
+all: inplace
+
+# Build in-place
+inplace:
+ $(PYTHON) setup.py $(SETUPFLAGS) build_ext -i
+
+build:
+ $(PYTHON) setup.py $(SETUPFLAGS) build
+
+runners:
+ echo "#!/bin/sh" > bin/runzope;
+ echo "exec $(PYTHON) z3.py" >> bin/runzope;
+ chmod +x bin/runzope
+ echo "#!/bin/sh" > bin/zopectl;
+ echo "$(PYTHON) $(PWD)/src/zdaemon/zdctl.py \
+ -S schema.xml \
+ -C zdaemon.conf -d \$$*" >> bin/zopectl
+ chmod +x bin/zopectl
+
+test_build: build
+ $(PYTHON) test.py $(TESTFLAGS) $(TESTOPTS)
+
+test_inplace: inplace
+ $(PYTHON) test.py $(TESTFLAGS) $(TESTOPTS)
+
+ftest_build: build
+ $(PYTHON) test.py -f $(TESTFLAGS) $(TESTOPTS)
+
+ftest_inplace: inplace
+ $(PYTHON) test.py -f $(TESTFLAGS) $(TESTOPTS)
+
+# XXX What should the default be?
+test: test_inplace
+
+ftest: ftest_inplace
+
+run: inplace
+ $(PYTHON) z3.py
+
+debug: principals.zcml
+ PYTHONPATH=`pwd`/src:$(PYTHONPATH) $(PYTHON) -i -c \
+ "from zope.app import Application;\
+ app = Application('Data.fs', 'site.zcml')()"
+
+clean:
+ find . \( -name '*.o' -o -name '*.so' -o -name '*.py[co]' -o -name '*.dll' \) -exec rm -f {} \;
+ rm -rf build
+
+realclean: clean
+ rm -f TAGS
+ $(PYTHON) setup.py clean -a
+
+zcmldocs:
+ PYTHONPATH=`pwd`/src:$(PYTHONPATH) $(PYTHON) \
+ ./src/zope/configuration/stxdocs.py \
+ -f ./src/zope/app/meta.zcml -o ./doc/zcml/namespaces.zope.org
+
+
+#
+# Naughty, naughty! How many Zope3 developers are going to have
+# that directory structure? The 'ctags' package is capable of generating
+# both emacs-sytle and vi-style tags files from python source; can the
+# emacs-provided 'etags' not read Python?
+#
+TAGS:
+ python ~/trunk/Tools/scripts/eptags.py `find . -name \*.py`
+# etags `find . -name \*.py -print`
+
+tags:
+ ctags -R
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/__init__.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/__init__.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,13 @@ />
+"""Install Zope3 dependencies
+"""
+import sys
+import os
+
+def wire():
+ path = os.path.dirname(__file__)
+ sys.path.append(path)
+ return path
+
+if __name__ == '__main__':
+ wire()
+ from zope.interface import Interface
\ No newline at end of file
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/setup.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/setup.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,282 @@ />
+#############################################################################
+#
+# Copyright (c) 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.
+#
+##############################################################################
+
+"""Zope application server
+
+Zope is a leading open source application server, specializing in content
+management, portals, and custom applications. Zope enables teams to
+collaborate in the creation and management of dynamic web-based business
+applications such as intranets and portals.
+"""
+
+classifiers = """\
+Development Status :: 3 - Alpha
+Environment :: Web Environment
+License :: OSI Approved :: Zope Public License
+Operating System :: Microsoft :: Windows
+Operating System :: Unix
+Programming Language :: Python
+Topic :: Internet :: WWW/HTTP
+Topic :: Internet :: WWW/HTTP :: Dynamic Content
+Topic :: Software Development :: Libraries :: Python Modules
+"""
+
+import os
+import sys
+
+# Provide a bunch of custom components that make it possible to build and
+# install non-.py files into the package destinations.
+from distutils import dir_util
+from distutils.command.build import build as buildcmd
+from distutils.command.build_ext import build_ext
+from distutils.command.install_lib import install_lib as installcmd
+from distutils.core import setup
+from distutils.dist import Distribution
+from distutils.extension import Extension
+
+if sys.version_info < (2, 3):
+ _setup = setup
+ def setup(**kwargs):
+ if kwargs.has_key("classifiers"):
+ del kwargs["classifiers"]
+ _setup(**kwargs)
+
+
+# A hack to determine if Extension objects support the `depends' keyword arg,
+# which only exists in Python 2.3's distutils.
+if not "depends" in Extension.__init__.func_code.co_varnames:
+ # If it doesn't, create a local replacement that removes depends from the
+ # kwargs before calling the regular constructor.
+ _Extension = Extension
+ class Extension(_Extension):
+ def __init__(self, name, sources, **kwargs):
+ if "depends" in kwargs:
+ del kwargs["depends"]
+ _Extension.__init__(self, name, sources, **kwargs)
+
+
+# We have to snoop for file types that distutils doesn't copy correctly when
+# doing a non-build-in-place.
+EXTS = ['.conf', '.css', '.dtd', '.gif', '.jpg', '.html',
+ '.js', '.mo', '.png', '.pt', '.stx', '.ref',
+ '.txt', '.xml', '.zcml', '.mar', '.in', '.sample',
+ ]
+
+
+# This class serves multiple purposes. It walks the file system looking for
+# auxiliary files that distutils doesn't install properly, and it actually
+# copies those files (when hooked into by distutils). It also walks the file
+# system looking for candidate packages for distutils to install as normal.
+# The key here is that the package must have an __init__.py file.
+class Finder:
+ def __init__(self, exts, fix):
+ self._files = []
+ self._pkgs = {}
+ self._exts = exts
+ # We're finding packages in lib/python in the source dir, but we're
+ # copying them directly under build/lib.<plat>. So we need to lop off
+ # the fix when calculating the package names from the file names.
+ self._plen = len(fix)
+
+ def visit(self, ignore, dir, files):
+ for file in files:
+ # First see if this is one of the packages we want to add, or if
+ # we're really skipping this package.
+ if '__init__.py' in files:
+ aspkg = dir[self._plen:].replace(os.sep, '.')
+ self._pkgs[aspkg] = True
+ # Add any extra files we're interested in
+ base, ext = os.path.splitext(file)
+ if ext in self._exts:
+ self._files.append(os.path.join(dir, file))
+
+ def copy_files(self, cmd, outputbase):
+ for file in self._files:
+ dest = os.path.join(outputbase, file[self._plen:])
+ # Make sure the destination directory exists
+ dir = os.path.dirname(dest)
+ if not os.path.exists(dir):
+ dir_util.mkpath(dir)
+ cmd.copy_file(file, dest)
+
+ def get_packages(self):
+ return self._pkgs.keys()
+
+def remove_stale_bytecode(arg, dirname, names):
+ names = map(os.path.normcase, names)
+ for name in names:
+ if name.endswith(".pyc") or name.endswith(".pyo"):
+ srcname = name[:-1]
+ if srcname not in names:
+ fullname = os.path.join(dirname, name)
+ print "Removing stale bytecode file", fullname
+ os.unlink(fullname)
+
+# Create the finder instance, which will be used in lots of places. `finder'
+# is the global we're most interested in.
+# XXX basedir = 'src/'
+basedir = './'
+finder = Finder(EXTS, basedir)
+os.path.walk(basedir, finder.visit, None)
+packages = finder.get_packages()
+
+# Distutils hook classes
+class MyBuilder(buildcmd):
+ def run(self):
+ os.path.walk(os.curdir, remove_stale_bytecode, None)
+ buildcmd.run(self)
+ finder.copy_files(self, self.build_lib)
+
+class MyExtBuilder(build_ext):
+ # Override the default build_ext to remove stale bytecodes.
+ # Technically, removing bytecode has nothing to do with
+ # building extensions, but Zope's the build_ext -i variant
+ # is used to build Zope in place.
+ def run(self):
+ os.path.walk(os.curdir, remove_stale_bytecode, None)
+ build_ext.run(self)
+
+class MyLibInstaller(installcmd):
+ def run(self):
+ installcmd.run(self)
+ finder.copy_files(self, self.install_dir)
+
+class MyDistribution(Distribution):
+ # To control the selection of MyLibInstaller and MyPyBuilder, we
+ # have to set it into the cmdclass instance variable, set in
+ # Distribution.__init__().
+ def __init__(self, *attrs):
+ Distribution.__init__(self, *attrs)
+ self.cmdclass['build'] = MyBuilder
+ self.cmdclass['build_ext'] = MyExtBuilder
+ self.cmdclass['install_lib'] = MyLibInstaller
+
+
+# Set up dependencies for the BTrees package
+base_btrees_depends = [
+ "src/persistent/cPersistence.h",
+ "src/BTrees/BTreeItemsTemplate.c",
+ "src/BTrees/BTreeModuleTemplate.c",
+ "src/BTrees/BTreeTemplate.c",
+ "src/BTrees/BucketTemplate.c",
+ "src/BTrees/MergeTemplate.c",
+ "src/BTrees/SetOpTemplate.c",
+ "src/BTrees/SetTemplate.c",
+ "src/BTrees/TreeSetTemplate.c",
+ "src/BTrees/sorters.c",
+ ]
+
+_flavors = {"O": "object", "I": "int"}
+
+KEY_H = "src/BTrees/%skeymacros.h"
+VALUE_H = "src/BTrees/%svaluemacros.h"
+
+
+def BTreeExtension(flavor):
+ key = flavor[0]
+ value = flavor[1]
+ name = "BTrees._%sBTree" % flavor
+ sources = ["src/BTrees/_%sBTree.c" % flavor]
+ kwargs = {"include_dirs": ['src/persistent']}
+ if flavor != "fs":
+ kwargs["depends"] = (base_btrees_depends + [KEY_H % _flavors[key],
+ VALUE_H % _flavors[value]])
+ return Extension(name, sources, **kwargs)
+
+# All Zope3 extension modules must be listed here.
+XXX_ext_modules = [
+ BTreeExtension("OO"),
+ BTreeExtension("IO"),
+ BTreeExtension("OI"),
+ BTreeExtension("II"),
+ BTreeExtension("fs"),
+ Extension(name = 'persistent.cPersistence',
+ include_dirs = ['src/persistent'],
+ sources= ['src/persistent/cPersistence.c',
+ 'src/persistent/ring.c'],
+ depends = ['src/persistent/cPersistence.h',
+ 'src/persistent/ring.h',
+ 'src/persistent/ring.c']
+ ),
+ Extension(name = 'persistent.cPickleCache',
+ include_dirs = ['src/persistent'],
+ sources= ['src/persistent/cPickleCache.c',
+ 'src/persistent/ring.c'],
+ depends = ['src/persistent/cPersistence.h',
+ 'src/persistent/ring.h',
+ 'src/persistent/ring.c']
+ ),
+ Extension(name = 'persistent.TimeStamp',
+ sources= ['src/persistent/TimeStamp.c']
+ ),
+ Extension(name = 'ZODB.winlock',
+ sources = ['src/ZODB/winlock.c']
+ ),
+
+ Extension("zope.proxy._zope_proxy_proxy",
+ ["src/zope/proxy/_zope_proxy_proxy.c"],
+ include_dirs = ["src/zope/proxy"],
+ depends = ["src/zope/proxy/proxy.h"]),
+
+ Extension("zope.security._proxy", ["src/zope/security/_proxy.c"],
+ include_dirs = ["src/zope/proxy"],
+ depends = ["src/zope/proxy/proxy.h"]),
+
+ Extension("zope.interface._zope_interface_coptimizations",
+ ["src/zope/interface/_zope_interface_coptimizations.c"]),
+
+ Extension("zope.hookable._zope_hookable",
+ ["src/zope/hookable/_zope_hookable.c"]),
+
+ Extension("zope.app.container._zope_app_container_contained",
+ ["src/zope/app/container/_zope_app_container_contained.c"],
+ include_dirs = ["src/persistent",
+ "src/zope/proxy",
+ "src/zope/app/container"],
+ depends = [
+ "src/persistent/cPersistence.h",
+ "src/zope/proxy/_zope_proxy_proxy.c",
+ ]),
+
+ ]
+
+ext_modules = [
+ Extension("zope.interface._zope_interface_coptimizations",
+ ["zope/interface/_zope_interface_coptimizations.c"]),
+
+ ]
+
+# We're using the module docstring as the distutils descriptions.
+doclines = __doc__.split("\n")
+
+setup(name="ZopeX3",
+ version="3.0m5",
+ maintainer="Zope Corporation",
+ maintainer_email="zope3-dev@zope.org", />
+ url = "" target="_blank">http://dev.zope.org/Zope3/",
+ ext_modules = ext_modules,
+ # This doesn't work right at all
+ #headers = ["src/persistent/cPersistence.h",
+ # "src/zope/proxy/proxy.h",
+ # "src/zope/context/wrapper.h"],
+ scripts = ["z3.py", "utilities/runurl.py"],
+ license = "" target="_blank">http://www.zope.org/Resources/ZPL",
+ platforms = ["any"],
+ description = doclines[0],
+ classifiers = filter(None, classifiers.split("\n")),
+ long_description = "\n".join(doclines[2:]),
+ packages = packages,
+ #package_dir = {'': 'src'},
+ distclass = MyDistribution,
+ )
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/__init__.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/__init__.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,35 @@ />
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+#
+# This file is necessary to make this directory a package.
+
+# XXX Evil monkey patch of weakref to avoid a Python 2.3.3 weakref bug that
+# causes sporadic segfaults
+
+def monkey_patch():
+ import weakref
+ import gc
+ ref = weakref.ref
+ disable = gc.disable
+ enable = gc.enable
+ def monkey_ref(*args, **kw):
+ disable()
+ r = ref(*args, **kw)
+ enable()
+ return r
+
+ weakref.ref = monkey_ref
+
+monkey_patch()
+del monkey_patch
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/DEPENDENCIES.cfg
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/DEPENDENCIES.cfg Wed Jun 2 16:09:24 2004
@@ -0,0 +1,2 @@ />
+zope.interface
+zope.testing
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/__init__.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/__init__.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,35 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""General exceptions that wish they were standard exceptions
+
+These exceptions are so general purpose that they don't belong in Zope
+application-specific packages.
+
+$Id: __init__.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+# This module should be independent of I18n, so let's not require it.
+try:
+ from zope.i18n import MessageIDFactory
+except ImportError:
+ ZopeMessageIDFactory = unicode
+else:
+ # Import _ to use to create message ids in the zope domain
+ ZopeMessageIDFactory = MessageIDFactory('zope')
+
+from zope.exceptions._zope_error import ZopeError, IZopeError
+from zope.exceptions.unauthorized import Unauthorized, IUnauthorized
+from zope.exceptions._notfounderror import NotFoundError, INotFoundError
+from zope.exceptions._forbidden import Forbidden, ForbiddenAttribute
+from zope.exceptions._forbidden import IForbidden, IForbiddenAttribute
+from zope.exceptions._duplicate import DuplicationError, IDuplicationError
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/_duplicate.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/_duplicate.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,25 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+$Id: _duplicate.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+from zope.exceptions import ZopeError, IZopeError
+from zope.interface import implements
+
+class IDuplicationError(IZopeError):
+ pass
+
+class DuplicationError(ZopeError):
+ """A duplicate registration was attempted"""
+ implements(IDuplicationError)
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/_forbidden.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/_forbidden.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,37 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+
+$Id: _forbidden.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+from zope.exceptions import ZopeError, IZopeError
+from zope.interface import implements
+from zope.interface.common.interfaces import IAttributeError
+
+class IForbidden(IZopeError):
+ pass
+
+class Forbidden(ZopeError):
+ """A resource cannot be accessed under any circumstances
+ """
+ implements(IForbidden)
+
+class IForbiddenAttribute(IForbidden, IAttributeError):
+ pass
+
+class ForbiddenAttribute(Forbidden, AttributeError):
+ """An attribute is unavailable because it is forbidden (private)
+ """
+ implements(IForbiddenAttribute)
+
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/_notfounderror.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/_notfounderror.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,28 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+$Id: _notfounderror.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+from zope.exceptions import ZopeError, IZopeError
+from zope.interface.common.interfaces import IKeyError
+from zope.interface import implements
+
+class INotFoundError(IZopeError, IKeyError):
+ pass
+
+class NotFoundError(ZopeError, KeyError):
+ """A resource could not be found.
+ """
+ implements(INotFoundError)
+
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/_zope_error.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/_zope_error.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,26 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Base class for Zope application errors.
+
+$Id: _zope_error.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+from zope.interface.common.interfaces import IException
+from zope.interface import implements
+
+class IZopeError(IException):
+ pass
+
+class ZopeError(Exception):
+ """Generic base class for Zope errors."""
+ implements(IZopeError)
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/exceptionformatter.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/exceptionformatter.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,245 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""An exception formatter that shows traceback supplements and traceback info,
+optionally in HTML.
+
+$Id: exceptionformatter.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+import sys
+import cgi
+import linecache
+
+DEBUG_EXCEPTION_FORMATTER = 1
+
+class TextExceptionFormatter:
+
+ line_sep = '\n'
+ show_revisions = 0
+
+ def __init__(self, limit=None):
+ self.limit = limit
+
+ def escape(self, s):
+ return s
+
+ def getPrefix(self):
+ return 'Traceback (innermost last):'
+
+ def getLimit(self):
+ limit = self.limit
+ if limit is None:
+ limit = getattr(sys, 'tracebacklimit', None)
+ return limit
+
+ def getRevision(self, globals):
+ if not self.show_revisions:
+ return None
+ revision = globals.get('__revision__', None)
+ if revision is None:
+ # Incorrect but commonly used spelling
+ revision = globals.get('__version__', None)
+
+ if revision is not None:
+ try:
+ revision = str(revision).strip()
+ # XXX bare except without a comment explaining it.
+ except:
+ revision = '???'
+ return revision
+
+ def formatSupplementLine(self, line):
+ return ' - %s' % line
+
+ def formatSourceURL(self, url):
+ return [self.formatSupplementLine(url)]
+
+ def formatSupplement(self, supplement, tb):
+ result = []
+ fmtLine = self.formatSupplementLine
+
+ url = getattr(supplement, 'source_url', None)
+ if url is not None:
+ result.extend(self.formatSourceURL(url))
+
+ line = getattr(supplement, 'line', 0)
+ if line == -1:
+ line = tb.tb_lineno
+ col = getattr(supplement, 'column', -1)
+ if line:
+ if col is not None and col >= 0:
+ result.append(fmtLine('Line %s, Column %s' % (
+ line, col)))
+ else:
+ result.append(fmtLine('Line %s' % line))
+ elif col is not None and col >= 0:
+ result.append(fmtLine('Column %s' % col))
+
+ expr = getattr(supplement, 'exssion', None)
+ if expr:
+ result.append(fmtLine('Exssion: %s' % expr))
+
+ warnings = getattr(supplement, 'warnings', None)
+ if warnings:
+ for warning in warnings:
+ result.append(fmtLine('Warning: %s' % warning))
+
+ getInfo = getattr(supplement, 'getInfo', None)
+ if getInfo is not None:
+ try:
+ extra = getInfo()
+ if extra:
+ extra = self.escape(extra)
+ if self.line_sep != "\n":
+ extra = extra.replace(" ", " ")
+ extra = extra.replace("\n", self.line_sep)
+ result.append(extra)
+ except:
+ if DEBUG_EXCEPTION_FORMATTER:
+ import traceback
+ traceback.print_exc()
+ # else just swallow the exception.
+ return result
+
+ def formatTracebackInfo(self, tbi):
+ return self.formatSupplementLine('__traceback_info__: %s' % tbi)
+
+ def formatLine(self, tb):
+ f = tb.tb_frame
+ lineno = tb.tb_lineno
+ co = f.f_code
+ filename = co.co_filename
+ name = co.co_name
+ locals = f.f_locals
+ globals = f.f_globals
+ modname = globals.get('__name__', filename)
+
+ s = ' Module %s, line %d' % (modname, lineno)
+
+ revision = self.getRevision(globals)
+ if revision:
+ s = s + ', rev. %s' % revision
+
+ s = s + ', in %s' % name
+
+ result = []
+ result.append(self.escape(s))
+
+ # Append the source line, if available
+ line = linecache.getline(filename, lineno)
+ if line:
+ result.append(" " + self.escape(line.strip()))
+
+ # Output a traceback supplement, if any.
+ if '__traceback_supplement__' in locals:
+ # Use the supplement defined in the function.
+ tbs = locals['__traceback_supplement__']
+ elif '__traceback_supplement__' in globals:
+ # Use the supplement defined in the module.
+ # This is used by Scripts (Python).
+ tbs = globals['__traceback_supplement__']
+ else:
+ tbs = None
+ if tbs is not None:
+ factory = tbs[0]
+ args = tbs[1:]
+ try:
+ supp = factory(*args)
+ result.extend(self.formatSupplement(supp, tb))
+ except:
+ if DEBUG_EXCEPTION_FORMATTER:
+ import traceback
+ traceback.print_exc()
+ # else just swallow the exception.
+
+ try:
+ tbi = locals.get('__traceback_info__', None)
+ if tbi is not None:
+ result.append(self.formatTracebackInfo(tbi))
+ except:
+ if DEBUG_EXCEPTION_FORMATTER:
+ import traceback
+ traceback.print_exc()
+ # else just swallow the exception.
+
+ return self.line_sep.join(result)
+
+ def formatExceptionOnly(self, etype, value):
+ import traceback
+ return self.line_sep.join(
+ traceback.format_exception_only(etype, value))
+
+ def formatLastLine(self, exc_line):
+ return self.escape(exc_line)
+
+ def formatException(self, etype, value, tb):
+ # The next line provides a way to detect recursion.
+ __exception_formatter__ = 1
+ result = [self.getPrefix() + '\n']
+ limit = self.getLimit()
+ n = 0
+ while tb is not None and (limit is None or n < limit):
+ if tb.tb_frame.f_locals.get('__exception_formatter__'):
+ # Stop recursion.
+ result.append('(Recursive formatException() stopped)\n')
+ break
+ line = self.formatLine(tb)
+ result.append(line + '\n')
+ tb = tb.tb_next
+ n = n + 1
+ exc_line = self.formatExceptionOnly(etype, value)
+ result.append(self.formatLastLine(exc_line))
+ return result
+
+
+class HTMLExceptionFormatter(TextExceptionFormatter):
+
+ line_sep = '<br />\r\n'
+
+ def escape(self, s):
+ return cgi.escape(s)
+
+ def getPrefix(self):
+ return '<p>Traceback (innermost last):\r\n<ul>'
+
+ def formatSupplementLine(self, line):
+ return '<b>%s</b>' % self.escape(str(line))
+
+ def formatTracebackInfo(self, tbi):
+ s = self.escape(str(tbi))
+ s = s.replace('\n', self.line_sep)
+ return '__traceback_info__: %s' % s
+
+ def formatLine(self, tb):
+ line = TextExceptionFormatter.formatLine(self, tb)
+ return '<li>%s</li>' % line
+
+ def formatLastLine(self, exc_line):
+ return '</ul>%s</p>' % self.escape(exc_line)
+
+
+limit = 200
+
+if hasattr(sys, 'tracebacklimit'):
+ limit = min(limit, sys.tracebacklimit)
+
+text_formatter = TextExceptionFormatter(limit)
+html_formatter = HTMLExceptionFormatter(limit)
+
+
+def format_exception(t, v, tb, limit=None, as_html=0):
+ if as_html:
+ fmt = html_formatter
+ else:
+ fmt = text_formatter
+ return fmt.formatException(t, v, tb)
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/interfaces.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/interfaces.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,82 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""ITracebackSupplement interface definition.
+
+$Id: interfaces.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+
+from zope.interface import Interface, Attribute
+
+class ITracebackSupplement(Interface):
+ """Provides valuable information to supplement an exception traceback.
+
+ The interface is geared toward providing meaningful feedback when
+ exceptions occur in user code written in mini-languages like
+ Zope page templates and restricted Python scripts.
+ """
+
+ source_url = Attribute(
+ 'source_url',
+ """Optional. Set to URL of the script where the exception occurred.
+
+ Normally this generates a URL in the traceback that the user
+ can visit to manage the object. Set to None if unknown or
+ not available.
+ """
+ )
+
+ line = Attribute(
+ 'line',
+ """Optional. Set to the line number (>=1) where the exception
+ occurred.
+
+ Set to 0 or None if the line number is unknown.
+ """
+ )
+
+ column = Attribute(
+ 'column',
+ """Optional. Set to the column offset (>=0) where the exception
+ occurred.
+
+ Set to None if the column number is unknown.
+ """
+ )
+
+ exssion = Attribute(
+ 'exssion',
+ """Optional. Set to the exssion that was being evaluated.
+
+ Set to None if not available or not applicable.
+ """
+ )
+
+ warnings = Attribute(
+ 'warnings',
+ """Optional. Set to a sequence of warning messages.
+
+ Set to None if not available, not applicable, or if the exception
+ itself provides enough information.
+ """
+ )
+
+
+ def getInfo(as_html=0):
+ """Optional. Returns a string containing any other useful info.
+
+ If as_html is set, the implementation must HTML-quote the result
+ (normally using cgi.escape()). Returns None to provide no
+ extra info.
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/tests/__init__.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/tests/__init__.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,2 @@ />
+#
+# This file is necessary to make this directory a package.
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/tests/test_exceptionformatter.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/tests/test_exceptionformatter.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,145 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+ExceptionFormatter tests.
+
+Revision information:
+$Id: test_exceptionformatter.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+from unittest import TestCase, main, makeSuite
+from zope.testing.cleanup import CleanUp # Base class w registry cleanup
+
+import sys
+from zope.exceptions.exceptionformatter import format_exception
+
+
+def tb(as_html=0):
+ t, v, b = sys.exc_info()
+ try:
+ return ''.join(format_exception(t, v, b, as_html=as_html))
+ finally:
+ del b
+
+
+class ExceptionForTesting (Exception):
+ pass
+
+
+
+class TestingTracebackSupplement:
+
+ source_url = '/somepath'
+ line = 634
+ column = 57
+ warnings = ['Repent, for the end is nigh']
+
+ def __init__(self, exssion):
+ self.exssion = exssion
+
+
+
+class Test(CleanUp, TestCase):
+
+ def testBasicNamesText(self, as_html=0):
+ try:
+ raise ExceptionForTesting
+ except ExceptionForTesting:
+ s = tb(as_html)
+ # The traceback should include the name of this function.
+ self.assert_(s.find('testBasicNamesText') >= 0)
+ # The traceback should include the name of the exception.
+ self.assert_(s.find('ExceptionForTesting') >= 0)
+ else:
+ self.fail('no exception occurred')
+
+ def testBasicNamesHTML(self):
+ self.testBasicNamesText(1)
+
+ def testSupplement(self, as_html=0):
+ try:
+ __traceback_supplement__ = (TestingTracebackSupplement,
+ "You're one in a million")
+ raise ExceptionForTesting
+ except ExceptionForTesting:
+ s = tb(as_html)
+ # The source URL
+ self.assert_(s.find('/somepath') >= 0, s)
+ # The line number
+ self.assert_(s.find('634') >= 0, s)
+ # The column number
+ self.assert_(s.find('57') >= 0, s)
+ # The exssion
+ self.assert_(s.find("You're one in a million") >= 0, s)
+ # The warning
+ self.assert_(s.find("Repent, for the end is nigh") >= 0, s)
+ else:
+ self.fail('no exception occurred')
+
+ def testSupplementHTML(self):
+ self.testSupplement(1)
+
+ def testTracebackInfo(self, as_html=0):
+ try:
+ __traceback_info__ = "Adam & Eve"
+ raise ExceptionForTesting
+ except ExceptionForTesting:
+ s = tb(as_html)
+ if as_html:
+ # Be sure quoting is happening.
+ self.assert_(s.find('Adam & Eve') >= 0, s)
+ else:
+ self.assert_(s.find('Adam & Eve') >= 0, s)
+ else:
+ self.fail('no exception occurred')
+
+ def testTracebackInfoHTML(self):
+ self.testTracebackInfo(1)
+
+ def testMultipleLevels(self):
+ # Makes sure many levels are shown in a traceback.
+ def f(n):
+ """Produces a (n + 1)-level traceback."""
+ __traceback_info__ = 'level%d' % n
+ if n > 0:
+ f(n - 1)
+ else:
+ raise ExceptionForTesting
+
+ try:
+ f(10)
+ except ExceptionForTesting:
+ s = tb()
+ for n in range(11):
+ self.assert_(s.find('level%d' % n) >= 0, s)
+ else:
+ self.fail('no exception occurred')
+
+ def testQuoteLastLine(self):
+ class C: pass
+ try: raise TypeError, C()
+ except:
+ s = tb(1)
+ else:
+ self.fail('no exception occurred')
+ self.assert_(s.find('<') >= 0, s)
+ self.assert_(s.find('>') >= 0, s)
+
+
+
+def test_suite():
+ return makeSuite(Test)
+
+if __name__=='__main__':
+ main(defaultTest='test_suite')
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/unauthorized.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/exceptions/unauthorized.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,85 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Unauthorized Exception definition
+
+$Id: unauthorized.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+from types import StringType
+from zope.exceptions import ZopeError
+from zope.exceptions import IZopeError
+from zope.exceptions import ZopeMessageIDFactory as _
+from zope.interface import implements
+
+
+class IUnauthorized(IZopeError):
+ pass
+
+class Unauthorized(ZopeError):
+ """Some user wasn't allowed to access a resource"""
+
+ implements(IUnauthorized)
+
+ def __init__(self, message=None, value=None, needed=None, name=None, **kw):
+ """Possible signatures:
+
+ Unauthorized()
+ Unauthorized(message) # Note that message includes a space
+ Unauthorized(name)
+ Unauthorized(name, value)
+ Unauthorized(name, value, needed)
+ Unauthorized(message, value, needed, name)
+
+ Where needed is a mapping objects with items resnting requirements
+ (e.g. {'permission': 'add spam'}). Any extra keyword arguments
+ provides are added to needed.
+ """
+ if name is None and (
+ not isinstance(message, StringType) or len(message.split()) <= 1):
+ # First arg is a name, not a message
+ name = message
+ message = None
+
+ self.name = name
+ self.message = message
+ self.value = value
+
+ if kw:
+ if needed:
+ needed.update(kw)
+ else:
+ needed = kw
+
+ self.needed = needed
+
+ def __str__(self):
+ if self.message is not None:
+ return _(self.message)
+ if self.name is not None:
+ msg = _("You are not allowed to access ${name} in this context")
+ msg.mapping = {'name': self.name}
+ elif self.value is not None:
+ msg = _("You are not allowed to access ${name} in this context")
+ msg.mapping = {'name': self.getValueName()}
+ return _("You are not authorized")
+
+
+ def getValueName(self):
+ v = self.value
+ vname = getattr(v, '__name__', None)
+ if vname:
+ return vname
+ c = getattr(v, '__class__', type(v))
+ c = getattr(c, '__name__', 'object')
+ msg = _("a particular ${object}")
+ msg.mapping = {'object': c}
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/DEPENDENCIES.cfg
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/DEPENDENCIES.cfg Wed Jun 2 16:09:24 2004
@@ -0,0 +1 @@ />
+zope.testing
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/PUBLICATION.cfg
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/PUBLICATION.cfg Wed Jun 2 16:09:24 2004
@@ -0,0 +1,8 @@ />
+Metadata-Version: 1.0
+Name: zope.interface
+Summary: Zope 3 Interface Infrastructure
+Author: Zope Corporation and Contributors
+Author-email: zope3-dev@zope.org />
+License: ZPL 2
+Description:
+ The implementation of interface definitions for Zope 3.
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/README.txt
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/README.txt Wed Jun 2 16:09:24 2004
@@ -0,0 +1,583 @@ />
+==========
+Interfaces
+==========
+
+.. contents::
+
+Interfaces are objects that specify (document) the external behavior
+of objects that "provide" them. An interface specifies behavior
+through:
+
+- Informal documentation in a doc string
+
+- Attribute definitions
+
+- Invariants, which are conditions that must hold for objects that
+ provide the interface
+
+Attribute definitions specify specific attributes. They define the
+attribute name and provide documentation and constraints of attribute
+values. Attribute definitions can take a number of forms, as we'll
+see below.
+
+Defining interfaces
+===================
+
+Interfaces are defined using Python class statements:
+
+ >>> import zope.interface
+ >>> class IFoo(zope.interface.Interface):
+ ... """Foo blah blah"""
+ ...
+ ... x = zope.interface.Attribute("""X blah blah""")
+ ...
+ ... def bar(q, r=None):
+ ... """bar blah blah"""
+
+In the example above, we've created an interface, `IFoo`. We
+subclassed `zope.interface.Interface`, which is an ancestor interface for
+all interfaces, much as `object` is an ancestor of all new-style
+classes [#create]_. The interface is not a class, It's an Interface,
+an instance of `InterfaceClass`:
+
+ >>> type(IFoo)
+ <class 'zope.interface.interface.InterfaceClass'>
+
+We can ask for the interfaces documentation:
+
+ >>> IFoo.__doc__
+ 'Foo blah blah'
+
+and it's name:
+
+ >>> IFoo.__name__
+ 'IFoo'
+
+and even it's module:
+
+ >>> IFoo.__module__
+ '__main__'
+
+The interface defined two attributes:
+
+`x`
+ This is the simplest form of attribute definition. It has a name
+ and a doc string. It doesn't formally specify anything else.
+
+`bar`
+ This is a method. A method is defined via a function definition. A
+ method is simply an attribute constrained to be a callable with a
+ particular signature, as provided by the function definition.
+
+ Note that `bar` doesn't take a `self` argument. Interfaces document
+ how an object is *used*. When calling instance methods, you don't
+ pass a `self` argument, so a `self` argument isn't included in the
+ interface signature. The `self` argument in instance methods is
+ really an implementation detail of Python instances. Other objects,
+ besides instances can provide interfaces and their methods might not
+ be instance methods. For example, modules can provide interfaces and
+ their methods are usually just functions. Even instances can have
+ methods that are not instance methods.
+
+You can access the attributes defined by an interface using mapping
+syntax:
+
+ >>> x = IFoo['x']
+ >>> type(x)
+ <class 'zope.interface.interface.Attribute'>
+ >>> x.__name__
+ 'x'
+ >>> x.__doc__
+ 'X blah blah'
+
+You can use `in` to determine if an interface defines a name:
+
+ >>> 'x' in IFoo
+ True
+
+You can iterate over interfaces to get the names they define:
+
+ >>> names = list(IFoo)
+ >>> names.sort()
+ >>> names
+ ['bar', 'x']
+
+Remember that interfaces aren't classes. You can't access attribute
+definitions as attributes of interfaces:
+
+ >>> IFoo.x
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in ?
+ AttributeError: 'InterfaceClass' object has no attribute 'x'
+
+Methods provide access to the method signature:
+
+ >>> bar = IFoo['bar']
+ >>> bar.getSignatureString()
+ '(q, r=None)'
+
+XXX
+ Methods really should have a better API. This is something that
+ needs to be improved.
+
+Declaring interfaces
+====================
+
+Having defined interfaces, we can *declare* that objects provide
+them. Before we describe the details, lets define some some terms:
+
+*provide*
+ We say that objects *provide* interfaces. If an object provides an
+ interface, then the interface specifies the behavior of the
+ object. In other words, interfaces specify the behavior of the
+ objects that provide them.
+
+*implement*
+ We normally say that classes *implement* interfaces. If a class
+ implements an interface, then the instances of the class provide
+ the interface. Objects provide interfaces that their classes
+ implement [#factory]_. (Objects can provide interfaces directly,
+ in addition to what their classes implement.)
+
+ It is important to note that classes don't usually provide the
+ interfaces that the implement.
+
+Now that we've defined these terms, we can talk about the API for
+declaring interfaces.
+
+The most common way to declare interfaces is using the implements
+function in a class statement:
+
+ >>> class Foo:
+ ... zope.interface.implements(IFoo)
+ ...
+ ... def __init__(self, x=None):
+ ... self.x = x
+ ...
+ ... def bar(self, q, r=None):
+ ... return q, r, self.x
+ ...
+ ... def __repr__(self):
+ ... return "Foo(%s)" % self.x
+
+
+In this example, we declared that `Foo` implements `IFoo`. This means
+that instances of `Foo` provide `IFoo`. Having made this declaration,
+there are several ways we can introspect the declarations. First, we
+can ask an interface whether it is implemented by a class:
+
+ >>> IFoo.implementedBy(Foo)
+ True
+
+And we can ask whether an interface is provided by an object:
+
+ >>> foo = Foo()
+ >>> IFoo.providedBy(foo)
+ True
+
+Of course, `Foo` doesn't provide `IFoo`, it implements it.
+
+ >>> IFoo.providedBy(Foo)
+ False
+
+We can also ask what interfaces are implemented by an object:
+
+ >>> list(zope.interface.implementedBy(Foo))
+ [<InterfaceClass __main__.IFoo>]
+
+It's an error to ask for interfaces implemented by a non-class:
+
+ >>> IFoo.implementedBy(foo)
+ Traceback (most recent call last):
+ ...
+ TypeError: ('ImplementedBy called for non-type', Foo(None))
+
+ >>> list(zope.interface.implementedBy(foo))
+ Traceback (most recent call last):
+ ...
+ TypeError: ('ImplementedBy called for non-type', Foo(None))
+
+Similarly, we can ask what interfaces are provided by an object:
+
+ >>> list(zope.interface.providedBy(foo))
+ [<InterfaceClass __main__.IFoo>]
+ >>> list(zope.interface.providedBy(Foo))
+ []
+
+We can declare interfaces directly provided by objects. Suppose that
+we want to document what the `__init__` method of the `Foo` class
+does. It's not *really* part of `IFoo`. You wouldn't normally call
+the `__init__` method on Foo instances. Rather, the `__init__` method
+is part of the `Foo`'s `__call__` method:
+
+ >>> class IFooFactory(zope.interface.Interface):
+ ... """Create foos"""
+ ...
+ ... def __call__(x=None):
+ ... """Create a foo
+ ...
+ ... The argument provides the initial value for x ...
+ ... """
+
+It's the class that provides this interface, so we declare the
+interface on the class:
+
+ >>> zope.interface.directlyProvides(Foo, IFooFactory)
+
+And then, we'll see that Foo provides some interfaces:
+
+ >>> list(zope.interface.providedBy(Foo))
+ [<InterfaceClass __main__.IFooFactory>]
+ >>> IFooFactory.providedBy(Foo)
+ True
+
+Declaring class interfaces is common enough that there's a special
+declaration function for it, `classProvides`, that allows the
+declaration from within a class statement:
+
+ >>> class Foo2:
+ ... zope.interface.implements(IFoo)
+ ... zope.interface.classProvides(IFooFactory)
+ ...
+ ... def __init__(self, x=None):
+ ... self.x = x
+ ...
+ ... def bar(self, q, r=None):
+ ... return q, r, self.x
+ ...
+ ... def __repr__(self):
+ ... return "Foo(%s)" % self.x
+
+ >>> list(zope.interface.providedBy(Foo2))
+ [<InterfaceClass __main__.IFooFactory>]
+ >>> IFooFactory.providedBy(Foo2)
+ True
+
+There's a similar function, `moduleProvides`, that supports interface
+declarations from within module definitions. For example, see the use
+of `moduleProvides` call in `zope.interface.__init__`, which declares that
+the package `zope.interface` provides `IInterfaceDeclaration`.
+
+Sometimes, we want to declare interfaces on instances, even though
+those instances get interfaces from their classes. Suppose we create
+a new interface, `ISpecial`:
+
+ >>> class ISpecial(zope.interface.Interface):
+ ... reason = zope.interface.Attribute("Reason why we're special")
+ ... def brag():
+ ... "Brag about being special"
+
+We can make a an existing foo instance special by providing `reason`
+and `brag` attributes:
+
+ >>> foo.reason = 'I just am'
+ >>> def brag():
+ ... return "I'm special!"
+ >>> foo.brag = brag
+ >>> foo.reason
+ 'I just am'
+ >>> foo.brag()
+ "I'm special!"
+
+and by declaring the interface:
+
+ >>> zope.interface.directlyProvides(foo, ISpecial)
+
+then the new interface is included in the provided interfaces:
+
+ >>> ISpecial.providedBy(foo)
+ True
+ >>> list(zope.interface.providedBy(foo))
+ [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
+
+We can find out what interfaces are directly provided by an object:
+
+ >>> list(zope.interface.directlyProvidedBy(foo))
+ [<InterfaceClass __main__.ISpecial>]
+
+ >>> newfoo = Foo()
+ >>> list(zope.interface.directlyProvidedBy(newfoo))
+ []
+
+Inherited declarations
+----------------------
+
+Normally, declarations are inherited:
+
+ >>> class SpecialFoo(Foo):
+ ... zope.interface.implements(ISpecial)
+ ... reason = 'I just am'
+ ... def brag(self):
+ ... return "I'm special because %s" % self.reason
+
+ >>> list(zope.interface.implementedBy(SpecialFoo))
+ [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
+
+ >>> list(zope.interface.providedBy(SpecialFoo()))
+ [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
+
+Sometimes, you don't want to inherit declarations. In that case, you
+can use `implementsOnly`, instead of `implements`:
+
+ >>> class Special(Foo):
+ ... zope.interface.implementsOnly(ISpecial)
+ ... reason = 'I just am'
+ ... def brag(self):
+ ... return "I'm special because %s" % self.reason
+
+ >>> list(zope.interface.implementedBy(Special))
+ [<InterfaceClass __main__.ISpecial>]
+
+ >>> list(zope.interface.providedBy(Special()))
+ [<InterfaceClass __main__.ISpecial>]
+
+External declarations
+---------------------
+
+Normally, we make implementation declarations as part of a class
+definition. Sometimes, we may want to make declarations from outside
+the class definition. For example, we might want to declare interfaces
+for classes that we didn't write. The function `classImplements` can
+be used for this purpose:
+
+ >>> class C:
+ ... pass
+
+ >>> zope.interface.classImplements(C, IFoo)
+ >>> list(zope.interface.implementedBy(C))
+ [<InterfaceClass __main__.IFoo>]
+
+We can use `classImplementsOnly` to exclude inherited interfaces:
+
+ >>> class C(Foo):
+ ... pass
+
+ >>> zope.interface.classImplementsOnly(C, ISpecial)
+ >>> list(zope.interface.implementedBy(C))
+ [<InterfaceClass __main__.ISpecial>]
+
+
+
+Declaration Objects
+-------------------
+
+When we declare interfaces, we create *declaration* objects. When we
+query declarations, declaration objects are returned:
+
+ >>> type(zope.interface.implementedBy(Special))
+ <class 'zope.interface.declarations.Implements'>
+
+Declaration objects and interface objects are similar in many ways. In
+fact, they share a common base class. The important thing to realize
+about them is that they can be used where interfaces are expected in
+declarations. Here's a silly example:
+
+ >>> class Special2(Foo):
+ ... zope.interface.implementsOnly(
+ ... zope.interface.implementedBy(Foo),
+ ... ISpecial,
+ ... )
+ ... reason = 'I just am'
+ ... def brag(self):
+ ... return "I'm special because %s" % self.reason
+
+The declaration here is almost the same as
+``zope.interface.implements(ISpecial)``, except that the order of
+interfaces in the resulting declaration is different:
+
+ >>> list(zope.interface.implementedBy(Special2))
+ [<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.ISpecial>]
+
+
+
+
+Interface Inheritance
+=====================
+
+Interfaces can extend other interfaces. They do this simply by listing
+the other interfaces as base interfaces:
+
+ >>> class IBlat(zope.interface.Interface):
+ ... """Blat blah blah"""
+ ...
+ ... y = zope.interface.Attribute("y blah blah")
+ ... def eek():
+ ... """eek blah blah"""
+
+ >>> IBlat.__bases__
+ (<InterfaceClass zope.interface.Interface>,)
+
+ >>> class IBaz(IFoo, IBlat):
+ ... """Baz blah"""
+ ... def eek(a=1):
+ ... """eek in baz blah"""
+ ...
+
+ >>> IBaz.__bases__
+ (<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.IBlat>)
+
+ >>> names = list(IBaz)
+ >>> names.sort()
+ >>> names
+ ['bar', 'eek', 'x', 'y']
+
+Note that `IBaz` overrides eek:
+
+ >>> IBlat['eek'].__doc__
+ 'eek blah blah'
+ >>> IBaz['eek'].__doc__
+ 'eek in baz blah'
+
+We were careful to override eek in a compatible way. When an
+extending an interface, the extending interface should be compatible
+[#compat]_ with the extended interfaces.
+
+We can ask whether one interface extends another:
+
+ >>> IBaz.extends(IFoo)
+ True
+ >>> IBlat.extends(IFoo)
+ False
+
+Note that interfaces don't extend themselves:
+
+ >>> IBaz.extends(IBaz)
+ False
+
+Sometimes we wish they did, but we can, instead use `isOrExtends`:
+
+ >>> IBaz.isOrExtends(IBaz)
+ True
+ >>> IBaz.isOrExtends(IFoo)
+ True
+ >>> IFoo.isOrExtends(IBaz)
+ False
+
+When we iterate over an interface, we get all of the names it defines,
+including names defined by base interfaces. Sometimes, we want *just*
+the names defined by the interface directly. We bane use the `names`
+method for that:
+
+ >>> list(IBaz.names())
+ ['eek']
+
+
+Tagged Values
+=============
+
+Interfaces and attribute descriptions support an extension mechanism,
+borrowed from UML, called "tagged values" that lets us store extra
+data:
+
+ >>> IFoo.setTaggedValue('date-modified', '2004-04-01')
+ >>> IFoo.setTaggedValue('author', 'Jim Fulton')
+ >>> IFoo.getTaggedValue('date-modified')
+ '2004-04-01'
+ >>> IFoo.queryTaggedValue('date-modified')
+ '2004-04-01'
+ >>> IFoo.queryTaggedValue('datemodified')
+ >>> tags = list(IFoo.getTaggedValueTags())
+ >>> tags.sort()
+ >>> tags
+ ['author', 'date-modified']
+
+Function attributes are converted to tagged values when method
+attribute definitions are created:
+
+ >>> class IBazFactory(zope.interface.Interface):
+ ... def __call__():
+ ... "create one"
+ ... __call__.return_type = IBaz
+
+ >>> IBazFactory['__call__'].getTaggedValue('return_type')
+ <InterfaceClass __main__.IBaz>
+
+
+Invariants
+==========
+
+Interfaces can exss conditions that must hold for objects that
+provide them. These conditions are exssed using one or more
+invariants. Invariants are callable objects that will be called with
+an object that provides an interface. An invariant raises an `Invalid`
+exception if the condition doesn't hold. Here's an example:
+
+ >>> class RangeError(zope.interface.Invalid):
+ ... """A range has invalid limits"""
+ ... def __repr__(self):
+ ... return "RangeError(%r)" % self.args
+
+ >>> def range_invariant(ob):
+ ... if ob.max < ob.min:
+ ... raise RangeError(ob)
+
+Given this invariant, we can use it in an interface definition:
+
+ >>> class IRange(zope.interface.Interface):
+ ... min = zope.interface.Attribute("Lower bound")
+ ... max = zope.interface.Attribute("Upper bound")
+ ...
+ ... zope.interface.invariant(range_invariant)
+
+Interfaces have a method for checking their invariants:
+
+ >>> class Range(object):
+ ... zope.interface.implements(IRange)
+ ...
+ ... def __init__(self, min, max):
+ ... self.min, self.max = min, max
+ ...
+ ... def __repr__(self):
+ ... return "Range(%s, %s)" % (self.min, self.max)
+
+ >>> IRange.validateInvariants(Range(1,2))
+ >>> IRange.validateInvariants(Range(1,1))
+ >>> IRange.validateInvariants(Range(2,1))
+ Traceback (most recent call last):
+ ...
+ RangeError: Range(2, 1)
+
+If you have multiple invariants, you may not want to stop checking
+after the first error. If you pass a list to `validateInvariants`,
+then a single `Invalid` exception will be raised with the list of
+exceptions as it's argument:
+
+ >>> errors = []
+ >>> IRange.validateInvariants(Range(2,1), errors)
+ Traceback (most recent call last):
+ ...
+ Invalid: [RangeError(Range(2, 1))]
+
+And the list will be filled with the individual exceptions:
+
+ >>> errors
+ [RangeError(Range(2, 1))]
+
+
+
+
+
+.. [#create] The main reason we subclass `Interface` is to cause the
+ Python class statement to create an interface, rather
+ than a class.
+
+ It's possible to create interfaces by calling a special
+ interface class directly. Doing this, it's possible
+ (and, on rare occasions, useful) to create interfaces
+ that don't descend from `Interface`. Using this
+ technique is beyond the scope of this document.
+
+.. [#factory] Classes are factories. They can be called to create
+ their instances. We expect that we will eventually
+ extend the concept of implementation to other kinds of
+ factories, so that we can declare the interfaces
+ provided by the objects created.
+
+.. [#compat] The goal is substitutability. An object that provides an
+ extending interface should be substitutable for an object
+ that provides the extended interface. In our example, an
+ object that provides IBaz should be usable whereever an
+ object that provides IBlat is expected.
+
+ The interface implementation doesn't enforce this. XXX
+ but maybe it should do some checks.
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/SETUP.cfg
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/SETUP.cfg Wed Jun 2 16:09:24 2004
@@ -0,0 +1,5 @@ />
+# Extension information for zpkg:
+
+<extension _zope_interface_coptimizations>
+ source _zope_interface_coptimizations.c
+</extension>
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/__init__.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/__init__.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,97 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Interfaces
+
+This package implements the Python "scarecrow" proposal.
+
+The package exports two names, 'Interface' and 'Attribute' directly.
+Interface is used to create an interface with a class statement, as
+in:
+
+
+
+ class IMyInterface(Interface):
+ '''Interface documentation
+ '''
+
+ def meth(arg1, arg2):
+ '''Documentation for meth
+ '''
+
+ # Note that there is no self argument
+
+To find out what you can do with interfaces, see the interface
+interface, IInterface in the IInterface module.
+
+The package has several public modules:
+
+ XXX This docstring needs to be updated after the Grand Renaming.
+
+ o Attribute has the implementation for interface attributes
+ for people who want to build interfaces by hand.
+ (Maybe someone should cry YAGNI for this. ;)
+
+ o Document has a utility for documenting an interface as structured text.
+
+ o Exceptions has the interface-defined exceptions
+
+ o IAttribute defines the attribute descriptor interface.
+
+ o IElement defined the base interface for IAttribute, IInterface,
+ and IMethod.
+
+ o IInterface defines the interface interface
+
+ o IMethod defined the method interface.
+
+ o Implements has various utilities for examining interface assertions.
+
+ o Method has the implementation for interface methods. See above.
+
+ o Verify has utilities for verifying (sort of) interfaces.
+
+See the module doc strings for more information.
+
+There is also a script, pyskel.py in the package that can be used to
+create interface skeletons. Run it without arguments to get documentation.
+
+Revision information:
+$Id: __init__.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+from zope.interface.interface import Interface, _wire
+
+# Need to actually get the interface elements to implement the right interfaces
+_wire()
+del _wire
+
+from zope.interface.interface import Attribute, invariant
+
+from zope.interface.declarations import providedBy, implementedBy
+from zope.interface.declarations import classImplements, classImplementsOnly
+from zope.interface.declarations import directlyProvidedBy, directlyProvides
+from zope.interface.declarations import implements, implementsOnly
+from zope.interface.declarations import classProvides, moduleProvides
+from zope.interface.declarations import Declaration
+from zope.interface.exceptions import Invalid
+
+# The following are to make spec pickles cleaner
+from zope.interface.declarations import Provides
+
+
+from zope.interface.interfaces import IInterfaceDeclaration
+
+moduleProvides(IInterfaceDeclaration)
+
+__all__ = ('Interface', 'Attribute') + tuple(IInterfaceDeclaration)
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/_flatten.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/_flatten.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,39 @@ />
+##############################################################################
+#
+# Copyright (c) 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.
+#
+##############################################################################
+"""Adapter-style interface registry
+
+See Adapter class.
+
+$Id: _flatten.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+__metaclass__ = type # All classes are new style when run with Python 2.2+
+
+from zope.interface import Declaration
+
+def _flatten(implements, include_None=0):
+
+ try:
+ r = implements.flattened()
+ except AttributeError:
+ if implements is None:
+ r=()
+ else:
+ r = Declaration(implements).flattened()
+
+ if not include_None:
+ return r
+
+ r = list(r)
+ r.append(None)
+ return r
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/_zope_interface_coptimizations.c
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/_zope_interface_coptimizations.c Wed Jun 2 16:09:24 2004
@@ -0,0 +1,551 @@ />
+/*###########################################################################
+ #
+ # Copyright (c) 2003 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.
+ #
+ ############################################################################*/
+
+#include "Python.h"
+#include "structmember.h"
+
+#define TYPE(O) ((PyTypeObject*)(O))
+#define OBJECT(O) ((PyObject*)(O))
+#define CLASSIC(O) ((PyClassObject*)(O))
+
+static PyObject *str__dict__, *str__implemented__, *strextends;
+static PyObject *BuiltinImplementationSpecifications, *str__provides__;
+static PyObject *str__class__, *str__providedBy__, *strisOrExtends;
+static PyObject *empty, *fallback, *str_implied, *str_cls, *str_implements;
+static PyTypeObject *Implements;
+
+static int imported_declarations = 0;
+
+static int
+import_declarations(void)
+{
+ PyObject *declarations, *i;
+
+ declarations = PyImport_ImportModule("zope.interface.declarations");
+ if (declarations == NULL)
+ return -1;
+
+ BuiltinImplementationSpecifications = PyObject_GetAttrString(
+ declarations, "BuiltinImplementationSpecifications");
+ if (BuiltinImplementationSpecifications == NULL)
+ return -1;
+
+ empty = PyObject_GetAttrString(declarations, "_empty");
+ if (empty == NULL)
+ return -1;
+
+ fallback = PyObject_GetAttrString(declarations, "implementedByFallback");
+ if (fallback == NULL)
+ return -1;
+
+
+
+ i = PyObject_GetAttrString(declarations, "Implements");
+ if (i == NULL)
+ return -1;
+
+ if (! PyType_Check(i))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "zope.declarations.Implements is not a type");
+ return -1;
+ }
+
+ Implements = (PyTypeObject *)i;
+
+ Py_DECREF(declarations);
+
+ imported_declarations = 1;
+ return 0;
+}
+
+extern PyTypeObject SpecType; /* Forward */
+
+static PyObject *
+implementedByFallback(PyObject *cls)
+{
+ if (imported_declarations == 0 && import_declarations() < 0)
+ return NULL;
+
+ return PyObject_CallFunctionObjArgs(fallback, cls, NULL);
+}
+
+static PyObject *
+implementedBy(PyObject *ignored, PyObject *cls)
+{
+ /* Fast retrieval of implements spec, if possible, to optimize
+ common case. Use fallback code if we get stuck.
+ */
+
+ PyObject *dict = NULL, *spec;
+
+ if (PyType_Check(cls))
+ {
+ dict = TYPE(cls)->tp_dict;
+ Py_XINCREF(dict);
+ }
+
+ if (dict == NULL)
+ dict = PyObject_GetAttr(cls, str__dict__);
+
+ if (dict == NULL)
+ {
+ /* Probably a security proxied class, use more expensive fallback code */
+ PyErr_Clear();
+ return implementedByFallback(cls);
+ }
+
+ spec = PyObject_GetItem(dict, str__implemented__);
+ Py_DECREF(dict);
+ if (spec)
+ {
+ if (imported_declarations == 0 && import_declarations() < 0)
+ return NULL;
+
+ if (PyObject_TypeCheck(spec, Implements))
+ return spec;
+
+ /* Old-style declaration, use more expensive fallback code */
+ Py_DECREF(spec);
+ return implementedByFallback(cls);
+ }
+
+ PyErr_Clear();
+
+ /* Maybe we have a builtin */
+ if (imported_declarations == 0 && import_declarations() < 0)
+ return NULL;
+
+ spec = PyDict_GetItem(BuiltinImplementationSpecifications, cls);
+ if (spec != NULL)
+ {
+ Py_INCREF(spec);
+ return spec;
+ }
+
+ /* We're stuck, use fallback */
+ return implementedByFallback(cls);
+}
+
+static PyObject *
+getObjectSpecification(PyObject *ignored, PyObject *ob)
+{
+ PyObject *cls, *result;
+
+ result = PyObject_GetAttr(ob, str__provides__);
+ if (result != NULL)
+ return result;
+
+ PyErr_Clear();
+
+ /* We do a getattr here so as not to be defeated by proxies */
+ cls = PyObject_GetAttr(ob, str__class__);
+ if (cls == NULL)
+ {
+ PyErr_Clear();
+ if (imported_declarations == 0 && import_declarations() < 0)
+ return NULL;
+ Py_INCREF(empty);
+ return empty;
+ }
+
+ result = implementedBy(NULL, cls);
+ Py_DECREF(cls);
+
+ return result;
+}
+
+static PyObject *
+providedBy(PyObject *ignored, PyObject *ob)
+{
+ PyObject *result, *cls, *cp;
+
+ result = PyObject_GetAttr(ob, str__providedBy__);
+ if (result == NULL)
+ {
+ PyErr_Clear();
+ return getObjectSpecification(NULL, ob);
+ }
+
+
+ /* We want to make sure we have a spec. We can't do a type check
+ because we may have a proxy, so we'll just try to get the
+ only attribute.
+ */
+ if (PyObject_HasAttr(result, strextends))
+ return result;
+
+ /*
+ The object's class doesn't understand descriptors.
+ Sigh. We need to get an object descriptor, but we have to be
+ careful. We want to use the instance's __provides__,l if
+ there is one, but only if it didn't come from the class.
+ */
+ Py_DECREF(result);
+
+ cls = PyObject_GetAttr(ob, str__class__);
+ if (cls == NULL)
+ return NULL;
+
+ result = PyObject_GetAttr(ob, str__provides__);
+ if (result == NULL)
+ {
+ /* No __provides__, so just fall back to implementedBy */
+ PyErr_Clear();
+ result = implementedBy(NULL, cls);
+ Py_DECREF(cls);
+ return result;
+ }
+
+ cp = PyObject_GetAttr(cls, str__provides__);
+ if (cp == NULL)
+ {
+ /* The the class has no provides, assume we're done: */
+ PyErr_Clear();
+ Py_DECREF(cls);
+ return result;
+ }
+
+ if (cp == result)
+ {
+ /*
+ Oops, we got the provides from the class. This means
+ the object doesn't have it's own. We should use implementedBy
+ */
+ Py_DECREF(result);
+ result = implementedBy(NULL, cls);
+ }
+
+ Py_DECREF(cls);
+ Py_DECREF(cp);
+
+ return result;
+}
+
+static PyObject *
+inst_attr(PyObject *self, PyObject *name)
+{
+ /* Get an attribute from an inst dict. Return a borrowed reference.
+ */
+
+ PyObject **dictp, *v;
+
+ dictp = _PyObject_GetDictPtr(self);
+ if (dictp && *dictp && (v = PyDict_GetItem(*dictp, name)))
+ return v;
+ PyErr_SetObject(PyExc_AttributeError, name);
+ return NULL;
+}
+
+
+static PyObject *
+Spec_extends(PyObject *self, PyObject *other)
+{
+ PyObject *implied;
+
+ implied = inst_attr(self, str_implied);
+ if (implied == NULL)
+ return implied;
+
+#ifdef Py_True
+ if (PyDict_GetItem(implied, other) != NULL)
+ {
+ Py_INCREF(Py_True);
+ return Py_True;
+ }
+ Py_INCREF(Py_False);
+ return Py_False;
+#else
+ return PyInt_FromLong(PyDict_GetItem(implied, other) != NULL);
+#endif
+}
+
+static char Spec_extends__doc__[] =
+"Test whether a specification is or extends another"
+;
+
+static char Spec_providedBy__doc__[] =
+"Test whether an interface is implemented by the specification"
+;
+
+static PyObject *
+Spec_providedBy(PyObject *self, PyObject *ob)
+{
+ PyObject *decl, *item;
+
+ decl = providedBy(NULL, ob);
+
+ if (PyObject_TypeCheck(ob, &SpecType))
+ item = Spec_extends(decl, self);
+ else
+ /* decl is probably a security proxy. We have to go the long way
+ around.
+ */
+ item = PyObject_CallMethodObjArgs(decl, strisOrExtends, self, NULL);
+
+ Py_DECREF(decl);
+ return item;
+}
+
+
+static char Spec_implementedBy__doc__[] =
+"Test whether the specification is implemented by instances of a class"
+;
+
+static PyObject *
+Spec_implementedBy(PyObject *self, PyObject *cls)
+{
+ PyObject *decl, *item;
+
+ decl = implementedBy(NULL, cls);
+ if (decl == NULL)
+ return NULL;
+
+ if (PyObject_TypeCheck(decl, &SpecType))
+ item = Spec_extends(decl, self);
+ else
+ item = PyObject_CallMethodObjArgs(decl, strisOrExtends, self, NULL);
+
+ Py_DECREF(decl);
+ return item;
+}
+
+static struct PyMethodDef Spec_methods[] = {
+ {"providedBy",
+ (PyCFunction)Spec_providedBy, METH_O,
+ Spec_providedBy__doc__},
+ {"implementedBy",
+ (PyCFunction)Spec_implementedBy, METH_O,
+ Spec_implementedBy__doc__},
+ {"isOrExtends", (PyCFunction)Spec_extends, METH_O,
+ Spec_extends__doc__},
+
+ {NULL, NULL} /* sentinel */
+};
+
+static PyTypeObject SpecType = {
+ PyObject_HEAD_INIT(NULL)
+ /* ob_size */ 0,
+ /* tp_name */ "_interface_coptimizations."
+ "SpecificationBase",
+ /* tp_basicsize */ 0,
+ /* tp_itemsize */ 0,
+ /* tp_dealloc */ (destructor)0,
+ /* tp_print */ (printfunc)0,
+ /* tp_getattr */ (getattrfunc)0,
+ /* tp_setattr */ (setattrfunc)0,
+ /* tp_compare */ (cmpfunc)0,
+ /* tp_repr */ (reprfunc)0,
+ /* tp_as_number */ 0,
+ /* tp_as_sequence */ 0,
+ /* tp_as_mapping */ 0,
+ /* tp_hash */ (hashfunc)0,
+ /* tp_call */ (ternaryfunc)0,
+ /* tp_str */ (reprfunc)0,
+ /* tp_getattro */ (getattrofunc)0,
+ /* tp_setattro */ (setattrofunc)0,
+ /* tp_as_buffer */ 0,
+ /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ "Base type for Specification objects",
+ /* tp_traverse */ (traverseproc)0,
+ /* tp_clear */ (inquiry)0,
+ /* tp_richcompare */ (richcmpfunc)0,
+ /* tp_weaklistoffset */ (long)0,
+ /* tp_iter */ (getiterfunc)0,
+ /* tp_iternext */ (iternextfunc)0,
+ /* tp_methods */ Spec_methods,
+};
+
+static PyObject *
+OSD_descr_get(PyObject *self, PyObject *inst, PyObject *cls)
+{
+ PyObject *provides;
+
+ if (inst == NULL)
+ return getObjectSpecification(NULL, cls);
+
+ provides = PyObject_GetAttr(inst, str__provides__);
+ if (provides != NULL)
+ return provides;
+ PyErr_Clear();
+ return implementedBy(NULL, cls);
+}
+
+static PyTypeObject OSDType = {
+ PyObject_HEAD_INIT(NULL)
+ /* ob_size */ 0,
+ /* tp_name */ "_interface_coptimizations."
+ "ObjectSpecificationDescriptor",
+ /* tp_basicsize */ 0,
+ /* tp_itemsize */ 0,
+ /* tp_dealloc */ (destructor)0,
+ /* tp_print */ (printfunc)0,
+ /* tp_getattr */ (getattrfunc)0,
+ /* tp_setattr */ (setattrfunc)0,
+ /* tp_compare */ (cmpfunc)0,
+ /* tp_repr */ (reprfunc)0,
+ /* tp_as_number */ 0,
+ /* tp_as_sequence */ 0,
+ /* tp_as_mapping */ 0,
+ /* tp_hash */ (hashfunc)0,
+ /* tp_call */ (ternaryfunc)0,
+ /* tp_str */ (reprfunc)0,
+ /* tp_getattro */ (getattrofunc)0,
+ /* tp_setattro */ (setattrofunc)0,
+ /* tp_as_buffer */ 0,
+ /* tp_flags */ Py_TPFLAGS_DEFAULT
+ | Py_TPFLAGS_BASETYPE ,
+ "Object Specification Descriptor",
+ /* tp_traverse */ (traverseproc)0,
+ /* tp_clear */ (inquiry)0,
+ /* tp_richcompare */ (richcmpfunc)0,
+ /* tp_weaklistoffset */ (long)0,
+ /* tp_iter */ (getiterfunc)0,
+ /* tp_iternext */ (iternextfunc)0,
+ /* tp_methods */ 0,
+ /* tp_members */ 0,
+ /* tp_getset */ 0,
+ /* tp_base */ 0,
+ /* tp_dict */ 0, /* internal use */
+ /* tp_descr_get */ (descrgetfunc)OSD_descr_get,
+};
+
+static PyObject *
+CPB_descr_get(PyObject *self, PyObject *inst, PyObject *cls)
+{
+ PyObject *mycls, *implements;
+
+ mycls = inst_attr(self, str_cls);
+ if (mycls == NULL)
+ return NULL;
+
+ if (cls == mycls)
+ {
+ if (inst == NULL)
+ {
+ Py_INCREF(self);
+ return OBJECT(self);
+ }
+
+ implements = inst_attr(self, str_implements);
+ Py_XINCREF(implements);
+ return implements;
+ }
+
+ PyErr_SetObject(PyExc_AttributeError, str__provides__);
+ return NULL;
+}
+
+static PyTypeObject CPBType = {
+ PyObject_HEAD_INIT(NULL)
+ /* ob_size */ 0,
+ /* tp_name */ "_interface_coptimizations."
+ "ClassProvidesBase",
+ /* tp_basicsize */ 0,
+ /* tp_itemsize */ 0,
+ /* tp_dealloc */ (destructor)0,
+ /* tp_print */ (printfunc)0,
+ /* tp_getattr */ (getattrfunc)0,
+ /* tp_setattr */ (setattrfunc)0,
+ /* tp_compare */ (cmpfunc)0,
+ /* tp_repr */ (reprfunc)0,
+ /* tp_as_number */ 0,
+ /* tp_as_sequence */ 0,
+ /* tp_as_mapping */ 0,
+ /* tp_hash */ (hashfunc)0,
+ /* tp_call */ (ternaryfunc)0,
+ /* tp_str */ (reprfunc)0,
+ /* tp_getattro */ (getattrofunc)0,
+ /* tp_setattro */ (setattrofunc)0,
+ /* tp_as_buffer */ 0,
+ /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ "C Base class for ClassProvides",
+ /* tp_traverse */ (traverseproc)0,
+ /* tp_clear */ (inquiry)0,
+ /* tp_richcompare */ (richcmpfunc)0,
+ /* tp_weaklistoffset */ (long)0,
+ /* tp_iter */ (getiterfunc)0,
+ /* tp_iternext */ (iternextfunc)0,
+ /* tp_methods */ 0,
+ /* tp_members */ 0,
+ /* tp_getset */ 0,
+ /* tp_base */ &SpecType,
+ /* tp_dict */ 0, /* internal use */
+ /* tp_descr_get */ (descrgetfunc)CPB_descr_get,
+};
+
+
+static struct PyMethodDef m_methods[] = {
+ {"implementedBy", (PyCFunction)implementedBy, METH_O,
+ "Interfaces implemented by instances of a class"},
+ {"getObjectSpecification", (PyCFunction)getObjectSpecification, METH_O,
+ "Get an object's interfaces (internal api)"},
+ {"providedBy", (PyCFunction)providedBy, METH_O,
+ "Get an object's interfaces"},
+
+ {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */
+};
+
+#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
+#define PyMODINIT_FUNC void
+#endif
+PyMODINIT_FUNC
+init_zope_interface_coptimizations(void)
+{
+ PyObject *m;
+
+#define DEFINE_STRING(S) \
+ if(! (str ## S = PyString_FromString(# S))) return
+
+ DEFINE_STRING(__dict__);
+ DEFINE_STRING(__implemented__);
+ DEFINE_STRING(__provides__);
+ DEFINE_STRING(__class__);
+ DEFINE_STRING(__providedBy__);
+ DEFINE_STRING(isOrExtends);
+ DEFINE_STRING(extends);
+ DEFINE_STRING(_implied);
+ DEFINE_STRING(_implements);
+ DEFINE_STRING(_cls);
+#undef DEFINE_STRING
+
+
+ /* Initialize types: */
+ SpecType.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&SpecType) < 0)
+ return;
+ OSDType.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&OSDType) < 0)
+ return;
+ CPBType.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&CPBType) < 0)
+ return;
+
+ /* Create the module and add the functions */
+ m = Py_InitModule3("_zope_interface_coptimizations", m_methods,
+ "C optimizations for zope.interface\n\n"
+ "$Id: _zope_interface_coptimizations.c 24749 2004-05-16 13:00:21Z philikon $");
+ if (m == NULL)
+ return;
+
+ /* Add types: */
+ if (PyModule_AddObject(m, "SpecificationBase", (PyObject *)&SpecType) < 0)
+ return;
+ if (PyModule_AddObject(m, "ObjectSpecificationDescriptor",
+ (PyObject *)&OSDType) < 0)
+ return;
+ if (PyModule_AddObject(m, "ClassProvidesBase", (PyObject *)&CPBType) < 0)
+ return;
+}
+
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/adapter.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/adapter.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,649 @@ />
+############################################################################
+#
+# Copyright (c) 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.
+#
+############################################################################
+"""Adapter-style interface registry
+
+This implementation is based on a notion of "surrogate" interfaces.
+
+$Id: adapter.py 24981 2004-05-26 09:22:25Z jim $
+"""
+
+# Implementation notes
+
+# We keep a collection of surrogates.
+
+# A surrogate is a surrogate for a specification (interface or
+# declaration). We use weak references in order to remove surrogates
+# if the corresponding specification goes away.
+
+# Each surrogate keeps track of:
+
+# - The adapters registered directly for that surrogate, and
+
+# - The "implied" adapters, which is the adapters that can be computed
+# from instances of that surrogate.
+
+# The later data structure takes into account adapters registered for
+# specifications that the registered surrogate extends.
+
+# The registrations are of the form:
+
+# {(subscription, with, name, specification) -> factories}
+
+# where:
+
+# 'subscription' is a flag indicating if this registration is for
+# subscription adapters.
+
+# 'with' is a tuple of specs that is non-empty only in the case
+# of multi-adapters.
+
+# 'name' is a unicode adapter name. Unnamed adapters have an empty
+# name.
+
+# 'specification' is the interface being adapted to.
+
+# 'factories' is normally a tuple of factories, but can be anything.
+# (See the "raw" option to the query-adapter calls.) For subscription
+# adapters, it is a tuple of tuples of factories.
+
+# The implied adapters are held in a single dictionary. The items in the
+# dictionary are of several forms:
+
+# For single adapters:
+#
+# {specification -> {name -> object}
+#
+# where object is usually a sequence of factories
+
+# For multiple adapters:
+#
+# {(specification, order) -> {name -> {with -> object}}}
+
+# For single subscription adapters:
+#
+# {('s', specification) -> tuple([object])}
+
+# For multiple-subscription adapters:
+#
+# {('s', specification, order) -> {with -> tuple([object])}}
+
+
+from __future__ import generators
+
+import weakref
+from zope.interface.ro import ro
+from zope.interface.declarations import providedBy
+from zope.interface.interface import InterfaceClass, Interface
+
+Default = InterfaceClass("Default", (), {})
+Null = InterfaceClass("Null", (), {})
+
+# 2.2 backwards compatability
+try:
+ enumerate
+except NameError:
+ def enumerate(l):
+ i = 0
+ for o in l:
+ yield i, o
+ i += 1
+try:
+ basestring
+except NameError:
+ basestring = (str, unicode)
+
+
+class ReadProperty(object):
+
+ def __init__(self, func):
+ self.func = func
+
+ def __get__(self, inst, class_):
+ if inst is None:
+ return self
+ return self.func(inst)
+
+class Surrogate(object):
+ """Specification surrogate
+
+ A specification surrogate is used to hold adapter registrations on
+ behalf of a specification.
+ """
+
+ def __init__(self, spec, registry):
+ self.spec = spec.weakref()
+ spec.subscribe(self)
+ self.adapters = {}
+ self.dependents = weakref.WeakKeyDictionary()
+
+ self.__bases__ = [registry.get(base) for base in spec.__bases__]
+ for base in self.__bases__:
+ base.subscribe(self)
+
+ def dirty(self):
+ if 'get' in self.__dict__:
+ # Not already dirty
+ del self.selfImplied
+ del self.multImplied
+ del self.get
+ for dependent in self.dependents.keys():
+ dependent.dirty()
+
+ def clean(self):
+ self.selfImplied, self.multImplied = adapterImplied(self.adapters)
+
+ implied = {}
+
+ ancestors = ro(self)
+
+ # Collect implied data in reverse order to have more specific data
+ # override less-specific data.
+ ancestors.reverse()
+ for ancestor in ancestors:
+
+ for key, v in ancestor.selfImplied.iteritems():
+
+ # key is specification or ('s', specification)
+ subscription = isinstance(key, tuple) and key[0] == 's'
+ if subscription:
+ # v is tuple of subs
+ implied[key] = implied.get(key, ()) + v
+ else:
+ oldbyname = implied.get(key)
+ if not oldbyname:
+ implied[key] = oldbyname = {}
+
+ # v is name -> object
+ oldbyname.update(v)
+
+ for key, v in ancestor.multImplied.iteritems():
+ # key is (specification, order)
+ # or ('s', specification, order)
+ subscription = key[0] == 's'
+ if subscription:
+ oldwithobs = implied.get(key)
+ if not oldwithobs:
+ oldwithobs = implied[key] = {}
+
+ # v is {with -> tuple([object])}
+ for with, objects in v.iteritems():
+ oldwithobs[with] = oldwithobs.get(with, ()) + objects
+
+ else:
+ oldbyname = implied.get(key)
+ if not oldbyname:
+ implied[key] = oldbyname = {}
+
+ # v is {name -> {with -> ?}}
+ for name, withobs in v.iteritems():
+ oldwithobs = oldbyname.get(name)
+ if not oldwithobs:
+ oldwithobs = oldbyname[name] = {}
+
+ # withobs is {with -> object}
+ oldwithobs.update(withobs)
+
+ # Now flatten with mappings to tuples
+ for key, v in implied.iteritems():
+ if isinstance(key, tuple) and key[0] == 's':
+ # subscriptions
+ if isinstance(v, dict):
+ implied[key] = v.items()
+ else:
+ byname = v
+ for name, value in byname.iteritems():
+ if isinstance(value, dict):
+ # We have {with -> value}
+ # convert it to sorted [(with, value]
+ byname[name] = orderwith(value)
+
+ self.get = implied.get
+
+ def get(self, key):
+ """Get an implied value
+
+ This is only called when the surrogate is dirty
+ """
+ self.clean()
+ return self.__dict__['get'](key)
+
+ def selfImplied(self):
+ """Return selfImplied when dirty
+ """
+ self.clean()
+ return self.__dict__['selfImplied']
+ selfImplied = ReadProperty(selfImplied)
+
+ def multiImplied(self):
+ """Return _multiImplied when dirty
+ """
+ self.clean()
+ return self.__dict__['multiImplied']
+ multiImplied = ReadProperty(multiImplied)
+
+ def subscribe(self, dependent):
+ self.dependents[dependent] = 1
+
+ def unsubscribe(self, dependent):
+ del self.dependents[dependent]
+
+ def _adaptTo(self, specification, object, name='', with=()):
+ if object is None:
+ try:
+ del self.adapters[False, tuple(with), name, specification]
+ except KeyError:
+ pass
+ else:
+ self.adapters[False, tuple(with), name, specification
+ ] = object
+
+ self.dirty()
+
+ def _subscriptionAdaptTo(self, specification, object, with=()):
+ if object is None:
+ raise TypeError, ("Unregistering subscription adapters"
+ " isn't implemented")
+
+ key = (True, tuple(with), '', specification)
+ self.adapters[key] = self.adapters.get(key, ()) + (object, )
+ self.dirty()
+
+ def changed(self, which=None):
+ self.dirty()
+
+ def __repr__(self):
+ return '<%s(%s)>' % (self.__class__.__name__, self.spec())
+
+def orderwith(bywith):
+
+ # Convert {with -> adapter} to withs, [(with, value)]
+ # such that there are no i, j, i < j, such that
+ # withs[j][0] extends withs[i][0].
+
+ withs = []
+ for with, value in bywith.iteritems():
+ for i, (w, v) in enumerate(withs):
+ if withextends(with, w):
+ withs.insert(i, (with, value))
+ break
+ else:
+ withs.append((with, value))
+
+ return withs
+
+
+def withextends(with1, with2):
+ for spec1, spec2 in zip(with1, with2):
+ if spec1.extends(spec2):
+ return True
+ if spec1 != spec2:
+ break
+ return False
+
+class AdapterRegistry(object):
+ """Adapter registry
+ """
+
+ # Implementation note:
+ # We are like a weakref dict ourselves. We can't use a weakref
+ # dict because we have to use spec.weakref() rather than
+ # weakref.ref(spec) to get weak refs to specs.
+
+ _surrogateClass = Surrogate
+
+ def __init__(self):
+ default = self._surrogateClass(Default, self)
+ self._default = default
+ null = self._surrogateClass(Null, self)
+ self._null = null
+ surrogates = {Default.weakref(): default, Null.weakref(): null}
+ self._surrogates = surrogates
+
+ def _remove(k):
+ try:
+ del surrogates[k]
+ except KeyError:
+ pass
+
+ self._remove = _remove
+
+ def get(self, declaration):
+ if declaration is None:
+ return self._default
+
+ ref = declaration.weakref(self._remove)
+ surrogate = self._surrogates.get(ref)
+ if surrogate is None:
+ surrogate = self._surrogateClass(declaration, self)
+ self._surrogates[ref] = surrogate
+
+ return surrogate
+
+ def register(self, required, provided, name, value):
+ if required:
+ with = []
+ for iface in required[1:]:
+ if iface is None:
+ iface = Interface
+ with.append(iface)
+ with = tuple(with)
+ required = self.get(required[0])
+ else:
+ with = ()
+ required = self._null
+
+ if not isinstance(name, basestring):
+ raise TypeError("The name provided to provideAdapter "
+ "must be a string or unicode")
+
+ required._adaptTo(provided, value, unicode(name), with)
+
+ def lookup(self, required, provided, name='', default=None):
+ order = len(required)
+ if order == 1:
+ # Simple adapter:
+ s = self.get(required[0])
+ byname = s.get(provided)
+ if byname:
+ value = byname.get(name)
+ else:
+ value = None
+
+ if value is None:
+ byname = self._default.get(provided)
+ if byname:
+ value = byname.get(name, default)
+ else:
+ return default
+
+ return value
+
+ elif order == 0:
+ # null adapter
+ byname = self._null.get(provided)
+ if byname:
+ return byname.get(name, default)
+ else:
+ return default
+
+ # Multi adapter
+
+ with = required[1:]
+ key = provided, order
+
+ for surrogate in self.get(required[0]), self._default:
+ byname = surrogate.get(key)
+ if not byname:
+ continue
+
+ bywith = byname.get(name)
+ if not bywith:
+ continue
+
+ for rwith, value in bywith:
+ for rspec, spec in zip(rwith, with):
+ if not spec.isOrExtends(rspec):
+ break # This one is no good
+ else:
+ return value
+
+ return default
+
+ def lookup1(self, required, provided, name='', default=None):
+ s = self.get(required)
+ byname = s.get(provided)
+ if byname:
+ value = byname.get(name)
+ else:
+ value = None
+
+ if value is None:
+ byname = self._default.get(provided)
+ if byname:
+ value = byname.get(name, default)
+ else:
+ return default
+
+ return value
+
+ def lookupAll(self, required, provided):
+ order = len(required)
+ if order == 1:
+ # Simple adapter:
+ s = self.get(required[0])
+ byname = s.get(provided)
+ if byname:
+ for item in byname.iteritems():
+ yield item
+
+ defbyname = self._default.get(provided)
+ if defbyname:
+ for name, value in defbyname.iteritems():
+ if name in byname:
+ continue
+ yield name, value
+
+ return
+
+ elif order == 0:
+ # null adapter
+ byname = self._null.get(provided)
+ if byname:
+ for item in byname.iteritems():
+ yield item
+
+ return
+
+
+ # Multi adapter
+
+ with = required[1:]
+ key = provided, order
+ first = ()
+
+ for surrogate in self.get(required[0]), self._default:
+ byname = surrogate.get(key)
+ if not byname:
+ continue
+
+ for name, bywith in byname.iteritems():
+ if not bywith or name in first:
+ continue
+
+ for rwith, value in bywith:
+ for rspec, spec in zip(rwith, with):
+ if not spec.isOrExtends(rspec):
+ break # This one is no good
+ else:
+ # Got this far, we have a match
+ yield name, value
+ break
+
+ first = byname
+
+
+ def subscribe(self, required, provided, value):
+ if required:
+ required, with = self.get(required[0]), tuple(required[1:])
+ else:
+ required = self._null
+ with = ()
+
+ if provided is None:
+ provided = Null
+
+ required._subscriptionAdaptTo(provided, value, with)
+
+
+ def subscriptions(self, required, provided):
+ if provided is None:
+ provided = Null
+
+ order = len(required)
+ if order == 1:
+ # Simple subscriptions:
+ s = self.get(required[0])
+ result = s.get(('s', provided))
+ if result:
+ result = list(result)
+ else:
+ result = []
+
+ default = self._default.get(('s', provided))
+ if default:
+ result.extend(default)
+
+ return result
+
+ elif order == 0:
+ result = self._null.get(('s', provided))
+ if result:
+ return list(result)
+ else:
+ return []
+
+ # Multi
+ key = 's', provided, order
+ with = required[1:]
+ result = []
+
+ for surrogate in self.get(required[0]), self._default:
+ bywith = surrogate.get(key)
+ if not bywith:
+ continue
+
+ for rwith, values in bywith:
+ for rspec, spec in zip(rwith, with):
+ if not spec.isOrExtends(rspec):
+ break # This one is no good
+ else:
+ # we didn't break, so we have a match
+ result.extend(values)
+
+ return result
+
+
+
+def mextends(with, rwith):
+ if len(with) == len(rwith):
+ for w, r in zip(with, rwith):
+ if not w.isOrExtends(r):
+ break
+ else:
+ return True
+ return False
+
+def adapterImplied(adapters):
+ implied = {}
+ multi = {}
+
+ # This dictionary is used to catch situations specific adapters
+ # override less specific adapters.
+ # Because subscriptions are cummulative, registered doesn't apply.
+ registered = {}
+
+ # Add adapters and interfaces directly implied by same:
+
+ for key, value in adapters.iteritems():
+
+ # XXX Backward compatability
+ # Don't need to handle 3-tuples some day
+ try:
+ (subscription, with, name, target) = key
+ except ValueError:
+ (with, name, target) = key
+ subscription = False
+
+ if subscription:
+ if with:
+ _add_multi_sub_adapter(with, target, multi, value)
+ else:
+ _add_named_sub_adapter(target, implied, value)
+ else:
+ if with:
+ _add_multi_adapter(with, name, target, target, multi,
+ registered, value)
+ else:
+ _add_named_adapter(target, target, name, implied,
+ registered, value)
+
+ return implied, multi
+
+def _add_named_adapter(target, provided, name, implied,
+ registered, value):
+
+ ikey = target
+ rkey = target, name
+
+ byname = implied.get(ikey)
+ if not byname:
+ byname = implied[ikey] = {}
+
+ if (name not in byname
+ or
+ (rkey in registered and registered[rkey].extends(provided))
+ ):
+
+ registered[rkey] = provided
+ byname[name] = value
+
+ for b in target.__bases__:
+ _add_named_adapter(b, provided, name, implied,
+ registered, value)
+
+def _add_multi_adapter(with, name, target, provided, implied,
+ registered, object):
+
+ ikey = target, (len(with) + 1)
+ byname = implied.get(ikey)
+ if not byname:
+ byname = implied[ikey] = {}
+
+ bywith = byname.get(name)
+ if not bywith:
+ bywith = byname[name] = {}
+
+
+ rkey = ikey, name, with # The full key has all 4
+ if (with not in bywith
+ or
+ (rkey not in registered or registered[rkey].extends(provided))
+ ):
+ # This is either a new entry or it is an entry for a more
+ # general interface that is closer provided than what we had
+ # before
+ registered[rkey] = provided
+ bywith[with] = object
+
+ for b in target.__bases__:
+ _add_multi_adapter(with, name, b, provided, implied,
+ registered, object)
+
+def _add_named_sub_adapter(target, implied, objects):
+ key = ('s', target)
+ implied[key] = implied.get(key, ()) + objects
+
+ for b in target.__bases__:
+ _add_named_sub_adapter(b, implied, objects)
+
+def _add_multi_sub_adapter(with, target, implied, objects):
+ key = 's', target, (len(with) + 1)
+ bywith = implied.get(key)
+ if not bywith:
+ bywith = implied[key] = {}
+
+ bywith[with] = bywith.get(with, ()) + objects
+
+ for b in target.__bases__:
+ _add_multi_sub_adapter(with, b, implied, objects)
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/adapter.txt
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/adapter.txt Wed Jun 2 16:09:24 2004
@@ -0,0 +1,349 @@ />
+================
+Adapter Registry
+================
+
+Adapter registries provide a way to register objects that depend on
+one or more interface specifications and provide (perhaps indirectly)
+some interface. In addition, the registrations have names. (You can
+think of the names as qualifiers of the provided interfaces.)
+
+The term "interface specification" refers both to interfaces and to
+interface declarations, such as declarations of interfaces implemented
+by a class.
+
+
+Single Adapters
+===============
+
+Let's look at a simple example, using a single required specification::
+
+ >>> from zope.interface.adapter import AdapterRegistry
+ >>> import zope.interface
+
+ >>> class IR1(zope.interface.Interface):
+ ... pass
+ >>> class IP1(zope.interface.Interface):
+ ... pass
+ >>> class IP2(IP1):
+ ... pass
+
+ >>> registry = AdapterRegistry()
+
+We'll register an object that depends on IR1 and "provides" IP2::
+
+ >>> registry.register([IR1], IP2, '', 12)
+
+Given the registration, we can look it up again::
+
+ >>> registry.lookup([IR1], IP2, '')
+ 12
+
+Note that we used an integer in the example. In real applications,
+one would use some objects that actually depend on or provide
+interfaces. The registry doesn't care about what gets registered, so
+we'll use integers and strings to keep the examples simple. There is
+one exception. Registering a value of None unregisters any
+viously-registered value.
+
+If an object depends on a specification, it can be looked up with a
+specification that extends the specification that it depends on::
+
+ >>> class IR2(IR1):
+ ... pass
+ >>> registry.lookup([IR2], IP2, '')
+ 12
+
+We can use a class implementation specification to look up the object::
+
+ >>> class C2:
+ ... zope.interface.implements(IR2)
+
+ >>> registry.lookup([zope.interface.implementedBy(C2)], IP2, '')
+ 12
+
+
+and it can be looked up for interfaces that its provided interface
+extends::
+
+ >>> registry.lookup([IR1], IP1, '')
+ 12
+ >>> registry.lookup([IR2], IP1, '')
+ 12
+
+But if you require a specification that doesn't extend the specification the
+object depends on, you won't get anything::
+
+ >>> registry.lookup([zope.interface.Interface], IP1, '')
+
+By the way, you can pass a default value to lookup::
+
+ >>> registry.lookup([zope.interface.Interface], IP1, '', 42)
+ 42
+
+If you try to get an interface the object doesn't provide, you also
+won't get anything::
+
+ >>> class IP3(IP2):
+ ... pass
+ >>> registry.lookup([IR1], IP3, '')
+
+You also won't get anything if you use the wrong name::
+
+ >>> registry.lookup([IR1], IP1, 'bob')
+ >>> registry.register([IR1], IP2, 'bob', "Bob's 12")
+ >>> registry.lookup([IR1], IP1, 'bob')
+ "Bob's 12"
+
+You can leave the name off when doing a lookup:
+
+ >>> registry.lookup([IR1], IP1)
+ 12
+
+If we register an object that provides IP1::
+
+ >>> registry.register([IR1], IP1, '', 11)
+
+then that object will be fered over O(12)::
+
+ >>> registry.lookup([IR1], IP1, '')
+ 11
+
+Also, if we register an object for IR2, then that will be fered
+when using IR2::
+
+ >>> registry.register([IR2], IP1, '', 21)
+ >>> registry.lookup([IR2], IP1, '')
+ 21
+
+lookup1
+-------
+
+Lookup of single adapters is common enough that there is a
+specialized version of lookup that takes a single required interface:
+
+ >>> registry.lookup1(IR2, IP1, '')
+ 21
+ >>> registry.lookup1(IR2, IP1)
+ 21
+
+
+Default Adapters
+----------------
+
+Sometimes, you want to provide an adapter that will adapt anything.
+For that, provide None as the required interface::
+
+ >>> registry.register([None], IP1, '', 1)
+
+then we can use that adapter for interfaces we don't have specific
+adapters for::
+
+ >>> class IQ(zope.interface.Interface):
+ ... pass
+ >>> registry.lookup([IQ], IP1, '')
+ 1
+
+Of course, specific adapters are still used when applicable::
+
+ >>> registry.lookup([IR2], IP1, '')
+ 21
+
+Class adapters
+--------------
+
+You can register adapters for class declarations, which is almost the
+same as registering them for a class::
+
+ >>> registry.register([zope.interface.implementedBy(C2)], IP1, '', 'C21')
+ >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
+ 'C21'
+
+Unregistering
+-------------
+
+You can unregister by registering None, rather than an object:;
+
+ >>> registry.register([zope.interface.implementedBy(C2)], IP1, '', None)
+ >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
+ 21
+
+Of course, this means that None can't be registered. This is an
+exception to the statement, made earlier, that the registry doesn't
+care what gets registered.
+
+Multi-adapters
+==============
+
+You can adapt multiple specifications::
+
+ >>> registry.register([IR1, IQ], IP2, '', '1q2')
+ >>> registry.lookup([IR1, IQ], IP2, '')
+ '1q2'
+ >>> registry.lookup([IR2, IQ], IP1, '')
+ '1q2'
+
+ >>> class IS(zope.interface.Interface):
+ ... pass
+ >>> registry.lookup([IR2, IS], IP1, '')
+
+ >>> class IQ2(IQ):
+ ... pass
+
+ >>> registry.lookup([IR2, IQ2], IP1, '')
+ '1q2'
+
+ >>> registry.register([IR1, IQ2], IP2, '', '1q22')
+ >>> registry.lookup([IR2, IQ2], IP1, '')
+ '1q22'
+
+
+Default Adapters
+----------------
+
+As with single adapters, you can define default adapters by specifying
+None for the *first* specification:
+
+ >>> registry.register([None, IQ], IP2, '', 'q2')
+ >>> registry.lookup([IS, IQ], IP2, '')
+ 'q2'
+
+Null Adapters
+=============
+
+You can also adapt no specification:
+
+ >>> registry.register([], IP2, '', 2)
+ >>> registry.lookup([], IP2, '')
+ 2
+ >>> registry.lookup([], IP1, '')
+ 2
+
+Listing named adapters
+----------------------
+
+Adapters are named. Sometimes, it's useful to get all of the named
+adapters for given interfaces.
+
+ >>> adapters = list(registry.lookupAll([IR1], IP1))
+ >>> adapters.sort()
+ >>> adapters
+ [(u'', 11), (u'bob', "Bob's 12")]
+
+This works for multi-adapters too:
+
+ >>> registry.register([IR1, IQ2], IP2, 'bob', '1q2 for bob')
+ >>> adapters = list(registry.lookupAll([IR2, IQ2], IP1))
+ >>> adapters.sort()
+ >>> adapters
+ [(u'', '1q22'), (u'bob', '1q2 for bob')]
+
+And even null adapters:
+
+ >>> registry.register([], IP2, 'bob', 3)
+ >>> adapters = list(registry.lookupAll([], IP1))
+ >>> adapters.sort()
+ >>> adapters
+ [(u'', 2), (u'bob', 3)]
+
+Subscriptions
+=============
+
+Normally, we want to look up an object that most-closely matches a
+specification. Sometimes, we want to get all of the objects that
+match some specification. We use subscriptions for this. We
+subscribe objects against specifications and then later find all of
+the subscribed objects::
+
+ >>> registry.subscribe([IR1], IP2, 'sub12 1')
+ >>> registry.subscriptions([IR1], IP2)
+ ['sub12 1']
+
+Note that, unlike regular adapters, subscriptions are unnamed.
+
+The order of returned subscriptions is not specified.
+
+You can have multiple subscribers for the same specification::
+
+ >>> registry.subscribe([IR1], IP2, 'sub12 2')
+ >>> subs = registry.subscriptions([IR1], IP2)
+ >>> subs.sort()
+ >>> subs
+ ['sub12 1', 'sub12 2']
+
+You can register subscribers for all specifications using None::
+
+ >>> registry.subscribe([None], IP1, 'sub_1')
+ >>> subs = registry.subscriptions([IR2], IP1)
+ >>> subs.sort()
+ >>> subs
+ ['sub12 1', 'sub12 2', 'sub_1']
+
+Subscriptions may be combined over multiple compatible specifications::
+
+ >>> subs = registry.subscriptions([IR2], IP1)
+ >>> subs.sort()
+ >>> subs
+ ['sub12 1', 'sub12 2', 'sub_1']
+ >>> registry.subscribe([IR1], IP1, 'sub11')
+ >>> subs = registry.subscriptions([IR2], IP1)
+ >>> subs.sort()
+ >>> subs
+ ['sub11', 'sub12 1', 'sub12 2', 'sub_1']
+ >>> registry.subscribe([IR2], IP2, 'sub22')
+ >>> subs = registry.subscriptions([IR2], IP1)
+ >>> subs.sort()
+ >>> subs
+ ['sub11', 'sub12 1', 'sub12 2', 'sub22', 'sub_1']
+ >>> subs = registry.subscriptions([IR2], IP2)
+ >>> subs.sort()
+ >>> subs
+ ['sub12 1', 'sub12 2', 'sub22']
+
+Subscriptions can be on multiple specifications::
+
+ >>> registry.subscribe([IR1, IQ], IP2, 'sub1q2')
+ >>> registry.subscriptions([IR1, IQ], IP2)
+ ['sub1q2']
+
+As with single subscriptions and non-subscription adapters, you can
+specify None for the first required interface, to specify a default::
+
+ >>> registry.subscribe([None, IQ], IP2, 'sub_q2')
+ >>> registry.subscriptions([IS, IQ], IP2)
+ ['sub_q2']
+ >>> subs = registry.subscriptions([IR1, IQ], IP2)
+ >>> subs.sort()
+ >>> subs
+ ['sub1q2', 'sub_q2']
+
+You can have subscriptions that are indepenent of any specifications::
+
+ >>> registry.subscriptions([], IP1)
+ []
+
+ >>> registry.subscribe([], IP2, 'sub2')
+ >>> registry.subscriptions([], IP1)
+ ['sub2']
+ >>> registry.subscribe([], IP1, 'sub1')
+ >>> subs = registry.subscriptions([], IP1)
+ >>> subs.sort()
+ >>> subs
+ ['sub1', 'sub2']
+ >>> registry.subscriptions([], IP2)
+ ['sub2']
+
+Handlers
+--------
+
+A handler is a subscriber factory that doesn't produce any normal
+output. It returns None. A handler is unlike adapters in that it does
+all of it's work when the factory is called.
+
+To register a handler, simply provide None as the provided interface:
+
+ >>> def handler(event):
+ ... print 'handler', event
+
+ >>> registry.subscribe([IR1], None, handler)
+ >>> registry.subscriptions([IR1], None) == [handler]
+ True
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/advice.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/advice.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,192 @@ />
+##############################################################################
+#
+# Copyright (c) 2003 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.
+#
+##############################################################################
+"""Class advice.
+
+This module was adapted from 'protocols.advice', part of the Python
+Enterprise Application Kit (PEAK). Please notify the PEAK authors
+(pje@telecommunity.com and tsarna@sarna.org) if bugs are found or
+Zope-specific changes are required, so that the PEAK version of this module
+can be kept in sync.
+
+PEAK is a Python application framework that interoperates with (but does
+not require) Zope 3 and Twisted. It provides tools for manipulating UML
+models, object-relational persistence, aspect-oriented programming, and more.
+Visit the PEAK home page at http://peak.telecommunity.com for more information.
+
+$Id: advice.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+from types import ClassType, FunctionType
+import sys
+
+def getFrameInfo(frame):
+ """Return (kind,module,locals,globals) for a frame
+
+ 'kind' is one of "exec", "module", "class", "function call", or "unknown".
+ """
+
+ f_locals = frame.f_locals
+ f_globals = frame.f_globals
+
+ sameNamespace = f_locals is f_globals
+ hasModule = '__module__' in f_locals
+ hasName = '__name__' in f_globals
+
+ sameName = hasModule and hasName
+ sameName = sameName and f_globals['__name__']==f_locals['__module__']
+
+ module = hasName and sys.modules.get(f_globals['__name__']) or None
+
+ namespaceIsModule = module and module.__dict__ is f_globals
+
+ if not namespaceIsModule:
+ # some kind of funky exec
+ kind = "exec"
+ elif sameNamespace and not hasModule:
+ kind = "module"
+ elif sameName and not sameNamespace:
+ kind = "class"
+ elif not sameNamespace:
+ kind = "function call"
+ else:
+ # How can you have f_locals is f_globals, and have '__module__' set?
+ # This is probably module-level code, but with a '__module__' variable.
+ kind = "unknown"
+ return kind, module, f_locals, f_globals
+
+
+def addClassAdvisor(callback, depth=2):
+ """Set up 'callback' to be passed the containing class upon creation
+
+ This function is designed to be called by an "advising" function executed
+ in a class suite. The "advising" function supplies a callback that it
+ wishes to have executed when the containing class is created. The
+ callback will be given one argument: the newly created containing class.
+ The return value of the callback will be used in place of the class, so
+ the callback should return the input if it does not wish to replace the
+ class.
+
+ The optional 'depth' argument to this function determines the number of
+ frames between this function and the targeted class suite. 'depth'
+ defaults to 2, since this skips this function's frame and one calling
+ function frame. If you use this function from a function called directly
+ in the class suite, the default will be correct, otherwise you will need
+ to determine the correct depth yourself.
+
+ This function works by installing a special class factory function in
+ place of the '__metaclass__' of the containing class. Therefore, only
+ callbacks *after* the last '__metaclass__' assignment in the containing
+ class will be executed. Be sure that classes using "advising" functions
+ declare any '__metaclass__' *first*, to ensure all callbacks are run."""
+
+ frame = sys._getframe(depth)
+ kind, module, caller_locals, caller_globals = getFrameInfo(frame)
+
+ # This causes a problem when zope interfaces are used from doctest.
+ # In these cases, kind == "exec".
+ #
+ #if kind != "class":
+ # raise SyntaxError(
+ # "Advice must be in the body of a class statement"
+ # )
+
+ viousMetaclass = caller_locals.get('__metaclass__')
+ defaultMetaclass = caller_globals.get('__metaclass__', ClassType)
+
+
+ def advise(name, bases, cdict):
+
+ if '__metaclass__' in cdict:
+ del cdict['__metaclass__']
+
+ if viousMetaclass is None:
+ if bases:
+ # find best metaclass or use global __metaclass__ if no bases
+ meta = determineMetaclass(bases)
+ else:
+ meta = defaultMetaclass
+
+ elif isClassAdvisor(viousMetaclass):
+ # special case: we can't compute the "true" metaclass here,
+ # so we need to invoke the vious metaclass and let it
+ # figure it out for us (and apply its own advice in the process)
+ meta = viousMetaclass
+
+ else:
+ meta = determineMetaclass(bases, viousMetaclass)
+
+ newClass = meta(name,bases,cdict)
+
+ # this lets the callback replace the class completely, if it wants to
+ return callback(newClass)
+
+ # introspection data only, not used by inner function
+ advise.viousMetaclass = viousMetaclass
+ advise.callback = callback
+
+ # install the advisor
+ caller_locals['__metaclass__'] = advise
+
+
+def isClassAdvisor(ob):
+ """True if 'ob' is a class advisor function"""
+ return isinstance(ob,FunctionType) and hasattr(ob,'viousMetaclass')
+
+
+def determineMetaclass(bases, explicit_mc=None):
+ """Determine metaclass from 1+ bases and optional explicit __metaclass__"""
+
+ meta = [getattr(b,'__class__',type(b)) for b in bases]
+
+ if explicit_mc is not None:
+ # The explicit metaclass needs to be verified for compatibility
+ # as well, and allowed to resolve the incompatible bases, if any
+ meta.append(explicit_mc)
+
+ if len(meta)==1:
+ # easy case
+ return meta[0]
+
+ candidates = minimalBases(meta) # minimal set of metaclasses
+
+ if not candidates:
+ # they're all "classic" classes
+ return ClassType
+
+ elif len(candidates)>1:
+ # We could auto-combine, but for now we won't...
+ raise TypeError("Incompatible metatypes",bases)
+
+ # Just one, return it
+ return candidates[0]
+
+
+def minimalBases(classes):
+ """Reduce a list of base classes to its ordered minimum equivalent"""
+
+ classes = [c for c in classes if c is not ClassType]
+ candidates = []
+
+ for m in classes:
+ for n in classes:
+ if issubclass(n,m) and m is not n:
+ break
+ else:
+ # m has no subclasses in 'classes'
+ if m in candidates:
+ candidates.remove(m) # ensure that we're later in the list
+ candidates.append(m)
+
+ return candidates
+
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/__init__.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/__init__.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,2 @@ />
+#
+# This file is necessary to make this directory a package.
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/idatetime.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/idatetime.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,577 @@ />
+##############################################################################
+# Copyright (c) 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.
+##############################################################################
+"""Datetime interfaces.
+
+This module is called idatetime because if it were called datetime the import
+of the real datetime would fail.
+
+$Id: idatetime.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+from zope.interface import Interface, Attribute
+from zope.interface import classImplements, directlyProvides
+
+from datetime import timedelta, date, datetime, time, tzinfo
+
+
+class ITimeDeltaClass(Interface):
+ """This is the timedelta class interface."""
+
+ min = Attribute("The most negative timedelta object")
+
+ max = Attribute("The most positive timedelta object")
+
+ resolution = Attribute(
+ "The smallest difference between non-equal timedelta objects")
+
+
+class ITimeDelta(ITimeDeltaClass):
+ """Resent the difference between two datetime objects.
+
+ Supported operators:
+
+ - add, subtract timedelta
+ - unary plus, minus, abs
+ - compare to timedelta
+ - multiply, divide by int/long
+
+ In addition, datetime supports subtraction of two datetime objects
+ returning a timedelta, and addition or subtraction of a datetime
+ and a timedelta giving a datetime.
+
+ Resentation: (days, seconds, microseconds).
+ """
+
+ days = Attribute("Days between -999999999 and 999999999 inclusive")
+
+ seconds = Attribute("Seconds between 0 and 86399 inclusive")
+
+ microseconds = Attribute("Microseconds between 0 and 999999 inclusive")
+
+
+class IDateClass(Interface):
+ """This is the date class interface."""
+
+ min = Attribute("The earliest resentable date")
+
+ max = Attribute("The latest resentable date")
+
+ resolution = Attribute(
+ "The smallest difference between non-equal date objects")
+
+ def today():
+ """Return the current local time.
+
+ This is equivalent to date.fromtimestamp(time.time())"""
+
+ def fromtimestamp(timestamp):
+ """Return the local date from a POSIX timestamp (like time.time())
+
+ This may raise ValueError, if the timestamp is out of the range of
+ values supported by the platform C localtime() function. It's common
+ for this to be restricted to years from 1970 through 2038. Note that
+ on non-POSIX systems that include leap seconds in their notion of a
+ timestamp, leap seconds are ignored by fromtimestamp().
+ """
+
+ def fromordinal(ordinal):
+ """Return the date corresponding to the proleptic Gregorian ordinal.
+
+ January 1 of year 1 has ordinal 1. ValueError is raised unless
+ 1 <= ordinal <= date.max.toordinal().
+ For any date d, date.fromordinal(d.toordinal()) == d.
+ """
+
+
+class IDate(IDateClass):
+ """Resents a date (year, month and day) in an idealized calendar.
+
+ Operators:
+
+ __repr__, __str__
+ __cmp__, __hash__
+ __add__, __radd__, __sub__ (add/radd only with timedelta arg)
+ """
+
+ year = Attribute("Between MINYEAR and MAXYEAR inclusive.")
+
+ month = Attribute("Between 1 and 12 inclusive")
+
+ day = Attribute(
+ "Between 1 and the number of days in the given month of the given year.")
+
+ def replace(year, month, day):
+ """Return a date with the same value.
+
+ Except for those members given new values by whichever keyword
+ arguments are specified. For example, if d == date(2002, 12, 31), then
+ d.replace(day=26) == date(2000, 12, 26).
+ """
+
+ def timetuple():
+ """Return a 9-element tuple of the form returned by time.localtime().
+
+ The hours, minutes and seconds are 0, and the DST flag is -1.
+ d.timetuple() is equivalent to
+ (d.year, d.month, d.day, 0, 0, 0, d.weekday(), d.toordinal() -
+ date(d.year, 1, 1).toordinal() + 1, -1)
+ """
+
+ def toordinal():
+ """Return the proleptic Gregorian ordinal of the date
+
+ January 1 of year 1 has ordinal 1. For any date object d,
+ date.fromordinal(d.toordinal()) == d.
+ """
+
+ def weekday():
+ """Return the day of the week as an integer.
+
+ Monday is 0 and Sunday is 6. For example,
+ date(2002, 12, 4).weekday() == 2, a Wednesday.
+
+ See also isoweekday().
+ """
+
+ def isoweekday():
+ """Return the day of the week as an integer.
+
+ Monday is 1 and Sunday is 7. For example,
+ date(2002, 12, 4).isoweekday() == 3, a Wednesday.
+
+ See also weekday(), isocalendar().
+ """
+
+ def isocalendar():
+ """Return a 3-tuple, (ISO year, ISO week number, ISO weekday).
+
+ The ISO calendar is a widely used variant of the Gregorian calendar.
+ See http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm for a good
+ explanation.
+
+ The ISO year consists of 52 or 53 full weeks, and where a week starts
+ on a Monday and ends on a Sunday. The first week of an ISO year is the
+ first (Gregorian) calendar week of a year containing a Thursday. This
+ is called week number 1, and the ISO year of that Thursday is the same
+ as its Gregorian year.
+
+ For example, 2004 begins on a Thursday, so the first week of ISO year
+ 2004 begins on Monday, 29 Dec 2003 and ends on Sunday, 4 Jan 2004, so
+ that date(2003, 12, 29).isocalendar() == (2004, 1, 1) and
+ date(2004, 1, 4).isocalendar() == (2004, 1, 7).
+ """
+
+ def isoformat():
+ """Return a string resenting the date in ISO 8601 format.
+
+ This is 'YYYY-MM-DD'.
+ For example, date(2002, 12, 4).isoformat() == '2002-12-04'.
+ """
+
+ def __str__():
+ """For a date d, str(d) is equivalent to d.isoformat()."""
+
+ def ctime():
+ """Return a string resenting the date.
+
+ For example date(2002, 12, 4).ctime() == 'Wed Dec 4 00:00:00 2002'.
+ d.ctime() is equivalent to time.ctime(time.mktime(d.timetuple()))
+ on platforms where the native C ctime() function
+ (which time.ctime() invokes, but which date.ctime() does not invoke)
+ conforms to the C standard.
+ """
+
+ def strftime(format):
+ """Return a string resenting the date.
+
+ Controlled by an explicit format string. Format codes referring to
+ hours, minutes or seconds will see 0 values.
+ """
+
+
+class IDateTimeClass(Interface):
+ """This is the datetime class interface."""
+
+ min = Attribute("The earliest resentable datetime")
+
+ max = Attribute("The latest resentable datetime")
+
+ resolution = Attribute(
+ "The smallest possible difference between non-equal datetime objects")
+
+ def today():
+ """Return the current local datetime, with tzinfo None.
+
+ This is equivalent to datetime.fromtimestamp(time.time()).
+ See also now(), fromtimestamp().
+ """
+
+ def now(tz=None):
+ """Return the current local date and time.
+
+ If optional argument tz is None or not specified, this is like today(),
+ but, if possible, supplies more cision than can be gotten from going
+ through a time.time() timestamp (for example, this may be possible on
+ platforms supplying the C gettimeofday() function).
+
+ Else tz must be an instance of a class tzinfo subclass, and the current
+ date and time are converted to tz's time zone. In this case the result
+ is equivalent to tz.fromutc(datetime.utcnow().replace(tzinfo=tz)).
+
+ See also today(), utcnow().
+ """
+
+ def utcnow():
+ """Return the current UTC date and time, with tzinfo None.
+
+ This is like now(), but returns the current UTC date and time, as a
+ naive datetime object.
+
+ See also now().
+ """
+
+ def fromtimestamp(timestamp, tz=None):
+ """Return the local date and time corresponding to the POSIX timestamp.
+
+ Same as is returned by time.time(). If optional argument tz is None or
+ not specified, the timestamp is converted to the platform's local date
+ and time, and the returned datetime object is naive.
+
+ Else tz must be an instance of a class tzinfo subclass, and the
+ timestamp is converted to tz's time zone. In this case the result is
+ equivalent to
+ tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz)).
+
+ fromtimestamp() may raise ValueError, if the timestamp is out of the
+ range of values supported by the platform C localtime() or gmtime()
+ functions. It's common for this to be restricted to years in 1970
+ through 2038. Note that on non-POSIX systems that include leap seconds
+ in their notion of a timestamp, leap seconds are ignored by
+ fromtimestamp(), and then it's possible to have two timestamps
+ differing by a second that yield identical datetime objects.
+
+ See also utcfromtimestamp().
+ """
+
+ def utcfromtimestamp(timestamp):
+ """Return the UTC datetime from the POSIX timestamp with tzinfo None.
+
+ This may raise ValueError, if the timestamp is out of the range of
+ values supported by the platform C gmtime() function. It's common for
+ this to be restricted to years in 1970 through 2038.
+
+ See also fromtimestamp().
+ """
+
+ def fromordinal(ordinal):
+ """Return the datetime from the proleptic Gregorian ordinal.
+
+ January 1 of year 1 has ordinal 1. ValueError is raised unless
+ 1 <= ordinal <= datetime.max.toordinal().
+ The hour, minute, second and microsecond of the result are all 0, and
+ tzinfo is None.
+ """
+
+ def combine(date, time):
+ """Return a new datetime object.
+
+ Its date members are equal to the given date object's, and whose time
+ and tzinfo members are equal to the given time object's. For any
+ datetime object d, d == datetime.combine(d.date(), d.timetz()).
+ If date is a datetime object, its time and tzinfo members are ignored.
+ """
+
+
+class IDateTime(IDate, IDateTimeClass):
+ """Object contains all the information from a date object and a time object.
+ """
+
+ year = Attribute("Year between MINYEAR and MAXYEAR inclusive")
+
+ month = Attribute("Month between 1 and 12 inclusive")
+
+ day = Attribute(
+ "Day between 1 and the number of days in the given month of the year")
+
+ hour = Attribute("Hour in range(24)")
+
+ minute = Attribute("Minute in range(60)")
+
+ second = Attribute("Second in range(60)")
+
+ microsecond = Attribute("Microsecond in range(1000000)")
+
+ tzinfo = Attribute(
+ """The object passed as the tzinfo argument to the datetime constructor
+ or None if none was passed""")
+
+ def date():
+ """Return date object with same year, month and day."""
+
+ def time():
+ """Return time object with same hour, minute, second, microsecond.
+
+ tzinfo is None. See also method timetz().
+ """
+
+ def timetz():
+ """Return time object with same hour, minute, second, microsecond,
+ and tzinfo.
+
+ See also method time().
+ """
+
+ def replace(year, month, day, hour, minute, second, microsecond, tzinfo):
+ """Return a datetime with the same members, except for those members
+ given new values by whichever keyword arguments are specified.
+
+ Note that tzinfo=None can be specified to create a naive datetime from
+ an aware datetime with no conversion of date and time members.
+ """
+
+ def astimezone(tz):
+ """Return a datetime object with new tzinfo member tz, adjusting the
+ date and time members so the result is the same UTC time as self, but
+ in tz's local time.
+
+ tz must be an instance of a tzinfo subclass, and its utcoffset() and
+ dst() methods must not return None. self must be aware (self.tzinfo
+ must not be None, and self.utcoffset() must not return None).
+
+ If self.tzinfo is tz, self.astimezone(tz) is equal to self: no
+ adjustment of date or time members is performed. Else the result is
+ local time in time zone tz, resenting the same UTC time as self:
+ after astz = dt.astimezone(tz), astz - astz.utcoffset()
+ will usually have the same date and time members as dt - dt.utcoffset().
+ The discussion of class tzinfo explains the cases at Daylight Saving
+ Time transition boundaries where this cannot be achieved (an issue only
+ if tz models both standard and daylight time).
+
+ If you merely want to attach a time zone object tz to a datetime dt
+ without adjustment of date and time members, use dt.replace(tzinfo=tz).
+ If you merely want to remove the time zone object from an aware
+ datetime dt without conversion of date and time members, use
+ dt.replace(tzinfo=None).
+
+ Note that the default tzinfo.fromutc() method can be overridden in a
+ tzinfo subclass to effect the result returned by astimezone().
+ """
+
+ def utcoffset():
+ """Return the timezone offset in minutes east of UTC (negative west of
+ UTC)."""
+
+ def dst():
+ """Return 0 if DST is not in effect, or the DST offset (in minutes
+ eastward) if DST is in effect.
+ """
+
+ def tzname():
+ """Return the timezone name."""
+
+ def timetuple():
+ """Return a 9-element tuple of the form returned by time.localtime()."""
+
+ def utctimetuple():
+ """Return UTC time tuple compatilble with time.gmtimr()."""
+
+ def toordinal():
+ """Return the proleptic Gregorian ordinal of the date.
+
+ The same as self.date().toordinal().
+ """
+
+ def weekday():
+ """Return the day of the week as an integer.
+
+ Monday is 0 and Sunday is 6. The same as self.date().weekday().
+ See also isoweekday().
+ """
+
+ def isoweekday():
+ """Return the day of the week as an integer.
+
+ Monday is 1 and Sunday is 7. The same as self.date().isoweekday.
+ See also weekday(), isocalendar().
+ """
+
+ def isocalendar():
+ """Return a 3-tuple, (ISO year, ISO week number, ISO weekday).
+
+ The same as self.date().isocalendar().
+ """
+
+ def isoformat(sep='T'):
+ """Return a string resenting the date and time in ISO 8601 format.
+
+ YYYY-MM-DDTHH:MM:SS.mmmmmm or YYYY-MM-DDTHH:MM:SS if microsecond is 0
+
+ If utcoffset() does not return None, a 6-character string is appended,
+ giving the UTC offset in (signed) hours and minutes:
+
+ YYYY-MM-DDTHH:MM:SS.mmmmmm+HH:MM or YYYY-MM-DDTHH:MM:SS+HH:MM
+ if microsecond is 0.
+
+ The optional argument sep (default 'T') is a one-character separator,
+ placed between the date and time portions of the result.
+ """
+
+ def __str__():
+ """For a datetime instance d, str(d) is equivalent to d.isoformat(' ').
+ """
+
+ def ctime():
+ """Return a string resenting the date and time.
+
+ datetime(2002, 12, 4, 20, 30, 40).ctime() == 'Wed Dec 4 20:30:40 2002'.
+ d.ctime() is equivalent to time.ctime(time.mktime(d.timetuple())) on
+ platforms where the native C ctime() function (which time.ctime()
+ invokes, but which datetime.ctime() does not invoke) conforms to the
+ C standard.
+ """
+
+ def strftime(format):
+ """Return a string resenting the date and time.
+
+ This is controlled by an explicit format string.
+ """
+
+
+class ITimeClass(Interface):
+ """This is the time class interface."""
+
+ min = Attribute("The earliest resentable time")
+
+ max = Attribute("The latest resentable time")
+
+ resolution = Attribute(
+ "The smallest possible difference between non-equal time objects")
+
+
+class ITime(ITimeClass):
+ """Resent time with time zone.
+
+ Operators:
+
+ __repr__, __str__
+ __cmp__, __hash__
+ """
+
+ hour = Attribute("Hour in range(24)")
+
+ minute = Attribute("Minute in range(60)")
+
+ second = Attribute("Second in range(60)")
+
+ microsecond = Attribute("Microsecond in range(1000000)")
+
+ tzinfo = Attribute(
+ """The object passed as the tzinfo argument to the time constructor
+ or None if none was passed.""")
+
+ def replace(hour, minute, second, microsecond, tzinfo):
+ """Return a time with the same value.
+
+ Except for those members given new values by whichever keyword
+ arguments are specified. Note that tzinfo=None can be specified
+ to create a naive time from an aware time, without conversion of the
+ time members.
+ """
+
+ def isoformat():
+ """Return a string resenting the time in ISO 8601 format.
+
+ That is HH:MM:SS.mmmmmm or, if self.microsecond is 0, HH:MM:SS
+ If utcoffset() does not return None, a 6-character string is appended,
+ giving the UTC offset in (signed) hours and minutes:
+ HH:MM:SS.mmmmmm+HH:MM or, if self.microsecond is 0, HH:MM:SS+HH:MM
+ """
+
+ def __str__():
+ """For a time t, str(t) is equivalent to t.isoformat()."""
+
+ def strftime(format):
+ """Return a string resenting the time.
+
+ This is controlled by an explicit format string.
+ """
+
+ def utcoffset():
+ """Return the timezone offset in minutes east of UTC (negative west of
+ UTC).
+
+ If tzinfo is None, returns None, else returns
+ self.tzinfo.utcoffset(None), and raises an exception if the latter
+ doesn't return None or a timedelta object resenting a whole number
+ of minutes with magnitude less than one day.
+ """
+
+ def dst():
+ """Return 0 if DST is not in effect, or the DST offset (in minutes
+ eastward) if DST is in effect.
+
+ If tzinfo is None, returns None, else returns self.tzinfo.dst(None),
+ and raises an exception if the latter doesn't return None, or a
+ timedelta object resenting a whole number of minutes with
+ magnitude less than one day.
+ """
+
+ def tzname():
+ """Return the timezone name.
+
+ If tzinfo is None, returns None, else returns self.tzinfo.tzname(None),
+ or raises an exception if the latter doesn't return None or a string
+ object.
+ """
+
+
+class ITZInfo(Interface):
+ """Time zone info class.
+ """
+
+ def utcoffset(dt):
+ """Return offset of local time from UTC, in minutes east of UTC.
+
+ If local time is west of UTC, this should be negative.
+ Note that this is intended to be the total offset from UTC;
+ for example, if a tzinfo object resents both time zone and DST
+ adjustments, utcoffset() should return their sum. If the UTC offset
+ isn't known, return None. Else the value returned must be a timedelta
+ object specifying a whole number of minutes in the range -1439 to 1439
+ inclusive (1440 = 24*60; the magnitude of the offset must be less
+ than one day).
+ """
+
+ def dst(dt):
+ """Return the daylight saving time (DST) adjustment, in minutes east
+ of UTC, or None if DST information isn't known.
+ """
+
+ def tzname(dt):
+ """Return the time zone name corresponding to the datetime object as
+ a string.
+ """
+
+ def fromutc(dt):
+ """Return an equivalent datetime in self's local time."""
+
+
+classImplements(timedelta, ITimeDelta)
+classImplements(date, IDate)
+classImplements(datetime, IDateTime)
+classImplements(time, ITime)
+classImplements(tzinfo, ITZInfo)
+
+## directlyProvides(timedelta, ITimeDeltaClass)
+## directlyProvides(date, IDateClass)
+## directlyProvides(datetime, IDateTimeClass)
+## directlyProvides(time, ITimeClass)
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/interfaces.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/interfaces.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,98 @@ />
+##############################################################################
+#
+# Copyright (c) 2003 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.
+#
+##############################################################################
+"""Interfaces for standard python exceptions
+
+$Id: interfaces.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+from zope.interface import Interface
+from zope.interface import classImplements
+
+class IException(Interface): pass
+class IStandardError(IException): pass
+class IWarning(IException): pass
+class ISyntaxError(IStandardError): pass
+class ILookupError(IStandardError): pass
+class IValueError(IStandardError): pass
+class IRuntimeError(IStandardError): pass
+class IArithmeticError(IStandardError): pass
+class IAssertionError(IStandardError): pass
+class IAttributeError(IStandardError): pass
+class IDecationWarning(IWarning): pass
+class IEOFError(IStandardError): pass
+class IEnvironmentError(IStandardError): pass
+class IFloatingPointError(IArithmeticError): pass
+class IIOError(IEnvironmentError): pass
+class IImportError(IStandardError): pass
+class IIndentationError(ISyntaxError): pass
+class IIndexError(ILookupError): pass
+class IKeyError(ILookupError): pass
+class IKeyboardInterrupt(IStandardError): pass
+class IMemoryError(IStandardError): pass
+class INameError(IStandardError): pass
+class INotImplementedError(IRuntimeError): pass
+class IOSError(IEnvironmentError): pass
+class IOverflowError(IArithmeticError): pass
+class IOverflowWarning(IWarning): pass
+class IReferenceError(IStandardError): pass
+class IRuntimeWarning(IWarning): pass
+class IStopIteration(IException): pass
+class ISyntaxWarning(IWarning): pass
+class ISystemError(IStandardError): pass
+class ISystemExit(IException): pass
+class ITabError(IIndentationError): pass
+class ITypeError(IStandardError): pass
+class IUnboundLocalError(INameError): pass
+class IUnicodeError(IValueError): pass
+class IUserWarning(IWarning): pass
+class IZeroDivisionError(IArithmeticError): pass
+
+classImplements(ArithmeticError, IArithmeticError)
+classImplements(AssertionError, IAssertionError)
+classImplements(AttributeError, IAttributeError)
+classImplements(DecationWarning, IDecationWarning)
+classImplements(EnvironmentError, IEnvironmentError)
+classImplements(EOFError, IEOFError)
+classImplements(Exception, IException)
+classImplements(FloatingPointError, IFloatingPointError)
+classImplements(ImportError, IImportError)
+classImplements(IndentationError, IIndentationError)
+classImplements(IndexError, IIndexError)
+classImplements(IOError, IIOError)
+classImplements(KeyboardInterrupt, IKeyboardInterrupt)
+classImplements(KeyError, IKeyError)
+classImplements(LookupError, ILookupError)
+classImplements(MemoryError, IMemoryError)
+classImplements(NameError, INameError)
+classImplements(NotImplementedError, INotImplementedError)
+classImplements(OSError, IOSError)
+classImplements(OverflowError, IOverflowError)
+classImplements(OverflowWarning, IOverflowWarning)
+classImplements(ReferenceError, IReferenceError)
+classImplements(RuntimeError, IRuntimeError)
+classImplements(RuntimeWarning, IRuntimeWarning)
+classImplements(StandardError, IStandardError)
+classImplements(StopIteration, IStopIteration)
+classImplements(SyntaxError, ISyntaxError)
+classImplements(SyntaxWarning, ISyntaxWarning)
+classImplements(SystemError, ISystemError)
+classImplements(SystemExit, ISystemExit)
+classImplements(TabError, ITabError)
+classImplements(TypeError, ITypeError)
+classImplements(UnboundLocalError, IUnboundLocalError)
+classImplements(UnicodeError, IUnicodeError)
+classImplements(UserWarning, IUserWarning)
+classImplements(ValueError, IValueError)
+classImplements(Warning, IWarning)
+classImplements(ZeroDivisionError, IZeroDivisionError)
+
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/mapping.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/mapping.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,81 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Mapping Interfaces
+
+$Id: mapping.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+from zope.interface import Interface
+
+class IItemMapping(Interface):
+ """Simplest readable mapping object
+ """
+
+ def __getitem__(key):
+ """Get a value for a key
+
+ A KeyError is raised if there is no value for the key.
+ """
+
+
+class IReadMapping(IItemMapping):
+ """Basic mapping interface
+ """
+
+ def get(key, default=None):
+ """Get a value for a key
+
+ The default is returned if there is no value for the key.
+ """
+
+ def __contains__(key):
+ """Tell if a key exists in the mapping."""
+
+
+class IWriteMapping(Interface):
+ """Mapping methods for changing data"""
+
+ def __delitem__(key):
+ """Delete a value from the mapping using the key."""
+
+ def __setitem__(key, value):
+ """Set a new item in the mapping."""
+
+
+class IEnumerableMapping(IReadMapping):
+ """Mapping objects whose items can be enumerated.
+ """
+
+ def keys():
+ """Return the keys of the mapping object.
+ """
+
+ def __iter__():
+ """Return an iterator for the keys of the mapping object.
+ """
+
+ def values():
+ """Return the values of the mapping object.
+ """
+
+ def items():
+ """Return the items of the mapping object.
+ """
+
+ def __len__():
+ """Return the number of items.
+ """
+
+
+class IMapping(IReadMapping, IWriteMapping, IEnumerableMapping):
+ ''' Full mapping interface '''
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/tests/__init__.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/tests/__init__.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,2 @@ />
+#
+# This file is necessary to make this directory a package.
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/tests/basemapping.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/tests/basemapping.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,117 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id: basemapping.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+from operator import __getitem__
+
+def testIReadMapping(self, inst, state, absent):
+ for key in state:
+ self.assertEqual(inst[key], state[key])
+ self.assertEqual(inst.get(key, None), state[key])
+ self.failUnless(key in inst)
+
+ for key in absent:
+ self.assertEqual(inst.get(key, None), None)
+ self.assertEqual(inst.get(key), None)
+ self.assertEqual(inst.get(key, self), self)
+ self.assertRaises(KeyError, __getitem__, inst, key)
+
+
+def test_keys(self, inst, state):
+ # Return the keys of the mapping object
+ inst_keys = list(inst.keys()); inst_keys.sort()
+ state_keys = list(state.keys()) ; state_keys.sort()
+ self.assertEqual(inst_keys, state_keys)
+
+def test_iter(self, inst, state):
+ # Return the keys of the mapping object
+ inst_keys = list(inst); inst_keys.sort()
+ state_keys = list(state.keys()) ; state_keys.sort()
+ self.assertEqual(inst_keys, state_keys)
+
+def test_values(self, inst, state):
+ # Return the values of the mapping object
+ inst_values = list(inst.values()); inst_values.sort()
+ state_values = list(state.values()) ; state_values.sort()
+ self.assertEqual(inst_values, state_values)
+
+def test_items(self, inst, state):
+ # Return the items of the mapping object
+ inst_items = list(inst.items()); inst_items.sort()
+ state_items = list(state.items()) ; state_items.sort()
+ self.assertEqual(inst_items, state_items)
+
+def test___len__(self, inst, state):
+ # Return the number of items
+ self.assertEqual(len(inst), len(state))
+
+def testIEnumerableMapping(self, inst, state):
+ test_keys(self, inst, state)
+ test_items(self, inst, state)
+ test_values(self, inst, state)
+ test___len__(self, inst, state)
+
+
+class BaseTestIReadMapping:
+ def testIReadMapping(self):
+ inst = self._IReadMapping__sample()
+ state = self._IReadMapping__stateDict()
+ absent = self._IReadMapping__absentKeys()
+ testIReadMapping(self, inst, state, absent)
+
+
+class BaseTestIEnumerableMapping(BaseTestIReadMapping):
+ # Mapping objects whose items can be enumerated
+ def test_keys(self):
+ # Return the keys of the mapping object
+ inst = self._IEnumerableMapping__sample()
+ state = self._IEnumerableMapping__stateDict()
+ test_keys(self, inst, state)
+
+ def test_values(self):
+ # Return the values of the mapping object
+ inst = self._IEnumerableMapping__sample()
+ state = self._IEnumerableMapping__stateDict()
+ test_values(self, inst, state)
+
+ def test_values(self):
+ # Return the values of the mapping object
+ inst = self._IEnumerableMapping__sample()
+ state = self._IEnumerableMapping__stateDict()
+ test_iter(self, inst, state)
+
+ def test_items(self):
+ # Return the items of the mapping object
+ inst = self._IEnumerableMapping__sample()
+ state = self._IEnumerableMapping__stateDict()
+ test_items(self, inst, state)
+
+ def test___len__(self):
+ # Return the number of items
+ inst = self._IEnumerableMapping__sample()
+ state = self._IEnumerableMapping__stateDict()
+ test___len__(self, inst, state)
+
+ def _IReadMapping__stateDict(self):
+ return self._IEnumerableMapping__stateDict()
+
+ def _IReadMapping__sample(self):
+ return self._IEnumerableMapping__sample()
+
+ def _IReadMapping__absentKeys(self):
+ return self._IEnumerableMapping__absentKeys()
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/tests/test_idatetime.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/common/tests/test_idatetime.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,49 @@ />
+##############################################################################
+#
+# Copyright (c) 2003 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.
+#
+##############################################################################
+"""Test for datetime interfaces
+
+$Id: test_idatetime.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+import unittest
+
+from zope.interface.verify import verifyObject, verifyClass
+from zope.interface.common.idatetime import ITimeDelta, ITimeDeltaClass
+from zope.interface.common.idatetime import IDate, IDateClass
+from zope.interface.common.idatetime import IDateTime, IDateTimeClass
+from zope.interface.common.idatetime import ITime, ITimeClass, ITZInfo
+from datetime import timedelta, date, datetime, time, tzinfo
+
+class TestDateTimeInterfaces(unittest.TestCase):
+
+ def test_interfaces(self):
+ verifyObject(ITimeDelta, timedelta(minutes=20))
+ verifyObject(IDate, date(2000, 1, 2))
+ verifyObject(IDateTime, datetime(2000, 1, 2, 10, 20))
+ verifyObject(ITime, time(20, 30, 15, 1234))
+ verifyObject(ITZInfo, tzinfo())
+ verifyClass(ITimeDeltaClass, timedelta)
+ verifyClass(IDateClass, date)
+ verifyClass(IDateTimeClass, datetime)
+ verifyClass(ITimeClass, time)
+
+
+def test_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(TestDateTimeInterfaces))
+ return suite
+
+
+if __name__ == '__main__':
+ unittest.main()
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/declarations.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/declarations.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,1286 @@ />
+##############################################################################
+# Copyright (c) 2003 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.
+##############################################################################
+"""Implementation of interface declarations
+
+There are three flavors of declarations:
+
+ - Declarations are used to simply name declared interfaces.
+
+ - ImplementsDeclarations are used to exss the interfaces that a
+ class implements (that instances of the class provides).
+
+ Implements specifications support inheriting interfaces.
+
+ - ProvidesDeclarations are used to exss interfaces directly
+ provided by objects.
+
+
+$Id: declarations.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+import sys
+import weakref
+from zope.interface.interface import InterfaceClass, Specification
+from ro import mergeOrderings, ro
+import exceptions
+from types import ClassType
+from zope.interface.advice import addClassAdvisor
+
+# Registry of class-implementation specifications
+BuiltinImplementationSpecifications = {}
+
+
+__metaclass__ = type
+
+class Declaration(Specification):
+ """Interface declarations
+
+ """
+
+ def __init__(self, *interfaces):
+ Specification.__init__(self, _normalizeargs(interfaces))
+
+ def __contains__(self, interface):
+ """Test whether an interface is in the specification
+
+ for example::
+
+ >>> from zope.interface import Interface
+ >>> class I1(Interface): pass
+ ...
+ >>> class I2(I1): pass
+ ...
+ >>> class I3(Interface): pass
+ ...
+ >>> class I4(I3): pass
+ ...
+ >>> spec = Declaration(I2, I3)
+ >>> spec = Declaration(I4, spec)
+ >>> int(I1 in spec)
+ 0
+ >>> int(I2 in spec)
+ 1
+ >>> int(I3 in spec)
+ 1
+ >>> int(I4 in spec)
+ 1
+ """
+ return self.extends(interface) and interface in self.interfaces()
+
+ def __iter__(self):
+ """Return an iterator for the interfaces in the specification
+
+ for example::
+
+ >>> from zope.interface import Interface
+ >>> class I1(Interface): pass
+ ...
+ >>> class I2(I1): pass
+ ...
+ >>> class I3(Interface): pass
+ ...
+ >>> class I4(I3): pass
+ ...
+ >>> spec = Declaration(I2, I3)
+ >>> spec = Declaration(I4, spec)
+ >>> i = iter(spec)
+ >>> i.next().getName()
+ 'I4'
+ >>> i.next().getName()
+ 'I2'
+ >>> i.next().getName()
+ 'I3'
+ >>> list(i)
+ []
+ """
+ return self.interfaces()
+
+ def flattened(self):
+ """Return an iterator of all included and extended interfaces
+
+ for example::
+
+ >>> from zope.interface import Interface
+ >>> class I1(Interface): pass
+ ...
+ >>> class I2(I1): pass
+ ...
+ >>> class I3(Interface): pass
+ ...
+ >>> class I4(I3): pass
+ ...
+ >>> spec = Declaration(I2, I3)
+ >>> spec = Declaration(I4, spec)
+ >>> i = spec.flattened()
+ >>> i.next().getName()
+ 'I4'
+ >>> i.next().getName()
+ 'I2'
+ >>> i.next().getName()
+ 'I1'
+ >>> i.next().getName()
+ 'I3'
+ >>> i.next().getName()
+ 'Interface'
+ >>> list(i)
+ []
+
+ """
+ return iter(self.__iro__)
+
+ def __sub__(self, other):
+ """Remove interfaces from a specification
+
+ Examples::
+
+ >>> from zope.interface import Interface
+ >>> class I1(Interface): pass
+ ...
+ >>> class I2(I1): pass
+ ...
+ >>> class I3(Interface): pass
+ ...
+ >>> class I4(I3): pass
+ ...
+ >>> spec = Declaration()
+ >>> [iface.getName() for iface in spec]
+ []
+ >>> spec -= I1
+ >>> [iface.getName() for iface in spec]
+ []
+ >>> spec -= Declaration(I1, I2)
+ >>> [iface.getName() for iface in spec]
+ []
+ >>> spec = Declaration(I2, I4)
+ >>> [iface.getName() for iface in spec]
+ ['I2', 'I4']
+ >>> [iface.getName() for iface in spec - I4]
+ ['I2']
+ >>> [iface.getName() for iface in spec - I1]
+ ['I4']
+ >>> [iface.getName() for iface
+ ... in spec - Declaration(I3, I4)]
+ ['I2']
+
+ """
+
+ return Declaration(
+ *[i for i in self.interfaces()
+ if not [j for j in other.interfaces()
+ if i.extends(j, 0)]
+ ]
+ )
+
+ def __add__(self, other):
+ """Add two specifications or a specification and an interface
+
+
+ Examples::
+
+ >>> from zope.interface import Interface
+ >>> class I1(Interface): pass
+ ...
+ >>> class I2(I1): pass
+ ...
+ >>> class I3(Interface): pass
+ ...
+ >>> class I4(I3): pass
+ ...
+ >>> spec = Declaration()
+ >>> [iface.getName() for iface in spec]
+ []
+ >>> [iface.getName() for iface in spec+I1]
+ ['I1']
+ >>> [iface.getName() for iface in I1+spec]
+ ['I1']
+ >>> spec2 = spec
+ >>> spec += I1
+ >>> [iface.getName() for iface in spec]
+ ['I1']
+ >>> [iface.getName() for iface in spec2]
+ []
+ >>> spec2 += Declaration(I3, I4)
+ >>> [iface.getName() for iface in spec2]
+ ['I3', 'I4']
+ >>> [iface.getName() for iface in spec+spec2]
+ ['I1', 'I3', 'I4']
+ >>> [iface.getName() for iface in spec2+spec]
+ ['I3', 'I4', 'I1']
+
+ """
+
+ seen = {}
+ result = []
+ for i in self.interfaces():
+ if i not in seen:
+ seen[i] = 1
+ result.append(i)
+ for i in other.interfaces():
+ if i not in seen:
+ seen[i] = 1
+ result.append(i)
+
+ return Declaration(*result)
+
+ __radd__ = __add__
+
+ def __nonzero__(self):
+ """Test whether there are any interfaces in a specification.
+
+ >>> from zope.interface import Interface
+ >>> class I1(Interface): pass
+ ...
+ >>> spec = Declaration(I1)
+ >>> int(bool(spec))
+ 1
+ >>> spec = Declaration()
+ >>> int(bool(spec))
+ 0
+ """
+ return bool(self.__iro__)
+
+
+##############################################################################
+#
+# Implementation specifications
+#
+# These specify interfaces implemented by instances of classes
+
+class Implements(Declaration):
+ inherit = None
+ declared = ()
+ __name__ = '?'
+
+ def __repr__(self):
+ return '<implementedBy %s>' % (self.__name__)
+
+
+
+def implementedByFallback(cls):
+ """Return the interfaces implemented for a class' instances
+
+ The value returned is an IDeclaration.
+
+ for example:
+
+ >>> from zope.interface import Interface
+ >>> class I1(Interface): pass
+ ...
+ >>> class I2(I1): pass
+ ...
+ >>> class I3(Interface): pass
+ ...
+ >>> class I4(I3): pass
+ ...
+ >>> class C1:
+ ... implements(I2)
+ >>> class C2(C1):
+ ... implements(I3)
+ >>> [i.getName() for i in implementedBy(C2)]
+ ['I3', 'I2']
+ """
+
+ # This also manages storage of implementation specifications
+
+ try:
+ spec = cls.__dict__.get('__implemented__')
+ except AttributeError:
+
+ # we can't get the class dict. This is probably due to a
+ # security proxy. If this is the case, then probably no
+ # descriptor was installed for the class.
+
+ # We don't want to depend directly on zope.secury in
+ # zope.interface, but we'll try to make reasonable
+ # accommodations in an indirect way.
+
+ # We'll check to see if there's an implements:
+
+ spec = getattr(cls, '__implemented__', None)
+ if spec is None:
+ return _empty
+ if spec.__class__ == Implements:
+ # we defaulted to _empty or there was a spec. Good enough.
+ # Return it.
+ return spec
+
+ # XXX need old style __implements__ compatibility?
+ # Hm, there's an __implemented__, but it's not a spec. Must be
+ # an old-style declaration. Just compute a spec for it
+ return Declaration(*_normalizeargs((spec, )))
+
+ if isinstance(spec, Implements):
+ return spec
+
+ if spec is None:
+ spec = BuiltinImplementationSpecifications.get(cls)
+ if spec is not None:
+ return spec
+
+ # XXX need old style __implements__ comptability?
+ if spec is not None:
+ # old-style __implemented__ = foo declaration
+ spec = (spec, ) # tuplefy, as it might be just an int
+ spec = Implements(*_normalizeargs(spec))
+ spec.inherit = None # old-style implies no inherit
+ del cls.__implemented__ # get rid of the old-style declaration
+ else:
+ try:
+ bases = cls.__bases__
+ except AttributeError:
+ raise TypeError("ImplementedBy called for non-type", cls)
+
+ spec = Implements(*[implementedBy(c) for c in bases])
+ spec.inherit = cls
+
+ spec.__name__ = getattr(cls, '__module__', '?') + '.' + cls.__name__
+
+ try:
+ cls.__implemented__ = spec
+ if not hasattr(cls, '__providedBy__'):
+ cls.__providedBy__ = objectSpecificationDescriptor
+
+ if (isinstance(cls, DescriptorAwareMetaClasses)
+ and
+ '__provides__' not in cls.__dict__):
+ # Make sure we get a __provides__ descriptor
+ cls.__provides__ = ClassProvides(
+ cls,
+ getattr(cls, '__class__', type(cls)),
+ )
+
+ except TypeError:
+ if not isinstance(cls, type):
+ raise TypeError("ImplementedBy called for non-type", cls)
+ BuiltinImplementationSpecifications[cls] = spec
+
+ return spec
+
+implementedBy = implementedByFallback
+
+def classImplementsOnly(cls, *interfaces):
+ """Declare the only interfaces implemented by instances of a class
+
+ The arguments after the class are one or more interfaces or
+ interface specifications (IDeclaration objects).
+
+ The interfaces given (including the interfaces in the
+ specifications) replace any vious declarations.
+
+ Consider the following example::
+
+ >>> from zope.interface import Interface
+ >>> class I1(Interface): pass
+ ...
+ >>> class I2(Interface): pass
+ ...
+ >>> class I3(Interface): pass
+ ...
+ >>> class I4(Interface): pass
+ ...
+ >>> class A:
+ ... implements(I3)
+ >>> class B:
+ ... implements(I4)
+ >>> class C(A, B):
+ ... pass
+ >>> classImplementsOnly(C, I1, I2)
+ >>> [i.getName() for i in implementedBy(C)]
+ ['I1', 'I2']
+
+ Instances of ``C`` provide only ``I1``, ``I2``, and regardless of
+ whatever interfaces instances of ``A`` and ``B`` implement.
+
+ """
+ spec = implementedBy(cls)
+ spec.__bases__ = tuple(_normalizeargs(interfaces))
+ spec.inherit = None
+
+def classImplements(cls, *interfaces):
+ """Declare additional interfaces implemented for instances of a class
+
+ The arguments after the class are one or more interfaces or
+ interface specifications (IDeclaration objects).
+
+ The interfaces given (including the interfaces in the
+ specifications) are added to any interfaces viously
+ declared.
+
+ Consider the following example::
+
+
+ for example:
+
+ >>> from zope.interface import Interface
+ >>> class I1(Interface): pass
+ ...
+ >>> class I2(Interface): pass
+ ...
+ >>> class I3(Interface): pass
+ ...
+ >>> class I4(Interface): pass
+ ...
+ >>> class I5(Interface): pass
+ ...
+ >>> class A:
+ ... implements(I3)
+ >>> class B:
+ ... implements(I4)
+ >>> class C(A, B):
+ ... pass
+ >>> classImplements(C, I1, I2)
+ >>> [i.getName() for i in implementedBy(C)]
+ ['I1', 'I2', 'I3', 'I4']
+ >>> classImplements(C, I5)
+ >>> [i.getName() for i in implementedBy(C)]
+ ['I1', 'I2', 'I5', 'I3', 'I4']
+
+ Instances of ``C`` provide ``I1``, ``I2``, ``I5``, and whatever
+ interfaces instances of ``A`` and ``B`` provide.
+
+ """
+
+ spec = implementedBy(cls)
+ spec.declared += tuple(_normalizeargs(interfaces))
+
+ # compute the bases
+ bases = []
+ seen = {}
+ for b in spec.declared:
+ if b not in seen:
+ seen[b] = 1
+ bases.append(b)
+
+ if spec.inherit is not None:
+
+ for c in spec.inherit.__bases__:
+ b = implementedBy(c)
+ if b not in seen:
+ seen[b] = 1
+ bases.append(b)
+
+ spec.__bases__ = bases
+
+def _implements_advice(cls):
+ interfaces, classImplements = cls.__dict__['__implements_advice_data__']
+ del cls.__implements_advice_data__
+ classImplements(cls, *interfaces)
+ return cls
+
+def _implements(name, interfaces, classImplements):
+ frame = sys._getframe(2)
+ locals = frame.f_locals
+
+ # Try to make sure we were called from a class def
+ if (locals is frame.f_globals) or ('__module__' not in locals):
+ raise TypeError(name+" can be used only from a class definition.")
+
+ if '__implements_advice_data__' in locals:
+ raise TypeError(name+" can be used only once in a class definition.")
+
+ locals['__implements_advice_data__'] = interfaces, classImplements
+ addClassAdvisor(_implements_advice, depth=3)
+
+def implements(*interfaces):
+ """Declare interfaces implemented by instances of a class
+
+ This function is called in a class definition.
+
+ The arguments are one or more interfaces or interface
+ specifications (IDeclaration objects).
+
+ The interfaces given (including the interfaces in the
+ specifications) are added to any interfaces viously
+ declared.
+
+ Previous declarations include declarations for base classes
+ unless implementsOnly was used.
+
+ This function is provided for convenience. It provides a more
+ convenient way to call classImplements. For example::
+
+ implements(I1)
+
+ is equivalent to calling::
+
+ classImplements(C, I1)
+
+ after the class has been created.
+
+ Consider the following example::
+
+
+ >>> from zope.interface import Interface
+ >>> class IA1(Interface): pass
+ ...
+ >>> class IA2(Interface): pass
+ ...
+ >>> class IB(Interface): pass
+ ...
+ >>> class IC(Interface): pass
+ ...
+ >>> class A: implements(IA1, IA2)
+ ...
+ >>> class B: implements(IB)
+ ...
+
+ >>> class C(A, B):
+ ... implements(IC)
+
+ >>> ob = C()
+ >>> int(IA1 in providedBy(ob))
+ 1
+ >>> int(IA2 in providedBy(ob))
+ 1
+ >>> int(IB in providedBy(ob))
+ 1
+ >>> int(IC in providedBy(ob))
+ 1
+
+ Instances of ``C`` implement ``I1``, ``I2``, and whatever interfaces
+ instances of ``A`` and ``B`` implement.
+
+ """
+ _implements("implements", interfaces, classImplements)
+
+def implementsOnly(*interfaces):
+ """Declare the only interfaces implemented by instances of a class
+
+ This function is called in a class definition.
+
+ The arguments are one or more interfaces or interface
+ specifications (IDeclaration objects).
+
+ Previous declarations including declarations for base classes
+ are overridden.
+
+ This function is provided for convenience. It provides a more
+ convenient way to call classImplementsOnly. For example::
+
+ implementsOnly(I1)
+
+ is equivalent to calling::
+
+ classImplementsOnly(I1)
+
+ after the class has been created.
+
+ Consider the following example::
+
+ >>> from zope.interface import Interface
+ >>> class IA1(Interface): pass
+ ...
+ >>> class IA2(Interface): pass
+ ...
+ >>> class IB(Interface): pass
+ ...
+ >>> class IC(Interface): pass
+ ...
+ >>> class A: implements(IA1, IA2)
+ ...
+ >>> class B: implements(IB)
+ ...
+
+ >>> class C(A, B):
+ ... implementsOnly(IC)
+
+ >>> ob = C()
+ >>> int(IA1 in providedBy(ob))
+ 0
+ >>> int(IA2 in providedBy(ob))
+ 0
+ >>> int(IB in providedBy(ob))
+ 0
+ >>> int(IC in providedBy(ob))
+ 1
+
+
+ Instances of ``C`` implement ``IC``, regardless of what
+ instances of ``A`` and ``B`` implement.
+
+ """
+ _implements("implementsOnly", interfaces, classImplementsOnly)
+
+##############################################################################
+#
+# Instance declarations
+
+class Provides(Declaration): # Really named ProvidesClass
+ """Implement __provides__, the instance-specific specification
+
+ When an object is pickled, we pickle the interfaces that it implements.
+ """
+
+ def __init__(self, cls, *interfaces):
+ self.__args = (cls, ) + interfaces
+ self._cls = cls
+ Declaration.__init__(self, *(interfaces + (implementedBy(cls), )))
+
+ def __reduce__(self):
+ return Provides, self.__args
+
+ __module__ = 'zope.interface'
+
+ def __get__(self, inst, cls):
+ """Make sure that a class __provides__ doesn't leak to an instance
+
+ For example::
+
+ >>> from zope.interface import Interface
+ >>> class IFooFactory(Interface): pass
+ ...
+
+ >>> class C:
+ ... pass
+
+ >>> C.__provides__ = ProvidesClass(C, IFooFactory)
+ >>> [i.getName() for i in C.__provides__]
+ ['IFooFactory']
+ >>> getattr(C(), '__provides__', 0)
+ 0
+
+ """
+ if inst is None and cls is self._cls:
+ # We were accessed through a class, so we are the class'
+ # provides spec. Just return this object, but only if we are
+ # being called on the same class that we were defined for:
+ return self
+
+ raise AttributeError, '__provides__'
+
+ProvidesClass = Provides
+
+# Registry of instance declarations
+# This is a memory optimization to allow objects to share specifications.
+InstanceDeclarations = weakref.WeakValueDictionary()
+
+def Provides(*interfaces):
+ """Cache instance declarations
+
+ Instance declarations are shared among instances that have the
+ same declaration. The declarations are cached in an weak value
+ dictionary.
+
+ (Note that, in the examples below, we are going to make
+ assertions about the size of the weakvalue dictionary. For the
+ assertions to be meaningful, we need to force garbage
+ collection to make sure garbage objects are, indeed, removed
+ from the system. Depending on how Python is run, we may need to
+ make multiple calls to be sure. We provide a collect function
+ to help with this:
+
+ >>> import gc
+ >>> def collect():
+ ... for i in range(4):
+ ... gc.collect()
+
+ )
+
+ >>> collect()
+ >>> before = len(InstanceDeclarations)
+
+ >>> class C:
+ ... pass
+
+ >>> from zope.interface import Interface
+ >>> class I(Interface):
+ ... pass
+
+ >>> c1 = C()
+ >>> c2 = C()
+
+ >>> len(InstanceDeclarations) == before
+ 1
+
+ >>> directlyProvides(c1, I)
+ >>> len(InstanceDeclarations) == before + 1
+ 1
+
+ >>> directlyProvides(c2, I)
+ >>> len(InstanceDeclarations) == before + 1
+ 1
+
+ >>> del c1
+ >>> collect()
+ >>> len(InstanceDeclarations) == before + 1
+ 1
+
+ >>> del c2
+ >>> collect()
+ >>> len(InstanceDeclarations) == before
+ 1
+
+ """
+
+ spec = InstanceDeclarations.get(interfaces)
+ if spec is None:
+ spec = ProvidesClass(*interfaces)
+ InstanceDeclarations[interfaces] = spec
+
+ return spec
+Provides.__safe_for_unpickling__ = True
+
+
+DescriptorAwareMetaClasses = ClassType, type
+def directlyProvides(object, *interfaces):
+ """Declare interfaces declared directly for an object
+
+ The arguments after the object are one or more interfaces or
+ interface specifications (IDeclaration objects).
+
+ The interfaces given (including the interfaces in the
+ specifications) replace interfaces viously
+ declared for the object.
+
+ Consider the following example::
+
+ >>> from zope.interface import Interface
+ >>> class I1(Interface): pass
+ ...
+ >>> class I2(Interface): pass
+ ...
+ >>> class IA1(Interface): pass
+ ...
+ >>> class IA2(Interface): pass
+ ...
+ >>> class IB(Interface): pass
+ ...
+ >>> class IC(Interface): pass
+ ...
+ >>> class A: implements(IA1, IA2)
+ ...
+ >>> class B: implements(IB)
+ ...
+
+ >>> class C(A, B):
+ ... implements(IC)
+
+ >>> ob = C()
+ >>> directlyProvides(ob, I1, I2)
+ >>> int(I1 in providedBy(ob))
+ 1
+ >>> int(I2 in providedBy(ob))
+ 1
+ >>> int(IA1 in providedBy(ob))
+ 1
+ >>> int(IA2 in providedBy(ob))
+ 1
+ >>> int(IB in providedBy(ob))
+ 1
+ >>> int(IC in providedBy(ob))
+ 1
+
+ The object, ``ob`` provides ``I1``, ``I2``, and whatever interfaces
+ instances have been declared for instances of ``C``.
+
+ To remove directly provided interfaces, use ``directlyProvidedBy`` and
+ subtract the unwanted interfaces. For example::
+
+ >>> directlyProvides(ob, directlyProvidedBy(ob)-I2)
+ >>> int(I1 in providedBy(ob))
+ 1
+ >>> int(I2 in providedBy(ob))
+ 0
+
+ removes I2 from the interfaces directly provided by
+ ``ob``. The object, ``ob`` no longer directly provides ``I2``,
+ although it might still provide ``I2`` if it's class
+ implements ``I2``.
+
+ To add directly provided interfaces, use ``directlyProvidedBy`` and
+ include additional interfaces. For example::
+
+ >>> int(I2 in providedBy(ob))
+ 0
+ >>> directlyProvides(ob, directlyProvidedBy(ob), I2)
+
+ adds I2 to the interfaces directly provided by ob::
+
+ >>> int(I2 in providedBy(ob))
+ 1
+
+ """
+
+ # We need to avoid setting this attribute on meta classes that
+ # don't support descriptors.
+ # We can do away with this check when we get rid of the old EC
+ cls = getattr(object, '__class__', None)
+ if cls is not None and getattr(cls, '__class__', None) is cls:
+ # It's a meta class (well, at least it it could be an extension class)
+ if not isinstance(object, DescriptorAwareMetaClasses):
+ raise TypeError("Attempt to make an interface declaration on a "
+ "non-descriptor-aware class")
+
+ interfaces = _normalizeargs(interfaces)
+ if cls is None:
+ cls = type(object)
+
+ issub = False
+ for damc in DescriptorAwareMetaClasses:
+ if issubclass(cls, damc):
+ issub = True
+ break
+ if issub:
+ # we have a class or type. We'll use a special descriptor
+ # that provides some extra caching
+ object.__provides__ = ClassProvides(object, cls, *interfaces)
+ else:
+ object.__provides__ = Provides(cls, *interfaces)
+
+
+class ClassProvidesBasePy(object):
+
+ def __get__(self, inst, cls):
+ if cls is self._cls:
+ # We only work if called on the class we were defined for
+
+ if inst is None:
+ # We were accessed through a class, so we are the class'
+ # provides spec. Just return this object as is:
+ return self
+
+ return self._implements
+
+ raise AttributeError, '__provides__'
+
+ClassProvidesBase = ClassProvidesBasePy
+
+# Try to get C base:
+try:
+ import _zope_interface_coptimizations
+except ImportError:
+ pass
+else:
+ from _zope_interface_coptimizations import ClassProvidesBase
+
+
+class ClassProvides(Declaration, ClassProvidesBase):
+ """Special descriptor for class __provides__
+
+ The descriptor caches the implementedBy info, so that
+ we can get declarations for objects without instance-specific
+ interfaces a bit quicker.
+
+ For example::
+
+ >>> from zope.interface import Interface
+ >>> class IFooFactory(Interface):
+ ... pass
+ >>> class IFoo(Interface):
+ ... pass
+ >>> class C:
+ ... implements(IFoo)
+ ... classProvides(IFooFactory)
+ >>> [i.getName() for i in C.__provides__]
+ ['IFooFactory']
+
+ >>> [i.getName() for i in C().__provides__]
+ ['IFoo']
+
+
+ """
+
+ def __init__(self, cls, metacls, *interfaces):
+ self._cls = cls
+ self._implements = implementedBy(cls)
+ self.__args = (cls, metacls, ) + interfaces
+ Declaration.__init__(self, *(interfaces + (implementedBy(metacls), )))
+
+ def __reduce__(self):
+ return self.__class__, self.__args
+
+ # Copy base-class method for speed
+ __get__ = ClassProvidesBase.__get__
+
+def directlyProvidedBy(object):
+ """Return the interfaces directly provided by the given object
+
+ The value returned is an IDeclaration.
+
+ """
+ provides = getattr(object, "__provides__", None)
+ if (provides is None # no spec
+ or
+ # We might have gotten the implements spec, as an
+ # optimization. If so, it's like having only one base, that we
+ # lop off to exclude class-supplied declarations:
+ isinstance(provides, Implements)
+ ):
+ return _empty
+
+ # Strip off the class part of the spec:
+ return Declaration(provides.__bases__[:-1])
+
+def classProvides(*interfaces):
+ """Declare interfaces provided directly by a class
+
+ This function is called in a class definition.
+
+ The arguments are one or more interfaces or interface
+ specifications (IDeclaration objects).
+
+ The given interfaces (including the interfaces in the
+ specifications) are used to create the class's direct-object
+ interface specification. An error will be raised if the module
+ class has an direct interface specification. In other words, it is
+ an error to call this function more than once in a class
+ definition.
+
+ Note that the given interfaces have nothing to do with the
+ interfaces implemented by instances of the class.
+
+ This function is provided for convenience. It provides a more
+ convenient way to call directlyProvidedByProvides for a class. For
+ example::
+
+ classProvides(I1)
+
+ is equivalent to calling::
+
+ directlyProvides(theclass, I1)
+
+ after the class has been created.
+
+ For example::
+
+ >>> from zope.interface import Interface
+ >>> class IFoo(Interface): pass
+ ...
+ >>> class IFooFactory(Interface): pass
+ ...
+ >>> class C:
+ ... implements(IFoo)
+ ... classProvides(IFooFactory)
+ >>> [i.getName() for i in C.__providedBy__]
+ ['IFooFactory']
+ >>> [i.getName() for i in C().__providedBy__]
+ ['IFoo']
+
+ if equivalent to::
+
+ >>> from zope.interface import Interface
+ >>> class IFoo(Interface): pass
+ ...
+ >>> class IFooFactory(Interface): pass
+ ...
+ >>> class C:
+ ... implements(IFoo)
+ >>> directlyProvides(C, IFooFactory)
+ >>> [i.getName() for i in C.__providedBy__]
+ ['IFooFactory']
+ >>> [i.getName() for i in C().__providedBy__]
+ ['IFoo']
+
+
+ """
+ frame = sys._getframe(1)
+ locals = frame.f_locals
+
+ # Try to make sure we were called from a class def
+ if (locals is frame.f_globals) or ('__module__' not in locals):
+ raise TypeError(name+" can be used only from a class definition.")
+
+ if '__provides__' in locals:
+ raise TypeError(
+ "classProvides can only be used once in a class definition.")
+
+ locals["__provides__"] = _normalizeargs(interfaces)
+
+ addClassAdvisor(_classProvides_advice, depth=2)
+
+def _classProvides_advice(cls):
+ interfaces = cls.__dict__['__provides__']
+ del cls.__provides__
+ directlyProvides(cls, *interfaces)
+ return cls
+
+def moduleProvides(*interfaces):
+ """Declare interfaces provided by a module
+
+ This function is used in a module definition.
+
+ The arguments are one or more interfaces or interface
+ specifications (IDeclaration objects).
+
+ The given interfaces (including the interfaces in the
+ specifications) are used to create the module's direct-object
+ interface specification. An error will be raised if the module
+ already has an interface specification. In other words, it is
+ an error to call this function more than once in a module
+ definition.
+
+ This function is provided for convenience. It provides a more
+ convenient way to call directlyProvides. For example::
+
+ moduleImplements(I1)
+
+ is equivalent to::
+
+ directlyProvides(sys.modules[__name__], I1)
+
+ """
+ frame = sys._getframe(1)
+ locals = frame.f_locals
+
+ # Try to make sure we were called from a class def
+ if (locals is not frame.f_globals) or ('__name__' not in locals):
+ raise TypeError(
+ "moduleProvides can only be used from a module definition.")
+
+ if '__provides__' in locals:
+ raise TypeError(
+ "moduleProvides can only be used once in a module definition.")
+
+ module = sys.modules[__name__]
+
+ locals["__provides__"] = Provides(type(module),
+ *_normalizeargs(interfaces))
+
+##############################################################################
+#
+# Declaration querying support
+
+def ObjectSpecification(direct, cls):
+ """Provide object specifications
+
+ These combine information for the object and for it's classes.
+
+ For example::
+
+ >>> from zope.interface import Interface
+ >>> class I1(Interface): pass
+ ...
+ >>> class I2(Interface): pass
+ ...
+ >>> class I3(Interface): pass
+ ...
+ >>> class I31(I3): pass
+ ...
+ >>> class I4(Interface): pass
+ ...
+ >>> class I5(Interface): pass
+ ...
+ >>> class A: implements(I1)
+ ...
+ >>> class B: __implemented__ = I2
+ ...
+ >>> class C(A, B): implements(I31)
+ ...
+ >>> c = C()
+ >>> directlyProvides(c, I4)
+ >>> [i.getName() for i in providedBy(c)]
+ ['I4', 'I31', 'I1', 'I2']
+ >>> [i.getName() for i in providedBy(c).flattened()]
+ ['I4', 'I31', 'I3', 'I1', 'I2', 'Interface']
+ >>> int(I1 in providedBy(c))
+ 1
+ >>> int(I3 in providedBy(c))
+ 0
+ >>> int(providedBy(c).extends(I3))
+ 1
+ >>> int(providedBy(c).extends(I31))
+ 1
+ >>> int(providedBy(c).extends(I5))
+ 0
+ >>> class COnly(A, B): implementsOnly(I31)
+ ...
+ >>> class D(COnly): implements(I5)
+ ...
+ >>> c = D()
+ >>> directlyProvides(c, I4)
+ >>> [i.getName() for i in providedBy(c)]
+ ['I4', 'I5', 'I31']
+ >>> [i.getName() for i in providedBy(c).flattened()]
+ ['I4', 'I5', 'I31', 'I3', 'Interface']
+ >>> int(I1 in providedBy(c))
+ 0
+ >>> int(I3 in providedBy(c))
+ 0
+ >>> int(providedBy(c).extends(I3))
+ 1
+ >>> int(providedBy(c).extends(I1))
+ 0
+ >>> int(providedBy(c).extends(I31))
+ 1
+ >>> int(providedBy(c).extends(I5))
+ 1
+
+
+ nonzero:
+
+ >>> from zope.interface import Interface
+ >>> class I1(Interface):
+ ... pass
+ >>> class I2(Interface):
+ ... pass
+ >>> class C:
+ ... implements(I1)
+ >>> c = C()
+ >>> int(bool(providedBy(c)))
+ 1
+ >>> directlyProvides(c, I2)
+ >>> int(bool(providedBy(c)))
+ 1
+ >>> class C:
+ ... pass
+ >>> c = C()
+ >>> int(bool(providedBy(c)))
+ 0
+ >>> directlyProvides(c, I2)
+ >>> int(bool(providedBy(c)))
+ 1
+
+
+ """
+
+ return Provides(cls, direct)
+
+def getObjectSpecification(ob):
+
+ provides = getattr(ob, '__provides__', None)
+ if provides is not None:
+ return provides
+
+ try:
+ cls = ob.__class__
+ except AttributeError:
+ # We can't get the class, so just consider provides
+ return _empty
+
+ return implementedBy(cls)
+
+def providedBy(ob):
+
+ # Here we have either a special object, an old-style declaration
+ # or a descriptor
+
+ # Try to get __providedBy__
+ try:
+ r = ob.__providedBy__
+ except AttributeError:
+ # Not set yet. Fall back to lower-level thing that computes it
+ return getObjectSpecification(ob)
+
+
+ try:
+ # We might have gotten a descriptor from an instance of a
+ # class (like an ExtensionClass) that doesn't support
+ # descriptors. We'll make sure we got one by trying to get
+ # the only attribute, which all specs have.
+ r.extends
+
+ except AttributeError:
+
+ # The object's class doesn't understand descriptors.
+ # Sigh. We need to get an object descriptor, but we have to be
+ # careful. We want to use the instance's __provides__,l if
+ # there is one, but only if it didn't come from the class.
+
+ try:
+ r = ob.__provides__
+ except AttributeError:
+ # No __provides__, so just fall back to implementedBy
+ return implementedBy(ob.__class__)
+
+ # We need to make sure we got the __provides__ from the
+ # instance. We'll do this by making sure we don't get the same
+ # thing from the class:
+
+ try:
+ cp = ob.__class__.__provides__
+ except AttributeError:
+ # The ob doesn't have a class or the class has no
+ # provides, assume we're done:
+ return r
+
+ if r is cp:
+ # Oops, we got the provides from the class. This means
+ # the object doesn't have it's own. We should use implementedBy
+ return implementedBy(ob.__class__)
+
+ return r
+
+class ObjectSpecificationDescriptorPy(object):
+ """Implement the __providedBy__ attribute
+
+ The __providedBy__ attribute computes the interfaces peovided by
+ an object.
+ """
+
+ def __get__(self, inst, cls):
+ """Get an object specification for an object
+
+ For example::
+
+ >>> from zope.interface import Interface
+ >>> class IFoo(Interface): pass
+ ...
+ >>> class IFooFactory(Interface): pass
+ ...
+ >>> class C:
+ ... implements(IFoo)
+ ... classProvides(IFooFactory)
+ >>> [i.getName() for i in C.__providedBy__]
+ ['IFooFactory']
+ >>> [i.getName() for i in C().__providedBy__]
+ ['IFoo']
+
+ """
+
+ # Get an ObjectSpecification bound to either an instance or a class,
+ # depending on how we were accessed.
+
+ if inst is None:
+ return getObjectSpecification(cls)
+
+ provides = getattr(inst, '__provides__', None)
+ if provides is not None:
+ return provides
+
+ return implementedBy(cls)
+
+ObjectSpecificationDescriptor = ObjectSpecificationDescriptorPy
+
+objectSpecificationDescriptor = ObjectSpecificationDescriptor()
+
+##############################################################################
+
+def _normalizeargs(sequence, output = None):
+ """Normalize declaration arguments
+
+ Normalization arguments might contain Declarions, tuples, or single
+ interfaces.
+
+ Anything but individial interfaces or implements specs will be expanded.
+ """
+ if output is None:
+ output = []
+
+ cls = sequence.__class__
+ if InterfaceClass in cls.__mro__ or Implements in cls.__mro__:
+ output.append(sequence)
+ else:
+ for v in sequence:
+ _normalizeargs(v, output)
+
+ return output
+
+_empty = Declaration()
+
+try:
+ import _zope_interface_coptimizations
+except ImportError:
+ pass
+else:
+ from _zope_interface_coptimizations import implementedBy, providedBy
+ from _zope_interface_coptimizations import getObjectSpecification
+ from _zope_interface_coptimizations import ObjectSpecificationDescriptor
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/document.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/document.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,123 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+""" Pretty-Print an Interface object as structured text (Yum)
+
+This module provides a function, asStructuredText, for rendering an
+interface as structured text.
+
+Revision information:
+$Id: document.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+import zope.interface
+from string import maketrans
+
+def asStructuredText(I, munge=0):
+ """ Output structured text format. Note, this will wack any existing
+ 'structured' format of the text. """
+
+
+ r = ["%s\n\n" % I.getName()]
+ outp = r.append
+ level = 1
+
+ if I.getDoc():
+ outp(_justify_and_indent(_trim_doc_string(I.getDoc()), level)+ "\n\n")
+
+ bases = [base
+ for base in I.__bases__
+ if base is not zope.interface.Interface
+ ]
+ if bases:
+ outp((" " * level) + "This interface extends:\n\n")
+ level = level + 1
+ for b in bases:
+ item = "o %s" % b.getName()
+ outp(_justify_and_indent(_trim_doc_string(item), level, munge)
+ + "\n\n")
+
+ level = level - 1
+
+ outp(_justify_and_indent("Attributes:", level, munge)+'\n\n')
+ level = level + 1
+
+ namesAndDescriptions = I.namesAndDescriptions()
+ namesAndDescriptions.sort()
+
+ for name, desc in namesAndDescriptions:
+ if not hasattr(desc, 'getSignatureString'): # ugh...
+ item = "%s -- %s" % (desc.getName(),
+ desc.getDoc() or 'no documentation')
+ outp(_justify_and_indent(_trim_doc_string(item), level, munge)
+ + "\n\n")
+ level = level - 1
+
+ outp(_justify_and_indent("Methods:", level, munge)+'\n\n')
+ level = level + 1
+ for name, desc in namesAndDescriptions:
+ if hasattr(desc, 'getSignatureString'): # ugh...
+ item = "%s%s -- %s" % (desc.getName(),
+ desc.getSignatureString(),
+ desc.getDoc() or 'no documentation')
+ outp(_justify_and_indent(_trim_doc_string(item), level, munge)
+ + "\n\n")
+
+ return "".join(r)
+
+def _trim_doc_string(text):
+ """
+ Trims a doc string to make it format
+ correctly with structured text.
+ """
+ text = text.strip().replace('\r\n', '\n')
+ lines = text.split('\n')
+ nlines = [lines[0]]
+ if len(lines) > 1:
+ min_indent=None
+ for line in lines[1:]:
+ indent=len(line) - len(line.lstrip())
+ if indent < min_indent or min_indent is None:
+ min_indent=indent
+ for line in lines[1:]:
+ nlines.append(line[min_indent:])
+ return '\n'.join(nlines)
+
+
+_trans = maketrans("\r\n", " ")
+def _justify_and_indent(text, level, munge=0, width=72):
+ """ indent and justify text, rejustify (munge) if specified """
+
+ lines = []
+
+ if munge:
+ line = " " * level
+ text = text.translate(text, _trans).strip().split()
+
+ for word in text:
+ line = ' '.join([line, word])
+ if len(line) > width:
+ lines.append(line)
+ line = " " * level
+ else:
+ lines.append(line)
+
+ return "\n".join(lines)
+
+ else:
+ text = text.replace("\r\n", "\n").split("\n")
+
+ for line in text:
+ lines.append((" " * level) + line)
+
+ return '\n'.join(lines)
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/exceptions.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/exceptions.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,69 @@ />
+##############################################################################
+#
+# Copyright (c) 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.
+#
+##############################################################################
+"""
+
+$Id: exceptions.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+class Invalid(Exception):
+ """An specification is violated
+ """
+
+class DoesNotImplement(Invalid):
+ """ This object does not implement """
+ def __init__(self, interface):
+ self.interface = interface
+
+ def __str__(self):
+ return """An object does not implement interface %(interface)s
+
+ """ % self.__dict__
+
+class BrokenImplementation(Invalid):
+ """An attribute is not completely implemented.
+ """
+
+ def __init__(self, interface, name):
+ self.interface=interface
+ self.name=name
+
+ def __str__(self):
+ return """An object has failed to implement interface %(interface)s
+
+ The %(name)s attribute was not provided.
+ """ % self.__dict__
+
+class BrokenMethodImplementation(Invalid):
+ """An method is not completely implemented.
+ """
+
+ def __init__(self, method, mess):
+ self.method=method
+ self.mess=mess
+
+ def __str__(self):
+ return """The implementation of %(method)s violates its contract
+ because %(mess)s.
+ """ % self.__dict__
+
+class InvalidInterface(Exception):
+ """The interface has invalid contents
+ """
+
+class BadImplements(TypeError):
+ """An implementation assertion is invalid
+
+ because it doesn't contain an interface or a sequence of valid
+ implementation assertions.
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/interface.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/interface.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,917 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Interface object implementation
+
+$Id: interface.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+from __future__ import generators
+
+import sys
+import warnings
+import weakref
+from types import FunctionType
+from ro import ro
+from zope.interface.exceptions import Invalid
+
+CO_VARARGS = 4
+CO_VARKEYWORDS = 8
+TAGGED_DATA = '__interface_tagged_values__'
+
+def invariant(call):
+ f_locals = sys._getframe(1).f_locals
+ tags = f_locals.get(TAGGED_DATA)
+ if tags is None:
+ tags = f_locals[TAGGED_DATA] = {}
+ invariants = tags.get('invariants')
+ if invariants is None:
+ invariants = tags['invariants'] = []
+ invariants.append(call)
+
+class Element(object):
+
+ # We can't say this yet because we don't have enough
+ # infrastructure in place.
+ #
+ #implements(IElement)
+
+ def __init__(self, __name__, __doc__=''):
+ """Create an 'attribute' description
+ """
+ if not __doc__ and __name__.find(' ') >= 0:
+ __doc__ = __name__
+ __name__ = None
+
+ self.__name__=__name__
+ self.__doc__=__doc__
+ self.__tagged_values = {}
+
+ def getName(self):
+ """ Returns the name of the object. """
+ return self.__name__
+
+ def getDoc(self):
+ """ Returns the documentation for the object. """
+ return self.__doc__
+
+ def getTaggedValue(self, tag):
+ """ Returns the value associated with 'tag'. """
+ return self.__tagged_values[tag]
+
+ def queryTaggedValue(self, tag, default=None):
+ """ Returns the value associated with 'tag'. """
+ return self.__tagged_values.get(tag, default)
+
+ def getTaggedValueTags(self):
+ """ Returns a list of all tags. """
+ return self.__tagged_values.keys()
+
+ def setTaggedValue(self, tag, value):
+ """ Associates 'value' with 'key'. """
+ self.__tagged_values[tag] = value
+
+class SpecificationBasePy(object):
+
+ def providedBy(self, ob):
+ """Is the interface implemented by an object
+
+ >>> from zope.interface import *
+ >>> class I1(Interface):
+ ... pass
+ >>> class C:
+ ... implements(I1)
+ >>> c = C()
+ >>> class X:
+ ... pass
+ >>> x = X()
+ >>> I1.providedBy(x)
+ False
+ >>> I1.providedBy(C)
+ False
+ >>> I1.providedBy(c)
+ True
+ >>> directlyProvides(x, I1)
+ >>> I1.providedBy(x)
+ True
+ >>> directlyProvides(C, I1)
+ >>> I1.providedBy(C)
+ True
+
+ """
+ spec = providedBy(ob)
+ return self in spec._implied
+
+ def implementedBy(self, cls):
+ """Do instances of the given class implement the interface?"""
+ spec = implementedBy(cls)
+ return self in spec._implied
+
+ def isOrExtends(self, interface):
+ """Is the interface the same as or extend the given interface
+
+ Examples::
+
+ >>> from zope.interface import Interface
+ >>> from zope.interface.declarations import Declaration
+ >>> class I1(Interface): pass
+ ...
+ >>> class I2(I1): pass
+ ...
+ >>> class I3(Interface): pass
+ ...
+ >>> class I4(I3): pass
+ ...
+ >>> spec = Declaration()
+ >>> int(spec.extends(Interface))
+ 0
+ >>> spec = Declaration(I2)
+ >>> int(spec.extends(Interface))
+ 1
+ >>> int(spec.extends(I1))
+ 1
+ >>> int(spec.extends(I2))
+ 1
+ >>> int(spec.extends(I3))
+ 0
+ >>> int(spec.extends(I4))
+ 0
+
+ """
+ return interface in self._implied
+
+SpecificationBase = SpecificationBasePy
+
+try:
+ from _zope_interface_coptimizations import SpecificationBase
+except ImportError:
+ pass
+
+class Specification(SpecificationBase):
+ """Specifications
+
+ An interface specification is used to track interface declarations
+ and component registrations.
+
+ This class is a base class for both interfaces themselves and for
+ interface specifications (declarations).
+
+ Specifications are mutable. If you reassign their cases, their
+ relations with other specifications are adjusted accordingly.
+
+ For example:
+
+ >>> from zope.interface import Interface
+ >>> class I1(Interface):
+ ... pass
+ >>> class I2(I1):
+ ... pass
+ >>> class I3(I2):
+ ... pass
+
+ >>> [i.__name__ for i in I1.__bases__]
+ ['Interface']
+
+ >>> [i.__name__ for i in I2.__bases__]
+ ['I1']
+
+ >>> I3.extends(I1)
+ 1
+
+ >>> I2.__bases__ = (Interface, )
+
+ >>> [i.__name__ for i in I2.__bases__]
+ ['Interface']
+
+ >>> I3.extends(I1)
+ 0
+
+ """
+
+ # Copy some base class methods for speed
+ isOrExtends = SpecificationBase.isOrExtends
+ providedBy = SpecificationBase.providedBy
+
+ #########################################################################
+ # XXX Backward Compat
+ def isImplementedByInstancesOf(self, cls):
+ warnings.warn(
+ "isImplementedByInstancesOf has been renamed to implementedBy",
+ DecationWarning, stacklevel=2,
+ )
+ return self.implementedBy(cls)
+
+ def isImplementedBy(self, ob):
+ warnings.warn(
+ "isImplementedBy has been renamed to providedBy",
+ DecationWarning, stacklevel=2,
+ )
+ return self.providedBy(ob)
+ #
+ #########################################################################
+
+ def __init__(self, bases=()):
+ self._implied = {}
+ self.dependents = weakref.WeakKeyDictionary()
+ self.__bases__ = tuple(bases)
+
+ def subscribe(self, dependent):
+ self.dependents[dependent] = 1
+
+ def unsubscribe(self, dependent):
+ del self.dependents[dependent]
+
+ def __setBases(self, bases):
+ # Register ourselves as a dependent of our old bases
+ for b in self.__bases__:
+ b.unsubscribe(self)
+
+ # Register ourselves as a dependent of our bases
+ self.__dict__['__bases__'] = bases
+ for b in bases:
+ b.subscribe(self)
+
+ self.changed()
+
+ __bases__ = property(
+
+ lambda self: self.__dict__.get('__bases__', ()),
+ __setBases,
+ )
+
+ def changed(self):
+ """We, or something we depend on, have changed
+ """
+
+ implied = self._implied
+ implied.clear()
+
+ ancestors = ro(self)
+ self.__iro__ = tuple([ancestor for ancestor in ancestors
+ if isinstance(ancestor, InterfaceClass)
+ ])
+
+ for ancestor in ancestors:
+ # We directly imply our ancestors:
+ implied[ancestor] = ()
+
+ # Now, advise our dependents of change:
+ for dependent in self.dependents.keys():
+ dependent.changed()
+
+
+ def interfaces(self):
+ """Return an iterator for the interfaces in the specification
+
+ for example::
+
+ >>> from zope.interface import Interface
+ >>> class I1(Interface): pass
+ ...
+ >>> class I2(I1): pass
+ ...
+ >>> class I3(Interface): pass
+ ...
+ >>> class I4(I3): pass
+ ...
+ >>> spec = Specification((I2, I3))
+ >>> spec = Specification((I4, spec))
+ >>> i = spec.interfaces()
+ >>> i.next().getName()
+ 'I4'
+ >>> i.next().getName()
+ 'I2'
+ >>> i.next().getName()
+ 'I3'
+ >>> list(i)
+ []
+ """
+ seen = {}
+ for base in self.__bases__:
+ for interface in base.interfaces():
+ if interface not in seen:
+ seen[interface] = 1
+ yield interface
+
+
+ def extends(self, interface, strict=True):
+ """Does the specification extend the given interface?
+
+ Test whether an interface in the specification extends the
+ given interface
+
+ Examples::
+
+ >>> from zope.interface import Interface
+ >>> from zope.interface.declarations import Declaration
+ >>> class I1(Interface): pass
+ ...
+ >>> class I2(I1): pass
+ ...
+ >>> class I3(Interface): pass
+ ...
+ >>> class I4(I3): pass
+ ...
+ >>> spec = Declaration()
+ >>> int(spec.extends(Interface))
+ 0
+ >>> spec = Declaration(I2)
+ >>> int(spec.extends(Interface))
+ 1
+ >>> int(spec.extends(I1))
+ 1
+ >>> int(spec.extends(I2))
+ 1
+ >>> int(spec.extends(I3))
+ 0
+ >>> int(spec.extends(I4))
+ 0
+ >>> I2.extends(I2)
+ 0
+ >>> I2.extends(I2, False)
+ 1
+ >>> I2.extends(I2, strict=False)
+ 1
+
+ """
+ return ((interface in self._implied)
+ and
+ ((not strict) or (self != interface))
+ )
+
+ def weakref(self, callback=None):
+ if callback is None:
+ return weakref.ref(self)
+ else:
+ return weakref.ref(self, callback)
+
+
+class InterfaceClass(Element, Specification):
+ """Prototype (scarecrow) Interfaces Implementation."""
+
+ # We can't say this yet because we don't have enough
+ # infrastructure in place.
+ #
+ #implements(IInterface)
+
+ def __init__(self, name, bases=(), attrs=None, __doc__=None,
+ __module__=None):
+
+ if __module__ is None:
+ if (attrs is not None and
+ ('__module__' in attrs) and
+ isinstance(attrs['__module__'], str)
+ ):
+ __module__ = attrs['__module__']
+ del attrs['__module__']
+ else:
+
+ try:
+ # Figure out what module defined the interface.
+ # This is how cPython figures out the module of
+ # a class, but of course it does it in C. :-/
+ __module__ = sys._getframe(1).f_globals['__name__']
+ except (AttributeError, KeyError):
+ pass
+
+ self.__module__ = __module__
+
+ if attrs is None:
+ attrs = {}
+
+ d = attrs.get('__doc__')
+ if d is not None:
+ if not isinstance(d, Attribute):
+ if __doc__ is None:
+ __doc__ = d
+ del attrs['__doc__']
+
+ if __doc__ is None:
+ __doc__ = ''
+
+ Element.__init__(self, name, __doc__)
+
+ if attrs.has_key(TAGGED_DATA):
+ tagged_data = attrs[TAGGED_DATA]
+ del attrs[TAGGED_DATA]
+ else:
+ tagged_data = None
+ if tagged_data is not None:
+ for key, val in tagged_data.items():
+ self.setTaggedValue(key, val)
+
+ for b in bases:
+ if not isinstance(b, InterfaceClass):
+ raise TypeError, 'Expected base interfaces'
+
+ Specification.__init__(self, bases)
+
+ for k, v in attrs.items():
+ if isinstance(v, Attribute):
+ v.interface = name
+ if not v.__name__:
+ v.__name__ = k
+ elif isinstance(v, FunctionType):
+ attrs[k] = fromFunction(v, name, name=k)
+ else:
+ raise InvalidInterface("Concrete attribute, %s" % k)
+
+ self.__attrs = attrs
+
+ self.__identifier__ = "%s.%s" % (self.__module__, self.__name__)
+
+ def interfaces(self):
+ """Return an iterator for the interfaces in the specification
+
+ for example::
+
+ >>> from zope.interface import Interface
+ >>> class I1(Interface): pass
+ ...
+ >>>
+ >>> i = I1.interfaces()
+ >>> i.next().getName()
+ 'I1'
+ >>> list(i)
+ []
+ """
+ yield self
+
+
+
+ def getBases(self):
+ return self.__bases__
+
+ def isEqualOrExtendedBy(self, other):
+ """Same interface or extends?"""
+ if self == other:
+ return True
+ return other.extends(self)
+
+ def names(self, all=False):
+ """Return the attribute names defined by the interface."""
+ if not all:
+ return self.__attrs.keys()
+
+ r = {}
+ for name in self.__attrs.keys():
+ r[name] = 1
+ for base in self.__bases__:
+ for name in base.names(all):
+ r[name] = 1
+ return r.keys()
+
+ def __iter__(self):
+ return iter(self.names(all=True))
+
+ def namesAndDescriptions(self, all=False):
+ """Return attribute names and descriptions defined by interface."""
+ if not all:
+ return self.__attrs.items()
+
+ r = {}
+ for name, d in self.__attrs.items():
+ r[name] = d
+
+ for base in self.__bases__:
+ for name, d in base.namesAndDescriptions(all):
+ if name not in r:
+ r[name] = d
+
+ return r.items()
+
+ def getDescriptionFor(self, name):
+ """Return the attribute description for the given name."""
+ r = self.queryDescriptionFor(name)
+ if r is not None:
+ return r
+
+ raise KeyError, name
+
+ __getitem__ = getDescriptionFor
+
+ def __contains__(self, name):
+ return self.queryDescriptionFor(name) is not None
+
+ def queryDescriptionFor(self, name, default=None):
+ """Return the attribute description for the given name."""
+ r = self.__attrs.get(name, self)
+ if r is not self:
+ return r
+ for base in self.__bases__:
+ r = base.queryDescriptionFor(name, self)
+ if r is not self:
+ return r
+
+ return default
+
+ get = queryDescriptionFor
+
+ def deferred(self):
+ """Return a defered class corresponding to the interface."""
+ if hasattr(self, "_deferred"): return self._deferred
+
+ klass={}
+ exec "class %s: pass" % self.__name__ in klass
+ klass=klass[self.__name__]
+
+ self.__d(klass.__dict__)
+
+ self._deferred=klass
+
+ return klass
+
+ def validateInvariants(self, obj, errors=None):
+ """validate object to defined invariants."""
+ for call in self.queryTaggedValue('invariants', []):
+ try:
+ call(obj)
+ except Invalid, e:
+ if errors is None:
+ raise
+ else:
+ errors.append(e)
+ for base in self.__bases__:
+ try:
+ base.validateInvariants(obj, errors)
+ except Invalid:
+ if errors is None:
+ raise
+ pass
+ if errors:
+ raise Invalid(errors)
+
+ def _getInterface(self, ob, name):
+ """Retrieve a named interface."""
+ return None
+
+ def __d(self, dict):
+
+ for k, v in self.__attrs.items():
+ if isinstance(v, Method) and not (k in dict):
+ dict[k]=v
+
+ for b in self.__bases__: b.__d(dict)
+
+ def __repr__(self):
+ r = getattr(self, '_v_repr', self)
+ if r is self:
+ name = self.__name__
+ m = self.__module__
+ if m:
+ name = '%s.%s' % (m, name)
+ r = "<%s %s>" % (self.__class__.__name__, name)
+ self._v_repr = r
+ return r
+
+ def __call__():
+ # TRICK! Create the call method
+ #
+ # An embedded function is used to allow an optional argument to
+ # __call__ without resorting to a global marker.
+ #
+ # The evility of this trick is a reflection of the underlying
+ # evility of "optional" arguments, arguments whos sense or
+ # absense changes the behavior of the methos.
+ #
+ # I think the evil is necessary, and perhaps desireable to
+ # provide some consistencey with the PEP 246 adapt method.
+
+ marker = object()
+
+ def __call__(self, obj, alternate=marker):
+ """Adapt an object to the interface
+
+ The sematics based on those of the PEP 246 adapt function.
+
+ If an object cannot be adapted, then a TypeError is raised::
+
+ >>> import zope.interface
+ >>> class I(zope.interface.Interface):
+ ... pass
+
+ >>> I(0)
+ Traceback (most recent call last):
+ ...
+ TypeError: ('Could not adapt', 0, """ \
+ """<InterfaceClass zope.interface.interface.I>)
+
+ unless an alternate value is provided as a second
+ positional argument::
+
+ >>> I(0, 'bob')
+ 'bob'
+
+ If an object already implements the interface, then it will be
+ returned::
+
+ >>> class C:
+ ... zope.interface.implements(I)
+
+ >>> obj = C()
+ >>> I(obj) is obj
+ True
+
+ If an object implements __conform__, then it will be used::
+
+ >>> class C:
+ ... zope.interface.implements(I)
+ ... def __conform__(self, proto):
+ ... return 0
+
+ >>> I(C())
+ 0
+
+ Adapter hooks (see __adapt__) will also be used, if sent:
+
+ >>> from zope.interface.interface import adapter_hooks
+ >>> def adapt_0_to_42(iface, obj):
+ ... if obj == 0:
+ ... return 42
+
+ >>> adapter_hooks.append(adapt_0_to_42)
+ >>> I(0)
+ 42
+
+ >>> adapter_hooks.remove(adapt_0_to_42)
+ >>> I(0)
+ Traceback (most recent call last):
+ ...
+ TypeError: ('Could not adapt', 0, """ \
+ """<InterfaceClass zope.interface.interface.I>)
+
+ """
+ conform = getattr(obj, '__conform__', None)
+ if conform is not None:
+ try:
+ adapter = conform(self)
+ except TypeError:
+ # We got a TypeError. It might be an error raised by
+ # the __conform__ implementation, or *we* may have
+ # made the TypeError by calling an unbound method
+ # (object is a class). In the later case, we behave
+ # as though there is no __conform__ method. We can
+ # detect this case by checking whether there is more
+ # than one traceback object in the traceback chain:
+ if sys.exc_info()[2].tb_next is not None:
+ # There is more than one entry in the chain, so
+ # reraise the error:
+ raise
+ # This clever trick is from Phillip Eby
+ else:
+ if adapter is not None:
+ return adapter
+
+ adapter = self.__adapt__(obj)
+
+ if adapter is None:
+ if alternate is not marker:
+ return alternate
+
+ raise TypeError("Could not adapt", obj, self)
+
+ return adapter
+
+ return __call__
+
+ __call__ = __call__() # TRICK! Make the *real* __call__ method
+
+ def __adapt__(self, obj):
+ """Adapt an object to the reciever
+
+ This method is normally not called directly. It is called by
+ the PEP 246 adapt framework and by the interface __call__
+ operator.
+
+ The adapt method is responsible for adapting an object to
+ the reciever.
+
+ The default version returns None::
+
+ >>> import zope.interface
+ >>> class I(zope.interface.Interface):
+ ... pass
+
+ >>> I.__adapt__(0)
+
+ unless the object given provides the interface::
+
+ >>> class C:
+ ... zope.interface.implements(I)
+
+ >>> obj = C()
+ >>> I.__adapt__(obj) is obj
+ True
+
+ Adapter hooks can be provided (or removed) to provide custom
+ adaptation. We'll install a silly hook that adapts 0 to 42.
+ We install a hook by simply adding it to the adapter_hooks
+ list::
+
+ >>> from zope.interface.interface import adapter_hooks
+ >>> def adapt_0_to_42(iface, obj):
+ ... if obj == 0:
+ ... return 42
+
+ >>> adapter_hooks.append(adapt_0_to_42)
+ >>> I.__adapt__(0)
+ 42
+
+ Hooks must either return an adapter, or None if no adapter can
+ be found.
+
+ Hooks can be uninstalled by removing them from the list::
+
+ >>> adapter_hooks.remove(adapt_0_to_42)
+ >>> I.__adapt__(0)
+
+ """
+ if self.providedBy(obj):
+ return obj
+
+ for hook in adapter_hooks:
+ adapter = hook(self, obj)
+ if adapter is not None:
+ return adapter
+
+ def __reduce__(self):
+ return self.__name__
+
+ def __cmp(self, o1, o2):
+ # Yes, I did mean to name this __cmp, rather than __cmp__.
+ # It is a private method used by __lt__ and __gt__.
+ # I don't want to override __eq__ because I want the default
+ # __eq__, which is really fast.
+ """Make interfaces sortable
+
+ It would ne nice if:
+
+ More specific interfaces should sort before less specific ones.
+ Otherwise, sort on name and module.
+
+ But this is too complicated, and we're going to punt on it
+ for now. XXX
+
+ XXX For now, sort on interface and module name.
+
+ None is treated as a pseudo interface that implies the loosest
+ contact possible, no contract. For that reason, all interfaces
+ sort before None.
+
+ """
+
+ if o1 == o2:
+ return 0
+
+ if o1 is None:
+ return 1
+ if o2 is None:
+ return -1
+
+
+ n1 = (getattr(o1, '__name__', ''),
+ getattr(getattr(o1, '__module__', None), '__name__', ''))
+ n2 = (getattr(o2, '__name__', ''),
+ getattr(getattr(o2, '__module__', None), '__name__', ''))
+
+ return cmp(n1, n2)
+
+ def __lt__(self, other):
+ c = self.__cmp(self, other)
+ #print '<', self, other, c < 0, c
+ return c < 0
+
+ def __gt__(self, other):
+ c = self.__cmp(self, other)
+ #print '>', self, other, c > 0, c
+ return c > 0
+
+
+adapter_hooks = []
+
+Interface = InterfaceClass("Interface", __module__ = 'zope.interface')
+
+class Attribute(Element):
+ """Attribute descriptions
+ """
+
+ # We can't say this yet because we don't have enough
+ # infrastructure in place.
+ #
+ #__implemented__ = IAttribute
+
+class Method(Attribute):
+ """Method interfaces
+
+ The idea here is that you have objects that describe methods.
+ This provides an opportunity for rich meta-data.
+ """
+
+ # We can't say this yet because we don't have enough
+ # infrastructure in place.
+ #
+ #__implemented__ = IMethod
+
+ interface=''
+
+ def __call__(self, *args, **kw):
+ raise BrokenImplementation(self.interface, self.__name__)
+
+ def getSignatureInfo(self):
+ return {'positional': self.positional,
+ 'required': self.required,
+ 'optional': self.optional,
+ 'varargs': self.varargs,
+ 'kwargs': self.kwargs,
+ }
+
+ def getSignatureString(self):
+ sig = "("
+ for v in self.positional:
+ sig = sig + v
+ if v in self.optional.keys():
+ sig = sig + "=%s" % `self.optional[v]`
+ sig = sig + ", "
+ if self.varargs:
+ sig = sig + ("*%s, " % self.varargs)
+ if self.kwargs:
+ sig = sig + ("**%s, " % self.kwargs)
+
+ # slice off the last comma and space
+ if self.positional or self.varargs or self.kwargs:
+ sig = sig[:-2]
+
+ sig = sig + ")"
+ return sig
+
+
+def fromFunction(func, interface='', imlevel=0, name=None):
+ name = name or func.__name__
+ m=Method(name, func.__doc__)
+ defaults=func.func_defaults or ()
+ c=func.func_code
+ na=c.co_argcount-imlevel
+ names=c.co_varnames[imlevel:]
+ d={}
+ nr=na-len(defaults)
+ if nr < 0:
+ defaults=defaults[-nr:]
+ nr=0
+
+ for i in range(len(defaults)):
+ d[names[i+nr]]=defaults[i]
+
+ m.positional=names[:na]
+ m.required=names[:nr]
+ m.optional=d
+
+ argno = na
+ if c.co_flags & CO_VARARGS:
+ m.varargs = names[argno]
+ argno = argno + 1
+ else:
+ m.varargs = None
+ if c.co_flags & CO_VARKEYWORDS:
+ m.kwargs = names[argno]
+ else:
+ m.kwargs = None
+
+ m.interface=interface
+
+ for k, v in func.__dict__.items():
+ m.setTaggedValue(k, v)
+
+ return m
+
+def fromMethod(meth, interface=''):
+ func = meth.im_func
+ return fromFunction(func, interface, imlevel=1)
+
+
+# Now we can create the interesting interfaces and wire them up:
+def _wire():
+ from zope.interface.declarations import classImplements
+
+ from zope.interface.interfaces import IAttribute
+ classImplements(Attribute, IAttribute)
+
+ from zope.interface.interfaces import IMethod
+ classImplements(Method, IMethod)
+
+ from zope.interface.interfaces import IInterface
+ classImplements(InterfaceClass, IInterface)
+
+# We import this here to deal with module dependencies.
+from zope.interface.declarations import providedBy, implementedBy
+from zope.interface.exceptions import InvalidInterface
+from zope.interface.exceptions import BrokenImplementation
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/interfaces.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/interfaces.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,635 @@ />
+##############################################################################
+#
+# Copyright (c) 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.
+#
+##############################################################################
+"""
+
+$Id: interfaces.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+from zope.interface import Interface
+from zope.interface.interface import Attribute
+
+class IElement(Interface):
+ """Objects that have basic documentation and tagged values.
+ """
+
+ __name__ = Attribute('__name__', 'The object name')
+ __doc__ = Attribute('__doc__', 'The object doc string')
+
+ def getTaggedValue(tag):
+ """Returns the value associated with 'tag'.
+
+ Raise a KeyError of the tag isn't set
+ """
+
+ def queryTaggedValue(tag, default=None):
+ """Returns the value associated with 'tag'.
+
+ Return the default value of the tag isn't set.
+ """
+
+ def getTaggedValueTags():
+ """Returns a list of all tags."""
+
+ def setTaggedValue(tag, value):
+ """Associates 'value' with 'key'."""
+
+
+class IAttribute(IElement):
+ """Attribute descriptors"""
+
+
+class IMethod(IAttribute):
+ """Method attributes
+ """
+ # XXX What the heck should methods provide? Grrrr
+
+ def getSignatureString():
+ """Return a signature string suitable for inclusion in documentation.
+ """
+
+class ISpecification(Interface):
+ """Object Behavioral specifications
+ """
+
+ def extends(other, strict=True):
+ """Test whether a specification extends another
+
+ The specification extends other if it has other as a base
+ interface or if one of it's bases extends other.
+
+ If strict is false, then the specification extends itself.
+
+ """
+
+ def isOrExtends(other):
+ """Test whether the specification is or extends another
+ """
+
+ def weakref(callback=None):
+ """Return a weakref to the specification
+
+ This method is, regrettably, needed to allow weakrefs to be
+ computed to security-proxied specifications. While the
+ zope.interface package does not require zope.security or
+ zope.proxy, it has to be able to coexist with it.
+
+ """
+
+ __bases__ = Attribute("""Base specifications
+
+ A tuple if specifications from which this specification is
+ directly derived.
+
+ """)
+
+
+
+class IInterface(ISpecification, IElement):
+ """Interface objects
+
+ Interface objects describe the behavior of an object by containing
+ useful information about the object. This information includes:
+
+ o Prose documentation about the object. In Python terms, this
+ is called the "doc string" of the interface. In this element,
+ you describe how the object works in prose language and any
+ other useful information about the object.
+
+ o Descriptions of attributes. Attribute descriptions include
+ the name of the attribute and prose documentation describing
+ the attributes usage.
+
+ o Descriptions of methods. Method descriptions can include:
+
+ o Prose "doc string" documentation about the method and its
+ usage.
+
+ o A description of the methods arguments; how many arguments
+ are expected, optional arguments and their default values,
+ the position or arguments in the signature, whether the
+ method accepts arbitrary arguments and whether the method
+ accepts arbitrary keyword arguments.
+
+ o Optional tagged data. Interface objects (and their attributes and
+ methods) can have optional, application specific tagged data
+ associated with them. Examples uses for this are examples,
+ security assertions, /post conditions, and other possible
+ information you may want to associate with an Interface or its
+ attributes.
+
+ Not all of this information is mandatory. For example, you may
+ only want the methods of your interface to have prose
+ documentation and not describe the arguments of the method in
+ exact detail. Interface objects are flexible and let you give or
+ take any of these components.
+
+ Interfaces are created with the Python class statement using
+ either Interface.Interface or another interface, as in::
+
+ from zope.interface import Interface
+
+ class IMyInterface(Interface):
+ '''Interface documentation
+ '''
+
+ def meth(arg1, arg2):
+ '''Documentation for meth
+ '''
+
+ # Note that there is no self argument
+
+ class IMySubInterface(IMyInterface):
+ '''Interface documentation
+ '''
+
+ def meth2():
+ '''Documentation for meth2
+ '''
+
+ You use interfaces in two ways:
+
+ o You assert that your object implement the interfaces.
+
+ There are several ways that you can assert that an object
+ implements an interface::
+
+ 1. Call zope.interface.implements in your class definition.
+
+ 2. Call zope.interfaces.directlyProvides on your object.
+
+ 3. Call 'zope.interface.classImplements' to assert that instances
+ of a class implement an interface.
+
+ For example::
+
+ from zope.interface import classImplements
+
+ classImplements(some_class, some_interface)
+
+ This approach is useful when it is not an option to modify
+ the class source. Note that this doesn't affect what the
+ class itself implements, but only what its instances
+ implement.
+
+ o You query interface meta-data. See the IInterface methods and
+ attributes for details.
+
+ """
+
+ def providedBy(object):
+ """Test whether the interface is implemented by the object
+
+ Return true of the object asserts that it implements the
+ interface, including asserting that it implements an extended
+ interface.
+ """
+
+ def implementedBy(class_):
+ """Test whether the interface is implemented by instances of the class
+
+ Return true of the class asserts that its instances implement the
+ interface, including asserting that they implement an extended
+ interface.
+ """
+
+ def names(all=False):
+ """Get the interface attribute names
+
+ Return a sequence of the names of the attributes, including
+ methods, included in the interface definition.
+
+ Normally, only directly defined attributes are included. If
+ a true positional or keyword argument is given, then
+ attributes defined by base classes will be included.
+ """
+
+ def namesAndDescriptions(all=False):
+ """Get the interface attribute names and descriptions
+
+ Return a sequence of the names and descriptions of the
+ attributes, including methods, as name-value pairs, included
+ in the interface definition.
+
+ Normally, only directly defined attributes are included. If
+ a true positional or keyword argument is given, then
+ attributes defined by base classes will be included.
+ """
+
+ def __getitem__(name):
+ """Get the description for a name
+
+ If the named attribute is not defined, a KeyError is raised.
+ """
+
+ def validateInvariants(obj, errors=None):
+ """Validate invariants
+
+ Validate object to defined invariants. If errors is None,
+ raises first Invalid error; if errors is a list, appends all errors
+ to list, then raises Invalid with the errors as the first element
+ of the "args" tuple."""
+
+ def get(name, default=None):
+ """Look up the description for a name
+
+ If the named attribute is not defined, the default is
+ returned.
+ """
+
+ def __contains__(name):
+ """Test whether the name is defined by the interface"""
+
+ def __iter__():
+ """Return an iterator over the names defined by the interface
+
+ The names iterated include all of the names defined by the
+ interface directly and indirectly by base interfaces.
+ """
+
+ __module__ = Attribute("""The name of the module defining the interface""")
+
+class IDeclaration(ISpecification):
+ """Interface declaration
+
+ Declarations are used to exss the interfaces implemented by
+ classes or provided by objects.
+
+ """
+
+ def __contains__(interface):
+ """Test whether an interface is in the specification
+
+ Return true if the given interface is one of the interfaces in
+ the specification and false otherwise.
+ """
+
+ def __iter__():
+ """Return an iterator for the interfaces in the specification
+ """
+
+ def flattened():
+ """Return an iterator of all included and extended interfaces
+
+ An iterator is returned for all interfaces either included in
+ or extended by interfaces included in the specifications
+ without duplicates. The interfaces are in "interface
+ resolution order". The interface resolution order is such that
+ base interfaces are listed after interfaces that extend them
+ and, otherwise, interfaces are included in the order that they
+ were defined in the specification.
+ """
+
+ def __sub__(interfaces):
+ """Create an interface specification with some interfaces excluded
+
+ The argument can be an interface or an interface
+ specifications. The interface or interfaces given in a
+ specification are subtracted from the interface specification.
+
+ Removing an interface that is not in the specification does
+ not raise an error. Doing so has no effect.
+
+ Removing an interface also removes sub-interfaces of the interface.
+
+ """
+
+ def __add__(interfaces):
+ """Create an interface specification with some interfaces added
+
+ The argument can be an interface or an interface
+ specifications. The interface or interfaces given in a
+ specification are added to the interface specification.
+
+ Adding an interface that is already in the specification does
+ not raise an error. Doing so has no effect.
+ """
+
+ def __nonzero__():
+ """Return a true value of the interface specification is non-empty
+ """
+
+class IInterfaceDeclaration(Interface):
+ """Declare and check the interfaces of objects
+
+ The functions defined in this interface are used to declare the
+ interfaces that objects provide and to query the interfaces that have
+ been declared.
+
+ Interfaces can be declared for objects in two ways:
+
+ - Interfaces are declared for instances of the object's class
+
+ - Interfaces are declared for the object directly.
+
+ The interfaces declared for an object are, therefore, the union of
+ interfaces declared for the object directly and the interfaces
+ declared for instances of the object's class.
+
+ Note that we say that a class implements the interfaces provided
+ by it's instances. An instance can also provide interfaces
+ directly. The interfaces provided by an object are the union of
+ the interfaces provided directly and the interfaces implemented by
+ the class.
+ """
+
+ def providedBy(ob):
+ """Return the interfaces provided by an object
+
+ This is the union of the interfaces directly provided by an
+ object and interfaces implemented by it's class.
+
+ The value returned is an IDeclaration.
+ """
+
+ def implementedBy(class_):
+ """Return the interfaces implemented for a class' instances
+
+ The value returned is an IDeclaration.
+ """
+
+ def classImplements(class_, *interfaces):
+ """Declare additional interfaces implemented for instances of a class
+
+ The arguments after the class are one or more interfaces or
+ interface specifications (IDeclaration objects).
+
+ The interfaces given (including the interfaces in the
+ specifications) are added to any interfaces viously
+ declared.
+
+ Consider the following example::
+
+ class C(A, B):
+ ...
+
+ classImplements(C, I1, I2)
+
+
+ Instances of ``C`` provide ``I1``, ``I2``, and whatever interfaces
+ instances of ``A`` and ``B`` provide.
+ """
+
+ def classImplementsOnly(class_, *interfaces):
+ """Declare the only interfaces implemented by instances of a class
+
+ The arguments after the class are one or more interfaces or
+ interface specifications (IDeclaration objects).
+
+ The interfaces given (including the interfaces in the
+ specifications) replace any vious declarations.
+
+ Consider the following example::
+
+ class C(A, B):
+ ...
+
+ classImplements(C, IA, IB. IC)
+ classImplementsOnly(C. I1, I2)
+
+ Instances of ``C`` provide only ``I1``, ``I2``, and regardless of
+ whatever interfaces instances of ``A`` and ``B`` implement.
+ """
+
+ def directlyProvidedBy(object):
+ """Return the interfaces directly provided by the given object
+
+ The value returned is an IDeclaration.
+ """
+
+ def directlyProvides(object, *interfaces):
+ """Declare interfaces declared directly for an object
+
+ The arguments after the object are one or more interfaces or
+ interface specifications (IDeclaration objects).
+
+ The interfaces given (including the interfaces in the
+ specifications) replace interfaces viously
+ declared for the object.
+
+ Consider the following example::
+
+ class C(A, B):
+ ...
+
+ ob = C()
+ directlyProvides(ob, I1, I2)
+
+ The object, ``ob`` provides ``I1``, ``I2``, and whatever interfaces
+ instances have been declared for instances of ``C``.
+
+ To remove directly provided interfaces, use ``directlyProvidedBy`` and
+ subtract the unwanted interfaces. For example::
+
+ directlyProvides(ob, directlyProvidedBy(ob)-I2)
+
+ removes I2 from the interfaces directly provided by
+ ``ob``. The object, ``ob`` no longer directly provides ``I2``,
+ although it might still provide ``I2`` if it's class
+ implements ``I2``.
+
+ To add directly provided interfaces, use ``directlyProvidedBy`` and
+ include additional interfaces. For example::
+
+ directlyProvides(ob, directlyProvidedBy(ob), I2)
+
+ adds I2 to the interfaces directly provided by ob.
+ """
+
+ def implements(*interfaces):
+ """Declare interfaces implemented by instances of a class
+
+ This function is called in a class definition.
+
+ The arguments are one or more interfaces or interface
+ specifications (IDeclaration objects).
+
+ The interfaces given (including the interfaces in the
+ specifications) are added to any interfaces viously
+ declared.
+
+ Previous declarations include declarations for base classes
+ unless implementsOnly was used.
+
+ This function is provided for convenience. It provides a more
+ convenient way to call classImplements. For example::
+
+ implements(I1)
+
+ is equivalent to calling::
+
+ classImplements(C, I1)
+
+ after the class has been created.
+
+ Consider the following example::
+
+ class C(A, B):
+ implements(I1, I2)
+
+
+ Instances of ``C`` implement ``I1``, ``I2``, and whatever interfaces
+ instances of ``A`` and ``B`` implement.
+ """
+
+ def implementsOnly(*interfaces):
+ """Declare the only interfaces implemented by instances of a class
+
+ This function is called in a class definition.
+
+ The arguments are one or more interfaces or interface
+ specifications (IDeclaration objects).
+
+ Previous declarations including declarations for base classes
+ are overridden.
+
+ This function is provided for convenience. It provides a more
+ convenient way to call classImplementsOnly. For example::
+
+ implementsOnly(I1)
+
+ is equivalent to calling::
+
+ classImplementsOnly(I1)
+
+ after the class has been created.
+
+ Consider the following example::
+
+ class C(A, B):
+ implementsOnly(I1, I2)
+
+
+ Instances of ``C`` implement ``I1``, ``I2``, regardless of what
+ instances of ``A`` and ``B`` implement.
+ """
+
+ def classProvides(*interfaces):
+ """Declare interfaces provided directly by a class
+
+ This function is called in a class definition.
+
+ The arguments are one or more interfaces or interface
+ specifications (IDeclaration objects).
+
+ The given interfaces (including the interfaces in the
+ specifications) are used to create the class's direct-object
+ interface specification. An error will be raised if the module
+ class has an direct interface specification. In other words, it is
+ an error to call this function more than once in a class
+ definition.
+
+ Note that the given interfaces have nothing to do with the
+ interfaces implemented by instances of the class.
+
+ This function is provided for convenience. It provides a more
+ convenient way to call directlyProvides for a class. For example::
+
+ classProvides(I1)
+
+ is equivalent to calling::
+
+ directlyProvides(theclass, I1)
+
+ after the class has been created.
+ """
+
+ def moduleProvides(*interfaces):
+ """Declare interfaces provided by a module
+
+ This function is used in a module definition.
+
+ The arguments are one or more interfaces or interface
+ specifications (IDeclaration objects).
+
+ The given interfaces (including the interfaces in the
+ specifications) are used to create the module's direct-object
+ interface specification. An error will be raised if the module
+ already has an interface specification. In other words, it is
+ an error to call this function more than once in a module
+ definition.
+
+ This function is provided for convenience. It provides a more
+ convenient way to call directlyProvides for a module. For example::
+
+ moduleImplements(I1)
+
+ is equivalent to::
+
+ directlyProvides(sys.modules[__name__], I1)
+ """
+
+ def Declaration(*interfaces):
+ """Create an interface specification
+
+ The arguments are one or more interfaces or interface
+ specifications (IDeclaration objects).
+
+ A new interface specification (IDeclaration) with
+ the given interfaces is returned.
+ """
+
+class IAdapterRegistry(Interface):
+ """Provide an interface-based registry for adapters
+
+ This registry registers objects that are in some sense "from" a
+ sequence of specification to an interface and a name.
+
+ No specific semantics are assumed for the registered objects,
+ however, the most common application will be to register factories
+ that adapt objects providing required specifications to a provided
+ interface.
+
+ """
+
+ def register(required, provided, name, value):
+ """Register a value
+
+ A value is registered for a *sequence* of required specifications, a
+ provided interface, and a name.
+ """
+
+ def lookup(required, provided, name, default=None):
+ """Lookup a value
+
+ A value is looked up based on a *sequence* of required
+ specifications, a provided interface, and a name.
+ """
+
+ def lookupAll(required, provided):
+ """Find all adapters from the required to the provided interfaces
+
+ An iterable object is returned that provides name-value two-tuples.
+ """
+
+ def names(required, provided):
+ """Return the names for which there are registered objects
+ """
+
+ def subscribe(required, provided, subscriber):
+ """Register a subscriber
+
+ A subscriber is registered for a *sequence* of required
+ specifications, a provided interface, and a name.
+
+ Multiple subscribers may be registered for the same (or
+ equivalent) interfaces.
+ """
+
+ def subscriptions(required, provided):
+ """Get a sequence of subscribers
+
+ Subscribers for a *sequence* of required interfaces, and a provided
+ interface are returned.
+ """
+
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/ro.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/ro.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,63 @@ />
+##############################################################################
+#
+# Copyright (c) 2003 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.
+#
+##############################################################################
+"""Compute a resolution order for an object and it's bases
+
+$Id: ro.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+def ro(object):
+ """Compute a "resolution order" for an object
+ """
+ return mergeOrderings([_flatten(object, [])])
+
+def mergeOrderings(orderings, seen=None):
+ """Merge multiple orderings so that within-ordering order is served
+
+ Orderings are constrained in such a way that if an object appears
+ in two or more orderings, then the suffix that begins with the
+ object must be in both orderings.
+
+ For example:
+
+ >>> _mergeOrderings([
+ ... ['x', 'y', 'z'],
+ ... ['q', 'z'],
+ ... [1, 3, 5],
+ ... ['z']
+ ... ])
+ ['x', 'y', 'q', 1, 3, 5, 'z']
+
+ """
+
+ if seen is None:
+ seen = {}
+ result = []
+ orderings.reverse()
+ for ordering in orderings:
+ ordering = list(ordering)
+ ordering.reverse()
+ for o in ordering:
+ if o not in seen:
+ seen[o] = 1
+ result.append(o)
+
+ result.reverse()
+ return result
+
+def _flatten(ob, result):
+ result.append(ob)
+ for base in ob.__bases__:
+ _flatten(base, result)
+
+ return result
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/__init__.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/__init__.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,2 @@ />
+#
+# This file is necessary to make this directory a package.
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/docfilesuite.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/docfilesuite.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,44 @@ />
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Utility to create doc tests from readme files
+
+$Id: docfilesuite.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+import os, doctest, new, unittest
+
+def DocFileSuite(*paths):
+ """Utility to create doc tests from readme files
+
+ Eventually, this, or something like it, will be part of doctest
+ """
+ # It's not entirely obvious how to connection this single string
+ # with unittest. For now, re-use the _utest() function that comes
+ # standard with doctest in Python 2.3. One problem is that the
+ # error indicator doesn't point to the line of the doctest file
+ # that failed.
+ t = doctest.Tester(globs={'__name__': '__main__'})
+ suite = unittest.TestSuite()
+ dir = os.path.split(__file__)[0]
+ for path in paths:
+ path = os.path.join(dir, path)
+ source = open(path).read()
+ def runit(path=path, source=source):
+ doctest._utest(t, path, source, path, 0)
+ runit = new.function(runit.func_code, runit.func_globals, path,
+ runit.func_defaults, runit.func_closure)
+ f = unittest.FunctionTestCase(runit,
+ description="doctest from %s" % path)
+ suite.addTest(f)
+ return suite
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/dummy.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/dummy.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,21 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+from zope.interface import moduleProvides
+from zope.interface.tests.ifoo import IFoo
+from zope.interface import moduleProvides
+
+moduleProvides(IFoo)
+
+def bar(baz):
+ pass
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/foodforthought.txt
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/foodforthought.txt Wed Jun 2 16:09:24 2004
@@ -0,0 +1,61 @@ />
+================================
+Food-based subscription examples
+================================
+
+
+This file gives more subscription examples using a cooking-based examples
+
+ >>> from zope.interface.adapter import AdapterRegistry
+ >>> registry = AdapterRegistry()
+
+ >>> import zope.interface
+ >>> class IAnimal(zope.interface.Interface):
+ ... pass
+ >>> class IPoultry(IAnimal):
+ ... pass
+ >>> class IChicken(IPoultry):
+ ... pass
+ >>> class ISeafood(IAnimal):
+ ... pass
+
+Adapting to some other interface for which there is no
+subscription adapter returns an empty sequence:
+
+ >>> class IRecipe(zope.interface.Interface):
+ ... pass
+ >>> class ISausages(IRecipe):
+ ... pass
+ >>> class INoodles(IRecipe):
+ ... pass
+ >>> class IKFC(IRecipe):
+ ... pass
+
+>>> list(registry.subscriptions([IPoultry], IRecipe))
+[]
+
+unless we define a subscription::
+
+>>> registry.subscribe([IAnimal], ISausages, 'sausages')
+>>> list(registry.subscriptions([IPoultry], ISausages))
+['sausages']
+
+And define another subscription adapter:
+
+>>> registry.subscribe([IPoultry], INoodles, 'noodles')
+>>> meals = list(registry.subscriptions([IPoultry], IRecipe))
+>>> meals.sort()
+>>> meals
+['noodles', 'sausages']
+
+>>> registry.subscribe([IChicken], IKFC, 'kfc')
+>>> meals = list(registry.subscriptions([IChicken], IRecipe))
+>>> meals.sort()
+>>> meals
+['kfc', 'noodles', 'sausages']
+
+And the answer for poultry hasn't changed:
+
+>>> meals = list(registry.subscriptions([IPoultry], IRecipe))
+>>> meals.sort()
+>>> meals
+['noodles', 'sausages']
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/ifoo.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/ifoo.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,24 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+from zope.interface import Interface
+
+class IFoo(Interface):
+ """
+ Dummy interface for unit tests.
+ """
+
+ def bar(baz):
+ """
+ Just a note.
+ """
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/m1.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/m1.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,9 @@ />
+"""Test module that declares an interface
+"""
+
+from zope.interface import Interface, moduleProvides
+
+class I1(Interface): pass
+class I2(Interface): pass
+
+moduleProvides(I1, I2)
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/m2.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/m2.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,2 @@ />
+"""Test module that doesn't declare an interface
+"""
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/odd.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/odd.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,129 @@ />
+##############################################################################
+#
+# Copyright (c) 2003 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.
+#
+##############################################################################
+"""Odd meta class that doesn't subclass type.
+
+This is used for testing support for ExtensionClass in new interfaces.
+
+ >>> class A:
+ ... __metaclass__ = MetaClass
+ ... a = 1
+ ...
+ >>> A.__name__
+ 'A'
+ >>> A.__bases__
+ ()
+ >>> class B:
+ ... __metaclass__ = MetaClass
+ ... b = 1
+ ...
+ >>> class C(A, B): pass
+ ...
+ >>> C.__name__
+ 'C'
+ >>> int(C.__bases__ == (A, B))
+ 1
+ >>> a = A()
+ >>> aa = A()
+ >>> a.a
+ 1
+ >>> aa.a
+ 1
+ >>> aa.a = 2
+ >>> a.a
+ 1
+ >>> aa.a
+ 2
+ >>> c = C()
+ >>> c.a
+ 1
+ >>> c.b
+ 1
+ >>> c.b = 2
+ >>> c.b
+ 2
+ >>> C.c = 1
+ >>> c.c
+ 1
+ >>> from types import ClassType
+ >>> int(isinstance(C, (type, ClassType)))
+ 0
+ >>> int(C.__class__.__class__ is C.__class__)
+ 1
+
+$Id: odd.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+# class OddClass is an odd meta class
+
+class MetaMetaClass(type):
+
+ def __getattribute__(self, name):
+ if name == '__class__':
+ return self
+ return type.__getattribute__(self, name)
+
+
+class MetaClass(object):
+ """Odd classes
+ """
+ __metaclass__ = MetaMetaClass
+
+ def __init__(self, name, bases, dict):
+ self.__name__ = name
+ self.__bases__ = bases
+ self.__dict__.update(dict)
+
+ def __call__(self):
+ return OddInstance(self)
+
+ def __getattr__(self, name):
+ for b in self.__bases__:
+ v = getattr(b, name, self)
+ if v is not self:
+ return v
+ raise AttributeError, name
+
+ def __repr__(self):
+ return "<odd class %s at %s>" % (self.__name__, hex(id(self)))
+
+class OddInstance(object):
+
+ def __init__(self, cls):
+ self.__dict__['__class__'] = cls
+
+ def __getattribute__(self, name):
+ dict = object.__getattribute__(self, '__dict__')
+ if name == '__dict__':
+ return dict
+ v = dict.get(name, self)
+ if v is not self:
+ return v
+ return getattr(dict['__class__'], name)
+
+ def __setattr__(self, name, v):
+ self.__dict__[name] = v
+
+ def __delattr__(self, name):
+ del self.__dict__[name]
+
+ def __repr__(self):
+ return "<odd %s instance at %s>" % (
+ self.__class__.__name__, hex(id(self)))
+
+
+
+# DocTest:
+if __name__ == "__main__":
+ import doctest, __main__
+ doctest.testmod(__main__, isprivate=lambda *a: False)
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_adapter.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_adapter.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,143 @@ />
+##############################################################################
+#
+# Copyright (c) 2003 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.
+#
+##############################################################################
+"""Adapter registry tests
+
+$Id: test_adapter.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+import unittest, doctest
+import zope.interface
+from zope.interface.adapter import AdapterRegistry
+import zope.interface
+
+class IF0(zope.interface.Interface):
+ pass
+class IF1(IF0):
+ pass
+
+class IB0(zope.interface.Interface):
+ pass
+class IB1(IB0):
+ pass
+
+class IR0(zope.interface.Interface):
+ pass
+class IR1(IR0):
+ pass
+
+def test_multi_adapter_w_default():
+ """
+ >>> registry = AdapterRegistry()
+
+ >>> registry.register([None, None], IB1, 'bob', 'A0')
+
+ >>> registry.lookup((IF1, IR1), IB0, 'bob')
+ 'A0'
+
+ >>> registry.register([None, IR0], IB1, 'bob', 'A1')
+
+ >>> registry.lookup((IF1, IR1), IB0, 'bob')
+ 'A1'
+
+ >>> registry.lookup((IF1, IR1), IB0, 'bruce')
+
+ >>> registry.register([None, IR1], IB1, 'bob', 'A2')
+ >>> registry.lookup((IF1, IR1), IB0, 'bob')
+ 'A2'
+ """
+
+def test_multi_adapter_w_inherited_and_multiple_registrations():
+ """
+ >>> registry = AdapterRegistry()
+
+ >>> class IX(zope.interface.Interface):
+ ... pass
+
+ >>> registry.register([IF0, IR0], IB1, 'bob', 'A1')
+ >>> registry.register([IF1, IX], IB1, 'bob', 'AX')
+
+ >>> registry.lookup((IF1, IR1), IB0, 'bob')
+ 'A1'
+ """
+
+def test_named_adapter_with_default():
+ """Query a named simple adapter
+
+ >>> registry = AdapterRegistry()
+
+ If we ask for a named adapter, we won't get a result unless there
+ is a named adapter, even if the object implements the interface:
+
+ >>> registry.lookup([IF1], IF0, 'bob')
+
+ >>> registry.register([None], IB1, 'bob', 'A1')
+ >>> registry.lookup([IF1], IB0, 'bob')
+ 'A1'
+
+ >>> registry.lookup([IF1], IB0, 'bruce')
+
+ >>> registry.register([None], IB0, 'bob', 'A2')
+ >>> registry.lookup([IF1], IB0, 'bob')
+ 'A2'
+ """
+
+def test_multi_adapter_gets_closest_provided():
+ """
+ >>> registry = AdapterRegistry()
+ >>> registry.register([IF1, IR0], IB0, 'bob', 'A1')
+ >>> registry.register((IF1, IR0), IB1, 'bob', 'A2')
+ >>> registry.lookup((IF1, IR1), IB0, 'bob')
+ 'A1'
+
+ >>> registry = AdapterRegistry()
+ >>> registry.register([IF1, IR0], IB1, 'bob', 'A2')
+ >>> registry.register([IF1, IR0], IB0, 'bob', 'A1')
+ >>> registry.lookup([IF1, IR0], IB0, 'bob')
+ 'A1'
+
+ >>> registry = AdapterRegistry()
+ >>> registry.register([IF1, IR0], IB0, 'bob', 'A1')
+ >>> registry.register([IF1, IR1], IB1, 'bob', 'A2')
+ >>> registry.lookup([IF1, IR1], IB0, 'bob')
+ 'A2'
+
+ >>> registry = AdapterRegistry()
+ >>> registry.register([IF1, IR1], IB1, 'bob', 2)
+ >>> registry.register([IF1, IR0], IB0, 'bob', 1)
+ >>> registry.lookup([IF1, IR1], IB0, 'bob')
+ 2
+ """
+
+def test_multi_adapter_check_non_default_dont_hide_default():
+ """
+ >>> registry = AdapterRegistry()
+
+ >>> class IX(zope.interface.Interface):
+ ... pass
+
+
+ >>> registry.register([None, IR0], IB0, 'bob', 1)
+ >>> registry.register([IF1, IX], IB0, 'bob', 2)
+ >>> registry.lookup([IF1, IR1], IB0, 'bob')
+ 1
+ """
+
+
+def test_suite():
+ from docfilesuite import DocFileSuite
+ return unittest.TestSuite((
+ DocFileSuite('../adapter.txt', 'foodforthought.txt'),
+ doctest.DocTestSuite(),
+ ))
+
+if __name__ == '__main__': unittest.main()
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_advice.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_advice.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,195 @@ />
+
+##############################################################################
+#
+# Copyright (c) 2003 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.
+#
+##############################################################################
+"""Tests for advice
+
+This module was adapted from 'protocols.tests.advice', part of the Python
+Enterprise Application Kit (PEAK). Please notify the PEAK authors
+(pje@telecommunity.com and tsarna@sarna.org) if bugs are found or
+Zope-specific changes are required, so that the PEAK version of this module
+can be kept in sync.
+
+PEAK is a Python application framework that interoperates with (but does
+not require) Zope 3 and Twisted. It provides tools for manipulating UML
+models, object-relational persistence, aspect-oriented programming, and more.
+Visit the PEAK home page at http://peak.telecommunity.com for more information.
+
+$Id: test_advice.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+from unittest import TestCase, makeSuite, TestSuite
+from zope.interface.advice import *
+from types import ClassType
+import sys
+
+def ping(log, value):
+
+ def pong(klass):
+ log.append((value,klass))
+ return [klass]
+
+ addClassAdvisor(pong)
+
+class ClassicClass:
+ __metaclass__ = ClassType
+ classLevelFrameInfo = getFrameInfo(sys._getframe())
+
+class NewStyleClass:
+ __metaclass__ = type
+ classLevelFrameInfo = getFrameInfo(sys._getframe())
+
+moduleLevelFrameInfo = getFrameInfo(sys._getframe())
+
+class FrameInfoTest(TestCase):
+
+ classLevelFrameInfo = getFrameInfo(sys._getframe())
+
+ def checkModuleInfo(self):
+ kind, module, f_locals, f_globals = moduleLevelFrameInfo
+ self.assertEquals(kind, "module")
+ for d in module.__dict__, f_locals, f_globals:
+ self.assert_(d is globals())
+
+ def checkClassicClassInfo(self):
+ kind, module, f_locals, f_globals = ClassicClass.classLevelFrameInfo
+ self.assertEquals(kind, "class")
+
+ self.assert_(f_locals is ClassicClass.__dict__) # ???
+ for d in module.__dict__, f_globals:
+ self.assert_(d is globals())
+
+ def checkNewStyleClassInfo(self):
+ kind, module, f_locals, f_globals = NewStyleClass.classLevelFrameInfo
+ self.assertEquals(kind, "class")
+
+ for d in module.__dict__, f_globals:
+ self.assert_(d is globals())
+
+ def checkCallInfo(self):
+ kind, module, f_locals, f_globals = getFrameInfo(sys._getframe())
+ self.assertEquals(kind, "function call")
+ self.assert_(f_locals is locals()) # ???
+ for d in module.__dict__, f_globals:
+ self.assert_(d is globals())
+
+
+class AdviceTests(TestCase):
+
+ def checkOrder(self):
+ log = []
+ class Foo:
+ ping(log, 1)
+ ping(log, 2)
+ ping(log, 3)
+
+ # Strip the list nesting
+ for i in 1,2,3:
+ self.assert_(isinstance(Foo, list))
+ Foo, = Foo
+
+ self.assertEquals(log, [(1, Foo), (2, [Foo]), (3, [[Foo]])])
+
+ def XXXcheckOutside(self):
+ # Disabled because the check does not work with doctest tests.
+ try:
+ ping([], 1)
+ except SyntaxError:
+ pass
+ else:
+ raise AssertionError(
+ "Should have detected advice outside class body"
+ )
+
+ def checkDoubleType(self):
+ if sys.hexversion >= 0x02030000:
+ return # you can't duplicate bases in 2.3
+ class aType(type,type):
+ ping([],1)
+ aType, = aType
+ self.assert_(aType.__class__ is type)
+
+ def checkSingleExplicitMeta(self):
+
+ class M(type):
+ pass
+
+ class C(M):
+ __metaclass__ = M
+ ping([],1)
+
+ C, = C
+ self.assert_(C.__class__ is M)
+
+
+ def checkMixedMetas(self):
+
+ class M1(type): pass
+ class M2(type): pass
+
+ class B1: __metaclass__ = M1
+ class B2: __metaclass__ = M2
+
+ try:
+ class C(B1,B2):
+ ping([],1)
+ except TypeError:
+ pass
+ else:
+ raise AssertionError("Should have gotten incompatibility error")
+
+ class M3(M1,M2): pass
+
+ class C(B1,B2):
+ __metaclass__ = M3
+ ping([],1)
+
+ self.assert_(isinstance(C,list))
+ C, = C
+ self.assert_(isinstance(C,M3))
+
+ def checkMetaOfClass(self):
+
+ class metameta(type):
+ pass
+
+ class meta(type):
+ __metaclass__ = metameta
+
+ self.assertEquals(determineMetaclass((meta, type)), metameta)
+
+TestClasses = (AdviceTests, FrameInfoTest)
+
+def test_suite():
+ return TestSuite([makeSuite(t,'check') for t in TestClasses])
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_declarations.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_declarations.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,293 @@ />
+##############################################################################
+#
+# Copyright (c) 2003 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.
+#
+##############################################################################
+"""Test the new API for making and checking interface declarations
+
+
+$Id: test_declarations.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+import unittest
+from zope.interface import *
+from zope.testing.doctestunit import DocTestSuite
+from zope.interface import Interface
+
+class I1(Interface): pass
+class I2(Interface): pass
+class I3(Interface): pass
+class I4(Interface): pass
+class I5(Interface): pass
+
+class A:
+ implements(I1)
+class B:
+ implements(I2)
+class C(A, B):
+ implements(I3)
+
+class COnly(A, B):
+ implementsOnly(I3)
+
+class COnly_old(A, B):
+ __implemented__ = I3
+
+class D(COnly):
+ implements(I5)
+
+def test_ObjectSpecification_Simple():
+ """
+ >>> c = C()
+ >>> directlyProvides(c, I4)
+ >>> [i.__name__ for i in providedBy(c)]
+ ['I4', 'I3', 'I1', 'I2']
+ """
+
+def test_ObjectSpecification_Simple_w_only():
+ """
+ >>> c = COnly()
+ >>> directlyProvides(c, I4)
+ >>> [i.__name__ for i in providedBy(c)]
+ ['I4', 'I3']
+ """
+
+def test_ObjectSpecification_Simple_old_style():
+ """
+ >>> c = COnly_old()
+ >>> directlyProvides(c, I4)
+ >>> [i.__name__ for i in providedBy(c)]
+ ['I4', 'I3']
+ """
+
+
+class Test(unittest.TestCase):
+
+ # Note that most of the tests are in the doc strings of the
+ # declarations module.
+
+ def test_backward_compat(self):
+
+ class C1: __implemented__ = I1
+ class C2(C1): __implemented__ = I2, I5
+ class C3(C2): __implemented__ = I3, C2.__implemented__
+
+ self.assert_(C3.__implemented__.__class__ is tuple)
+
+ self.assertEqual(
+ [i.getName() for i in providedBy(C3())],
+ ['I3', 'I2', 'I5'],
+ )
+
+ class C4(C3):
+ implements(I4)
+
+ self.assertEqual(
+ [i.getName() for i in providedBy(C4())],
+ ['I4', 'I3', 'I2', 'I5'],
+ )
+
+ self.assertEqual(
+ [i.getName() for i in C4.__implemented__],
+ ['I4', 'I3', 'I2', 'I5'],
+ )
+
+ # Note that C3.__implemented__ should now be a sequence of interfaces
+ self.assertEqual(
+ [i.getName() for i in C3.__implemented__],
+ ['I3', 'I2', 'I5'],
+ )
+ self.failIf(C3.__implemented__.__class__ is tuple)
+
+ def test_module(self):
+ import zope.interface.tests.m1
+ import zope.interface.tests.m2
+ directlyProvides(zope.interface.tests.m2,
+ zope.interface.tests.m1.I1,
+ zope.interface.tests.m1.I2,
+ )
+ self.assertEqual(list(providedBy(zope.interface.tests.m1)),
+ list(providedBy(zope.interface.tests.m2)),
+ )
+
+ def test_builtins(self):
+ # Setup
+
+ intspec = implementedBy(int)
+ olddeclared = intspec.declared
+
+ classImplements(int, I1)
+ class myint(int):
+ implements(I2)
+
+ x = 42
+ self.assertEqual([i.getName() for i in providedBy(x)],
+ ['I1'])
+
+ x = myint(42)
+ directlyProvides(x, I3)
+ self.assertEqual([i.getName() for i in providedBy(x)],
+ ['I3', 'I2', 'I1'])
+
+ # cleanup
+ intspec.declared = olddeclared
+ classImplements(int)
+
+ x = 42
+ self.assertEqual([i.getName() for i in providedBy(x)],
+ [])
+
+
+def test_signature_w_no_class_interfaces():
+ """
+ >>> from zope.interface import *
+ >>> class C:
+ ... pass
+ >>> c = C()
+ >>> list(providedBy(c))
+ []
+
+ >>> class I(Interface):
+ ... pass
+ >>> directlyProvides(c, I)
+ >>> list(providedBy(c)) == list(directlyProvidedBy(c))
+ 1
+ """
+
+def test_classImplement_on_deeply_nested_classes():
+ """This test is in response to a bug found, which is why it's a bit
+ contrived
+
+ >>> from zope.interface import *
+ >>> class B1:
+ ... pass
+ >>> class B2(B1):
+ ... pass
+ >>> class B3(B2):
+ ... pass
+ >>> class D:
+ ... implements()
+ >>> class S(B3, D):
+ ... implements()
+
+ This failed due to a bug in the code for finding __providedBy__
+ descriptors for old-style classes.
+
+ """
+
+def test_pickle_provides_specs():
+ """
+ >>> from pickle import dumps, loads
+ >>> a = A()
+ >>> I2.providedBy(a)
+ 0
+ >>> directlyProvides(a, I2)
+ >>> I2.providedBy(a)
+ 1
+ >>> a2 = loads(dumps(a))
+ >>> I2.providedBy(a2)
+ 1
+
+ """
+
+def test_that_we_dont_inherit_class_provides():
+ """
+ >>> class X:
+ ... classProvides(I1)
+ >>> class Y(X):
+ ... pass
+ >>> [i.__name__ for i in X.__provides__]
+ ['I1']
+ >>> Y.__provides__
+ Traceback (most recent call last):
+ ...
+ AttributeError: __provides__
+
+ """
+
+def test_that_we_dont_inherit_provides_optimizations():
+ """
+
+ When we make a declaration for a class, we install a __provides__
+ descriptors that provides a default for instances that don't have
+ instance-specific declarations:
+
+ >>> class A:
+ ... implements(I1)
+
+ >>> class B:
+ ... implements(I2)
+
+ >>> [i.__name__ for i in A().__provides__]
+ ['I1']
+ >>> [i.__name__ for i in B().__provides__]
+ ['I2']
+
+ But it's important that we don't use this for subclasses without
+ declarations. This would cause incorrect results:
+
+ >>> class X(A, B):
+ ... pass
+
+ >>> X().__provides__
+ Traceback (most recent call last):
+ ...
+ AttributeError: __provides__
+
+ However, if we "induce" a declaration, by calling implementedBy
+ (even indirectly through providedBy):
+
+ >>> [i.__name__ for i in providedBy(X())]
+ ['I1', 'I2']
+
+
+ then the optimization will work:
+
+ >>> [i.__name__ for i in X().__provides__]
+ ['I1', 'I2']
+
+ """
+
+def test_classProvides_before_implements():
+ """Special descriptor for class __provides__
+
+ The descriptor caches the implementedBy info, so that
+ we can get declarations for objects without instance-specific
+ interfaces a bit quicker.
+
+ For example::
+
+ >>> from zope.interface import Interface
+ >>> class IFooFactory(Interface):
+ ... pass
+ >>> class IFoo(Interface):
+ ... pass
+ >>> class C:
+ ... classProvides(IFooFactory)
+ ... implements(IFoo)
+ >>> [i.getName() for i in C.__provides__]
+ ['IFooFactory']
+
+ >>> [i.getName() for i in C().__provides__]
+ ['IFoo']
+ """
+
+def test_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(Test))
+ suite.addTest(DocTestSuite("zope.interface.declarations"))
+ suite.addTest(DocTestSuite())
+
+ return suite
+
+
+if __name__ == '__main__':
+ unittest.main()
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_document.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_document.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,73 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id: test_document.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+from unittest import TestCase, main, makeSuite
+from zope.interface import Interface
+from zope.interface.interface import Attribute
+
+class Test(TestCase):
+
+ def testBlech(self):
+ from zope.interface.document import asStructuredText
+
+ self.assertEqual(asStructuredText(I2), '''\
+I2
+
+ I2 doc
+
+ This interface extends:
+
+ o _I1
+
+ Attributes:
+
+ a1 -- no documentation
+
+ a2 -- a2 doc
+
+ Methods:
+
+ f21() -- f21 doc
+
+ f22() -- no documentation
+
+ f23() -- f23 doc
+
+''')
+
+
+def test_suite():
+ return makeSuite(Test)
+
+class _I1(Interface):
+ def f11(): pass
+ def f12(): pass
+
+class I2(_I1):
+ "I2 doc"
+
+ a1 = Attribute('a1')
+ a2 = Attribute('a2', 'a2 doc')
+
+ def f21(): "f21 doc"
+ def f22(): pass
+ def f23(): "f23 doc"
+
+if __name__=='__main__':
+ main(defaultTest='test_suite')
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_element.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_element.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,46 @@ />
+##############################################################################
+#
+# Copyright (c) 2003 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.
+#
+##############################################################################
+"""XXX short summary goes here.
+
+XXX longer description goes here.
+
+$Id: test_element.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+import unittest
+from zope.interface.interface import Element
+
+class TestElement(unittest.TestCase):
+
+ def test_taggedValues(self):
+ """Test that we can update tagged values of more than one element
+ """
+
+ e1 = Element("foo")
+ e2 = Element("bar")
+ e1.setTaggedValue("x", 1)
+ e2.setTaggedValue("x", 2)
+ self.assertEqual(e1.getTaggedValue("x"), 1)
+ self.assertEqual(e2.getTaggedValue("x"), 2)
+
+
+
+def test_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(TestElement))
+ return suite
+
+
+if __name__ == '__main__':
+ unittest.main()
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_interface.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_interface.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,281 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+
+import unittest
+from zope.testing.doctestunit import DocTestSuite
+from zope.interface.tests.unitfixtures import * # hehehe
+from zope.interface.exceptions import BrokenImplementation, Invalid
+from zope.interface import implementedBy, providedBy
+from zope.interface import Interface, directlyProvides, Attribute
+
+class InterfaceTests(unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def testClassImplements(self):
+ self.assert_(IC.implementedBy(C))
+
+ self.assert_(I1.implementedBy(A))
+ self.assert_(I1.implementedBy(B))
+ self.assert_(not I1.implementedBy(C))
+ self.assert_(I1.implementedBy(D))
+ self.assert_(I1.implementedBy(E))
+
+ self.assert_(not I2.implementedBy(A))
+ self.assert_(I2.implementedBy(B))
+ self.assert_(not I2.implementedBy(C))
+
+ # No longer after interfacegeddon
+ # self.assert_(not I2.implementedBy(D))
+
+ self.assert_(not I2.implementedBy(E))
+
+ def testUtil(self):
+ self.assert_(IC in implementedBy(C))
+ self.assert_(I1 in implementedBy(A))
+ self.assert_(not I1 in implementedBy(C))
+ self.assert_(I2 in implementedBy(B))
+ self.assert_(not I2 in implementedBy(C))
+
+ self.assert_(IC in providedBy(C()))
+ self.assert_(I1 in providedBy(A()))
+ self.assert_(not I1 in providedBy(C()))
+ self.assert_(I2 in providedBy(B()))
+ self.assert_(not I2 in providedBy(C()))
+
+
+ def testObjectImplements(self):
+ self.assert_(IC.providedBy(C()))
+
+ self.assert_(I1.providedBy(A()))
+ self.assert_(I1.providedBy(B()))
+ self.assert_(not I1.providedBy(C()))
+ self.assert_(I1.providedBy(D()))
+ self.assert_(I1.providedBy(E()))
+
+ self.assert_(not I2.providedBy(A()))
+ self.assert_(I2.providedBy(B()))
+ self.assert_(not I2.providedBy(C()))
+
+ # Not after interface geddon
+ # self.assert_(not I2.providedBy(D()))
+
+ self.assert_(not I2.providedBy(E()))
+
+ def testDeferredClass(self):
+ a = A()
+ self.assertRaises(BrokenImplementation, a.ma)
+
+
+ def testInterfaceExtendsInterface(self):
+ self.assert_(BazInterface.extends(BobInterface))
+ self.assert_(BazInterface.extends(BarInterface))
+ self.assert_(BazInterface.extends(FunInterface))
+ self.assert_(not BobInterface.extends(FunInterface))
+ self.assert_(not BobInterface.extends(BarInterface))
+ self.assert_(BarInterface.extends(FunInterface))
+ self.assert_(not BarInterface.extends(BazInterface))
+
+ def testVerifyImplementation(self):
+ from zope.interface.verify import verifyClass
+ self.assert_(verifyClass(FooInterface, Foo))
+ self.assert_(Interface.providedBy(I1))
+
+ def test_names(self):
+ names = list(_I2.names()); names.sort()
+ self.assertEqual(names, ['f21', 'f22', 'f23'])
+ names = list(_I2.names(all=True)); names.sort()
+ self.assertEqual(names, ['a1', 'f11', 'f12', 'f21', 'f22', 'f23'])
+
+ def test_namesAndDescriptions(self):
+ names = [nd[0] for nd in _I2.namesAndDescriptions()]; names.sort()
+ self.assertEqual(names, ['f21', 'f22', 'f23'])
+ names = [nd[0] for nd in _I2.namesAndDescriptions(1)]; names.sort()
+ self.assertEqual(names, ['a1', 'f11', 'f12', 'f21', 'f22', 'f23'])
+
+ for name, d in _I2.namesAndDescriptions(1):
+ self.assertEqual(name, d.__name__)
+
+ def test_getDescriptionFor(self):
+ self.assertEqual(_I2.getDescriptionFor('f11').__name__, 'f11')
+ self.assertEqual(_I2.getDescriptionFor('f22').__name__, 'f22')
+ self.assertEqual(_I2.queryDescriptionFor('f33', self), self)
+ self.assertRaises(KeyError, _I2.getDescriptionFor, 'f33')
+
+ def test___getitem__(self):
+ self.assertEqual(_I2['f11'].__name__, 'f11')
+ self.assertEqual(_I2['f22'].__name__, 'f22')
+ self.assertEqual(_I2.get('f33', self), self)
+ self.assertRaises(KeyError, _I2.__getitem__, 'f33')
+
+ def test___contains__(self):
+ self.failUnless('f11' in _I2)
+ self.failIf('f33' in _I2)
+
+ def test___iter__(self):
+ names = list(iter(_I2))
+ names.sort()
+ self.assertEqual(names, ['a1', 'f11', 'f12', 'f21', 'f22', 'f23'])
+
+ def testAttr(self):
+ description = _I2.getDescriptionFor('a1')
+ self.assertEqual(description.__name__, 'a1')
+ self.assertEqual(description.__doc__, 'This is an attribute')
+
+ def testFunctionAttributes(self):
+ # Make sure function attributes become tagged values.
+ meth = _I1['f12']
+ self.assertEqual(meth.getTaggedValue('optional'), 1)
+
+ def testInvariant(self):
+ # set up
+ o = InvariantC()
+ directlyProvides(o, IInvariant)
+ # a helper
+ def errorsEqual(self, o, error_len, error_msgs, interface=None):
+ if interface is None:
+ interface = IInvariant
+ self.assertRaises(Invalid, interface.validateInvariants, o)
+ e = []
+ try:
+ interface.validateInvariants(o, e)
+ except Invalid, error:
+ self.assertEquals(error.args[0], e)
+ else:
+ self._assert(0) # validateInvariants should always raise
+ # Invalid
+ self.assertEquals(len(e), error_len)
+ msgs = [error.args[0] for error in e]
+ msgs.sort()
+ for msg in msgs:
+ self.assertEquals(msg, error_msgs.pop(0))
+ # the tests
+ self.assertEquals(IInvariant.getTaggedValue('invariants'),
+ [ifFooThenBar])
+ self.assertEquals(IInvariant.validateInvariants(o), None)
+ o.bar = 27
+ self.assertEquals(IInvariant.validateInvariants(o), None)
+ o.foo = 42
+ self.assertEquals(IInvariant.validateInvariants(o), None)
+ del o.bar
+ errorsEqual(self, o, 1, ['If Foo, then Bar!'])
+ # nested interfaces with invariants:
+ self.assertEquals(ISubInvariant.getTaggedValue('invariants'),
+ [BarGreaterThanFoo])
+ o = InvariantC()
+ directlyProvides(o, ISubInvariant)
+ o.foo = 42
+ # even though the interface has changed, we should still only have one
+ # error.
+ errorsEqual(self, o, 1, ['If Foo, then Bar!'], ISubInvariant)
+ # however, if we set foo to 0 (Boolean False) and bar to a negative
+ # number then we'll get the new error
+ o.foo = 2
+ o.bar = 1
+ errorsEqual(self, o, 1, ['Please, Boo MUST be greater than Foo!'],
+ ISubInvariant)
+ # and if we set foo to a positive number and boo to 0, we'll
+ # get both errors!
+ o.foo = 1
+ o.bar = 0
+ errorsEqual(self, o, 2, ['If Foo, then Bar!',
+ 'Please, Boo MUST be greater than Foo!'],
+ ISubInvariant)
+ # for a happy ending, we'll make the invariants happy
+ o.foo = 1
+ o.bar = 2
+ self.assertEquals(IInvariant.validateInvariants(o), None) # woohoo
+ # now we'll do two invariants on the same interface,
+ # just to make sure that a small
+ # multi-invariant interface is at least minimally tested.
+ o = InvariantC()
+ directlyProvides(o, IInvariant)
+ o.foo = 42
+ old_invariants = IInvariant.getTaggedValue('invariants')
+ invariants = old_invariants[:]
+ invariants.append(BarGreaterThanFoo) # if you really need to mutate,
+ # then this would be the way to do it. Probably a bad idea, though. :-)
+ IInvariant.setTaggedValue('invariants', invariants)
+ #
+ # even though the interface has changed, we should still only have one
+ # error.
+ errorsEqual(self, o, 1, ['If Foo, then Bar!'])
+ # however, if we set foo to 0 (Boolean False) and bar to a negative
+ # number then we'll get the new error
+ o.foo = 2
+ o.bar = 1
+ errorsEqual(self, o, 1, ['Please, Boo MUST be greater than Foo!'])
+ # and if we set foo to a positive number and boo to 0, we'll
+ # get both errors!
+ o.foo = 1
+ o.bar = 0
+ errorsEqual(self, o, 2, ['If Foo, then Bar!',
+ 'Please, Boo MUST be greater than Foo!'])
+ # for another happy ending, we'll make the invariants happy again
+ o.foo = 1
+ o.bar = 2
+ self.assertEquals(IInvariant.validateInvariants(o), None) # bliss
+ # clean up
+ IInvariant.setTaggedValue('invariants', old_invariants)
+
+ def test___doc___element(self):
+ class I(Interface):
+ "xxx"
+
+ self.assertEqual(I.__doc__, "xxx")
+ self.assertEqual(list(I), [])
+
+ class I(Interface):
+ "xxx"
+
+ __doc__ = Attribute('the doc')
+
+ self.assertEqual(I.__doc__, "")
+ self.assertEqual(list(I), ['__doc__'])
+
+
+
+class _I1(Interface):
+
+ a1 = Attribute("This is an attribute")
+
+ def f11(): pass
+ def f12(): pass
+ f12.optional = 1
+
+class _I1_(_I1): pass
+class _I1__(_I1_): pass
+
+class _I2(_I1__):
+ def f21(): pass
+ def f22(): pass
+ f23 = f22
+
+
+def test_suite():
+ from docfilesuite import DocFileSuite
+ suite = unittest.makeSuite(InterfaceTests)
+ suite.addTest(DocTestSuite("zope.interface.interface"))
+ suite.addTest(DocFileSuite('../README.txt'))
+ return suite
+
+def main():
+ unittest.TextTestRunner().run(test_suite())
+
+if __name__=="__main__":
+ main()
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_odd_declarations.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_odd_declarations.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,205 @@ />
+##############################################################################
+#
+# Copyright (c) 2003 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.
+#
+##############################################################################
+"""Test interface declarations against ExtensionClass-like classes.
+
+These tests are to make sure we do something sane in the sense of
+classic ExtensionClass classes and instances.
+
+$Id: test_odd_declarations.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+import unittest, odd
+from zope.interface import Interface, implements, implementsOnly
+from zope.interface import directlyProvides, providedBy, directlyProvidedBy
+from zope.interface import classImplements, classImplementsOnly, implementedBy
+
+class I1(Interface): pass
+class I2(Interface): pass
+class I3(Interface): pass
+class I31(I3): pass
+class I4(Interface): pass
+class I5(Interface): pass
+
+class Odd: __metaclass__ = odd.MetaClass
+
+class B(Odd): __implemented__ = I2
+
+
+# XXX We are going to need more magic to make classProvides work with odd
+# classes. This will work in the next iteration. For now, we'll use
+# a different mechanism.
+
+# from zope.interface import classProvides
+
+class A(Odd):
+ implements(I1)
+
+class C(A, B):
+ implements(I31)
+
+
+class Test(unittest.TestCase):
+
+ def test_ObjectSpecification(self):
+ c = C()
+ directlyProvides(c, I4)
+ self.assertEqual([i.getName() for i in providedBy(c)],
+ ['I4', 'I31', 'I1', 'I2']
+ )
+ self.assertEqual([i.getName() for i in providedBy(c).flattened()],
+ ['I4', 'I31', 'I3', 'I1', 'I2', 'Interface']
+ )
+ self.assert_(I1 in providedBy(c))
+ self.failIf(I3 in providedBy(c))
+ self.assert_(providedBy(c).extends(I3))
+ self.assert_(providedBy(c).extends(I31))
+ self.failIf(providedBy(c).extends(I5))
+
+ class COnly(A, B):
+ implementsOnly(I31)
+
+ class D(COnly):
+ implements(I5)
+
+ classImplements(D, I5)
+
+ c = D()
+ directlyProvides(c, I4)
+ self.assertEqual([i.getName() for i in providedBy(c)],
+ ['I4', 'I5', 'I31'])
+ self.assertEqual([i.getName() for i in providedBy(c).flattened()],
+ ['I4', 'I5', 'I31', 'I3', 'Interface'])
+ self.failIf(I1 in providedBy(c))
+ self.failIf(I3 in providedBy(c))
+ self.assert_(providedBy(c).extends(I3))
+ self.failIf(providedBy(c).extends(I1))
+ self.assert_(providedBy(c).extends(I31))
+ self.assert_(providedBy(c).extends(I5))
+
+ class COnly(A, B): __implemented__ = I31
+ class D(COnly):
+ implements(I5)
+
+ classImplements(D, I5)
+ c = D()
+ directlyProvides(c, I4)
+ self.assertEqual([i.getName() for i in providedBy(c)],
+ ['I4', 'I5', 'I31'])
+ self.assertEqual([i.getName() for i in providedBy(c).flattened()],
+ ['I4', 'I5', 'I31', 'I3', 'Interface'])
+ self.failIf(I1 in providedBy(c))
+ self.failIf(I3 in providedBy(c))
+ self.assert_(providedBy(c).extends(I3))
+ self.failIf(providedBy(c).extends(I1))
+ self.assert_(providedBy(c).extends(I31))
+ self.assert_(providedBy(c).extends(I5))
+
+ def test_classImplements(self):
+ class A(Odd):
+ implements(I3)
+
+ class B(Odd):
+ implements(I4)
+
+ class C(A, B):
+ pass
+ classImplements(C, I1, I2)
+ self.assertEqual([i.getName() for i in implementedBy(C)],
+ ['I1', 'I2', 'I3', 'I4'])
+ classImplements(C, I5)
+ self.assertEqual([i.getName() for i in implementedBy(C)],
+ ['I1', 'I2', 'I5', 'I3', 'I4'])
+
+ def test_classImplementsOnly(self):
+ class A(Odd):
+ implements(I3)
+
+ class B(Odd):
+ implements(I4)
+
+ class C(A, B):
+ pass
+ classImplementsOnly(C, I1, I2)
+ self.assertEqual([i.__name__ for i in implementedBy(C)],
+ ['I1', 'I2'])
+
+
+ def test_directlyProvides(self):
+ class IA1(Interface): pass
+ class IA2(Interface): pass
+ class IB(Interface): pass
+ class IC(Interface): pass
+ class A(Odd):
+ implements(IA1, IA2)
+
+ class B(Odd):
+ implements(IB)
+
+ class C(A, B):
+ implements(IC)
+
+
+ ob = C()
+ directlyProvides(ob, I1, I2)
+ self.assert_(I1 in providedBy(ob))
+ self.assert_(I2 in providedBy(ob))
+ self.assert_(IA1 in providedBy(ob))
+ self.assert_(IA2 in providedBy(ob))
+ self.assert_(IB in providedBy(ob))
+ self.assert_(IC in providedBy(ob))
+
+ directlyProvides(ob, directlyProvidedBy(ob)-I2)
+ self.assert_(I1 in providedBy(ob))
+ self.failIf(I2 in providedBy(ob))
+ self.failIf(I2 in providedBy(ob))
+ directlyProvides(ob, directlyProvidedBy(ob), I2)
+ self.assert_(I2 in providedBy(ob))
+
+ def test_directlyProvides_fails_for_odd_class(self):
+ self.assertRaises(TypeError, directlyProvides, C, I5)
+
+ # XXX see above
+ def XXX_test_classProvides_fails_for_odd_class(self):
+ try:
+ class A(Odd):
+ classProvides(I1)
+ except TypeError:
+ pass # Sucess
+ self.assert_(False,
+ "Shouldn't be able to use directlyProvides on odd class."
+ )
+
+ def test_implementedBy(self):
+ class I2(I1): pass
+
+ class C1(Odd):
+ implements(I2)
+
+ class C2(C1):
+ implements(I3)
+
+ self.assertEqual([i.getName() for i in implementedBy(C2)],
+ ['I3', 'I2'])
+
+
+
+
+def test_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(Test))
+ return suite
+
+
+if __name__ == '__main__':
+ unittest.main()
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_sorting.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_sorting.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,49 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Test interface sorting
+
+$Id: test_sorting.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+from unittest import TestCase, TestSuite, main, makeSuite
+
+from zope.interface import Interface
+
+class I1(Interface): pass
+class I2(I1): pass
+class I3(I1): pass
+class I4(Interface): pass
+class I5(I4): pass
+class I6(I2): pass
+
+
+class Test(TestCase):
+
+ def test(self):
+ l = [I1, I3, I5, I6, I4, I2]
+ l.sort()
+ self.assertEqual(l, [I1, I2, I3, I4, I5, I6])
+
+ def test_w_None(self):
+ l = [I1, None, I3, I5, None, I6, I4, I2]
+ l.sort()
+ self.assertEqual(l, [I1, I2, I3, I4, I5, I6, None, None])
+
+def test_suite():
+ return TestSuite((
+ makeSuite(Test),
+ ))
+
+if __name__=='__main__':
+ main(defaultTest='test_suite')
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_type.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_type.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,162 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id: test_type.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+import unittest
+from zope.interface.type import TypeRegistry
+from zope.interface import Interface, implements
+
+def getAllForObject(reg, ob):
+ all = list(reg.getAllForObject(ob))
+ all.sort()
+ return all
+
+def getTypesMatching(reg, interface):
+ all = list(reg.getTypesMatching(interface))
+ all.sort()
+ return all
+
+class TestTypeRegistry(unittest.TestCase):
+
+ def new_instance(self):
+ return TypeRegistry()
+
+ def test(self):
+ class I1(Interface): pass
+ class I2(I1): pass
+ class I3(I2): pass
+
+ reg = self.new_instance()
+ self.assertEqual(len(reg), 0)
+
+ reg.register(I2, 2)
+ self.assertEqual(len(reg), 1)
+ self.assertEqual(getTypesMatching(reg, None), [I2])
+ self.assertEqual(getTypesMatching(reg, Interface), [I2])
+ self.assertEqual(getTypesMatching(reg, I1), [I2])
+ self.assertEqual(getTypesMatching(reg, I2), [I2])
+ self.assertEqual(getTypesMatching(reg, I3), [])
+
+ class C1: implements(I1)
+ class C2: implements(I2)
+ class C3: implements(I3)
+ class C: pass
+
+ self.assertEqual(getAllForObject(reg, C1()), [])
+ self.assertEqual(getAllForObject(reg, C2()), [2])
+ self.assertEqual(getAllForObject(reg, C3()), [2])
+ self.assertEqual(getAllForObject(reg, C()), [])
+
+ self.assertEqual(reg.get(I1), None)
+ self.assertEqual(reg.get(I2), 2)
+ self.assertEqual(reg.get(I3), None)
+
+ reg.register(I1, 1)
+ self.assertEqual(len(reg), 2)
+ self.assertEqual(getTypesMatching(reg, None), [I1, I2])
+ self.assertEqual(getTypesMatching(reg, Interface), [I1, I2])
+ self.assertEqual(getTypesMatching(reg, I1), [I1, I2])
+ self.assertEqual(getTypesMatching(reg, I2), [I2])
+ self.assertEqual(getTypesMatching(reg, I3), [])
+
+ self.assertEqual(getAllForObject(reg, C1()), [1])
+ self.assertEqual(getAllForObject(reg, C2()), [1, 2])
+ self.assertEqual(getAllForObject(reg, C3()), [1, 2])
+ self.assertEqual(getAllForObject(reg, C()), [])
+
+ self.assertEqual(reg.get(I1), 1)
+ self.assertEqual(reg.get(I2), 2)
+ self.assertEqual(reg.get(I3), None)
+
+ reg.register(I3, 3)
+ self.assertEqual(len(reg), 3)
+ self.assertEqual(getTypesMatching(reg, None), [I1, I2, I3])
+ self.assertEqual(getTypesMatching(reg, Interface), [I1, I2, I3])
+ self.assertEqual(getTypesMatching(reg, I1), [I1, I2, I3])
+ self.assertEqual(getTypesMatching(reg, I2), [I2, I3])
+ self.assertEqual(getTypesMatching(reg, I3), [I3])
+
+ self.assertEqual(getAllForObject(reg, C1()), [1])
+ self.assertEqual(getAllForObject(reg, C2()), [1, 2])
+ self.assertEqual(getAllForObject(reg, C3()), [1, 2, 3])
+ self.assertEqual(getAllForObject(reg, C()), [])
+
+ self.assertEqual(reg.get(I1), 1)
+ self.assertEqual(reg.get(I2), 2)
+ self.assertEqual(reg.get(I3), 3)
+
+ reg.unregister(I3)
+ self.assertEqual(len(reg), 2)
+ self.assertEqual(getTypesMatching(reg, None), [I1, I2])
+ self.assertEqual(getTypesMatching(reg, Interface), [I1, I2])
+ self.assertEqual(getTypesMatching(reg, I1), [I1, I2])
+ self.assertEqual(getTypesMatching(reg, I2), [I2])
+ self.assertEqual(getTypesMatching(reg, I3), [])
+
+ self.assertEqual(getAllForObject(reg, C1()), [1])
+ self.assertEqual(getAllForObject(reg, C2()), [1, 2])
+ self.assertEqual(getAllForObject(reg, C3()), [1, 2])
+ self.assertEqual(getAllForObject(reg, C()), [])
+
+ self.assertEqual(reg.get(I1), 1)
+ self.assertEqual(reg.get(I2), 2)
+ self.assertEqual(reg.get(I3), None)
+
+ def testSetdefault(self):
+ class I(Interface):
+ pass
+ reg = TypeRegistry()
+ x = reg.setdefault(I, 1)
+ y = reg.setdefault(I, 2)
+ self.assertEqual(x, y)
+ self.assertEqual(x, 1)
+
+ def testDup(self):
+ class I1(Interface): pass
+ class I2(I1): pass
+ class I3(I1): pass
+ class I4(I2, I3): pass
+ class C1: implements(I1)
+ class C2: implements(I2)
+ class C3: implements(I3)
+ class C4: implements(I4)
+ class C5: implements(I1, I2, I3, I4)
+ class C: pass
+
+ reg = TypeRegistry()
+ reg.register(I1, 1)
+ reg.register(I2, 2)
+ reg.register(I3, 3)
+
+ self.assertEqual(getAllForObject(reg, C1()), [1])
+ self.assertEqual(getAllForObject(reg, C2()), [1, 2])
+ self.assertEqual(getAllForObject(reg, C3()), [1, 3])
+ self.assertEqual(getAllForObject(reg, C4()), [1, 2, 3])
+ self.assertEqual(getAllForObject(reg, C5()), [1, 2, 3])
+ self.assertEqual(getAllForObject(reg, C()), [])
+
+ def testBadRequire(self):
+ registry = TypeRegistry()
+ self.assertRaises(TypeError, registry.register, 42, '')
+
+def test_suite():
+ loader = unittest.TestLoader()
+ return loader.loadTestsFromTestCase(TestTypeRegistry)
+
+if __name__=='__main__':
+ unittest.TextTestRunner().run(test_suite())
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_verify.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/test_verify.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,178 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id: test_verify.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+
+from zope.interface import Interface, implements, classImplements
+from zope.interface.verify import verifyClass, verifyObject
+from zope.interface.exceptions import DoesNotImplement, BrokenImplementation
+from zope.interface.exceptions import BrokenMethodImplementation
+
+import unittest
+
+class Test(unittest.TestCase):
+
+ def testNotImplemented(self):
+
+ class C: pass
+
+ class I(Interface): pass
+
+ self.assertRaises(DoesNotImplement, verifyClass, I, C)
+
+ classImplements(C, I)
+
+ verifyClass(I, C)
+
+ def testMissingAttr(self):
+
+ class I(Interface):
+ def f(): pass
+
+ class C:
+ implements(I)
+
+ self.assertRaises(BrokenImplementation, verifyClass, I, C)
+
+ C.f=lambda self: None
+
+ verifyClass(I, C)
+
+ def testMissingAttr_with_Extended_Interface(self):
+
+ class II(Interface):
+ def f():
+ pass
+
+ class I(II):
+ pass
+
+ class C:
+
+ implements(I)
+
+ self.assertRaises(BrokenImplementation, verifyClass, I, C)
+
+ C.f=lambda self: None
+
+ verifyClass(I, C)
+
+ def testWrongArgs(self):
+
+ class I(Interface):
+ def f(a): pass
+
+ class C:
+
+ def f(self, b): pass
+
+ implements(I)
+
+ # We no longer require names to match.
+ #self.assertRaises(BrokenMethodImplementation, verifyClass, I, C)
+
+ C.f=lambda self, a: None
+
+ verifyClass(I, C)
+
+ C.f=lambda self, **kw: None
+
+ self.assertRaises(BrokenMethodImplementation, verifyClass, I, C)
+
+ C.f=lambda self, a, *args: None
+
+ verifyClass(I, C)
+
+ C.f=lambda self, a, *args, **kw: None
+
+ verifyClass(I, C)
+
+ C.f=lambda self, *args: None
+
+ verifyClass(I, C)
+
+ def testExtraArgs(self):
+
+ class I(Interface):
+ def f(a): pass
+
+ class C:
+
+ def f(self, a, b): pass
+
+ implements(I)
+
+ self.assertRaises(BrokenMethodImplementation, verifyClass, I, C)
+
+ C.f=lambda self, a: None
+
+ verifyClass(I, C)
+
+ C.f=lambda self, a, b=None: None
+
+ verifyClass(I, C)
+
+ def testNoVar(self):
+
+ class I(Interface):
+ def f(a, *args): pass
+
+ class C:
+
+ def f(self, a): pass
+
+ implements(I)
+
+ self.assertRaises(BrokenMethodImplementation, verifyClass, I, C)
+
+ C.f=lambda self, a, *foo: None
+
+ verifyClass(I, C)
+
+ def testNoKW(self):
+
+ class I(Interface):
+ def f(a, **args): pass
+
+ class C:
+
+ def f(self, a): pass
+
+ implements(I)
+
+ self.assertRaises(BrokenMethodImplementation, verifyClass, I, C)
+
+ C.f=lambda self, a, **foo: None
+
+ verifyClass(I, C)
+
+ def testModule(self):
+
+ from zope.interface.tests.ifoo import IFoo
+ from zope.interface.tests import dummy
+
+ verifyObject(IFoo, dummy)
+
+
+
+def test_suite():
+ loader=unittest.TestLoader()
+ return loader.loadTestsFromTestCase(Test)
+
+if __name__=='__main__':
+ unittest.TextTestRunner().run(test_suite())
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/unitfixtures.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/tests/unitfixtures.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,141 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+from zope.interface import Interface, invariant
+from zope.interface.interface import Attribute
+from zope.interface.exceptions import Invalid
+
+class mytest(Interface):
+ pass
+
+class C:
+ def m1(self, a, b):
+ "return 1"
+ return 1
+
+ def m2(self, a, b):
+ "return 2"
+ return 2
+
+# testInstancesOfClassImplements
+
+
+
+
+# YAGNI IC=Interface.impliedInterface(C)
+class IC(Interface):
+ def m1(a, b):
+ "return 1"
+
+ def m2(a, b):
+ "return 2"
+
+
+
+C.__implemented__=IC
+
+class I1(Interface):
+ def ma():
+ "blah"
+
+class I2(I1): pass
+
+class I3(Interface): pass
+
+class I4(Interface): pass
+
+class A(I1.deferred()):
+ __implemented__=I1
+
+class B:
+ __implemented__=I2, I3
+
+class D(A, B): pass
+
+class E(A, B):
+ __implemented__ = A.__implemented__, C.__implemented__
+
+
+class FooInterface(Interface):
+ """ This is an Abstract Base Class """
+
+ foobar = Attribute("fuzzed over beyond all recognition")
+
+ def aMethod(foo, bar, bingo):
+ """ This is aMethod """
+
+ def anotherMethod(foo=6, bar="where you get sloshed", bingo=(1,3,)):
+ """ This is anotherMethod """
+
+ def wammy(zip, *argues):
+ """ yadda yadda """
+
+ def useless(**keywords):
+ """ useless code is fun! """
+
+class Foo:
+ """ A concrete class """
+
+ __implemented__ = FooInterface,
+
+ foobar = "yeah"
+
+ def aMethod(self, foo, bar, bingo):
+ """ This is aMethod """
+ return "barf!"
+
+ def anotherMethod(self, foo=6, bar="where you get sloshed", bingo=(1,3,)):
+ """ This is anotherMethod """
+ return "barf!"
+
+ def wammy(self, zip, *argues):
+ """ yadda yadda """
+ return "barf!"
+
+ def useless(self, **keywords):
+ """ useless code is fun! """
+ return "barf!"
+
+foo_instance = Foo()
+
+class Blah:
+ pass
+
+new = Interface.__class__
+FunInterface = new('FunInterface')
+BarInterface = new('BarInterface', [FunInterface])
+BobInterface = new('BobInterface')
+BazInterface = new('BazInterface', [BobInterface, BarInterface])
+
+# fixtures for invariant tests
+def ifFooThenBar(obj):
+ if getattr(obj, 'foo', None) and not getattr(obj, 'bar', None):
+ raise Invalid('If Foo, then Bar!')
+class IInvariant(Interface):
+ foo = Attribute('foo')
+ bar = Attribute('bar; must eval to Boolean True if foo does')
+ invariant(ifFooThenBar)
+def BarGreaterThanFoo(obj):
+ foo = getattr(obj, 'foo', None)
+ bar = getattr(obj, 'bar', None)
+ if foo is not None and isinstance(foo, type(bar)):
+ # type checking should be handled elsewhere (like, say,
+ # schema); these invariants should be intra-interface
+ # constraints. This is a hacky way to do it, maybe, but you
+ # get the idea
+ if not bar > foo:
+ raise Invalid('Please, Boo MUST be greater than Foo!')
+class ISubInvariant(IInvariant):
+ invariant(BarGreaterThanFoo)
+class InvariantC(object):
+ pass
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/type.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/type.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,157 @@ />
+##############################################################################
+#
+# Copyright (c) 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.
+#
+##############################################################################
+"""This module is DEPRECATED. Don't use it!
+
+$Id: type.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+__metaclass__ = type # All classes are new style when run with Python 2.2+
+
+import zope.interface
+import types
+from zope.interface import providedBy, implements, Interface
+from zope.interface.interfaces import IInterface
+
+class ITypeRegistry(Interface):
+ """Type-specific registry
+
+ This registry stores objects registered for objects that implement
+ a required interface.
+ """
+
+ def register(interface, object):
+ """Register an object for an interface.
+
+ The interface argument may be None. This effectively defines a
+ default object.
+ """
+
+ def unregister(interface):
+ """Remove the registration for the given interface
+
+ If nothing is registered for the interface, the call is ignored.
+ """
+
+ def get(interface, default=None):
+ """Return the object registered for the given interface.
+ """
+
+ def getAll(implements):
+ """Get registered objects
+
+ Return a sequence of all objects registered with interfaces
+ that are extended by or equal to one or more interfaces in the
+ given interface specification.
+
+ Objects that match more specific interfaces of the specification
+ come before those that match less specific interfaces, as per
+ the interface resolution order described in the flattened() operation
+ of IInterfaceSpecification.
+ """
+
+ def getAllForObject(object):
+ """Get all registered objects for types that object implements.
+ """
+
+ def getTypesMatching(interface):
+ """Get all registered interfaces matching the given interface
+
+ Returns a sequence of all interfaces registered that extend
+ or are equal to the given interface.
+ """
+
+ def __len__():
+ """Returns the number of distinct interfaces registered.
+ """
+
+class TypeRegistry:
+
+ implements(ITypeRegistry)
+
+ # XXX This comment doesn't seem to be correct, because the mapping is
+ # from interface -> object. There are no tuples that I see. Also,
+ # I'm not sure what the last sentence is trying to say :-).
+
+ # The implementation uses a mapping:
+ #
+ # { (required, provided) -> (registered_provided, component) }
+ #
+ # Where the registered provides is what was registered and
+ # provided may be some base interface
+
+ def __init__(self, data=None):
+ if data is None:
+ data = {}
+
+ self._reg = data
+
+ def register(self, interface, object):
+ if not (interface is None or IInterface.providedBy(interface)):
+ if isinstance(interface, (type, types.ClassType)):
+ interface = zope.interface.implementedBy(interface)
+ else:
+ raise TypeError(
+ "The interface argument must be an interface (or None)")
+
+ self._reg[interface] = object
+
+ def unregister(self, interface):
+ if interface is None or IInterface.providedBy(interface):
+ if interface in self._reg:
+ del self._reg[interface]
+ else:
+ raise TypeError(
+ "The interface argument must be an interface (or None)")
+
+ def get(self, interface, default=None):
+ """
+ Finds a registered component that provides the given interface.
+ Returns None if not found.
+ """
+ return self._reg.get(interface, default)
+
+ def setdefault(self, interface, default=None):
+ return self._reg.setdefault(interface, default)
+
+ def getAll(self, interface_spec):
+ result = []
+ for interface in interface_spec.flattened():
+ object = self._reg.get(interface)
+ if object is not None:
+ result.append(object)
+
+ if interface_spec is not None:
+ object = self._reg.get(None)
+ if object is not None:
+ result.append(object)
+
+ return result
+
+ def getAllForObject(self, object):
+ # XXX This isn't quite right, since it doesn't take into
+ # account implementation registries for objects that can't
+ # have '__implemented__' attributes.
+ return self.getAll(providedBy(object))
+
+ def getTypesMatching(self, interface):
+ if interface is None:
+ return self._reg.keys()
+
+ result = []
+ for k in self._reg:
+ if k is None or k.extends(interface, False):
+ result.append(k)
+ return result
+
+ def __len__(self):
+ return len(self._reg)
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/verify.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/interface/verify.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,97 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+
+from zope.interface.exceptions import BrokenImplementation, DoesNotImplement
+from zope.interface.exceptions import BrokenMethodImplementation
+from types import FunctionType, MethodType
+from zope.interface.interface import fromMethod, fromFunction, Method
+
+# This will be monkey-patched when running under Zope 2, so leave this
+# here:
+MethodTypes = (MethodType, )
+
+
+def _verify(iface, candidate, tentative=0, vtype=None):
+ """Verify that 'candidate' might correctly implements 'iface'.
+
+ This involves:
+
+ o Making sure the candidate defines all the necessary methods
+
+ o Making sure the methods have the correct signature
+
+ o Making sure the candidate asserts that it implements the interface
+
+ Note that this isn't the same as verifying that the class does
+ implement the interface.
+
+ If optional tentative is true, supss the "is implemented by" test.
+ """
+
+ if vtype == 'c':
+ tester = iface.implementedBy
+ else:
+ tester = iface.providedBy
+
+ if not tentative and not tester(candidate):
+ raise DoesNotImplement(iface)
+
+ for n, d in iface.namesAndDescriptions(1):
+ if not hasattr(candidate, n):
+ if (not isinstance(d, Method)) and vtype == 'c':
+ # We can't verify non-methods on classes, since the
+ # class may provide attrs in it's __init__.
+ continue
+
+ raise BrokenImplementation(iface, n)
+
+ attr = getattr(candidate, n)
+ if type(attr) is FunctionType:
+ # should never get here
+ meth = fromFunction(attr, n)
+ elif (isinstance(attr, MethodTypes)
+ and type(attr.im_func) is FunctionType):
+ meth = fromMethod(attr, n)
+ else:
+ continue # must be an attribute...
+
+ d=d.getSignatureInfo()
+ meth = meth.getSignatureInfo()
+
+ mess = _incompat(d, meth)
+ if mess:
+ raise BrokenMethodImplementation(n, mess)
+
+ return True
+
+def verifyClass(iface, candidate, tentative=0):
+ return _verify(iface, candidate, tentative, vtype='c')
+
+def verifyObject(iface, candidate, tentative=0):
+ return _verify(iface, candidate, tentative, vtype='o')
+
+def _incompat(required, implemented):
+ #if (required['positional'] !=
+ # implemented['positional'][:len(required['positional'])]
+ # and implemented['kwargs'] is None):
+ # return 'imlementation has different argument names'
+ if len(implemented['required']) > len(required['required']):
+ return 'implementation requires too many arguments'
+ if ((len(implemented['positional']) < len(required['positional']))
+ and not implemented['varargs']):
+ return "implementation doesn't allow enough arguments"
+ if required['kwargs'] and not implemented['kwargs']:
+ return "implementation doesn't support keyword arguments"
+ if required['varargs'] and not implemented['varargs']:
+ return "implementation doesn't support variable arguments"
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/DEPENDENCIES.cfg
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/DEPENDENCIES.cfg Wed Jun 2 16:09:24 2004
@@ -0,0 +1 @@ />
+zope.exceptions
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/__init__.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/__init__.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,31 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+Set up testing environment
+
+$Id: __init__.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+import os
+
+def patchTracebackModule():
+ """Use the ExceptionFormatter to show more info in tracebacks.
+ """
+ from zope.exceptions.exceptionformatter import format_exception
+ import traceback
+ traceback.format_exception = format_exception
+
+# Don't use the new exception formatter by default, since it
+# doesn't show filenames.
+if os.environ.get('NEW_ZOPE_EXCEPTION_FORMATTER', 0):
+ patchTracebackModule()
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/cleanup.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/cleanup.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,58 @@ />
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Provide a standard cleanup registry
+
+Unit tests that change global data should include the CleanUp base
+class, which provides simpler setUp and tearDown methods that call
+global-data cleanup routines::
+
+ class Test(CleanUp, unittest.TestCase):
+
+ ....
+
+If custom setUp or tearDown are needed, then the base routines should
+be called, as in::
+
+ def tearDown(self):
+ super(Test, self).tearDown()
+ ....
+
+Cleanup routines for global data should be registered by passing them to
+addCleanup::
+
+
+ addCleanUp(pigRegistry._clear)
+
+
+$Id: cleanup.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+_cleanups = []
+
+def addCleanUp(func, args=(), kw={}):
+ """Register a cleanup routines
+
+ Pass a function to be called to cleanup global data.
+ Optional argument tuple and keyword arguments may be passed.
+ """
+ _cleanups.append((func, args, kw))
+
+class CleanUp(object):
+ """Mix-in class providing clean-up setUp and tearDown routines."""
+
+ def cleanUp(self):
+ """Clean up global data."""
+ for func, args, kw in _cleanups:
+ func(*args, **kw)
+
+ setUp = tearDown = cleanUp
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/doctest.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/doctest.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,1520 @@ />
+# Module doctest.
+# Released to the public domain 16-Jan-2001,
+# by Tim Peters (tim.one@home.com). />
+
+# Provided as-is; use at your own risk; no warranty; no promises; enjoy!
+
+"""Module doctest -- a framework for running examples in docstrings.
+
+NORMAL USAGE
+
+In normal use, end each module M with:
+
+def _test():
+ import doctest, M # replace M with your module's name
+ return doctest.testmod(M) # ditto
+
+if __name__ == "__main__":
+ _test()
+
+Then running the module as a script will cause the examples in the
+docstrings to get executed and verified:
+
+python M.py
+
+This won't display anything unless an example fails, in which case the
+failing example(s) and the cause(s) of the failure(s) are printed to stdout
+(why not stderr? because stderr is a lame hack <0.2 wink>), and the final
+line of output is "Test failed.".
+
+Run it with the -v switch instead:
+
+python M.py -v
+
+and a detailed report of all examples tried is printed to stdout, along
+with assorted summaries at the end.
+
+You can force verbose mode by passing "verbose=1" to testmod, or prohibit
+it by passing "verbose=0". In either of those cases, sys.argv is not
+examined by testmod.
+
+In any case, testmod returns a 2-tuple of ints (f, t), where f is the
+number of docstring examples that failed and t is the total number of
+docstring examples attempted.
+
+
+WHICH DOCSTRINGS ARE EXAMINED?
+
++ M.__doc__.
+
++ f.__doc__ for all functions f in M.__dict__.values(), except those
+ defined in other modules.
+
++ C.__doc__ for all classes C in M.__dict__.values(), except those
+ defined in other modules.
+
++ If M.__test__ exists and "is true", it must be a dict, and
+ each entry maps a (string) name to a function object, class object, or
+ string. Function and class object docstrings found from M.__test__
+ are searched even if the name is private, and strings are searched
+ directly as if they were docstrings. In output, a key K in M.__test__
+ appears with name
+ <name of M>.__test__.K
+
+Any classes found are recursively searched similarly, to test docstrings in
+their contained methods and nested classes. All names reached from
+M.__test__ are searched.
+
+Optionally, functions with private names can be skipped (unless listed in
+M.__test__) by supplying a function to the "isprivate" argument that will
+identify private functions. For convenience, one such function is
+supplied. docttest.is_private considers a name to be private if it begins
+with an underscore (like "_my_func") but doesn't both begin and end with
+(at least) two underscores (like "__init__"). By supplying this function
+or your own "isprivate" function to testmod, the behavior can be customized.
+
+If you want to test docstrings in objects with private names too, stuff
+them into an M.__test__ dict, or see ADVANCED USAGE below (e.g., pass your
+own isprivate function to Tester's constructor, or call the rundoc method
+of a Tester instance).
+
+WHAT'S THE EXECUTION CONTEXT?
+
+By default, each time testmod finds a docstring to test, it uses a *copy*
+of M's globals (so that running tests on a module doesn't change the
+module's real globals, and so that one test in M can't leave behind crumbs
+that accidentally allow another test to work). This means examples can
+freely use any names defined at top-level in M. It also means that sloppy
+imports (see above) can cause examples in external docstrings to use
+globals inappropriate for them.
+
+You can force use of your own dict as the execution context by passing
+"globs=your_dict" to testmod instead. Presumably this would be a copy of
+M.__dict__ merged with the globals from other imported modules.
+
+
+WHAT IF I WANT TO TEST A WHOLE PACKAGE?
+
+Piece o' cake, provided the modules do their testing from docstrings.
+Here's the test.py I use for the world's most elaborate Rational/
+floating-base-conversion pkg (which I'll distribute some day):
+
+from Rational import Cvt
+from Rational import Format
+from Rational import machc
+from Rational import Rat
+from Rational import Round
+from Rational import utils
+
+modules = (Cvt,
+ Format,
+ machc,
+ Rat,
+ Round,
+ utils)
+
+def _test():
+ import doctest
+ import sys
+ verbose = "-v" in sys.argv
+ for mod in modules:
+ doctest.testmod(mod, verbose=verbose, report=0)
+ doctest.master.summarize()
+
+if __name__ == "__main__":
+ _test()
+
+IOW, it just runs testmod on all the pkg modules. testmod remembers the
+names and outcomes (# of failures, # of tries) for each item it's seen, and
+passing "report=0" vents it from printing a summary in verbose mode.
+Instead, the summary is delayed until all modules have been tested, and
+then "doctest.master.summarize()" forces the summary at the end.
+
+So this is very nice in practice: each module can be tested individually
+with almost no work beyond writing up docstring examples, and collections
+of modules can be tested too as a unit with no more work than the above.
+
+
+WHAT ABOUT EXCEPTIONS?
+
+No problem, as long as the only output generated by the example is the
+traceback itself. For example:
+
+ >>> [1, 2, 3].remove(42)
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in ?
+ ValueError: list.remove(x): x not in list
+ >>>
+
+Note that only the exception type and value are compared (specifically,
+only the last line in the traceback).
+
+
+ADVANCED USAGE
+
+doctest.testmod() captures the testing policy I find most useful most
+often. You may want other policies.
+
+testmod() actually creates a local instance of class doctest.Tester, runs
+appropriate methods of that class, and merges the results into global
+Tester instance doctest.master.
+
+You can create your own instances of doctest.Tester, and so build your own
+policies, or even run methods of doctest.master directly. See
+doctest.Tester.__doc__ for details.
+
+
+SO WHAT DOES A DOCSTRING EXAMPLE LOOK LIKE ALREADY!?
+
+Oh ya. It's easy! In most cases a copy-and-paste of an interactive
+console session works fine -- just make sure the leading whitespace is
+rigidly consistent (you can mix tabs and spaces if you're too lazy to do it
+right, but doctest is not in the business of guessing what you think a tab
+means).
+
+ >>> # comments are ignored
+ >>> x = 12
+ >>> x
+ 12
+ >>> if x == 13:
+ ... print "yes"
+ ... else:
+ ... print "no"
+ ... print "NO"
+ ... print "NO!!!"
+ ...
+ no
+ NO
+ NO!!!
+ >>>
+
+Any expected output must immediately follow the final ">>>" or "..." line
+containing the code, and the expected output (if any) extends to the next
+">>>" or all-whitespace line. That's it.
+
+Bummers:
+
++ Expected output cannot contain an all-whitespace line, since such a line
+ is taken to signal the end of expected output.
+
++ Output to stdout is captured, but not output to stderr (exception
+ tracebacks are captured via a different means).
+
++ If you continue a line via backslashing in an interactive session, or for
+ any other reason use a backslash, you need to double the backslash in the
+ docstring version. This is simply because you're in a string, and so the
+ backslash must be escaped for it to survive intact. Like:
+
+>>> if "yes" == \\
+... "y" + \\
+... "es": # in the source code you'll see the doubled backslashes
+... print 'yes'
+yes
+
+The starting column doesn't matter:
+
+>>> assert "Easy!"
+ >>> import math
+ >>> math.floor(1.9)
+ 1.0
+
+and as many leading whitespace characters are stripped from the expected
+output as appeared in the initial ">>>" line that triggered it.
+
+If you execute this very file, the examples above will be found and
+executed, leading to this output in verbose mode:
+
+Running doctest.__doc__
+Trying: [1, 2, 3].remove(42)
+Expecting:
+Traceback (most recent call last):
+ File "<stdin>", line 1, in ?
+ValueError: list.remove(x): x not in list
+ok
+Trying: x = 12
+Expecting: nothing
+ok
+Trying: x
+Expecting: 12
+ok
+Trying:
+if x == 13:
+ print "yes"
+else:
+ print "no"
+ print "NO"
+ print "NO!!!"
+Expecting:
+no
+NO
+NO!!!
+ok
+... and a bunch more like that, with this summary at the end:
+
+5 items had no tests:
+ doctest.Tester.__init__
+ doctest.Tester.run__test__
+ doctest.Tester.summarize
+ doctest.run_docstring_examples
+ doctest.testmod
+12 items passed all tests:
+ 8 tests in doctest
+ 6 tests in doctest.Tester
+ 10 tests in doctest.Tester.merge
+ 14 tests in doctest.Tester.rundict
+ 3 tests in doctest.Tester.rundoc
+ 3 tests in doctest.Tester.runstring
+ 2 tests in doctest.__test__._TestClass
+ 2 tests in doctest.__test__._TestClass.__init__
+ 2 tests in doctest.__test__._TestClass.get
+ 1 tests in doctest.__test__._TestClass.square
+ 2 tests in doctest.__test__.string
+ 7 tests in doctest.is_private
+60 tests in 17 items.
+60 passed and 0 failed.
+
+Test passed.
+"""
+
+__all__ = [
+ 'testmod',
+ 'run_docstring_examples',
+ 'is_private',
+ 'Tester',
+ 'DocTestTestFailure',
+ 'DocTestSuite',
+ 'testsource',
+ 'debug',
+ 'master',
+]
+
+import __future__
+
+import pdb
+import re
+PS1 = ">>>"
+PS2 = "..."
+_isPS1 = re.compile(r"(\s*)" + re.escape(PS1)).match
+_isPS2 = re.compile(r"(\s*)" + re.escape(PS2)).match
+_isEmpty = re.compile(r"\s*$").match
+_isComment = re.compile(r"\s*#").match
+del re
+
+from types import StringTypes as _StringTypes
+
+from inspect import isclass as _isclass
+from inspect import isfunction as _isfunction
+from inspect import ismethod as _ismethod
+from inspect import ismodule as _ismodule
+from inspect import classify_class_attrs as _classify_class_attrs
+
+# Option constants.
+DONT_ACCEPT_TRUE_FOR_1 = 1 << 0
+RUN_DEBUGGER_ON_UNEXPECTED_EXCEPTION = 1 << 1
+
+# Extract interactive examples from a string. Return a list of triples,
+# (source, outcome, lineno). "source" is the source code, and ends
+# with a newline iff the source spans more than one line. "outcome" is
+# the expected output if any, else an empty string. When not empty,
+# outcome always ends with a newline. "lineno" is the line number,
+# 0-based wrt the start of the string, of the first source line.
+
+def _extract_examples(s):
+ isPS1, isPS2 = _isPS1, _isPS2
+ isEmpty, isComment = _isEmpty, _isComment
+ examples = []
+ lines = s.split("\n")
+ i, n = 0, len(lines)
+ while i < n:
+ line = lines[i]
+ i = i + 1
+ m = isPS1(line)
+ if m is None:
+ continue
+ j = m.end(0) # beyond the prompt
+ if isEmpty(line, j) or isComment(line, j):
+ # a bare prompt or comment -- not interesting
+ continue
+ lineno = i - 1
+ if line[j] != " ":
+ raise ValueError("line %r of docstring lacks blank after %s: %s" %
+ (lineno, PS1, line))
+ j = j + 1
+ blanks = m.group(1)
+ nblanks = len(blanks)
+ # suck up this and following PS2 lines
+ source = []
+ while 1:
+ source.append(line[j:])
+ line = lines[i]
+ m = isPS2(line)
+ if m:
+ if m.group(1) != blanks:
+ raise ValueError("inconsistent leading whitespace "
+ "in line %r of docstring: %s" % (i, line))
+ i = i + 1
+ else:
+ break
+ if len(source) == 1:
+ source = source[0]
+ else:
+ # get rid of useless null line from trailing empty "..."
+ if source[-1] == "":
+ del source[-1]
+ source = "\n".join(source) + "\n"
+ # suck up response
+ if isPS1(line) or isEmpty(line):
+ expect = ""
+ else:
+ expect = []
+ while 1:
+ if line[:nblanks] != blanks:
+ raise ValueError("inconsistent leading whitespace "
+ "in line %r of docstring: %s" % (i, line))
+ expect.append(line[nblanks:])
+ i = i + 1
+ line = lines[i]
+ if isPS1(line) or isEmpty(line):
+ break
+ expect = "\n".join(expect) + "\n"
+ examples.append( (source, expect, lineno) )
+ return examples
+
+# Capture stdout when running examples.
+
+class _SpoofOut:
+ def __init__(self):
+ self.clear()
+ def write(self, s):
+ self.buf.append(s)
+ def get(self):
+ guts = "".join(self.buf)
+ # If anything at all was written, make sure there's a trailing
+ # newline. There's no way for the expected output to indicate
+ # that a trailing newline is missing.
+ if guts and not guts.endswith("\n"):
+ guts = guts + "\n"
+ # Prevent softspace from screwing up the next test case, in
+ # case they used print with a trailing comma in an example.
+ if hasattr(self, "softspace"):
+ del self.softspace
+ return guts
+ def clear(self):
+ self.buf = []
+ if hasattr(self, "softspace"):
+ del self.softspace
+ def flush(self):
+ # JPython calls flush
+ pass
+
+# Display some tag-and-msg pairs nicely, keeping the tag and its msg
+# on the same line when that makes sense.
+
+def _tag_out(printer, *tag_msg_pairs):
+ for tag, msg in tag_msg_pairs:
+ printer(tag + ":")
+ msg_has_nl = msg[-1:] == "\n"
+ msg_has_two_nl = msg_has_nl and \
+ msg.find("\n") < len(msg) - 1
+ if len(tag) + len(msg) < 76 and not msg_has_two_nl:
+ printer(" ")
+ else:
+ printer("\n")
+ printer(msg)
+ if not msg_has_nl:
+ printer("\n")
+
+# Run list of examples, in context globs. "out" can be used to display
+# stuff to "the real" stdout, and fakeout is an instance of _SpoofOut
+# that captures the examples' std output. Return (#failures, #tries).
+
+def _run_examples_inner(out, fakeout, examples, globs, verbose, name,
+ compileflags, optionflags):
+ import sys, traceback
+ OK, BOOM, FAIL = range(3)
+ NADA = "nothing"
+ stderr = _SpoofOut()
+ failures = 0
+ for source, want, lineno in examples:
+ if verbose:
+ _tag_out(out, ("Trying", source),
+ ("Expecting", want or NADA))
+ fakeout.clear()
+ try:
+ exec compile(source, "<string>", "single",
+ compileflags, 1) in globs
+ got = fakeout.get()
+ state = OK
+ except KeyboardInterrupt:
+ raise
+ except:
+ # See whether the exception was expected.
+ if want.find("Traceback (innermost last):\n") == 0 or \
+ want.find("Traceback (most recent call last):\n") == 0:
+ # Only compare exception type and value - the rest of
+ # the traceback isn't necessary.
+ want = want.split('\n')[-2] + '\n'
+ exc_type, exc_val = sys.exc_info()[:2]
+ got = traceback.format_exception_only(exc_type, exc_val)[-1]
+ state = OK
+ else:
+ # unexpected exception
+ stderr.clear()
+ traceback.print_exc(file=stderr)
+ state = BOOM
+
+ if optionflags & RUN_DEBUGGER_ON_UNEXPECTED_EXCEPTION:
+ # Be sure to undo all wrappings. If the test is
+ # run under unittest, there will at at least two now.
+ stdout = sys.stdout
+ sys.stdout = sys.__stdout__
+ print stderr.get()
+ pdb.post_mortem(sys.exc_info()[2])
+ # Restore stdout if we exit the debugger without error.
+ sys.stdout = stdout
+
+ if state == OK:
+ if (got == want or
+ (not (optionflags & DONT_ACCEPT_TRUE_FOR_1) and
+ (got, want) in (("True\n", "1\n"), ("False\n", "0\n"))
+ )
+ ):
+ if verbose:
+ out("ok\n")
+ continue
+ state = FAIL
+
+ assert state in (FAIL, BOOM)
+ failures = failures + 1
+ out("*" * 65 + "\n")
+ _tag_out(out, ("Failure in example", source))
+ out("from line #%r of %s\n" % (lineno, name))
+ if state == FAIL:
+ _tag_out(out, ("Expected", want or NADA), ("Got", got))
+ else:
+ assert state == BOOM
+ _tag_out(out, ("Exception raised", stderr.get()))
+
+ return failures, len(examples)
+
+# Get the future-flags associated with the future features that have been
+# imported into globs.
+
+def _extract_future_flags(globs):
+ flags = 0
+ for fname in __future__.all_feature_names:
+ feature = globs.get(fname, None)
+ if feature is getattr(__future__, fname):
+ flags |= feature.compiler_flag
+ return flags
+
+# Run list of examples, in a shallow copy of context (dict) globs.
+# Return (#failures, #tries).
+
+def _run_examples(examples, globs, verbose, name, compileflags,
+ optionflags):
+ import sys
+ saveout = sys.stdout
+ globs = globs.copy()
+ try:
+ sys.stdout = fakeout = _SpoofOut()
+ x = _run_examples_inner(saveout.write, fakeout, examples,
+ globs, verbose, name, compileflags,
+ optionflags)
+ finally:
+ sys.stdout = saveout
+ # While Python gc can clean up most cycles on its own, it doesn't
+ # chase frame objects. This is especially irksome when running
+ # generator tests that raise exceptions, because a named generator-
+ # iterator gets an entry in globs, and the generator-iterator
+ # object's frame's traceback info points back to globs. This is
+ # easy to break just by clearing the namespace. This can also
+ # help to break other kinds of cycles, and even for cycles that
+ # gc can break itself it's better to break them ASAP.
+ globs.clear()
+ return x
+
+def run_docstring_examples(f, globs, verbose=0, name="NoName",
+ compileflags=None, optionflags=0):
+ """f, globs, verbose=0, name="NoName" -> run examples from f.__doc__.
+
+ Use (a shallow copy of) dict globs as the globals for execution.
+ Return (#failures, #tries).
+
+ If optional arg verbose is true, print stuff even if there are no
+ failures.
+ Use string name in failure msgs.
+ """
+
+ try:
+ doc = f.__doc__
+ if not doc:
+ # docstring empty or None
+ return 0, 0
+ # just in case CT invents a doc object that has to be forced
+ # to look like a string <0.9 wink>
+ doc = str(doc)
+ except KeyboardInterrupt:
+ raise
+ except:
+ return 0, 0
+
+ e = _extract_examples(doc)
+ if not e:
+ return 0, 0
+ if compileflags is None:
+ compileflags = _extract_future_flags(globs)
+ return _run_examples(e, globs, verbose, name, compileflags, optionflags)
+
+def is_private(fix, base):
+ """fix, base -> true iff name fix + "." + base is "private".
+
+ Prefix may be an empty string, and base does not contain a period.
+ Prefix is ignored (although functions you write conforming to this
+ protocol may make use of it).
+ Return true iff base begins with an (at least one) underscore, but
+ does not both begin and end with (at least) two underscores.
+
+ >>> is_private("a.b", "my_func")
+ False
+ >>> is_private("____", "_my_func")
+ True
+ >>> is_private("someclass", "__init__")
+ False
+ >>> is_private("sometypo", "__init_")
+ True
+ >>> is_private("x.y.z", "_")
+ True
+ >>> is_private("_x.y.z", "__")
+ False
+ >>> is_private("", "") # senseless but consistent
+ False
+ """
+
+ return base[:1] == "_" and not base[:2] == "__" == base[-2:]
+
+# Determine if a class of function was defined in the given module.
+
+def _from_module(module, object):
+ if _isfunction(object):
+ return module.__dict__ is object.func_globals
+ if _isclass(object):
+ return module.__name__ == object.__module__
+ raise ValueError("object must be a class or function")
+
+class Tester:
+ """Class Tester -- runs docstring examples and accumulates stats.
+
+In normal use, function doctest.testmod() hides all this from you,
+so use that if you can. Create your own instances of Tester to do
+fancier things.
+
+Methods:
+ runstring(s, name)
+ Search string s for examples to run; use name for logging.
+ Return (#failures, #tries).
+
+ rundoc(object, name=None)
+ Search object.__doc__ for examples to run; use name (or
+ object.__name__) for logging. Return (#failures, #tries).
+
+ rundict(d, name, module=None)
+ Search for examples in docstrings in all of d.values(); use name
+ for logging. Exclude functions and classes not defined in module
+ if specified. Return (#failures, #tries).
+
+ run__test__(d, name)
+ Treat dict d like module.__test__. Return (#failures, #tries).
+
+ summarize(verbose=None)
+ Display summary of testing results, to stdout. Return
+ (#failures, #tries).
+
+ merge(other)
+ Merge in the test results from Tester instance "other".
+
+>>> from doctest import Tester
+>>> t = Tester(globs={'x': 42}, verbose=0)
+>>> t.runstring(r'''
+... >>> x = x * 2
+... >>> print x
+... 42
+... ''', 'XYZ')
+*****************************************************************
+Failure in example: print x
+from line #2 of XYZ
+Expected: 42
+Got: 84
+(1, 2)
+>>> t.runstring(">>> x = x * 2\\n>>> print x\\n84\\n", 'example2')
+(0, 2)
+>>> t.summarize()
+*****************************************************************
+1 items had failures:
+ 1 of 2 in XYZ
+***Test Failed*** 1 failures.
+(1, 4)
+>>> t.summarize(verbose=1)
+1 items passed all tests:
+ 2 tests in example2
+*****************************************************************
+1 items had failures:
+ 1 of 2 in XYZ
+4 tests in 2 items.
+3 passed and 1 failed.
+***Test Failed*** 1 failures.
+(1, 4)
+>>>
+"""
+
+ def __init__(self, mod=None, globs=None, verbose=None,
+ isprivate=None, optionflags=0):
+ """mod=None, globs=None, verbose=None, isprivate=None,
+optionflags=0
+
+See doctest.__doc__ for an overview.
+
+Optional keyword arg "mod" is a module, whose globals are used for
+executing examples. If not specified, globs must be specified.
+
+Optional keyword arg "globs" gives a dict to be used as the globals
+when executing examples; if not specified, use the globals from
+module mod.
+
+In either case, a copy of the dict is used for each docstring
+examined.
+
+Optional keyword arg "verbose" prints lots of stuff if true, only
+failures if false; by default, it's true iff "-v" is in sys.argv.
+
+Optional keyword arg "isprivate" specifies a function used to determine
+whether a name is private. The default function is to assume that
+no functions are private. The "isprivate" arg may be set to
+doctest.is_private in order to skip over functions marked as private
+using an underscore naming convention; see its docs for details.
+
+See doctest.testmod docs for the meaning of optionflags.
+"""
+
+ if mod is None and globs is None:
+ raise TypeError("Tester.__init__: must specify mod or globs")
+ if mod is not None and not _ismodule(mod):
+ raise TypeError("Tester.__init__: mod must be a module; %r" % (mod,))
+ if globs is None:
+ globs = mod.__dict__
+ self.globs = globs
+
+ if verbose is None:
+ import sys
+ verbose = "-v" in sys.argv
+ self.verbose = verbose
+
+ # By default, assume that nothing is private
+ if isprivate is None:
+ isprivate = lambda fix, base: 0
+ self.isprivate = isprivate
+ self.optionflags = optionflags
+
+ self.name2ft = {} # map name to (#failures, #trials) pair
+
+ self.compileflags = _extract_future_flags(globs)
+
+ def runstring(self, s, name):
+ """
+ s, name -> search string s for examples to run, logging as name.
+
+ Use string name as the key for logging the outcome.
+ Return (#failures, #examples).
+
+ >>> t = Tester(globs={}, verbose=1)
+ >>> test = r'''
+ ... # just an example
+ ... >>> x = 1 + 2
+ ... >>> x
+ ... 3
+ ... '''
+ >>> t.runstring(test, "Example")
+ Running string Example
+ Trying: x = 1 + 2
+ Expecting: nothing
+ ok
+ Trying: x
+ Expecting: 3
+ ok
+ 0 of 2 examples failed in string Example
+ (0, 2)
+ """
+
+ if self.verbose:
+ print "Running string", name
+ f = t = 0
+ e = _extract_examples(s)
+ if e:
+ f, t = _run_examples(e, self.globs, self.verbose, name,
+ self.compileflags, self.optionflags)
+ if self.verbose:
+ print f, "of", t, "examples failed in string", name
+ self.__record_outcome(name, f, t)
+ return f, t
+
+ def rundoc(self, object, name=None):
+ """
+ object, name=None -> search object.__doc__ for examples to run.
+
+ Use optional string name as the key for logging the outcome;
+ by default use object.__name__.
+ Return (#failures, #examples).
+ If object is a class object, search recursively for method
+ docstrings too.
+ object.__doc__ is examined regardless of name, but if object is
+ a class, whether private names reached from object are searched
+ depends on the constructor's "isprivate" argument.
+
+ >>> t = Tester(globs={}, verbose=0)
+ >>> def _f():
+ ... '''Trivial docstring example.
+ ... >>> assert 2 == 2
+ ... '''
+ ... return 32
+ ...
+ >>> t.rundoc(_f) # expect 0 failures in 1 example
+ (0, 1)
+ """
+
+ if name is None:
+ try:
+ name = object.__name__
+ except AttributeError:
+ raise ValueError("Tester.rundoc: name must be given "
+ "when object.__name__ doesn't exist; %r" % (object,))
+ if self.verbose:
+ print "Running", name + ".__doc__"
+ f, t = run_docstring_examples(object, self.globs, self.verbose, name,
+ self.compileflags, self.optionflags)
+ if self.verbose:
+ print f, "of", t, "examples failed in", name + ".__doc__"
+ self.__record_outcome(name, f, t)
+ if _isclass(object):
+ # In 2.2, class and static methods complicate life. Build
+ # a dict "that works", by hook or by crook.
+ d = {}
+ for tag, kind, homecls, value in _classify_class_attrs(object):
+
+ if homecls is not object:
+ # Only look at names defined immediately by the class.
+ continue
+
+ elif self.isprivate(name, tag):
+ continue
+
+ elif kind == "method":
+ # value is already a function
+ d[tag] = value
+
+ elif kind == "static method":
+ # value isn't a function, but getattr reveals one
+ d[tag] = getattr(object, tag)
+
+ elif kind == "class method":
+ # Hmm. A classmethod object doesn't seem to reveal
+ # enough. But getattr turns it into a bound method,
+ # and from there .im_func retrieves the underlying
+ # function.
+ d[tag] = getattr(object, tag).im_func
+
+ elif kind == "property":
+ # The methods implementing the property have their
+ # own docstrings -- but the property may have one too.
+ if value.__doc__ is not None:
+ d[tag] = str(value.__doc__)
+
+ elif kind == "data":
+ # Grab nested classes.
+ if _isclass(value):
+ d[tag] = value
+
+ else:
+ raise ValueError("teach doctest about %r" % kind)
+
+ f2, t2 = self.run__test__(d, name)
+ f += f2
+ t += t2
+
+ return f, t
+
+ def rundict(self, d, name, module=None):
+ """
+ d, name, module=None -> search for docstring examples in d.values().
+
+ For k, v in d.items() such that v is a function or class,
+ do self.rundoc(v, name + "." + k). Whether this includes
+ objects with private names depends on the constructor's
+ "isprivate" argument. If module is specified, functions and
+ classes that are not defined in module are excluded.
+ Return aggregate (#failures, #examples).
+
+ Build and populate two modules with sample functions to test that
+ exclusion of external functions and classes works.
+
+ >>> import new
+ >>> m1 = new.module('_m1')
+ >>> m2 = new.module('_m2')
+ >>> test_data = \"""
+ ... def _f():
+ ... '''>>> assert 1 == 1
+ ... '''
+ ... def g():
+ ... '''>>> assert 2 != 1
+ ... '''
+ ... class H:
+ ... '''>>> assert 2 > 1
+ ... '''
+ ... def bar(self):
+ ... '''>>> assert 1 < 2
+ ... '''
+ ... \"""
+ >>> exec test_data in m1.__dict__
+ >>> exec test_data in m2.__dict__
+ >>> m1.__dict__.update({"f2": m2._f, "g2": m2.g, "h2": m2.H})
+
+ Tests that objects outside m1 are excluded:
+
+ >>> t = Tester(globs={}, verbose=0, isprivate=is_private)
+ >>> t.rundict(m1.__dict__, "rundict_test", m1) # _f, f2 and g2 and h2 skipped
+ (0, 3)
+
+ Again, but with the default isprivate function allowing _f:
+
+ >>> t = Tester(globs={}, verbose=0)
+ >>> t.rundict(m1.__dict__, "rundict_test_pvt", m1) # Only f2, g2 and h2 skipped
+ (0, 4)
+
+ And once more, not excluding stuff outside m1:
+
+ >>> t = Tester(globs={}, verbose=0)
+ >>> t.rundict(m1.__dict__, "rundict_test_pvt") # None are skipped.
+ (0, 8)
+
+ The exclusion of objects from outside the designated module is
+ meant to be invoked automagically by testmod.
+
+ >>> testmod(m1, isprivate=is_private)
+ (0, 3)
+
+ """
+
+ if not hasattr(d, "items"):
+ raise TypeError("Tester.rundict: d must support .items(); %r" % (d,))
+ f = t = 0
+ # Run the tests by alpha order of names, for consistency in
+ # verbose-mode output.
+ names = d.keys()
+ names.sort()
+ for thisname in names:
+ value = d[thisname]
+ if _isfunction(value) or _isclass(value):
+ if module and not _from_module(module, value):
+ continue
+ f2, t2 = self.__runone(value, name + "." + thisname)
+ f = f + f2
+ t = t + t2
+ return f, t
+
+ def run__test__(self, d, name):
+ """d, name -> Treat dict d like module.__test__.
+
+ Return (#failures, #tries).
+ See testmod.__doc__ for details.
+ """
+
+ failures = tries = 0
+ fix = name + "."
+ savepvt = self.isprivate
+ try:
+ self.isprivate = lambda *args: 0
+ # Run the tests by alpha order of names, for consistency in
+ # verbose-mode output.
+ keys = d.keys()
+ keys.sort()
+ for k in keys:
+ v = d[k]
+ thisname = fix + k
+ if type(v) in _StringTypes:
+ f, t = self.runstring(v, thisname)
+ elif _isfunction(v) or _isclass(v) or _ismethod(v):
+ f, t = self.rundoc(v, thisname)
+ else:
+ raise TypeError("Tester.run__test__: values in "
+ "dict must be strings, functions, methods, "
+ "or classes; %r" % (v,))
+ failures = failures + f
+ tries = tries + t
+ finally:
+ self.isprivate = savepvt
+ return failures, tries
+
+ def summarize(self, verbose=None):
+ """
+ verbose=None -> summarize results, return (#failures, #tests).
+
+ Print summary of test results to stdout.
+ Optional arg 'verbose' controls how wordy this is. By
+ default, use the verbose setting established by the
+ constructor.
+ """
+
+ if verbose is None:
+ verbose = self.verbose
+ notests = []
+ passed = []
+ failed = []
+ totalt = totalf = 0
+ for x in self.name2ft.items():
+ name, (f, t) = x
+ assert f <= t
+ totalt = totalt + t
+ totalf = totalf + f
+ if t == 0:
+ notests.append(name)
+ elif f == 0:
+ passed.append( (name, t) )
+ else:
+ failed.append(x)
+ if verbose:
+ if notests:
+ print len(notests), "items had no tests:"
+ notests.sort()
+ for thing in notests:
+ print " ", thing
+ if passed:
+ print len(passed), "items passed all tests:"
+ passed.sort()
+ for thing, count in passed:
+ print " %3d tests in %s" % (count, thing)
+ if failed:
+ print "*" * 65
+ print len(failed), "items had failures:"
+ failed.sort()
+ for thing, (f, t) in failed:
+ print " %3d of %3d in %s" % (f, t, thing)
+ if verbose:
+ print totalt, "tests in", len(self.name2ft), "items."
+ print totalt - totalf, "passed and", totalf, "failed."
+ if totalf:
+ print "***Test Failed***", totalf, "failures."
+ elif verbose:
+ print "Test passed."
+ return totalf, totalt
+
+ def merge(self, other):
+ """
+ other -> merge in test results from the other Tester instance.
+
+ If self and other both have a test result for something
+ with the same name, the (#failures, #tests) results are
+ summed, and a warning is printed to stdout.
+
+ >>> from doctest import Tester
+ >>> t1 = Tester(globs={}, verbose=0)
+ >>> t1.runstring('''
+ ... >>> x = 12
+ ... >>> print x
+ ... 12
+ ... ''', "t1example")
+ (0, 2)
+ >>>
+ >>> t2 = Tester(globs={}, verbose=0)
+ >>> t2.runstring('''
+ ... >>> x = 13
+ ... >>> print x
+ ... 13
+ ... ''', "t2example")
+ (0, 2)
+ >>> common = ">>> assert 1 + 2 == 3\\n"
+ >>> t1.runstring(common, "common")
+ (0, 1)
+ >>> t2.runstring(common, "common")
+ (0, 1)
+ >>> t1.merge(t2)
+ *** Tester.merge: 'common' in both testers; summing outcomes.
+ >>> t1.summarize(1)
+ 3 items passed all tests:
+ 2 tests in common
+ 2 tests in t1example
+ 2 tests in t2example
+ 6 tests in 3 items.
+ 6 passed and 0 failed.
+ Test passed.
+ (0, 6)
+ >>>
+ """
+
+ d = self.name2ft
+ for name, (f, t) in other.name2ft.items():
+ if name in d:
+ print "*** Tester.merge: '" + name + "' in both" \
+ " testers; summing outcomes."
+ f2, t2 = d[name]
+ f = f + f2
+ t = t + t2
+ d[name] = f, t
+
+ def __record_outcome(self, name, f, t):
+ if name in self.name2ft:
+ print "*** Warning: '" + name + "' was tested before;", \
+ "summing outcomes."
+ f2, t2 = self.name2ft[name]
+ f = f + f2
+ t = t + t2
+ self.name2ft[name] = f, t
+
+ def __runone(self, target, name):
+ if "." in name:
+ i = name.rindex(".")
+ fix, base = name[:i], name[i+1:]
+ else:
+ fix, base = "", base
+ if self.isprivate(fix, base):
+ return 0, 0
+ return self.rundoc(target, name)
+
+master = None
+
+def testmod(m=None, name=None, globs=None, verbose=None, isprivate=None,
+ report=True, optionflags=0):
+ """m=None, name=None, globs=None, verbose=None, isprivate=None,
+ report=True, optionflags=0
+
+ Test examples in docstrings in functions and classes reachable
+ from module m (or the current module if m is not supplied), starting
+ with m.__doc__. Unless isprivate is specified, private names
+ are not skipped.
+
+ Also test examples reachable from dict m.__test__ if it exists and is
+ not None. m.__dict__ maps names to functions, classes and strings;
+ function and class docstrings are tested even if the name is private;
+ strings are tested directly, as if they were docstrings.
+
+ Return (#failures, #tests).
+
+ See doctest.__doc__ for an overview.
+
+ Optional keyword arg "name" gives the name of the module; by default
+ use m.__name__.
+
+ Optional keyword arg "globs" gives a dict to be used as the globals
+ when executing examples; by default, use m.__dict__. A copy of this
+ dict is actually used for each docstring, so that each docstring's
+ examples start with a clean slate.
+
+ Optional keyword arg "verbose" prints lots of stuff if true, prints
+ only failures if false; by default, it's true iff "-v" is in sys.argv.
+
+ Optional keyword arg "isprivate" specifies a function used to
+ determine whether a name is private. The default function is
+ treat all functions as public. Optionally, "isprivate" can be
+ set to doctest.is_private to skip over functions marked as private
+ using the underscore naming convention; see its docs for details.
+
+ Optional keyword arg "report" prints a summary at the end when true,
+ else prints nothing at the end. In verbose mode, the summary is
+ detailed, else very brief (in fact, empty if all tests passed).
+
+ Optional keyword arg "optionflags" or's together module constants,
+ and defaults to 0. This is new in 2.3. Possible values:
+
+ DONT_ACCEPT_TRUE_FOR_1
+ By default, if an expected output block contains just "1",
+ an actual output block containing just "True" is considered
+ to be a match, and similarly for "0" versus "False". When
+ DONT_ACCEPT_TRUE_FOR_1 is specified, neither substitution
+ is allowed.
+
+ RUN_DEBUGGER_ON_UNEXPECTED_EXCEPTION
+ By default, a traceback is printed for each unexpected
+ exception. If this option is specified, the first unexpected
+ exception will cause pdb's post-mortem debugger to be run.
+
+ Advanced tomfoolery: testmod runs methods of a local instance of
+ class doctest.Tester, then merges the results into (or creates)
+ global Tester instance doctest.master. Methods of doctest.master
+ can be called directly too, if you want to do something unusual.
+ Passing report=0 to testmod is especially useful then, to delay
+ displaying a summary. Invoke doctest.master.summarize(verbose)
+ when you're done fiddling.
+ """
+
+ global master
+
+ if m is None:
+ import sys
+ # DWA - m will still be None if this wasn't invoked from the command
+ # line, in which case the following TypeError is about as good an error
+ # as we should expect
+ m = sys.modules.get('__main__')
+
+ if not _ismodule(m):
+ raise TypeError("testmod: module required; %r" % (m,))
+ if name is None:
+ name = m.__name__
+ tester = Tester(m, globs=globs, verbose=verbose, isprivate=isprivate,
+ optionflags=optionflags)
+ failures, tries = tester.rundoc(m, name)
+ f, t = tester.rundict(m.__dict__, name, m)
+ failures += f
+ tries += t
+ if hasattr(m, "__test__"):
+ testdict = m.__test__
+ if testdict:
+ if not hasattr(testdict, "items"):
+ raise TypeError("testmod: module.__test__ must support "
+ ".items(); %r" % (testdict,))
+ f, t = tester.run__test__(testdict, name + ".__test__")
+ failures += f
+ tries += t
+ if report:
+ tester.summarize()
+ if master is None:
+ master = tester
+ else:
+ master.merge(tester)
+ return failures, tries
+
+###########################################################################
+# Various doctest extensions, to make using doctest with unittest
+# easier, and to help debugging when a doctest goes wrong. Original
+# code by Jim Fulton.
+
+# Utilities.
+
+# If module is None, return the calling module (the module that called
+# the routine that called _normalize_module -- this normally won't be
+# doctest!). If module is a string, it should be the (possibly dotted)
+# name of a module, and the (rightmost) module object is returned. Else
+# module is returned untouched; the intent appears to be that module is
+# already a module object in this case (although this isn't checked).
+
+def _normalize_module(module):
+ import sys
+
+ if module is None:
+ # Get our caller's caller's module.
+ module = sys._getframe(2).f_globals['__name__']
+ module = sys.modules[module]
+
+ elif isinstance(module, basestring):
+ # The ["*"] at the end is a mostly meaningless incantation with
+ # a crucial property: if, e.g., module is 'a.b.c', it convinces
+ # __import__ to return c instead of a.
+ module = __import__(module, globals(), locals(), ["*"])
+
+ return module
+
+# tests is a list of (testname, docstring, filename, lineno) tuples.
+# If object has a __doc__ attr, and the __doc__ attr looks like it
+# contains a doctest (specifically, if it contains an instance of '>>>'),
+# then tuple
+# fix + name, object.__doc__, filename, lineno
+# is appended to tests. Else tests is left alone.
+# There is no return value.
+
+def _get_doctest(name, object, tests, fix, filename='', lineno=''):
+ doc = getattr(object, '__doc__', '')
+ if isinstance(doc, basestring) and '>>>' in doc:
+ tests.append((fix + name, doc, filename, lineno))
+
+# tests is a list of (testname, docstring, filename, lineno) tuples.
+# docstrings containing doctests are appended to tests (if any are found).
+# items is a dict, like a module or class dict, mapping strings to objects.
+# mdict is the global dict of a "home" module -- only objects belonging
+# to this module are searched for docstrings. module is the module to
+# which mdict belongs.
+# fix is a string to be pended to an object's name when adding a
+# tuple to tests.
+# The objects (values) in items are examined (recursively), and doctests
+# belonging to functions and classes in the home module are appended to
+# tests.
+# minlineno is a gimmick to try to guess the file-relative line number
+# at which a doctest probably begins.
+
+def _extract_doctests(items, module, mdict, tests, fix, minlineno=0):
+
+ for name, object in items:
+ # Only interested in named objects.
+ if not hasattr(object, '__name__'):
+ continue
+
+ elif hasattr(object, 'func_globals'):
+ # Looks like a function.
+ if object.func_globals is not mdict:
+ # Non-local function.
+ continue
+ code = getattr(object, 'func_code', None)
+ filename = getattr(code, 'co_filename', '')
+ lineno = getattr(code, 'co_firstlineno', -1) + 1
+ if minlineno:
+ minlineno = min(lineno, minlineno)
+ else:
+ minlineno = lineno
+ _get_doctest(name, object, tests, fix, filename, lineno)
+
+ elif hasattr(object, "__module__"):
+ # Maybe a class-like thing, in which case we care.
+ if object.__module__ != module.__name__:
+ # Not the same module.
+ continue
+ if not (hasattr(object, '__dict__')
+ and hasattr(object, '__bases__')):
+ # Not a class.
+ continue
+
+ lineno = _extract_doctests(object.__dict__.items(),
+ module,
+ mdict,
+ tests,
+ fix + name + ".")
+ # XXX "-3" is unclear.
+ _get_doctest(name, object, tests, fix,
+ lineno="%s (or above)" % (lineno - 3))
+
+ return minlineno
+
+# Find all the doctests belonging to the module object.
+# Return a list of
+# (testname, docstring, filename, lineno)
+# tuples.
+
+def _find_tests(module, fix=None):
+ if fix is None:
+ fix = module.__name__
+ mdict = module.__dict__
+ tests = []
+ # Get the module-level doctest (if any).
+ _get_doctest(fix, module, tests, '', lineno="1 (or above)")
+ # Recursively search the module __dict__ for doctests.
+ if fix:
+ fix += "."
+ _extract_doctests(mdict.items(), module, mdict, tests, fix)
+ return tests
+
+# unittest helpers.
+
+# A function passed to unittest, for unittest to drive.
+# tester is doctest Tester instance. doc is the docstring whose
+# doctests are to be run.
+
+def _utest(tester, name, doc, filename, lineno):
+ import sys
+ from StringIO import StringIO
+
+ old = sys.stdout
+ sys.stdout = new = StringIO()
+ try:
+ failures, tries = tester.runstring(doc, name)
+ finally:
+ sys.stdout = old
+
+ if failures:
+ msg = new.getvalue()
+ lname = '.'.join(name.split('.')[-1:])
+ if not lineno:
+ lineno = "0 (don't know line number)"
+ # Don't change this format! It was designed so that Emacs can
+ # parse it naturally.
+ raise DocTestTestFailure('Failed doctest test for %s\n'
+ ' File "%s", line %s, in %s\n\n%s' %
+ (name, filename, lineno, lname, msg))
+
+class DocTestTestFailure(Exception):
+ """A doctest test failed"""
+
+def DocTestSuite(module=None, options=None):
+ """Convert doctest tests for a module to a unittest TestSuite.
+
+ The returned TestSuite is to be run by the unittest framework, and
+ runs each doctest in the module. If any of the doctests fail,
+ then the synthesized unit test fails, and an error is raised showing
+ the name of the file containing the test and a (sometimes approximate)
+ line number.
+
+ The optional module argument provides the module to be tested. It
+ can be a module object or a (possibly dotted) module name. If not
+ specified, the module calling DocTestSuite() is used.
+
+ Example (although note that unittest supplies many ways to use the
+ TestSuite returned; see the unittest docs):
+
+ import unittest
+ import doctest
+ import my_module_with_doctests
+
+ suite = doctest.DocTestSuite(my_module_with_doctests)
+ runner = unittest.TextTestRunner()
+ runner.run(suite)
+ """
+
+ import unittest
+
+ module = _normalize_module(module)
+ tests = _find_tests(module)
+ if not tests:
+ raise ValueError(module, "has no tests")
+
+ tests.sort()
+ suite = unittest.TestSuite()
+ tester = Tester(module)
+ for name, doc, filename, lineno in tests:
+ if not filename:
+ filename = module.__file__
+ if filename.endswith(".pyc"):
+ filename = filename[:-1]
+ elif filename.endswith(".pyo"):
+ filename = filename[:-1]
+ def runit(name=name, doc=doc, filename=filename, lineno=lineno):
+ _utest(tester, name, doc, filename, lineno)
+ suite.addTest(unittest.FunctionTestCase(
+ runit,
+ description="doctest of " + name))
+ return suite
+
+# Debugging support.
+
+def _expect(expect):
+ # Return the expected output (if any), formatted as a Python
+ # comment block.
+ if expect:
+ expect = "\n# ".join(expect.split("\n"))
+ expect = "\n# Expect:\n# %s" % expect
+ return expect
+
+def testsource(module, name):
+ """Extract the doctest examples from a docstring.
+
+ Provide the module (or dotted name of the module) containing the
+ tests to be extracted, and the name (within the module) of the object
+ with the docstring containing the tests to be extracted.
+
+ The doctest examples are returned as a string containing Python
+ code. The expected output blocks in the examples are converted
+ to Python comments.
+ """
+
+ module = _normalize_module(module)
+ tests = _find_tests(module, "")
+ test = [doc for (tname, doc, dummy, dummy) in tests
+ if tname == name]
+ if not test:
+ raise ValueError(name, "not found in tests")
+ test = test[0]
+ examples = [source + _expect(expect)
+ for source, expect, dummy in _extract_examples(test)]
+ return '\n'.join(examples)
+
+def debug(module, name):
+ """Debug a single docstring containing doctests.
+
+ Provide the module (or dotted name of the module) containing the
+ docstring to be debugged, and the name (within the module) of the
+ object with the docstring to be debugged.
+
+ The doctest examples are extracted (see function testsource()),
+ and written to a temp file. The Python debugger (pdb) is then
+ invoked on that file.
+ """
+
+ import os
+ import pdb
+ import tempfile
+
+ module = _normalize_module(module)
+ testsrc = testsource(module, name)
+ srcfilename = tempfile.mktemp("doctestdebug.py")
+ f = file(srcfilename, 'w')
+ f.write(testsrc)
+ f.close()
+
+ globs = {}
+ globs.update(module.__dict__)
+ try:
+ # Note that %r is vital here. '%s' instead can, e.g., cause
+ # backslashes to get treated as metacharacters on Windows.
+ pdb.run("execfile(%r)" % srcfilename, globs, globs)
+ finally:
+ os.remove(srcfilename)
+
+
+
+class _TestClass:
+ """
+ A pointless class, for sanity-checking of docstring testing.
+
+ Methods:
+ square()
+ get()
+
+ >>> _TestClass(13).get() + _TestClass(-12).get()
+ 1
+ >>> hex(_TestClass(13).square().get())
+ '0xa9'
+ """
+
+ def __init__(self, val):
+ """val -> _TestClass object with associated value val.
+
+ >>> t = _TestClass(123)
+ >>> print t.get()
+ 123
+ """
+
+ self.val = val
+
+ def square(self):
+ """square() -> square TestClass's associated value
+
+ >>> _TestClass(13).square().get()
+ 169
+ """
+
+ self.val = self.val ** 2
+ return self
+
+ def get(self):
+ """get() -> return TestClass's associated value.
+
+ >>> x = _TestClass(-42)
+ >>> print x.get()
+ -42
+ """
+
+ return self.val
+
+__test__ = {"_TestClass": _TestClass,
+ "string": r"""
+ Example of a string object, searched as-is.
+ >>> x = 1; y = 2
+ >>> x + y, x * y
+ (3, 2)
+ """,
+ "bool-int equivalence": r"""
+ In 2.2, boolean exssions displayed
+ 0 or 1. By default, we still accept
+ them. This can be disabled by passing
+ DONT_ACCEPT_TRUE_FOR_1 to the new
+ optionflags argument.
+ >>> 4 == 4
+ 1
+ >>> 4 == 4
+ True
+ >>> 4 > 4
+ 0
+ >>> 4 > 4
+ False
+ """,
+ }
+
+def _test():
+ import doctest
+ return doctest.testmod(doctest)
+
+if __name__ == "__main__":
+ _test()
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/doctestunit.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/doctestunit.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,309 @@ />
+##############################################################################
+#
+# Copyright (c) 2003 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.
+#
+##############################################################################
+"""Extension to use doctest tests as unit tests
+
+This module provides a DocTestSuite contructor for converting doctest
+tests to unit tests.
+
+$Id: doctestunit.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+
+from StringIO import StringIO
+import doctest
+import os
+import pdb
+import sys
+import tempfile
+import unittest
+
+
+class DocTestTestCase(unittest.TestCase):
+ """A test case that wraps a test function.
+
+ This is useful for slipping -existing test functions into the
+ PyUnit framework. Optionally, set-up and tidy-up functions can be
+ supplied. As with TestCase, the tidy-up ('tearDown') function will
+ always be called if the set-up ('setUp') function ran successfully.
+ """
+
+ def __init__(self, tester, name, doc, filename, lineno,
+ setUp=None, tearDown=None):
+ unittest.TestCase.__init__(self)
+ (self.__tester, self.__name, self.__doc,
+ self.__filename, self.__lineno,
+ self.__setUp, self.__tearDown
+ ) = tester, name, doc, filename, lineno, setUp, tearDown
+
+ def setUp(self):
+ if self.__setUp is not None:
+ self.__setUp()
+
+ def tearDown(self):
+ if self.__tearDown is not None:
+ self.__tearDown()
+
+ def setDebugModeOn(self):
+ self.__tester.optionflags |= (
+ doctest.RUN_DEBUGGER_ON_UNEXPECTED_EXCEPTION)
+
+ def runTest(self):
+ old = sys.stdout
+ new = StringIO()
+ try:
+ sys.stdout = new
+ failures, tries = self.__tester.runstring(self.__doc, self.__name)
+ finally:
+ sys.stdout = old
+
+ if failures:
+ lname = '.'.join(self.__name.split('.')[-1:])
+ lineno = self.__lineno or "0 (don't know line no)"
+ raise self.failureException(
+ 'Failed doctest test for %s\n'
+ ' File "%s", line %s, in %s\n\n%s'
+ % (self.__name, self.__filename, lineno, lname, new.getvalue())
+ )
+
+ def id(self):
+ return self.__name
+
+ def __repr__(self):
+ name = self.__name.split('.')
+ return "%s (%s)" % (name[-1], '.'.join(name[:-1]))
+
+ __str__ = __repr__
+
+ def shortDescription(self):
+ return "Doctest: " + self.__name
+
+def DocFileSuite(package, *paths):
+ """Creates a suite of doctest files.
+
+ package is the source package containing the doctest files.
+
+ Each subsequent argument is a string specifying the file name of the
+ doctest relative to the package.
+ """
+
+ # It's not entirely obvious how to connection this single string
+ # with unittest. For now, re-use the _utest() function that comes
+ # standard with doctest in Python 2.3. One problem is that the
+ # error indicator doesn't point to the line of the doctest file
+ # that failed.
+ import os, doctest, new
+ t = doctest.Tester(globs={})
+ suite = unittest.TestSuite()
+ dir = os.path.split(package.__file__)[0]
+ for path in paths:
+ path = os.path.join(dir, path)
+ source = open(path).read()
+ def runit(path=path, source=source):
+ doctest._utest(t, path, source, path, 0)
+ runit = new.function(runit.func_code, runit.func_globals, path,
+ runit.func_defaults, runit.func_closure)
+ f = unittest.FunctionTestCase(runit,
+ description="doctest from %s" % path)
+ suite.addTest(f)
+ return suite
+
+def DocTestSuite(module=None,
+ setUp=lambda: None,
+ tearDown=lambda: None,
+ ):
+ """Convert doctest tests for a mudule to a unittest test suite
+
+ This tests convers each documentation string in a module that
+ contains doctest tests to a unittest test case. If any of the
+ tests in a doc string fail, then the test case fails. An error is
+ raised showing the name of the file containing the test and a
+ (sometimes approximate) line number.
+
+ A module argument provides the module to be tested. The argument
+ can be either a module or a module name.
+
+ If no argument is given, the calling module is used.
+
+ """
+ module = _normalizeModule(module)
+ tests = _findTests(module)
+
+ if not tests:
+ raise ValueError(module, "has no tests")
+
+ tests.sort()
+ suite = unittest.TestSuite()
+ tester = doctest.Tester(module)
+ for name, doc, filename, lineno in tests:
+ if not filename:
+ filename = module.__file__
+ if filename.endswith(".pyc"):
+ filename = filename[:-1]
+ elif filename.endswith(".pyo"):
+ filename = filename[:-1]
+
+ suite.addTest(DocTestTestCase(
+ tester, name, doc, filename, lineno,
+ setUp, tearDown))
+
+
+ return suite
+
+def _normalizeModule(module):
+ # Normalize a module
+ if module is None:
+ # Test the calling module
+ module = sys._getframe(2).f_globals['__name__']
+ module = sys.modules[module]
+
+ elif isinstance(module, (str, unicode)):
+ module = __import__(module, globals(), locals(), ["*"])
+
+ return module
+
+def _doc(name, object, tests, fix, filename='', lineno=''):
+ doc = getattr(object, '__doc__', '')
+ if doc and doc.find('>>>') >= 0:
+ tests.append((fix+name, doc, filename, lineno))
+
+
+def _findTests(module, fix=None):
+ if fix is None:
+ fix = module.__name__
+ dict = module.__dict__
+ tests = []
+ _doc(fix, module, tests, '',
+ lineno="1 (or below)")
+ fix = fix and (fix + ".")
+ _find(dict.items(), module, dict, tests, fix)
+ return tests
+
+def _find(items, module, dict, tests, fix, minlineno=0):
+ for name, object in items:
+
+ # Only interested in named objects
+ if not hasattr(object, '__name__'):
+ continue
+
+ if hasattr(object, 'func_globals'):
+ # Looks like a func
+ if object.func_globals is not dict:
+ # Non-local func
+ continue
+ code = getattr(object, 'func_code', None)
+ filename = getattr(code, 'co_filename', '')
+ lineno = getattr(code, 'co_firstlineno', -1) + 1
+ if minlineno:
+ minlineno = min(lineno, minlineno)
+ else:
+ minlineno = lineno
+ _doc(name, object, tests, fix, filename, lineno)
+
+ elif hasattr(object, "__module__"):
+ # Maybe a class-like things. In which case, we care
+ if object.__module__ != module.__name__:
+ continue # not the same module
+ if not (hasattr(object, '__dict__')
+ and hasattr(object, '__bases__')):
+ continue # not a class
+
+ lineno = _find(object.__dict__.items(), module, dict, tests,
+ fix+name+".")
+
+ _doc(name, object, tests, fix,
+ lineno="%s (or above)" % (lineno-3))
+
+ return minlineno
+
+
+
+
+####################################################################
+# doctest debugger
+
+def _expect(expect):
+ # Return the expected output, if any
+ if expect:
+ expect = "\n# ".join(expect.split("\n"))
+ expect = "\n# Expect:\n# %s" % expect
+ return expect
+
+def testsource(module, name):
+ """Extract the test sources from a doctest test docstring as a script
+
+ Provide the module (or dotted name of the module) containing the
+ test to be debugged and the name (within the module) of the object
+ with the doc string with tests to be debugged.
+
+ """
+ module = _normalizeModule(module)
+ tests = _findTests(module, "")
+ test = [doc for (tname, doc, f, l) in tests if tname == name]
+ if not test:
+ raise ValueError(name, "not found in tests")
+ test = test[0]
+ # XXX we rely on an internal doctest function:
+ examples = doctest._extract_examples(test)
+ testsrc = '\n'.join([
+ "%s%s" % (source, _expect(expect))
+ for (source, expect, lineno) in examples
+ ])
+ return testsrc
+
+def debug_src(src, pm=False, globs=None):
+ """Debug a single doctest test doc string
+
+ The string is provided directly
+ """
+ # XXX we rely on an internal doctest function:
+ examples = doctest._extract_examples(src)
+ src = '\n'.join([
+ "%s%s" % (source, _expect(expect))
+ for (source, expect, lineno) in examples
+ ])
+ debug_script(src, pm, globs)
+
+def debug_script(src, pm=False, globs=None):
+ "Debug a test script"
+ srcfilename = tempfile.mktemp("doctestdebug.py")
+ open(srcfilename, 'w').write(src)
+ if globs:
+ globs = globs.copy()
+ else:
+ globs = {}
+
+ try:
+ if pm:
+ try:
+ execfile(srcfilename, globs, globs)
+ except:
+ print sys.exc_info()[1]
+ pdb.post_mortem(sys.exc_info()[2])
+ else:
+ # Note that %r is vital here. '%s' instead can, e.g., cause
+ # backslashes to get treated as metacharacters on Windows.
+ pdb.run("execfile(%r)" % srcfilename, globs, globs)
+ finally:
+ os.remove(srcfilename)
+
+def debug(module, name, pm=False):
+ """Debug a single doctest test doc string
+
+ Provide the module (or dotted name of the module) containing the
+ test to be debugged and the name (within the module) of the object
+ with the doc string with tests to be debugged.
+
+ """
+ module = _normalizeModule(module)
+ testsrc = testsource(module, name)
+ debug_script(testsrc, pm, module.__dict__)
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/loggingsupport.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/loggingsupport.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,122 @@ />
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Support for testing logging code
+
+If you want to test that your code generates proper log output, you
+can create and install a handler that collects output:
+
+ >>> handler = InstalledHandler('foo.bar')
+
+The handler is installed into loggers for all of the names passed. In
+addition, the logger level is set to 1, which means, log
+everything. If you want to log less than everything, you can provide a
+level keyword argument. The level setting effects only the named
+loggers.
+
+Then, any log output is collected in the handler:
+
+ >>> logging.getLogger('foo.bar').exception('eek')
+ >>> logging.getLogger('foo.bar').info('blah blah')
+
+ >>> for record in handler.records:
+ ... print record.name, record.levelname
+ ... print ' ', record.getMessage()
+ foo.bar ERROR
+ eek
+ foo.bar INFO
+ blah blah
+
+A similar effect can be gotten by just printing the handler:
+
+ >>> print handler
+ foo.bar ERROR
+ eek
+ foo.bar INFO
+ blah blah
+
+After checking the log output, you need to uninstall the handler:
+
+ >>> handler.uninstall()
+
+At which point, the handler won't get any more log output.
+Let's clear the handler:
+
+ >>> handler.clear()
+ >>> handler.records
+ []
+
+And then log something:
+
+ >>> logging.getLogger('foo.bar').info('blah')
+
+and, sure enough, we still have no output:
+
+ >>> handler.records
+ []
+
+$Id: loggingsupport.py 24809 2004-05-18 18:45:05Z fdrake $
+"""
+
+import logging
+
+class Handler(logging.Handler):
+
+ def __init__(self, *names, **kw):
+ logging.Handler.__init__(self)
+ self.names = names
+ self.records = []
+ self.setLoggerLevel(**kw)
+
+ def setLoggerLevel(self, level=1):
+ self.level = level
+ self.oldlevels = {}
+
+ def emit(self, record):
+ self.records.append(record)
+
+ def clear(self):
+ del self.records[:]
+
+ def install(self):
+ for name in self.names:
+ logger = logging.getLogger(name)
+ self.oldlevels[name] = logger.level
+ logger.setLevel(self.level)
+ logger.addHandler(self)
+
+ def uninstall(self):
+ for name in self.names:
+ logger = logging.getLogger(name)
+ logger.setLevel(self.oldlevels[name])
+ logger.removeHandler(self)
+
+ def __str__(self):
+ return '\n'.join(
+ [("%s %s\n %s" %
+ (record.name, record.levelname,
+ '\n'.join([line
+ for line in record.getMessage().split('\n')
+ if line.strip()])
+ )
+ )
+ for record in self.records]
+ )
+
+
+class InstalledHandler(Handler):
+
+ def __init__(self, *names):
+ Handler.__init__(self, *names)
+ self.install()
+
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/loghandler.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/loghandler.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,75 @@ />
+##############################################################################
+#
+# Copyright (c) 2003 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.
+#
+##############################################################################
+"""logging handler for tests that check logging output."""
+
+import logging
+
+class Handler(logging.Handler):
+ """Handler for use with unittest.TestCase objects.
+
+ The handler takes a TestCase instance as a constructor argument.
+ It can be registered with one or more loggers and collects log
+ records they generate.
+
+ The assertLogsMessage() and failIfLogsMessage() methods can be
+ used to check the logger output and causes the test to fail as
+ appropriate.
+ """
+
+ def __init__(self, testcase, propagate=False):
+ logging.Handler.__init__(self)
+ self.records = []
+ # loggers stores (logger, propagate) tuples
+ self.loggers = []
+ self.closed = False
+ self.propagate = propagate
+ self.testcase = testcase
+
+ def close(self):
+ """Remove handler from any loggers it was added to."""
+ if self.closed:
+ return
+ for logger, propagate in self.loggers:
+ logger.removeHandler(self)
+ logger.propagate = propagate
+ self.closed = True
+
+ def add(self, name):
+ """Add handler to logger named name."""
+ logger = logging.getLogger(name)
+ old_prop = logger.propagate
+ logger.addHandler(self)
+ if self.propagate:
+ logger.propagate = 1
+ else:
+ logger.propagate = 0
+ self.loggers.append((logger, old_prop))
+
+ def emit(self, record):
+ self.records.append(record)
+
+ def assertLogsMessage(self, msg, level=None):
+ for r in self.records:
+ if r.getMessage() == msg:
+ if level is not None and r.levelno == level:
+ return
+ msg = "No log message contained %r" % msg
+ if level is not None:
+ msg += " at level %d" % level
+ self.testcase.fail(msg)
+
+ def failIfLogsMessage(self, msg):
+ for r in self.records:
+ if r.getMessage() == msg:
+ self.testcase.fail("Found log message %r" % msg)
Added: CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/tests.py
==============================================================================
--- (empty file)
+++ CMFPlone/branches/tiran-z3iface-branch/zope3/zope/testing/tests.py Wed Jun 2 16:09:24 2004
@@ -0,0 +1,29 @@ />
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""XXX short summary goes here.
+
+$Id: tests.py 24749 2004-05-16 13:00:21Z philikon $
+"""
+import unittest
+from zope.testing.doctestunit import DocTestSuite
+
+
+def test_suite():
+ return unittest.TestSuite((
+ DocTestSuite('zope.testing.loggingsupport'),
+ ))
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
+
|
|