Add interfaces for builtins and the io ABCs.
This commit is contained in:
parent
5cda166377
commit
a061c2d726
|
@ -36,3 +36,13 @@ zope.interface.common.numbers
|
|||
=============================
|
||||
|
||||
.. automodule:: zope.interface.common.numbers
|
||||
|
||||
zope.interface.common.builtins
|
||||
==============================
|
||||
|
||||
.. automodule:: zope.interface.common.builtins
|
||||
|
||||
zope.interface.common.io
|
||||
========================
|
||||
|
||||
.. automodule:: zope.interface.common.io
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
# FOR A PARTICULAR PURPOSE.
|
||||
##############################################################################
|
||||
|
||||
import itertools
|
||||
from types import FunctionType
|
||||
|
||||
from zope.interface import classImplements
|
||||
|
@ -41,9 +42,24 @@ class ABCInterfaceClass(InterfaceClass):
|
|||
|
||||
Internal use only.
|
||||
|
||||
The body of the interface definition *must* define
|
||||
a property ``abc`` that is the ABC to base the interface on.
|
||||
|
||||
If ``abc`` is *not* in the interface definition, a regular
|
||||
interface will be defined instead (but ``extra_classes`` is still
|
||||
respected).
|
||||
|
||||
Use the ``@optional`` decorator on method definitions if
|
||||
the ABC defines methods that are not actually required in all cases
|
||||
because the Python language has multiple ways to implement a protocol.
|
||||
For example, the ``iter()`` protocol can be implemented with
|
||||
``__iter__`` or the pair ``__len__`` and ``__getitem__``.
|
||||
|
||||
When created, any existing classes that are registered to conform
|
||||
to the ABC are declared to implement this interface. This is *not*
|
||||
automatically updated as the ABC registry changes.
|
||||
automatically updated as the ABC registry changes. If the body of the
|
||||
interface definition defines ``extra_classes``, it should be a
|
||||
tuple giving additional classes to declare implement the interface.
|
||||
|
||||
Note that this is not fully symmetric. For example, it is usually
|
||||
the case that a subclass relationship carries the interface
|
||||
|
@ -103,27 +119,51 @@ class ABCInterfaceClass(InterfaceClass):
|
|||
def __init__(self, name, bases, attrs):
|
||||
# go ahead and give us a name to ease debugging.
|
||||
self.__name__ = name
|
||||
extra_classes = attrs.pop('extra_classes', ())
|
||||
|
||||
if 'abc' not in attrs:
|
||||
# Something like ``IList(ISequence)``: We're extending
|
||||
# abc interfaces but not an ABC interface ourself.
|
||||
self.__class__ = InterfaceClass
|
||||
InterfaceClass.__init__(self, name, bases, attrs)
|
||||
for cls in extra_classes:
|
||||
classImplements(cls, self)
|
||||
return
|
||||
|
||||
based_on = attrs.pop('abc')
|
||||
if based_on is None:
|
||||
# An ABC from the future, not available to us.
|
||||
methods = {
|
||||
'__doc__': 'This ABC is not available.'
|
||||
}
|
||||
else:
|
||||
assert name[1:] == based_on.__name__, (name, based_on)
|
||||
methods = {
|
||||
# Passing the name is important in case of aliases,
|
||||
# e.g., ``__ror__ = __or__``.
|
||||
k: self.__method_from_function(v, k)
|
||||
for k, v in vars(based_on).items()
|
||||
if isinstance(v, FunctionType) and not self.__is_private_name(k)
|
||||
and not self.__is_reverse_protocol_name(k)
|
||||
}
|
||||
methods['__doc__'] = "See `%s.%s`" % (
|
||||
based_on.__module__,
|
||||
based_on.__name__,
|
||||
)
|
||||
self.__abc = based_on
|
||||
self.__extra_classes = tuple(extra_classes)
|
||||
|
||||
assert name[1:] == based_on.__name__, (name, based_on)
|
||||
methods = {
|
||||
# Passing the name is important in case of aliases,
|
||||
# e.g., ``__ror__ = __or__``.
|
||||
k: self.__method_from_function(v, k)
|
||||
for k, v in vars(based_on).items()
|
||||
if isinstance(v, FunctionType) and not self.__is_private_name(k)
|
||||
and not self.__is_reverse_protocol_name(k)
|
||||
}
|
||||
|
||||
def ref(c):
|
||||
mod = c.__module__
|
||||
name = c.__name__
|
||||
if mod == str.__module__:
|
||||
return "`%s`" % name
|
||||
if mod == '_io':
|
||||
mod = 'io'
|
||||
return "`%s.%s`" % (mod, name)
|
||||
implementations_doc = "\n - ".join(
|
||||
ref(c)
|
||||
for c in sorted(self.getRegisteredConformers(), key=ref)
|
||||
)
|
||||
if implementations_doc:
|
||||
implementations_doc = "\n\nKnown implementations are:\n\n - " + implementations_doc
|
||||
|
||||
methods['__doc__'] = """Interface for the ABC `%s.%s`.%s""" % (
|
||||
based_on.__module__,
|
||||
based_on.__name__,
|
||||
implementations_doc
|
||||
)
|
||||
# Anything specified in the body takes precedence.
|
||||
# This lets us remove things that are rarely, if ever,
|
||||
# actually implemented. For example, ``tuple`` is registered
|
||||
|
@ -132,7 +172,6 @@ class ABCInterfaceClass(InterfaceClass):
|
|||
# because it has ``__len__`` and ``__getitem__``.
|
||||
methods.update(attrs)
|
||||
InterfaceClass.__init__(self, name, bases, methods)
|
||||
self.__abc = based_on
|
||||
self.__register_classes()
|
||||
|
||||
@staticmethod
|
||||
|
@ -187,7 +226,7 @@ class ABCInterfaceClass(InterfaceClass):
|
|||
registered = [x() for x in registry]
|
||||
registered = [x for x in registered if x is not None]
|
||||
|
||||
return registered
|
||||
return set(itertools.chain(registered, self.__extra_classes))
|
||||
|
||||
|
||||
ABCInterface = ABCInterfaceClass.__new__(ABCInterfaceClass, None, None, None)
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
##############################################################################
|
||||
# Copyright (c) 2020 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
##############################################################################
|
||||
"""
|
||||
Interface definitions for builtin types.
|
||||
|
||||
After this module is imported, the standard library types will declare
|
||||
that they implement the appropriate interface.
|
||||
|
||||
.. versionadded:: 5.0.0
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
from zope.interface import classImplements
|
||||
|
||||
from zope.interface.common import collections
|
||||
from zope.interface.common import numbers
|
||||
from zope.interface.common import io
|
||||
|
||||
__all__ = [
|
||||
'IList',
|
||||
'ITuple',
|
||||
'ITextString',
|
||||
'IByteString',
|
||||
'INativeString',
|
||||
'IBool',
|
||||
'IDict',
|
||||
'IFile',
|
||||
]
|
||||
|
||||
class IList(collections.IMutableSequence):
|
||||
"""
|
||||
Interface for :class:`list`
|
||||
"""
|
||||
extra_classes = (list,)
|
||||
|
||||
|
||||
class ITuple(collections.ISequence):
|
||||
"""
|
||||
Interface for :class:`tuple`
|
||||
"""
|
||||
extra_classes = (tuple,)
|
||||
|
||||
|
||||
class ITextString(collections.ISequence):
|
||||
"""
|
||||
Interface for text (unicode) strings.
|
||||
|
||||
On Python 2, this is :class:`unicode`. On Python 3,
|
||||
this is :class:`str`
|
||||
"""
|
||||
extra_classes = (type(u'unicode'),)
|
||||
|
||||
|
||||
class IByteString(collections.IByteString):
|
||||
"""
|
||||
Interface for immutable byte strings.
|
||||
|
||||
On all Python versions this is :class:`bytes`.
|
||||
|
||||
Unlike :class:`zope.interface.common.collections.IByteString`
|
||||
(the parent of this interface) this does *not* include
|
||||
:class:`bytearray`.
|
||||
"""
|
||||
extra_classes = (bytes,)
|
||||
|
||||
|
||||
class INativeString(IByteString if str is bytes else ITextString):
|
||||
"""
|
||||
Interface for native strings.
|
||||
|
||||
On all Python versions, this is :class:`str`. On Python 2,
|
||||
this extends :class:`IByteString`, while on Python 3 it extends
|
||||
:class:`ITextString`.
|
||||
"""
|
||||
# We're not extending ABCInterface so extra_classes won't work
|
||||
classImplements(str, INativeString)
|
||||
|
||||
|
||||
class IBool(numbers.IIntegral):
|
||||
"""
|
||||
Interface for :class:`bool`
|
||||
"""
|
||||
extra_classes = (bool,)
|
||||
|
||||
|
||||
class IDict(collections.IMutableMapping):
|
||||
"""
|
||||
Interface for :class:`dict`
|
||||
"""
|
||||
extra_classes = (dict,)
|
||||
|
||||
|
||||
class IFile(io.IIOBase):
|
||||
"""
|
||||
Interface for :class:`file`.
|
||||
|
||||
It is recommended to use the interfaces from :mod:`zope.interface.common.io`
|
||||
instead of this interface.
|
||||
|
||||
On Python 3, there is no single implementation of this interface;
|
||||
depending on the arguments, the :func:`open` builtin can return
|
||||
many different classes that implement different interfaces from
|
||||
:mod:`zope.interface.common.io`.
|
||||
"""
|
||||
try:
|
||||
extra_classes = (file,)
|
||||
except NameError:
|
||||
extra_classes = ()
|
|
@ -34,11 +34,31 @@ from __future__ import absolute_import
|
|||
import sys
|
||||
|
||||
from abc import ABCMeta
|
||||
# The collections imports are here, and not in
|
||||
# zope.interface._compat to avoid importing collections
|
||||
# unless requested. It's a big import.
|
||||
try:
|
||||
from collections import abc
|
||||
except ImportError:
|
||||
import collections as abc
|
||||
|
||||
try:
|
||||
# On Python 3, all of these extend the appropriate collection ABC,
|
||||
# but on Python 2, UserDict does not (though it is registered as a
|
||||
# MutableMapping). (Importantly, UserDict on Python 2 is *not*
|
||||
# registered, because it's not iterable.) Extending the ABC is not
|
||||
# taken into account for interface declarations, though, so we
|
||||
# need to be explicit about it.
|
||||
from collections import UserList
|
||||
from collections import UserDict
|
||||
from collections import UserString
|
||||
except ImportError:
|
||||
# Python 2
|
||||
from UserList import UserList
|
||||
from UserDict import IterableUserDict as UserDict
|
||||
from UserString import UserString
|
||||
|
||||
|
||||
from zope.interface._compat import PYTHON2 as PY2
|
||||
from zope.interface._compat import PYTHON3 as PY3
|
||||
from zope.interface.common import ABCInterface
|
||||
|
@ -149,6 +169,7 @@ class ICollection(ISized,
|
|||
class ISequence(IReversible,
|
||||
ICollection):
|
||||
abc = abc.Sequence
|
||||
extra_classes = (UserString,)
|
||||
|
||||
@optional
|
||||
def __reversed__():
|
||||
|
@ -161,6 +182,7 @@ class ISequence(IReversible,
|
|||
|
||||
class IMutableSequence(ISequence):
|
||||
abc = abc.MutableSequence
|
||||
extra_classes = (UserList,)
|
||||
|
||||
|
||||
class IByteString(ISequence):
|
||||
|
@ -192,8 +214,10 @@ class IMapping(ICollection):
|
|||
|
||||
__ne__ = __eq__
|
||||
|
||||
|
||||
class IMutableMapping(IMapping):
|
||||
abc = abc.MutableMapping
|
||||
extra_classes = (UserDict,)
|
||||
|
||||
|
||||
class IMappingView(ISized):
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
##############################################################################
|
||||
# Copyright (c) 2020 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
##############################################################################
|
||||
"""
|
||||
Interface definitions paralleling the abstract base classes defined in
|
||||
:mod:`io`.
|
||||
|
||||
After this module is imported, the standard library types will declare
|
||||
that they implement the appropriate interface.
|
||||
|
||||
.. versionadded:: 5.0.0
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import io as abc
|
||||
try:
|
||||
import cStringIO
|
||||
import StringIO
|
||||
except ImportError:
|
||||
# Python 3
|
||||
extra_buffered_io_base = ()
|
||||
else:
|
||||
extra_buffered_io_base = (StringIO.StringIO, cStringIO.InputType, cStringIO.OutputType)
|
||||
|
||||
from zope.interface.common import ABCInterface
|
||||
|
||||
# pylint:disable=inherit-non-class,
|
||||
# pylint:disable=no-member
|
||||
|
||||
class IIOBase(ABCInterface):
|
||||
abc = abc.IOBase
|
||||
|
||||
|
||||
class IRawIOBase(IIOBase):
|
||||
abc = abc.RawIOBase
|
||||
|
||||
|
||||
class IBufferedIOBase(IIOBase):
|
||||
abc = abc.BufferedIOBase
|
||||
extra_classes = extra_buffered_io_base
|
||||
|
||||
|
||||
class ITextIOBase(IIOBase):
|
||||
abc = abc.TextIOBase
|
|
@ -10,6 +10,10 @@
|
|||
# FOR A PARTICULAR PURPOSE.
|
||||
##############################################################################
|
||||
|
||||
import unittest
|
||||
|
||||
from zope.interface.verify import verifyClass
|
||||
from zope.interface.verify import verifyObject
|
||||
|
||||
from zope.interface.common import ABCInterface
|
||||
from zope.interface.common import ABCInterfaceClass
|
||||
|
@ -56,3 +60,27 @@ def add_abc_interface_tests(cls, module):
|
|||
test.__name__ = name
|
||||
assert not hasattr(cls, name)
|
||||
setattr(cls, name, test)
|
||||
|
||||
|
||||
|
||||
class VerifyClassMixin(unittest.TestCase):
|
||||
verifier = staticmethod(verifyClass)
|
||||
UNVERIFIABLE = ()
|
||||
|
||||
def _adjust_object_before_verify(self, iface, x):
|
||||
return x
|
||||
|
||||
def verify(self, iface, klass, **kwargs):
|
||||
return self.verifier(iface,
|
||||
self._adjust_object_before_verify(iface, klass),
|
||||
**kwargs)
|
||||
|
||||
|
||||
class VerifyObjectMixin(VerifyClassMixin):
|
||||
verifier = staticmethod(verifyObject)
|
||||
CONSTRUCTORS = {
|
||||
}
|
||||
|
||||
def _adjust_object_before_verify(self, iface, x):
|
||||
return self.CONSTRUCTORS.get(iface,
|
||||
self.CONSTRUCTORS.get(x, x))()
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
##############################################################################
|
||||
# Copyright (c) 2020 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
##############################################################################
|
||||
from __future__ import absolute_import
|
||||
|
||||
import unittest
|
||||
|
||||
from zope.interface._compat import PYTHON2 as PY2
|
||||
from zope.interface.common import builtins
|
||||
|
||||
from . import VerifyClassMixin
|
||||
from . import VerifyObjectMixin
|
||||
|
||||
|
||||
class TestVerifyClass(VerifyClassMixin,
|
||||
unittest.TestCase):
|
||||
UNVERIFIABLE = (
|
||||
|
||||
)
|
||||
FILE_IMPL = ()
|
||||
if PY2:
|
||||
UNVERIFIABLE += (
|
||||
# On both CPython and PyPy, there's no
|
||||
# exposed __iter__ method for strings or unicode.
|
||||
unicode,
|
||||
str,
|
||||
)
|
||||
FILE_IMPL = ((file, builtins.IFile),)
|
||||
@classmethod
|
||||
def create_tests(cls):
|
||||
for klass, iface in (
|
||||
(list, builtins.IList),
|
||||
(tuple, builtins.ITuple),
|
||||
(type(u'abc'), builtins.ITextString),
|
||||
(bytes, builtins.IByteString),
|
||||
(str, builtins.INativeString),
|
||||
(bool, builtins.IBool),
|
||||
(dict, builtins.IDict),
|
||||
) + cls.FILE_IMPL:
|
||||
def test(self, klass=klass, iface=iface):
|
||||
if klass in self.UNVERIFIABLE:
|
||||
self.skipTest("Cannot verify %s" % klass)
|
||||
|
||||
self.assertTrue(self.verify(iface, klass))
|
||||
|
||||
name = 'test_auto_' + klass.__name__ + '_' + iface.__name__
|
||||
test.__name__ = name
|
||||
setattr(cls, name, test)
|
||||
|
||||
TestVerifyClass.create_tests()
|
||||
|
||||
|
||||
class TestVerifyObject(VerifyObjectMixin,
|
||||
TestVerifyClass):
|
||||
CONSTRUCTORS = {
|
||||
builtins.IFile: lambda: open(__file__)
|
||||
}
|
|
@ -18,11 +18,13 @@ except ImportError:
|
|||
import collections as abc
|
||||
from collections import deque
|
||||
|
||||
|
||||
try:
|
||||
from types import MappingProxyType
|
||||
except ImportError:
|
||||
MappingProxyType = object()
|
||||
|
||||
from zope.interface import Invalid
|
||||
from zope.interface.verify import verifyClass
|
||||
from zope.interface.verify import verifyObject
|
||||
|
||||
|
@ -34,19 +36,10 @@ from zope.interface._compat import PYPY
|
|||
from zope.interface._compat import PYTHON2 as PY2
|
||||
|
||||
from . import add_abc_interface_tests
|
||||
from . import VerifyClassMixin
|
||||
from . import VerifyObjectMixin
|
||||
|
||||
class TestVerifyClass(unittest.TestCase):
|
||||
|
||||
verifier = staticmethod(verifyClass)
|
||||
|
||||
def _adjust_object_before_verify(self, iface, x):
|
||||
return x
|
||||
|
||||
def verify(self, iface, klass, **kwargs):
|
||||
return self.verifier(iface,
|
||||
self._adjust_object_before_verify(iface, klass),
|
||||
**kwargs)
|
||||
|
||||
class TestVerifyClass(VerifyClassMixin, unittest.TestCase):
|
||||
|
||||
# Here we test some known builtin classes that are defined to implement
|
||||
# various collection interfaces as a quick sanity test.
|
||||
|
@ -58,6 +51,29 @@ class TestVerifyClass(unittest.TestCase):
|
|||
self.assertIsInstance(list(), abc.MutableSequence)
|
||||
self.assertTrue(self.verify(collections.IMutableSequence, list))
|
||||
|
||||
# Here we test some derived classes.
|
||||
def test_UserList(self):
|
||||
self.assertTrue(self.verify(collections.IMutableSequence,
|
||||
collections.UserList))
|
||||
|
||||
def test_UserDict(self):
|
||||
self.assertTrue(self.verify(collections.IMutableMapping,
|
||||
collections.UserDict))
|
||||
|
||||
def test_UserString(self):
|
||||
self.assertTrue(self.verify(collections.ISequence,
|
||||
collections.UserString))
|
||||
|
||||
def test_non_iterable_UserDict(self):
|
||||
try:
|
||||
from UserDict import UserDict as NonIterableUserDict # pylint:disable=import-error
|
||||
except ImportError:
|
||||
# Python 3
|
||||
self.skipTest("No UserDict.NonIterableUserDict on Python 3")
|
||||
|
||||
with self.assertRaises(Invalid):
|
||||
self.verify(collections.IMutableMapping, NonIterableUserDict)
|
||||
|
||||
# Now we go through the registry, which should have several things,
|
||||
# mostly builtins, but if we've imported other libraries already,
|
||||
# it could contain things from outside of there too. We aren't concerned
|
||||
|
@ -109,25 +125,20 @@ class TestVerifyClass(unittest.TestCase):
|
|||
add_abc_interface_tests(TestVerifyClass, collections.ISet.__module__)
|
||||
|
||||
|
||||
|
||||
class TestVerifyObject(TestVerifyClass):
|
||||
verifier = staticmethod(verifyObject)
|
||||
|
||||
_CONSTRUCTORS = {
|
||||
class TestVerifyObject(VerifyObjectMixin,
|
||||
TestVerifyClass):
|
||||
CONSTRUCTORS = {
|
||||
collections.IValuesView: {}.values,
|
||||
collections.IItemsView: {}.items,
|
||||
collections.IKeysView: {}.keys,
|
||||
memoryview: lambda: memoryview(b'abc'),
|
||||
range: lambda: range(10),
|
||||
MappingProxyType: lambda: MappingProxyType({})
|
||||
MappingProxyType: lambda: MappingProxyType({}),
|
||||
collections.UserString: lambda: collections.UserString('abc'),
|
||||
}
|
||||
|
||||
if PY2:
|
||||
# pylint:disable=undefined-variable,no-member
|
||||
_CONSTRUCTORS.update({
|
||||
CONSTRUCTORS.update({
|
||||
collections.IValuesView: {}.viewvalues,
|
||||
})
|
||||
|
||||
def _adjust_object_before_verify(self, iface, x):
|
||||
return self._CONSTRUCTORS.get(iface,
|
||||
self._CONSTRUCTORS.get(x, x))()
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
##############################################################################
|
||||
# Copyright (c) 2020 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
##############################################################################
|
||||
|
||||
|
||||
import unittest
|
||||
import io as abc
|
||||
|
||||
# Note that importing z.i.c.io does work on import.
|
||||
from zope.interface.common import io
|
||||
|
||||
from . import add_abc_interface_tests
|
||||
from . import VerifyClassMixin
|
||||
from . import VerifyObjectMixin
|
||||
|
||||
|
||||
class TestVerifyClass(VerifyClassMixin,
|
||||
unittest.TestCase):
|
||||
pass
|
||||
|
||||
add_abc_interface_tests(TestVerifyClass, io.IIOBase.__module__)
|
||||
|
||||
|
||||
class TestVerifyObject(VerifyObjectMixin,
|
||||
TestVerifyClass):
|
||||
CONSTRUCTORS = {
|
||||
abc.BufferedWriter: lambda: abc.BufferedWriter(abc.StringIO()),
|
||||
abc.BufferedReader: lambda: abc.BufferedReader(abc.StringIO()),
|
||||
abc.TextIOWrapper: lambda: abc.TextIOWrapper(abc.BytesIO()),
|
||||
abc.BufferedRandom: lambda: abc.BufferedRandom(abc.BytesIO()),
|
||||
abc.BufferedRWPair: lambda: abc.BufferedRWPair(abc.BytesIO(), abc.BytesIO()),
|
||||
abc.FileIO: lambda: abc.FileIO(__file__),
|
||||
}
|
||||
|
||||
try:
|
||||
import cStringIO
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
CONSTRUCTORS.update({
|
||||
cStringIO.InputType: lambda cStringIO=cStringIO: cStringIO.StringIO('abc'),
|
||||
cStringIO.OutputType: cStringIO.StringIO,
|
||||
})
|
|
@ -14,26 +14,16 @@
|
|||
import unittest
|
||||
import numbers as abc
|
||||
|
||||
from zope.interface.verify import verifyClass
|
||||
from zope.interface.verify import verifyObject
|
||||
|
||||
# Note that importing z.i.c.numbers does work on import.
|
||||
from zope.interface.common import numbers
|
||||
|
||||
from . import add_abc_interface_tests
|
||||
from . import VerifyClassMixin
|
||||
from . import VerifyObjectMixin
|
||||
|
||||
|
||||
class TestVerifyClass(unittest.TestCase):
|
||||
verifier = staticmethod(verifyClass)
|
||||
UNVERIFIABLE = ()
|
||||
|
||||
def _adjust_object_before_verify(self, iface, x):
|
||||
return x
|
||||
|
||||
def verify(self, iface, klass, **kwargs):
|
||||
return self.verifier(iface,
|
||||
self._adjust_object_before_verify(iface, klass),
|
||||
**kwargs)
|
||||
class TestVerifyClass(VerifyClassMixin,
|
||||
unittest.TestCase):
|
||||
|
||||
def test_int(self):
|
||||
self.assertIsInstance(int(), abc.Integral)
|
||||
|
@ -46,8 +36,6 @@ class TestVerifyClass(unittest.TestCase):
|
|||
add_abc_interface_tests(TestVerifyClass, numbers.INumber.__module__)
|
||||
|
||||
|
||||
class TestVerifyObject(TestVerifyClass):
|
||||
verifier = staticmethod(verifyObject)
|
||||
|
||||
def _adjust_object_before_verify(self, iface, x):
|
||||
return x()
|
||||
class TestVerifyObject(VerifyObjectMixin,
|
||||
TestVerifyClass):
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue