test_collections.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. ##############################################################################
  2. # Copyright (c) 2020 Zope Foundation and Contributors.
  3. # All Rights Reserved.
  4. #
  5. # This software is subject to the provisions of the Zope Public License,
  6. # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
  7. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
  8. # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  9. # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
  10. # FOR A PARTICULAR PURPOSE.
  11. ##############################################################################
  12. import array
  13. import sys
  14. import unittest
  15. from collections import OrderedDict
  16. from collections import abc
  17. from collections import deque
  18. from types import MappingProxyType
  19. from zope.interface import Invalid
  20. from zope.interface._compat import PYPY
  21. # Note that importing z.i.c.collections does work on import.
  22. from zope.interface.common import collections
  23. from . import VerifyClassMixin
  24. from . import VerifyObjectMixin
  25. from . import add_abc_interface_tests
  26. class TestVerifyClass(VerifyClassMixin, unittest.TestCase):
  27. # Here we test some known builtin classes that are defined to implement
  28. # various collection interfaces as a quick sanity test.
  29. def test_frozenset(self):
  30. self.assertIsInstance(frozenset(), abc.Set)
  31. self.assertTrue(self.verify(collections.ISet, frozenset))
  32. def test_list(self):
  33. self.assertIsInstance(list(), abc.MutableSequence)
  34. self.assertTrue(self.verify(collections.IMutableSequence, list))
  35. # Here we test some derived classes.
  36. def test_UserList(self):
  37. self.assertTrue(self.verify(collections.IMutableSequence,
  38. collections.UserList))
  39. def test_UserDict(self):
  40. self.assertTrue(self.verify(collections.IMutableMapping,
  41. collections.UserDict))
  42. def test_UserString(self):
  43. self.assertTrue(self.verify(collections.ISequence,
  44. collections.UserString))
  45. # Now we go through the registry, which should have several things, mostly
  46. # builtins, but if we've imported other libraries already, it could
  47. # contain things from outside of there too. We aren't concerned about
  48. # third-party code here, just standard library types. We start with a
  49. # blacklist of things to exclude, but if that gets out of hand we can
  50. # figure out a better whitelisting.
  51. UNVERIFIABLE = {
  52. # This is declared to be an ISequence, but is missing lots of methods,
  53. # including some that aren't part of a language protocol, such as
  54. # ``index`` and ``count``.
  55. memoryview,
  56. # 'pkg_resources._vendor.pyparsing.ParseResults' is registered as a
  57. # MutableMapping but is missing methods like ``popitem`` and
  58. # ``setdefault``. It's imported due to namespace packages.
  59. 'ParseResults',
  60. # sqlite3.Row claims ISequence but also misses ``index`` and
  61. # ``count``. It's imported because...? Coverage imports it, but why
  62. # do we have it without coverage?
  63. 'Row',
  64. # In Python 3.10 ``array.array`` appears as ``IMutableSequence`` but it
  65. # does not provide a ``clear()`` method and it cannot be instantiated
  66. # using ``array.array()``.
  67. array.array,
  68. }
  69. if PYPY:
  70. UNVERIFIABLE.update({
  71. # collections.deque.pop() doesn't support the index= argument to
  72. # MutableSequence.pop(). We can't verify this on CPython because
  73. # we can't get the signature, but on PyPy we /can/ get the
  74. # signature, and of course it doesn't match.
  75. deque,
  76. # Likewise for index
  77. range,
  78. })
  79. UNVERIFIABLE_RO = {
  80. # ``array.array`` fails the ``test_auto_ro_*`` tests with and
  81. # without strict RO but only on Windows (AppVeyor) on Python 3.10.0
  82. # (in older versions ``array.array`` does not appear as
  83. # ``IMutableSequence``).
  84. array.array,
  85. }
  86. add_abc_interface_tests(TestVerifyClass, collections.ISet.__module__)
  87. def _get_FrameLocalsProxy():
  88. return type(sys._getframe().f_locals)
  89. class TestVerifyObject(VerifyObjectMixin,
  90. TestVerifyClass):
  91. CONSTRUCTORS = {
  92. collections.IValuesView: {}.values,
  93. collections.IItemsView: {}.items,
  94. collections.IKeysView: {}.keys,
  95. memoryview: lambda: memoryview(b'abc'),
  96. range: lambda: range(10),
  97. MappingProxyType: lambda: MappingProxyType({}),
  98. collections.UserString: lambda: collections.UserString('abc'),
  99. type(iter(bytearray())): lambda: iter(bytearray()),
  100. type(iter(b'abc')): lambda: iter(b'abc'),
  101. 'coroutine': unittest.SkipTest,
  102. type(iter({}.keys())): lambda: iter({}.keys()),
  103. type(iter({}.items())): lambda: iter({}.items()),
  104. type(iter({}.values())): lambda: iter({}.values()),
  105. type(i for i in range(1)): lambda: (i for i in range(3)),
  106. type(iter([])): lambda: iter([]),
  107. type(reversed([])): lambda: reversed([]),
  108. 'longrange_iterator': unittest.SkipTest,
  109. 'range_iterator': lambda: iter(range(3)),
  110. 'rangeiterator': lambda: iter(range(3)),
  111. type(iter(set())): lambda: iter(set()),
  112. type(iter('')): lambda: iter(''),
  113. 'async_generator': unittest.SkipTest,
  114. type(iter(tuple())): lambda: iter(tuple()),
  115. }
  116. if sys.version_info >= (3, 13):
  117. def FrameLocalsProxy_constructor():
  118. return _get_FrameLocalsProxy()(sys._getframe())
  119. FrameLocalsProxy = _get_FrameLocalsProxy()
  120. CONSTRUCTORS[FrameLocalsProxy] = FrameLocalsProxy_constructor
  121. UNVERIFIABLE_RO = {
  122. # ``array.array`` fails the ``test_auto_ro_*`` tests with and
  123. # without strict RO but only on Windows (AppVeyor) on Python 3.10.0
  124. # (in older versions ``array.array`` does not appear as
  125. # ``IMutableSequence``).
  126. array.array,
  127. }