[Checkins] SVN: zope.interface/branches/tseaver-no_2to3/ Deprecated the "class advice" APIs from ``zope.interface.declarations``.
Tres Seaver
cvs-admin at zope.org
Fri Apr 6 05:35:36 UTC 2012
Log message for revision 124990:
Deprecated the "class advice" APIs from ``zope.interface.declarations``.
Code which uses the deprecated APIs will not work as expected under Py3k.
Instead of ``implements``, ``implementsOnly``, or ``classProvides``,
prefer the equivalent class decorators: ``@implementer``,
``@implementer_only``, and ``@provider``.
Changed:
U zope.interface/branches/tseaver-no_2to3/CHANGES.txt
U zope.interface/branches/tseaver-no_2to3/src/zope/interface/declarations.py
U zope.interface/branches/tseaver-no_2to3/src/zope/interface/tests/test_declarations.py
-=-
Modified: zope.interface/branches/tseaver-no_2to3/CHANGES.txt
===================================================================
--- zope.interface/branches/tseaver-no_2to3/CHANGES.txt 2012-04-06 05:35:28 UTC (rev 124989)
+++ zope.interface/branches/tseaver-no_2to3/CHANGES.txt 2012-04-06 05:35:33 UTC (rev 124990)
@@ -4,6 +4,12 @@
4.0.0a1 (unreleased)
--------------------
+- Deprecated the "class advice" APIs from ``zope.interface.declarations``:
+ ``implements``, ``implementsOnly``, and ``classProvides``. In their place,
+ prefer the equivalent class decorators: ``@implementer``,
+ ``@implementer_only``, and ``@provider``. Code which uses the deprecated
+ APIs will not work as expected under Py3k.
+
- Removed use of '2to3' and associated fixers when installing under Py3k.
The code is now in a "compatible subset" which supports Python 2.6, 2.7,
and 3.2, including PyPy 1.8 (the version compatible with the 2.7 language
Modified: zope.interface/branches/tseaver-no_2to3/src/zope/interface/declarations.py
===================================================================
--- zope.interface/branches/tseaver-no_2to3/src/zope/interface/declarations.py 2012-04-06 05:35:28 UTC (rev 124989)
+++ zope.interface/branches/tseaver-no_2to3/src/zope/interface/declarations.py 2012-04-06 05:35:33 UTC (rev 124990)
@@ -30,6 +30,7 @@
from types import FunctionType
from types import MethodType
from types import ModuleType
+import warnings
import weakref
from zope.interface.advice import addClassAdvisor
@@ -42,6 +43,12 @@
# Registry of class-implementation specifications
BuiltinImplementationSpecifications = {}
+_ADVICE_ERROR = ('Class advice impossible in Python3. '
+ 'Use the @%s class decorator instead.')
+
+_ADVICE_WARNING = ('The %s API is deprecated, and will not work in Python3 '
+ 'Use the @%s class decorator instead.')
+
class Declaration(Specification):
"""Interface declarations"""
@@ -394,9 +401,10 @@
# This entire approach is invalid under Py3K. Don't even try to fix
# the coverage for this block there. :(
if PYTHON3: #pragma NO COVER
- raise TypeError('Class advice impossible in Python3. Use the'
- '@implementer class decorator instead.'
- )
+ raise TypeError(_ADVICE_ERROR % 'implementer')
+ else:
+ warnings.warn(_ADVICE_WARNING % ('implements', 'implementer'),
+ DeprecationWarning, 2)
_implements("implements", interfaces, classImplements)
def implementsOnly(*interfaces):
@@ -424,9 +432,10 @@
# This entire approach is invalid under Py3K. Don't even try to fix
# the coverage for this block there. :(
if PYTHON3: #pragma NO COVER
- raise TypeError('Class advice impossible in Python3. Use the'
- '@implementer_only class decorator instead.'
- )
+ raise TypeError(_ADVICE_ERROR % 'implementer_only')
+ else:
+ warnings.warn(_ADVICE_WARNING % ('implementsOnly', 'implementer_only'),
+ DeprecationWarning, 2)
_implements("implementsOnly", interfaces, classImplementsOnly)
##############################################################################
@@ -630,10 +639,12 @@
"""
# This entire approach is invalid under Py3K. Don't even try to fix
# the coverage for this block there. :(
+
if PYTHON3: #pragma NO COVER
- raise TypeError('Class advice impossible in Python3. Use the'
- '@provider class decorator instead.'
- )
+ raise TypeError(_ADVICE_ERROR % 'provider')
+ else:
+ warnings.warn(_ADVICE_WARNING % ('classProvides', 'provider'),
+ DeprecationWarning, 2)
frame = sys._getframe(1)
locals = frame.f_locals
Modified: zope.interface/branches/tseaver-no_2to3/src/zope/interface/tests/test_declarations.py
===================================================================
--- zope.interface/branches/tseaver-no_2to3/src/zope/interface/tests/test_declarations.py 2012-04-06 05:35:28 UTC (rev 124989)
+++ zope.interface/branches/tseaver-no_2to3/src/zope/interface/tests/test_declarations.py 2012-04-06 05:35:33 UTC (rev 124990)
@@ -32,19 +32,28 @@
class _Py3ClassAdvice(object):
- def _run_generated_code(self, code, globs, locs, fails_under_py3k=True):
- import sys
- if sys.version_info[0] < 3:
- exec(code, globs, locs)
- return True
- else:
- try:
+ def _run_generated_code(self, code, globs, locs,
+ fails_under_py3k=True,
+ warnings_under_py2=1):
+ import warnings
+ from zope.interface._compat import PYTHON3
+ with warnings.catch_warnings(record=True) as log:
+ warnings.resetwarnings()
+ if not PYTHON3:
exec(code, globs, locs)
- except TypeError:
- return False
+ if warnings_under_py2:
+ self.assertEqual(len(log), warnings_under_py2)
+ for entry in log:
+ self.assertEqual(entry.category, DeprecationWarning)
+ return True
else:
- if fails_under_py3k:
- self.fail("Didn't raise TypeError")
+ try:
+ exec(code, globs, locs)
+ except TypeError:
+ return False
+ else:
+ if fails_under_py3k:
+ self.fail("Didn't raise TypeError")
class DeclarationTests(_SilencePy3Deprecations):
@@ -642,6 +651,7 @@
return implementsOnly
def test_simple(self):
+ import warnings
from zope.interface.declarations import implementsOnly
from zope.interface._compat import PYTHON3
from zope.interface.interface import InterfaceClass
@@ -654,17 +664,21 @@
'class Foo(object):'
' implementsOnly(IFoo)',
])
- try:
- exec(CODE, globs, locs)
- except TypeError:
- if not PYTHON3:
- raise
- else:
- if PYTHON3:
- self.fail("Didn't raise TypeError")
- Foo = locs['Foo']
- spec = Foo.__implemented__
- self.assertEqual(list(spec), [IFoo])
+ with warnings.catch_warnings(record=True) as log:
+ warnings.resetwarnings()
+ try:
+ exec(CODE, globs, locs)
+ except TypeError:
+ if not PYTHON3:
+ raise
+ else:
+ if PYTHON3:
+ self.fail("Didn't raise TypeError")
+ Foo = locs['Foo']
+ spec = Foo.__implemented__
+ self.assertEqual(list(spec), [IFoo])
+ self.assertEqual(len(log), 1)
+ self.assertEqual(log[0].category, DeprecationWarning)
def test_called_once_from_class_w_bases(self):
from zope.interface.declarations import implements
@@ -684,7 +698,7 @@
'class Bar(Foo):'
' implementsOnly(IBar)',
])
- if self._run_generated_code(CODE, globs, locs):
+ if self._run_generated_code(CODE, globs, locs, warnings_under_py2=2):
Bar = locs['Bar']
spec = Bar.__implemented__
self.assertEqual(list(spec), [IBar])
@@ -697,6 +711,7 @@
return implements
def test_called_from_function(self):
+ import warnings
from zope.interface.declarations import implements
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass("IFoo")
@@ -706,13 +721,19 @@
'def foo():',
' implements(IFoo)'
])
- if self._run_generated_code(CODE, globs, locs, False):
+ if self._run_generated_code(CODE, globs, locs, False, 0):
foo = locs['foo']
- self.assertRaises(TypeError, foo)
+ with warnings.catch_warnings(record=True) as log:
+ warnings.resetwarnings()
+ self.assertRaises(TypeError, foo)
+ self.assertEqual(len(log), 1)
+ self.assertEqual(log[0].category, DeprecationWarning)
def test_called_twice_from_class(self):
+ import warnings
from zope.interface.declarations import implements
from zope.interface.interface import InterfaceClass
+ from zope.interface._compat import PYTHON3
IFoo = InterfaceClass("IFoo")
IBar = InterfaceClass("IBar")
globs = {'implements': implements, 'IFoo': IFoo, 'IBar': IBar}
@@ -722,12 +743,17 @@
' implements(IFoo)',
' implements(IBar)',
])
- try:
- exec(CODE, globs, locs)
- except TypeError:
- pass
- else:
- self.fail("Didn't raise TypeError")
+ with warnings.catch_warnings(record=True) as log:
+ warnings.resetwarnings()
+ try:
+ exec(CODE, globs, locs)
+ except TypeError:
+ if not PYTHON3:
+ self.assertEqual(len(log), 2)
+ for entry in log:
+ self.assertEqual(entry.category, DeprecationWarning)
+ else:
+ self.fail("Didn't raise TypeError")
def test_called_once_from_class(self):
from zope.interface.declarations import implements
@@ -1112,8 +1138,10 @@
return classProvides
def test_called_from_function(self):
+ import warnings
from zope.interface.declarations import classProvides
from zope.interface.interface import InterfaceClass
+ from zope.interface._compat import PYTHON3
IFoo = InterfaceClass("IFoo")
globs = {'classProvides': classProvides, 'IFoo': IFoo}
locs = {}
@@ -1123,11 +1151,18 @@
])
exec(CODE, globs, locs)
foo = locs['foo']
- self.assertRaises(TypeError, foo)
+ with warnings.catch_warnings(record=True) as log:
+ warnings.resetwarnings()
+ self.assertRaises(TypeError, foo)
+ if not PYTHON3:
+ self.assertEqual(len(log), 1)
+ self.assertEqual(log[0].category, DeprecationWarning)
def test_called_twice_from_class(self):
+ import warnings
from zope.interface.declarations import classProvides
from zope.interface.interface import InterfaceClass
+ from zope.interface._compat import PYTHON3
IFoo = InterfaceClass("IFoo")
IBar = InterfaceClass("IBar")
globs = {'classProvides': classProvides, 'IFoo': IFoo, 'IBar': IBar}
@@ -1137,12 +1172,17 @@
' classProvides(IFoo)',
' classProvides(IBar)',
])
- try:
- exec(CODE, globs, locs)
- except TypeError:
- pass
- else:
- self.fail("Didn't raise TypeError")
+ with warnings.catch_warnings(record=True) as log:
+ warnings.resetwarnings()
+ try:
+ exec(CODE, globs, locs)
+ except TypeError:
+ if not PYTHON3:
+ self.assertEqual(len(log), 2)
+ for entry in log:
+ self.assertEqual(entry.category, DeprecationWarning)
+ else:
+ self.fail("Didn't raise TypeError")
def test_called_once_from_class(self):
from zope.interface.declarations import classProvides
More information about the checkins
mailing list