[Checkins] SVN: zope.interface/trunk/ Merge of regebro-python3 branch, adding Python 3.1 compatibility\!

Lennart Regebro regebro at gmail.com
Fri Apr 9 04:16:18 EDT 2010


Log message for revision 110699:
  Merge of regebro-python3 branch, adding Python 3.1 compatibility\!

Changed:
  U   zope.interface/trunk/CHANGES.txt
  A   zope.interface/trunk/build_ext_2.py
  A   zope.interface/trunk/build_ext_3.py
  U   zope.interface/trunk/setup.py
  U   zope.interface/trunk/src/zope/interface/README.ru.txt
  U   zope.interface/trunk/src/zope/interface/README.txt
  U   zope.interface/trunk/src/zope/interface/__init__.py
  U   zope.interface/trunk/src/zope/interface/_zope_interface_coptimizations.c
  U   zope.interface/trunk/src/zope/interface/adapter.py
  U   zope.interface/trunk/src/zope/interface/adapter.ru.txt
  U   zope.interface/trunk/src/zope/interface/adapter.txt
  U   zope.interface/trunk/src/zope/interface/advice.py
  U   zope.interface/trunk/src/zope/interface/declarations.py
  U   zope.interface/trunk/src/zope/interface/interface.py
  U   zope.interface/trunk/src/zope/interface/interfaces.py
  U   zope.interface/trunk/src/zope/interface/tests/__init__.py
  U   zope.interface/trunk/src/zope/interface/tests/odd.py
  U   zope.interface/trunk/src/zope/interface/tests/test_advice.py
  U   zope.interface/trunk/src/zope/interface/tests/test_interface.py
  U   zope.interface/trunk/src/zope/interface/tests/test_odd_declarations.py
  U   zope.interface/trunk/src/zope/interface/tests/test_sorting.py
  U   zope.interface/trunk/src/zope/interface/verify.py
  U   zope.interface/trunk/src/zope/interface/verify.txt

-=-
Modified: zope.interface/trunk/CHANGES.txt
===================================================================
--- zope.interface/trunk/CHANGES.txt	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/CHANGES.txt	2010-04-09 08:16:17 UTC (rev 110699)
@@ -2,6 +2,37 @@
 *******
 
 ==================
+3.6.0 (unreleased)
+==================
+
+- Added support for Python 3.1. Contributors:
+    Lennart Regebro
+    Martin v Löwis
+    Thomas Lotze
+    Wolfgang Schnerring
+
+  The 3.1 support is completely backwards compatible. However, the implements
+  syntax used under Python 2.X does not work under 3.X, since it depends on
+  how metaclasses are implemented and this has changed. Instead it now supports
+  a decorator syntax (also under Python 2.X):
+
+    class Foo:
+        implements(IFoo)
+        ...
+
+  can now also be written
+
+    @implementor(IFoo):
+    class Foo:
+        ...
+
+  There are 2to3 fixers available to do this change automatically in the
+  zope.fixers package.
+
+- Python 2.3 is no longer supported.
+
+
+==================
 3.5.4 (2009-12-23)
 ==================
 
@@ -9,6 +40,7 @@
   has been deprecated.
 
 
+==================
 3.5.3 (2009-12-08)
 ==================
 

Copied: zope.interface/trunk/build_ext_2.py (from rev 110698, zope.interface/branches/regebro-python3/build_ext_2.py)
===================================================================
--- zope.interface/trunk/build_ext_2.py	                        (rev 0)
+++ zope.interface/trunk/build_ext_2.py	2010-04-09 08:16:17 UTC (rev 110699)
@@ -0,0 +1,38 @@
+import sys
+from distutils.errors import (CCompilerError, DistutilsExecError, 
+                              DistutilsPlatformError)
+try:
+    from setuptools.command.build_ext import build_ext
+except ImportError:
+    from distutils.command.build_ext import build_ext
+    
+
+class optional_build_ext(build_ext):
+    """This class subclasses build_ext and allows
+       the building of C extensions to fail.
+    """
+    def run(self):
+        try:
+            build_ext.run(self)
+        
+        except DistutilsPlatformError, e:
+            self._unavailable(e)
+
+    def build_extension(self, ext):
+        try:
+            build_ext.build_extension(self, ext)
+        
+        except (CCompilerError, DistutilsExecError), e:
+            self._unavailable(e)
+
+    def _unavailable(self, e):
+        print >> sys.stderr, '*' * 80
+        print >> sys.stderr, """WARNING:
+
+        An optional code optimization (C extension) could not be compiled.
+
+        Optimizations for this package will not be available!"""
+        print >> sys.stderr
+        print >> sys.stderr, e
+        print >> sys.stderr, '*' * 80
+        
\ No newline at end of file

Copied: zope.interface/trunk/build_ext_3.py (from rev 110698, zope.interface/branches/regebro-python3/build_ext_3.py)
===================================================================
--- zope.interface/trunk/build_ext_3.py	                        (rev 0)
+++ zope.interface/trunk/build_ext_3.py	2010-04-09 08:16:17 UTC (rev 110699)
@@ -0,0 +1,40 @@
+import os
+import sys
+from distutils.errors import (CCompilerError, DistutilsExecError, 
+                              DistutilsPlatformError)
+try:
+    from setuptools.command.build_ext import build_ext
+    from pkg_resources import (normalize_path, working_set, 
+                               add_activation_listener, require)
+except ImportError:
+    from distutils.command.build_ext import build_ext
+    
+
+class optional_build_ext(build_ext):
+    """This class subclasses build_ext and allows
+       the building of C extensions to fail.
+    """
+    def run(self):
+        try:
+            build_ext.run(self)
+        
+        except DistutilsPlatformError as e:
+            self._unavailable(e)
+
+    def build_extension(self, ext):
+        try:
+            build_ext.build_extension(self, ext)
+        
+        except (CCompilerError, DistutilsExecError) as e:
+            self._unavailable(e)
+
+    def _unavailable(self, e):
+        print('*' * 80, file=sys.stderr)
+        print("""WARNING:
+
+        An optional code optimization (C extension) could not be compiled.
+
+        Optimizations for this package will not be available!""", file=sys.stderr)
+        print(file=sys.stderr)
+        print(e, file=sys.stderr)
+        print('*' * 80, file=sys.stderr)

Modified: zope.interface/trunk/setup.py
===================================================================
--- zope.interface/trunk/setup.py	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/setup.py	2010-04-09 08:16:17 UTC (rev 110699)
@@ -23,17 +23,15 @@
 
 import os, sys
 
-from distutils.errors import (CCompilerError, DistutilsExecError, 
-                              DistutilsPlatformError)
+from distutils.errors import CCompilerError, DistutilsExecError, \
+                              DistutilsPlatformError
 
 try:
     from setuptools import setup, Extension, Feature
-    from setuptools.command.build_ext import build_ext
-except ImportError, e:
+except ImportError:
     # do we need to support plain distutils for building when even
     # the package itself requires setuptools for installing?
     from distutils.core import setup, Extension
-    from distutils.command.build_ext import build_ext
 
     if sys.version_info[:2] >= (2, 4):
         extra = dict(
@@ -60,7 +58,7 @@
         namespace_packages=["zope"],
         include_package_data = True,
         zip_safe = False,
-        tests_require = ['zope.testing'],
+        tests_require = [],
         install_requires = ['setuptools'],
         extras_require={'docs': ['z3c.recipe.sphinxdoc']},
         features = {'codeoptimization': codeoptimization}
@@ -87,40 +85,29 @@
         '********\n'
         )
 
+try: # Zope 3 setuptools versions
+    from build_ext_3 import optional_build_ext
+    # This is Python 3. Setuptools is now required, and so is zope.fixers.
+    extra['install_requires'] = ['setuptools']
+    extra['setup_requires'] = ['zope.fixers']
+    extra['use_2to3'] = True
+    extra['convert_2to3_doctests'] = [
+        'src/zope/interface/README.ru.txt',
+        'src/zope/interface/README.txt',
+        'src/zope/interface/adapter.ru.txt',
+        'src/zope/interface/adapter.txt',
+        'src/zope/interface/human.ru.txt',
+        'src/zope/interface/human.txt',
+        'src/zope/interface/index.txt',
+        'src/zope/interface/verify.txt',
+        ]
+    extra['use_2to3_fixers'] = ['zope.fixers']
 
-class optional_build_ext(build_ext):
-    """This class subclasses build_ext and allows
-       the building of C extensions to fail.
-    """
-    def run(self):
-        try:
-            build_ext.run(self)
-        
-        except DistutilsPlatformError, e:
-            self._unavailable(e)
-
-    def build_extension(self, ext):
-       try:
-           build_ext.build_extension(self, ext)
-        
-       except (CCompilerError, DistutilsExecError), e:
-           self._unavailable(e)
-
-    def _unavailable(self, e):
-        print >> sys.stderr, '*' * 80
-        print >> sys.stderr, """WARNING:
-
-        An optional code optimization (C extension) could not be compiled.
-
-        Optimizations for this package will not be available!"""
-        print >> sys.stderr
-        print >> sys.stderr, e
-        print >> sys.stderr, '*' * 80
+except (ImportError, SyntaxError):
+    from build_ext_2 import optional_build_ext
     
-
-
 setup(name='zope.interface',
-      version = '3.5.4',
+      version = '3.6.0dev',
       url='http://pypi.python.org/pypi/zope.interface',
       license='ZPL 2.1',
       description='Interfaces for Python',
@@ -128,7 +115,9 @@
       author_email='zope-dev at zope.org',
       long_description=long_description,
 
-      packages = ['zope', 'zope.interface'],
+      packages = ['zope', 'zope.interface', 'zope.interface.tests'],
       package_dir = {'': 'src'},
-      cmdclass = {'build_ext': optional_build_ext},
+      cmdclass = {'build_ext': optional_build_ext,
+                  },
+      test_suite = 'zope.interface.tests',
       **extra)

Modified: zope.interface/trunk/src/zope/interface/README.ru.txt
===================================================================
--- zope.interface/trunk/src/zope/interface/README.ru.txt	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/README.ru.txt	2010-04-09 08:16:17 UTC (rev 110699)
@@ -231,16 +231,19 @@
 Вызывающая сторона не должна предполагать, что всегда будет создаваться
 новый объект.
 
-Также надо отметить, что как минимум сейчас implementer не может использоваться
-для классов::
+XXX: Double check and update these version numbers, and translate to russian:
 
-  >>> zope.interface.implementer(IFoo)(Foo)
-  ... # doctest: +NORMALIZE_WHITESPACE
-  Traceback (most recent call last):
-    ...
-  TypeError: Can't use implementer with classes.
-  Use one of the class-declaration functions instead.
+In zope.interface 3.5.1 and lower, the implementor decorator can not
+be used for classes, but in 3.5.2 and higher it can:
 
+  >>> Foo = zope.interface.implementer(IFoo)(Foo)
+  >>> list(zope.interface.providedBy(Foo()))
+  [<InterfaceClass __main__.IFoo>]
+  
+Note that class decorators using the @implementor(IFoo) syntax are only 
+supported in Python 2.6 and later.
+
+
 Объявление предоставляемых интерфейсов
 --------------------------------------
 
@@ -545,12 +548,12 @@
 к спецификациям. Объявления фактически расширяют интерфейсы которые они
 объявляют::
 
-  >>> class Baz:
+  >>> class Baz(object):
   ...     zope.interface.implements(IBaz)
 
   >>> baz_implements = zope.interface.implementedBy(Baz)
   >>> baz_implements.__bases__
-  (<InterfaceClass __main__.IBaz>,)
+  (<InterfaceClass __main__.IBaz>, <implementedBy ...object>)
 
   >>> baz_implements.extends(IFoo)
   True
@@ -568,7 +571,8 @@
    <InterfaceClass __main__.IBaz>,
    <InterfaceClass __main__.IFoo>,
    <InterfaceClass __main__.IBlat>,
-   <InterfaceClass zope.interface.Interface>)
+   <InterfaceClass zope.interface.Interface>,
+   <implementedBy ...object>)
 
 Помеченные значения
 ===================
@@ -657,11 +661,13 @@
 будет выкинуто единственное исключение `Invalid` со списком исключений
 как аргументом::
 
+  >>> from zope.interface.exceptions import Invalid
   >>> errors = []
-  >>> IRange.validateInvariants(Range(2,1), errors)
-  Traceback (most recent call last):
-  ...
-  Invalid: [RangeError(Range(2, 1))]
+  >>> try:
+  ...     IRange.validateInvariants(Range(2,1), errors)
+  ... except Invalid, e:
+  ...     str(e)
+  '[RangeError(Range(2, 1))]'
 
 И список будет заполнен индивидуальными исключениями::
 

Modified: zope.interface/trunk/src/zope/interface/README.txt
===================================================================
--- zope.interface/trunk/src/zope/interface/README.txt	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/README.txt	2010-04-09 08:16:17 UTC (rev 110699)
@@ -231,16 +231,33 @@
 Note that the implementer decorator may modify it's argument. Callers
 should not assume that a new object is created.
 
-Also note that, at least for now, implementer can't be used with
-classes::
+Using implementer also works on callable objects. This is used by
+zope.formlib, as an example.
 
-  >>> zope.interface.implementer(IFoo)(Foo)
-  ... # doctest: +NORMALIZE_WHITESPACE
-  Traceback (most recent call last):
-    ...
-  TypeError: Can't use implementer with classes.
-  Use one of the class-declaration functions instead.
+  >>> class yfactory:
+  ...     def __call__(self, y):
+  ...         foo = Foo()
+  ...         foo.y = y
+  ...         return foo
+  >>> yfoo = yfactory()
+  >>> yfoo = zope.interface.implementer(IFoo)(yfoo)
 
+  >>> list(zope.interface.implementedBy(yfoo))
+  [<InterfaceClass __main__.IFoo>]
+
+XXX: Double check and update these version numbers:
+
+In zope.interface 3.5.2 and lower, the implementor decorator can not
+be used for classes, but in 3.6.0 and higher it can:
+
+  >>> Foo = zope.interface.implementer(IFoo)(Foo)
+  >>> list(zope.interface.providedBy(Foo()))
+  [<InterfaceClass __main__.IFoo>]
+  
+Note that class decorators using the @implementor(IFoo) syntax are only 
+supported in Python 2.6 and later.
+
+
 Declaring provided interfaces
 -----------------------------
 
@@ -547,12 +564,12 @@
 declarations and specifications.  Declarations actually extend the
 interfaces that they declare::
 
-  >>> class Baz:
+  >>> class Baz(object):
   ...     zope.interface.implements(IBaz)
 
   >>> baz_implements = zope.interface.implementedBy(Baz)
   >>> baz_implements.__bases__
-  (<InterfaceClass __main__.IBaz>,)
+  (<InterfaceClass __main__.IBaz>, <implementedBy ...object>)
 
   >>> baz_implements.extends(IFoo)
   True
@@ -570,7 +587,8 @@
    <InterfaceClass __main__.IBaz>,
    <InterfaceClass __main__.IFoo>,
    <InterfaceClass __main__.IBlat>,
-   <InterfaceClass zope.interface.Interface>)
+   <InterfaceClass zope.interface.Interface>,
+   <implementedBy ...object>)
 
 
 Tagged Values
@@ -659,12 +677,14 @@
 then a single `Invalid` exception will be raised with the list of
 exceptions as it's argument::
 
+  >>> from zope.interface.exceptions import Invalid
   >>> errors = []
-  >>> IRange.validateInvariants(Range(2,1), errors)
-  Traceback (most recent call last):
-  ...
-  Invalid: [RangeError(Range(2, 1))]
-
+  >>> try:
+  ...     IRange.validateInvariants(Range(2,1), errors)
+  ... except Invalid, e:
+  ...     str(e)
+  '[RangeError(Range(2, 1))]'
+  
 And the list will be filled with the individual exceptions::
 
   >>> errors

Modified: zope.interface/trunk/src/zope/interface/__init__.py
===================================================================
--- zope.interface/trunk/src/zope/interface/__init__.py	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/__init__.py	2010-04-09 08:16:17 UTC (rev 110699)
@@ -63,7 +63,8 @@
 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 alsoProvides, implementer
+from zope.interface.declarations import alsoProvides, provider
+from zope.interface.declarations import implementer, implementer_only
 from zope.interface.declarations import implements, implementsOnly
 from zope.interface.declarations import classProvides, moduleProvides
 from zope.interface.declarations import noLongerProvides, Declaration

Modified: zope.interface/trunk/src/zope/interface/_zope_interface_coptimizations.c
===================================================================
--- zope.interface/trunk/src/zope/interface/_zope_interface_coptimizations.c	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/_zope_interface_coptimizations.c	2010-04-09 08:16:17 UTC (rev 110699)
@@ -18,6 +18,12 @@
 #define TYPE(O) ((PyTypeObject*)(O))
 #define OBJECT(O) ((PyObject*)(O))
 #define CLASSIC(O) ((PyClassObject*)(O))
+#ifndef PyVarObject_HEAD_INIT
+#define PyVarObject_HEAD_INIT(a, b) PyObject_HEAD_INIT(a) b,
+#endif
+#ifndef Py_TYPE
+#define Py_TYPE(o) ((o)->ob_type)
+#endif
 
 static PyObject *str__dict__, *str__implemented__, *strextends;
 static PyObject *BuiltinImplementationSpecifications, *str__provides__;
@@ -366,8 +372,7 @@
 };
 
 static PyTypeObject SpecType = {
-	PyObject_HEAD_INIT(NULL)
-	/* ob_size           */ 0,
+	PyVarObject_HEAD_INIT(NULL, 0)
 	/* tp_name           */ "_interface_coptimizations."
                                 "SpecificationBase",
 	/* tp_basicsize      */ 0,
@@ -376,7 +381,7 @@
 	/* tp_print          */ (printfunc)0,
 	/* tp_getattr        */ (getattrfunc)0,
 	/* tp_setattr        */ (setattrfunc)0,
-	/* tp_compare        */ (cmpfunc)0,
+	/* tp_compare        */ 0,
 	/* tp_repr           */ (reprfunc)0,
 	/* tp_as_number      */ 0,
 	/* tp_as_sequence    */ 0,
@@ -414,8 +419,7 @@
 }
 
 static PyTypeObject OSDType = {
-	PyObject_HEAD_INIT(NULL)
-	/* ob_size           */ 0,
+	PyVarObject_HEAD_INIT(NULL, 0)
 	/* tp_name           */ "_interface_coptimizations."
                                 "ObjectSpecificationDescriptor",
 	/* tp_basicsize      */ 0,
@@ -424,7 +428,7 @@
 	/* tp_print          */ (printfunc)0,
 	/* tp_getattr        */ (getattrfunc)0,
 	/* tp_setattr        */ (setattrfunc)0,
-	/* tp_compare        */ (cmpfunc)0,
+	/* tp_compare        */ 0,
 	/* tp_repr           */ (reprfunc)0,
 	/* tp_as_number      */ 0,
 	/* tp_as_sequence    */ 0,
@@ -479,8 +483,7 @@
 }
 
 static PyTypeObject CPBType = {
-	PyObject_HEAD_INIT(NULL)
-	/* ob_size           */ 0,
+	PyVarObject_HEAD_INIT(NULL, 0)
 	/* tp_name           */ "_interface_coptimizations."
                                 "ClassProvidesBase",
 	/* tp_basicsize      */ 0,
@@ -489,7 +492,7 @@
 	/* tp_print          */ (printfunc)0,
 	/* tp_getattr        */ (getattrfunc)0,
 	/* tp_setattr        */ (setattrfunc)0,
-	/* tp_compare        */ (cmpfunc)0,
+	/* tp_compare        */ 0,
 	/* tp_repr           */ (reprfunc)0,
 	/* tp_as_number      */ 0,
 	/* tp_as_sequence    */ 0,
@@ -670,8 +673,7 @@
 }
 
 static PyTypeObject InterfaceBase = {
-	PyObject_HEAD_INIT(NULL)
-	/* ob_size           */ 0,
+	PyVarObject_HEAD_INIT(NULL, 0)
 	/* tp_name           */ "_zope_interface_coptimizations."
                                 "InterfaceBase",
 	/* tp_basicsize      */ 0,
@@ -680,7 +682,7 @@
 	/* tp_print          */ (printfunc)0,
 	/* tp_getattr        */ (getattrfunc)0,
 	/* tp_setattr        */ (setattrfunc)0,
-	/* tp_compare        */ (cmpfunc)0,
+	/* tp_compare        */ 0,
 	/* tp_repr           */ (reprfunc)0,
 	/* tp_as_number      */ 0,
 	/* tp_as_sequence    */ 0,
@@ -764,7 +766,7 @@
 lookup_dealloc(lookup *self)
 {
   lookup_clear(self);
-  self->ob_type->tp_free((PyObject*)self);
+  Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 /*
@@ -1222,8 +1224,7 @@
 };
 
 static PyTypeObject LookupBase = {
-	PyObject_HEAD_INIT(NULL)
-	/* ob_size           */ 0,
+	PyVarObject_HEAD_INIT(NULL, 0)
 	/* tp_name           */ "_zope_interface_coptimizations."
                                 "LookupBase",
 	/* tp_basicsize      */ sizeof(lookup),
@@ -1232,7 +1233,7 @@
 	/* tp_print          */ (printfunc)0,
 	/* tp_getattr        */ (getattrfunc)0,
 	/* tp_setattr        */ (setattrfunc)0,
-	/* tp_compare        */ (cmpfunc)0,
+	/* tp_compare        */ 0,
 	/* tp_repr           */ (reprfunc)0,
 	/* tp_as_number      */ 0,
 	/* tp_as_sequence    */ 0,
@@ -1293,7 +1294,7 @@
 verifying_dealloc(verify *self)
 {
   verifying_clear(self);
-  self->ob_type->tp_free((PyObject*)self);
+  Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 /*  
@@ -1383,9 +1384,10 @@
       if (generations == NULL)
         return -1;
 
-      changed = PyObject_Compare(self->_verify_generations, generations);
+      changed = PyObject_RichCompareBool(self->_verify_generations, 
+					 generations, Py_NE);
       Py_DECREF(generations);
-      if (PyErr_Occurred())
+      if (changed == -1)
         return -1;
       
       if (changed == 0)
@@ -1509,8 +1511,7 @@
 };
 
 static PyTypeObject VerifyingBase = {
-	PyObject_HEAD_INIT(NULL)
-	/* ob_size           */ 0,
+	PyVarObject_HEAD_INIT(NULL, 0)
 	/* tp_name           */ "_zope_interface_coptimizations."
                                 "VerifyingBase",
 	/* tp_basicsize      */ sizeof(verify),
@@ -1519,7 +1520,7 @@
 	/* tp_print          */ (printfunc)0,
 	/* tp_getattr        */ (getattrfunc)0,
 	/* tp_setattr        */ (setattrfunc)0,
-	/* tp_compare        */ (cmpfunc)0,
+	/* tp_compare        */ 0,
 	/* tp_repr           */ (reprfunc)0,
 	/* tp_as_number      */ 0,
 	/* tp_as_sequence    */ 0,
@@ -1563,16 +1564,38 @@
   {NULL,	 (PyCFunction)NULL, 0, NULL}		/* sentinel */
 };
 
+static char module_doc[] = "C optimizations for zope.interface\n\n"
+  "$Id$";
+
+#if  PY_MAJOR_VERSION >= 3
+static struct PyModuleDef _zic_module = {
+	PyModuleDef_HEAD_INIT,
+	"_zope_interface_coptimizations",
+	module_doc,
+	-1,
+	m_methods,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+#endif
+
 #ifndef PyMODINIT_FUNC	/* declarations for DLL import/export */
 #define PyMODINIT_FUNC void
 #endif
-PyMODINIT_FUNC
-init_zope_interface_coptimizations(void)
+static PyObject *
+init(void)
 {
   PyObject *m;
 
+#if  PY_MAJOR_VERSION < 3
 #define DEFINE_STRING(S) \
   if(! (str ## S = PyString_FromString(# S))) return
+#else
+#define DEFINE_STRING(S) \
+  if(! (str ## S = PyUnicode_FromString(# S))) return NULL
+#endif
 
   DEFINE_STRING(__dict__);
   DEFINE_STRING(__implemented__);
@@ -1595,53 +1618,70 @@
 #undef DEFINE_STRING
   adapter_hooks = PyList_New(0);
   if (adapter_hooks == NULL)
-    return;
+    return NULL;
         
   /* Initialize types: */
   SpecType.tp_new = PyBaseObject_Type.tp_new;
   if (PyType_Ready(&SpecType) < 0)
-    return;
+    return NULL;
   OSDType.tp_new = PyBaseObject_Type.tp_new;
   if (PyType_Ready(&OSDType) < 0)
-    return;
+    return NULL;
   CPBType.tp_new = PyBaseObject_Type.tp_new;
   if (PyType_Ready(&CPBType) < 0)
-    return;
+    return NULL;
 
   InterfaceBase.tp_new = PyBaseObject_Type.tp_new;
   if (PyType_Ready(&InterfaceBase) < 0)
-    return;
+    return NULL;
 
   LookupBase.tp_new = PyBaseObject_Type.tp_new;
   if (PyType_Ready(&LookupBase) < 0)
-    return;
+    return NULL;
 
   VerifyingBase.tp_new = PyBaseObject_Type.tp_new;
   if (PyType_Ready(&VerifyingBase) < 0)
-    return;
+    return NULL;
 
-  
+  #if PY_MAJOR_VERSION < 3
   /* Create the module and add the functions */
   m = Py_InitModule3("_zope_interface_coptimizations", m_methods,
                      "C optimizations for zope.interface\n\n"
-                     "$Id$");  
+                     "$Id$");
+  #else
+  m = PyModule_Create(&_zic_module);
+  #endif
   if (m == NULL)
-    return;
-  
+    return NULL;
+
   /* Add types: */
   if (PyModule_AddObject(m, "SpecificationBase", OBJECT(&SpecType)) < 0)
-    return;
+    return NULL;
   if (PyModule_AddObject(m, "ObjectSpecificationDescriptor", 
                          (PyObject *)&OSDType) < 0)
-    return;
+    return NULL;
   if (PyModule_AddObject(m, "ClassProvidesBase", OBJECT(&CPBType)) < 0)
-    return;
+    return NULL;
   if (PyModule_AddObject(m, "InterfaceBase", OBJECT(&InterfaceBase)) < 0)
-    return;
+    return NULL;
   if (PyModule_AddObject(m, "LookupBase", OBJECT(&LookupBase)) < 0)
-    return;
+    return NULL;
   if (PyModule_AddObject(m, "VerifyingBase", OBJECT(&VerifyingBase)) < 0)
-    return;
+    return NULL;
   if (PyModule_AddObject(m, "adapter_hooks", adapter_hooks) < 0)
-    return;
+    return NULL;
+  return m;
 }
+
+#if PY_MAJOR_VERSION < 3
+PyMODINIT_FUNC
+init_zope_interface_coptimizations(void)
+{
+  init();
+}
+#else
+PyInit__zope_interface_coptimizations(void)
+{
+  return init();
+}
+#endif

Modified: zope.interface/trunk/src/zope/interface/adapter.py
===================================================================
--- zope.interface/trunk/src/zope/interface/adapter.py	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/adapter.py	2010-04-09 08:16:17 UTC (rev 110699)
@@ -33,6 +33,10 @@
 
     def __init__(self, bases=()):
 
+        # The comments here could be improved. Possibly this bit needs
+        # explaining in a separate document, as the comments here can
+        # be quite confusing. /regebro
+
         # {order -> {required -> {provided -> {name -> value}}}}
         # Here "order" is actually an index in a list, "required" and
         # "provided" are interfaces, and "required" is really a nested
@@ -41,6 +45,7 @@
         #   {provided -> {name -> value}}
         # but for order == 2 (that is, self._adapters[2]), we have:
         #   {r1 -> {r2 -> {provided -> {name -> value}}}}
+        #
         self._adapters = []
 
         # {order -> {required -> {provided -> {name -> [value]}}}}
@@ -70,6 +75,7 @@
         # Setting the bases causes the registries described above
         # to be initialized (self._setBases -> self.changed ->
         # self._v_lookup.changed).
+
         self.__bases__ = bases
 
     def _setBases(self, bases):
@@ -153,6 +159,8 @@
 
         # Keep track of how we got to `components`:
         lookups = []
+        # Keep track of how we got to `components`:
+        lookups = []
         for k in key:
             d = components.get(k)
             if d is None:
@@ -228,6 +236,8 @@
 
         # Keep track of how we got to `components`:
         lookups = []
+        # Keep track of how we got to `components`:
+        lookups = []
         for k in key:
             d = components.get(k)
             if d is None:

Modified: zope.interface/trunk/src/zope/interface/adapter.ru.txt
===================================================================
--- zope.interface/trunk/src/zope/interface/adapter.ru.txt	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/adapter.ru.txt	2010-04-09 08:16:17 UTC (rev 110699)
@@ -384,24 +384,21 @@
 
   >>> adapters = list(registry.lookupAll([IR1], IP1))
   >>> adapters.sort()
-  >>> adapters
-  [(u'', 11), (u'bob', "Bob's 12")]
+  >>> assert adapters == [(u'', 11), (u'bob', "Bob's 12")]
 
 Это работает также и для мульти-адаптеров::
 
   >>> 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')]
+  >>> assert adapters == [(u'', '1q22'), (u'bob', '1q2 for bob')]
 
 И даже для нулевых адаптеров::
 
   >>> registry.register([], IP2, 'bob', 3)
   >>> adapters = list(registry.lookupAll([], IP1))
   >>> adapters.sort()
-  >>> adapters
-  [(u'', 2), (u'bob', 3)]
+  >>> assert adapters == [(u'', 2), (u'bob', 3)]
 
 Подписки
 ========

Modified: zope.interface/trunk/src/zope/interface/adapter.txt
===================================================================
--- zope.interface/trunk/src/zope/interface/adapter.txt	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/adapter.txt	2010-04-09 08:16:17 UTC (rev 110699)
@@ -386,24 +386,21 @@
 
   >>> adapters = list(registry.lookupAll([IR1], IP1))
   >>> adapters.sort()
-  >>> adapters
-  [(u'', 11), (u'bob', "Bob's 12")]
+  >>> assert 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')]
+  >>> assert 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)]
+  >>> assert adapters == [(u'', 2), (u'bob', 3)]
 
 Subscriptions
 =============

Modified: zope.interface/trunk/src/zope/interface/advice.py
===================================================================
--- zope.interface/trunk/src/zope/interface/advice.py	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/advice.py	2010-04-09 08:16:17 UTC (rev 110699)
@@ -27,7 +27,13 @@
 $Id$
 """
 
-from types import ClassType, FunctionType
+from types import FunctionType
+try:
+    from types import ClassType
+    __python3 = False
+except ImportError:
+    __python3 = True
+    
 import sys
 
 def getFrameInfo(frame):
@@ -102,7 +108,10 @@
     #    )
 
     previousMetaclass = caller_locals.get('__metaclass__')
-    defaultMetaclass  = caller_globals.get('__metaclass__', ClassType)
+    if __python3:
+        defaultMetaclass  = caller_globals.get('__metaclass__', type)
+    else:
+        defaultMetaclass  = caller_globals.get('__metaclass__', ClassType)
 
 
     def advise(name, bases, cdict):
@@ -111,11 +120,11 @@
             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
+            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,
@@ -162,6 +171,7 @@
 
     if not candidates:
         # they're all "classic" classes
+        assert(not __python3) # This should not happen under Python 3
         return ClassType
 
     elif len(candidates)>1:
@@ -175,7 +185,8 @@
 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]
+    if not __python3:
+        classes = [c for c in classes if c is not ClassType]
     candidates = []
 
     for m in classes:

Modified: zope.interface/trunk/src/zope/interface/declarations.py
===================================================================
--- zope.interface/trunk/src/zope/interface/declarations.py	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/declarations.py	2010-04-09 08:16:17 UTC (rev 110699)
@@ -33,8 +33,7 @@
 from zope.interface.interface import InterfaceClass, Specification
 from zope.interface.interface import SpecificationBase
 from ro import mergeOrderings, ro
-import exceptions
-from types import ClassType, ModuleType
+from types import ModuleType, MethodType, FunctionType
 from zope.interface.advice import addClassAdvisor
 
 # Registry of class-implementation specifications
@@ -97,12 +96,8 @@
           >>> spec = Declaration(I2, I3)
           >>> spec = Declaration(I4, spec)
           >>> i = iter(spec)
-          >>> i.next().getName()
-          'I4'
-          >>> i.next().getName()
-          'I2'
-          >>> i.next().getName()
-          'I3'
+          >>> [x.getName() for x in i]
+          ['I4', 'I2', 'I3']
           >>> list(i)
           []
         """
@@ -125,16 +120,8 @@
           >>> spec = Declaration(I2, I3)
           >>> spec = Declaration(I4, spec)
           >>> i = spec.flattened()
-          >>> i.next().getName()
-          'I4'
-          >>> i.next().getName()
-          'I2'
-          >>> i.next().getName()
-          'I1'
-          >>> i.next().getName()
-          'I3'
-          >>> i.next().getName()
-          'Interface'
+          >>> [x.getName() for x in i]
+          ['I4', 'I2', 'I1', 'I3', 'Interface']
           >>> list(i)
           []
 
@@ -475,7 +462,7 @@
             b = implementedBy(c)
             if b not in seen:
                 seen[b] = 1
-                bases.append(b)
+                bases.append(b)            
 
     spec.__bases__ = tuple(bases)
 
@@ -493,9 +480,9 @@
 
     def __call__(self, ob):
         if isinstance(ob, DescriptorAwareMetaClasses):
-            raise TypeError("Can't use implementer with classes.  Use one of "
-                            "the class-declaration functions instead."
-                            )
+            classImplements(ob, *self.interfaces)
+            return ob            
+        
         spec = Implements(*self.interfaces)
         try:
             ob.__implemented__ = spec
@@ -503,6 +490,23 @@
             raise TypeError("Can't declare implements", ob)
         return ob
 
+class implementer_only:
+
+    def __init__(self, *interfaces):
+        self.interfaces = interfaces
+
+    def __call__(self, ob):
+        if isinstance(ob, (FunctionType, MethodType)):
+            # XXX Does this decorator make sense for anything but classes?
+            # I don't think so. There can be no inheritance of interfaces
+            # on a method pr function....
+            raise ValueError('The implementor_only decorator is not '
+                             'supported for methods or functions.')
+        else:
+            # Assume it's a class:
+            classImplementsOnly(ob, *self.interfaces)
+            return ob            
+        
 def _implements(name, interfaces, classImplements):
     frame = sys._getframe(2)
     locals = frame.f_locals
@@ -558,10 +562,10 @@
         ...
         >>> class IC(Interface): pass
         ...
-        >>> class A(object): implements(IA1, IA2)
-        ...
-        >>> class B(object): implements(IB)
-        ...
+        >>> class A(object):
+        ...     implements(IA1, IA2)
+        >>> class B(object):
+        ...     implements(IB)
 
         >>> class C(A, B):
         ...    implements(IC)
@@ -615,10 +619,10 @@
         ...
         >>> class IC(Interface): pass
         ...
-        >>> class A(object): implements(IA1, IA2)
-        ...
-        >>> class B(object): implements(IB)
-        ...
+        >>> class A(object):
+        ...     implements(IA1, IA2)
+        >>> class B(object):
+        ...     implements(IB)
 
         >>> class C(A, B):
         ...    implementsOnly(IC)
@@ -756,8 +760,12 @@
     return spec
 Provides.__safe_for_unpickling__ = True
 
-
-DescriptorAwareMetaClasses = ClassType, type
+try:
+    from types import ClassType
+    DescriptorAwareMetaClasses = ClassType, type
+except ImportError: # Python 3
+    DescriptorAwareMetaClasses = (type,)
+    
 def directlyProvides(object, *interfaces):
     """Declare interfaces declared directly for an object
 
@@ -782,10 +790,10 @@
         ...
         >>> class IC(Interface): pass
         ...
-        >>> class A(object): implements(IA1, IA2)
-        ...
-        >>> class B(object): implements(IB)
-        ...
+        >>> class A(object):
+        ...     implements(IA1, IA2)
+        >>> class B(object):
+        ...     implements(IB)
 
         >>> class C(A, B):
         ...    implements(IC)
@@ -886,10 +894,10 @@
       ...
       >>> class IC(Interface): pass
       ...
-      >>> class A(object): implements(IA1, IA2)
-      ...
-      >>> class B(object): implements(IB)
-      ...
+      >>> class A(object):
+      ...     implements(IA1, IA2)
+      >>> class B(object):
+      ...     implements(IB)
 
       >>> class C(A, B):
       ...    implements(IC)
@@ -1106,13 +1114,6 @@
         >>> [i.getName() for i in C().__providedBy__]
         ['IFoo']
 
-      If classProvides is called outside of a class definition, it fails.
-
-        >>> classProvides(IFooFactory)
-        Traceback (most recent call last):
-        ...
-        TypeError: classProvides can be used only from a class definition.
-
       """
     frame = sys._getframe(1)
     locals = frame.f_locals
@@ -1135,6 +1136,16 @@
     directlyProvides(cls, *interfaces)
     return cls
 
+class provider:
+    """Class decorator version of classProvides"""
+
+    def __init__(self, *interfaces):
+        self.interfaces = interfaces
+
+    def __call__(self, ob):
+        directlyProvides(ob, *self.interfaces)
+        return ob            
+
 def moduleProvides(*interfaces):
     """Declare interfaces provided by a module
 
@@ -1197,12 +1208,12 @@
       ...
       >>> class I5(Interface): pass
       ...
-      >>> class A(object): implements(I1)
-      ...
+      >>> class A(object):
+      ...     implements(I1)
       >>> class B(object): __implemented__ = I2
       ...
-      >>> class C(A, B): implements(I31)
-      ...
+      >>> class C(A, B):
+      ...     implements(I31)
       >>> c = C()
       >>> directlyProvides(c, I4)
       >>> [i.getName() for i in providedBy(c)]
@@ -1219,10 +1230,10 @@
       1
       >>> int(providedBy(c).extends(I5))
       0
-      >>> class COnly(A, B): implementsOnly(I31)
-      ...
-      >>> class D(COnly): implements(I5)
-      ...
+      >>> class COnly(A, B):
+      ...     implementsOnly(I31)
+      >>> class D(COnly):
+      ...     implements(I5)
       >>> c = D()
       >>> directlyProvides(c, I4)
       >>> [i.getName() for i in providedBy(c)]

Modified: zope.interface/trunk/src/zope/interface/interface.py
===================================================================
--- zope.interface/trunk/src/zope/interface/interface.py	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/interface.py	2010-04-09 08:16:17 UTC (rev 110699)
@@ -340,12 +340,8 @@
           >>> spec = Specification((I2, I3))
           >>> spec = Specification((I4, spec))
           >>> i = spec.interfaces()
-          >>> i.next().getName()
-          'I4'
-          >>> i.next().getName()
-          'I2'
-          >>> i.next().getName()
-          'I3'
+          >>> [x.getName() for x in i]
+          ['I4', 'I2', 'I3']
           >>> list(i)
           []
         """
@@ -480,6 +476,9 @@
         # Make sure that all recorded attributes (and methods) are of type
         # `Attribute` and `Method`
         for name, attr in attrs.items():
+            if name == '__locals__':
+                # This happens under Python 3 sometimes, not sure why. /regebro
+                continue
             if isinstance(attr, Attribute):
                 attr.interface = self
                 if not attr.__name__:
@@ -505,8 +504,8 @@
           ...
           >>>
           >>> i = I1.interfaces()
-          >>> i.next().getName()
-          'I1'
+          >>> [x.getName() for x in i]
+          ['I1']
           >>> list(i)
           []
         """
@@ -574,7 +573,7 @@
         exec "class %s: pass" % self.__name__ in klass
         klass=klass[self.__name__]
 
-        self.__d(klass.__dict__)
+        self.__d(klass)
 
         self._deferred=klass
 
@@ -603,14 +602,13 @@
         """Retrieve a named interface."""
         return None
 
-    def __d(self, dict):
-
+    def __d(self, klass):
         for k, v in self.__attrs.items():
-            if isinstance(v, Method) and not (k in dict):
-                dict[k]=v
+            if isinstance(v, Method) and not (k in klass.__dict__):
+                setattr(klass, k, v)
 
         for b in self.__bases__:
-            b.__d(dict)
+            b.__d(klass)
 
     def __repr__(self):
         try:
@@ -681,7 +679,7 @@
         n2 = (getattr(o2, '__name__', ''),
               getattr(getattr(o2,  '__module__', None), '__name__', ''))
 
-        return cmp(n1, n2)
+        return (n1 > n2) - (n1 < n2)
 
     def __lt__(self, other):
         c = self.__cmp(self, other)

Modified: zope.interface/trunk/src/zope/interface/interfaces.py
===================================================================
--- zope.interface/trunk/src/zope/interface/interfaces.py	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/interfaces.py	2010-04-09 08:16:17 UTC (rev 110699)
@@ -446,6 +446,13 @@
         Instances of ``C`` provide only ``I1``, ``I2``, and regardless of
         whatever interfaces instances of ``A`` and ``B`` implement.
         """
+        
+    def implementer_only(*interfaces):
+        """Create a decorator for declaring the only interfaces implemented 
+        
+        A callable is returned that makes an implements declaration on
+        objects passed to it.
+        """
 
     def directlyProvidedBy(object):
         """Return the interfaces directly provided by the given object
@@ -614,6 +621,8 @@
 
         after the class has been created.
         """
+    def provider(*interfaces):
+        """A class decorator version of classProvides"""
 
     def moduleProvides(*interfaces):
         """Declare interfaces provided by a module

Modified: zope.interface/trunk/src/zope/interface/tests/__init__.py
===================================================================
--- zope.interface/trunk/src/zope/interface/tests/__init__.py	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/tests/__init__.py	2010-04-09 08:16:17 UTC (rev 110699)
@@ -1,2 +1,13 @@
-#
-# This file is necessary to make this directory a package.
+import os
+import unittest
+
+def additional_tests():
+    suites = unittest.TestSuite()
+    for file in os.listdir(os.path.dirname(__file__)):
+        if file.endswith('.py') and file!='__init__.py':
+            name = os.path.splitext(file)[0]
+            module = __import__('.'.join((__name__, name)), globals(), 
+                                locals(), [name])
+            if hasattr(module, 'test_suite'):
+                suites.addTests(module.test_suite())
+    return suites

Modified: zope.interface/trunk/src/zope/interface/tests/odd.py
===================================================================
--- zope.interface/trunk/src/zope/interface/tests/odd.py	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/tests/odd.py	2010-04-09 08:16:17 UTC (rev 110699)
@@ -21,8 +21,8 @@
   ...
   >>> A.__name__
   'A'
-  >>> A.__bases__
-  (<type 'object'>,)
+  >>> A.__bases__ == (object,)
+  True
   >>> class B(object):
   ...     __metaclass__ = MetaClass
   ...     b = 1
@@ -55,9 +55,11 @@
   >>> C.c = 1
   >>> c.c
   1
-  >>> from types import ClassType
-  >>> int(isinstance(C, (type, ClassType)))
-  0
+  >>> import sys
+  >>> if sys.version[0] == '2': # This test only makes sense under Python 2.x
+  ...     from types import ClassType
+  ...     assert not isinstance(C, (type, ClassType))
+  
   >>> int(C.__class__.__class__ is C.__class__)
   1
 

Modified: zope.interface/trunk/src/zope/interface/tests/test_advice.py
===================================================================
--- zope.interface/trunk/src/zope/interface/tests/test_advice.py	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/tests/test_advice.py	2010-04-09 08:16:17 UTC (rev 110699)
@@ -31,7 +31,6 @@
 import unittest
 from unittest import TestCase, makeSuite, TestSuite
 from zope.interface.advice import *
-from types import ClassType
 import sys
 
 def ping(log, value):
@@ -42,9 +41,14 @@
 
     addClassAdvisor(pong)
 
-class ClassicClass:
-    __metaclass__ = ClassType
-    classLevelFrameInfo = getFrameInfo(sys._getframe())
+try:
+    from types import ClassType
+    
+    class ClassicClass:
+        __metaclass__ = ClassType
+        classLevelFrameInfo = getFrameInfo(sys._getframe())
+except ImportError:
+    pass
 
 class NewStyleClass:
     __metaclass__ = type
@@ -172,7 +176,11 @@
 TestClasses = (AdviceTests, FrameInfoTest)
 
 def test_suite():
-    return TestSuite([makeSuite(t,'check') for t in TestClasses])
+    if sys.version[0] == '2':
+        return TestSuite([makeSuite(t,'check') for t in TestClasses])
+    else:
+        # Advise metaclasses doesn't work in Python 3
+        return []
 
 if __name__ == '__main__':
     unittest.main(defaultTest='test_suite')

Modified: zope.interface/trunk/src/zope/interface/tests/test_interface.py
===================================================================
--- zope.interface/trunk/src/zope/interface/tests/test_interface.py	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/tests/test_interface.py	2010-04-09 08:16:17 UTC (rev 110699)
@@ -338,6 +338,9 @@
     def testIssue228(self):
         from zope.interface import Interface
         # Test for http://collector.zope.org/Zope3-dev/228
+        if sys.version[0] == '3':
+            # No old style classes in Python 3, so the test becomes moot.
+            return
         class I(Interface):
             "xxx"
         class Bad:
@@ -373,12 +376,14 @@
           ...     def __init__(self, min, max):
           ...         self.min, self.max = min, max
 
+          >>> from zope.interface.exceptions import Invalid
           >>> IRange.validateInvariants(Range(1,2))
           >>> IRange.validateInvariants(Range(1,1))
-          >>> IRange.validateInvariants(Range(2,1))
-          Traceback (most recent call last):
-          ...
-          Invalid: max < min
+          >>> try:
+          ...     IRange.validateInvariants(Range(2,1))
+          ... except Invalid, e:
+          ...     str(e)
+          'max < min'
 
 
         """
@@ -391,11 +396,11 @@
     suite.addTest(doctest.DocFileSuite(
         '../README.txt',
         globs={'__name__': '__main__'},
-        optionflags=doctest.NORMALIZE_WHITESPACE,
+        optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
         ))
     suite.addTest(doctest.DocFileSuite(
         '../README.ru.txt',
         globs={'__name__': '__main__'},
-        optionflags=doctest.NORMALIZE_WHITESPACE,
+        optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
         ))
     return suite

Modified: zope.interface/trunk/src/zope/interface/tests/test_odd_declarations.py
===================================================================
--- zope.interface/trunk/src/zope/interface/tests/test_odd_declarations.py	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/tests/test_odd_declarations.py	2010-04-09 08:16:17 UTC (rev 110699)
@@ -19,9 +19,9 @@
 $Id$
 """
 import doctest
-import odd
 import unittest
 
+from zope.interface.tests import odd
 from zope.interface import Interface, implements, implementsOnly
 from zope.interface import directlyProvides, providedBy, directlyProvidedBy
 from zope.interface import classImplements, classImplementsOnly, implementedBy
@@ -45,10 +45,12 @@
 # from zope.interface import classProvides
 
 class A(Odd):
-    implements(I1)
+    pass
+classImplements(A, I1)
 
 class C(A, B):
-    implements(I31)
+    pass
+classImplements(C, I31)
 
 
 class Test(unittest.TestCase):
@@ -69,10 +71,12 @@
         self.failIf(providedBy(c).extends(I5))
 
         class COnly(A, B):
-            implementsOnly(I31)
+            pass
+        classImplementsOnly(COnly, I31)
 
         class D(COnly):
-            implements(I5)
+            pass
+        classImplements(D, I5)
 
         classImplements(D, I5)
 
@@ -91,7 +95,8 @@
 
         class COnly(A, B): __implemented__ = I31
         class D(COnly):
-            implements(I5)
+            pass
+        classImplements(D, I5)
 
         classImplements(D, I5)
         c = D()
@@ -143,13 +148,16 @@
         class IB(Interface): pass
         class IC(Interface): pass
         class A(Odd):
-            implements(IA1, IA2)
+            pass
+        classImplements(A, IA1, IA2)
 
         class B(Odd):
-            implements(IB)
+            pass
+        classImplements(B, IB)
 
         class C(A, B):
-            implements(IC)
+            pass
+        classImplements(C, IC)
 
 
         ob = C()
@@ -186,10 +194,12 @@
         class I2(I1): pass
 
         class C1(Odd):
-          implements(I2)
+            pass
+        classImplements(C1, I2)
 
         class C2(C1):
-          implements(I3)
+            pass
+        classImplements(C2, I3)
 
         self.assertEqual([i.getName() for i in implementedBy(C2)],
                          ['I3', 'I2'])

Modified: zope.interface/trunk/src/zope/interface/tests/test_sorting.py
===================================================================
--- zope.interface/trunk/src/zope/interface/tests/test_sorting.py	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/tests/test_sorting.py	2010-04-09 08:16:17 UTC (rev 110699)
@@ -36,9 +36,9 @@
         self.assertEqual(l, [I1, I2, I3, I4, I5, I6])
 
     def test_w_None(self):
-        l = [I1, None, I3, I5, None, I6, I4, I2]
+        l = [I1, None, I3, I5, I6, I4, I2]
         l.sort()
-        self.assertEqual(l, [I1, I2, I3, I4, I5, I6, None, None])
+        self.assertEqual(l, [I1, I2, I3, I4, I5, I6, None])
 
 def test_suite():
     return TestSuite((

Modified: zope.interface/trunk/src/zope/interface/verify.py
===================================================================
--- zope.interface/trunk/src/zope/interface/verify.py	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/verify.py	2010-04-09 08:16:17 UTC (rev 110699)
@@ -19,6 +19,7 @@
 from zope.interface.exceptions import BrokenMethodImplementation
 from types import FunctionType, MethodType
 from zope.interface.interface import fromMethod, fromFunction, Method
+import sys
 
 # This will be monkey-patched when running under Zope 2, so leave this
 # here:
@@ -67,8 +68,12 @@
             continue
 
         if isinstance(attr, FunctionType):
-            # should never get here, since classes should not provide functions
-            meth = fromFunction(attr, iface, name=name)
+            if sys.version[0] == '3' and isinstance(candidate, type):
+                # This is an "unbound method" in Python 3.
+                meth = fromFunction(attr, iface, name=name, imlevel=1)
+            else:
+                # Nope, just a normal function
+                meth = fromFunction(attr, iface, name=name)
         elif (isinstance(attr, MethodTypes)
               and type(attr.im_func) is FunctionType):
             meth = fromMethod(attr, iface, name)

Modified: zope.interface/trunk/src/zope/interface/verify.txt
===================================================================
--- zope.interface/trunk/src/zope/interface/verify.txt	2010-04-09 02:33:49 UTC (rev 110698)
+++ zope.interface/trunk/src/zope/interface/verify.txt	2010-04-09 08:16:17 UTC (rev 110699)
@@ -35,6 +35,7 @@
 ``__init__`` method, will be recognized:
 
 >>> from zope.interface import Interface, Attribute, implements
+>>> from zope.interface.exceptions import BrokenImplementation
 >>> class IFoo(Interface):
 ...     x = Attribute("The X attribute")
 ...     y = Attribute("The Y attribute")
@@ -55,20 +56,28 @@
 ...     implements(IFoo)
 ...     x = 1
 
->>> verifyObject(IFoo, Foo())
-Traceback (most recent call last):
-BrokenImplementation: An object has failed to implement interface <InterfaceClass __builtin__.IFoo>
-    The y attribute was not provided.
+>>> try: #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
+...     verifyObject(IFoo, Foo())
+... except BrokenImplementation, e:
+...     print str(e)
+An object has failed to implement interface <InterfaceClass ...IFoo>
+<BLANKLINE>
+        The y attribute was not provided.
+<BLANKLINE>
 
 >>> class Foo(object):
 ...     implements(IFoo)
 ...     def __init__(self):
 ...         self.y = 2
 
->>> verifyObject(IFoo, Foo())
-Traceback (most recent call last):
-BrokenImplementation: An object has failed to implement interface <InterfaceClass __builtin__.IFoo>
-    The x attribute was not provided.
+>>> try: #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
+...     verifyObject(IFoo, Foo())
+... except BrokenImplementation, e:
+...     print str(e)
+An object has failed to implement interface <InterfaceClass ...IFoo>
+<BLANKLINE>
+        The x attribute was not provided.
+<BLANKLINE>
 
 If an attribute is implemented as a property that raises an AttributeError
 when trying to get its value, the attribute is considered missing:
@@ -82,10 +91,14 @@
 ...     def x(self):
 ...         raise AttributeError
 
->>> verifyObject(IFoo, Foo())
-Traceback (most recent call last):
-BrokenImplementation: An object has failed to implement interface <InterfaceClass __builtin__.IFoo>
-    The x attribute was not provided.
+>>> try: #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
+...     verifyObject(IFoo, Foo())
+... except BrokenImplementation, e:
+...     print str(e)
+An object has failed to implement interface <InterfaceClass ...IFoo>
+<BLANKLINE>
+        The x attribute was not provided.
+<BLANKLINE>
 
 Any other exception raised by a property will propagate to the caller of
 ``verifyObject``:



More information about the checkins mailing list