Primer commit
This commit is contained in:
@@ -0,0 +1,272 @@
|
||||
##############################################################################
|
||||
# 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 itertools
|
||||
from types import FunctionType
|
||||
|
||||
from zope.interface import classImplements
|
||||
from zope.interface import Interface
|
||||
from zope.interface.interface import fromFunction
|
||||
from zope.interface.interface import InterfaceClass
|
||||
from zope.interface.interface import _decorator_non_return
|
||||
|
||||
__all__ = [
|
||||
# Nothing public here.
|
||||
]
|
||||
|
||||
|
||||
# pylint:disable=inherit-non-class,
|
||||
# pylint:disable=no-self-argument,no-method-argument
|
||||
# pylint:disable=unexpected-special-method-signature
|
||||
|
||||
class optional:
|
||||
# Apply this decorator to a method definition to make it
|
||||
# optional (remove it from the list of required names), overriding
|
||||
# the definition inherited from the ABC.
|
||||
def __init__(self, method):
|
||||
self.__doc__ = method.__doc__
|
||||
|
||||
|
||||
class ABCInterfaceClass(InterfaceClass):
|
||||
"""
|
||||
An interface that is automatically derived from a
|
||||
:class:`abc.ABCMeta` type.
|
||||
|
||||
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. 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
|
||||
declarations over::
|
||||
|
||||
>>> from zope.interface import Interface
|
||||
>>> class I1(Interface):
|
||||
... pass
|
||||
...
|
||||
>>> from zope.interface import implementer
|
||||
>>> @implementer(I1)
|
||||
... class Root(object):
|
||||
... pass
|
||||
...
|
||||
>>> class Child(Root):
|
||||
... pass
|
||||
...
|
||||
>>> child = Child()
|
||||
>>> isinstance(child, Root)
|
||||
True
|
||||
>>> from zope.interface import providedBy
|
||||
>>> list(providedBy(child))
|
||||
[<InterfaceClass __main__.I1>]
|
||||
|
||||
However, that's not the case with ABCs and ABC interfaces. Just
|
||||
because ``isinstance(A(), AnABC)`` and ``isinstance(B(), AnABC)``
|
||||
are both true, that doesn't mean there's any class hierarchy
|
||||
relationship between ``A`` and ``B``, or between either of them
|
||||
and ``AnABC``. Thus, if ``AnABC`` implemented ``IAnABC``, it would
|
||||
not follow that either ``A`` or ``B`` implements ``IAnABC`` (nor
|
||||
their instances provide it)::
|
||||
|
||||
>>> class SizedClass(object):
|
||||
... def __len__(self): return 1
|
||||
...
|
||||
>>> from collections.abc import Sized
|
||||
>>> isinstance(SizedClass(), Sized)
|
||||
True
|
||||
>>> from zope.interface import classImplements
|
||||
>>> classImplements(Sized, I1)
|
||||
None
|
||||
>>> list(providedBy(SizedClass()))
|
||||
[]
|
||||
|
||||
Thus, to avoid conflicting assumptions, ABCs should not be
|
||||
declared to implement their parallel ABC interface. Only concrete
|
||||
classes specifically registered with the ABC should be declared to
|
||||
do so.
|
||||
|
||||
.. versionadded:: 5.0.0
|
||||
"""
|
||||
|
||||
# If we could figure out invalidation, and used some special
|
||||
# Specification/Declaration instances, and override the method ``providedBy`` here,
|
||||
# perhaps we could more closely integrate with ABC virtual inheritance?
|
||||
|
||||
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', ())
|
||||
ignored_classes = attrs.pop('ignored_classes', ())
|
||||
|
||||
if 'abc' not in attrs:
|
||||
# Something like ``IList(ISequence)``: We're extending
|
||||
# abc interfaces but not an ABC interface ourself.
|
||||
InterfaceClass.__init__(self, name, bases, attrs)
|
||||
ABCInterfaceClass.__register_classes(self, extra_classes, ignored_classes)
|
||||
self.__class__ = InterfaceClass
|
||||
return
|
||||
|
||||
based_on = attrs.pop('abc')
|
||||
self.__abc = based_on
|
||||
self.__extra_classes = tuple(extra_classes)
|
||||
self.__ignored_classes = tuple(ignored_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)
|
||||
}
|
||||
|
||||
methods['__doc__'] = self.__create_class_doc(attrs)
|
||||
# Anything specified in the body takes precedence.
|
||||
methods.update(attrs)
|
||||
InterfaceClass.__init__(self, name, bases, methods)
|
||||
self.__register_classes()
|
||||
|
||||
@staticmethod
|
||||
def __optional_methods_to_docs(attrs):
|
||||
optionals = {k: v for k, v in attrs.items() if isinstance(v, optional)}
|
||||
for k in optionals:
|
||||
attrs[k] = _decorator_non_return
|
||||
|
||||
if not optionals:
|
||||
return ''
|
||||
|
||||
docs = "\n\nThe following methods are optional:\n - " + "\n-".join(
|
||||
"{}\n{}".format(k, v.__doc__) for k, v in optionals.items()
|
||||
)
|
||||
return docs
|
||||
|
||||
def __create_class_doc(self, attrs):
|
||||
based_on = self.__abc
|
||||
def ref(c):
|
||||
mod = c.__module__
|
||||
name = c.__name__
|
||||
if mod == str.__module__:
|
||||
return "`%s`" % name
|
||||
if mod == '_io':
|
||||
mod = 'io'
|
||||
return "`{}.{}`".format(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
|
||||
|
||||
based_on_doc = (based_on.__doc__ or '')
|
||||
based_on_doc = based_on_doc.splitlines()
|
||||
based_on_doc = based_on_doc[0] if based_on_doc else ''
|
||||
|
||||
doc = """Interface for the ABC `{}.{}`.\n\n{}{}{}""".format(
|
||||
based_on.__module__, based_on.__name__,
|
||||
attrs.get('__doc__', based_on_doc),
|
||||
self.__optional_methods_to_docs(attrs),
|
||||
implementations_doc
|
||||
)
|
||||
return doc
|
||||
|
||||
|
||||
@staticmethod
|
||||
def __is_private_name(name):
|
||||
if name.startswith('__') and name.endswith('__'):
|
||||
return False
|
||||
return name.startswith('_')
|
||||
|
||||
@staticmethod
|
||||
def __is_reverse_protocol_name(name):
|
||||
# The reverse names, like __rand__,
|
||||
# aren't really part of the protocol. The interpreter has
|
||||
# very complex behaviour around invoking those. PyPy
|
||||
# doesn't always even expose them as attributes.
|
||||
return name.startswith('__r') and name.endswith('__')
|
||||
|
||||
def __method_from_function(self, function, name):
|
||||
method = fromFunction(function, self, name=name)
|
||||
# Eliminate the leading *self*, which is implied in
|
||||
# an interface, but explicit in an ABC.
|
||||
method.positional = method.positional[1:]
|
||||
return method
|
||||
|
||||
def __register_classes(self, conformers=None, ignored_classes=None):
|
||||
# Make the concrete classes already present in our ABC's registry
|
||||
# declare that they implement this interface.
|
||||
conformers = conformers if conformers is not None else self.getRegisteredConformers()
|
||||
ignored = ignored_classes if ignored_classes is not None else self.__ignored_classes
|
||||
for cls in conformers:
|
||||
if cls in ignored:
|
||||
continue
|
||||
classImplements(cls, self)
|
||||
|
||||
def getABC(self):
|
||||
"""
|
||||
Return the ABC this interface represents.
|
||||
"""
|
||||
return self.__abc
|
||||
|
||||
def getRegisteredConformers(self):
|
||||
"""
|
||||
Return an iterable of the classes that are known to conform to
|
||||
the ABC this interface parallels.
|
||||
"""
|
||||
based_on = self.__abc
|
||||
|
||||
# The registry only contains things that aren't already
|
||||
# known to be subclasses of the ABC. But the ABC is in charge
|
||||
# of checking that, so its quite possible that registrations
|
||||
# are in fact ignored, winding up just in the _abc_cache.
|
||||
try:
|
||||
registered = list(based_on._abc_registry) + list(based_on._abc_cache)
|
||||
except AttributeError:
|
||||
# Rewritten in C in CPython 3.7.
|
||||
# These expose the underlying weakref.
|
||||
from abc import _get_dump
|
||||
data = _get_dump(based_on)
|
||||
registry = data[0]
|
||||
cache = data[1]
|
||||
registered = [x() for x in itertools.chain(registry, cache)]
|
||||
registered = [x for x in registered if x is not None]
|
||||
|
||||
return set(itertools.chain(registered, self.__extra_classes))
|
||||
|
||||
|
||||
def _create_ABCInterface():
|
||||
# It's a two-step process to create the root ABCInterface, because
|
||||
# without specifying a corresponding ABC, using the normal constructor
|
||||
# gets us a plain InterfaceClass object, and there is no ABC to associate with the
|
||||
# root.
|
||||
abc_name_bases_attrs = ('ABCInterface', (Interface,), {})
|
||||
instance = ABCInterfaceClass.__new__(ABCInterfaceClass, *abc_name_bases_attrs)
|
||||
InterfaceClass.__init__(instance, *abc_name_bases_attrs)
|
||||
return instance
|
||||
|
||||
ABCInterface = _create_ABCInterface()
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,119 @@
|
||||
##############################################################################
|
||||
# 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 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',
|
||||
]
|
||||
|
||||
# pylint:disable=no-self-argument
|
||||
class IList(collections.IMutableSequence):
|
||||
"""
|
||||
Interface for :class:`list`
|
||||
"""
|
||||
extra_classes = (list,)
|
||||
|
||||
def sort(key=None, reverse=False):
|
||||
"""
|
||||
Sort the list in place and return None.
|
||||
|
||||
*key* and *reverse* must be passed by name only.
|
||||
"""
|
||||
|
||||
|
||||
class ITuple(collections.ISequence):
|
||||
"""
|
||||
Interface for :class:`tuple`
|
||||
"""
|
||||
extra_classes = (tuple,)
|
||||
|
||||
|
||||
class ITextString(collections.ISequence):
|
||||
"""
|
||||
Interface for text ("unicode") strings.
|
||||
|
||||
This is :class:`str`
|
||||
"""
|
||||
extra_classes = (str,)
|
||||
|
||||
|
||||
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(ITextString):
|
||||
"""
|
||||
Interface for native strings.
|
||||
|
||||
On all Python versions, this is :class:`str`. Tt 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`.
|
||||
"""
|
||||
extra_classes = ()
|
||||
@@ -0,0 +1,253 @@
|
||||
##############################################################################
|
||||
# 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:`collections.abc`.
|
||||
|
||||
After this module is imported, the standard library types will declare
|
||||
that they implement the appropriate interface. While most standard
|
||||
library types will properly implement that interface (that
|
||||
is, ``verifyObject(ISequence, list()))`` will pass, for example), a few might not:
|
||||
|
||||
- `memoryview` doesn't feature all the defined methods of
|
||||
``ISequence`` such as ``count``; it is still declared to provide
|
||||
``ISequence`` though.
|
||||
|
||||
- `collections.deque.pop` doesn't accept the ``index`` argument of
|
||||
`collections.abc.MutableSequence.pop`
|
||||
|
||||
- `range.index` does not accept the ``start`` and ``stop`` arguments.
|
||||
|
||||
.. versionadded:: 5.0.0
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
from abc import ABCMeta
|
||||
from collections import abc
|
||||
from collections import OrderedDict
|
||||
from collections import UserList
|
||||
from collections import UserDict
|
||||
from collections import UserString
|
||||
|
||||
from zope.interface.common import ABCInterface
|
||||
from zope.interface.common import optional
|
||||
|
||||
# pylint:disable=inherit-non-class,
|
||||
# pylint:disable=no-self-argument,no-method-argument
|
||||
# pylint:disable=unexpected-special-method-signature
|
||||
# pylint:disable=no-value-for-parameter
|
||||
|
||||
|
||||
def _new_in_ver(name, ver,
|
||||
bases_if_missing=(ABCMeta,),
|
||||
register_if_missing=()):
|
||||
if ver:
|
||||
return getattr(abc, name)
|
||||
|
||||
# TODO: It's a shame to have to repeat the bases when
|
||||
# the ABC is missing. Can we DRY that?
|
||||
missing = ABCMeta(name, bases_if_missing, {
|
||||
'__doc__': "The ABC %s is not defined in this version of Python." % (
|
||||
name
|
||||
),
|
||||
})
|
||||
|
||||
for c in register_if_missing:
|
||||
missing.register(c)
|
||||
|
||||
return missing
|
||||
|
||||
__all__ = [
|
||||
'IAsyncGenerator',
|
||||
'IAsyncIterable',
|
||||
'IAsyncIterator',
|
||||
'IAwaitable',
|
||||
'ICollection',
|
||||
'IContainer',
|
||||
'ICoroutine',
|
||||
'IGenerator',
|
||||
'IHashable',
|
||||
'IItemsView',
|
||||
'IIterable',
|
||||
'IIterator',
|
||||
'IKeysView',
|
||||
'IMapping',
|
||||
'IMappingView',
|
||||
'IMutableMapping',
|
||||
'IMutableSequence',
|
||||
'IMutableSet',
|
||||
'IReversible',
|
||||
'ISequence',
|
||||
'ISet',
|
||||
'ISized',
|
||||
'IValuesView',
|
||||
]
|
||||
|
||||
class IContainer(ABCInterface):
|
||||
abc = abc.Container
|
||||
|
||||
@optional
|
||||
def __contains__(other):
|
||||
"""
|
||||
Optional method. If not provided, the interpreter will use
|
||||
``__iter__`` or the old ``__getitem__`` protocol
|
||||
to implement ``in``.
|
||||
"""
|
||||
|
||||
class IHashable(ABCInterface):
|
||||
abc = abc.Hashable
|
||||
|
||||
class IIterable(ABCInterface):
|
||||
abc = abc.Iterable
|
||||
|
||||
@optional
|
||||
def __iter__():
|
||||
"""
|
||||
Optional method. If not provided, the interpreter will
|
||||
implement `iter` using the old ``__getitem__`` protocol.
|
||||
"""
|
||||
|
||||
class IIterator(IIterable):
|
||||
abc = abc.Iterator
|
||||
|
||||
class IReversible(IIterable):
|
||||
abc = _new_in_ver('Reversible', True, (IIterable.getABC(),))
|
||||
|
||||
@optional
|
||||
def __reversed__():
|
||||
"""
|
||||
Optional method. If this isn't present, the interpreter
|
||||
will use ``__len__`` and ``__getitem__`` to implement the
|
||||
`reversed` builtin.
|
||||
"""
|
||||
|
||||
class IGenerator(IIterator):
|
||||
# New in Python 3.5
|
||||
abc = _new_in_ver('Generator', True, (IIterator.getABC(),))
|
||||
|
||||
|
||||
class ISized(ABCInterface):
|
||||
abc = abc.Sized
|
||||
|
||||
|
||||
# ICallable is not defined because there's no standard signature.
|
||||
|
||||
class ICollection(ISized,
|
||||
IIterable,
|
||||
IContainer):
|
||||
abc = _new_in_ver('Collection', True,
|
||||
(ISized.getABC(), IIterable.getABC(), IContainer.getABC()))
|
||||
|
||||
|
||||
class ISequence(IReversible,
|
||||
ICollection):
|
||||
abc = abc.Sequence
|
||||
extra_classes = (UserString,)
|
||||
# On Python 2, basestring is registered as an ISequence, and
|
||||
# its subclass str is an IByteString. If we also register str as
|
||||
# an ISequence, that tends to lead to inconsistent resolution order.
|
||||
ignored_classes = (basestring,) if str is bytes else () # pylint:disable=undefined-variable
|
||||
|
||||
@optional
|
||||
def __reversed__():
|
||||
"""
|
||||
Optional method. If this isn't present, the interpreter
|
||||
will use ``__len__`` and ``__getitem__`` to implement the
|
||||
`reversed` builtin.
|
||||
"""
|
||||
|
||||
@optional
|
||||
def __iter__():
|
||||
"""
|
||||
Optional method. If not provided, the interpreter will
|
||||
implement `iter` using the old ``__getitem__`` protocol.
|
||||
"""
|
||||
|
||||
class IMutableSequence(ISequence):
|
||||
abc = abc.MutableSequence
|
||||
extra_classes = (UserList,)
|
||||
|
||||
|
||||
class IByteString(ISequence):
|
||||
"""
|
||||
This unifies `bytes` and `bytearray`.
|
||||
"""
|
||||
abc = _new_in_ver('ByteString', True,
|
||||
(ISequence.getABC(),),
|
||||
(bytes, bytearray))
|
||||
|
||||
|
||||
class ISet(ICollection):
|
||||
abc = abc.Set
|
||||
|
||||
|
||||
class IMutableSet(ISet):
|
||||
abc = abc.MutableSet
|
||||
|
||||
|
||||
class IMapping(ICollection):
|
||||
abc = abc.Mapping
|
||||
extra_classes = (dict,)
|
||||
# OrderedDict is a subclass of dict. On CPython 2,
|
||||
# it winds up registered as a IMutableMapping, which
|
||||
# produces an inconsistent IRO if we also try to register it
|
||||
# here.
|
||||
ignored_classes = (OrderedDict,)
|
||||
|
||||
|
||||
class IMutableMapping(IMapping):
|
||||
abc = abc.MutableMapping
|
||||
extra_classes = (dict, UserDict,)
|
||||
ignored_classes = (OrderedDict,)
|
||||
|
||||
class IMappingView(ISized):
|
||||
abc = abc.MappingView
|
||||
|
||||
|
||||
class IItemsView(IMappingView, ISet):
|
||||
abc = abc.ItemsView
|
||||
|
||||
|
||||
class IKeysView(IMappingView, ISet):
|
||||
abc = abc.KeysView
|
||||
|
||||
|
||||
class IValuesView(IMappingView, ICollection):
|
||||
abc = abc.ValuesView
|
||||
|
||||
@optional
|
||||
def __contains__(other):
|
||||
"""
|
||||
Optional method. If not provided, the interpreter will use
|
||||
``__iter__`` or the old ``__len__`` and ``__getitem__`` protocol
|
||||
to implement ``in``.
|
||||
"""
|
||||
|
||||
class IAwaitable(ABCInterface):
|
||||
abc = _new_in_ver('Awaitable', True)
|
||||
|
||||
|
||||
class ICoroutine(IAwaitable):
|
||||
abc = _new_in_ver('Coroutine', True)
|
||||
|
||||
|
||||
class IAsyncIterable(ABCInterface):
|
||||
abc = _new_in_ver('AsyncIterable', True)
|
||||
|
||||
|
||||
class IAsyncIterator(IAsyncIterable):
|
||||
abc = _new_in_ver('AsyncIterator', True)
|
||||
|
||||
|
||||
class IAsyncGenerator(IAsyncIterator):
|
||||
abc = _new_in_ver('AsyncGenerator', True)
|
||||
@@ -0,0 +1,606 @@
|
||||
##############################################################################
|
||||
# Copyright (c) 2002 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.
|
||||
##############################################################################
|
||||
"""Datetime interfaces.
|
||||
|
||||
This module is called idatetime because if it were called datetime the import
|
||||
of the real datetime would fail.
|
||||
"""
|
||||
from datetime import timedelta, date, datetime, time, tzinfo
|
||||
|
||||
from zope.interface import Interface, Attribute
|
||||
from zope.interface import classImplements
|
||||
|
||||
|
||||
class ITimeDeltaClass(Interface):
|
||||
"""This is the timedelta class interface.
|
||||
|
||||
This is symbolic; this module does **not** make
|
||||
`datetime.timedelta` provide this interface.
|
||||
"""
|
||||
|
||||
min = Attribute("The most negative timedelta object")
|
||||
|
||||
max = Attribute("The most positive timedelta object")
|
||||
|
||||
resolution = Attribute(
|
||||
"The smallest difference between non-equal timedelta objects")
|
||||
|
||||
|
||||
class ITimeDelta(ITimeDeltaClass):
|
||||
"""Represent the difference between two datetime objects.
|
||||
|
||||
Implemented by `datetime.timedelta`.
|
||||
|
||||
Supported operators:
|
||||
|
||||
- add, subtract timedelta
|
||||
- unary plus, minus, abs
|
||||
- compare to timedelta
|
||||
- multiply, divide by int/long
|
||||
|
||||
In addition, `.datetime` supports subtraction of two `.datetime` objects
|
||||
returning a `.timedelta`, and addition or subtraction of a `.datetime`
|
||||
and a `.timedelta` giving a `.datetime`.
|
||||
|
||||
Representation: (days, seconds, microseconds).
|
||||
"""
|
||||
|
||||
days = Attribute("Days between -999999999 and 999999999 inclusive")
|
||||
|
||||
seconds = Attribute("Seconds between 0 and 86399 inclusive")
|
||||
|
||||
microseconds = Attribute("Microseconds between 0 and 999999 inclusive")
|
||||
|
||||
|
||||
class IDateClass(Interface):
|
||||
"""This is the date class interface.
|
||||
|
||||
This is symbolic; this module does **not** make
|
||||
`datetime.date` provide this interface.
|
||||
"""
|
||||
|
||||
min = Attribute("The earliest representable date")
|
||||
|
||||
max = Attribute("The latest representable date")
|
||||
|
||||
resolution = Attribute(
|
||||
"The smallest difference between non-equal date objects")
|
||||
|
||||
def today():
|
||||
"""Return the current local time.
|
||||
|
||||
This is equivalent to ``date.fromtimestamp(time.time())``"""
|
||||
|
||||
def fromtimestamp(timestamp):
|
||||
"""Return the local date from a POSIX timestamp (like time.time())
|
||||
|
||||
This may raise `ValueError`, if the timestamp is out of the range of
|
||||
values supported by the platform C ``localtime()`` function. It's common
|
||||
for this to be restricted to years from 1970 through 2038. Note that
|
||||
on non-POSIX systems that include leap seconds in their notion of a
|
||||
timestamp, leap seconds are ignored by `fromtimestamp`.
|
||||
"""
|
||||
|
||||
def fromordinal(ordinal):
|
||||
"""Return the date corresponding to the proleptic Gregorian ordinal.
|
||||
|
||||
January 1 of year 1 has ordinal 1. `ValueError` is raised unless
|
||||
1 <= ordinal <= date.max.toordinal().
|
||||
|
||||
For any date *d*, ``date.fromordinal(d.toordinal()) == d``.
|
||||
"""
|
||||
|
||||
|
||||
class IDate(IDateClass):
|
||||
"""Represents a date (year, month and day) in an idealized calendar.
|
||||
|
||||
Implemented by `datetime.date`.
|
||||
|
||||
Operators:
|
||||
|
||||
__repr__, __str__
|
||||
__cmp__, __hash__
|
||||
__add__, __radd__, __sub__ (add/radd only with timedelta arg)
|
||||
"""
|
||||
|
||||
year = Attribute("Between MINYEAR and MAXYEAR inclusive.")
|
||||
|
||||
month = Attribute("Between 1 and 12 inclusive")
|
||||
|
||||
day = Attribute(
|
||||
"Between 1 and the number of days in the given month of the given year.")
|
||||
|
||||
def replace(year, month, day):
|
||||
"""Return a date with the same value.
|
||||
|
||||
Except for those members given new values by whichever keyword
|
||||
arguments are specified. For example, if ``d == date(2002, 12, 31)``, then
|
||||
``d.replace(day=26) == date(2000, 12, 26)``.
|
||||
"""
|
||||
|
||||
def timetuple():
|
||||
"""Return a 9-element tuple of the form returned by `time.localtime`.
|
||||
|
||||
The hours, minutes and seconds are 0, and the DST flag is -1.
|
||||
``d.timetuple()`` is equivalent to
|
||||
``(d.year, d.month, d.day, 0, 0, 0, d.weekday(), d.toordinal() -
|
||||
date(d.year, 1, 1).toordinal() + 1, -1)``
|
||||
"""
|
||||
|
||||
def toordinal():
|
||||
"""Return the proleptic Gregorian ordinal of the date
|
||||
|
||||
January 1 of year 1 has ordinal 1. For any date object *d*,
|
||||
``date.fromordinal(d.toordinal()) == d``.
|
||||
"""
|
||||
|
||||
def weekday():
|
||||
"""Return the day of the week as an integer.
|
||||
|
||||
Monday is 0 and Sunday is 6. For example,
|
||||
``date(2002, 12, 4).weekday() == 2``, a Wednesday.
|
||||
|
||||
.. seealso:: `isoweekday`.
|
||||
"""
|
||||
|
||||
def isoweekday():
|
||||
"""Return the day of the week as an integer.
|
||||
|
||||
Monday is 1 and Sunday is 7. For example,
|
||||
date(2002, 12, 4).isoweekday() == 3, a Wednesday.
|
||||
|
||||
.. seealso:: `weekday`, `isocalendar`.
|
||||
"""
|
||||
|
||||
def isocalendar():
|
||||
"""Return a 3-tuple, (ISO year, ISO week number, ISO weekday).
|
||||
|
||||
The ISO calendar is a widely used variant of the Gregorian calendar.
|
||||
See http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm for a good
|
||||
explanation.
|
||||
|
||||
The ISO year consists of 52 or 53 full weeks, and where a week starts
|
||||
on a Monday and ends on a Sunday. The first week of an ISO year is the
|
||||
first (Gregorian) calendar week of a year containing a Thursday. This
|
||||
is called week number 1, and the ISO year of that Thursday is the same
|
||||
as its Gregorian year.
|
||||
|
||||
For example, 2004 begins on a Thursday, so the first week of ISO year
|
||||
2004 begins on Monday, 29 Dec 2003 and ends on Sunday, 4 Jan 2004, so
|
||||
that ``date(2003, 12, 29).isocalendar() == (2004, 1, 1)`` and
|
||||
``date(2004, 1, 4).isocalendar() == (2004, 1, 7)``.
|
||||
"""
|
||||
|
||||
def isoformat():
|
||||
"""Return a string representing the date in ISO 8601 format.
|
||||
|
||||
This is 'YYYY-MM-DD'.
|
||||
For example, ``date(2002, 12, 4).isoformat() == '2002-12-04'``.
|
||||
"""
|
||||
|
||||
def __str__():
|
||||
"""For a date *d*, ``str(d)`` is equivalent to ``d.isoformat()``."""
|
||||
|
||||
def ctime():
|
||||
"""Return a string representing the date.
|
||||
|
||||
For example date(2002, 12, 4).ctime() == 'Wed Dec 4 00:00:00 2002'.
|
||||
d.ctime() is equivalent to time.ctime(time.mktime(d.timetuple()))
|
||||
on platforms where the native C ctime() function
|
||||
(which `time.ctime` invokes, but which date.ctime() does not invoke)
|
||||
conforms to the C standard.
|
||||
"""
|
||||
|
||||
def strftime(format):
|
||||
"""Return a string representing the date.
|
||||
|
||||
Controlled by an explicit format string. Format codes referring to
|
||||
hours, minutes or seconds will see 0 values.
|
||||
"""
|
||||
|
||||
|
||||
class IDateTimeClass(Interface):
|
||||
"""This is the datetime class interface.
|
||||
|
||||
This is symbolic; this module does **not** make
|
||||
`datetime.datetime` provide this interface.
|
||||
"""
|
||||
|
||||
min = Attribute("The earliest representable datetime")
|
||||
|
||||
max = Attribute("The latest representable datetime")
|
||||
|
||||
resolution = Attribute(
|
||||
"The smallest possible difference between non-equal datetime objects")
|
||||
|
||||
def today():
|
||||
"""Return the current local datetime, with tzinfo None.
|
||||
|
||||
This is equivalent to ``datetime.fromtimestamp(time.time())``.
|
||||
|
||||
.. seealso:: `now`, `fromtimestamp`.
|
||||
"""
|
||||
|
||||
def now(tz=None):
|
||||
"""Return the current local date and time.
|
||||
|
||||
If optional argument *tz* is None or not specified, this is like `today`,
|
||||
but, if possible, supplies more precision than can be gotten from going
|
||||
through a `time.time` timestamp (for example, this may be possible on
|
||||
platforms supplying the C ``gettimeofday()`` function).
|
||||
|
||||
Else tz must be an instance of a class tzinfo subclass, and the current
|
||||
date and time are converted to tz's time zone. In this case the result
|
||||
is equivalent to tz.fromutc(datetime.utcnow().replace(tzinfo=tz)).
|
||||
|
||||
.. seealso:: `today`, `utcnow`.
|
||||
"""
|
||||
|
||||
def utcnow():
|
||||
"""Return the current UTC date and time, with tzinfo None.
|
||||
|
||||
This is like `now`, but returns the current UTC date and time, as a
|
||||
naive datetime object.
|
||||
|
||||
.. seealso:: `now`.
|
||||
"""
|
||||
|
||||
def fromtimestamp(timestamp, tz=None):
|
||||
"""Return the local date and time corresponding to the POSIX timestamp.
|
||||
|
||||
Same as is returned by time.time(). If optional argument tz is None or
|
||||
not specified, the timestamp is converted to the platform's local date
|
||||
and time, and the returned datetime object is naive.
|
||||
|
||||
Else tz must be an instance of a class tzinfo subclass, and the
|
||||
timestamp is converted to tz's time zone. In this case the result is
|
||||
equivalent to
|
||||
``tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz))``.
|
||||
|
||||
fromtimestamp() may raise `ValueError`, if the timestamp is out of the
|
||||
range of values supported by the platform C localtime() or gmtime()
|
||||
functions. It's common for this to be restricted to years in 1970
|
||||
through 2038. Note that on non-POSIX systems that include leap seconds
|
||||
in their notion of a timestamp, leap seconds are ignored by
|
||||
fromtimestamp(), and then it's possible to have two timestamps
|
||||
differing by a second that yield identical datetime objects.
|
||||
|
||||
.. seealso:: `utcfromtimestamp`.
|
||||
"""
|
||||
|
||||
def utcfromtimestamp(timestamp):
|
||||
"""Return the UTC datetime from the POSIX timestamp with tzinfo None.
|
||||
|
||||
This may raise `ValueError`, if the timestamp is out of the range of
|
||||
values supported by the platform C ``gmtime()`` function. It's common for
|
||||
this to be restricted to years in 1970 through 2038.
|
||||
|
||||
.. seealso:: `fromtimestamp`.
|
||||
"""
|
||||
|
||||
def fromordinal(ordinal):
|
||||
"""Return the datetime from the proleptic Gregorian ordinal.
|
||||
|
||||
January 1 of year 1 has ordinal 1. `ValueError` is raised unless
|
||||
1 <= ordinal <= datetime.max.toordinal().
|
||||
The hour, minute, second and microsecond of the result are all 0, and
|
||||
tzinfo is None.
|
||||
"""
|
||||
|
||||
def combine(date, time):
|
||||
"""Return a new datetime object.
|
||||
|
||||
Its date members are equal to the given date object's, and whose time
|
||||
and tzinfo members are equal to the given time object's. For any
|
||||
datetime object *d*, ``d == datetime.combine(d.date(), d.timetz())``.
|
||||
If date is a datetime object, its time and tzinfo members are ignored.
|
||||
"""
|
||||
|
||||
|
||||
class IDateTime(IDate, IDateTimeClass):
|
||||
"""Object contains all the information from a date object and a time object.
|
||||
|
||||
Implemented by `datetime.datetime`.
|
||||
"""
|
||||
|
||||
year = Attribute("Year between MINYEAR and MAXYEAR inclusive")
|
||||
|
||||
month = Attribute("Month between 1 and 12 inclusive")
|
||||
|
||||
day = Attribute(
|
||||
"Day between 1 and the number of days in the given month of the year")
|
||||
|
||||
hour = Attribute("Hour in range(24)")
|
||||
|
||||
minute = Attribute("Minute in range(60)")
|
||||
|
||||
second = Attribute("Second in range(60)")
|
||||
|
||||
microsecond = Attribute("Microsecond in range(1000000)")
|
||||
|
||||
tzinfo = Attribute(
|
||||
"""The object passed as the tzinfo argument to the datetime constructor
|
||||
or None if none was passed""")
|
||||
|
||||
def date():
|
||||
"""Return date object with same year, month and day."""
|
||||
|
||||
def time():
|
||||
"""Return time object with same hour, minute, second, microsecond.
|
||||
|
||||
tzinfo is None.
|
||||
|
||||
.. seealso:: Method :meth:`timetz`.
|
||||
"""
|
||||
|
||||
def timetz():
|
||||
"""Return time object with same hour, minute, second, microsecond,
|
||||
and tzinfo.
|
||||
|
||||
.. seealso:: Method :meth:`time`.
|
||||
"""
|
||||
|
||||
def replace(year, month, day, hour, minute, second, microsecond, tzinfo):
|
||||
"""Return a datetime with the same members, except for those members
|
||||
given new values by whichever keyword arguments are specified.
|
||||
|
||||
Note that ``tzinfo=None`` can be specified to create a naive datetime from
|
||||
an aware datetime with no conversion of date and time members.
|
||||
"""
|
||||
|
||||
def astimezone(tz):
|
||||
"""Return a datetime object with new tzinfo member tz, adjusting the
|
||||
date and time members so the result is the same UTC time as self, but
|
||||
in tz's local time.
|
||||
|
||||
tz must be an instance of a tzinfo subclass, and its utcoffset() and
|
||||
dst() methods must not return None. self must be aware (self.tzinfo
|
||||
must not be None, and self.utcoffset() must not return None).
|
||||
|
||||
If self.tzinfo is tz, self.astimezone(tz) is equal to self: no
|
||||
adjustment of date or time members is performed. Else the result is
|
||||
local time in time zone tz, representing the same UTC time as self:
|
||||
|
||||
after astz = dt.astimezone(tz), astz - astz.utcoffset()
|
||||
|
||||
will usually have the same date and time members as dt - dt.utcoffset().
|
||||
The discussion of class `datetime.tzinfo` explains the cases at Daylight Saving
|
||||
Time transition boundaries where this cannot be achieved (an issue only
|
||||
if tz models both standard and daylight time).
|
||||
|
||||
If you merely want to attach a time zone object *tz* to a datetime *dt*
|
||||
without adjustment of date and time members, use ``dt.replace(tzinfo=tz)``.
|
||||
If you merely want to remove the time zone object from an aware
|
||||
datetime dt without conversion of date and time members, use
|
||||
``dt.replace(tzinfo=None)``.
|
||||
|
||||
Note that the default `tzinfo.fromutc` method can be overridden in a
|
||||
tzinfo subclass to effect the result returned by `astimezone`.
|
||||
"""
|
||||
|
||||
def utcoffset():
|
||||
"""Return the timezone offset in minutes east of UTC (negative west of
|
||||
UTC)."""
|
||||
|
||||
def dst():
|
||||
"""Return 0 if DST is not in effect, or the DST offset (in minutes
|
||||
eastward) if DST is in effect.
|
||||
"""
|
||||
|
||||
def tzname():
|
||||
"""Return the timezone name."""
|
||||
|
||||
def timetuple():
|
||||
"""Return a 9-element tuple of the form returned by `time.localtime`."""
|
||||
|
||||
def utctimetuple():
|
||||
"""Return UTC time tuple compatilble with `time.gmtime`."""
|
||||
|
||||
def toordinal():
|
||||
"""Return the proleptic Gregorian ordinal of the date.
|
||||
|
||||
The same as self.date().toordinal().
|
||||
"""
|
||||
|
||||
def weekday():
|
||||
"""Return the day of the week as an integer.
|
||||
|
||||
Monday is 0 and Sunday is 6. The same as self.date().weekday().
|
||||
See also isoweekday().
|
||||
"""
|
||||
|
||||
def isoweekday():
|
||||
"""Return the day of the week as an integer.
|
||||
|
||||
Monday is 1 and Sunday is 7. The same as self.date().isoweekday.
|
||||
|
||||
.. seealso:: `weekday`, `isocalendar`.
|
||||
"""
|
||||
|
||||
def isocalendar():
|
||||
"""Return a 3-tuple, (ISO year, ISO week number, ISO weekday).
|
||||
|
||||
The same as self.date().isocalendar().
|
||||
"""
|
||||
|
||||
def isoformat(sep='T'):
|
||||
"""Return a string representing the date and time in ISO 8601 format.
|
||||
|
||||
YYYY-MM-DDTHH:MM:SS.mmmmmm or YYYY-MM-DDTHH:MM:SS if microsecond is 0
|
||||
|
||||
If `utcoffset` does not return None, a 6-character string is appended,
|
||||
giving the UTC offset in (signed) hours and minutes:
|
||||
|
||||
YYYY-MM-DDTHH:MM:SS.mmmmmm+HH:MM or YYYY-MM-DDTHH:MM:SS+HH:MM
|
||||
if microsecond is 0.
|
||||
|
||||
The optional argument sep (default 'T') is a one-character separator,
|
||||
placed between the date and time portions of the result.
|
||||
"""
|
||||
|
||||
def __str__():
|
||||
"""For a datetime instance *d*, ``str(d)`` is equivalent to ``d.isoformat(' ')``.
|
||||
"""
|
||||
|
||||
def ctime():
|
||||
"""Return a string representing the date and time.
|
||||
|
||||
``datetime(2002, 12, 4, 20, 30, 40).ctime() == 'Wed Dec 4 20:30:40 2002'``.
|
||||
``d.ctime()`` is equivalent to ``time.ctime(time.mktime(d.timetuple()))`` on
|
||||
platforms where the native C ``ctime()`` function (which `time.ctime`
|
||||
invokes, but which `datetime.ctime` does not invoke) conforms to the
|
||||
C standard.
|
||||
"""
|
||||
|
||||
def strftime(format):
|
||||
"""Return a string representing the date and time.
|
||||
|
||||
This is controlled by an explicit format string.
|
||||
"""
|
||||
|
||||
|
||||
class ITimeClass(Interface):
|
||||
"""This is the time class interface.
|
||||
|
||||
This is symbolic; this module does **not** make
|
||||
`datetime.time` provide this interface.
|
||||
|
||||
"""
|
||||
|
||||
min = Attribute("The earliest representable time")
|
||||
|
||||
max = Attribute("The latest representable time")
|
||||
|
||||
resolution = Attribute(
|
||||
"The smallest possible difference between non-equal time objects")
|
||||
|
||||
|
||||
class ITime(ITimeClass):
|
||||
"""Represent time with time zone.
|
||||
|
||||
Implemented by `datetime.time`.
|
||||
|
||||
Operators:
|
||||
|
||||
__repr__, __str__
|
||||
__cmp__, __hash__
|
||||
"""
|
||||
|
||||
hour = Attribute("Hour in range(24)")
|
||||
|
||||
minute = Attribute("Minute in range(60)")
|
||||
|
||||
second = Attribute("Second in range(60)")
|
||||
|
||||
microsecond = Attribute("Microsecond in range(1000000)")
|
||||
|
||||
tzinfo = Attribute(
|
||||
"""The object passed as the tzinfo argument to the time constructor
|
||||
or None if none was passed.""")
|
||||
|
||||
def replace(hour, minute, second, microsecond, tzinfo):
|
||||
"""Return a time with the same value.
|
||||
|
||||
Except for those members given new values by whichever keyword
|
||||
arguments are specified. Note that tzinfo=None can be specified
|
||||
to create a naive time from an aware time, without conversion of the
|
||||
time members.
|
||||
"""
|
||||
|
||||
def isoformat():
|
||||
"""Return a string representing the time in ISO 8601 format.
|
||||
|
||||
That is HH:MM:SS.mmmmmm or, if self.microsecond is 0, HH:MM:SS
|
||||
If utcoffset() does not return None, a 6-character string is appended,
|
||||
giving the UTC offset in (signed) hours and minutes:
|
||||
HH:MM:SS.mmmmmm+HH:MM or, if self.microsecond is 0, HH:MM:SS+HH:MM
|
||||
"""
|
||||
|
||||
def __str__():
|
||||
"""For a time t, str(t) is equivalent to t.isoformat()."""
|
||||
|
||||
def strftime(format):
|
||||
"""Return a string representing the time.
|
||||
|
||||
This is controlled by an explicit format string.
|
||||
"""
|
||||
|
||||
def utcoffset():
|
||||
"""Return the timezone offset in minutes east of UTC (negative west of
|
||||
UTC).
|
||||
|
||||
If tzinfo is None, returns None, else returns
|
||||
self.tzinfo.utcoffset(None), and raises an exception if the latter
|
||||
doesn't return None or a timedelta object representing a whole number
|
||||
of minutes with magnitude less than one day.
|
||||
"""
|
||||
|
||||
def dst():
|
||||
"""Return 0 if DST is not in effect, or the DST offset (in minutes
|
||||
eastward) if DST is in effect.
|
||||
|
||||
If tzinfo is None, returns None, else returns self.tzinfo.dst(None),
|
||||
and raises an exception if the latter doesn't return None, or a
|
||||
timedelta object representing a whole number of minutes with
|
||||
magnitude less than one day.
|
||||
"""
|
||||
|
||||
def tzname():
|
||||
"""Return the timezone name.
|
||||
|
||||
If tzinfo is None, returns None, else returns self.tzinfo.tzname(None),
|
||||
or raises an exception if the latter doesn't return None or a string
|
||||
object.
|
||||
"""
|
||||
|
||||
|
||||
class ITZInfo(Interface):
|
||||
"""Time zone info class.
|
||||
"""
|
||||
|
||||
def utcoffset(dt):
|
||||
"""Return offset of local time from UTC, in minutes east of UTC.
|
||||
|
||||
If local time is west of UTC, this should be negative.
|
||||
Note that this is intended to be the total offset from UTC;
|
||||
for example, if a tzinfo object represents both time zone and DST
|
||||
adjustments, utcoffset() should return their sum. If the UTC offset
|
||||
isn't known, return None. Else the value returned must be a timedelta
|
||||
object specifying a whole number of minutes in the range -1439 to 1439
|
||||
inclusive (1440 = 24*60; the magnitude of the offset must be less
|
||||
than one day).
|
||||
"""
|
||||
|
||||
def dst(dt):
|
||||
"""Return the daylight saving time (DST) adjustment, in minutes east
|
||||
of UTC, or None if DST information isn't known.
|
||||
"""
|
||||
|
||||
def tzname(dt):
|
||||
"""Return the time zone name corresponding to the datetime object as
|
||||
a string.
|
||||
"""
|
||||
|
||||
def fromutc(dt):
|
||||
"""Return an equivalent datetime in self's local time."""
|
||||
|
||||
|
||||
classImplements(timedelta, ITimeDelta)
|
||||
classImplements(date, IDate)
|
||||
classImplements(datetime, IDateTime)
|
||||
classImplements(time, ITime)
|
||||
classImplements(tzinfo, ITZInfo)
|
||||
|
||||
## directlyProvides(timedelta, ITimeDeltaClass)
|
||||
## directlyProvides(date, IDateClass)
|
||||
## directlyProvides(datetime, IDateTimeClass)
|
||||
## directlyProvides(time, ITimeClass)
|
||||
@@ -0,0 +1,208 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2003 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.
|
||||
#
|
||||
##############################################################################
|
||||
"""Interfaces for standard python exceptions
|
||||
"""
|
||||
from zope.interface import Interface
|
||||
from zope.interface import classImplements
|
||||
|
||||
class IException(Interface):
|
||||
"Interface for `Exception`"
|
||||
classImplements(Exception, IException)
|
||||
|
||||
|
||||
class IStandardError(IException):
|
||||
"Interface for `StandardError` (no longer existing.)"
|
||||
|
||||
|
||||
class IWarning(IException):
|
||||
"Interface for `Warning`"
|
||||
classImplements(Warning, IWarning)
|
||||
|
||||
|
||||
class ISyntaxError(IStandardError):
|
||||
"Interface for `SyntaxError`"
|
||||
classImplements(SyntaxError, ISyntaxError)
|
||||
|
||||
|
||||
class ILookupError(IStandardError):
|
||||
"Interface for `LookupError`"
|
||||
classImplements(LookupError, ILookupError)
|
||||
|
||||
|
||||
class IValueError(IStandardError):
|
||||
"Interface for `ValueError`"
|
||||
classImplements(ValueError, IValueError)
|
||||
|
||||
|
||||
class IRuntimeError(IStandardError):
|
||||
"Interface for `RuntimeError`"
|
||||
classImplements(RuntimeError, IRuntimeError)
|
||||
|
||||
|
||||
class IArithmeticError(IStandardError):
|
||||
"Interface for `ArithmeticError`"
|
||||
classImplements(ArithmeticError, IArithmeticError)
|
||||
|
||||
|
||||
class IAssertionError(IStandardError):
|
||||
"Interface for `AssertionError`"
|
||||
classImplements(AssertionError, IAssertionError)
|
||||
|
||||
|
||||
class IAttributeError(IStandardError):
|
||||
"Interface for `AttributeError`"
|
||||
classImplements(AttributeError, IAttributeError)
|
||||
|
||||
|
||||
class IDeprecationWarning(IWarning):
|
||||
"Interface for `DeprecationWarning`"
|
||||
classImplements(DeprecationWarning, IDeprecationWarning)
|
||||
|
||||
|
||||
class IEOFError(IStandardError):
|
||||
"Interface for `EOFError`"
|
||||
classImplements(EOFError, IEOFError)
|
||||
|
||||
|
||||
class IEnvironmentError(IStandardError):
|
||||
"Interface for `EnvironmentError`"
|
||||
classImplements(EnvironmentError, IEnvironmentError)
|
||||
|
||||
|
||||
class IFloatingPointError(IArithmeticError):
|
||||
"Interface for `FloatingPointError`"
|
||||
classImplements(FloatingPointError, IFloatingPointError)
|
||||
|
||||
|
||||
class IIOError(IEnvironmentError):
|
||||
"Interface for `IOError`"
|
||||
classImplements(IOError, IIOError)
|
||||
|
||||
|
||||
class IImportError(IStandardError):
|
||||
"Interface for `ImportError`"
|
||||
classImplements(ImportError, IImportError)
|
||||
|
||||
|
||||
class IIndentationError(ISyntaxError):
|
||||
"Interface for `IndentationError`"
|
||||
classImplements(IndentationError, IIndentationError)
|
||||
|
||||
|
||||
class IIndexError(ILookupError):
|
||||
"Interface for `IndexError`"
|
||||
classImplements(IndexError, IIndexError)
|
||||
|
||||
|
||||
class IKeyError(ILookupError):
|
||||
"Interface for `KeyError`"
|
||||
classImplements(KeyError, IKeyError)
|
||||
|
||||
|
||||
class IKeyboardInterrupt(IStandardError):
|
||||
"Interface for `KeyboardInterrupt`"
|
||||
classImplements(KeyboardInterrupt, IKeyboardInterrupt)
|
||||
|
||||
|
||||
class IMemoryError(IStandardError):
|
||||
"Interface for `MemoryError`"
|
||||
classImplements(MemoryError, IMemoryError)
|
||||
|
||||
|
||||
class INameError(IStandardError):
|
||||
"Interface for `NameError`"
|
||||
classImplements(NameError, INameError)
|
||||
|
||||
|
||||
class INotImplementedError(IRuntimeError):
|
||||
"Interface for `NotImplementedError`"
|
||||
classImplements(NotImplementedError, INotImplementedError)
|
||||
|
||||
|
||||
class IOSError(IEnvironmentError):
|
||||
"Interface for `OSError`"
|
||||
classImplements(OSError, IOSError)
|
||||
|
||||
|
||||
class IOverflowError(IArithmeticError):
|
||||
"Interface for `ArithmeticError`"
|
||||
classImplements(OverflowError, IOverflowError)
|
||||
|
||||
|
||||
class IOverflowWarning(IWarning):
|
||||
"""Deprecated, no standard class implements this.
|
||||
|
||||
This was the interface for ``OverflowWarning`` prior to Python 2.5,
|
||||
but that class was removed for all versions after that.
|
||||
"""
|
||||
|
||||
|
||||
class IReferenceError(IStandardError):
|
||||
"Interface for `ReferenceError`"
|
||||
classImplements(ReferenceError, IReferenceError)
|
||||
|
||||
|
||||
class IRuntimeWarning(IWarning):
|
||||
"Interface for `RuntimeWarning`"
|
||||
classImplements(RuntimeWarning, IRuntimeWarning)
|
||||
|
||||
|
||||
class IStopIteration(IException):
|
||||
"Interface for `StopIteration`"
|
||||
classImplements(StopIteration, IStopIteration)
|
||||
|
||||
|
||||
class ISyntaxWarning(IWarning):
|
||||
"Interface for `SyntaxWarning`"
|
||||
classImplements(SyntaxWarning, ISyntaxWarning)
|
||||
|
||||
|
||||
class ISystemError(IStandardError):
|
||||
"Interface for `SystemError`"
|
||||
classImplements(SystemError, ISystemError)
|
||||
|
||||
|
||||
class ISystemExit(IException):
|
||||
"Interface for `SystemExit`"
|
||||
classImplements(SystemExit, ISystemExit)
|
||||
|
||||
|
||||
class ITabError(IIndentationError):
|
||||
"Interface for `TabError`"
|
||||
classImplements(TabError, ITabError)
|
||||
|
||||
|
||||
class ITypeError(IStandardError):
|
||||
"Interface for `TypeError`"
|
||||
classImplements(TypeError, ITypeError)
|
||||
|
||||
|
||||
class IUnboundLocalError(INameError):
|
||||
"Interface for `UnboundLocalError`"
|
||||
classImplements(UnboundLocalError, IUnboundLocalError)
|
||||
|
||||
|
||||
class IUnicodeError(IValueError):
|
||||
"Interface for `UnicodeError`"
|
||||
classImplements(UnicodeError, IUnicodeError)
|
||||
|
||||
|
||||
class IUserWarning(IWarning):
|
||||
"Interface for `UserWarning`"
|
||||
classImplements(UserWarning, IUserWarning)
|
||||
|
||||
|
||||
class IZeroDivisionError(IArithmeticError):
|
||||
"Interface for `ZeroDivisionError`"
|
||||
classImplements(ZeroDivisionError, IZeroDivisionError)
|
||||
@@ -0,0 +1,43 @@
|
||||
##############################################################################
|
||||
# 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
|
||||
"""
|
||||
|
||||
import io as abc
|
||||
|
||||
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 = ()
|
||||
|
||||
|
||||
class ITextIOBase(IIOBase):
|
||||
abc = abc.TextIOBase
|
||||
@@ -0,0 +1,168 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2001, 2002 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.
|
||||
#
|
||||
##############################################################################
|
||||
"""
|
||||
Mapping Interfaces.
|
||||
|
||||
Importing this module does *not* mark any standard classes as
|
||||
implementing any of these interfaces.
|
||||
|
||||
While this module is not deprecated, new code should generally use
|
||||
:mod:`zope.interface.common.collections`, specifically
|
||||
:class:`~zope.interface.common.collections.IMapping` and
|
||||
:class:`~zope.interface.common.collections.IMutableMapping`. This
|
||||
module is occasionally useful for its extremely fine grained breakdown
|
||||
of interfaces.
|
||||
|
||||
The standard library :class:`dict` and :class:`collections.UserDict`
|
||||
implement ``IMutableMapping``, but *do not* implement any of the
|
||||
interfaces in this module.
|
||||
"""
|
||||
from zope.interface import Interface
|
||||
from zope.interface.common import collections
|
||||
|
||||
class IItemMapping(Interface):
|
||||
"""Simplest readable mapping object
|
||||
"""
|
||||
|
||||
def __getitem__(key):
|
||||
"""Get a value for a key
|
||||
|
||||
A `KeyError` is raised if there is no value for the key.
|
||||
"""
|
||||
|
||||
|
||||
class IReadMapping(collections.IContainer, IItemMapping):
|
||||
"""
|
||||
Basic mapping interface.
|
||||
|
||||
.. versionchanged:: 5.0.0
|
||||
Extend ``IContainer``
|
||||
"""
|
||||
|
||||
def get(key, default=None):
|
||||
"""Get a value for a key
|
||||
|
||||
The default is returned if there is no value for the key.
|
||||
"""
|
||||
|
||||
def __contains__(key):
|
||||
"""Tell if a key exists in the mapping."""
|
||||
# Optional in IContainer, required by this interface.
|
||||
|
||||
|
||||
class IWriteMapping(Interface):
|
||||
"""Mapping methods for changing data"""
|
||||
|
||||
def __delitem__(key):
|
||||
"""Delete a value from the mapping using the key."""
|
||||
|
||||
def __setitem__(key, value):
|
||||
"""Set a new item in the mapping."""
|
||||
|
||||
|
||||
class IEnumerableMapping(collections.ISized, IReadMapping):
|
||||
"""
|
||||
Mapping objects whose items can be enumerated.
|
||||
|
||||
.. versionchanged:: 5.0.0
|
||||
Extend ``ISized``
|
||||
"""
|
||||
|
||||
def keys():
|
||||
"""Return the keys of the mapping object.
|
||||
"""
|
||||
|
||||
def __iter__():
|
||||
"""Return an iterator for the keys of the mapping object.
|
||||
"""
|
||||
|
||||
def values():
|
||||
"""Return the values of the mapping object.
|
||||
"""
|
||||
|
||||
def items():
|
||||
"""Return the items of the mapping object.
|
||||
"""
|
||||
|
||||
class IMapping(IWriteMapping, IEnumerableMapping):
|
||||
''' Simple mapping interface '''
|
||||
|
||||
class IIterableMapping(IEnumerableMapping):
|
||||
"""A mapping that has distinct methods for iterating
|
||||
without copying.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class IClonableMapping(Interface):
|
||||
"""Something that can produce a copy of itself.
|
||||
|
||||
This is available in `dict`.
|
||||
"""
|
||||
|
||||
def copy():
|
||||
"return copy of dict"
|
||||
|
||||
class IExtendedReadMapping(IIterableMapping):
|
||||
"""
|
||||
Something with a particular method equivalent to ``__contains__``.
|
||||
|
||||
On Python 2, `dict` provided the ``has_key`` method, but it was removed
|
||||
in Python 3.
|
||||
"""
|
||||
|
||||
|
||||
class IExtendedWriteMapping(IWriteMapping):
|
||||
"""Additional mutation methods.
|
||||
|
||||
These are all provided by `dict`.
|
||||
"""
|
||||
|
||||
def clear():
|
||||
"delete all items"
|
||||
|
||||
def update(d):
|
||||
" Update D from E: for k in E.keys(): D[k] = E[k]"
|
||||
|
||||
def setdefault(key, default=None):
|
||||
"D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D"
|
||||
|
||||
def pop(k, default=None):
|
||||
"""
|
||||
pop(k[,default]) -> value
|
||||
|
||||
Remove specified key and return the corresponding value.
|
||||
|
||||
If key is not found, *default* is returned if given, otherwise
|
||||
`KeyError` is raised. Note that *default* must not be passed by
|
||||
name.
|
||||
"""
|
||||
|
||||
def popitem():
|
||||
"""remove and return some (key, value) pair as a
|
||||
2-tuple; but raise KeyError if mapping is empty"""
|
||||
|
||||
class IFullMapping(
|
||||
collections.IMutableMapping,
|
||||
IExtendedReadMapping, IExtendedWriteMapping, IClonableMapping, IMapping,):
|
||||
"""
|
||||
Full mapping interface.
|
||||
|
||||
Most uses of this interface should instead use
|
||||
:class:`~zope.interface.commons.collections.IMutableMapping` (one of the
|
||||
bases of this interface). The required methods are the same.
|
||||
|
||||
.. versionchanged:: 5.0.0
|
||||
Extend ``IMutableMapping``
|
||||
"""
|
||||
@@ -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.
|
||||
##############################################################################
|
||||
"""
|
||||
Interface definitions paralleling the abstract base classes defined in
|
||||
:mod:`numbers`.
|
||||
|
||||
After this module is imported, the standard library types will declare
|
||||
that they implement the appropriate interface.
|
||||
|
||||
.. versionadded:: 5.0.0
|
||||
"""
|
||||
|
||||
import numbers as abc
|
||||
|
||||
from zope.interface.common import ABCInterface
|
||||
from zope.interface.common import optional
|
||||
|
||||
|
||||
# pylint:disable=inherit-non-class,
|
||||
# pylint:disable=no-self-argument,no-method-argument
|
||||
# pylint:disable=unexpected-special-method-signature
|
||||
# pylint:disable=no-value-for-parameter
|
||||
|
||||
|
||||
class INumber(ABCInterface):
|
||||
abc = abc.Number
|
||||
|
||||
|
||||
class IComplex(INumber):
|
||||
abc = abc.Complex
|
||||
|
||||
@optional
|
||||
def __complex__():
|
||||
"""
|
||||
Rarely implemented, even in builtin types.
|
||||
"""
|
||||
|
||||
|
||||
class IReal(IComplex):
|
||||
abc = abc.Real
|
||||
|
||||
@optional
|
||||
def __complex__():
|
||||
"""
|
||||
Rarely implemented, even in builtin types.
|
||||
"""
|
||||
|
||||
__floor__ = __ceil__ = __complex__
|
||||
|
||||
|
||||
class IRational(IReal):
|
||||
abc = abc.Rational
|
||||
|
||||
|
||||
class IIntegral(IRational):
|
||||
abc = abc.Integral
|
||||
@@ -0,0 +1,189 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2001, 2002 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.
|
||||
#
|
||||
##############################################################################
|
||||
"""
|
||||
Sequence Interfaces
|
||||
|
||||
Importing this module does *not* mark any standard classes as
|
||||
implementing any of these interfaces.
|
||||
|
||||
While this module is not deprecated, new code should generally use
|
||||
:mod:`zope.interface.common.collections`, specifically
|
||||
:class:`~zope.interface.common.collections.ISequence` and
|
||||
:class:`~zope.interface.common.collections.IMutableSequence`. This
|
||||
module is occasionally useful for its fine-grained breakdown of interfaces.
|
||||
|
||||
The standard library :class:`list`, :class:`tuple` and
|
||||
:class:`collections.UserList`, among others, implement ``ISequence``
|
||||
or ``IMutableSequence`` but *do not* implement any of the interfaces
|
||||
in this module.
|
||||
"""
|
||||
|
||||
__docformat__ = 'restructuredtext'
|
||||
from zope.interface import Interface
|
||||
from zope.interface.common import collections
|
||||
|
||||
class IMinimalSequence(collections.IIterable):
|
||||
"""Most basic sequence interface.
|
||||
|
||||
All sequences are iterable. This requires at least one of the
|
||||
following:
|
||||
|
||||
- a `__getitem__()` method that takes a single argument; integer
|
||||
values starting at 0 must be supported, and `IndexError` should
|
||||
be raised for the first index for which there is no value, or
|
||||
|
||||
- an `__iter__()` method that returns an iterator as defined in
|
||||
the Python documentation (http://docs.python.org/lib/typeiter.html).
|
||||
|
||||
"""
|
||||
|
||||
def __getitem__(index):
|
||||
"""``x.__getitem__(index) <==> x[index]``
|
||||
|
||||
Declaring this interface does not specify whether `__getitem__`
|
||||
supports slice objects."""
|
||||
|
||||
class IFiniteSequence(collections.ISized, IMinimalSequence):
|
||||
"""
|
||||
A sequence of bound size.
|
||||
|
||||
.. versionchanged:: 5.0.0
|
||||
Extend ``ISized``
|
||||
"""
|
||||
|
||||
class IReadSequence(collections.IContainer, IFiniteSequence):
|
||||
"""
|
||||
read interface shared by tuple and list
|
||||
|
||||
This interface is similar to
|
||||
:class:`~zope.interface.common.collections.ISequence`, but
|
||||
requires that all instances be totally ordered. Most users
|
||||
should prefer ``ISequence``.
|
||||
|
||||
.. versionchanged:: 5.0.0
|
||||
Extend ``IContainer``
|
||||
"""
|
||||
|
||||
def __contains__(item):
|
||||
"""``x.__contains__(item) <==> item in x``"""
|
||||
# Optional in IContainer, required here.
|
||||
|
||||
def __lt__(other):
|
||||
"""``x.__lt__(other) <==> x < other``"""
|
||||
|
||||
def __le__(other):
|
||||
"""``x.__le__(other) <==> x <= other``"""
|
||||
|
||||
def __eq__(other):
|
||||
"""``x.__eq__(other) <==> x == other``"""
|
||||
|
||||
def __ne__(other):
|
||||
"""``x.__ne__(other) <==> x != other``"""
|
||||
|
||||
def __gt__(other):
|
||||
"""``x.__gt__(other) <==> x > other``"""
|
||||
|
||||
def __ge__(other):
|
||||
"""``x.__ge__(other) <==> x >= other``"""
|
||||
|
||||
def __add__(other):
|
||||
"""``x.__add__(other) <==> x + other``"""
|
||||
|
||||
def __mul__(n):
|
||||
"""``x.__mul__(n) <==> x * n``"""
|
||||
|
||||
def __rmul__(n):
|
||||
"""``x.__rmul__(n) <==> n * x``"""
|
||||
|
||||
|
||||
class IExtendedReadSequence(IReadSequence):
|
||||
"""Full read interface for lists"""
|
||||
|
||||
def count(item):
|
||||
"""Return number of occurrences of value"""
|
||||
|
||||
def index(item, *args):
|
||||
"""index(value, [start, [stop]]) -> int
|
||||
|
||||
Return first index of *value*
|
||||
"""
|
||||
|
||||
class IUniqueMemberWriteSequence(Interface):
|
||||
"""The write contract for a sequence that may enforce unique members"""
|
||||
|
||||
def __setitem__(index, item):
|
||||
"""``x.__setitem__(index, item) <==> x[index] = item``
|
||||
|
||||
Declaring this interface does not specify whether `__setitem__`
|
||||
supports slice objects.
|
||||
"""
|
||||
|
||||
def __delitem__(index):
|
||||
"""``x.__delitem__(index) <==> del x[index]``
|
||||
|
||||
Declaring this interface does not specify whether `__delitem__`
|
||||
supports slice objects.
|
||||
"""
|
||||
|
||||
def __iadd__(y):
|
||||
"""``x.__iadd__(y) <==> x += y``"""
|
||||
|
||||
def append(item):
|
||||
"""Append item to end"""
|
||||
|
||||
def insert(index, item):
|
||||
"""Insert item before index"""
|
||||
|
||||
def pop(index=-1):
|
||||
"""Remove and return item at index (default last)"""
|
||||
|
||||
def remove(item):
|
||||
"""Remove first occurrence of value"""
|
||||
|
||||
def reverse():
|
||||
"""Reverse *IN PLACE*"""
|
||||
|
||||
def sort(cmpfunc=None):
|
||||
"""Stable sort *IN PLACE*; `cmpfunc(x, y)` -> -1, 0, 1"""
|
||||
|
||||
def extend(iterable):
|
||||
"""Extend list by appending elements from the iterable"""
|
||||
|
||||
class IWriteSequence(IUniqueMemberWriteSequence):
|
||||
"""Full write contract for sequences"""
|
||||
|
||||
def __imul__(n):
|
||||
"""``x.__imul__(n) <==> x *= n``"""
|
||||
|
||||
class ISequence(IReadSequence, IWriteSequence):
|
||||
"""
|
||||
Full sequence contract.
|
||||
|
||||
New code should prefer
|
||||
:class:`~zope.interface.common.collections.IMutableSequence`.
|
||||
|
||||
Compared to that interface, which is implemented by :class:`list`
|
||||
(:class:`~zope.interface.common.builtins.IList`), among others,
|
||||
this interface is missing the following methods:
|
||||
|
||||
- clear
|
||||
|
||||
- count
|
||||
|
||||
- index
|
||||
|
||||
This interface adds the following methods:
|
||||
|
||||
- sort
|
||||
"""
|
||||
@@ -0,0 +1,136 @@
|
||||
##############################################################################
|
||||
# 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
|
||||
|
||||
from zope.interface.verify import verifyClass
|
||||
from zope.interface.verify import verifyObject
|
||||
|
||||
from zope.interface.common import ABCInterface
|
||||
from zope.interface.common import ABCInterfaceClass
|
||||
|
||||
|
||||
def iter_abc_interfaces(predicate=lambda iface: True):
|
||||
# Iterate ``(iface, classes)``, where ``iface`` is a descendent of
|
||||
# the ABCInterfaceClass passing the *predicate* and ``classes`` is
|
||||
# an iterable of classes registered to conform to that interface.
|
||||
#
|
||||
# Note that some builtin classes are registered for two distinct
|
||||
# parts of the ABC/interface tree. For example, bytearray is both ByteString
|
||||
# and MutableSequence.
|
||||
seen = set()
|
||||
stack = list(ABCInterface.dependents) # subclasses, but also implementedBy objects
|
||||
while stack:
|
||||
iface = stack.pop(0)
|
||||
if iface in seen or not isinstance(iface, ABCInterfaceClass):
|
||||
continue
|
||||
seen.add(iface)
|
||||
stack.extend(list(iface.dependents))
|
||||
if not predicate(iface):
|
||||
continue
|
||||
|
||||
registered = set(iface.getRegisteredConformers())
|
||||
registered -= set(iface._ABCInterfaceClass__ignored_classes)
|
||||
if registered:
|
||||
yield iface, registered
|
||||
|
||||
|
||||
def add_abc_interface_tests(cls, module):
|
||||
def predicate(iface):
|
||||
return iface.__module__ == module
|
||||
add_verify_tests(cls, iter_abc_interfaces(predicate))
|
||||
|
||||
|
||||
def add_verify_tests(cls, iface_classes_iter):
|
||||
cls.maxDiff = None
|
||||
for iface, registered_classes in iface_classes_iter:
|
||||
for stdlib_class in registered_classes:
|
||||
def test(self, stdlib_class=stdlib_class, iface=iface):
|
||||
if stdlib_class in self.UNVERIFIABLE or stdlib_class.__name__ in self.UNVERIFIABLE:
|
||||
self.skipTest("Unable to verify %s" % stdlib_class)
|
||||
|
||||
self.assertTrue(self.verify(iface, stdlib_class))
|
||||
|
||||
suffix = "{}_{}_{}_{}".format(
|
||||
stdlib_class.__module__.replace('.', '_'),
|
||||
stdlib_class.__name__,
|
||||
iface.__module__.replace('.', '_'),
|
||||
iface.__name__
|
||||
)
|
||||
name = 'test_auto_' + suffix
|
||||
test.__name__ = name
|
||||
assert not hasattr(cls, name), (name, list(cls.__dict__))
|
||||
setattr(cls, name, test)
|
||||
|
||||
def test_ro(self, stdlib_class=stdlib_class, iface=iface):
|
||||
from zope.interface import ro
|
||||
from zope.interface import implementedBy
|
||||
from zope.interface import Interface
|
||||
self.assertEqual(
|
||||
tuple(ro.ro(iface, strict=True)),
|
||||
iface.__sro__)
|
||||
implements = implementedBy(stdlib_class)
|
||||
sro = implements.__sro__
|
||||
self.assertIs(sro[-1], Interface)
|
||||
|
||||
if stdlib_class not in self.UNVERIFIABLE_RO:
|
||||
# Check that we got the strict C3 resolution order, unless
|
||||
# we know we cannot. Note that 'Interface' is virtual base
|
||||
# that doesn't necessarily appear at the same place in the
|
||||
# calculated SRO as in the final SRO.
|
||||
strict = stdlib_class not in self.NON_STRICT_RO
|
||||
isro = ro.ro(implements, strict=strict)
|
||||
isro.remove(Interface)
|
||||
isro.append(Interface)
|
||||
|
||||
self.assertEqual(tuple(isro), sro)
|
||||
|
||||
name = 'test_auto_ro_' + suffix
|
||||
test_ro.__name__ = name
|
||||
assert not hasattr(cls, name)
|
||||
setattr(cls, name, test_ro)
|
||||
|
||||
class VerifyClassMixin(unittest.TestCase):
|
||||
verifier = staticmethod(verifyClass)
|
||||
UNVERIFIABLE = ()
|
||||
NON_STRICT_RO = ()
|
||||
UNVERIFIABLE_RO = ()
|
||||
|
||||
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):
|
||||
constructor = self.CONSTRUCTORS.get(x)
|
||||
if not constructor:
|
||||
constructor = self.CONSTRUCTORS.get(iface)
|
||||
if not constructor:
|
||||
constructor = self.CONSTRUCTORS.get(x.__name__)
|
||||
if not constructor:
|
||||
constructor = x
|
||||
if constructor is unittest.SkipTest:
|
||||
self.skipTest("Cannot create " + str(x))
|
||||
|
||||
result = constructor()
|
||||
if hasattr(result, 'close'):
|
||||
self.addCleanup(result.close)
|
||||
return result
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,107 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2001, 2002 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.
|
||||
#
|
||||
##############################################################################
|
||||
"""Base Mapping tests
|
||||
"""
|
||||
from operator import __getitem__
|
||||
|
||||
def testIReadMapping(self, inst, state, absent):
|
||||
for key in state:
|
||||
self.assertEqual(inst[key], state[key])
|
||||
self.assertEqual(inst.get(key, None), state[key])
|
||||
self.assertTrue(key in inst)
|
||||
|
||||
for key in absent:
|
||||
self.assertEqual(inst.get(key, None), None)
|
||||
self.assertEqual(inst.get(key), None)
|
||||
self.assertEqual(inst.get(key, self), self)
|
||||
self.assertRaises(KeyError, __getitem__, inst, key)
|
||||
|
||||
|
||||
def test_keys(self, inst, state):
|
||||
# Return the keys of the mapping object
|
||||
inst_keys = list(inst.keys()); inst_keys.sort()
|
||||
state_keys = list(state.keys()) ; state_keys.sort()
|
||||
self.assertEqual(inst_keys, state_keys)
|
||||
|
||||
def test_iter(self, inst, state):
|
||||
# Return the keys of the mapping object
|
||||
inst_keys = list(inst); inst_keys.sort()
|
||||
state_keys = list(state.keys()) ; state_keys.sort()
|
||||
self.assertEqual(inst_keys, state_keys)
|
||||
|
||||
def test_values(self, inst, state):
|
||||
# Return the values of the mapping object
|
||||
inst_values = list(inst.values()); inst_values.sort()
|
||||
state_values = list(state.values()) ; state_values.sort()
|
||||
self.assertEqual(inst_values, state_values)
|
||||
|
||||
def test_items(self, inst, state):
|
||||
# Return the items of the mapping object
|
||||
inst_items = list(inst.items()); inst_items.sort()
|
||||
state_items = list(state.items()) ; state_items.sort()
|
||||
self.assertEqual(inst_items, state_items)
|
||||
|
||||
def test___len__(self, inst, state):
|
||||
# Return the number of items
|
||||
self.assertEqual(len(inst), len(state))
|
||||
|
||||
def testIEnumerableMapping(self, inst, state):
|
||||
test_keys(self, inst, state)
|
||||
test_items(self, inst, state)
|
||||
test_values(self, inst, state)
|
||||
test___len__(self, inst, state)
|
||||
|
||||
|
||||
class BaseTestIReadMapping:
|
||||
def testIReadMapping(self):
|
||||
inst = self._IReadMapping__sample()
|
||||
state = self._IReadMapping__stateDict()
|
||||
absent = self._IReadMapping__absentKeys()
|
||||
testIReadMapping(self, inst, state, absent)
|
||||
|
||||
|
||||
class BaseTestIEnumerableMapping(BaseTestIReadMapping):
|
||||
# Mapping objects whose items can be enumerated
|
||||
def test_keys(self):
|
||||
# Return the keys of the mapping object
|
||||
inst = self._IEnumerableMapping__sample()
|
||||
state = self._IEnumerableMapping__stateDict()
|
||||
test_keys(self, inst, state)
|
||||
|
||||
def test_values(self):
|
||||
# Return the values of the mapping object
|
||||
inst = self._IEnumerableMapping__sample()
|
||||
state = self._IEnumerableMapping__stateDict()
|
||||
test_values(self, inst, state)
|
||||
|
||||
def test_items(self):
|
||||
# Return the items of the mapping object
|
||||
inst = self._IEnumerableMapping__sample()
|
||||
state = self._IEnumerableMapping__stateDict()
|
||||
test_items(self, inst, state)
|
||||
|
||||
def test___len__(self):
|
||||
# Return the number of items
|
||||
inst = self._IEnumerableMapping__sample()
|
||||
state = self._IEnumerableMapping__stateDict()
|
||||
test___len__(self, inst, state)
|
||||
|
||||
def _IReadMapping__stateDict(self):
|
||||
return self._IEnumerableMapping__stateDict()
|
||||
|
||||
def _IReadMapping__sample(self):
|
||||
return self._IEnumerableMapping__sample()
|
||||
|
||||
def _IReadMapping__absentKeys(self):
|
||||
return self._IEnumerableMapping__absentKeys()
|
||||
@@ -0,0 +1,43 @@
|
||||
##############################################################################
|
||||
# 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
|
||||
|
||||
from zope.interface.common import builtins
|
||||
|
||||
from . import VerifyClassMixin
|
||||
from . import VerifyObjectMixin
|
||||
from . import add_verify_tests
|
||||
|
||||
|
||||
class TestVerifyClass(VerifyClassMixin,
|
||||
unittest.TestCase):
|
||||
pass
|
||||
|
||||
|
||||
add_verify_tests(TestVerifyClass, (
|
||||
(builtins.IList, (list,)),
|
||||
(builtins.ITuple, (tuple,)),
|
||||
(builtins.ITextString, (str,)),
|
||||
(builtins.IByteString, (bytes,)),
|
||||
(builtins.INativeString, (str,)),
|
||||
(builtins.IBool, (bool,)),
|
||||
(builtins.IDict, (dict,)),
|
||||
(builtins.IFile, ()),
|
||||
))
|
||||
|
||||
|
||||
class TestVerifyObject(VerifyObjectMixin,
|
||||
TestVerifyClass):
|
||||
CONSTRUCTORS = {
|
||||
builtins.IFile: lambda: open(__file__)
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
##############################################################################
|
||||
# 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 array
|
||||
import unittest
|
||||
from collections import abc
|
||||
from collections import deque
|
||||
from collections import OrderedDict
|
||||
|
||||
|
||||
from types import MappingProxyType
|
||||
|
||||
from zope.interface import Invalid
|
||||
|
||||
|
||||
# Note that importing z.i.c.collections does work on import.
|
||||
from zope.interface.common import collections
|
||||
|
||||
|
||||
from zope.interface._compat import PYPY
|
||||
|
||||
|
||||
from . import add_abc_interface_tests
|
||||
from . import VerifyClassMixin
|
||||
from . import VerifyObjectMixin
|
||||
|
||||
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.
|
||||
def test_frozenset(self):
|
||||
self.assertIsInstance(frozenset(), abc.Set)
|
||||
self.assertTrue(self.verify(collections.ISet, frozenset))
|
||||
|
||||
def test_list(self):
|
||||
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))
|
||||
|
||||
# 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
|
||||
# about third-party code here, just standard library types. We start with a
|
||||
# blacklist of things to exclude, but if that gets out of hand we can figure
|
||||
# out a better whitelisting.
|
||||
UNVERIFIABLE = {
|
||||
# This is declared to be an ISequence, but is missing lots of methods,
|
||||
# including some that aren't part of a language protocol, such as
|
||||
# ``index`` and ``count``.
|
||||
memoryview,
|
||||
# 'pkg_resources._vendor.pyparsing.ParseResults' is registered as a
|
||||
# MutableMapping but is missing methods like ``popitem`` and ``setdefault``.
|
||||
# It's imported due to namespace packages.
|
||||
'ParseResults',
|
||||
# sqlite3.Row claims ISequence but also misses ``index`` and ``count``.
|
||||
# It's imported because...? Coverage imports it, but why do we have it without
|
||||
# coverage?
|
||||
'Row',
|
||||
# In Python 3.10 ``array.array`` appears as ``IMutableSequence`` but it
|
||||
# does not provide a ``clear()`` method and it cannot be instantiated
|
||||
# using ``array.array()``.
|
||||
array.array,
|
||||
}
|
||||
|
||||
if PYPY:
|
||||
UNVERIFIABLE.update({
|
||||
# collections.deque.pop() doesn't support the index= argument to
|
||||
# MutableSequence.pop(). We can't verify this on CPython because we can't
|
||||
# get the signature, but on PyPy we /can/ get the signature, and of course
|
||||
# it doesn't match.
|
||||
deque,
|
||||
# Likewise for index
|
||||
range,
|
||||
})
|
||||
UNVERIFIABLE_RO = {
|
||||
# ``array.array`` fails the ``test_auto_ro_*`` tests with and
|
||||
# without strict RO but only on Windows (AppVeyor) on Python 3.10.0
|
||||
# (in older versions ``array.array`` does not appear as
|
||||
# ``IMutableSequence``).
|
||||
array.array,
|
||||
}
|
||||
|
||||
add_abc_interface_tests(TestVerifyClass, collections.ISet.__module__)
|
||||
|
||||
|
||||
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({}),
|
||||
collections.UserString: lambda: collections.UserString('abc'),
|
||||
type(iter(bytearray())): lambda: iter(bytearray()),
|
||||
type(iter(b'abc')): lambda: iter(b'abc'),
|
||||
'coroutine': unittest.SkipTest,
|
||||
type(iter({}.keys())): lambda: iter({}.keys()),
|
||||
type(iter({}.items())): lambda: iter({}.items()),
|
||||
type(iter({}.values())): lambda: iter({}.values()),
|
||||
type(i for i in range(1)): lambda: (i for i in range(3)),
|
||||
type(iter([])): lambda: iter([]),
|
||||
type(reversed([])): lambda: reversed([]),
|
||||
'longrange_iterator': unittest.SkipTest,
|
||||
'range_iterator': lambda: iter(range(3)),
|
||||
'rangeiterator': lambda: iter(range(3)),
|
||||
type(iter(set())): lambda: iter(set()),
|
||||
type(iter('')): lambda: iter(''),
|
||||
'async_generator': unittest.SkipTest,
|
||||
type(iter(tuple())): lambda: iter(tuple()),
|
||||
}
|
||||
|
||||
UNVERIFIABLE_RO = {
|
||||
# ``array.array`` fails the ``test_auto_ro_*`` tests with and
|
||||
# without strict RO but only on Windows (AppVeyor) on Python 3.10.0
|
||||
# (in older versions ``array.array`` does not appear as
|
||||
# ``IMutableSequence``).
|
||||
array.array,
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2003 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.
|
||||
#
|
||||
##############################################################################
|
||||
"""Test for datetime interfaces
|
||||
"""
|
||||
|
||||
import unittest
|
||||
|
||||
from zope.interface.verify import verifyObject, verifyClass
|
||||
from zope.interface.common.idatetime import ITimeDelta, ITimeDeltaClass
|
||||
from zope.interface.common.idatetime import IDate, IDateClass
|
||||
from zope.interface.common.idatetime import IDateTime, IDateTimeClass
|
||||
from zope.interface.common.idatetime import ITime, ITimeClass, ITZInfo
|
||||
from datetime import timedelta, date, datetime, time, tzinfo
|
||||
|
||||
class TestDateTimeInterfaces(unittest.TestCase):
|
||||
|
||||
def test_interfaces(self):
|
||||
verifyObject(ITimeDelta, timedelta(minutes=20))
|
||||
verifyObject(IDate, date(2000, 1, 2))
|
||||
verifyObject(IDateTime, datetime(2000, 1, 2, 10, 20))
|
||||
verifyObject(ITime, time(20, 30, 15, 1234))
|
||||
verifyObject(ITZInfo, tzinfo())
|
||||
verifyClass(ITimeDeltaClass, timedelta)
|
||||
verifyClass(IDateClass, date)
|
||||
verifyClass(IDateTimeClass, datetime)
|
||||
verifyClass(ITimeClass, time)
|
||||
@@ -0,0 +1,20 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2006 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
|
||||
|
||||
class TestInterfaceImport(unittest.TestCase):
|
||||
|
||||
def test_import(self):
|
||||
import zope.interface.common.interfaces as x
|
||||
self.assertIsNotNone(x)
|
||||
@@ -0,0 +1,42 @@
|
||||
##############################################################################
|
||||
# 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__),
|
||||
'_WindowsConsoleIO': unittest.SkipTest,
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
##############################################################################
|
||||
# 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 numbers as abc
|
||||
|
||||
# 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(VerifyClassMixin,
|
||||
unittest.TestCase):
|
||||
|
||||
def test_int(self):
|
||||
self.assertIsInstance(int(), abc.Integral)
|
||||
self.assertTrue(self.verify(numbers.IIntegral, int))
|
||||
|
||||
def test_float(self):
|
||||
self.assertIsInstance(float(), abc.Real)
|
||||
self.assertTrue(self.verify(numbers.IReal, float))
|
||||
|
||||
add_abc_interface_tests(TestVerifyClass, numbers.INumber.__module__)
|
||||
|
||||
|
||||
class TestVerifyObject(VerifyObjectMixin,
|
||||
TestVerifyClass):
|
||||
pass
|
||||
Reference in New Issue
Block a user