summaryrefslogtreecommitdiffstats
path: root/contrib/python
diff options
context:
space:
mode:
authorrobot-piglet <[email protected]>2025-10-27 15:28:03 +0300
committerrobot-piglet <[email protected]>2025-10-27 15:55:09 +0300
commitc029f40013a315ebe6ea23d33c4562ed10e176a4 (patch)
treee755671c7d038af6cdf1688dfb5710b3759e8962 /contrib/python
parent058dc84c54b72daf9e25b9ae090a80ed843d4cd0 (diff)
Intermediate changes
commit_hash:50448cf0b9f7db378645dc682bab1b0bc040f4eb
Diffstat (limited to 'contrib/python')
-rw-r--r--contrib/python/PyHamcrest/py3/.dist-info/METADATA212
-rw-r--r--contrib/python/PyHamcrest/py3/LICENSE.txt2
-rw-r--r--contrib/python/PyHamcrest/py3/README.rst128
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/__init__.py9
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/_version.py5
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/__init__.py19
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/assert_that.py43
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/base_description.py73
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/base_matcher.py34
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/compat.py19
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/core/__init__.py18
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/core/allof.py30
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/core/anyof.py17
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/core/described_as.py26
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/core/future.py137
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/core/is_.py54
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/core/isanything.py19
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/core/isequal.py22
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/core/isinstanceof.py21
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/core/isnone.py23
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/core/isnot.py57
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/core/issame.py35
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/core/raises.py99
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/description.py30
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/helpers/hasmethod.py2
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/helpers/ismock.py14
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/helpers/wrap_matcher.py13
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/matcher.py34
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/selfdescribing.py8
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/selfdescribingvalue.py13
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/core/string_description.py23
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/__init__.py59
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/collection/__init__.py18
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/collection/is_empty.py23
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containing.py59
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containingentries.py88
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containingkey.py24
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containingvalue.py24
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/collection/isin.py18
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_containing.py56
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_containinginanyorder.py66
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_containinginorder.py61
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_onlycontaining.py27
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/integration/__init__.py3
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/integration/match_equality.py18
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/number/__init__.py16
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/number/iscloseto.py66
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/number/ordering_comparison.py48
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/object/__init__.py10
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/object/haslength.py28
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/object/hasproperty.py99
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/object/hasstring.py16
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/text/__init__.py15
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/text/isequal_ignoring_case.py27
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/text/isequal_ignoring_whitespace.py33
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/text/stringcontains.py14
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/text/stringcontainsinorder.py30
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/text/stringendswith.py14
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/text/stringmatches.py32
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/text/stringstartswith.py18
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/library/text/substringmatcher.py30
-rw-r--r--contrib/python/PyHamcrest/py3/hamcrest/py.typed0
-rw-r--r--contrib/python/PyHamcrest/py3/patches/01-add-additional-matcher.patch64
-rw-r--r--contrib/python/PyHamcrest/py3/patches/02-add-additional-matcher.patch87
-rw-r--r--contrib/python/PyHamcrest/py3/patches/03-pr54.patch30
-rw-r--r--contrib/python/PyHamcrest/py3/patches/04-pr130.patch11
-rw-r--r--contrib/python/PyHamcrest/py3/ya.make10
67 files changed, 1436 insertions, 1045 deletions
diff --git a/contrib/python/PyHamcrest/py3/.dist-info/METADATA b/contrib/python/PyHamcrest/py3/.dist-info/METADATA
index 071bd13e3ad..48a8683ed0d 100644
--- a/contrib/python/PyHamcrest/py3/.dist-info/METADATA
+++ b/contrib/python/PyHamcrest/py3/.dist-info/METADATA
@@ -1,63 +1,102 @@
Metadata-Version: 2.1
Name: PyHamcrest
-Version: 1.10.1
+Version: 2.1.0
Summary: Hamcrest framework for matcher objects
-Home-page: https://github.com/hamcrest/PyHamcrest
-Author: Chris Rose
-Author-email: [email protected]
-License: New BSD
-Download-URL: http://pypi.python.org/packages/source/P/PyHamcrest/PyHamcrest-1.10.1.tar.gz
-Keywords: hamcrest matchers pyunit unit test testing unittest unittesting
-Platform: All
+Project-URL: History, https://github.com/hamcrest/PyHamcrest/blob/main/CHANGELOG.rst
+Project-URL: Source, https://github.com/hamcrest/PyHamcrest/
+Project-URL: Issues, https://github.com/hamcrest/PyHamcrest/issues
+Author: Simon Brunning, Jon Reid
+Author-email: Chris Rose <[email protected]>
+License: BSD License
+
+ Copyright 2020 hamcrest.org
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice, this list of
+ conditions and the following disclaimer. Redistributions in binary form must reproduce
+ the above copyright notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ Neither the name of Hamcrest nor the names of its contributors may be used to endorse
+ or promote products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGE.
+License-File: LICENSE.txt
+Keywords: hamcrest,matchers,pyunit,test,testing,unit,unittest,unittesting
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: Jython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Software Development
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Testing
-Provides: hamcrest
-Requires-Python: >=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4
-Requires-Dist: six
+Requires-Python: >=3.6
+Provides-Extra: dev
+Requires-Dist: black; extra == 'dev'
+Requires-Dist: doc2dash; extra == 'dev'
+Requires-Dist: flake8; extra == 'dev'
+Requires-Dist: pyhamcrest[docs,tests]; extra == 'dev'
+Requires-Dist: pytest-mypy; extra == 'dev'
+Requires-Dist: towncrier; extra == 'dev'
+Requires-Dist: tox; extra == 'dev'
+Requires-Dist: tox-asdf; extra == 'dev'
+Requires-Dist: twine; extra == 'dev'
+Provides-Extra: docs
+Requires-Dist: alabaster~=0.7; extra == 'docs'
+Requires-Dist: sphinx~=4.0; extra == 'docs'
+Provides-Extra: tests
+Requires-Dist: coverage[toml]; extra == 'tests'
+Requires-Dist: dataclasses; python_version < '3.7' and extra == 'tests'
+Requires-Dist: mypy!=0.940; platform_python_implementation != 'PyPy' and extra == 'tests'
+Requires-Dist: pytest-mypy-plugins; platform_python_implementation != 'PyPy' and extra == 'tests'
+Requires-Dist: pytest-sugar; extra == 'tests'
+Requires-Dist: pytest-xdist; extra == 'tests'
+Requires-Dist: pytest>=5.0; extra == 'tests'
+Requires-Dist: pyyaml; extra == 'tests'
+Requires-Dist: types-dataclasses; python_version < '3.7' and extra == 'tests'
+Requires-Dist: types-mock; extra == 'tests'
+Provides-Extra: tests-numpy
+Requires-Dist: numpy; extra == 'tests-numpy'
+Requires-Dist: pyhamcrest[tests]; extra == 'tests-numpy'
+Description-Content-Type: text/x-rst
PyHamcrest
==========
-| |docs| |travis| |coveralls| |landscape| |scrutinizer|
-| |version| |downloads| |wheel| |supported-versions| |supported-implementations|
-| |GitHub forks| |GitHub stars| |GitHub watchers| |GitHub contributors| |Lines of Code|
-| |GitHub issues| |GitHub issues-closed| |GitHub pull-requests| |GitHub pull-requests closed|
+| |docs| |status| |version| |downloads|
-.. |docs| image:: https://readthedocs.org/projects/pyhamcrest/badge/
- :target: https://pyhamcrest.readthedocs.org/
+.. |docs| image:: https://readthedocs.org/projects/pyhamcrest/badge/?version=latest
+ :target: https://pyhamcrest.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
-.. |travis| image:: http://img.shields.io/travis/hamcrest/PyHamcrest/master.svg
- :alt: Travis-CI Build Status
- :target: https://travis-ci.org/hamcrest/PyHamcrest
-
-.. |appveyor| image:: https://ci.appveyor.com/api/projects/status/github/hamcrest/PyHamcrest?branch=master&svg=true
- :alt: AppVeyor Build Status
- :target: https://ci.appveyor.com/project/hamcrest/PyHamcrest
-
-.. |coveralls| image:: http://img.shields.io/coveralls/hamcrest/PyHamcrest/master.svg?style=flat
- :alt: Coverage Status
- :target: https://coveralls.io/r/hamcrest/PyHamcrest
-
-.. |landscape| image:: https://landscape.io/github/hamcrest/PyHamcrest/master/landscape.svg?style=flat
- :target: https://landscape.io/github/hamcrest/PyHamcrest/master
- :alt: Code Quality Status
+.. |status| image:: https://github.com/hamcrest/PyHamcrest/workflows/CI/badge.svg
+ :alt: CI Build Status
+ :target: https://github.com/hamcrest/PyHamcrest/actions?query=workflow%3ACI
.. |version| image:: http://img.shields.io/pypi/v/PyHamcrest.svg?style=flat
:alt: PyPI Package latest release
@@ -67,58 +106,6 @@ PyHamcrest
:alt: PyPI Package monthly downloads
:target: https://pypi.python.org/pypi/PyHamcrest
-.. |wheel| image:: https://pypip.in/wheel/PyHamcrest/badge.svg?style=flat
- :alt: PyPI Wheel
- :target: https://pypi.python.org/pypi/PyHamcrest
-
-.. |supported-versions| image:: https://pypip.in/py_versions/PyHamcrest/badge.svg?style=flat
- :alt: Supported versions
- :target: https://pypi.python.org/pypi/PyHamcrest
-
-.. |GitHub forks| image:: https://img.shields.io/github/forks/hamcrest/PyHamcrest.svg?label=Fork&logo=github
- :alt: GitHub forks
- :target: https://github.com/hamcrest/PyHamcrest/network/members
-
-.. |GitHub stars| image:: https://img.shields.io/github/stars/hamcrest/PyHamcrest.svg?label=Star&logo=github
- :alt: GitHub stars
- :target: https://github.com/hamcrest/PyHamcrest/stargazers/
-
-.. |GitHub watchers| image:: https://img.shields.io/github/watchers/hamcrest/PyHamcrest.svg?label=Watch&logo=github
- :alt: GitHub watchers
- :target: https://github.com/hamcrest/PyHamcrest/watchers/
-
-.. |GitHub contributors| image:: https://img.shields.io/github/contributors/hamcrest/PyHamcrest.svg?logo=github
- :alt: GitHub contributors
- :target: https://github.com/hamcrest/PyHamcrest/graphs/contributors/
-
-.. |GitHub issues| image:: https://img.shields.io/github/issues/hamcrest/PyHamcrest.svg?logo=github
- :alt: GitHub issues
- :target: https://github.com/hamcrest/PyHamcrest/issues/
-
-.. |GitHub issues-closed| image:: https://img.shields.io/github/issues-closed/hamcrest/PyHamcrest.svg?logo=github
- :alt: GitHub issues-closed
- :target: https://github.com/hamcrest/PyHamcrest/issues?q=is%3Aissue+is%3Aclosed
-
-.. |GitHub pull-requests| image:: https://img.shields.io/github/issues-pr/hamcrest/PyHamcrest.svg?logo=github
- :alt: GitHub pull-requests
- :target: https://github.com/hamcrest/PyHamcrest/pulls
-
-.. |GitHub pull-requests closed| image:: https://img.shields.io/github/issues-pr-closed/hamcrest/PyHamcrest.svg?logo=github
- :alt: GitHub pull-requests closed
- :target: https://github.com/hamcrest/PyHamcrest/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aclosed
-
-.. |Lines of Code| image:: https://tokei.rs/b1/github/hamcrest/PyHamcrest
- :alt: Lines of Code
- :target: https://github.com/hamcrest/PyHamcrest
-
-.. |supported-implementations| image:: https://pypip.in/implementation/PyHamcrest/badge.svg?style=flat
- :alt: Supported implementations
- :target: https://pypi.python.org/pypi/PyHamcrest
-
-.. |scrutinizer| image:: https://img.shields.io/scrutinizer/g/hamcrest/PyHamcrest/master.svg?style=flat
- :alt: Scrtinizer Status
- :target: https://scrutinizer-ci.com/g/hamcrest/PyHamcrest/
-
Introduction
============
@@ -146,6 +133,12 @@ Hamcrest can be installed using the usual Python packaging tools. It depends on
distribute, but as long as you have a network connection when you install, the
installation process will take care of that for you.
+For example:
+
+.. code::
+
+ pip install PyHamcrest
+
My first PyHamcrest test
========================
@@ -155,16 +148,18 @@ the standard set of matchers:
.. code:: python
- from hamcrest import *
+ from hamcrest import assert_that, equal_to
import unittest
+
class BiscuitTest(unittest.TestCase):
def testEquals(self):
- theBiscuit = Biscuit('Ginger')
- myBiscuit = Biscuit('Ginger')
+ theBiscuit = Biscuit("Ginger")
+ myBiscuit = Biscuit("Ginger")
assert_that(theBiscuit, equal_to(myBiscuit))
- if __name__ == '__main__':
+
+ if __name__ == "__main__":
unittest.main()
The ``assert_that`` function is a stylized sentence for making a test
@@ -179,14 +174,14 @@ for the tested value in the assertion:
.. code:: python
- assert_that(theBiscuit.getChocolateChipCount(), equal_to(10), 'chocolate chips')
- assert_that(theBiscuit.getHazelnutCount(), equal_to(3), 'hazelnuts')
+ assert_that(theBiscuit.getChocolateChipCount(), equal_to(10), "chocolate chips")
+ assert_that(theBiscuit.getHazelnutCount(), equal_to(3), "hazelnuts")
As a convenience, assert_that can also be used to verify a boolean condition:
.. code:: python
- assert_that(theBiscuit.isCooked(), 'cooked')
+ assert_that(theBiscuit.isCooked(), "cooked")
This is equivalent to the ``assert_`` method of unittest.TestCase, but because
it's a standalone function, it offers greater flexibility in test writing.
@@ -315,21 +310,30 @@ And here's the implementation:
from hamcrest.core.base_matcher import BaseMatcher
from hamcrest.core.helpers.hasmethod import hasmethod
- class IsGivenDayOfWeek(BaseMatcher):
+ class IsGivenDayOfWeek(BaseMatcher):
def __init__(self, day):
self.day = day # Monday is 0, Sunday is 6
def _matches(self, item):
- if not hasmethod(item, 'weekday'):
+ if not hasmethod(item, "weekday"):
return False
return item.weekday() == self.day
def describe_to(self, description):
- day_as_string = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
- 'Friday', 'Saturday', 'Sunday']
- description.append_text('calendar date falling on ') \
- .append_text(day_as_string[self.day])
+ day_as_string = [
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday",
+ "Sunday",
+ ]
+ description.append_text("calendar date falling on ").append_text(
+ day_as_string[self.day]
+ )
+
def on_a_saturday():
return IsGivenDayOfWeek(5)
@@ -355,16 +359,18 @@ could use it in our test by importing the factory function ``on_a_saturday``:
.. code:: python
- from hamcrest import *
+ from hamcrest import assert_that, is_
import unittest
from isgivendayofweek import on_a_saturday
+
class DateTest(unittest.TestCase):
def testDateIsOnASaturday(self):
d = datetime.date(2008, 4, 26)
assert_that(d, is_(on_a_saturday()))
- if __name__ == '__main__':
+
+ if __name__ == "__main__":
unittest.main()
Even though the ``on_a_saturday`` function creates a new matcher each time it
@@ -385,5 +391,3 @@ More resources
.. _Package: http://pypi.python.org/pypi/PyHamcrest
.. _Sources: https://github.com/hamcrest/PyHamcrest
.. _Hamcrest: http://hamcrest.org
-
-
diff --git a/contrib/python/PyHamcrest/py3/LICENSE.txt b/contrib/python/PyHamcrest/py3/LICENSE.txt
index 0bea089e5ca..fe93ce18e18 100644
--- a/contrib/python/PyHamcrest/py3/LICENSE.txt
+++ b/contrib/python/PyHamcrest/py3/LICENSE.txt
@@ -1,6 +1,6 @@
BSD License
-Copyright 2011 hamcrest.org
+Copyright 2020 hamcrest.org
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/contrib/python/PyHamcrest/py3/README.rst b/contrib/python/PyHamcrest/py3/README.rst
index 7bae39eea29..3d0bcf12224 100644
--- a/contrib/python/PyHamcrest/py3/README.rst
+++ b/contrib/python/PyHamcrest/py3/README.rst
@@ -1,30 +1,15 @@
PyHamcrest
==========
-| |docs| |travis| |coveralls| |landscape| |scrutinizer|
-| |version| |downloads| |wheel| |supported-versions| |supported-implementations|
-| |GitHub forks| |GitHub stars| |GitHub watchers| |GitHub contributors| |Lines of Code|
-| |GitHub issues| |GitHub issues-closed| |GitHub pull-requests| |GitHub pull-requests closed|
+| |docs| |status| |version| |downloads|
-.. |docs| image:: https://readthedocs.org/projects/pyhamcrest/badge/
- :target: https://pyhamcrest.readthedocs.org/
+.. |docs| image:: https://readthedocs.org/projects/pyhamcrest/badge/?version=latest
+ :target: https://pyhamcrest.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
-.. |travis| image:: http://img.shields.io/travis/hamcrest/PyHamcrest/master.svg
- :alt: Travis-CI Build Status
- :target: https://travis-ci.org/hamcrest/PyHamcrest
-
-.. |appveyor| image:: https://ci.appveyor.com/api/projects/status/github/hamcrest/PyHamcrest?branch=master&svg=true
- :alt: AppVeyor Build Status
- :target: https://ci.appveyor.com/project/hamcrest/PyHamcrest
-
-.. |coveralls| image:: http://img.shields.io/coveralls/hamcrest/PyHamcrest/master.svg?style=flat
- :alt: Coverage Status
- :target: https://coveralls.io/r/hamcrest/PyHamcrest
-
-.. |landscape| image:: https://landscape.io/github/hamcrest/PyHamcrest/master/landscape.svg?style=flat
- :target: https://landscape.io/github/hamcrest/PyHamcrest/master
- :alt: Code Quality Status
+.. |status| image:: https://github.com/hamcrest/PyHamcrest/workflows/CI/badge.svg
+ :alt: CI Build Status
+ :target: https://github.com/hamcrest/PyHamcrest/actions?query=workflow%3ACI
.. |version| image:: http://img.shields.io/pypi/v/PyHamcrest.svg?style=flat
:alt: PyPI Package latest release
@@ -34,58 +19,6 @@ PyHamcrest
:alt: PyPI Package monthly downloads
:target: https://pypi.python.org/pypi/PyHamcrest
-.. |wheel| image:: https://pypip.in/wheel/PyHamcrest/badge.svg?style=flat
- :alt: PyPI Wheel
- :target: https://pypi.python.org/pypi/PyHamcrest
-
-.. |supported-versions| image:: https://pypip.in/py_versions/PyHamcrest/badge.svg?style=flat
- :alt: Supported versions
- :target: https://pypi.python.org/pypi/PyHamcrest
-
-.. |GitHub forks| image:: https://img.shields.io/github/forks/hamcrest/PyHamcrest.svg?label=Fork&logo=github
- :alt: GitHub forks
- :target: https://github.com/hamcrest/PyHamcrest/network/members
-
-.. |GitHub stars| image:: https://img.shields.io/github/stars/hamcrest/PyHamcrest.svg?label=Star&logo=github
- :alt: GitHub stars
- :target: https://github.com/hamcrest/PyHamcrest/stargazers/
-
-.. |GitHub watchers| image:: https://img.shields.io/github/watchers/hamcrest/PyHamcrest.svg?label=Watch&logo=github
- :alt: GitHub watchers
- :target: https://github.com/hamcrest/PyHamcrest/watchers/
-
-.. |GitHub contributors| image:: https://img.shields.io/github/contributors/hamcrest/PyHamcrest.svg?logo=github
- :alt: GitHub contributors
- :target: https://github.com/hamcrest/PyHamcrest/graphs/contributors/
-
-.. |GitHub issues| image:: https://img.shields.io/github/issues/hamcrest/PyHamcrest.svg?logo=github
- :alt: GitHub issues
- :target: https://github.com/hamcrest/PyHamcrest/issues/
-
-.. |GitHub issues-closed| image:: https://img.shields.io/github/issues-closed/hamcrest/PyHamcrest.svg?logo=github
- :alt: GitHub issues-closed
- :target: https://github.com/hamcrest/PyHamcrest/issues?q=is%3Aissue+is%3Aclosed
-
-.. |GitHub pull-requests| image:: https://img.shields.io/github/issues-pr/hamcrest/PyHamcrest.svg?logo=github
- :alt: GitHub pull-requests
- :target: https://github.com/hamcrest/PyHamcrest/pulls
-
-.. |GitHub pull-requests closed| image:: https://img.shields.io/github/issues-pr-closed/hamcrest/PyHamcrest.svg?logo=github
- :alt: GitHub pull-requests closed
- :target: https://github.com/hamcrest/PyHamcrest/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aclosed
-
-.. |Lines of Code| image:: https://tokei.rs/b1/github/hamcrest/PyHamcrest
- :alt: Lines of Code
- :target: https://github.com/hamcrest/PyHamcrest
-
-.. |supported-implementations| image:: https://pypip.in/implementation/PyHamcrest/badge.svg?style=flat
- :alt: Supported implementations
- :target: https://pypi.python.org/pypi/PyHamcrest
-
-.. |scrutinizer| image:: https://img.shields.io/scrutinizer/g/hamcrest/PyHamcrest/master.svg?style=flat
- :alt: Scrtinizer Status
- :target: https://scrutinizer-ci.com/g/hamcrest/PyHamcrest/
-
Introduction
============
@@ -113,6 +46,12 @@ Hamcrest can be installed using the usual Python packaging tools. It depends on
distribute, but as long as you have a network connection when you install, the
installation process will take care of that for you.
+For example:
+
+.. code::
+
+ pip install PyHamcrest
+
My first PyHamcrest test
========================
@@ -122,16 +61,18 @@ the standard set of matchers:
.. code:: python
- from hamcrest import *
+ from hamcrest import assert_that, equal_to
import unittest
+
class BiscuitTest(unittest.TestCase):
def testEquals(self):
- theBiscuit = Biscuit('Ginger')
- myBiscuit = Biscuit('Ginger')
+ theBiscuit = Biscuit("Ginger")
+ myBiscuit = Biscuit("Ginger")
assert_that(theBiscuit, equal_to(myBiscuit))
- if __name__ == '__main__':
+
+ if __name__ == "__main__":
unittest.main()
The ``assert_that`` function is a stylized sentence for making a test
@@ -146,14 +87,14 @@ for the tested value in the assertion:
.. code:: python
- assert_that(theBiscuit.getChocolateChipCount(), equal_to(10), 'chocolate chips')
- assert_that(theBiscuit.getHazelnutCount(), equal_to(3), 'hazelnuts')
+ assert_that(theBiscuit.getChocolateChipCount(), equal_to(10), "chocolate chips")
+ assert_that(theBiscuit.getHazelnutCount(), equal_to(3), "hazelnuts")
As a convenience, assert_that can also be used to verify a boolean condition:
.. code:: python
- assert_that(theBiscuit.isCooked(), 'cooked')
+ assert_that(theBiscuit.isCooked(), "cooked")
This is equivalent to the ``assert_`` method of unittest.TestCase, but because
it's a standalone function, it offers greater flexibility in test writing.
@@ -282,21 +223,30 @@ And here's the implementation:
from hamcrest.core.base_matcher import BaseMatcher
from hamcrest.core.helpers.hasmethod import hasmethod
- class IsGivenDayOfWeek(BaseMatcher):
+ class IsGivenDayOfWeek(BaseMatcher):
def __init__(self, day):
self.day = day # Monday is 0, Sunday is 6
def _matches(self, item):
- if not hasmethod(item, 'weekday'):
+ if not hasmethod(item, "weekday"):
return False
return item.weekday() == self.day
def describe_to(self, description):
- day_as_string = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
- 'Friday', 'Saturday', 'Sunday']
- description.append_text('calendar date falling on ') \
- .append_text(day_as_string[self.day])
+ day_as_string = [
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday",
+ "Sunday",
+ ]
+ description.append_text("calendar date falling on ").append_text(
+ day_as_string[self.day]
+ )
+
def on_a_saturday():
return IsGivenDayOfWeek(5)
@@ -322,16 +272,18 @@ could use it in our test by importing the factory function ``on_a_saturday``:
.. code:: python
- from hamcrest import *
+ from hamcrest import assert_that, is_
import unittest
from isgivendayofweek import on_a_saturday
+
class DateTest(unittest.TestCase):
def testDateIsOnASaturday(self):
d = datetime.date(2008, 4, 26)
assert_that(d, is_(on_a_saturday()))
- if __name__ == '__main__':
+
+ if __name__ == "__main__":
unittest.main()
Even though the ``on_a_saturday`` function creates a new matcher each time it
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/__init__.py b/contrib/python/PyHamcrest/py3/hamcrest/__init__.py
index f45b032075d..b40f70119c4 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/__init__.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/__init__.py
@@ -1,8 +1,13 @@
-from __future__ import absolute_import
from hamcrest.core import *
from hamcrest.library import *
+from hamcrest import core, library
+from hamcrest._version import version
-__version__ = "1.10.1"
+__version__ = version
__author__ = "Chris Rose"
__copyright__ = "Copyright 2020 hamcrest.org"
__license__ = "BSD, see License.txt"
+
+__all__ = []
+__all__.extend(core.__all__)
+__all__.extend(library.__all__)
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/_version.py b/contrib/python/PyHamcrest/py3/hamcrest/_version.py
new file mode 100644
index 00000000000..b2687cd7063
--- /dev/null
+++ b/contrib/python/PyHamcrest/py3/hamcrest/_version.py
@@ -0,0 +1,5 @@
+# coding: utf-8
+# file generated by setuptools_scm
+# don't change, don't track in version control
+version = '2.1.0' # pragma: no mutate
+version_tuple = (2, 1, 0) # pragma: no mutate
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/__init__.py b/contrib/python/PyHamcrest/py3/hamcrest/core/__init__.py
index 779fa723459..a578f365748 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/__init__.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/__init__.py
@@ -1,7 +1,24 @@
-from __future__ import absolute_import
from hamcrest.core.assert_that import assert_that
from hamcrest.core.core import *
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
+
+__all__ = [
+ "assert_that",
+ "all_of",
+ "any_of",
+ "anything",
+ "calling",
+ "described_as",
+ "equal_to",
+ "instance_of",
+ "is_",
+ "is_not",
+ "none",
+ "not_",
+ "not_none",
+ "raises",
+ "same_instance",
+]
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/assert_that.py b/contrib/python/PyHamcrest/py3/hamcrest/core/assert_that.py
index 8c36ceab764..a31cf3a1b21 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/assert_that.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/assert_that.py
@@ -1,5 +1,6 @@
-from __future__ import absolute_import
import warnings
+from typing import Optional, TypeVar, cast, overload
+
from hamcrest.core.matcher import Matcher
from hamcrest.core.string_description import StringDescription
@@ -11,7 +12,20 @@ __unittest = True
# py.test integration; hide these frames from tracebacks
__tracebackhide__ = True
-def assert_that(arg1, arg2=None, arg3=''):
+T = TypeVar("T")
+
+
+@overload
+def assert_that(actual_or_assertion: T, matcher: Matcher[T], reason: str = "") -> None:
+ ...
+
+
+@overload
+def assert_that(actual_or_assertion: bool, reason: str = "") -> None:
+ ...
+
+
+def assert_that(actual_or_assertion, matcher=None, reason=""):
"""Asserts that actual value satisfies matcher. (Can also assert plain
boolean condition.)
@@ -40,28 +54,27 @@ def assert_that(arg1, arg2=None, arg3=''):
writing by being a standalone function.
"""
- if isinstance(arg2, Matcher):
- _assert_match(actual=arg1, matcher=arg2, reason=arg3)
+ if isinstance(matcher, Matcher):
+ _assert_match(actual=actual_or_assertion, matcher=matcher, reason=reason)
else:
- if isinstance(arg1, Matcher):
- warnings.warn("arg1 should be boolean, but was {}".format(type(arg1)))
- _assert_bool(assertion=arg1, reason=arg2)
+ if isinstance(actual_or_assertion, Matcher):
+ warnings.warn("arg1 should be boolean, but was {}".format(type(actual_or_assertion)))
+ _assert_bool(assertion=cast(bool, actual_or_assertion), reason=cast(str, matcher))
-def _assert_match(actual, matcher, reason):
+def _assert_match(actual: T, matcher: Matcher[T], reason: str) -> None:
if not matcher.matches(actual):
description = StringDescription()
- description.append_text(reason) \
- .append_text('\nExpected: ') \
- .append_description_of(matcher) \
- .append_text('\n but: ')
+ description.append_text(reason).append_text("\nExpected: ").append_description_of(
+ matcher
+ ).append_text("\n but: ")
matcher.describe_mismatch(actual, description)
- description.append_text('\n')
+ description.append_text("\n")
raise AssertionError(description)
-def _assert_bool(assertion, reason=None):
+def _assert_bool(assertion: bool, reason: Optional[str] = None) -> None:
if not assertion:
if not reason:
- reason = 'Assertion failed'
+ reason = "Assertion failed"
raise AssertionError(reason)
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/base_description.py b/contrib/python/PyHamcrest/py3/hamcrest/core/base_description.py
index 18b3ee9ee53..e0ceea34ff0 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/base_description.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/base_description.py
@@ -1,63 +1,40 @@
-from __future__ import absolute_import
-__author__ = "Jon Reid"
-__copyright__ = "Copyright 2011 hamcrest.org"
-__license__ = "BSD, see License.txt"
-
-import warnings
-import six
+from typing import Any, Iterable
from hamcrest.core.description import Description
-from hamcrest.core.selfdescribingvalue import SelfDescribingValue
from hamcrest.core.helpers.hasmethod import hasmethod
from hamcrest.core.helpers.ismock import ismock
+__author__ = "Jon Reid"
+__copyright__ = "Copyright 2011 hamcrest.org"
+__license__ = "BSD, see License.txt"
+
+
class BaseDescription(Description):
"""Base class for all :py:class:`~hamcrest.core.description.Description`
implementations.
"""
- def append_text(self, text):
+ def append_text(self, text: str) -> Description:
self.append(text)
return self
- def append_description_of(self, value):
- if not ismock(value) and hasmethod(value, 'describe_to'):
+ def append_description_of(self, value: Any) -> Description:
+ if not ismock(value) and hasmethod(value, "describe_to"):
value.describe_to(self)
- elif six.PY3 and isinstance(value, six.text_type):
+ elif isinstance(value, str):
self.append(repr(value))
- elif six.PY2 and isinstance(value, six.binary_type):
- self.append_string_in_python_syntax(value)
- elif isinstance(value, six.text_type):
- self.append_string_in_python_syntax(value)
else:
description = str(value)
- if description[:1] == '<' and description[-1:] == '>':
+ if description[:1] == "<" and description[-1:] == ">":
self.append(description)
else:
- self.append('<')
+ self.append("<")
self.append(description)
- self.append('>')
- return self
-
- def append_value(self, value):
- warnings.warn('Call append_description_of instead of append_value',
- DeprecationWarning)
- if isinstance(value, str):
- self.append_string_in_python_syntax(value)
- else:
- self.append('<')
- self.append(str(value))
- self.append('>')
+ self.append(">")
return self
- def append_value_list(self, start, separator, end, list):
- warnings.warn('Call append_list instead of append_value_list',
- DeprecationWarning)
- return self.append_list(start, separator, end,
- map(SelfDescribingValue, list))
-
- def append_list(self, start, separator, end, list):
+ def append_list(self, start: str, separator: str, end: str, list: Iterable[Any]) -> Description:
separate = False
self.append(start)
@@ -69,25 +46,25 @@ class BaseDescription(Description):
self.append(end)
return self
- def append(self, string):
+ def append(self, string: str) -> None:
"""Append the string to the description."""
- raise NotImplementedError('append')
+ raise NotImplementedError("append")
- def append_string_in_python_syntax(self, string):
+ def append_string_in_python_syntax(self, string: str) -> None:
self.append("'")
for ch in string:
self.append(character_in_python_syntax(ch))
self.append("'")
-def character_in_python_syntax(ch):
+def character_in_python_syntax(ch: str) -> str:
if ch == "'":
- return "\'"
- elif ch == '\n':
- return '\\n'
- elif ch == '\r':
- return '\\r'
- elif ch == '\t':
- return '\\t'
+ return "'"
+ elif ch == "\n":
+ return "\\n"
+ elif ch == "\r":
+ return "\\r"
+ elif ch == "\t":
+ return "\\t"
else:
return ch
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/base_matcher.py b/contrib/python/PyHamcrest/py3/hamcrest/core/base_matcher.py
index 951e2a7b95d..7edc994f9c1 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/base_matcher.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/base_matcher.py
@@ -1,13 +1,18 @@
-from __future__ import absolute_import
+from textwrap import shorten
+from typing import Optional, TypeVar
+
+from hamcrest.core.description import Description
+from hamcrest.core.matcher import Matcher
+from hamcrest.core.string_description import tostring
+
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
-from hamcrest.core.matcher import Matcher
-from hamcrest.core.string_description import tostring
+T = TypeVar("T")
-class BaseMatcher(Matcher):
+class BaseMatcher(Matcher[T]):
"""Base class for all :py:class:`~hamcrest.core.matcher.Matcher`
implementations.
@@ -18,17 +23,26 @@ class BaseMatcher(Matcher):
"""
- def __str__(self):
+ def __str__(self) -> str:
return tostring(self)
- def _matches(self, item):
- raise NotImplementedError('_matches')
+ def __repr__(self) -> str:
+ """Returns matcher string representation."""
+ return "<{0}({1})>".format(
+ self.__class__.__name__, shorten(tostring(self), 60, placeholder="...")
+ )
- def matches(self, item, mismatch_description=None):
+ def _matches(self, item: T) -> bool:
+ raise NotImplementedError("_matches")
+
+ def matches(self, item: T, mismatch_description: Optional[Description] = None) -> bool:
match_result = self._matches(item)
if not match_result and mismatch_description:
self.describe_mismatch(item, mismatch_description)
return match_result
- def describe_mismatch(self, item, mismatch_description):
- mismatch_description.append_text('was ').append_description_of(item)
+ def describe_mismatch(self, item: T, mismatch_description: Description) -> None:
+ mismatch_description.append_text("was ").append_description_of(item)
+
+ def describe_match(self, item: T, match_description: Description) -> None:
+ match_description.append_text("was ").append_description_of(item)
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/compat.py b/contrib/python/PyHamcrest/py3/hamcrest/core/compat.py
deleted file mode 100644
index 2c6d1fa74c8..00000000000
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/compat.py
+++ /dev/null
@@ -1,19 +0,0 @@
-__author__ = "Per Fagrell"
-__copyright__ = "Copyright 2013 hamcrest.org"
-__license__ = "BSD, see License.txt"
-
-__all__ = ['is_callable']
-
-import sys
-
-# callable was not part of py3k until 3.2, so we create this
-# generic is_callable to use callable if possible, otherwise
-# we use generic homebrew.
-if sys.version_info[0] == 3 and sys.version_info[1] < 2:
- def is_callable(function):
- """Return whether the object is callable (i.e., some kind of function)."""
- if function is None:
- return False
- return any("__call__" in klass.__dict__ for klass in type(function).__mro__)
-else:
- is_callable = callable
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/core/__init__.py b/contrib/python/PyHamcrest/py3/hamcrest/core/core/__init__.py
index 38e93e249a7..3bb11209fb5 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/core/__init__.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/core/__init__.py
@@ -1,4 +1,3 @@
-from __future__ import absolute_import
"""Fundamental matchers of objects and values, and composite matchers."""
from hamcrest.core.core.allof import all_of
@@ -16,3 +15,20 @@ from hamcrest.core.core.raises import calling, raises
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
+
+__all__ = [
+ "all_of",
+ "any_of",
+ "anything",
+ "calling",
+ "described_as",
+ "equal_to",
+ "instance_of",
+ "is_",
+ "is_not",
+ "none",
+ "not_",
+ "not_none",
+ "raises",
+ "same_instance",
+]
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/core/allof.py b/contrib/python/PyHamcrest/py3/hamcrest/core/core/allof.py
index e051f6abb30..ffb62f6c3e0 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/core/allof.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/core/allof.py
@@ -1,42 +1,48 @@
+from typing import Optional, TypeVar, Union
+
from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
+from hamcrest.core.matcher import Matcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
+T = TypeVar("T")
-class AllOf(BaseMatcher):
- def __init__(self, *matchers, **kwargs):
+class AllOf(BaseMatcher[T]):
+ def __init__(self, *matchers: Matcher[T], **kwargs):
self.matchers = matchers
- self.describe_matcher_in_mismatch = kwargs.pop('describe_matcher_in_mismatch', True) # No keyword-only args in 2.7 :-(
- self.describe_all_mismatches = kwargs.pop('describe_all_mismatches', False)
+ self.describe_matcher_in_mismatch = kwargs.pop(
+ "describe_matcher_in_mismatch", True
+ ) # No keyword-only args in 2.7 :-(
+ self.describe_all_mismatches = kwargs.pop("describe_all_mismatches", False)
- def matches(self, item, mismatch_description=None):
+ def matches(self, item: T, mismatch_description: Optional[Description] = None) -> bool:
found_mismatch = False
for i, matcher in enumerate(self.matchers):
if not matcher.matches(item):
if mismatch_description:
if self.describe_matcher_in_mismatch:
- mismatch_description.append_description_of(matcher) \
- .append_text(' ')
+ mismatch_description.append_description_of(matcher).append_text(" ")
matcher.describe_mismatch(item, mismatch_description)
found_mismatch = True
if not self.describe_all_mismatches:
break
elif i < len(self.matchers) - 1 and mismatch_description:
- mismatch_description.append_text(' and ')
+ mismatch_description.append_text(" and ")
return not found_mismatch
- def describe_mismatch(self, item, mismatch_description):
+ def describe_mismatch(self, item: T, mismatch_description: Description) -> None:
self.matches(item, mismatch_description)
- def describe_to(self, description):
- description.append_list('(', ' and ', ')', self.matchers)
+ def describe_to(self, description: Description) -> None:
+ description.append_list("(", " and ", ")", self.matchers)
-def all_of(*items):
+def all_of(*items: Union[Matcher[T], T]) -> Matcher[T]:
"""Matches if all of the given matchers evaluate to ``True``.
:param matcher1,...: A comma-separated list of matchers.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/core/anyof.py b/contrib/python/PyHamcrest/py3/hamcrest/core/core/anyof.py
index 7a2bfc6627d..921e3b2f9f5 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/core/anyof.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/core/anyof.py
@@ -1,27 +1,32 @@
+from typing import TypeVar, Union
+
from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
+from hamcrest.core.matcher import Matcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
+T = TypeVar("T")
-class AnyOf(BaseMatcher):
- def __init__(self, *matchers):
+class AnyOf(BaseMatcher[T]):
+ def __init__(self, *matchers: Matcher[T]) -> None:
self.matchers = matchers
- def _matches(self, item):
+ def _matches(self, item: T) -> bool:
for matcher in self.matchers:
if matcher.matches(item):
return True
return False
- def describe_to(self, description):
- description.append_list('(', ' or ', ')', self.matchers)
+ def describe_to(self, description: Description) -> None:
+ description.append_list("(", " or ", ")", self.matchers)
-def any_of(*items):
+def any_of(*items: Union[Matcher[T], T]) -> Matcher[T]:
"""Matches if any of the given matchers evaluate to ``True``.
:param matcher1,...: A comma-separated list of matchers.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/core/described_as.py b/contrib/python/PyHamcrest/py3/hamcrest/core/core/described_as.py
index 93b4d6ac458..dba2b5ccdd3 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/core/described_as.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/core/described_as.py
@@ -1,31 +1,35 @@
-from hamcrest.core.base_matcher import BaseMatcher
import re
+from typing import Any, Optional, Tuple
+
+from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
+from hamcrest.core.matcher import Matcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
+ARG_PATTERN = re.compile("%([0-9]+)")
-ARG_PATTERN = re.compile('%([0-9]+)')
-
-
-class DescribedAs(BaseMatcher):
- def __init__(self, description_template, matcher, *values):
+class DescribedAs(BaseMatcher[Any]):
+ def __init__(
+ self, description_template: str, matcher: Matcher[Any], *values: Tuple[Any, ...]
+ ) -> None:
self.template = description_template
self.matcher = matcher
self.values = values
- def matches(self, item, mismatch_description=None):
+ def matches(self, item: Any, mismatch_description: Optional[Description] = None) -> bool:
return self.matcher.matches(item, mismatch_description)
- def describe_mismatch(self, item, mismatch_description):
+ def describe_mismatch(self, item: Any, mismatch_description: Description) -> None:
self.matcher.describe_mismatch(item, mismatch_description)
- def describe_to(self, description):
+ def describe_to(self, description: Description) -> None:
text_start = 0
for match in re.finditer(ARG_PATTERN, self.template):
- description.append_text(self.template[text_start:match.start()])
+ description.append_text(self.template[text_start : match.start()])
arg_index = int(match.group()[1:])
description.append_description_of(self.values[arg_index])
text_start = match.end()
@@ -34,7 +38,7 @@ class DescribedAs(BaseMatcher):
description.append_text(self.template[text_start:])
-def described_as(description, matcher, *values):
+def described_as(description: str, matcher: Matcher[Any], *values) -> Matcher[Any]:
"""Adds custom failure description to a given matcher.
:param description: Overrides the matcher's description.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/core/future.py b/contrib/python/PyHamcrest/py3/hamcrest/core/core/future.py
new file mode 100644
index 00000000000..b58bc2a892a
--- /dev/null
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/core/future.py
@@ -0,0 +1,137 @@
+import sys
+import re
+import asyncio
+from typing import (
+ Optional,
+ Type,
+ TypeVar,
+ Union,
+ Awaitable,
+)
+
+from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
+from hamcrest.core.matcher import Matcher
+
+__author__ = "David Keijser"
+__copyright__ = "Copyright 2021 hamcrest.org"
+__license__ = "BSD, see License.txt"
+
+T = TypeVar("T")
+
+if sys.version_info > (3, 9):
+ # Same as used in typeshed for asyncio.ensure_future
+ FutureT = asyncio.Future[T]
+ FutureLike = Union[asyncio.Future[T], Awaitable[T]]
+else:
+ # Future is not a parametrised type in earlier version of python
+ FutureT = asyncio.Future
+ FutureLike = Union[asyncio.Future, Awaitable]
+
+
+class FutureRaising(BaseMatcher[asyncio.Future]):
+ def __init__(
+ self,
+ expected: Type[Exception],
+ pattern: Optional[str] = None,
+ matching: Optional[Matcher] = None,
+ ) -> None:
+ self.pattern = pattern
+ self.matcher = matching
+ self.expected = expected
+
+ def _matches(self, future: asyncio.Future) -> bool:
+ if not asyncio.isfuture(future):
+ return False
+
+ if not future.done():
+ return False
+
+ if future.cancelled():
+ return False
+
+ exc = future.exception()
+ if exc is None:
+ return False
+
+ if isinstance(exc, self.expected):
+ if self.pattern is not None:
+ if re.search(self.pattern, str(exc)) is None:
+ return False
+ if self.matcher is not None:
+ if not self.matcher.matches(exc):
+ return False
+ return True
+
+ return False
+
+ def describe_to(self, description: Description) -> None:
+ description.append_text("Expected a completed future with exception %s" % self.expected)
+
+ def describe_mismatch(self, future: asyncio.Future, description: Description) -> None:
+ if not asyncio.isfuture(future):
+ description.append_text("%s is not a future" % future)
+ return
+
+ if not future.done():
+ description.append_text("%s is not completed yet" % future)
+ return
+
+ if future.cancelled():
+ description.append_text("%s is cancelled" % future)
+ return
+
+ exc = future.exception()
+ if exc is None:
+ description.append_text("No exception raised.")
+ elif isinstance(exc, self.expected):
+ if self.pattern is not None or self.matcher is not None:
+ description.append_text("Correct assertion type raised, but ")
+ if self.pattern is not None:
+ description.append_text('the expected pattern ("%s") ' % self.pattern)
+ if self.pattern is not None and self.matcher is not None:
+ description.append_text("and ")
+ if self.matcher is not None:
+ description.append_description_of(self.matcher)
+ description.append_text(" ")
+ description.append_text('not found. Exception message was: "%s"' % str(exc))
+ else:
+ description.append_text("%r of type %s was raised instead" % (exc, type(exc)))
+
+ def describe_match(self, future: asyncio.Future, match_description: Description) -> None:
+ exc = future.exception()
+ match_description.append_text("%r of type %s was raised." % (exc, type(exc)))
+
+
+def future_raising(
+ exception: Type[Exception], pattern=None, matching=None
+) -> Matcher[asyncio.Future]:
+ """Matches a future with the expected exception.
+
+ :param exception: The class of the expected exception
+ :param pattern: Optional regular expression to match exception message.
+ :param matching: Optional Hamcrest matchers to apply to the exception.
+
+ Expects the actual to be an already resolved future. The :py:func:`~hamcrest:core.core.future.resolved` helper can be used to wait for a future to resolve.
+ Optional argument pattern should be a string containing a regular expression. If provided,
+ the string representation of the actual exception - e.g. `str(actual)` - must match pattern.
+
+ Examples::
+
+ assert_that(somefuture, future_exception(ValueError))
+ assert_that(
+ await resolved(async_http_get()),
+ future_exception(HTTPError, matching=has_properties(status_code=500)
+ )
+ """
+ return FutureRaising(exception, pattern, matching)
+
+
+async def resolved(obj: FutureLike) -> FutureT:
+ """Wait for an async operation to finish and return a resolved future object with the result.
+
+ :param obj: A future like object or an awaitable object.
+ """
+ fut = asyncio.ensure_future(obj)
+ await asyncio.wait([fut])
+ return fut
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/core/is_.py b/contrib/python/PyHamcrest/py3/hamcrest/core/core/is_.py
index ba11a762aeb..dafe41cd553 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/core/is_.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/core/is_.py
@@ -1,35 +1,65 @@
-from __future__ import absolute_import
-__author__ = "Jon Reid"
-__copyright__ = "Copyright 2011 hamcrest.org"
-__license__ = "BSD, see License.txt"
+from typing import Optional, Type, TypeVar, overload, Any
from hamcrest.core.base_matcher import BaseMatcher
-from hamcrest.core.helpers.wrap_matcher import wrap_matcher, is_matchable_type
+from hamcrest.core.description import Description
+from hamcrest.core.helpers.wrap_matcher import is_matchable_type, wrap_matcher
+from hamcrest.core.matcher import Matcher
+
from .isinstanceof import instance_of
+__author__ = "Jon Reid"
+__copyright__ = "Copyright 2011 hamcrest.org"
+__license__ = "BSD, see License.txt"
-class Is(BaseMatcher):
+T = TypeVar("T")
- def __init__(self, matcher):
+
+class Is(BaseMatcher[T]):
+ def __init__(self, matcher: Matcher[T]) -> None:
self.matcher = matcher
- def matches(self, item, mismatch_description=None):
+ def matches(self, item: T, mismatch_description: Optional[Description] = None) -> bool:
return self.matcher.matches(item, mismatch_description)
- def describe_mismatch(self, item, mismatch_description):
+ def describe_mismatch(self, item: T, mismatch_description: Description) -> None:
return self.matcher.describe_mismatch(item, mismatch_description)
- def describe_to(self, description):
+ def describe_to(self, description: Description):
description.append_description_of(self.matcher)
-def wrap_value_or_type(x):
+@overload
+def _wrap_value_or_type(x: Type) -> Matcher[object]:
+ ...
+
+
+@overload
+def _wrap_value_or_type(x: T) -> Matcher[T]:
+ ...
+
+
+def _wrap_value_or_type(x):
if is_matchable_type(x):
return instance_of(x)
else:
return wrap_matcher(x)
+@overload
+def is_(x: Type) -> Matcher[Any]:
+ ...
+
+
+@overload
+def is_(x: Matcher[T]) -> Matcher[T]:
+ ...
+
+
+@overload
+def is_(x: T) -> Matcher[T]:
+ ...
+
+
def is_(x):
"""Decorates another matcher, or provides shortcuts to the frequently used
``is(equal_to(x))`` and ``is(instance_of(x))``.
@@ -73,4 +103,4 @@ def is_(x):
depending on context.
"""
- return Is(wrap_value_or_type(x))
+ return Is(_wrap_value_or_type(x))
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/core/isanything.py b/contrib/python/PyHamcrest/py3/hamcrest/core/core/isanything.py
index f916811bc97..bed86d82a37 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/core/isanything.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/core/isanything.py
@@ -1,25 +1,26 @@
+from typing import Any, Optional
+
from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
+from hamcrest.core.matcher import Matcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
-class IsAnything(BaseMatcher):
-
- def __init__(self, description):
- self.description = description
- if not description:
- self.description = 'ANYTHING'
+class IsAnything(BaseMatcher[Any]):
+ def __init__(self, description: Optional[str]) -> None:
+ self.description: str = description or "ANYTHING"
- def _matches(self, item):
+ def _matches(self, item: Any) -> bool:
return True
- def describe_to(self, description):
+ def describe_to(self, description: Description) -> None:
description.append_text(self.description)
-def anything(description=None):
+def anything(description: Optional[str] = None) -> Matcher[Any]:
"""Matches anything.
:param description: Optional string used to describe this matcher.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/core/isequal.py b/contrib/python/PyHamcrest/py3/hamcrest/core/core/isequal.py
index 119fd58a482..18160919c17 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/core/isequal.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/core/isequal.py
@@ -1,29 +1,31 @@
-__author__ = "Jon Reid"
-__copyright__ = "Copyright 2011 hamcrest.org"
-__license__ = "BSD, see License.txt"
+from typing import Any
from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
from hamcrest.core.matcher import Matcher
+__author__ = "Jon Reid"
+__copyright__ = "Copyright 2011 hamcrest.org"
+__license__ = "BSD, see License.txt"
-class IsEqual(BaseMatcher):
- def __init__(self, equals):
+class IsEqual(BaseMatcher[Any]):
+ def __init__(self, equals: Any) -> None:
self.object = equals
- def _matches(self, item):
+ def _matches(self, item: Any) -> bool:
return item == self.object
- def describe_to(self, description):
+ def describe_to(self, description: Description) -> None:
nested_matcher = isinstance(self.object, Matcher)
if nested_matcher:
- description.append_text('<')
+ description.append_text("<")
description.append_description_of(self.object)
if nested_matcher:
- description.append_text('>')
+ description.append_text(">")
-def equal_to(obj):
+def equal_to(obj: Any) -> Matcher[Any]:
"""Matches if object is equal to a given object.
:param obj: The object to compare against as the expected value.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/core/isinstanceof.py b/contrib/python/PyHamcrest/py3/hamcrest/core/core/isinstanceof.py
index f8eb4a2fd10..e1a077bb0cb 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/core/isinstanceof.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/core/isinstanceof.py
@@ -1,32 +1,33 @@
+from typing import Type
+
from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
from hamcrest.core.helpers.wrap_matcher import is_matchable_type
+from hamcrest.core.matcher import Matcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
-import types
-
-class IsInstanceOf(BaseMatcher):
- def __init__(self, expected_type):
+class IsInstanceOf(BaseMatcher[object]):
+ def __init__(self, expected_type: Type) -> None:
if not is_matchable_type(expected_type):
- raise TypeError('IsInstanceOf requires type or a tuple of classes and types')
+ raise TypeError("IsInstanceOf requires type or a tuple of classes and types")
self.expected_type = expected_type
- def _matches(self, item):
+ def _matches(self, item: object) -> bool:
return isinstance(item, self.expected_type)
- def describe_to(self, description):
+ def describe_to(self, description: Description) -> None:
try:
type_description = self.expected_type.__name__
except AttributeError:
type_description = "one of %s" % ",".join(str(e) for e in self.expected_type)
- description.append_text('an instance of ') \
- .append_text(type_description)
+ description.append_text("an instance of ").append_text(type_description)
-def instance_of(atype):
+def instance_of(atype: Type) -> Matcher[object]:
"""Matches if object is an instance of, or inherits from, a given type.
:param atype: The type to compare against as the expected type or a tuple
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/core/isnone.py b/contrib/python/PyHamcrest/py3/hamcrest/core/core/isnone.py
index 511fd5ae461..1b4fbc123ae 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/core/isnone.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/core/isnone.py
@@ -1,26 +1,29 @@
-from __future__ import absolute_import
-__author__ = "Jon Reid"
-__copyright__ = "Copyright 2011 hamcrest.org"
-__license__ = "BSD, see License.txt"
+from typing import Any, Optional
from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
+from hamcrest.core.matcher import Matcher
+
from .isnot import is_not
+__author__ = "Jon Reid"
+__copyright__ = "Copyright 2011 hamcrest.org"
+__license__ = "BSD, see License.txt"
-class IsNone(BaseMatcher):
- def _matches(self, item):
+class IsNone(BaseMatcher[Optional[Any]]):
+ def _matches(self, item: Any) -> bool:
return item is None
- def describe_to(self, description):
- description.append_text('None')
+ def describe_to(self, description: Description) -> None:
+ description.append_text("None")
-def none():
+def none() -> Matcher[Optional[Any]]:
"""Matches if object is ``None``."""
return IsNone()
-def not_none():
+def not_none() -> Matcher[Optional[Any]]:
"""Matches if object is not ``None``."""
return is_not(none())
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/core/isnot.py b/contrib/python/PyHamcrest/py3/hamcrest/core/core/isnot.py
index 7567e6f325d..de26f68398d 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/core/isnot.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/core/isnot.py
@@ -1,33 +1,61 @@
-from __future__ import absolute_import
+from typing import Type, TypeVar, Union, overload
+
+from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
+from hamcrest.core.helpers.wrap_matcher import is_matchable_type, wrap_matcher
+from hamcrest.core.matcher import Matcher
+
+from .isinstanceof import instance_of
+
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
-from hamcrest.core.base_matcher import BaseMatcher, Matcher
-from hamcrest.core.helpers.wrap_matcher import wrap_matcher, is_matchable_type
-from .isequal import equal_to
-from .isinstanceof import instance_of
-
+T = TypeVar("T")
-class IsNot(BaseMatcher):
- def __init__(self, matcher):
+class IsNot(BaseMatcher[T]):
+ def __init__(self, matcher: Matcher[T]) -> None:
self.matcher = matcher
- def _matches(self, item):
+ def _matches(self, item: T) -> bool:
return not self.matcher.matches(item)
- def describe_to(self, description):
- description.append_text('not ').append_description_of(self.matcher)
+ def describe_to(self, description: Description) -> None:
+ description.append_text("not ").append_description_of(self.matcher)
+
+ def describe_mismatch(self, item: T, mismatch_description: Description) -> None:
+ mismatch_description.append_text("but ")
+ self.matcher.describe_match(item, mismatch_description)
+
+@overload
+def _wrap_value_or_type(x: Type) -> Matcher[object]:
+ ...
-def wrap_value_or_type(x):
+
+@overload
+def _wrap_value_or_type(x: T) -> Matcher[T]:
+ ...
+
+
+def _wrap_value_or_type(x):
if is_matchable_type(x):
return instance_of(x)
else:
return wrap_matcher(x)
+@overload
+def is_not(match: Type) -> Matcher[object]:
+ ...
+
+
+@overload
+def is_not(match: Union[Matcher[T], T]) -> Matcher[T]:
+ ...
+
+
def is_not(match):
"""Inverts the given matcher to its logical negation.
@@ -44,9 +72,10 @@ def is_not(match):
assert_that(cheese, is_not(smelly))
"""
- return IsNot(wrap_value_or_type(match))
+ return IsNot(_wrap_value_or_type(match))
+
-def not_(match):
+def not_(match: Union[Matcher[T], T]) -> Matcher[T]:
"""Alias of :py:func:`is_not` for better readability of negations.
Examples::
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/core/issame.py b/contrib/python/PyHamcrest/py3/hamcrest/core/core/issame.py
index b1f85427d7a..d4269444e6c 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/core/issame.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/core/issame.py
@@ -1,33 +1,36 @@
+from typing import TypeVar
+
+from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
+from hamcrest.core.matcher import Matcher
+
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
-from hamcrest.core.base_matcher import BaseMatcher
-
+T = TypeVar("T")
-class IsSame(BaseMatcher):
- def __init__(self, object):
- self.object = object
+class IsSame(BaseMatcher[T]):
+ def __init__(self, obj: T) -> None:
+ self.object = obj
- def _matches(self, item):
+ def _matches(self, item: T) -> bool:
return item is self.object
- def describe_to(self, description):
- description.append_text('same instance as ') \
- .append_text(hex(id(self.object))) \
- .append_text(' ') \
- .append_description_of(self.object)
+ def describe_to(self, description: Description) -> None:
+ description.append_text("same instance as ").append_text(hex(id(self.object))).append_text(
+ " "
+ ).append_description_of(self.object)
- def describe_mismatch(self, item, mismatch_description):
- mismatch_description.append_text('was ')
+ def describe_mismatch(self, item: T, mismatch_description: Description) -> None:
+ mismatch_description.append_text("was ")
if item is not None:
- mismatch_description.append_text(hex(id(item))) \
- .append_text(' ')
+ mismatch_description.append_text(hex(id(item))).append_text(" ")
mismatch_description.append_description_of(item)
-def same_instance(obj):
+def same_instance(obj: T) -> Matcher[T]:
"""Matches if evaluated object is the same instance as a given object.
:param obj: The object to compare against as the expected value.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/core/raises.py b/contrib/python/PyHamcrest/py3/hamcrest/core/core/raises.py
index 699a1ccc91d..dddbcb59093 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/core/raises.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/core/raises.py
@@ -1,32 +1,40 @@
-from weakref import ref
import re
import sys
+from typing import Any, Callable, Mapping, Optional, Tuple, Type, cast
+from weakref import ref
+
from hamcrest.core.base_matcher import BaseMatcher
-from hamcrest.core.helpers.wrap_matcher import wrap_matcher
-from hamcrest.core.compat import is_callable
+from hamcrest.core.description import Description
+from hamcrest.core.matcher import Matcher
__author__ = "Per Fagrell"
__copyright__ = "Copyright 2013 hamcrest.org"
__license__ = "BSD, see License.txt"
-class Raises(BaseMatcher):
- def __init__(self, expected, pattern=None, matcher=None):
+class Raises(BaseMatcher[Callable[..., Any]]):
+ def __init__(
+ self,
+ expected: Type[Exception],
+ pattern: Optional[str] = None,
+ matching: Optional[Matcher] = None,
+ matcher: Optional[Matcher] = None,
+ ) -> None:
self.pattern = pattern
+ self.matcher = matching or matcher
self.expected = expected
- self.actual = None
- self.function = None
- self.matcher = matcher
+ self.actual: Optional[BaseException] = None
+ self.function: Optional[Callable[..., Any]] = None
self.actual_return_value = None
- def _matches(self, function):
- if not is_callable(function):
+ def _matches(self, function: Callable[..., Any]) -> bool:
+ if not callable(function):
return False
- self.function = ref(function)
+ self.function = cast(Callable[..., Any], ref(function))
return self._call_function(function)
- def _call_function(self, function):
+ def _call_function(self, function: Callable[..., Any]) -> bool:
self.actual = None
try:
self.actual_return_value = function()
@@ -35,22 +43,23 @@ class Raises(BaseMatcher):
if isinstance(self.actual, self.expected):
if self.pattern is not None:
- return (
- re.search(self.pattern, str(self.actual)) is not None
- and (self.matcher is None or self.matcher.matches(self.actual))
- )
- return self.matcher is None or self.matcher.matches(self.actual)
+ if re.search(self.pattern, str(self.actual)) is None:
+ return False
+ if self.matcher is not None:
+ if not self.matcher.matches(self.actual):
+ return False
+ return True
return False
- def describe_to(self, description):
- description.append_text('Expected a callable raising %s' % self.expected)
+ def describe_to(self, description: Description) -> None:
+ description.append_text("Expected a callable raising %s" % self.expected)
if self.matcher is not None:
description.append_text("\n and ")
description.append_description_of(self.matcher)
- def describe_mismatch(self, item, description):
- if not is_callable(item):
- description.append_text('%s is not callable' % item)
+ def describe_mismatch(self, item, description: Description) -> None:
+ if not callable(item):
+ description.append_text("%s is not callable" % item)
return
function = None if self.function is None else self.function()
@@ -60,24 +69,36 @@ class Raises(BaseMatcher):
return
if self.actual is None:
- description.append_text('No exception raised and actual return value = ')
- description.append_value(self.actual_return_value)
+ description.append_text("No exception raised and actual return value = '{}'".format(self.actual_return_value))
elif isinstance(self.actual, self.expected):
- if self.pattern is not None:
- description.append_text('Correct assertion type raised, but the expected pattern ("%s") not found.' % self.pattern)
- description.append_text('\n message was: "%s"' % str(self.actual))
- if self.matcher is not None:
- description.append_text("\nAdditional exception matcher: ")
- self.matcher.describe_mismatch(self.actual, description)
+ if self.pattern is not None or self.matcher is not None:
+ description.append_text("Correct assertion type raised, but ")
+ if self.pattern is not None:
+ description.append_text('the expected pattern ("%s") ' % self.pattern)
+ if self.pattern is not None and self.matcher is not None:
+ description.append_text("and ")
+ if self.matcher is not None:
+ description.append_description_of(self.matcher)
+ description.append_text(" ")
+ description.append_text('not found. Exception message was: "%s"' % str(self.actual))
else:
- description.append_text('%r of type %s was raised instead' % (self.actual, type(self.actual)))
+ description.append_text(
+ "%r of type %s was raised instead" % (self.actual, type(self.actual))
+ )
+
+ def describe_match(self, item, match_description: Description) -> None:
+ self._call_function(item)
+ match_description.append_text(
+ "%r of type %s was raised." % (self.actual, type(self.actual))
+ )
-def raises(exception, pattern=None, matcher=None):
+def raises(exception: Type[Exception], pattern=None, matching=None, matcher=None) -> Matcher[Callable[..., Any]]:
"""Matches if the called function raised the expected exception.
:param exception: The class of the expected exception
:param pattern: Optional regular expression to match exception message.
+ :param matching: Optional Hamcrest matchers to apply to the exception.
Expects the actual to be wrapped by using :py:func:`~hamcrest.core.core.raises.calling`,
or a callable taking no arguments.
@@ -88,15 +109,19 @@ def raises(exception, pattern=None, matcher=None):
assert_that(calling(int).with_args('q'), raises(TypeError))
assert_that(calling(parse, broken_input), raises(ValueError))
+ assert_that(
+ calling(valid_user, bad_json),
+ raises(HTTPError, matching=has_properties(status_code=500)
+ )
"""
- return Raises(exception, pattern, matcher)
+ return Raises(exception, pattern, matching, matcher)
class DeferredCallable(object):
- def __init__(self, func):
+ def __init__(self, func: Callable[..., Any]):
self.func = func
- self.args = tuple()
- self.kwargs = {}
+ self.args: Tuple[Any, ...] = tuple()
+ self.kwargs: Mapping[str, Any] = {}
def __call__(self):
self.func(*self.args, **self.kwargs)
@@ -107,7 +132,7 @@ class DeferredCallable(object):
return self
-def calling(func):
+def calling(func: Callable[..., Any]) -> DeferredCallable:
"""Wrapper for function call that delays the actual execution so that
:py:func:`~hamcrest.core.core.raises.raises` matcher can catch any thrown exception.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/description.py b/contrib/python/PyHamcrest/py3/hamcrest/core/description.py
index 6201b7f70f9..6f22414bfda 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/description.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/description.py
@@ -1,9 +1,11 @@
+from typing import Any, Iterable
+
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
-class Description(object):
+class Description:
"""A description of a :py:class:`~hamcrest.core.matcher.Matcher`.
A :py:class:`~hamcrest.core.matcher.Matcher` will describe itself to a
@@ -11,15 +13,15 @@ class Description(object):
"""
- def append_text(self, text):
+ def append_text(self, text: str) -> "Description":
"""Appends some plain text to the description.
:returns: ``self``, for chaining
"""
- raise NotImplementedError('append_text')
+ raise NotImplementedError("append_text")
- def append_description_of(self, value):
+ def append_description_of(self, value: Any) -> "Description":
"""Appends description of given value to this description.
If the value implements
@@ -29,21 +31,11 @@ class Description(object):
:returns: ``self``, for chaining
"""
- raise NotImplementedError('append_description_of')
-
- def append_value(self, value):
- """Appends an arbitary value to the description.
-
- **Deprecated:** Call
- :py:meth:`~hamcrest.core.description.Description.append_description_of`
- instead.
-
- :returns: ``self``, for chaining
-
- """
- raise NotImplementedError('append_value')
+ raise NotImplementedError("append_description_of")
- def append_list(self, start, separator, end, list):
+ def append_list(
+ self, start: str, separator: str, end: str, list: Iterable[Any]
+ ) -> "Description":
"""Appends a list of objects to the description.
:param start: String that will begin the list description.
@@ -55,4 +47,4 @@ class Description(object):
:returns: ``self``, for chaining
"""
- raise NotImplementedError('append_list')
+ raise NotImplementedError("append_list")
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/helpers/hasmethod.py b/contrib/python/PyHamcrest/py3/hamcrest/core/helpers/hasmethod.py
index a1f3bfb1549..fcf41208b9d 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/helpers/hasmethod.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/helpers/hasmethod.py
@@ -3,7 +3,7 @@ __copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
-def hasmethod(obj, methodname):
+def hasmethod(obj: object, methodname: str) -> bool:
"""Does ``obj`` have a method named ``methodname``?"""
if not hasattr(obj, methodname):
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/helpers/ismock.py b/contrib/python/PyHamcrest/py3/hamcrest/core/helpers/ismock.py
index 318e0d4f9cb..56f24f4ab51 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/helpers/ismock.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/helpers/ismock.py
@@ -1,15 +1,19 @@
-MOCKTYPES = ()
+from typing import Any, List, Type
+
+MOCKTYPES: List[Type] = []
try:
from mock import Mock
- MOCKTYPES += (Mock,)
+
+ MOCKTYPES += [Mock]
except ImportError:
pass
try:
from unittest.mock import Mock
- MOCKTYPES += (Mock,)
+
+ MOCKTYPES += [Mock]
except ImportError:
pass
-def ismock(obj):
- return isinstance(obj, MOCKTYPES)
+def ismock(obj: Any) -> bool:
+ return isinstance(obj, tuple(MOCKTYPES))
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/helpers/wrap_matcher.py b/contrib/python/PyHamcrest/py3/hamcrest/core/helpers/wrap_matcher.py
index 587ae4c6101..b2574203a86 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/helpers/wrap_matcher.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/helpers/wrap_matcher.py
@@ -1,4 +1,4 @@
-import six
+from typing import Type, TypeVar, Union
from hamcrest.core.base_matcher import Matcher
from hamcrest.core.core.isequal import equal_to
@@ -7,9 +7,10 @@ __author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
-import types
+T = TypeVar("T")
-def wrap_matcher(x):
+
+def wrap_matcher(x: Union[Matcher[T], T]) -> Matcher[T]:
"""Wraps argument in a matcher, if necessary.
:returns: the argument as-is if it is already a matcher, otherwise wrapped
@@ -21,11 +22,9 @@ def wrap_matcher(x):
else:
return equal_to(x)
-def is_matchable_type(expected_type):
- if isinstance(expected_type, type):
- return True
- if isinstance(expected_type, six.class_types):
+def is_matchable_type(expected_type: Type) -> bool:
+ if isinstance(expected_type, type):
return True
if isinstance(expected_type, tuple) and all(map(is_matchable_type, expected_type)):
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/matcher.py b/contrib/python/PyHamcrest/py3/hamcrest/core/matcher.py
index 81ee27c6d9d..7ee5ece12f3 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/matcher.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/matcher.py
@@ -1,12 +1,17 @@
-from __future__ import absolute_import
+from typing import Generic, Optional, TypeVar
+
+from hamcrest.core.description import Description
+
from .selfdescribing import SelfDescribing
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
+T = TypeVar("T")
+
-class Matcher(SelfDescribing):
+class Matcher(Generic[T], SelfDescribing):
"""A matcher over acceptable values.
A matcher is able to describe itself to give feedback when it fails.
@@ -20,7 +25,7 @@ class Matcher(SelfDescribing):
"""
- def matches(self, item, mismatch_description=None):
+ def matches(self, item: T, mismatch_description: Optional[Description] = None) -> bool:
"""Evaluates the matcher for argument item.
If a mismatch is detected and argument ``mismatch_description`` is
@@ -28,12 +33,13 @@ class Matcher(SelfDescribing):
accepted the item.
:param item: The object against which the matcher is evaluated.
+ :param mismatch_description:
:returns: ``True`` if ``item`` matches, otherwise ``False``.
"""
- raise NotImplementedError('matches')
+ raise NotImplementedError("matches")
- def describe_mismatch(self, item, mismatch_description):
+ def describe_mismatch(self, item: T, mismatch_description: Description) -> None:
"""Generates a description of why the matcher has not accepted the
item.
@@ -49,4 +55,20 @@ class Matcher(SelfDescribing):
to.
"""
- raise NotImplementedError('describe_mismatch')
+ raise NotImplementedError("describe_mismatch")
+
+ def describe_match(self, item: T, match_description: Description) -> None:
+ """Generates a description of why the matcher has accepted the item.
+
+ The description may be part of a larger description of why a matching
+ failed, so it should be concise.
+
+ This method assumes that ``matches(item)`` is ``True``, but will not
+ check this.
+
+ :param item: The item that the
+ :py:class:`~hamcrest.core.matcher.Matcher` has accepted.
+ :param match_description: The description to be built or appended to.
+
+ """
+ raise NotImplementedError("describe_match")
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/selfdescribing.py b/contrib/python/PyHamcrest/py3/hamcrest/core/selfdescribing.py
index e77b0e0fdb6..d57cb6ef0c0 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/selfdescribing.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/selfdescribing.py
@@ -1,12 +1,14 @@
+from hamcrest.core.description import Description
+
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
-class SelfDescribing(object):
+class SelfDescribing:
"""The ability of an object to describe itself."""
- def describe_to(self, description):
+ def describe_to(self, description: Description) -> None:
"""Generates a description of the object.
The description may be part of a description of a larger object of
@@ -15,4 +17,4 @@ class SelfDescribing(object):
:param description: The description to be built or appended to.
"""
- raise NotImplementedError('describe_to')
+ raise NotImplementedError("describe_to")
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/selfdescribingvalue.py b/contrib/python/PyHamcrest/py3/hamcrest/core/selfdescribingvalue.py
index 7f471e04f2d..148ca01f4f6 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/selfdescribingvalue.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/selfdescribingvalue.py
@@ -1,6 +1,8 @@
-from hamcrest.core.selfdescribing import SelfDescribing
-
import warnings
+from typing import Any
+
+from hamcrest.core.description import Description
+from hamcrest.core.selfdescribing import SelfDescribing
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
@@ -17,11 +19,10 @@ class SelfDescribingValue(SelfDescribing):
"""
- def __init__(self, value):
- warnings.warn('SelfDescribingValue no longer needed',
- DeprecationWarning)
+ def __init__(self, value: Any) -> None:
+ warnings.warn("SelfDescribingValue no longer needed", DeprecationWarning)
self.value = value
- def describe_to(self, description):
+ def describe_to(self, description: Description) -> None:
"""Generates a description of the value."""
description.append_description_of(self.value)
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/core/string_description.py b/contrib/python/PyHamcrest/py3/hamcrest/core/string_description.py
index 172dfb4ff22..96fbb26080d 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/core/string_description.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/core/string_description.py
@@ -1,7 +1,4 @@
-from __future__ import absolute_import
-
-import codecs
-import six
+from hamcrest.core.selfdescribing import SelfDescribing
from .base_description import BaseDescription
@@ -10,7 +7,7 @@ __copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
-def tostring(selfdescribing):
+def tostring(selfdescribing: SelfDescribing) -> str:
"""Returns the description of a
:py:class:`~hamcrest.core.selfdescribing.SelfDescribing` object as a
string.
@@ -27,18 +24,12 @@ class StringDescription(BaseDescription):
"""
- def __init__(self):
- self.out = ''
+ def __init__(self) -> None:
+ self.out = ""
- def __str__(self):
+ def __str__(self) -> str:
"""Returns the description."""
return self.out
- def append(self, string):
- if six.PY3:
- self.out += str(string)
- else:
- if isinstance(string, unicode):
- self.out += string
- else:
- self.out += unicode(string, errors="ignore")
+ def append(self, string: str) -> None:
+ self.out += str(string)
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/__init__.py b/contrib/python/PyHamcrest/py3/hamcrest/library/__init__.py
index d5f909c9216..fb02c2bbb53 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/__init__.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/__init__.py
@@ -1,4 +1,3 @@
-from __future__ import absolute_import
"""Library of Matcher implementations."""
from hamcrest.core import *
@@ -13,33 +12,33 @@ __copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
__all__ = [
- 'has_entry',
- 'has_entries',
- 'has_key',
- 'has_value',
- 'is_in',
- 'empty',
- 'has_item',
- 'has_items',
- 'contains_inanyorder',
- 'contains',
- 'contains_exactly',
- 'only_contains',
- 'match_equality',
- 'matches_regexp',
- 'close_to',
- 'greater_than',
- 'greater_than_or_equal_to',
- 'less_than',
- 'less_than_or_equal_to',
- 'has_length',
- 'has_property',
- 'has_properties',
- 'has_string',
- 'equal_to_ignoring_case',
- 'equal_to_ignoring_whitespace',
- 'contains_string',
- 'ends_with',
- 'starts_with',
- 'string_contains_in_order',
+ "has_entry",
+ "has_entries",
+ "has_key",
+ "has_value",
+ "is_in",
+ "empty",
+ "has_item",
+ "has_items",
+ "contains_inanyorder",
+ "contains",
+ "contains_exactly",
+ "only_contains",
+ "match_equality",
+ "matches_regexp",
+ "close_to",
+ "greater_than",
+ "greater_than_or_equal_to",
+ "less_than",
+ "less_than_or_equal_to",
+ "has_length",
+ "has_property",
+ "has_properties",
+ "has_string",
+ "equal_to_ignoring_case",
+ "equal_to_ignoring_whitespace",
+ "contains_string",
+ "ends_with",
+ "starts_with",
+ "string_contains_in_order",
]
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/__init__.py b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/__init__.py
index f910e973259..bf07a66e624 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/__init__.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/__init__.py
@@ -1,5 +1,5 @@
"""Matchers of collections."""
-from __future__ import absolute_import
+from .is_empty import empty
from .isdict_containing import has_entry
from .isdict_containingentries import has_entries
from .isdict_containingkey import has_key
@@ -9,8 +9,22 @@ from .issequence_containing import has_item, has_items
from .issequence_containinginanyorder import contains_inanyorder
from .issequence_containinginorder import contains, contains_exactly
from .issequence_onlycontaining import only_contains
-from .is_empty import empty
__author__ = "Chris Rose"
__copyright__ = "Copyright 2013 hamcrest.org"
__license__ = "BSD, see License.txt"
+
+__all__ = [
+ "contains",
+ "contains_exactly",
+ "contains_inanyorder",
+ "empty",
+ "has_entries",
+ "has_entry",
+ "has_item",
+ "has_items",
+ "has_key",
+ "has_value",
+ "is_in",
+ "only_contains",
+]
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/is_empty.py b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/is_empty.py
index bc99b633730..cff60d636d0 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/is_empty.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/is_empty.py
@@ -1,33 +1,34 @@
+from typing import Optional, Sized
+
from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
+from hamcrest.core.matcher import Matcher
__author__ = "Chris Rose"
__copyright__ = "Copyright 2012 hamcrest.org"
__license__ = "BSD, see License.txt"
-class IsEmpty(BaseMatcher):
-
- def matches(self, item, mismatch_description=None):
+class IsEmpty(BaseMatcher[Sized]):
+ def matches(self, item: Sized, mismatch_description: Optional[Description] = None) -> bool:
try:
if len(item) == 0:
return True
if mismatch_description:
- mismatch_description \
- .append_text('has %d item(s)' % len(item))
+ mismatch_description.append_text("has %d item(s)" % len(item))
except TypeError:
if mismatch_description:
- mismatch_description \
- .append_text('does not support length')
+ mismatch_description.append_text("does not support length")
- return False
+ return False
- def describe_to(self, description):
- description.append_text('an empty collection')
+ def describe_to(self, description: Description) -> None:
+ description.append_text("an empty collection")
-def empty():
+def empty() -> Matcher[Sized]:
"""
This matcher matches any collection-like object that responds to the
__len__ method, and has a length of 0.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containing.py b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containing.py
index 95281973fb5..cfe1a5e86ae 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containing.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containing.py
@@ -1,34 +1,69 @@
+from typing import Hashable, Mapping, MutableMapping, TypeVar, Union
+
from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
from hamcrest.core.helpers.hasmethod import hasmethod
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
+from hamcrest.core.matcher import Matcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
-class IsDictContaining(BaseMatcher):
+K = TypeVar("K", bound=Hashable) # TODO - covariant?
+V = TypeVar("V")
+
- def __init__(self, key_matcher, value_matcher):
+class IsDictContaining(BaseMatcher[Mapping[K, V]]):
+ def __init__(self, key_matcher: Matcher[K], value_matcher: Matcher[V]) -> None:
self.key_matcher = key_matcher
self.value_matcher = value_matcher
- def _matches(self, dictionary):
- if hasmethod(dictionary, 'items'):
- for key, value in dictionary.items():
+ def _matches(self, item: Mapping[K, V]) -> bool:
+ if hasmethod(item, "items"):
+ for key, value in item.items():
if self.key_matcher.matches(key) and self.value_matcher.matches(value):
return True
return False
- def describe_to(self, description):
- description.append_text('a dictionary containing [') \
- .append_description_of(self.key_matcher) \
- .append_text(': ') \
- .append_description_of(self.value_matcher) \
- .append_text(']')
+ def describe_to(self, description: Description) -> None:
+ description.append_text("a dictionary containing [").append_description_of(
+ self.key_matcher
+ ).append_text(": ").append_description_of(self.value_matcher).append_text("]")
+
+ def describe_mismatch(self, item: Mapping[K, V], mismatch_description: Description) -> None:
+ key_matches = self._matching_keys(item)
+ if len(key_matches) == 1:
+ key, value = key_matches.popitem()
+ mismatch_description.append_text("value for ").append_description_of(key).append_text(
+ " "
+ )
+ self.value_matcher.describe_mismatch(value, mismatch_description)
+ else:
+ super().describe_mismatch(item, mismatch_description)
+
+ def describe_match(self, item: Mapping[K, V], match_description: Description) -> None:
+ key_matches = self._matching_keys(item)
+ if len(key_matches) == 1:
+ key, value = key_matches.popitem()
+ match_description.append_text("value for ").append_description_of(key).append_text(" ")
+ self.value_matcher.describe_mismatch(value, match_description)
+ else:
+ super().describe_match(item, match_description)
+
+ def _matching_keys(self, item) -> MutableMapping[K, V]:
+ key_matches: MutableMapping[K, V] = {}
+ if hasmethod(item, "items"):
+ for key, value in item.items():
+ if self.key_matcher.matches(key):
+ key_matches[key] = value
+ return key_matches
-def has_entry(key_match, value_match):
+def has_entry(
+ key_match: Union[K, Matcher[K]], value_match: Union[V, Matcher[V]]
+) -> Matcher[Mapping[K, V]]:
"""Matches if dictionary contains key-value entry satisfying a given pair
of matchers.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containingentries.py b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containingentries.py
index eb83ade52de..79341ff9310 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containingentries.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containingentries.py
@@ -1,70 +1,92 @@
+from typing import Any, Hashable, Mapping, Optional, TypeVar, Union, overload
+
from hamcrest.core.base_matcher import BaseMatcher
-from hamcrest.core.helpers.hasmethod import hasmethod
+from hamcrest.core.description import Description
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
+from hamcrest.core.matcher import Matcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
+K = TypeVar("K", bound=Hashable)
+V = TypeVar("V")
-class IsDictContainingEntries(BaseMatcher):
- def __init__(self, value_matchers):
+class IsDictContainingEntries(BaseMatcher[Mapping[K, V]]):
+ def __init__(self, value_matchers) -> None:
self.value_matchers = sorted(value_matchers.items())
- def _not_a_dictionary(self, dictionary, mismatch_description):
+ def _not_a_dictionary(
+ self, item: Mapping[K, V], mismatch_description: Optional[Description]
+ ) -> bool:
if mismatch_description:
- mismatch_description.append_description_of(dictionary) \
- .append_text(' is not a mapping object')
+ mismatch_description.append_description_of(item).append_text(" is not a mapping object")
return False
- def matches(self, dictionary, mismatch_description=None):
+ def matches(
+ self, item: Mapping[K, V], mismatch_description: Optional[Description] = None
+ ) -> bool:
for key, value_matcher in self.value_matchers:
-
try:
- if not key in dictionary:
+ if key not in item:
if mismatch_description:
- mismatch_description.append_text('no ') \
- .append_description_of(key) \
- .append_text(' key in ') \
- .append_description_of(dictionary)
+ mismatch_description.append_text("no ").append_description_of(
+ key
+ ).append_text(" key in ").append_description_of(item)
return False
except TypeError:
- return self._not_a_dictionary(dictionary, mismatch_description)
+ return self._not_a_dictionary(item, mismatch_description)
try:
- actual_value = dictionary[key]
+ actual_value = item[key]
except TypeError:
- return self._not_a_dictionary(dictionary, mismatch_description)
+ return self._not_a_dictionary(item, mismatch_description)
if not value_matcher.matches(actual_value):
if mismatch_description:
- mismatch_description.append_text('value for ') \
- .append_description_of(key) \
- .append_text(' ')
+ mismatch_description.append_text("value for ").append_description_of(
+ key
+ ).append_text(" ")
value_matcher.describe_mismatch(actual_value, mismatch_description)
return False
return True
- def describe_mismatch(self, item, mismatch_description):
+ def describe_mismatch(self, item: Mapping[K, V], mismatch_description: Description) -> None:
self.matches(item, mismatch_description)
- def describe_keyvalue(self, index, value, description):
+ def describe_keyvalue(self, index: K, value: V, description: Description) -> None:
"""Describes key-value pair at given index."""
- description.append_description_of(index) \
- .append_text(': ') \
- .append_description_of(value)
+ description.append_description_of(index).append_text(": ").append_description_of(value)
- def describe_to(self, description):
- description.append_text('a dictionary containing {')
+ def describe_to(self, description: Description) -> None:
+ description.append_text("a dictionary containing {")
first = True
for key, value in self.value_matchers:
if not first:
- description.append_text(', ')
+ description.append_text(", ")
self.describe_keyvalue(key, value, description)
first = False
- description.append_text('}')
+ description.append_text("}")
+
+
+# Keyword argument form
+@overload
+def has_entries(**keys_valuematchers: Union[Matcher[V], V]) -> Matcher[Mapping[str, V]]:
+ ...
+
+
+# Key to matcher dict form
+@overload
+def has_entries(keys_valuematchers: Mapping[K, Union[Matcher[V], V]]) -> Matcher[Mapping[K, V]]:
+ ...
+
+
+# Alternating key/matcher form
+@overload
+def has_entries(*keys_valuematchers: Any) -> Matcher[Mapping[Any, Any]]:
+ ...
def has_entries(*keys_valuematchers, **kv_args):
@@ -119,13 +141,17 @@ def has_entries(*keys_valuematchers, **kv_args):
for key in base_dict:
base_dict[key] = wrap_matcher(base_dict[key])
except AttributeError:
- raise ValueError('single-argument calls to has_entries must pass a dict as the argument')
+ raise ValueError(
+ "single-argument calls to has_entries must pass a dict as the argument"
+ )
else:
if len(keys_valuematchers) % 2:
- raise ValueError('has_entries requires key-value pairs')
+ raise ValueError("has_entries requires key-value pairs")
base_dict = {}
for index in range(int(len(keys_valuematchers) / 2)):
- base_dict[keys_valuematchers[2 * index]] = wrap_matcher(keys_valuematchers[2 * index + 1])
+ base_dict[keys_valuematchers[2 * index]] = wrap_matcher(
+ keys_valuematchers[2 * index + 1]
+ )
for key, value in kv_args.items():
base_dict[key] = wrap_matcher(value)
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containingkey.py b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containingkey.py
index ccb51e6396d..90c7cc79ac6 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containingkey.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containingkey.py
@@ -1,30 +1,36 @@
+from typing import Any, Hashable, Mapping, TypeVar, Union
+
from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
from hamcrest.core.helpers.hasmethod import hasmethod
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
+from hamcrest.core.matcher import Matcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
+K = TypeVar("K", bound=Hashable)
-class IsDictContainingKey(BaseMatcher):
- def __init__(self, key_matcher):
+class IsDictContainingKey(BaseMatcher[Mapping[K, Any]]):
+ def __init__(self, key_matcher: Matcher[K]) -> None:
self.key_matcher = key_matcher
- def _matches(self, dictionary):
- if hasmethod(dictionary, 'keys'):
- for key in dictionary.keys():
+ def _matches(self, item: Mapping[K, Any]) -> bool:
+ if hasmethod(item, "keys"):
+ for key in item.keys():
if self.key_matcher.matches(key):
return True
return False
- def describe_to(self, description):
- description.append_text('a dictionary containing key ') \
- .append_description_of(self.key_matcher)
+ def describe_to(self, description: Description) -> None:
+ description.append_text("a dictionary containing key ").append_description_of(
+ self.key_matcher
+ )
-def has_key(key_match):
+def has_key(key_match: Union[K, Matcher[K]]) -> Matcher[Mapping[K, Any]]:
"""Matches if dictionary contains an entry whose key satisfies a given
matcher.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containingvalue.py b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containingvalue.py
index e5288841b26..ca5b71aa380 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containingvalue.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isdict_containingvalue.py
@@ -1,30 +1,36 @@
+from typing import Any, Mapping, TypeVar, Union
+
from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
from hamcrest.core.helpers.hasmethod import hasmethod
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
+from hamcrest.core.matcher import Matcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
+V = TypeVar("V")
-class IsDictContainingValue(BaseMatcher):
- def __init__(self, value_matcher):
+class IsDictContainingValue(BaseMatcher[Mapping[Any, V]]):
+ def __init__(self, value_matcher: Matcher[V]) -> None:
self.value_matcher = value_matcher
- def _matches(self, dictionary):
- if hasmethod(dictionary, 'values'):
- for value in dictionary.values():
+ def _matches(self, item: Mapping[Any, V]) -> bool:
+ if hasmethod(item, "values"):
+ for value in item.values():
if self.value_matcher.matches(value):
return True
return False
- def describe_to(self, description):
- description.append_text('a dictionary containing value ') \
- .append_description_of(self.value_matcher)
+ def describe_to(self, description: Description) -> None:
+ description.append_text("a dictionary containing value ").append_description_of(
+ self.value_matcher
+ )
-def has_value(value):
+def has_value(value: Union[V, Matcher[V]]) -> Matcher[Mapping[Any, V]]:
"""Matches if dictionary contains an entry whose value satisfies a given
matcher.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isin.py b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isin.py
index 87962a2474b..e958ea315ca 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isin.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/isin.py
@@ -1,24 +1,28 @@
+from typing import Sequence, TypeVar
+
from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
+from hamcrest.core.matcher import Matcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
+T = TypeVar("T")
-class IsIn(BaseMatcher):
- def __init__(self, sequence):
+class IsIn(BaseMatcher[T]):
+ def __init__(self, sequence: Sequence[T]) -> None:
self.sequence = sequence
- def _matches(self, item):
+ def _matches(self, item: T) -> bool:
return item in self.sequence
- def describe_to(self, description):
- description.append_text('one of ') \
- .append_list('(', ', ', ')', self.sequence)
+ def describe_to(self, description: Description) -> None:
+ description.append_text("one of ").append_list("(", ", ", ")", self.sequence)
-def is_in(sequence):
+def is_in(sequence: Sequence[T]) -> Matcher[T]:
"""Matches if evaluated object is present in a given sequence.
:param sequence: The sequence to search.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_containing.py b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_containing.py
index 21939b3f3f3..f615dcc7427 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_containing.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_containing.py
@@ -1,56 +1,60 @@
-__author__ = "Jon Reid"
-__copyright__ = "Copyright 2011 hamcrest.org"
-__license__ = "BSD, see License.txt"
+from typing import Sequence, TypeVar, Union, cast
from hamcrest.core.base_matcher import BaseMatcher
from hamcrest.core.core.allof import all_of
-from hamcrest.core.helpers.hasmethod import hasmethod
+from hamcrest.core.description import Description
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
+from hamcrest.core.matcher import Matcher
+
+__author__ = "Jon Reid"
+__copyright__ = "Copyright 2011 hamcrest.org"
+__license__ = "BSD, see License.txt"
+T = TypeVar("T")
-class IsSequenceContaining(BaseMatcher):
- def __init__(self, element_matcher):
+class IsSequenceContaining(BaseMatcher[Sequence[T]]):
+ def __init__(self, element_matcher: Matcher[T]) -> None:
self.element_matcher = element_matcher
- def _matches(self, sequence):
+ def _matches(self, item: Sequence[T]) -> bool:
try:
- for item in sequence:
- if self.element_matcher.matches(item):
+ for element in item:
+ if self.element_matcher.matches(element):
return True
- except TypeError: # not a sequence
- return False
+ except TypeError: # not a sequence
+ pass
+ return False
- def describe_to(self, description):
- description.append_text('a sequence containing ') \
- .append_description_of(self.element_matcher)
+ def describe_to(self, description: Description) -> None:
+ description.append_text("a sequence containing ").append_description_of(
+ self.element_matcher
+ )
# It'd be great to make use of all_of, but we can't be sure we won't
# be seeing a one-time sequence here (like a generator); see issue #20
# Instead, we wrap it inside a class that will convert the sequence into
# a concrete list and then hand it off to the all_of matcher.
-class IsSequenceContainingEvery(BaseMatcher):
+class IsSequenceContainingEvery(BaseMatcher[Sequence[T]]):
+ def __init__(self, *element_matchers: Matcher[T]) -> None:
+ delegates = [cast(Matcher[Sequence[T]], has_item(e)) for e in element_matchers]
+ self.matcher: Matcher[Sequence[T]] = all_of(*delegates)
- def __init__(self, *element_matchers):
- delegates = [has_item(e) for e in element_matchers]
- self.matcher = all_of(*delegates)
-
- def _matches(self, sequence):
+ def _matches(self, item: Sequence[T]) -> bool:
try:
- return self.matcher.matches(list(sequence))
+ return self.matcher.matches(list(item))
except TypeError:
return False
- def describe_mismatch(self, item, mismatch_description):
+ def describe_mismatch(self, item: Sequence[T], mismatch_description: Description) -> None:
self.matcher.describe_mismatch(item, mismatch_description)
- def describe_to(self, description):
+ def describe_to(self, description: Description) -> None:
self.matcher.describe_to(description)
-
-def has_item(match):
+def has_item(match: Union[Matcher[T], T]) -> Matcher[Sequence[T]]:
"""Matches if any element of sequence satisfies a given matcher.
:param match: The matcher to satisfy, or an expected value for
@@ -68,7 +72,7 @@ def has_item(match):
return IsSequenceContaining(wrap_matcher(match))
-def has_items(*items):
+def has_items(*items: Union[Matcher[T], T]) -> Matcher[Sequence[T]]:
"""Matches if all of the given matchers are satisfied by any elements of
the sequence.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_containinginanyorder.py b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_containinginanyorder.py
index 78e2b006fcc..431709c290c 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_containinginanyorder.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_containinginanyorder.py
@@ -1,79 +1,85 @@
+from typing import MutableSequence, Optional, Sequence, TypeVar, Union, cast
+
from hamcrest.core.base_matcher import BaseMatcher
-from hamcrest.core.helpers.hasmethod import hasmethod
+from hamcrest.core.description import Description
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
+from hamcrest.core.matcher import Matcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
+T = TypeVar("T")
+
class MatchInAnyOrder(object):
- def __init__(self, matchers, mismatch_description):
- self.matchers = matchers[:]
+ def __init__(
+ self, matchers: Sequence[Matcher[T]], mismatch_description: Optional[Description]
+ ) -> None:
+ self.matchers = cast(MutableSequence[Matcher[T]], matchers[:])
self.mismatch_description = mismatch_description
- def matches(self, item):
+ def matches(self, item: T) -> bool:
return self.isnotsurplus(item) and self.ismatched(item)
- def isfinished(self, sequence):
+ def isfinished(self, item: Sequence[T]) -> bool:
if not self.matchers:
return True
if self.mismatch_description:
- self.mismatch_description.append_text('no item matches: ') \
- .append_list('', ', ', '', self.matchers) \
- .append_text(' in ') \
- .append_list('[', ', ', ']', sequence)
+ self.mismatch_description.append_text("no item matches: ").append_list(
+ "", ", ", "", self.matchers
+ ).append_text(" in ").append_list("[", ", ", "]", item)
return False
- def isnotsurplus(self, item):
+ def isnotsurplus(self, item: T) -> bool:
if not self.matchers:
if self.mismatch_description:
- self.mismatch_description.append_text('not matched: ') \
- .append_description_of(item)
+ self.mismatch_description.append_text("not matched: ").append_description_of(item)
return False
return True
- def ismatched(self, item):
+ def ismatched(self, item: T) -> bool:
for index, matcher in enumerate(self.matchers):
if matcher.matches(item):
del self.matchers[index]
return True
if self.mismatch_description:
- self.mismatch_description.append_text('not matched: ') \
- .append_description_of(item)
+ self.mismatch_description.append_text("not matched: ").append_description_of(item)
return False
-class IsSequenceContainingInAnyOrder(BaseMatcher):
-
- def __init__(self, matchers):
+class IsSequenceContainingInAnyOrder(BaseMatcher[Sequence[T]]):
+ def __init__(self, matchers: Sequence[Matcher[T]]) -> None:
self.matchers = matchers
- def matches(self, sequence, mismatch_description=None):
+ def matches(
+ self, item: Sequence[T], mismatch_description: Optional[Description] = None
+ ) -> bool:
try:
- sequence = list(sequence)
+ sequence = list(item)
matchsequence = MatchInAnyOrder(self.matchers, mismatch_description)
- for item in sequence:
- if not matchsequence.matches(item):
+ for element in sequence:
+ if not matchsequence.matches(element):
return False
return matchsequence.isfinished(sequence)
except TypeError:
if mismatch_description:
- super(IsSequenceContainingInAnyOrder, self) \
- .describe_mismatch(sequence, mismatch_description)
+ super(IsSequenceContainingInAnyOrder, self).describe_mismatch(
+ item, mismatch_description
+ )
return False
- def describe_mismatch(self, item, mismatch_description):
+ def describe_mismatch(self, item: Sequence[T], mismatch_description: Description) -> None:
self.matches(item, mismatch_description)
- def describe_to(self, description):
- description.append_text('a sequence over ') \
- .append_list('[', ', ', ']', self.matchers) \
- .append_text(' in any order')
+ def describe_to(self, description: Description) -> None:
+ description.append_text("a sequence over ").append_list(
+ "[", ", ", "]", self.matchers
+ ).append_text(" in any order")
-def contains_inanyorder(*items):
+def contains_inanyorder(*items: Union[Matcher[T], T]) -> Matcher[Sequence[T]]:
"""Matches if sequences's elements, in any order, satisfy a given list of
matchers.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_containinginorder.py b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_containinginorder.py
index 7c37b328b61..c7cbda3af07 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_containinginorder.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_containinginorder.py
@@ -1,77 +1,84 @@
import warnings
+from typing import Optional, Sequence, TypeVar, Union
+
+from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
+from hamcrest.core.helpers.wrap_matcher import wrap_matcher
+from hamcrest.core.matcher import Matcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
-from hamcrest.core.base_matcher import BaseMatcher
-from hamcrest.core.helpers.hasmethod import hasmethod
-from hamcrest.core.helpers.wrap_matcher import wrap_matcher
+T = TypeVar("T")
class MatchingInOrder(object):
- def __init__(self, matchers, mismatch_description):
+ def __init__(
+ self, matchers: Sequence[Matcher[T]], mismatch_description: Optional[Description]
+ ) -> None:
self.matchers = matchers
self.mismatch_description = mismatch_description
self.next_match_index = 0
- def matches(self, item):
+ def matches(self, item: T) -> bool:
return self.isnotsurplus(item) and self.ismatched(item)
- def isfinished(self):
+ def isfinished(self) -> bool:
if self.next_match_index < len(self.matchers):
if self.mismatch_description:
- self.mismatch_description.append_text('No item matched: ') \
- .append_description_of(self.matchers[self.next_match_index])
+ self.mismatch_description.append_text("No item matched: ").append_description_of(
+ self.matchers[self.next_match_index]
+ )
return False
return True
- def ismatched(self, item):
+ def ismatched(self, item: T) -> bool:
matcher = self.matchers[self.next_match_index]
if not matcher.matches(item):
if self.mismatch_description:
- self.mismatch_description.append_text('item ' + str(self.next_match_index) + ': ')
+ self.mismatch_description.append_text("item " + str(self.next_match_index) + ": ")
matcher.describe_mismatch(item, self.mismatch_description)
return False
self.next_match_index += 1
return True
- def isnotsurplus(self, item):
+ def isnotsurplus(self, item: T) -> bool:
if len(self.matchers) <= self.next_match_index:
if self.mismatch_description:
- self.mismatch_description.append_text('Not matched: ') \
- .append_description_of(item)
+ self.mismatch_description.append_text("Not matched: ").append_description_of(item)
return False
return True
-class IsSequenceContainingInOrder(BaseMatcher):
-
- def __init__(self, matchers):
+class IsSequenceContainingInOrder(BaseMatcher[Sequence[T]]):
+ def __init__(self, matchers: Sequence[Matcher[T]]) -> None:
self.matchers = matchers
- def matches(self, sequence, mismatch_description=None):
+ def matches(
+ self, item: Sequence[T], mismatch_description: Optional[Description] = None
+ ) -> bool:
try:
matchsequence = MatchingInOrder(self.matchers, mismatch_description)
- for item in sequence:
- if not matchsequence.matches(item):
+ for element in item:
+ if not matchsequence.matches(element):
return False
return matchsequence.isfinished()
except TypeError:
if mismatch_description:
- super(IsSequenceContainingInOrder, self) \
- .describe_mismatch(sequence, mismatch_description)
+ super(IsSequenceContainingInOrder, self).describe_mismatch(
+ item, mismatch_description
+ )
return False
- def describe_mismatch(self, item, mismatch_description):
+ def describe_mismatch(self, item: Sequence[T], mismatch_description: Description) -> None:
self.matches(item, mismatch_description)
- def describe_to(self, description):
- description.append_text('a sequence containing ') \
- .append_list('[', ', ', ']', self.matchers)
+ def describe_to(self, description: Description) -> None:
+ description.append_text("a sequence containing ").append_list("[", ", ", "]", self.matchers)
-def contains_exactly(*items):
+def contains_exactly(*items: Union[Matcher[T], T]) -> Matcher[Sequence[T]]:
"""Matches if sequence's elements satisfy a given list of matchers, in order.
:param match1,...: A comma-separated list of matchers.
@@ -90,7 +97,7 @@ def contains_exactly(*items):
return IsSequenceContainingInOrder(matchers)
-def contains(*items):
+def contains(*items: Union[Matcher[T], T]) -> Matcher[Sequence[T]]:
"""Deprecated - use contains_exactly(*items)"""
warnings.warn("deprecated - use contains_exactly(*items)", DeprecationWarning)
return contains_exactly(*items)
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_onlycontaining.py b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_onlycontaining.py
index bd52c10419e..f7819987e19 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_onlycontaining.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/collection/issequence_onlycontaining.py
@@ -1,36 +1,41 @@
+from typing import Sequence, TypeVar, Union
+
from hamcrest.core.base_matcher import BaseMatcher
from hamcrest.core.core.anyof import any_of
-from hamcrest.core.helpers.hasmethod import hasmethod
+from hamcrest.core.description import Description
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
+from hamcrest.core.matcher import Matcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
+T = TypeVar("T")
-class IsSequenceOnlyContaining(BaseMatcher):
- def __init__(self, matcher):
+class IsSequenceOnlyContaining(BaseMatcher[Sequence[T]]):
+ def __init__(self, matcher: Matcher[T]) -> None:
self.matcher = matcher
- def _matches(self, sequence):
+ def _matches(self, item: Sequence[T]) -> bool:
try:
- sequence = list(sequence)
+ sequence = list(item)
if len(sequence) == 0:
return False
- for item in sequence:
- if not self.matcher.matches(item):
+ for element in sequence:
+ if not self.matcher.matches(element):
return False
return True
except TypeError:
return False
- def describe_to(self, description):
- description.append_text('a sequence containing items matching ') \
- .append_description_of(self.matcher)
+ def describe_to(self, description: Description) -> None:
+ description.append_text("a sequence containing items matching ").append_description_of(
+ self.matcher
+ )
-def only_contains(*items):
+def only_contains(*items: Union[Matcher[T], T]) -> Matcher[Sequence[T]]:
"""Matches if each element of sequence satisfies any of the given matchers.
:param match1,...: A comma-separated list of matchers.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/integration/__init__.py b/contrib/python/PyHamcrest/py3/hamcrest/library/integration/__init__.py
index cc1e1321635..e87d6e1ffc5 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/integration/__init__.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/integration/__init__.py
@@ -1,4 +1,3 @@
-from __future__ import absolute_import
"""Utilities for integrating Hamcrest with other libraries."""
from .match_equality import match_equality
@@ -6,3 +5,5 @@ from .match_equality import match_equality
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
+
+__all__ = ["match_equality"]
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/integration/match_equality.py b/contrib/python/PyHamcrest/py3/hamcrest/library/integration/match_equality.py
index 52da0547605..33494ef2d59 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/integration/match_equality.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/integration/match_equality.py
@@ -1,5 +1,8 @@
-from hamcrest.core.string_description import tostring
+from typing import Any
+
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
+from hamcrest.core.matcher import Matcher
+from hamcrest.core.string_description import tostring
__author__ = "Chris Rose"
__copyright__ = "Copyright 2011 hamcrest.org"
@@ -8,21 +11,20 @@ __unittest = True
class EqualityWrapper(object):
-
- def __init__(self, matcher):
+ def __init__(self, matcher: Matcher) -> None:
self.matcher = matcher
- def __eq__(self, object):
- return self.matcher.matches(object)
+ def __eq__(self, obj: Any) -> bool:
+ return self.matcher.matches(obj)
- def __str__(self):
+ def __str__(self) -> str:
return repr(self)
- def __repr__(self):
+ def __repr__(self) -> str:
return tostring(self.matcher)
-def match_equality(matcher):
+def match_equality(matcher: Matcher) -> EqualityWrapper:
"""Wraps a matcher to define equality in terms of satisfying the matcher.
``match_equality`` allows Hamcrest matchers to be used in libraries that
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/number/__init__.py b/contrib/python/PyHamcrest/py3/hamcrest/library/number/__init__.py
index 5087faf8468..85f4cf69982 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/number/__init__.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/number/__init__.py
@@ -1,9 +1,21 @@
-from __future__ import absolute_import
"""Matchers that perform numeric comparisons."""
from .iscloseto import close_to
-from .ordering_comparison import greater_than, greater_than_or_equal_to, less_than, less_than_or_equal_to
+from .ordering_comparison import (
+ greater_than,
+ greater_than_or_equal_to,
+ less_than,
+ less_than_or_equal_to,
+)
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
+
+__all__ = [
+ "close_to",
+ "greater_than",
+ "greater_than_or_equal_to",
+ "less_than",
+ "less_than_or_equal_to",
+]
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/number/iscloseto.py b/contrib/python/PyHamcrest/py3/hamcrest/library/number/iscloseto.py
index e401615e356..579eeb8624a 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/number/iscloseto.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/number/iscloseto.py
@@ -1,16 +1,21 @@
-import six
-from hamcrest.core.base_matcher import BaseMatcher
+from decimal import Decimal
from math import fabs
+from typing import Any, Union, overload
+
+from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
+from hamcrest.core.matcher import Matcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
+Number = Union[float, Decimal] # Argh, https://github.com/python/mypy/issues/3186
-def isnumeric(value):
- """Confirm that 'value' can be treated numerically; duck-test accordingly
- """
- if isinstance(value, (float, complex) + six.integer_types):
+
+def isnumeric(value: Any) -> bool:
+ """Confirm that 'value' can be treated numerically; duck-test accordingly"""
+ if isinstance(value, (float, complex, int)):
return True
try:
@@ -18,41 +23,52 @@ def isnumeric(value):
return True
except ArithmeticError:
return True
- except:
+ except Exception:
return False
- return False
-
-class IsCloseTo(BaseMatcher):
- def __init__(self, value, delta):
+class IsCloseTo(BaseMatcher[Number]):
+ def __init__(self, value: Number, delta: Number) -> None:
if not isnumeric(value):
- raise TypeError('IsCloseTo value must be numeric')
+ raise TypeError("IsCloseTo value must be numeric")
if not isnumeric(delta):
- raise TypeError('IsCloseTo delta must be numeric')
+ raise TypeError("IsCloseTo delta must be numeric")
self.value = value
self.delta = delta
- def _matches(self, item):
+ def _matches(self, item: Number) -> bool:
if not isnumeric(item):
return False
- return fabs(item - self.value) <= self.delta
+ return self._diff(item) <= self.delta
- def describe_mismatch(self, item, mismatch_description):
+ def _diff(self, item: Number) -> float:
+ # TODO - Fails for mixed floats & Decimals
+ return fabs(item - self.value) # type: ignore
+
+ def describe_mismatch(self, item: Number, mismatch_description: Description) -> None:
if not isnumeric(item):
super(IsCloseTo, self).describe_mismatch(item, mismatch_description)
else:
- actual_delta = fabs(item - self.value)
- mismatch_description.append_description_of(item) \
- .append_text(' differed by ') \
- .append_description_of(actual_delta)
+ actual_delta = self._diff(item)
+ mismatch_description.append_description_of(item).append_text(
+ " differed by "
+ ).append_description_of(actual_delta)
+
+ def describe_to(self, description: Description) -> None:
+ description.append_text("a numeric value within ").append_description_of(
+ self.delta
+ ).append_text(" of ").append_description_of(self.value)
+
+
+@overload
+def close_to(value: float, delta: float) -> Matcher[float]:
+ ...
+
- def describe_to(self, description):
- description.append_text('a numeric value within ') \
- .append_description_of(self.delta) \
- .append_text(' of ') \
- .append_description_of(self.value)
+@overload
+def close_to(value: Decimal, delta: Decimal) -> Matcher[Decimal]:
+ ...
def close_to(value, delta):
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/number/ordering_comparison.py b/contrib/python/PyHamcrest/py3/hamcrest/library/number/ordering_comparison.py
index c3c75f425d6..f121caf45f9 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/number/ordering_comparison.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/number/ordering_comparison.py
@@ -1,59 +1,69 @@
-from hamcrest.core.base_matcher import BaseMatcher
import operator
+from typing import Any, Callable
+
+from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
+from hamcrest.core.matcher import Matcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
-class OrderingComparison(BaseMatcher):
-
- def __init__(self, value, comparison_function, comparison_description):
+class OrderingComparison(BaseMatcher[Any]):
+ def __init__(
+ self,
+ value: Any,
+ comparison_function: Callable[[Any, Any], bool],
+ comparison_description: str,
+ ) -> None:
self.value = value
self.comparison_function = comparison_function
self.comparison_description = comparison_description
- def _matches(self, item):
- return self.comparison_function(item, self.value)
+ def _matches(self, item: Any) -> bool:
+ try:
+ return self.comparison_function(item, self.value)
+ except TypeError:
+ return False
- def describe_to(self, description):
- description.append_text('a value ') \
- .append_text(self.comparison_description) \
- .append_text(' ') \
- .append_description_of(self.value)
+ def describe_to(self, description: Description) -> None:
+ description.append_text("a value ").append_text(self.comparison_description).append_text(
+ " "
+ ).append_description_of(self.value)
-def greater_than(value):
+def greater_than(value: Any) -> Matcher[Any]:
"""Matches if object is greater than a given value.
:param value: The value to compare against.
"""
- return OrderingComparison(value, operator.gt, 'greater than')
+ return OrderingComparison(value, operator.gt, "greater than")
-def greater_than_or_equal_to(value):
+def greater_than_or_equal_to(value: Any) -> Matcher[Any]:
"""Matches if object is greater than or equal to a given value.
:param value: The value to compare against.
"""
- return OrderingComparison(value, operator.ge, 'greater than or equal to')
+ return OrderingComparison(value, operator.ge, "greater than or equal to")
-def less_than(value):
+def less_than(value: Any) -> Matcher[Any]:
"""Matches if object is less than a given value.
:param value: The value to compare against.
"""
- return OrderingComparison(value, operator.lt, 'less than')
+ return OrderingComparison(value, operator.lt, "less than")
-def less_than_or_equal_to(value):
+def less_than_or_equal_to(value: Any) -> Matcher[Any]:
"""Matches if object is less than or equal to a given value.
:param value: The value to compare against.
"""
- return OrderingComparison(value, operator.le, 'less than or equal to')
+ return OrderingComparison(value, operator.le, "less than or equal to")
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/object/__init__.py b/contrib/python/PyHamcrest/py3/hamcrest/library/object/__init__.py
index 5ca45566616..e015671d9d8 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/object/__init__.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/object/__init__.py
@@ -1,10 +1,16 @@
-from __future__ import absolute_import
"""Matchers that inspect objects and classes."""
from .haslength import has_length
-from .hasproperty import has_property, has_properties
+from .hasproperty import has_properties, has_property
from .hasstring import has_string
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
+
+__all__ = [
+ "has_length",
+ "has_properties",
+ "has_property",
+ "has_string",
+]
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/object/haslength.py b/contrib/python/PyHamcrest/py3/hamcrest/library/object/haslength.py
index 3ef0ab5b81e..86d03999d70 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/object/haslength.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/object/haslength.py
@@ -1,34 +1,36 @@
+from collections.abc import Sized
+from typing import Union
+
from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
from hamcrest.core.helpers.hasmethod import hasmethod
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
+from hamcrest.core.matcher import Matcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
-class HasLength(BaseMatcher):
-
- def __init__(self, len_matcher):
+class HasLength(BaseMatcher[Sized]):
+ def __init__(self, len_matcher: Matcher[int]) -> None:
self.len_matcher = len_matcher
- def _matches(self, item):
- if not hasmethod(item, '__len__'):
+ def _matches(self, item: Sized) -> bool:
+ if not hasmethod(item, "__len__"):
return False
return self.len_matcher.matches(len(item))
- def describe_mismatch(self, item, mismatch_description):
+ def describe_mismatch(self, item: Sized, mismatch_description: Description) -> None:
super(HasLength, self).describe_mismatch(item, mismatch_description)
- if hasmethod(item, '__len__'):
- mismatch_description.append_text(' with length of ') \
- .append_description_of(len(item))
+ if hasmethod(item, "__len__"):
+ mismatch_description.append_text(" with length of ").append_description_of(len(item))
- def describe_to(self, description):
- description.append_text('an object with length of ') \
- .append_description_of(self.len_matcher)
+ def describe_to(self, description: Description) -> None:
+ description.append_text("an object with length of ").append_description_of(self.len_matcher)
-def has_length(match):
+def has_length(match: Union[int, Matcher[int]]) -> Matcher[Sized]:
"""Matches if ``len(item)`` satisfies a given matcher.
:param match: The matcher to satisfy, or an expected value for
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/object/hasproperty.py b/contrib/python/PyHamcrest/py3/hamcrest/library/object/hasproperty.py
index 18f591f1ed6..ea2519f7380 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/object/hasproperty.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/object/hasproperty.py
@@ -1,52 +1,55 @@
+from typing import Any, Mapping, TypeVar, Union, overload
+
from hamcrest import described_as
from hamcrest.core import anything
from hamcrest.core.base_matcher import BaseMatcher
from hamcrest.core.core.allof import AllOf
+from hamcrest.core.description import Description
from hamcrest.core.helpers.wrap_matcher import wrap_matcher as wrap_shortcut
+from hamcrest.core.matcher import Matcher
from hamcrest.core.string_description import StringDescription
__author__ = "Chris Rose"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
+V = TypeVar("V")
-class IsObjectWithProperty(BaseMatcher):
- def __init__(self, property_name, value_matcher):
+class IsObjectWithProperty(BaseMatcher[object]):
+ def __init__(self, property_name: str, value_matcher: Matcher[V]) -> None:
self.property_name = property_name
self.value_matcher = value_matcher
- def _matches(self, o):
- if o is None:
+ def _matches(self, item: object) -> bool:
+ if item is None:
return False
- if not hasattr(o, self.property_name):
+ if not hasattr(item, self.property_name):
return False
- value = getattr(o, self.property_name)
+ value = getattr(item, self.property_name)
return self.value_matcher.matches(value)
- def describe_to(self, description):
- description.append_text("an object with a property '") \
- .append_text(self.property_name) \
- .append_text("' matching ") \
- .append_description_of(self.value_matcher)
+ def describe_to(self, description: Description) -> None:
+ description.append_text("an object with a property '").append_text(
+ self.property_name
+ ).append_text("' matching ").append_description_of(self.value_matcher)
- def describe_mismatch(self, item, mismatch_description):
+ def describe_mismatch(self, item: object, mismatch_description: Description) -> None:
if item is None:
- mismatch_description.append_text('was None')
+ mismatch_description.append_text("was None")
return
if not hasattr(item, self.property_name):
- mismatch_description.append_description_of(item) \
- .append_text(' did not have the ') \
- .append_description_of(self.property_name) \
- .append_text(' property')
+ mismatch_description.append_description_of(item).append_text(
+ " did not have the "
+ ).append_description_of(self.property_name).append_text(" property")
return
- mismatch_description.append_text('property ') \
- .append_description_of(self.property_name) \
- .append_text(' ')
+ mismatch_description.append_text("property ").append_description_of(
+ self.property_name
+ ).append_text(" ")
value = getattr(item, self.property_name)
self.value_matcher.describe_mismatch(value, mismatch_description)
@@ -56,7 +59,7 @@ class IsObjectWithProperty(BaseMatcher):
return str(d)
-def has_property(name, match=None):
+def has_property(name: str, match: Union[None, Matcher[V], V] = None) -> Matcher[object]:
"""Matches if object has a property with a given name whose value satisfies
a given matcher.
@@ -89,6 +92,24 @@ def has_property(name, match=None):
return IsObjectWithProperty(name, wrap_shortcut(match))
+# Keyword argument form
+@overload
+def has_properties(**keys_valuematchers: Union[Matcher[V], V]) -> Matcher[Any]:
+ ...
+
+
+# Name to matcher dict form
+@overload
+def has_properties(keys_valuematchers: Mapping[str, Union[Matcher[V], V]]) -> Matcher[Any]:
+ ...
+
+
+# Alternating name/matcher form
+@overload
+def has_properties(*keys_valuematchers: Any) -> Matcher[Any]:
+ ...
+
+
def has_properties(*keys_valuematchers, **kv_args):
"""Matches if an object has properties satisfying all of a dictionary
of string property names and corresponding value matchers.
@@ -141,31 +162,41 @@ def has_properties(*keys_valuematchers, **kv_args):
for key in base_dict:
base_dict[key] = wrap_shortcut(base_dict[key])
except AttributeError:
- raise ValueError('single-argument calls to has_properties must pass a dict as the argument')
+ raise ValueError(
+ "single-argument calls to has_properties must pass a dict as the argument"
+ )
else:
if len(keys_valuematchers) % 2:
- raise ValueError('has_properties requires key-value pairs')
+ raise ValueError("has_properties requires key-value pairs")
base_dict = {}
for index in range(int(len(keys_valuematchers) / 2)):
- base_dict[keys_valuematchers[2 * index]] = wrap_shortcut(keys_valuematchers[2 * index + 1])
+ base_dict[keys_valuematchers[2 * index]] = wrap_shortcut(
+ keys_valuematchers[2 * index + 1]
+ )
for key, value in kv_args.items():
base_dict[key] = wrap_shortcut(value)
if len(base_dict) > 1:
- description = StringDescription().append_text('an object with properties ')
+ description = StringDescription().append_text("an object with properties ")
for i, (property_name, property_value_matcher) in enumerate(sorted(base_dict.items())):
- description.append_value(property_name).append_text(' matching ').append_description_of(
- property_value_matcher)
+ description.append_description_of(property_name).append_text(
+ " matching "
+ ).append_description_of(property_value_matcher)
if i < len(base_dict) - 1:
- description.append_text(' and ')
+ description.append_text(" and ")
- return described_as(str(description),
- AllOf(*[has_property(property_name, property_value_matcher)
- for property_name, property_value_matcher
- in sorted(base_dict.items())],
- describe_all_mismatches=True,
- describe_matcher_in_mismatch=False))
+ return described_as(
+ str(description),
+ AllOf(
+ *[
+ has_property(property_name, property_value_matcher)
+ for property_name, property_value_matcher in sorted(base_dict.items())
+ ],
+ describe_all_mismatches=True,
+ describe_matcher_in_mismatch=False,
+ ),
+ )
else:
property_name, property_value_matcher = base_dict.popitem()
return has_property(property_name, property_value_matcher)
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/object/hasstring.py b/contrib/python/PyHamcrest/py3/hamcrest/library/object/hasstring.py
index 8b50547e21c..b03d46615b6 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/object/hasstring.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/object/hasstring.py
@@ -1,25 +1,25 @@
from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
+from hamcrest.core.matcher import Matcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
-class HasString(BaseMatcher):
-
- def __init__(self, str_matcher):
+class HasString(BaseMatcher[object]):
+ def __init__(self, str_matcher: Matcher[str]) -> None:
self.str_matcher = str_matcher
- def _matches(self, item):
+ def _matches(self, item: object) -> bool:
return self.str_matcher.matches(str(item))
- def describe_to(self, description):
- description.append_text('an object with str ') \
- .append_description_of(self.str_matcher)
+ def describe_to(self, description: Description) -> None:
+ description.append_text("an object with str ").append_description_of(self.str_matcher)
-def has_string(match):
+def has_string(match) -> Matcher[object]:
"""Matches if ``str(item)`` satisfies a given matcher.
:param match: The matcher to satisfy, or an expected value for
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/text/__init__.py b/contrib/python/PyHamcrest/py3/hamcrest/library/text/__init__.py
index 39d0e8b3822..19e46c4c88a 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/text/__init__.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/text/__init__.py
@@ -1,14 +1,23 @@
-from __future__ import absolute_import
"""Matchers that perform text comparisons."""
from .isequal_ignoring_case import equal_to_ignoring_case
from .isequal_ignoring_whitespace import equal_to_ignoring_whitespace
from .stringcontains import contains_string
+from .stringcontainsinorder import string_contains_in_order
from .stringendswith import ends_with
-from .stringstartswith import starts_with
from .stringmatches import matches_regexp
-from .stringcontainsinorder import string_contains_in_order
+from .stringstartswith import starts_with
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
+
+__all__ = [
+ "contains_string",
+ "ends_with",
+ "equal_to_ignoring_case",
+ "equal_to_ignoring_whitespace",
+ "matches_regexp",
+ "starts_with",
+ "string_contains_in_order",
+]
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/text/isequal_ignoring_case.py b/contrib/python/PyHamcrest/py3/hamcrest/library/text/isequal_ignoring_case.py
index d1ee2d17fc3..c7afb18464f 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/text/isequal_ignoring_case.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/text/isequal_ignoring_case.py
@@ -1,30 +1,29 @@
+from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
+from hamcrest.core.matcher import Matcher
+
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
-from hamcrest.core.base_matcher import BaseMatcher
-
-import six
-
-class IsEqualIgnoringCase(BaseMatcher):
- def __init__(self, string):
- if not isinstance(string, six.string_types):
- raise TypeError('IsEqualIgnoringCase requires string')
+class IsEqualIgnoringCase(BaseMatcher[str]):
+ def __init__(self, string: str) -> None:
+ if not isinstance(string, str):
+ raise TypeError("IsEqualIgnoringCase requires string")
self.original_string = string
self.lowered_string = string.lower()
- def _matches(self, item):
- if not isinstance(item, six.string_types):
+ def _matches(self, item: str) -> bool:
+ if not isinstance(item, str):
return False
return self.lowered_string == item.lower()
- def describe_to(self, description):
- description.append_description_of(self.original_string) \
- .append_text(' ignoring case')
+ def describe_to(self, description: Description) -> None:
+ description.append_description_of(self.original_string).append_text(" ignoring case")
-def equal_to_ignoring_case(string):
+def equal_to_ignoring_case(string: str) -> Matcher[str]:
"""Matches if object is a string equal to a given string, ignoring case
differences.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/text/isequal_ignoring_whitespace.py b/contrib/python/PyHamcrest/py3/hamcrest/library/text/isequal_ignoring_whitespace.py
index 86fa997601b..dcb7e853343 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/text/isequal_ignoring_whitespace.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/text/isequal_ignoring_whitespace.py
@@ -1,18 +1,19 @@
+from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
+from hamcrest.core.matcher import Matcher
+
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
-from hamcrest.core.base_matcher import BaseMatcher
-import six
-
-def stripspace(string):
- result = ''
+def stripspace(string: str) -> str:
+ result = ""
last_was_space = True
for character in string:
if character.isspace():
if not last_was_space:
- result += ' '
+ result += " "
last_was_space = True
else:
result += character
@@ -20,25 +21,23 @@ def stripspace(string):
return result.strip()
-class IsEqualIgnoringWhiteSpace(BaseMatcher):
-
- def __init__(self, string):
- if not isinstance(string, six.string_types):
- raise TypeError('IsEqualIgnoringWhiteSpace requires string')
+class IsEqualIgnoringWhiteSpace(BaseMatcher[str]):
+ def __init__(self, string) -> None:
+ if not isinstance(string, str):
+ raise TypeError("IsEqualIgnoringWhiteSpace requires string")
self.original_string = string
self.stripped_string = stripspace(string)
- def _matches(self, item):
- if not isinstance(item, six.string_types):
+ def _matches(self, item: str) -> bool:
+ if not isinstance(item, str):
return False
return self.stripped_string == stripspace(item)
- def describe_to(self, description):
- description.append_description_of(self.original_string) \
- .append_text(' ignoring whitespace')
+ def describe_to(self, description: Description) -> None:
+ description.append_description_of(self.original_string).append_text(" ignoring whitespace")
-def equal_to_ignoring_whitespace(string):
+def equal_to_ignoring_whitespace(string: str) -> Matcher[str]:
"""Matches if object is a string equal to a given string, ignoring
differences in whitespace.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringcontains.py b/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringcontains.py
index 58ffd283c66..34df2f6f01d 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringcontains.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringcontains.py
@@ -1,5 +1,6 @@
-from hamcrest.library.text.substringmatcher import SubstringMatcher
from hamcrest.core.helpers.hasmethod import hasmethod
+from hamcrest.core.matcher import Matcher
+from hamcrest.library.text.substringmatcher import SubstringMatcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
@@ -7,20 +8,19 @@ __license__ = "BSD, see License.txt"
class StringContains(SubstringMatcher):
-
- def __init__(self, substring):
+ def __init__(self, substring) -> None:
super(StringContains, self).__init__(substring)
- def _matches(self, item):
- if not hasmethod(item, 'find'):
+ def _matches(self, item: str) -> bool:
+ if not hasmethod(item, "find"):
return False
return item.find(self.substring) >= 0
def relationship(self):
- return 'containing'
+ return "containing"
-def contains_string(substring):
+def contains_string(substring: str) -> Matcher[str]:
"""Matches if object is a string containing a given string.
:param string: The string to search for.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringcontainsinorder.py b/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringcontainsinorder.py
index d5b24ffa40c..73c61fc83ad 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringcontainsinorder.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringcontainsinorder.py
@@ -1,23 +1,22 @@
-__author__ = "Romilly Cocking"
-__copyright__ = "Copyright 2011 hamcrest.org"
-__license__ = "BSD, see License.txt"
-
from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
from hamcrest.core.helpers.hasmethod import hasmethod
+from hamcrest.core.matcher import Matcher
-import six
+__author__ = "Romilly Cocking"
+__copyright__ = "Copyright 2011 hamcrest.org"
+__license__ = "BSD, see License.txt"
-class StringContainsInOrder(BaseMatcher):
- def __init__(self, *substrings):
+class StringContainsInOrder(BaseMatcher[str]):
+ def __init__(self, *substrings) -> None:
for substring in substrings:
- if not isinstance(substring, six.string_types):
- raise TypeError(self.__class__.__name__
- + ' requires string arguments')
+ if not isinstance(substring, str):
+ raise TypeError(self.__class__.__name__ + " requires string arguments")
self.substrings = substrings
- def _matches(self, item):
- if not hasmethod(item, 'find'):
+ def _matches(self, item: str) -> bool:
+ if not hasmethod(item, "find"):
return False
from_index = 0
for substring in self.substrings:
@@ -26,12 +25,11 @@ class StringContainsInOrder(BaseMatcher):
return False
return True
- def describe_to(self, description):
- description.append_list('a string containing ', ', ', ' in order',
- self.substrings)
+ def describe_to(self, description: Description) -> None:
+ description.append_list("a string containing ", ", ", " in order", self.substrings)
-def string_contains_in_order(*substrings):
+def string_contains_in_order(*substrings: str) -> Matcher[str]:
"""Matches if object is a string containing a given list of substrings in
relative order.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringendswith.py b/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringendswith.py
index 43f9c3d3021..16bebbdcdde 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringendswith.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringendswith.py
@@ -1,5 +1,6 @@
-from hamcrest.library.text.substringmatcher import SubstringMatcher
from hamcrest.core.helpers.hasmethod import hasmethod
+from hamcrest.core.matcher import Matcher
+from hamcrest.library.text.substringmatcher import SubstringMatcher
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
@@ -7,20 +8,19 @@ __license__ = "BSD, see License.txt"
class StringEndsWith(SubstringMatcher):
-
- def __init__(self, substring):
+ def __init__(self, substring) -> None:
super(StringEndsWith, self).__init__(substring)
- def _matches(self, item):
- if not hasmethod(item, 'endswith'):
+ def _matches(self, item: str) -> bool:
+ if not hasmethod(item, "endswith"):
return False
return item.endswith(self.substring)
def relationship(self):
- return 'ending with'
+ return "ending with"
-def ends_with(string):
+def ends_with(string: str) -> Matcher[str]:
"""Matches if object is a string ending with a given string.
:param string: The string to search for.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringmatches.py b/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringmatches.py
index 2a16e29729b..e7e8dd4190f 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringmatches.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringmatches.py
@@ -1,29 +1,29 @@
-__author__ = "Chris Rose"
-__copyright__ = "Copyright 2011 hamcrest.org"
-__license__ = "BSD, see License.txt"
-
import re
-
-import six
+from typing import Pattern, Union
from hamcrest.core.base_matcher import BaseMatcher
-from hamcrest.core.helpers.hasmethod import hasmethod
+from hamcrest.core.description import Description
+from hamcrest.core.matcher import Matcher
+
+__author__ = "Chris Rose"
+__copyright__ = "Copyright 2011 hamcrest.org"
+__license__ = "BSD, see License.txt"
-class StringMatchesPattern(BaseMatcher):
- def __init__(self, pattern):
+class StringMatchesPattern(BaseMatcher[str]):
+ def __init__(self, pattern) -> None:
self.pattern = pattern
- def describe_to(self, description):
- description.append_text("a string matching '") \
- .append_text(self.pattern.pattern) \
- .append_text("'")
+ def describe_to(self, description: Description) -> None:
+ description.append_text("a string matching '").append_text(
+ self.pattern.pattern
+ ).append_text("'")
- def _matches(self, item):
+ def _matches(self, item: str) -> bool:
return self.pattern.search(item) is not None
-def matches_regexp(pattern):
+def matches_regexp(pattern: Union[str, Pattern[str]]) -> Matcher[str]:
"""Matches if object is a string containing a match for a given regular
expression.
@@ -34,7 +34,7 @@ def matches_regexp(pattern):
evaluated object.
"""
- if isinstance(pattern, six.string_types):
+ if isinstance(pattern, str):
pattern = re.compile(pattern)
return StringMatchesPattern(pattern)
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringstartswith.py b/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringstartswith.py
index a0af49c9c2a..c3cc7eef408 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringstartswith.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/text/stringstartswith.py
@@ -1,26 +1,26 @@
+from hamcrest.core.helpers.hasmethod import hasmethod
+from hamcrest.core.matcher import Matcher
+from hamcrest.library.text.substringmatcher import SubstringMatcher
+
__author__ = "Jon Reid"
__copyright__ = "Copyright 2011 hamcrest.org"
__license__ = "BSD, see License.txt"
-from hamcrest.library.text.substringmatcher import SubstringMatcher
-from hamcrest.core.helpers.hasmethod import hasmethod
-
class StringStartsWith(SubstringMatcher):
-
- def __init__(self, substring):
+ def __init__(self, substring) -> None:
super(StringStartsWith, self).__init__(substring)
- def _matches(self, item):
- if not hasmethod(item, 'startswith'):
+ def _matches(self, item: str) -> bool:
+ if not hasmethod(item, "startswith"):
return False
return item.startswith(self.substring)
def relationship(self):
- return 'starting with'
+ return "starting with"
-def starts_with(substring):
+def starts_with(substring: str) -> Matcher[str]:
"""Matches if object is a string starting with a given string.
:param string: The string to search for.
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/library/text/substringmatcher.py b/contrib/python/PyHamcrest/py3/hamcrest/library/text/substringmatcher.py
index 63ea359a51c..ec7874c5f07 100644
--- a/contrib/python/PyHamcrest/py3/hamcrest/library/text/substringmatcher.py
+++ b/contrib/python/PyHamcrest/py3/hamcrest/library/text/substringmatcher.py
@@ -1,20 +1,24 @@
-__author__ = "Jon Reid"
-__copyright__ = "Copyright 2011 hamcrest.org"
-__license__ = "BSD, see License.txt"
+from abc import ABCMeta, abstractmethod
from hamcrest.core.base_matcher import BaseMatcher
+from hamcrest.core.description import Description
-import six
+__author__ = "Jon Reid"
+__copyright__ = "Copyright 2011 hamcrest.org"
+__license__ = "BSD, see License.txt"
-class SubstringMatcher(BaseMatcher):
- def __init__(self, substring):
- if not isinstance(substring, six.string_types):
- raise TypeError(self.__class__.__name__ + ' requires string')
+class SubstringMatcher(BaseMatcher[str], metaclass=ABCMeta):
+ def __init__(self, substring) -> None:
+ if not isinstance(substring, str):
+ raise TypeError(self.__class__.__name__ + " requires string")
self.substring = substring
- def describe_to(self, description):
- description.append_text('a string ') \
- .append_text(self.relationship()) \
- .append_text(' ') \
- .append_description_of(self.substring)
+ def describe_to(self, description: Description) -> None:
+ description.append_text("a string ").append_text(self.relationship()).append_text(
+ " "
+ ).append_description_of(self.substring)
+
+ @abstractmethod
+ def relationship(self):
+ ...
diff --git a/contrib/python/PyHamcrest/py3/hamcrest/py.typed b/contrib/python/PyHamcrest/py3/hamcrest/py.typed
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/contrib/python/PyHamcrest/py3/hamcrest/py.typed
diff --git a/contrib/python/PyHamcrest/py3/patches/01-add-additional-matcher.patch b/contrib/python/PyHamcrest/py3/patches/01-add-additional-matcher.patch
new file mode 100644
index 00000000000..a863411138b
--- /dev/null
+++ b/contrib/python/PyHamcrest/py3/patches/01-add-additional-matcher.patch
@@ -0,0 +1,64 @@
+--- contrib/python/PyHamcrest/py3/hamcrest/core/core/raises.py (index)
++++ contrib/python/PyHamcrest/py3/hamcrest/core/core/raises.py (working tree)
+@@ -18,12 +18,14 @@ class Raises(BaseMatcher[Callable[..., Any]]):
+ expected: Type[Exception],
+ pattern: Optional[str] = None,
+ matching: Optional[Matcher] = None,
++ matcher: Optional[Matcher] = None,
+ ) -> None:
+ self.pattern = pattern
+- self.matcher = matching
++ self.matcher = matching or matcher
+ self.expected = expected
+ self.actual: Optional[BaseException] = None
+ self.function: Optional[Callable[..., Any]] = None
++ self.actual_return_value = None
+
+ def _matches(self, function: Callable[..., Any]) -> bool:
+ if not callable(function):
+@@ -35,7 +37,7 @@ class Raises(BaseMatcher[Callable[..., Any]]):
+ def _call_function(self, function: Callable[..., Any]) -> bool:
+ self.actual = None
+ try:
+- function()
++ self.actual_return_value = function()
+ except BaseException:
+ self.actual = sys.exc_info()[1]
+
+@@ -51,6 +53,9 @@ class Raises(BaseMatcher[Callable[..., Any]]):
+
+ def describe_to(self, description: Description) -> None:
+ description.append_text("Expected a callable raising %s" % self.expected)
++ if self.matcher is not None:
++ description.append_text("\n and ")
++ description.append_description_of(self.matcher)
+
+ def describe_mismatch(self, item, description: Description) -> None:
+ if not callable(item):
+@@ -64,7 +69,7 @@ class Raises(BaseMatcher[Callable[..., Any]]):
+ return
+
+ if self.actual is None:
+- description.append_text("No exception raised.")
++ description.append_text("No exception raised and actual return value = '{}'".format(self.actual_return_value))
+ elif isinstance(self.actual, self.expected):
+ if self.pattern is not None or self.matcher is not None:
+ description.append_text("Correct assertion type raised, but ")
+@@ -88,7 +93,7 @@ class Raises(BaseMatcher[Callable[..., Any]]):
+ )
+
+
+-def raises(exception: Type[Exception], pattern=None, matching=None) -> Matcher[Callable[..., Any]]:
++def raises(exception: Type[Exception], pattern=None, matching=None, matcher=None) -> Matcher[Callable[..., Any]]:
+ """Matches if the called function raised the expected exception.
+
+ :param exception: The class of the expected exception
+@@ -109,7 +114,7 @@ def raises(exception: Type[Exception], pattern=None, matching=None) -> Matcher[C
+ raises(HTTPError, matching=has_properties(status_code=500)
+ )
+ """
+- return Raises(exception, pattern, matching)
++ return Raises(exception, pattern, matching, matcher)
+
+
+ class DeferredCallable(object):
diff --git a/contrib/python/PyHamcrest/py3/patches/02-add-additional-matcher.patch b/contrib/python/PyHamcrest/py3/patches/02-add-additional-matcher.patch
deleted file mode 100644
index 71d625bb19b..00000000000
--- a/contrib/python/PyHamcrest/py3/patches/02-add-additional-matcher.patch
+++ /dev/null
@@ -1,87 +0,0 @@
-commit d2cd9189374434ea6603b07c67b316c59e6d689f
-author: asatarin
-date: 2017-06-13T11:54:11+03:00
-revision: 2945097
-
- REVIEW:285653 Add additional capabilities to standard raises() matcher
-
---- contrib/python/PyHamcrest/py3/hamcrest/core/core/raises.py (f026926efe42aecf93ac9fb70955b96fbdb35a67)
-+++ contrib/python/PyHamcrest/py3/hamcrest/core/core/raises.py (d2cd9189374434ea6603b07c67b316c59e6d689f)
-@@ -10,11 +10,13 @@ __license__ = "BSD, see License.txt"
-
-
- class Raises(BaseMatcher):
-- def __init__(self, expected, pattern=None):
-+ def __init__(self, expected, pattern=None, matcher=None):
- self.pattern = pattern
- self.expected = expected
- self.actual = None
- self.function = None
-+ self.matcher = matcher
-+ self.actual_return_value = None
-
- def _matches(self, function):
- if not is_callable(function):
-@@ -26,18 +28,24 @@ class Raises(BaseMatcher):
- def _call_function(self, function):
- self.actual = None
- try:
-- function()
-+ self.actual_return_value = function()
- except BaseException:
- self.actual = sys.exc_info()[1]
-
- if isinstance(self.actual, self.expected):
- if self.pattern is not None:
-- return re.search(self.pattern, str(self.actual)) is not None
-- return True
-+ return (
-+ re.search(self.pattern, str(self.actual)) is not None
-+ and (self.matcher is None or self.matcher.matches(self.actual))
-+ )
-+ return self.matcher is None or self.matcher.matches(self.actual)
- return False
-
- def describe_to(self, description):
- description.append_text('Expected a callable raising %s' % self.expected)
-+ if self.matcher is not None:
-+ description.append_text("\n and ")
-+ description.append_description_of(self.matcher)
-
- def describe_mismatch(self, item, description):
- if not is_callable(item):
-@@ -51,15 +59,20 @@ class Raises(BaseMatcher):
- return
-
- if self.actual is None:
-- description.append_text('No exception raised.')
-- elif isinstance(self.actual, self.expected) and self.pattern is not None:
-- description.append_text('Correct assertion type raised, but the expected pattern ("%s") not found.' % self.pattern)
-- description.append_text('\n message was: "%s"' % str(self.actual))
-+ description.append_text('No exception raised and actual return value = ')
-+ description.append_value(self.actual_return_value)
-+ elif isinstance(self.actual, self.expected):
-+ if self.pattern is not None:
-+ description.append_text('Correct assertion type raised, but the expected pattern ("%s") not found.' % self.pattern)
-+ description.append_text('\n message was: "%s"' % str(self.actual))
-+ if self.matcher is not None:
-+ description.append_text("\nAdditional exception matcher: ")
-+ self.matcher.describe_mismatch(self.actual, description)
- else:
- description.append_text('%r of type %s was raised instead' % (self.actual, type(self.actual)))
-
-
--def raises(exception, pattern=None):
-+def raises(exception, pattern=None, matcher=None):
- """Matches if the called function raised the expected exception.
-
- :param exception: The class of the expected exception
-@@ -75,7 +88,7 @@ def raises(exception, pattern=None):
- assert_that(calling(int).with_args('q'), raises(TypeError))
- assert_that(calling(parse, broken_input), raises(ValueError))
- """
-- return Raises(exception, pattern)
-+ return Raises(exception, pattern, matcher)
-
-
- class DeferredCallable(object):
diff --git a/contrib/python/PyHamcrest/py3/patches/03-pr54.patch b/contrib/python/PyHamcrest/py3/patches/03-pr54.patch
index a4ff77bf863..cf9f1cf37dc 100644
--- a/contrib/python/PyHamcrest/py3/patches/03-pr54.patch
+++ b/contrib/python/PyHamcrest/py3/patches/03-pr54.patch
@@ -14,36 +14,20 @@ diff --git a/hamcrest/core/core/isinstanceof.py b/hamcrest/core/core/isinstanceo
index c96fdf31..f8eb4a2f 100644
--- a/hamcrest/core/core/isinstanceof.py
+++ b/hamcrest/core/core/isinstanceof.py
-@@ -11,21 +11,26 @@ class IsInstanceOf(BaseMatcher):
-
- def __init__(self, expected_type):
- if not is_matchable_type(expected_type):
-- raise TypeError('IsInstanceOf requires type')
-+ raise TypeError('IsInstanceOf requires type or a tuple of classes and types')
- self.expected_type = expected_type
-
- def _matches(self, item):
- return isinstance(item, self.expected_type)
-
- def describe_to(self, description):
+@@ -11,1 +11,1 @@ class IsInstanceOf(BaseMatcher):
+- raise TypeError("IsInstanceOf requires type")
++ raise TypeError("IsInstanceOf requires type or a tuple of classes and types")
+@@ -15,1 +15,5 @@ class IsInstanceOf(BaseMatcher):
+- description.append_text("an instance of ").append_text(self.expected_type.__name__)
+ try:
+ type_description = self.expected_type.__name__
+ except AttributeError:
+ type_description = "one of %s" % ",".join(str(e) for e in self.expected_type)
- description.append_text('an instance of ') \
-- .append_text(self.expected_type.__name__)
-+ .append_text(type_description)
-
-
- def instance_of(atype):
- """Matches if object is an instance of, or inherits from, a given type.
-
++ description.append_text("an instance of ").append_text(type_description)
+@@ -25,1 +25,2 @@ class IsInstanceOf(BaseMatcher):
- :param atype: The type to compare against as the expected type.
+ :param atype: The type to compare against as the expected type or a tuple
+ of types.
-
- This matcher checks whether the evaluated object is an instance of
- ``atype`` or an instance of any class that inherits from ``atype``.
diff --git a/hamcrest/core/helpers/wrap_matcher.py b/hamcrest/core/helpers/wrap_matcher.py
index 1ec9ab58..587ae4c6 100644
--- a/hamcrest/core/helpers/wrap_matcher.py
diff --git a/contrib/python/PyHamcrest/py3/patches/04-pr130.patch b/contrib/python/PyHamcrest/py3/patches/04-pr130.patch
deleted file mode 100644
index e95f47a8483..00000000000
--- a/contrib/python/PyHamcrest/py3/patches/04-pr130.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- contrib/python/PyHamcrest/py3/hamcrest/core/core/allof.py (index)
-+++ contrib/python/PyHamcrest/py3/hamcrest/core/core/allof.py (working tree)
-@@ -25,7 +25,7 @@ class AllOf(BaseMatcher):
- found_mismatch = True
- if not self.describe_all_mismatches:
- break
-- elif i < len(self.matchers) - 1:
-+ elif i < len(self.matchers) - 1 and mismatch_description:
- mismatch_description.append_text(' and ')
- return not found_mismatch
-
diff --git a/contrib/python/PyHamcrest/py3/ya.make b/contrib/python/PyHamcrest/py3/ya.make
index e036d7b9124..90936a53337 100644
--- a/contrib/python/PyHamcrest/py3/ya.make
+++ b/contrib/python/PyHamcrest/py3/ya.make
@@ -2,28 +2,25 @@
PY3_LIBRARY()
-VERSION(1.10.1)
+VERSION(2.1.0)
LICENSE(BSD-3-Clause)
-PEERDIR(
- contrib/python/six
-)
-
NO_LINT()
PY_SRCS(
TOP_LEVEL
hamcrest/__init__.py
+ hamcrest/_version.py
hamcrest/core/__init__.py
hamcrest/core/assert_that.py
hamcrest/core/base_description.py
hamcrest/core/base_matcher.py
- hamcrest/core/compat.py
hamcrest/core/core/__init__.py
hamcrest/core/core/allof.py
hamcrest/core/core/anyof.py
hamcrest/core/core/described_as.py
+ hamcrest/core/core/future.py
hamcrest/core/core/is_.py
hamcrest/core/core/isanything.py
hamcrest/core/core/isequal.py
@@ -77,6 +74,7 @@ RESOURCE_FILES(
PREFIX contrib/python/PyHamcrest/py3/
.dist-info/METADATA
.dist-info/top_level.txt
+ hamcrest/py.typed
)
END()