Commit 349c8486 authored by Tim Peters's avatar Tim Peters

Primary thrust here is to teach ZODB about zope.interface,

and include that in the ZODB project.  While we're at it,
include zope.testing too, as zope.interface depends on that,
and we had copied zope.testing.loggingsupport.py into ZODB
earlier anyway (and delete that unique copy here now).

This also merges some changes made to the ZODB copy in
Zope3 back into ZODB.
parent fe1edd81
...@@ -35,6 +35,8 @@ from ZODB.POSException \ ...@@ -35,6 +35,8 @@ from ZODB.POSException \
from ZODB.TmpStore import TmpStore from ZODB.TmpStore import TmpStore
from ZODB.utils import oid_repr, z64, positive_id from ZODB.utils import oid_repr, z64, positive_id
from ZODB.serialize import ObjectWriter, ConnectionObjectReader, myhasattr from ZODB.serialize import ObjectWriter, ConnectionObjectReader, myhasattr
from ZODB.interfaces import IConnection
from zope.interface import implements
global_reset_counter = 0 global_reset_counter = 0
...@@ -147,6 +149,7 @@ class Connection(ExportImport, object): ...@@ -147,6 +149,7 @@ class Connection(ExportImport, object):
getTransferCounts getTransferCounts
""" """
implements(IConnection)
_tmp = None _tmp = None
_code_timestamp = 0 _code_timestamp = 0
......
...@@ -16,19 +16,10 @@ ...@@ -16,19 +16,10 @@
$Id$ $Id$
""" """
try: import zope.interface
from zope.interface import Interface, Attribute from zope.interface import Attribute
except ImportError:
class Interface:
pass
class Attribute: class IDataManager(zope.interface.Interface):
def __init__(self, __name__, __doc__):
self.__name__ = __name__
self.__doc__ = __doc__
class IDataManager(Interface):
"""Objects that manage transactional storage. """Objects that manage transactional storage.
These object's may manage data for other objects, or they may manage These object's may manage data for other objects, or they may manage
...@@ -145,7 +136,7 @@ class IDataManager(Interface): ...@@ -145,7 +136,7 @@ class IDataManager(Interface):
""" """
class ITransaction(Interface): class ITransaction(zope.interface.Interface):
"""Object representing a running transaction. """Object representing a running transaction.
Objects with this interface may represent different transactions Objects with this interface may represent different transactions
...@@ -224,3 +215,26 @@ class ITransaction(Interface): ...@@ -224,3 +215,26 @@ class ITransaction(Interface):
""" """
# XXX is this this allowed to cause an exception here, during # XXX is this this allowed to cause an exception here, during
# the two-phase commit, or can it toss data silently? # the two-phase commit, or can it toss data silently?
class IConnection(zope.interface.Interface):
"""ZODB connection.
XXX: This interface is incomplete.
"""
def add(ob):
"""Add a new object 'obj' to the database and assign it an oid.
A persistent object is normally added to the database and
assigned an oid when it becomes reachable to an object already in
the database. In some cases, it is useful to create a new
object and use its oid (_p_oid) in a single transaction.
This method assigns a new oid regardless of whether the object
is reachable.
The object is added when the transaction commits. The object
must implement the IPersistent interface and must not
already be associated with a Connection.
"""
...@@ -22,6 +22,7 @@ import transaction ...@@ -22,6 +22,7 @@ import transaction
from ZODB.config import databaseFromString from ZODB.config import databaseFromString
from ZODB.utils import p64, u64 from ZODB.utils import p64, u64
from ZODB.tests.warnhook import WarningsHook from ZODB.tests.warnhook import WarningsHook
from zope.interface.verify import verifyObject
class ConnectionDotAdd(unittest.TestCase): class ConnectionDotAdd(unittest.TestCase):
...@@ -595,6 +596,15 @@ class StubStorage: ...@@ -595,6 +596,15 @@ class StubStorage:
return None return None
class TestConnectionInterface(unittest.TestCase):
def test_connection_interface(self):
from ZODB.interfaces import IConnection
db = databaseFromString("<zodb>\n<mappingstorage/>\n</zodb>")
cn = db.open()
verifyObject(IConnection, cn)
class StubDatabase: class StubDatabase:
def __init__(self): def __init__(self):
...@@ -608,4 +618,5 @@ class StubDatabase: ...@@ -608,4 +618,5 @@ class StubDatabase:
def test_suite(): def test_suite():
s = unittest.makeSuite(ConnectionDotAdd, 'check') s = unittest.makeSuite(ConnectionDotAdd, 'check')
s.addTest(doctest.DocTestSuite()) s.addTest(doctest.DocTestSuite())
s.addTest(unittest.makeSuite(TestConnectionInterface))
return s return s
...@@ -227,7 +227,7 @@ def testTimeTravelOnOpen(): ...@@ -227,7 +227,7 @@ def testTimeTravelOnOpen():
>>> from ZODB.FileStorage import FileStorage >>> from ZODB.FileStorage import FileStorage
>>> from ZODB.DB import DB >>> from ZODB.DB import DB
>>> import transaction >>> import transaction
>>> from ZODB.tests.loggingsupport import InstalledHandler >>> from zope.testing.loggingsupport import InstalledHandler
Arrange to capture log messages -- they're an important part of Arrange to capture log messages -- they're an important part of
this test! this test!
......
# Empty __init__ to make this a package.
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.1
Description:
The implementation of interface definitions for Zope 3.
This diff is collapsed.
# Extension information for zpkg:
<extension _zope_interface_coptimizations>
source _zope_interface_coptimizations.c
</extension>
##############################################################################
#
# 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.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""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$
"""
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)
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Adapter-style interface registry
See Adapter class.
$Id$
"""
__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
This diff is collapsed.
This diff is collapsed.
================
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
previously-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 prefered over O(12)::
>>> registry.lookup([IR1], IP1, '')
11
Also, if we register an object for IR2, then that will be prefered
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
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""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$
"""
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"
# )
previousMetaclass = caller_locals.get('__metaclass__')
defaultMetaclass = caller_globals.get('__metaclass__', ClassType)
def advise(name, bases, cdict):
if '__metaclass__' in cdict:
del cdict['__metaclass__']
if previousMetaclass is None:
if bases:
# find best metaclass or use global __metaclass__ if no bases
meta = determineMetaclass(bases)
else:
meta = defaultMetaclass
elif isClassAdvisor(previousMetaclass):
# special case: we can't compute the "true" metaclass here,
# so we need to invoke the previous metaclass and let it
# figure it out for us (and apply its own advice in the process)
meta = previousMetaclass
else:
meta = determineMetaclass(bases, previousMetaclass)
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.previousMetaclass = previousMetaclass
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,'previousMetaclass')
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
#
# This file is necessary to make this directory a package.
This diff is collapsed.
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Interfaces for standard python exceptions
$Id$
"""
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 IDeprecationWarning(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(DeprecationWarning, IDeprecationWarning)
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)
##############################################################################
#
# 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.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Mapping Interfaces
$Id$
"""
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 '''
#
# This file is necessary to make this directory a package.
##############################################################################
#
# 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.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""
Revision information:
$Id$
"""
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()
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Test for datetime interfaces
$Id$
"""
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()
This diff is collapsed.
##############################################################################
#
# 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.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
""" 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$
"""
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)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#
# This file is necessary to make this directory a package.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
"""Test module that declares an interface
"""
from zope.interface import Interface, moduleProvides
class I1(Interface): pass
class I2(Interface): pass
moduleProvides(I1, I2)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment