[Zope3-checkins] CVS: Packages3/Interface - Attribute.py:1.6 Document.py:1.6 Exceptions.py:1.12 IAttribute.py:1.5 IElement.py:1.6 IInterface.py:1.9 IMethod.py:1.5 Implements.py:1.9 Mapping.py:1.6 Method.py:1.15 Verify.py:1.8 _Element.py:1.5 _Interface.py:1.7 _InterfaceClass.py:1.15 __init__.py:1.11 _object.py:1.5 pprint.py:1.8 pyskel.py:1.10

Jim Fulton jim@zope.com
Fri, 18 Apr 2003 06:03:50 -0400


Update of /cvs-repository/Packages3/Interface
In directory cvs.zope.org:/tmp/cvs-serv27994

Added Files:
	Attribute.py Document.py Exceptions.py IAttribute.py 
	IElement.py IInterface.py IMethod.py Implements.py Mapping.py 
	Method.py Verify.py _Element.py _Interface.py 
	_InterfaceClass.py __init__.py _object.py pprint.py pyskel.py 
Log Message:
committing z2 sources in preparation for z3 compatability layer over zope.interface

=== Packages3/Interface/Attribute.py 1.5 => 1.6 ===
--- /dev/null	Fri Apr 18 06:03:49 2003
+++ Packages3/Interface/Attribute.py	Fri Apr 18 06:03:18 2003
@@ -0,0 +1,29 @@
+##############################################################################
+#
+# 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$
+"""
+
+from _Element import Element
+
+class Attribute(Element):
+    """Attribute descriptions
+    """
+
+    # We can't say this yet because we don't have enough
+    # infrastructure in place.
+    #
+    #__implements__ = IAttribute


=== Packages3/Interface/Document.py 1.5 => 1.6 ===
--- /dev/null	Fri Apr 18 06:03:49 2003
+++ Packages3/Interface/Document.py	Fri Apr 18 06:03:18 2003
@@ -0,0 +1,118 @@
+##############################################################################
+#
+# 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$
+"""
+
+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")
+
+    if I.getBases():
+        outp((" " * level) + "This interface extends:\n\n")
+        level = level + 1
+        for b in I.getBases():
+            item = "o %s" % b.getName()
+            outp(_justify_and_indent(_trim_doc_string(item), level, munge)
+                 + "\n\n")
+
+        level = level - 1
+
+    namesAndDescriptions = list(I.namesAndDescriptions())
+    namesAndDescriptions.sort()
+
+
+    outp(_justify_and_indent("Attributes:", level, munge)+'\n\n')
+    level = level + 1
+    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)


=== Packages3/Interface/Exceptions.py 1.11 => 1.12 ===
--- /dev/null	Fri Apr 18 06:03:49 2003
+++ Packages3/Interface/Exceptions.py	Fri Apr 18 06:03:18 2003
@@ -0,0 +1,63 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+
+class DoesNotImplement(Exception):
+    """ 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(Exception):
+    """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(Exception):
+    """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.
+    """


=== Packages3/Interface/IAttribute.py 1.4 => 1.5 ===
--- /dev/null	Fri Apr 18 06:03:49 2003
+++ Packages3/Interface/IAttribute.py	Fri Apr 18 06:03:18 2003
@@ -0,0 +1,23 @@
+##############################################################################
+#
+# 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$
+"""
+
+from IElement import IElement
+
+class IAttribute(IElement):
+    """Attribute descriptors"""


=== Packages3/Interface/IElement.py 1.5 => 1.6 ===
--- /dev/null	Fri Apr 18 06:03:49 2003
+++ Packages3/Interface/IElement.py	Fri Apr 18 06:03:18 2003
@@ -0,0 +1,43 @@
+##############################################################################
+#
+# 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$
+"""
+
+from _Interface import Interface
+from Attribute 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 getName():
+        """Returns the name of the object."""
+
+    def getDoc():
+        """Returns the documentation for the object."""
+
+    def getTaggedValue(tag):
+        """Returns the value associated with 'tag'."""
+
+    def getTaggedValueTags():
+        """Returns a list of all tags."""
+
+    def setTaggedValue(tag, value):
+        """Associates 'value' with 'key'."""


=== Packages3/Interface/IInterface.py 1.8 => 1.9 ===
--- /dev/null	Fri Apr 18 06:03:49 2003
+++ Packages3/Interface/IInterface.py	Fri Apr 18 06:03:18 2003
@@ -0,0 +1,200 @@
+##############################################################################
+#
+# 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$
+"""
+
+from IElement import IElement
+
+class IInterface(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, pre/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 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. Include an '__implements__' attribute in the object's class
+         definition. The value of the '__implements__' attribute must
+         be an implementation specification. An implementation
+         specification is either an interface or a tuple of
+         implementation specifications.
+
+      2. Incluse an '__implements__' attribute in the object.
+         Because Python classes don't have their own attributes, to
+         assert that a class implements interfaces, you must provide a
+         '__class_implements__' attribute in the class definition.
+
+         **Important**: A class usually doesn't implement the
+           interfaces that it's instances implement. The class and
+           it's instances are separate objects with their own
+           interfaces.
+
+      3. Call 'Interface.Implements.implements' to assert that instances
+         of a class implement an interface.
+
+         For example::
+
+           from Interface.Implements import implements
+
+           implements(some_class, some_interface)
+
+         This is 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 it's instances
+         implement.
+
+      4. For types that can't be modified, you can assert that
+         instances of the type implement an interface using
+         'Interface.Implements.assertTypeImplements'.
+
+         For example::
+
+           from Interface.Implements import assertTypeImplements
+
+           assertTypeImplements(some_type, some_interface)
+
+    o You query interface meta-data. See the IInterface methods and
+      attributes for details.
+
+    """
+
+    def getBases():
+        """Return a sequence of the base interfaces
+        """
+
+    def extends(other, strict=1):
+        """Test whether the interface extends another interface
+
+        A true value is returned in the interface extends the other
+        interface, and false otherwise.
+
+        Normally, an interface doesn't extend itself. If a false value
+        is passed as the second argument, or via the 'strict' keyword
+        argument, then a true value will be returned if the interface
+        and the other interface are the same.
+        """
+
+    def isImplementedBy(object):
+        """Test whether the interface is implemented by the object.
+
+        Return true of the object asserts that it implements the
+        interface, including asseting that it implements an extended
+        interface.
+        """
+
+    def isImplementedByInstancesOf(class_):
+        """Test whether the interface is implemented by instances of the class
+
+        Return true of the class asserts that it's instances implement the
+        interface, including asseting that they implement an extended
+        interface.
+        """
+    def names(all=0):
+        """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 nase classes will be included.
+        """
+
+    def namesAndDescriptions(all=0):
+        """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 nase classes will be included.
+        """
+
+    def getDescriptionFor(name):
+        """Get the description for a name
+
+        If the named attribute does not exist, a KeyError is raised.
+        """
+
+    def queryDescriptionFor(name, default=None):
+        """Get the description for a name
+
+        Return the default if no description exists.
+        """


=== Packages3/Interface/IMethod.py 1.4 => 1.5 ===
--- /dev/null	Fri Apr 18 06:03:49 2003
+++ Packages3/Interface/IMethod.py	Fri Apr 18 06:03:18 2003
@@ -0,0 +1,29 @@
+##############################################################################
+#
+# 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$
+"""
+
+from IAttribute import IAttribute
+
+class IMethod(IAttribute):
+    """Method attributes
+    """
+    # XXX What the heck should methods provide? Grrrr
+
+    def getSignatureString():
+        """Return a signature string suitable for inclusion in documentation.
+        """


=== Packages3/Interface/Implements.py 1.8 => 1.9 ===
--- /dev/null	Fri Apr 18 06:03:49 2003
+++ Packages3/Interface/Implements.py	Fri Apr 18 06:03:18 2003
@@ -0,0 +1,158 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Implemantation assertion facilities.
+
+Revision information:
+$Id$
+"""
+
+import Exceptions
+from types import ClassType
+from Verify import verifyClass
+from _InterfaceClass import Interface as InterfaceClass
+from types import TupleType, ClassType, StringType
+
+# Special value indicating the object supports
+# what its class supports.
+CLASS_INTERFACES = 1
+
+from _object import ClassTypes, isInstance
+
+_typeImplements={}
+
+def getImplements(object):
+    t = type(object)
+    if t in ClassTypes:
+        if hasattr(object, '__class_implements__'):
+            return object.__class_implements__
+    elif hasattr(object, '__implements__'):
+        return object.__implements__
+
+    return _typeImplements.get(t, None)
+
+
+def getImplementsOfInstances(klass, tiget=_typeImplements.get):
+    if type(klass) in ClassTypes:
+        if hasattr(klass, '__implements__'):
+            return klass.__implements__
+        else:
+            return None
+    else:
+        return tiget(klass, None)
+
+
+def visitImplements(implements, object, visitor, getInterface=None):
+    """
+    Visits the interfaces described by an __implements__ attribute,
+    invoking the visitor for each interface object.
+    If the visitor returns anything true, the loop stops.
+    This does not, and should not, visit superinterfaces.
+    """
+    # this allows us to work with proxy wrappers in Python 2.2,
+    # yet remain compatible with earlier versions of python.
+    implements_class = getattr(implements, '__class__', None)
+
+    if implements_class == InterfaceClass or \
+       isInstance(implements, InterfaceClass):
+        return visitor(implements)
+    elif implements == CLASS_INTERFACES:
+        klass = getattr(object, '__class__', None)
+        if klass is not None:
+            i = getImplementsOfInstances(klass)
+            if i:
+                return visitImplements(i, object, visitor, getInterface)
+    elif implements_class == StringType or type(implements) is StringType:
+        if getInterface is not None:
+            # Look up a named interface.
+            i = getInterface(object, implements)
+            if i is not None:
+                return visitImplements(i, object, visitor, getInterface)
+    elif implements_class == TupleType or type(implements) is TupleType:
+        for i in implements:
+            r = visitImplements(i, object, visitor, getInterface)
+            if r:
+                # If the visitor returns anything true, stop.
+                return r
+    else:
+        if implements_class is not None and \
+           type(implements) != implements_class:
+            raise Exceptions.BadImplements(
+                """__implements__ should be an interface or tuple,
+                not a %s pretending to be a %s"""
+                % (type(implements).__name__, implements_class.__name__)
+                )
+        raise Exceptions.BadImplements(
+            """__implements__ should be an interface or tuple,
+            not a %s""" % type(implements).__name__)
+    return 0
+
+
+def assertTypeImplements(type, interfaces):
+    """Assign a set of interfaces to a Python type such as int, str, tuple,
+       list and dict.
+    """
+    _typeImplements[type]=interfaces
+
+def objectImplements(object, getInterface=None):
+    r = []
+    implements = getImplements(object)
+    if not implements:
+        return r
+    visitImplements(implements, object, r.append, getInterface)
+    return r
+
+def instancesOfObjectImplements(klass, getInterface=None):
+    r = []
+    implements = getImplementsOfInstances(klass)
+    if not implements:
+        return r
+    visitImplements(implements, klass, r.append, getInterface)
+    return r
+
+
+def _flatten(i, append):
+    append(i)
+    bases = i.getBases()
+    if bases:
+        for b in bases:
+            _flatten(b, append)
+
+
+def flattenInterfaces(interfaces, remove_duplicates=1):
+    res = []
+    for i in interfaces:
+        _flatten(i, res.append)
+    if remove_duplicates:
+        # Remove duplicates in reverse.
+        # Similar to Python 2.2's method resolution order.
+        seen = {}
+        index = len(res) - 1
+        while index >= 0:
+            i = res[index]
+            if seen.has_key(i):
+                del res[index]
+            else:
+                seen[i] = 1
+            index = index - 1
+    return res
+
+def implements(klass, interface, check=1):
+    if check:
+        verifyClass(interface, klass, tentative=1)
+
+    old=getattr(klass, '__implements__', None)
+    if old is None:
+        klass.__implements__ = interface
+    else:
+        klass.__implements__ = old, interface


=== Packages3/Interface/Mapping.py 1.5 => 1.6 ===
--- /dev/null	Fri Apr 18 06:03:49 2003
+++ Packages3/Interface/Mapping.py	Fri Apr 18 06:03:18 2003
@@ -0,0 +1,80 @@
+import Basic, Util
+
+class Mapping(Basic.Base):
+    "anything supporting __getitem__"
+
+    def __getitem__(key):
+        """Get the value for the given key
+
+        Raise a key error if the key if not in the collection.
+        """
+
+class QueryMapping(Mapping):
+
+    def has_key(key):
+        """Check whether the object has an item with the given key"""
+
+
+    def get(key, default=None):
+        """Get the value for the given key
+
+        Return the default if the key is not in the  collection.
+        """
+
+class Sized(Basic.Base):
+    "anything supporting __len"
+
+    def __len__():
+        """Return the number of items in the container"""
+
+class MutableMapping(Basic.Mutable):
+    "Has __setitem__ and __delitem__"
+
+    def __setitem__(key, value):
+        """Set the value for the given key"""
+
+    def __delitem__(key):
+        """delete the value for the given key
+
+        Raise a key error if the key if not in the collection."""
+
+class EnumerableMapping(Mapping):
+
+    def keys():
+        """Return an Sequence containing the keys in the collection
+
+        The type of the IReadSequence is not specified. It could be a
+        list or a tuple or some other type.
+        """
+
+class MinimalDictionary(QueryMapping, Sized, MutableMapping,
+                        EnumerableMapping):
+    """Provide minimal dictionary-like behavior
+    """
+
+    def values():
+        """Return a IReadSequence containing the values in the collection
+
+        The type of the IReadSequence is not specified. It could be a
+        list or a tuple or some other type.
+        """
+
+    def items():
+        """Return a IReadSequence containing the items in the collection
+
+        An item is a key-value tuple.
+
+        The type of the IReadSequence is not specified. It could be a
+        list or a tuple or some other type.
+        """
+
+
+class Sequence(Mapping):
+    "Keys must be integers in a sequence starting at 0."
+
+class Sequential(Sequence):
+    "Keys must be used in order"
+
+Util.assertTypeImplements(type(()), (Sequence, Sized, Basic.HashKey))
+Util.assertTypeImplements(type([]), (Sequence, Sized, MutableMapping))
+Util.assertTypeImplements(type({}), (Mapping, Sized, MutableMapping))


=== Packages3/Interface/Method.py 1.14 => 1.15 ===
--- /dev/null	Fri Apr 18 06:03:49 2003
+++ Packages3/Interface/Method.py	Fri Apr 18 06:03:18 2003
@@ -0,0 +1,106 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Method interfaces
+
+Revision information:
+$Id$
+"""
+import Exceptions
+from Attribute import Attribute
+
+sig_traits = ['positional', 'required', 'optional', 'varargs', 'kwargs']
+
+CO_VARARGS = 4
+CO_VARKEYWORDS = 8
+
+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.
+    #
+    #__implements__ = IMethod
+
+    interface=''
+
+    def __call__(self, *args, **kw):
+        raise Exceptions.BrokenImplementation(self.interface, self.__name__)
+
+    def getSignatureInfo(self):
+        info = {}
+        for t in sig_traits:
+            info[t] = getattr(self, t)
+
+        return info
+
+    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):
+    m=Method(func.__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
+    return m
+
+def fromMethod(meth, interface=''):
+    func = meth.im_func
+    return fromFunction(func, interface, imlevel=1)


=== Packages3/Interface/Verify.py 1.7 => 1.8 ===
--- /dev/null	Fri Apr 18 06:03:49 2003
+++ Packages3/Interface/Verify.py	Fri Apr 18 06:03:18 2003
@@ -0,0 +1,88 @@
+##############################################################################
+#
+# 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 Exceptions import BrokenImplementation, DoesNotImplement
+from Exceptions import BrokenMethodImplementation
+from types import FunctionType
+from Method import fromMethod, fromFunction
+from _object import MethodTypes
+
+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, suppress the "is implemented by" test.
+    """
+
+    if vtype is 'c':
+        tester = iface.isImplementedByInstancesOf
+    else:
+        tester = iface.isImplementedBy
+
+    if not tentative and not tester( candidate ):
+        raise DoesNotImplement(iface)
+
+    for n, d in iface.namesAndDescriptions(1):
+        if not hasattr(candidate, n):
+            raise BrokenImplementation(iface, n)
+
+        attr = getattr(candidate, n)
+        if type(attr) is FunctionType:
+            # should never get here
+            meth = fromFunction(attr, n)
+        elif type(attr) in MethodTypes:
+            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 1
+
+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"


=== Packages3/Interface/_Element.py 1.4 => 1.5 ===
--- /dev/null	Fri Apr 18 06:03:49 2003
+++ Packages3/Interface/_Element.py	Fri Apr 18 06:03:18 2003
@@ -0,0 +1,59 @@
+##############################################################################
+#
+# 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$
+"""
+
+from _object import object
+
+class Element(object):
+
+    # We can't say this yet because we don't have enough
+    # infrastructure in place.
+    #
+    #__implements__ = IElement
+
+    __tagged_values = {}
+
+    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__
+
+    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 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


=== Packages3/Interface/_Interface.py 1.6 => 1.7 ===
--- /dev/null	Fri Apr 18 06:03:49 2003
+++ Packages3/Interface/_Interface.py	Fri Apr 18 06:03:18 2003
@@ -0,0 +1,42 @@
+##############################################################################
+#
+# 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
+
+Revision information:
+$Id$
+"""
+
+from _InterfaceClass import Interface as InterfaceClass
+
+Interface = InterfaceClass("Interface")
+
+# Now we can create the interesting interfaces and wire them up:
+def wire():
+
+    from Implements import implements
+
+    from Attribute import Attribute
+    from IAttribute import IAttribute
+    implements(Attribute, IAttribute)
+
+    from Method import Method
+    from IMethod import IMethod
+    implements(Method, IMethod)
+
+    from IInterface import IInterface
+    implements(InterfaceClass, IInterface)
+
+wire()
+del wire
+del InterfaceClass


=== Packages3/Interface/_InterfaceClass.py 1.14 => 1.15 ===
--- /dev/null	Fri Apr 18 06:03:50 2003
+++ Packages3/Interface/_InterfaceClass.py	Fri Apr 18 06:03:18 2003
@@ -0,0 +1,224 @@
+##############################################################################
+#
+# 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
+
+Revision information:
+$Id$
+"""
+
+from inspect import currentframe
+import sys
+from Method import Method, fromFunction
+from Attribute import Attribute
+from types import FunctionType
+import Exceptions
+from _Element import Element
+from _object import isInstance
+
+class Interface(Element):
+    """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 attrs.has_key('__module__'):
+                __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__ = currentframe().f_back.f_globals['__name__']
+                except (AttributeError, KeyError):
+                    pass
+        self.__module__ = __module__
+
+        for b in bases:
+            if not isInstance(b, Interface):
+                raise TypeError, 'Expected base interfaces'
+        self.__bases__=bases
+
+        if attrs is None: attrs={}
+        if attrs.has_key('__doc__'):
+            if __doc__ is None: __doc__=attrs['__doc__']
+            del attrs['__doc__']
+
+        if __doc__ is not None:
+            self.__doc__=__doc__
+        else:
+            self.__doc__ = ""
+
+        Element.__init__(self, name, __doc__)
+
+        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)
+            else:
+                raise Exceptions.InvalidInterface(
+                    "Concrete attribute, %s" % k)
+
+        self.__attrs = attrs
+
+    def getBases(self):
+        return self.__bases__
+
+    def extends(self, other, strict=1):
+        """Does an interface extend another?
+        """
+        if not strict and self is other:
+            return 1
+
+        for b in self.__bases__:
+            if b == other: return 1
+            if b.extends(other): return 1
+        return 0
+
+    def isEqualOrExtendedBy(self, other):
+        """Same interface or extends?
+        """
+        if self == other:
+            return 1
+        return other.extends(self)
+
+    def isImplementedBy(self, object):
+        """Does the given object implement the interface?
+        """
+        i = getImplements(object)
+        if i is not None:
+            return visitImplements(
+                i, object, self.isEqualOrExtendedBy, self._getInterface)
+        return 0
+
+    def isImplementedByInstancesOf(self, klass):
+        """Do instances of the given class implement the interface?
+        """
+        i = getImplementsOfInstances(klass)
+        if i is not None:
+            return visitImplements(
+                i, klass, self.isEqualOrExtendedBy, self._getInterface)
+        return 0
+
+    def names(self, all=0):
+        """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 namesAndDescriptions(self, all=0):
+        """Return the attribute names and descriptions defined by the 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 not r.has_key(name):
+                    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
+
+    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
+
+    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 _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 dict.has_key(k):
+                dict[k]=v
+
+        for b in self.__bases__: b.__d(dict)
+
+    def __repr__(self):
+        name = self.__name__
+        m = self.__module__
+        if m:
+            name = '%s.%s' % (m, name)
+        return "<%s %s at %x>" % (self.__class__.__name__, name, id(self))
+
+    def __reduce__(self):
+        return self.__name__
+
+    def __hash__(self):
+        """ interface instances need to be hashable, and inheriting
+        from extensionclass makes instances unhashable unless we declare
+        a __hash__ method here"""
+        return id(self)
+
+# We import this here to deal with module dependencies.
+from Implements import getImplementsOfInstances, visitImplements, getImplements
+from Implements import instancesOfObjectImplements


=== Packages3/Interface/__init__.py 1.10 => 1.11 ===
--- /dev/null	Fri Apr 18 06:03:50 2003
+++ Packages3/Interface/__init__.py	Fri Apr 18 06:03:18 2003
@@ -0,0 +1,72 @@
+##############################################################################
+#
+# 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 a single name, 'Interface' directly. Interface
+is used to create an interface with a class statement, as in:
+
+  from Interface import Interface
+
+  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:
+
+  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, pyself.py in the package that can be used to
+create interface skeletins. Run it without arguments to get documentation.
+
+Revision information:
+$Id$
+"""
+
+from _Interface import Interface
+from Attribute import Attribute
+Base = Interface # XXX We need to stamp out Base usage


=== Packages3/Interface/_object.py 1.4 => 1.5 ===
--- /dev/null	Fri Apr 18 06:03:50 2003
+++ Packages3/Interface/_object.py	Fri Apr 18 06:03:18 2003
@@ -0,0 +1,58 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Provide a halfway believable rendition of Python 2.2's object
+
+$Id$
+"""
+
+class _x:
+    def m(self):
+        pass
+
+ClassTypes  = (type(_x), )
+MethodTypes = (type(_x.m), )
+isInstance = isinstance
+
+
+try:
+    object
+except NameError:
+    # Python 2.1
+    try:
+        from ExtensionClass import Base as object
+    except ImportError:
+        class object: pass
+else:
+    # Python 2.2
+    ClassTypes += (type, )
+    object = object
+
+
+try:
+    import ExtensionClass
+except ImportError:
+    # ExtensionClass is not present
+    pass
+else:
+    # ExtensionClass is present
+    def isInstance(ob, klass):
+        if type(type(ob)) is type(klass):
+            return isinstance(ob, klass)
+        return 0
+
+    class _x(ExtensionClass.Base):
+        def m(self): pass
+
+    ClassTypes  += (type(_x), )
+    MethodTypes += (type(_x.m), )


=== Packages3/Interface/pprint.py 1.7 => 1.8 ===
--- /dev/null	Fri Apr 18 06:03:50 2003
+++ Packages3/Interface/pprint.py	Fri Apr 18 06:03:18 2003
@@ -0,0 +1,81 @@
+""" Pretty-Print an Interface object as structured text (Yum) """
+
+import string
+
+def trim_doc_string(text):
+    """
+    Trims a doc string to make it format
+    correctly with structured text.
+    """
+    text=text.strip()
+    text=text.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, '\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 = (string.translate(text, string.maketrans("\r\n", "  "))).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)
+
+
+def interface_as_stx(I, munge=0):
+    """ Output structured text format.  Note, this will wack any existing
+    'structured' format of the text.  """
+
+    outp = "%s\n\n" % I.getName()
+    level = 1
+
+    if I.getDoc():
+        outp = outp + justify_and_indent(trim_doc_string(I.getDoc()), level) + "\n\n"
+
+    if I.getBases():
+        outp = outp + (" " * level) + "This interface extends:\n\n"
+        level = level + 1
+        for b in I.getBases():
+            item = "o %s" % b.getName()
+            outp = outp + justify_and_indent(trim_doc_string(item), level, munge) + "\n\n"
+        level = level - 1
+
+    level = level + 1
+    for name, desc in I.namesAndDescriptions():
+        if hasattr(desc, 'getSignatureRepr'):   # ugh...
+            item = "%s%s -- %s" % (desc.getName(), desc.getSignatureRepr(), desc.getDoc())
+        else:
+            item = "%s -- %s" % (desc.getName(), desc.getDoc())
+
+        outp = outp + justify_and_indent(trim_doc_string(item), level, munge)  + "\n\n"
+
+    return outp


=== Packages3/Interface/pyskel.py 1.9 => 1.10 ===
--- /dev/null	Fri Apr 18 06:03:50 2003
+++ Packages3/Interface/pyskel.py	Fri Apr 18 06:03:18 2003
@@ -0,0 +1,189 @@
+#!/usr/bin/env python
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+Generate method skeletins for intefaces.
+
+Usage: python pyskel.py dotted_name
+
+Example:
+
+    cd lib/python
+    python Interface/pyskel.py Zope.App.Security.IRoleService.IRoleService
+
+The dotted name is the module name and interface object name connected
+with a dot.
+
+Revision information: $Id$
+"""
+
+import sys, os, re
+
+sys.path.insert(0, os.getcwd())
+
+from _object import isInstance
+
+from types import ModuleType
+from Interface.Method import Method
+from Interface.Attribute import Attribute
+
+class_re = re.compile(r'\s*class\s+([a-zA-Z_][a-zA-Z0-9_]*)')
+def_re = re.compile(r'\s*def\s+([a-zA-Z_][a-zA-Z0-9_]*)')
+attr_re = re.compile(r'\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*Attribute')
+
+
+def rskel(iface, print_iface=1):
+    name = "%s.%s" % (iface.__module__, iface.__name__)
+
+    file = resolve(iface.__module__).__file__
+    if file.endswith('pyc'):
+        file = file[:-1]
+    order = guessOrder(open(file))
+    namesAndDescriptions =  getAttributesInOrder(iface, order)
+
+    if namesAndDescriptions and print_iface:
+        print
+        print "    ######################################"
+        print "    # from:", name
+
+    for aname, ades in namesAndDescriptions:
+        if isInstance(ades, Method):
+            sig = ades.getSignatureString()[1:-1]
+            if sig: sig = "self, %s" % sig
+            else:   sig = "self"
+            print
+            print "    def %s(%s):" % (aname, sig)
+            print "        'See %s'" % name
+
+        elif isInstance(ades, Attribute):
+            print
+            print "    # See %s" % name
+            print "    %s = None" %aname
+
+    for base in iface.__bases__:
+        if base.__name__ not in ('Interface',):
+            rskel(base)
+
+def skel(name):
+    iface = resolve(name)
+    class_name = iface.__name__
+    if class_name.startswith('I'):
+        class_name = class_name[1:]
+    print "from %s import %s" % (iface.__module__, iface.__name__)
+    print
+    print "class %s:" %class_name
+    print
+    print "    __implements__ = ", iface.__name__
+    print
+    print "    ############################################################"
+    print "    # Implementation methods for interface"
+    print "    #", name
+
+    rskel(iface, 0)
+
+    print
+    print "    #"
+    print "    ############################################################"
+
+
+def resolve(name, _silly=('__doc__',), _globals={}):
+    # Support for file path syntax; this way I can use TAB to search for
+    # the module.
+    if '/' in name or name.endswith('.py'):
+        # We got a relative path. Let's try to get the full one and then
+        # make a package path out of it.
+        if not name.startswith('/'):
+            cwd = os.getcwd()
+            for path in sys.path[1:]: # Yeah, we need to exclude the cwd itself
+                if path != '' and cwd.startswith(path):
+                    name = os.path.join(cwd[len(path)+1:], name)
+                    name = os.path.normpath(name)
+                    break
+
+        # get rid of the file ending :)
+        if name.endswith('.py'):
+            name = name[:-3]
+        name = name.replace('/', '.')
+
+    # Now to the regular lookup
+    if name[:1]=='.':
+        name='ZopeProducts'+name
+
+    if name[-1:] == '.':
+        name = name[:-1]
+        repeat = 1
+    else:
+        repeat = 0
+
+    names=name.split('.')
+    last=names[-1]
+    mod='.'.join(names[:-1])
+
+    while 1:
+        m=__import__(mod, _globals, _globals, _silly)
+        try:
+            a=getattr(m, last)
+        except AttributeError:
+            pass
+        else:
+            if not repeat or (type(a) is not ModuleType):
+                return a
+        mod += '.' + last
+
+
+def guessOrder(source_file):
+    order = {}  # { class name -> list of methods }
+    lines = source_file.readlines()
+    class_name = None
+    for line in lines:
+        m = class_re.match(line)
+        if m and m.groups():
+            class_name = m.groups()[0]
+        else:
+            for m in (def_re.match(line),
+                      attr_re.match(line)):
+                if m and m.groups():
+                    def_name = m.groups()[0]
+                    name_order = order.get(class_name)
+                    if name_order is None:
+                        name_order = []
+                        order[class_name] = name_order
+                    name_order.append(def_name)
+
+    return order
+
+
+def getAttributesInOrder(interface, order):
+    # order is the dictionary returned from guessOrder().
+    # interface is a metaclass-based interface object.
+    name_order = order.get(interface.__name__)
+
+    if name_order is None:
+        # Something's wrong.  Oh well.
+        return interface.__dict__.items()
+    else:
+        items = []
+        for key, value in interface.namesAndDescriptions():
+            if key in name_order:
+                items.append((name_order.index(key), key, value))
+            else:
+                items.append((99999, key, value))  # Go to end.
+        items.sort()
+        return map(lambda item: item[1:], items)
+
+
+
+if __name__ == '__main__':
+    for a in sys.argv[1:]:
+        skel(a)