pax_global_header00006660000000000000000000000064145152414210014511gustar00rootroot0000000000000052 comment=dede7a338d9bb9a3fa21ddd5958b8c64a6df3282 PyHamcrest-2.1.0/000077500000000000000000000000001451524142100135705ustar00rootroot00000000000000PyHamcrest-2.1.0/.github/000077500000000000000000000000001451524142100151305ustar00rootroot00000000000000PyHamcrest-2.1.0/.github/workflows/000077500000000000000000000000001451524142100171655ustar00rootroot00000000000000PyHamcrest-2.1.0/.github/workflows/main.yml000066400000000000000000000062711451524142100206420ustar00rootroot00000000000000--- name: CI on: push: branches: ["main", "master", "ci-testing-*"] pull_request: branches: ["main", "master"] schedule: - cron: "0 6 * * MON" # Every Monday morning workflow_dispatch: jobs: tests: name: "Python ${{ matrix.python-version }} / ${{ matrix.os }}" runs-on: "${{ matrix.os }}" env: USING_COVERAGE: "3.8,3.9,3.10,3.11" strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] python-version: - "3.7" - "3.8" - "3.9" - "3.10" - "3.11" - "3.12.0-rc.1" - "pypy3.9" exclude: - os: macos-latest python-version: pypy3 steps: - uses: "actions/checkout@v3" with: # We want our tags here fetch-depth: 0 - uses: "actions/setup-python@v4" with: python-version: "${{ matrix.python-version }}" - name: "Install dependencies" run: | python -VV python -msite python -m pip install --upgrade pip setuptools wheel python -m pip install --upgrade coverage[toml] virtualenv tox tox-gh-actions - name: "Run tox targets for ${{ matrix.python-version }}" run: "python -m tox" - name: Upload coverage data uses: actions/upload-artifact@v3 with: name: coverage-data path: ".coverage.*" if-no-files-found: ignore coverage: needs: - tests runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: python-version: "3.11" - name: Install coverage run: python -m pip install --upgrade coverage[toml] - name: Download coverage data uses: actions/download-artifact@v2 with: name: coverage-data - name: Combine coverage run: python -m coverage combine # ignore-errors is so that we don't gag on missing code in .tox environments - name: Generate the HTML report run: python -m coverage html --skip-covered --skip-empty --ignore-errors - name: Upload the HTML report uses: actions/upload-artifact@v3 with: name: html-report path: htmlcov # ignore-errors is so that we don't gag on missing code in .tox environments - name: Enforce the coverage run: python -m coverage report --ignore-errors --fail-under 95 package: name: "Build & verify package" runs-on: "ubuntu-latest" steps: - uses: "actions/checkout@v3" with: # We want our tags here fetch-depth: 0 - uses: hynek/build-and-inspect-python-package@v1.1 install-dev: strategy: matrix: os: ["ubuntu-latest", "windows-latest", "macos-latest"] name: "Verify dev env / ${{ matrix.os }}" runs-on: "${{ matrix.os }}" steps: - uses: "actions/checkout@v3" - uses: "actions/setup-python@v4" with: python-version: "3.11" - name: "Install in dev mode" run: "python -m pip install -e .[dev]" - name: "Import package" run: "python -c 'import hamcrest; print(hamcrest.__version__)'" PyHamcrest-2.1.0/.github/workflows/release.yml000066400000000000000000000036021451524142100213310ustar00rootroot00000000000000name: Release on: push: tags: - V* branches: - main pull_request: branches: - main workflow_dispatch: release: types: - published permissions: contents: read # Needed for trusted publishing. id-token: write jobs: pure-python-wheel-and-sdist: name: Build a pure Python wheel and source distribution runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: # Fetch all tags; this is needed for hatch-vcs fetch-depth: 0 - uses: hynek/build-and-inspect-python-package@v1 # Upload to Test PyPI on every commit on main. publish-test-release: name: Publish in-dev package to test.pypi.org environment: publish-test-release if: github.event_name == 'push' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest needs: - pure-python-wheel-and-sdist steps: - name: Download packages built by build-and-inspect-python-package uses: actions/download-artifact@v3 with: name: Packages path: dist - name: Upload package to Test PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: repository-url: https://test.pypi.org/legacy/ publish-release: name: Publish release environment: publish-release needs: - pure-python-wheel-and-sdist runs-on: ubuntu-latest if: | (github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')) || (github.event_name == 'workflow_dispatch' && startsWith(github.event.ref, 'refs/tags')) steps: - uses: actions/download-artifact@v3 with: name: Packages path: dist - name: Push build artifacts to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: skip_existing: true user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} PyHamcrest-2.1.0/.gitignore000066400000000000000000000003461451524142100155630ustar00rootroot00000000000000.DS_Store *.pyc PyHamcrest.egg-info/ build/ dist/ .tox .coverage* .idea/ *~ .python-version .mypy_cache/ .pytest_cache/ requirements.txt requirements.in .envrc .direnv/ doc/_build/ htmlcov/ src/hamcrest/_version.py .tool-versions PyHamcrest-2.1.0/.pre-commit-config.yaml000066400000000000000000000012051451524142100200470ustar00rootroot00000000000000repos: - repo: meta hooks: - id: check-hooks-apply - id: check-useless-excludes - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.4.0 hooks: - id: debug-statements - repo: https://github.com/asottile/blacken-docs rev: 1.13.0 hooks: - id: blacken-docs # args: ["-l100"] - repo: https://github.com/PyCQA/flake8 rev: 6.0.0 hooks: - id: flake8 exclude: >- (?x)^( examples/.*\.py$ | doc/.*\.py$ ) - repo: https://github.com/psf/black rev: 23.3.0 hooks: - id: black # args: ["-l100"] PyHamcrest-2.1.0/.readthedocs.yml000066400000000000000000000004101451524142100166510ustar00rootroot00000000000000--- version: 2 build: os: ubuntu-22.04 tools: # Keep version in sync with tox.ini (docs and gh-actions). python: "3.11" sphinx: configuration: doc/conf.py python: install: - method: pip path: . extra_requirements: - docs PyHamcrest-2.1.0/CHANGELOG.rst000066400000000000000000000223051451524142100156130ustar00rootroot00000000000000Hamcrest 2.1.0 (2023-10-22) =========================== Features -------- - Add a matcher for exceptions in asyncio future (`#171 `_) Bugfixes -------- - Use the correct generic type in the internal ``describe_keyvalue`` method (`#182 `_) Hamcrest 2.0.4 (2022-08-07) ========================================== Bugfixes -------- - ``has_properties`` now returns ``Matcher[Any]`` type, which addresses type checking errors when nested as a matcher. (`#207 `_) `#207 `_ Features ^^^^^^^^ - Added Python 3.11 testing `#206 `_ Misc ^^^^ - `#175 `_ 2.0.3 (2021-12-12) ------------------ Features ^^^^^^^^ - * Adds the tests to the sdist. Fixed by #150 `#141 `_ - * Update the CI to test Python 3.10 `#160 `_ - * Add pretty string representation for matchers objects `#170 `_ Bugfixes ^^^^^^^^ - Test coverage is now submitted to codecov.io. Fixed by #150 `#135 `_ - Change to the ``has_entry()`` matcher - if exactly one key matches, but the value does not, report only the mismatching value. Fixed by #157 `#156 `_ - * Fix is_() type annotations `#180 `_ Misc ^^^^ - `#150 `_, `#159 `_, `#162 `_, `#163 `_, `#166 `_, `#175 `_ Version 2.0.2 ------------- Various type hint bug fixes. Version 2.0.1 ------------- * Make hamcrest package PEP 561 compatible, i.e. supply type hints for external use. Version 2.0.0 ------------- Drop formal support for 2.x Drop formal support for 3.x < 3.5 Fix #128 - raises() grows support for additional matchers on exception object. * Made has_properties() report all mismatches, not just the first. * Silence warnings. * Type fixes. * Remove obsolete dependencies. Version 1.10.1 -------------- Add support up to Python 3.8 Fix #66 - deprecate contains() in favour of contains_exactly(). Fix #72 - make has_properties mismatch description less verbose by adding option to AllOf not to include matcher description in its mismatch messages. Fix #82 - include exception details in mismatch description. Version 1.9.0 ------------- Drop formal support for 2.x < 2.7 Drop formal support for 3.x < 3.4 Fix #62 - Return result of a deferred call Version 1.8.5 ------------- Fix #56 - incorrect handling of () in ``is_`` matcher Fix #60 - correct calling API call with args Version 1.8.4 ------------- * Fix #54 - Make instance_of work with tuple like isinstance and unittest's assertIsInstance Version 1.8.3 ------------- * Fix #52 - bad handling when reporting mismatches for byte arrays in Python 3 Version 1.8.2 ------------- * [Bug] Fix unicode syntax via u() introduction (puppsman) Version 1.8.1 ------------- * Added ``not_`` alias for is_not [Matteo Bertini] * Added doc directory to the sdist [Alex Brandt] Version 1.8 ----------- * Supported versions - Support for Python 2.5 and Jython 2.5 has been dropped. They may still work, but no promises. * Bug Fixes - [#39] is_empty was missing from the global namespace * New Features - Support for numpy numeric values in iscloseto (Alexander Beedie) - A matcher targeting exceptions and call results (Per Fagrell) Version 1.7 ----------- 2 Sep 2013 (Version 1.7.2) * Supported versions - As of this version, support for Python 3.1 has been dropped due to no available CI platform. - Added support for Python 3.3 * Bug fixes: - string_contains_in_order is now used in the test as it would be in an application, and is properly exported. (Romilly Cocking) - Fix mismatch description of containing_inanyorder (David Keijser) - added import of stringmatches to text/__init__.py (Eric Scheidemantle) - added matches_regexp to __all__ list to library/__init__.py (Eric Scheidemantle) 5 Jan 2010 (Version 1.7.1) * Bug fixes: - included a fix by jaimegildesagredo for issue #28 (has_properties was not importable) - included a fix by keys for contains_inanyorder 29 Dec 2012 (All changes by Chris Rose unless otherwise noted.) * New matchers: - matches_regexp matches a regular expression in a string. - has_properties matches an object with more than one property. - is_empty matches any object with length 0. * Improvements: - Can now do matching against old-style classes. - Sequence matchers handle generators, as well as actual sequences and pseudo-sequences. - README enhancements by ming13 Version 1.6 ----------- 27 Sep 2011 (All changes by Chris Rose unless otherwise noted.) * Packaging: - Python 3.2 support. * New matchers: - has_property('property_name', value_matcher) matches if object has a property with a given name whose value satisfies a given matcher. * Improvements: - hasEntries supports two new calling conventions: has_entries({'key' : value_matcher, 'key_2' : other_value_matcher}) has_entries(key=value_matcher, key_2=other_value_matcher) - Describe Unicode strings by their __repr__. Thanks to: Sebastian Arming - Rewrote documentation. (Jon Reid) Version 1.5 ----------- 29 Apr 2011 * Packaging: - Python 3.1 support. Thanks to: Chris Rose - Easier installation with bootstrapping. Thanks to: Chris Rose * Mock integration: - "match_equality" wraps a matcher to define equality in terms of satisfying the matcher. This allows Hamcrest matchers to be used in libraries that are not Hamcrest-aware, such as Michael Foord's mock library. Thanks to: Chris Rose * New matcher: - "string_contains_in_order" matches string containing given list of substrings, in order. Thanks to: Romilly Cocking * Improved matchers: - For consistency, changed "any_of" and "all_of" to implicitly wrap non-matcher values in EqualTo. Thanks to: Chris Rose - Changed "sameInstance" mismatch description to omit address when describing None. Version 1.4 ----------- 13 Feb 2011 * New matchers: - "has_entries" matches dictionary containing key-value pairs satisfying a given list of alternating keys and value matchers. * "assert_that" can be invoked with a single boolean argument; the reason message is now optional. This is a convenience replacement for assertTrue. Thanks to: Jeong-Min Lee * Improved descriptions: - Reverted 1.3 change: Describe None as "" after all, since it is an object. - "``is_``" no longer says "is ..." in its description, but just lets the inner description pass through. - Consistently use articles to begin descriptions, such as "a sequence containing" instead of "sequence containing". Version 1.3 ----------- 04 Feb 2011 * PyHamcrest is now compatible with Python 3! To install PyHamcrest on Python 3: - Install the "distribute" package, http://pypi.python.org/pypi/distribute - Run "python3 setup.py install" Unit tests are not converted by the install procedure. Run "2to3 -nw ." separately to convert them. You may discover import statements in the __init__.py files (and one in core/base_description.py) that need dot prefixes. Thanks to: Jeong-Min Lee * Improved descriptions and mismatch descriptions of several matchers, including: - Fixed "contains" and "contains_inanyorder" to describe mismatch if item is not a sequence. - Fixed "described_as" to use nested matcher to generate mismatch description. - "same_instance" is more readable, and includes object memory addresses. - If object has a length, "has_length" mismatch describes actual length. - Describe None as "None" instead of "". - Don't wrap angle brackets around a description that already has them. - Improved readability of several matchers. Version 1.2.1 ------------- 04 Jan 2011 * Fixed "assert_that" to describe the diagnosis of the mismatch, not just the mismatched value. PyHamcrest will now give even more useful information. * Expanded BaseDescription.append_description_of to handle all types of values, not just self-describing values. * Deprecated: - Description.append_value no longer needed; call append_description_of instead. - BaseDescription.append_value_list no longer needed; call append_list instead. - SelfDescribingValue no longer needed. 1.2.1 fixes to 1.2: - Corrected manifest so install works. Thanks to: Jeong-Min Lee Version 1.1 ----------- 28 Dec 2010 * New matchers: - "contains" matches sequence containing matching items in order. - "contains_inanyorder" matches sequence containing matching items in any order. * Added Sphinx documentation support. Version 1.0 ----------- 04 Dec 2010 * First official release * Text matchers now support Unicode strings 15 Jan 2008 * Initial submission PyHamcrest-2.1.0/LICENSE.txt000066400000000000000000000026741451524142100154240ustar00rootroot00000000000000BSD 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. PyHamcrest-2.1.0/MANIFEST.in000066400000000000000000000011701451524142100153250ustar00rootroot00000000000000include LICENSE.txt *.rst *.md *.toml *.yml *.yaml *.ini include requirements* graft .github # Tests include tox.ini conftest.py recursive-include tests *.py recursive-include tests *.yml # Documentation include doc/Makefile doc/docutils.conf recursive-include examples *.py recursive-include doc *.png recursive-include doc *.svg recursive-include doc *.py recursive-include doc *.rst prune doc/_build # remove some of the random source prune docker exclude release.sh # Just to keep check-manifest happy; on releases those files are gone. # Last rule wins! exclude changelog.d/*.rst include changelog.d/towncrier_template.rst PyHamcrest-2.1.0/README.rst000066400000000000000000000245161451524142100152670ustar00rootroot00000000000000PyHamcrest ========== | |docs| |status| |version| |downloads| .. |docs| image:: https://readthedocs.org/projects/pyhamcrest/badge/?version=latest :target: https://pyhamcrest.readthedocs.io/en/latest/?badge=latest :alt: Documentation 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 :target: https://pypi.python.org/pypi/PyHamcrest .. |downloads| image:: http://img.shields.io/pypi/dm/PyHamcrest.svg?style=flat :alt: PyPI Package monthly downloads :target: https://pypi.python.org/pypi/PyHamcrest Introduction ============ PyHamcrest is a framework for writing matcher objects, allowing you to declaratively define "match" rules. There are a number of situations where matchers are invaluable, such as UI validation, or data filtering, but it is in the area of writing flexible tests that matchers are most commonly used. This tutorial shows you how to use PyHamcrest for unit testing. When writing tests it is sometimes difficult to get the balance right between overspecifying the test (and making it brittle to changes), and not specifying enough (making the test less valuable since it continues to pass even when the thing being tested is broken). Having a tool that allows you to pick out precisely the aspect under test and describe the values it should have, to a controlled level of precision, helps greatly in writing tests that are "just right." Such tests fail when the behavior of the aspect under test deviates from the expected behavior, yet continue to pass when minor, unrelated changes to the behaviour are made. Installation ============ 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 ======================== We'll start by writing a very simple PyUnit test, but instead of using PyUnit's ``assertEqual`` method, we'll use PyHamcrest's ``assert_that`` construct and the standard set of matchers: .. code:: python from hamcrest import assert_that, equal_to import unittest class BiscuitTest(unittest.TestCase): def testEquals(self): theBiscuit = Biscuit("Ginger") myBiscuit = Biscuit("Ginger") assert_that(theBiscuit, equal_to(myBiscuit)) if __name__ == "__main__": unittest.main() The ``assert_that`` function is a stylized sentence for making a test assertion. In this example, the subject of the assertion is the object ``theBiscuit``, which is the first method parameter. The second method parameter is a matcher for ``Biscuit`` objects, here a matcher that checks one object is equal to another using the Python ``==`` operator. The test passes since the ``Biscuit`` class defines an ``__eq__`` method. If you have more than one assertion in your test you can include an identifier 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") As a convenience, assert_that can also be used to verify a boolean condition: .. code:: python 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. Predefined matchers =================== PyHamcrest comes with a library of useful matchers: * Object * ``equal_to`` - match equal object * ``has_length`` - match ``len()`` * ``has_property`` - match value of property with given name * ``has_properties`` - match an object that has all of the given properties. * ``has_string`` - match ``str()`` * ``instance_of`` - match object type * ``none``, ``not_none`` - match ``None``, or not ``None`` * ``same_instance`` - match same object * ``calling, raises`` - wrap a method call and assert that it raises an exception * Number * ``close_to`` - match number close to a given value * ``greater_than``, ``greater_than_or_equal_to``, ``less_than``, ``less_than_or_equal_to`` - match numeric ordering * Text * ``contains_string`` - match part of a string * ``ends_with`` - match the end of a string * ``equal_to_ignoring_case`` - match the complete string but ignore case * ``equal_to_ignoring_whitespace`` - match the complete string but ignore extra whitespace * ``matches_regexp`` - match a regular expression in a string * ``starts_with`` - match the beginning of a string * ``string_contains_in_order`` - match parts of a string, in relative order * Logical * ``all_of`` - ``and`` together all matchers * ``any_of`` - ``or`` together all matchers * ``anything`` - match anything, useful in composite matchers when you don't care about a particular value * ``is_not``, ``not_`` - negate the matcher * Sequence * ``contains`` - exactly match the entire sequence * ``contains_inanyorder`` - match the entire sequence, but in any order * ``has_item`` - match if given item appears in the sequence * ``has_items`` - match if all given items appear in the sequence, in any order * ``is_in`` - match if item appears in the given sequence * ``only_contains`` - match if sequence's items appear in given list * ``empty`` - match if the sequence is empty * Dictionary * ``has_entries`` - match dictionary with list of key-value pairs * ``has_entry`` - match dictionary containing a key-value pair * ``has_key`` - match dictionary with a key * ``has_value`` - match dictionary with a value * Decorator * ``calling`` - wrap a callable in a deferred object, for subsequent matching on calling behaviour * ``raises`` - Ensure that a deferred callable raises as expected * ``described_as`` - give the matcher a custom failure description * ``is_`` - decorator to improve readability - see `Syntactic sugar` below The arguments for many of these matchers accept not just a matching value, but another matcher, so matchers can be composed for greater flexibility. For example, ``only_contains(less_than(5))`` will match any sequence where every item is less than 5. Syntactic sugar =============== PyHamcrest strives to make your tests as readable as possible. For example, the ``is_`` matcher is a wrapper that doesn't add any extra behavior to the underlying matcher. The following assertions are all equivalent: .. code:: python assert_that(theBiscuit, equal_to(myBiscuit)) assert_that(theBiscuit, is_(equal_to(myBiscuit))) assert_that(theBiscuit, is_(myBiscuit)) The last form is allowed since ``is_(value)`` wraps most non-matcher arguments with ``equal_to``. But if the argument is a type, it is wrapped with ``instance_of``, so the following are also equivalent: .. code:: python assert_that(theBiscuit, instance_of(Biscuit)) assert_that(theBiscuit, is_(instance_of(Biscuit))) assert_that(theBiscuit, is_(Biscuit)) *Note that PyHamcrest's ``is_`` matcher is unrelated to Python's ``is`` operator. The matcher for object identity is ``same_instance``.* Writing custom matchers ======================= PyHamcrest comes bundled with lots of useful matchers, but you'll probably find that you need to create your own from time to time to fit your testing needs. This commonly occurs when you find a fragment of code that tests the same set of properties over and over again (and in different tests), and you want to bundle the fragment into a single assertion. By writing your own matcher you'll eliminate code duplication and make your tests more readable! Let's write our own matcher for testing if a calendar date falls on a Saturday. This is the test we want to write: .. code:: python def testDateIsOnASaturday(self): d = datetime.date(2008, 4, 26) assert_that(d, is_(on_a_saturday())) And here's the implementation: .. code:: python from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod 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"): 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] ) def on_a_saturday(): return IsGivenDayOfWeek(5) For our Matcher implementation we implement the ``_matches`` method - which calls the ``weekday`` method after confirming that the argument (which may not be a date) has such a method - and the ``describe_to`` method - which is used to produce a failure message when a test fails. Here's an example of how the failure message looks: .. code:: python assert_that(datetime.date(2008, 4, 6), is_(on_a_saturday())) fails with the message:: AssertionError: Expected: is calendar date falling on Saturday got: <2008-04-06> Let's say this matcher is saved in a module named ``isgivendayofweek``. We could use it in our test by importing the factory function ``on_a_saturday``: .. code:: python 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__": unittest.main() Even though the ``on_a_saturday`` function creates a new matcher each time it is called, you should not assume this is the only usage pattern for your matcher. Therefore you should make sure your matcher is stateless, so a single instance can be reused between matches. More resources ============== * Documentation_ * Package_ * Sources_ * Hamcrest_ .. _Documentation: https://pyhamcrest.readthedocs.io/ .. _Package: http://pypi.python.org/pypi/PyHamcrest .. _Sources: https://github.com/hamcrest/PyHamcrest .. _Hamcrest: http://hamcrest.org PyHamcrest-2.1.0/changelog.d/000077500000000000000000000000001451524142100157415ustar00rootroot00000000000000PyHamcrest-2.1.0/changelog.d/towncrier_template.rst000066400000000000000000000014351451524142100224050ustar00rootroot00000000000000{% for section, _ in sections.items() %} {% set underline = underlines[0] %}{% if section %}{{section}} {{ underline * section|length }}{% set underline = underlines[1] %} {% endif %} {% if sections[section] %} {% for category, val in definitions.items() if category in sections[section]%} {{ definitions[category]['name'] }} {{ underline * definitions[category]['name']|length }} {% if definitions[category]['showcontent'] %} {% for text, values in sections[section][category].items() %} - {{ text }} {{ values|join(',n ') }} {% endfor %} {% else %} - {{ sections[section][category]['']|join(', ') }} {% endif %} {% if sections[section][category]|length == 0 %} No significant changes. {% else %} {% endif %} {% endfor %} {% else %} No significant changes. {% endif %} {% endfor %} ---- PyHamcrest-2.1.0/doc/000077500000000000000000000000001451524142100143355ustar00rootroot00000000000000PyHamcrest-2.1.0/doc/.gitignore000066400000000000000000000000101451524142100163140ustar00rootroot00000000000000_build/ PyHamcrest-2.1.0/doc/Makefile000066400000000000000000000110051451524142100157720ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest html: help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PyHamcrest.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PyHamcrest.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/PyHamcrest" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PyHamcrest" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." make -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." PyHamcrest-2.1.0/doc/conf.py000066400000000000000000000167621451524142100156500ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # PyHamcrest documentation build configuration file, created by # sphinx-quickstart on Sat Dec 25 21:13:30 2010. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os import alabaster # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath("../src")) from hamcrest import __version__ # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ["sphinx.ext.autodoc", "sphinx.ext.intersphinx", "alabaster"] autodoc_default_options = {"members": None, "show-inheritance": None} autodoc_typehints = "description" intersphinx_mapping = {"python": ("http://docs.python.org/3", None)} # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] # The suffix of source filenames. source_suffix = ".rst" # The encoding of source files. # source_encoding = 'utf-8-sig' # The master toctree document. master_doc = "index" # General information about the project. project = "PyHamcrest" copyright = "2020, hamcrest.org" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The full version, including alpha/beta/rc tags. version = __version__ # The short X.Y version. release = ".".join(version.split(".")[:2]) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ["_build"] # The reST default role (used for this markup: `text`) to use for all documents. default_role = "py:obj" # If true, '()' will be appended to :func: etc. cross-reference text. add_function_parentheses = False # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = "alabaster" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] html_theme_path = [alabaster.get_path()] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_domain_indices = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. # html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = "PyHamcrestdoc" # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). # latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). # latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ("index", "PyHamcrest.tex", "PyHamcrest Documentation", "hamcrest.org"), "manual", ] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # If true, show page references after internal links. # latex_show_pagerefs = False # If true, show URL addresses after external links. # latex_show_urls = False # Additional stuff for the LaTeX preamble. # latex_preamble = '' # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. # latex_domain_indices = True # PyHamcrest customization: Don't skip BaseMatcher's _matches method def skip_member(app, what, name, obj, skip, options): if skip and str(obj).find("BaseMatcher._matches") >= 0: return False return skip def setup(app): app.connect("autodoc-skip-member", skip_member) # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [("index", "pyhamcrest", "PyHamcrest Documentation", ["hamcrest.org"], 1)] PyHamcrest-2.1.0/doc/core.rst000066400000000000000000000011221451524142100160130ustar00rootroot00000000000000Core API ======== .. toctree:: helpers BaseDescription --------------- .. automodule:: hamcrest.core.base_description BaseMatcher ----------- .. automodule:: hamcrest.core.base_matcher :undoc-members: Description ----------- .. automodule:: hamcrest.core.description Matcher ------- .. automodule:: hamcrest.core.matcher SelfDescribing -------------- .. automodule:: hamcrest.core.selfdescribing SelfDescribingValue ------------------- .. automodule:: hamcrest.core.selfdescribingvalue StringDescription ----------------- .. automodule:: hamcrest.core.string_description PyHamcrest-2.1.0/doc/custom_matchers.rst000066400000000000000000000102151451524142100202660ustar00rootroot00000000000000Writing Custom Matchers ======================= PyHamcrest comes bundled with lots of useful matchers, but you'll probably find that you need to create your own from time to time to fit your testing needs. This commonly occurs when you find a fragment of code that tests the same set of properties over and over again (and in different tests), and you want to bundle the fragment into a single assertion. By writing your own matcher you'll eliminate code duplication and make your tests more readable! Let's write our own matcher for testing if a calendar date falls on a Saturday. This is the test we want to write:: def testDateIsOnASaturday(self): d = datetime.date(2008, 04, 26) assert_that(d, is_(on_a_saturday())) And here's the implementation:: from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod 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'): 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]) def on_a_saturday(): return IsGivenDayOfWeek(5) For our Matcher implementation we implement the :py:meth:`~hamcrest.core.base_matcher.BaseMatcher._matches` method - which calls the ``weekday`` method after confirming that the argument (which may not be a date) has such a method - and the :py:func:`~hamcrest.core.selfdescribing.SelfDescribing.describe_to` method - which is used to produce a failure message when a test fails. Here's an example of how the failure message looks:: assert_that(datetime.date(2008, 04, 06), is_(on_a_saturday())) fails with the message:: AssertionError: Expected: is calendar date falling on Saturday got: <2008-04-06> Let's say this matcher is saved in a module named ``isgivendayofweek``. We could use it in our test by importing the factory function ``on_a_saturday``:: from hamcrest import * import unittest from isgivendayofweek import on_a_saturday class DateTest(unittest.TestCase): def testDateIsOnASaturday(self): d = datetime.date(2008, 04, 26) assert_that(d, is_(on_a_saturday())) if __name__ == '__main__': unittest.main() Even though the ``on_a_saturday`` function creates a new matcher each time it is called, you should not assume this is the only usage pattern for your matcher. Therefore you should make sure your matcher is stateless, so a single instance can be reused between matches. If you need your matcher to provide more details in case of a mismatch, you can override the :py:meth:`~hamcrest.core.base_matcher.BaseMatcher.describe_mismatch` method. For example, if we added this :py:meth:`~hamcrest.core.base_matcher.BaseMatcher.describe_mismatch` implementation to our ``IsGivenDayOfWeek`` matcher:: def describe_mismatch(self, item, mismatch_description): day_as_string = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] mismatch_description.append_text('got ') \ .append_description_of(item) \ .append_text(' which is a ') \ .append_text(day_as_string[item.weekday()]) Our matcher would now give the message:: AssertionError: Expected: is calendar date falling on Saturday got: <2008-04-06> which is a Sunday Occasionally, you might also need your matcher to explain why it matched successfully. For example, if your matcher is wrapped by a :py:meth:`~hamcrest.core.core.isnot.is_not` matcher, the ``is_not`` matcher can only explain its mismatches by understanding why your matcher succeeded. In this case, your matcher can implement :py:meth:`~hamcrest.core.base_matcher.BaseMatcher.describe_match`. PyHamcrest-2.1.0/doc/helpers.rst000066400000000000000000000003061451524142100165300ustar00rootroot00000000000000Helpers ------- Utilities for writing Matchers hasmethod ^^^^^^^^^ .. automodule:: hamcrest.core.helpers.hasmethod wrap_matcher ^^^^^^^^^^^^ .. automodule:: hamcrest.core.helpers.wrap_matcher PyHamcrest-2.1.0/doc/index.rst000066400000000000000000000004161451524142100161770ustar00rootroot00000000000000PyHamcrest documentation ======================== Contents: .. toctree:: :maxdepth: 1 tutorial custom_matchers library internals integration core Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` PyHamcrest-2.1.0/doc/integration.rst000066400000000000000000000005231451524142100174120ustar00rootroot00000000000000Integration with PyUnit and Other Libraries =========================================== assert_that ----------- .. automodule:: hamcrest.core.assert_that :exclude-members: assert_that .. autofunction:: assert_that(actual, matcher[, reason]) match_equality -------------- .. automodule:: hamcrest.library.integration.match_equality PyHamcrest-2.1.0/doc/internals.rst000066400000000000000000000005521451524142100170700ustar00rootroot00000000000000Matcher Internals ================= Details of the Matcher internals. .. toctree:: matcher_internals/object_matchers matcher_internals/number_matchers matcher_internals/text_matchers matcher_internals/logical_matchers matcher_internals/sequence_matchers matcher_internals/dictionary_matchers matcher_internals/decorator_matchers PyHamcrest-2.1.0/doc/library.rst000066400000000000000000000005301451524142100165310ustar00rootroot00000000000000Matcher Library =============== Library of Matcher implementations. .. toctree:: matcher_library/object_matchers matcher_library/number_matchers matcher_library/text_matchers matcher_library/logical_matchers matcher_library/sequence_matchers matcher_library/dictionary_matchers matcher_library/decorator_matchers PyHamcrest-2.1.0/doc/matcher_internals/000077500000000000000000000000001451524142100200375ustar00rootroot00000000000000PyHamcrest-2.1.0/doc/matcher_internals/decorator_matchers.rst000066400000000000000000000003371451524142100244440ustar00rootroot00000000000000.. _decorator-matcher-internals: Decorator Matchers ------------------ Matchers that decorate other matchers for better expression. .. automodule:: hamcrest.core.core.described_as .. automodule:: hamcrest.core.core.is_ PyHamcrest-2.1.0/doc/matcher_internals/dictionary_matchers.rst000066400000000000000000000005601451524142100246250ustar00rootroot00000000000000.. _dictionary-matcher-internals: Dictionary Matchers ------------------- Matchers of dictionaries. .. automodule:: hamcrest.library.collection.isdict_containingentries .. automodule:: hamcrest.library.collection.isdict_containing .. automodule:: hamcrest.library.collection.isdict_containingkey .. automodule:: hamcrest.library.collection.isdict_containingvalue PyHamcrest-2.1.0/doc/matcher_internals/logical_matchers.rst000066400000000000000000000004211451524142100240660ustar00rootroot00000000000000.. _logical-matcher-internals: Logical Matchers ---------------- Boolean logic using other matchers. .. automodule:: hamcrest.core.core.allof .. automodule:: hamcrest.core.core.anyof .. automodule:: hamcrest.core.core.isanything .. automodule:: hamcrest.core.core.isnot PyHamcrest-2.1.0/doc/matcher_internals/number_matchers.rst000066400000000000000000000003321451524142100237450ustar00rootroot00000000000000.. _number-matcher-internals: Number Matchers --------------- Matchers that perform numeric comparisons. .. automodule:: hamcrest.library.number.iscloseto .. automodule:: hamcrest.library.number.ordering_comparison PyHamcrest-2.1.0/doc/matcher_internals/object_matchers.rst000066400000000000000000000007221451524142100237260ustar00rootroot00000000000000.. _object-matcher-internals: Object Matchers --------------- Matchers that inspect objects. .. automodule:: hamcrest.core.core.isequal .. automodule:: hamcrest.library.object.haslength .. automodule:: hamcrest.library.object.hasstring .. automodule:: hamcrest.library.object.hasproperty .. automodule:: hamcrest.core.core.isinstanceof .. automodule:: hamcrest.core.core.isnone .. automodule:: hamcrest.core.core.issame .. automodule:: hamcrest.core.core.raises PyHamcrest-2.1.0/doc/matcher_internals/sequence_matchers.rst000066400000000000000000000007421451524142100242720ustar00rootroot00000000000000.. _sequence-matcher-internals: Sequence Matchers ----------------- Matchers of sequences. .. automodule:: hamcrest.library.collection.issequence_containinginorder .. automodule:: hamcrest.library.collection.issequence_containinginanyorder .. automodule:: hamcrest.library.collection.issequence_containing .. automodule:: hamcrest.library.collection.isin .. automodule:: hamcrest.library.collection.issequence_onlycontaining .. automodule:: hamcrest.library.collection.is_empty PyHamcrest-2.1.0/doc/matcher_internals/text_matchers.rst000066400000000000000000000007621451524142100234500ustar00rootroot00000000000000.. _text-matcher-internals: Text Matchers ------------- Matchers that perform text comparisons. .. automodule:: hamcrest.library.text.stringcontains .. automodule:: hamcrest.library.text.stringendswith .. automodule:: hamcrest.library.text.isequal_ignoring_case .. automodule:: hamcrest.library.text.isequal_ignoring_whitespace .. automodule:: hamcrest.library.text.stringmatches .. automodule:: hamcrest.library.text.stringstartswith .. automodule:: hamcrest.library.text.stringcontainsinorder PyHamcrest-2.1.0/doc/matcher_library/000077500000000000000000000000001451524142100175045ustar00rootroot00000000000000PyHamcrest-2.1.0/doc/matcher_library/decorator_matchers.rst000066400000000000000000000005541451524142100241120ustar00rootroot00000000000000Decorator Matchers ------------------ Matchers that decorate other matchers for better expression. See also, :ref:`Decorator matcher internals`. described_as ^^^^^^^^^^^^ .. currentmodule:: hamcrest.core.core.described_as .. autofunction:: described_as is\_ ^^^^ .. currentmodule:: hamcrest.core.core.is_ .. autofunction:: is_ PyHamcrest-2.1.0/doc/matcher_library/dictionary_matchers.rst000066400000000000000000000011541451524142100242720ustar00rootroot00000000000000Dictionary Matchers ------------------- Matchers of dictionaries. See also, :ref:`Dictionary matcher internals` has_entries ^^^^^^^^^^^ .. currentmodule:: hamcrest.library.collection.isdict_containingentries .. autofunction:: has_entries has_entry ^^^^^^^^^ .. currentmodule:: hamcrest.library.collection.isdict_containing .. autofunction:: has_entry has_key ^^^^^^^ .. currentmodule:: hamcrest.library.collection.isdict_containingkey .. autofunction:: has_key has_value ^^^^^^^^^ .. currentmodule:: hamcrest.library.collection.isdict_containingvalue .. autofunction:: has_value PyHamcrest-2.1.0/doc/matcher_library/logical_matchers.rst000066400000000000000000000007571451524142100235470ustar00rootroot00000000000000Logical Matchers ---------------- Boolean logic using other matchers. See also, :ref:`Logical matcher internals` all_of ^^^^^^ .. currentmodule:: hamcrest.core.core.allof .. autofunction:: all_of any_of ^^^^^^ .. currentmodule:: hamcrest.core.core.anyof .. autofunction:: any_of anything ^^^^^^^^ .. currentmodule:: hamcrest.core.core.isanything .. autofunction:: anything is_not ^^^^^^ .. currentmodule:: hamcrest.core.core.isnot .. autofunction:: is_not PyHamcrest-2.1.0/doc/matcher_library/number_matchers.rst000066400000000000000000000011301451524142100234070ustar00rootroot00000000000000Number Matchers --------------- Matchers that perform numeric comparisons. See also, :ref:`Number matcher internals` close_to ^^^^^^^^ .. currentmodule:: hamcrest.library.number.iscloseto .. autofunction:: close_to greater_than, greater_than_or_equal_to, less_than, less_than_or_equal_to ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. currentmodule:: hamcrest.library.number.ordering_comparison .. autofunction:: greater_than .. autofunction:: greater_than_or_equal_to .. autofunction:: less_than .. autofunction:: less_than_or_equal_to PyHamcrest-2.1.0/doc/matcher_library/object_matchers.rst000066400000000000000000000021001451524142100233630ustar00rootroot00000000000000Object Matchers --------------- Matchers that inspect objects. See also, :ref:`Object matcher internals` equal_to ^^^^^^^^ .. currentmodule:: hamcrest.core.core.isequal .. autofunction:: equal_to has_length ^^^^^^^^^^ .. currentmodule:: hamcrest.library.object.haslength .. autofunction:: has_length has_string ^^^^^^^^^^ .. currentmodule:: hamcrest.library.object.hasstring .. autofunction:: has_string has_properties/has_property ^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. currentmodule:: hamcrest.library.object.hasproperty .. autofunction:: has_properties .. autofunction:: has_property instance_of ^^^^^^^^^^^ .. currentmodule:: hamcrest.core.core.isinstanceof .. autofunction:: instance_of none, not_none ^^^^^^^^^^^^^^ .. currentmodule:: hamcrest.core.core.isnone .. autofunction:: none .. autofunction:: not_none same_instance ^^^^^^^^^^^^^ .. currentmodule:: hamcrest.core.core.issame .. autofunction:: same_instance calling, raises ^^^^^^^^^^^^^^^ .. currentmodule:: hamcrest.core.core.raises .. autofunction:: calling .. autofunction:: raises PyHamcrest-2.1.0/doc/matcher_library/sequence_matchers.rst000066400000000000000000000016031451524142100237340ustar00rootroot00000000000000Sequence Matchers ----------------- Matchers of sequences. See also, :ref:`Sequence matcher internals`. contains_exactly ^^^^^^^^^^^^^^^^ .. currentmodule:: hamcrest.library.collection.issequence_containinginorder .. autofunction:: contains_exactly contains_inanyorder ^^^^^^^^^^^^^^^^^^^ .. currentmodule:: hamcrest.library.collection.issequence_containinginanyorder .. autofunction:: contains_inanyorder has_item, has_items ^^^^^^^^^^^^^^^^^^^ .. currentmodule:: hamcrest.library.collection.issequence_containing .. autofunction:: has_items is_in ^^^^^ .. currentmodule:: hamcrest.library.collection.isin .. autofunction:: is_in only_contains ^^^^^^^^^^^^^ .. currentmodule:: hamcrest.library.collection.issequence_onlycontaining .. autofunction:: only_contains empty ^^^^^ .. currentmodule:: hamcrest.library.collection.is_empty .. autofunction:: empty PyHamcrest-2.1.0/doc/matcher_library/text_matchers.rst000066400000000000000000000021011451524142100231020ustar00rootroot00000000000000Text Matchers ------------- Matchers that perform text comparisons. See also, :ref:`Text matcher internals`. contains_string ^^^^^^^^^^^^^^^ .. currentmodule:: hamcrest.library.text.stringcontains .. autofunction:: contains_string ends_with ^^^^^^^^^ .. currentmodule:: hamcrest.library.text.stringendswith .. autofunction:: ends_with equal_to_ignoring_case ^^^^^^^^^^^^^^^^^^^^^^ .. currentmodule:: hamcrest.library.text.isequal_ignoring_case .. autofunction:: equal_to_ignoring_case equal_to_ignoring_whitespace ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. currentmodule:: hamcrest.library.text.isequal_ignoring_whitespace .. autofunction:: equal_to_ignoring_whitespace matches_regexp ^^^^^^^^^^^^^^ .. currentmodule:: hamcrest.library.text.stringmatches .. autofunction:: matches_regexp starts_with ^^^^^^^^^^^ .. currentmodule:: hamcrest.library.text.stringstartswith .. autofunction:: starts_with string_contains_in_order ^^^^^^^^^^^^^^^^^^^^^^^^ .. currentmodule:: hamcrest.library.text.stringcontainsinorder .. autofunction:: string_contains_in_order PyHamcrest-2.1.0/doc/tutorial.rst000066400000000000000000000253021451524142100167340ustar00rootroot00000000000000PyHamcrest Tutorial =================== Introduction ------------ PyHamcrest is a framework for writing matcher objects, allowing you to declaratively define "match" rules. There are a number of situations where matchers are invaluable, such as UI validation, or data filtering, but it is in the area of writing flexible tests that matchers are most commonly used. This tutorial shows you how to use PyHamcrest for unit testing. When writing tests it is sometimes difficult to get the balance right between overspecifying the test (and making it brittle to changes), and not specifying enough (making the test less valuable since it continues to pass even when the thing being tested is broken). Having a tool that allows you to pick out precisely the aspect under test and describe the values it should have, to a controlled level of precision, helps greatly in writing tests that are "just right." Such tests fail when the behavior of the aspect under test deviates from the expected behavior, yet continue to pass when minor, unrelated changes to the behaviour are made. My first PyHamcrest test ------------------------ We'll start by writing a very simple PyUnit test, but instead of using PyUnit's :py:meth:`~unittest.TestCase.assertEqual` method, we'll use PyHamcrest's :py:func:`~hamcrest.core.matcher_assert.assert_that` construct and the standard set of matchers:: from hamcrest import assert_that, equal_to import unittest class BiscuitTest(unittest.TestCase): def testEquals(self): theBiscuit = Biscuit('Ginger') myBiscuit = Biscuit('Ginger') assert_that(theBiscuit, equal_to(myBiscuit)) if __name__ == '__main__': unittest.main() The :py:func:`~hamcrest.core.matcher_assert.assert_that` function is a stylized sentence for making a test assertion. In this example, the subject of the assertion is the object ``theBiscuit``, which is the first method parameter. The second method parameter is a matcher for ``Biscuit`` objects, here a matcher that checks one object is equal to another using the Python ``==`` operator. The test passes since the ``Biscuit`` class defines an ``__eq__`` method. If you have more than one assertion in your test you can include an identifier for the tested value in the assertion:: assert_that(theBiscuit.getChocolateChipCount(), equal_to(10), 'chocolate chips') assert_that(theBiscuit.getHazelnutCount(), equal_to(3), 'hazelnuts') As a convenience, :py:func:`~hamcrest.core.matcher_assert.assert_that` can also be used to verify a boolean condition:: assert_that(theBiscuit.isCooked(), 'cooked') This is equivalent to the :py:meth:`~unittest.TestCase.assert_` method of :py:class:`unittest.TestCase`, but because it's a standalone function, it offers greater flexibility in test writing. Asserting Exceptions -------------------- There's a utility function and matcher available to help you test that your code has the expected behavior in situations where it should raise an exception. The :py:func:`~hamcrest.core.core.raises.calling` function wraps a callable, and then allows you to set arguments to be used in a call to the wrapped callable. This, together with the :py:func:`~hamcrest.core.core.raises.raises` matcher lets you assert that calling a method with certain arguments causes an exception to be thrown. It is also possible to provide a regular expression pattern to the :py:func:`~hamcrest.core.core.raises.raises` matcher allowing you assure that the right issue was found:: assert_that(calling(parse, bad_data), raises(ValueError)) assert_that(calling(translate).with_args(curse_words), raises(LanguageError, "\w+very naughty")) assert_that(broken_function, raises(Exception)) # This will fail and complain that 23 is not callable # assert_that(23, raises(IOError)) Asserting exceptions from async methods --------------------------------------- An async method does not directly return the result or raise an exception but instead returns a Future-object that represent the async operation that can later be resolved with the `await` keyword. The :py:func:`~hamcrest.core.core.future.resolved` utility function can be used to wait for a future to be done but without retrieving the value or raising the exception. The :py:func:`~hamcrest.core.core.future.future_raising` matcher can be used with any future object but combined lets you assert that calling some async method, and waiting for the result, causes an exception to be raised. This is best used together with an async test runner like IsolatedAsyncioTestCase or pytest-asyncio:: async def parse(input: str): ... class Test(unittest.IsolatedAsyncioTestCase): async def testParse(self): future = parse("some bad data") assert_that(await resolved(future), future_raising(ValueError)) But it's possible to use with an async unware runner by explicitly running the event loop in the test:: class Test(unittest.TestCase): def test_parse(self): async def test(): future = parse("some bad data") assert_that(await resolved(future), future_raising(ValueError)) asyncio.get_event_loop().run_until_complete(test()) Predefined matchers ------------------- PyHamcrest comes with a library of useful matchers: * Object * :py:func:`~hamcrest.core.core.isequal.equal_to` - match equal object * :py:func:`~hamcrest.library.object.haslength.has_length` - match ``len(item)`` * :py:func:`~hamcrest.library.object.hasproperty.has_property` - match value of property with given name * :py:func:`~hamcrest.library.object.hasproperty.has_properties` - match an object that has all of the given properties. * :py:func:`~hamcrest.library.object.hasstring.has_string` - match ``str(item)`` * :py:func:`~hamcrest.core.core.isinstanceof.instance_of` - match object type * :py:func:`~hamcrest.core.core.isnone.none`, :py:func:`~hamcrest.core.core.isnone.not_none` - match ``None``, or not ``None`` * :py:func:`~hamcrest.core.core.issame.same_instance` - match same object * :py:func:`~hamcrest.core.core.raises.calling`, :py:func:`~hamcrest.core.core.raises.raises` - wrap a method call and assert that it raises an exception * Number * :py:func:`~hamcrest.library.number.iscloseto.close_to` - match number close to a given value * :py:func:`~hamcrest.library.number.ordering_comparison.greater_than`, :py:func:`~hamcrest.library.number.ordering_comparison.greater_than_or_equal_to`, :py:func:`~hamcrest.library.number.ordering_comparison.less_than`, :py:func:`~hamcrest.library.number.ordering_comparison.less_than_or_equal_to` - match numeric ordering * Text * :py:func:`~hamcrest.library.text.stringcontains.contains_string` - match part of a string * :py:func:`~hamcrest.library.text.stringendswith.ends_with` - match the end of a string * :py:func:`~hamcrest.library.text.isequal_ignoring_case.equal_to_ignoring_case` - match the complete string but ignore case * :py:func:`~hamcrest.library.text.isequal_ignoring_whitespace.equal_to_ignoring_whitespace` - match the complete string but ignore extra whitespace * :py:func:`~hamcrest.library.text.stringstartswith.starts_with` - match the beginning of a string * :py:func:`~hamcrest.library.text.stringcontainsinorder.string_contains_in_order` - match parts of a string, in relative order * Logical * :py:func:`~hamcrest.core.core.allof.all_of` - ``and`` together all matchers * :py:func:`~hamcrest.core.core.anyof.any_of` - ``or`` together all matchers * :py:func:`~hamcrest.core.core.isanything.anything` - match anything, useful in composite matchers when you don't care about a particular value * :py:func:`~hamcrest.core.core.isnot.is_not` - negate the matcher * :py:func:`~hamcrest.core.core.isnot.not_` - alias of :py:func:`~hamcrest.core.core.isnot.is_not` for better readability of negations. * Sequence * :py:func:`~hamcrest.library.collection.issequence_containinginorder.contains` - exactly match the entire sequence * :py:func:`~hamcrest.library.collection.issequence_containinginanyorder.contains_inanyorder` - match the entire sequence, but in any order * :py:func:`~hamcrest.library.collection.issequence_containing.has_item` - match if given item appears in the sequence * :py:func:`~hamcrest.library.collection.issequence_containing.has_items` - match if all given items appear in the list, in any order * :py:func:`~hamcrest.library.collection.isin.is_in` - match if item appears in the given sequence * :py:func:`~hamcrest.library.collection.issequence_onlycontaining.only_contains` - match if sequence's items appear in given list * :py:func:`~hamcrest.library.collection.is_empty.empty` - match if the sequence is empty * Dictionary * :py:func:`~hamcrest.library.collection.isdict_containingentries.has_entries` - match dictionary with list of key-value pairs * :py:func:`~hamcrest.library.collection.isdict_containing.has_entry` - match dictionary containing a key-value pair * :py:func:`~hamcrest.library.collection.isdict_containingkey.has_key` - match dictionary with a key * :py:func:`~hamcrest.library.collection.isdict_containingvalue.has_value` - match dictionary with a value * Decorator * :py:func:`~hamcrest.core.core.described_as.described_as` - give the matcher a custom failure description * :py:func:`~hamcrest.core.core.is_.is_` - decorator to improve readability - see :ref:`sugar`, below The arguments for many of these matchers accept not just a matching value, but another matcher, so matchers can be composed for greater flexibility. For example, ``only_contains(less_than(5))`` will match any sequence where every item is less than 5. .. _sugar: Syntactic sugar --------------- PyHamcrest strives to make your tests as readable as possible. For example, the :py:func:`~hamcrest.core.core.is_.is_` matcher is a wrapper that doesn't add any extra behavior to the underlying matcher. The following assertions are all equivalent:: assert_that(theBiscuit, equal_to(myBiscuit)) assert_that(theBiscuit, is_(equal_to(myBiscuit))) assert_that(theBiscuit, is_(myBiscuit)) The last form is allowed since ``is_(value)`` wraps most non-matcher arguments with :py:func:`~hamcrest.core.core.isequal.equal_to`. But if the argument is a type, it is wrapped with :py:func:`~hamcrest.core.core.isinstanceof.instance_of`, so the following are also equivalent:: assert_that(theBiscuit, instance_of(Biscuit)) assert_that(theBiscuit, is_(instance_of(Biscuit))) assert_that(theBiscuit, is_(Biscuit)) (Note that PyHamcrest's ``is_`` matcher is unrelated to Python's ``is`` operator. The matcher for object identity is :py:func:`~hamcrest.core.core.issame.same_instance`.) PyHamcrest-2.1.0/docker/000077500000000000000000000000001451524142100150375ustar00rootroot00000000000000PyHamcrest-2.1.0/docker/Dockerfile000066400000000000000000000034561451524142100170410ustar00rootroot00000000000000FROM ubuntu:14.04 MAINTAINER Chris Rose # ensure the base image has what we need RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get -yqq install \ build-essential python-pip \ software-properties-common openjdk-7-jdk && \ add-apt-repository ppa:fkrull/deadsnakes && \ apt-get update # install legacy python versions RUN DEBIAN_FRONTEND=noninteractive apt-get -yqq install \ python2.5-dev python2.6-dev python2.7-dev python3.1-dev python3.2-dev python3.3-dev python3.4-dev # install other commonly needed libraries for building Python extensions RUN DEBIAN_FRONTEND=noninteractive apt-get -yqq install \ freetds-dev libffi-dev libicu-dev libldap2-dev libmemcached-dev libxml2-dev libxmlsec1-dev libxslt1-dev # add Jython installer # ADD jython-installer-2.7-b4.jar /tmp/ ADD http://search.maven.org/remotecontent?filepath=org/python/jython-installer/2.7-b4/jython-installer-2.7-b4.jar /tmp/jython-installer-2.7-b4.jar # install pypy versions # ADD pypy-2.5.0-linux64.tar.bz2 /opt/ # ADD pypy3-2.4.0-linux64.tar.bz2 /opt/ RUN mkdir -p /opt ADD https://bitbucket.org/pypy/pypy/downloads/pypy3-2.4.0-linux64.tar.bz2 /tmp/ RUN cd /opt && tar -xf /tmp/pypy3-2.4.0-linux64.tar.bz2 ADD https://bitbucket.org/pypy/pypy/downloads/pypy-2.5.0-linux64.tar.bz2 /tmp/ RUN cd /opt && tar -xf /tmp/pypy-2.5.0-linux64.tar.bz2 # install Jython version RUN java -jar /tmp/jython-installer-2.7-b4.jar -d /opt/jython-2.7-b4 -s -t all ENV PATH /opt/jython-2.7-b4/bin:$PATH # bootstrap jython JAR cache RUN jython # make PyPy available ENV PATH /opt/pypy-2.5.0-linux64/bin:/opt/pypy3-2.4.0-linux64/bin:$PATH ENV PYTHON_BUILD_DOCKER=true # install tox RUN pip install tox ADD clean-launch.sh /tools/clean-launch.sh VOLUME /src WORKDIR /src ENTRYPOINT ["/tools/clean-launch.sh"] CMD ["tox"] PyHamcrest-2.1.0/docker/README.md000066400000000000000000000012761451524142100163240ustar00rootroot00000000000000# Test hamcrest with Docker ## Simple testing steps (this assumes that you have [Docker](https://docker.com) installed) 1. cd to the directory containing PyHamcrest's `tox.ini` file. 2. run `docker run --rm -v $(pwd):/src chrisr/pybuilder:latest` That's it! This will test PyHamcrest with all supported versions of Python ## Tweaking the build image 1. in this directory, modify the `Dockerfile` to have the setup you want 2. `docker build --tag $USER/pybuilder:latest .` 3. run your build 4. submit a pull request to the `hamcrest/PyHamcrest` repo with your changes to the Dockerfile We'll merge and publish the new tag to `chrisr/pybuilder:latest`, making the new instructions up to date. PyHamcrest-2.1.0/docker/clean-launch.sh000077500000000000000000000001211451524142100177220ustar00rootroot00000000000000#!/bin/bash find /src \( -name __pycache__ -o -name '*.pyc' \) -delete exec "$@" PyHamcrest-2.1.0/examples/000077500000000000000000000000001451524142100154065ustar00rootroot00000000000000PyHamcrest-2.1.0/examples/CustomDateMatcher.py000066400000000000000000000031751451524142100213420ustar00rootroot00000000000000import sys sys.path.append("..") from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.helpers.hasmethod import hasmethod from hamcrest import * import unittest import datetime class IsGivenDayOfWeek(BaseMatcher): """Matches dates that fall on a given day of the week.""" def __init__(self, day): self.day = day # Monday is 0, Sunday is 6 def _matches(self, item): """Test whether item matches.""" if not hasmethod(item, "weekday"): return False return item.weekday() == self.day def describe_to(self, description): """Describe the matcher.""" 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(): """Factory function to generate Saturday matcher.""" return IsGivenDayOfWeek(5) class SampleTest(unittest.TestCase): def testDateIsOnASaturday(self): """Example of successful match.""" d = datetime.date(2008, 4, 26) assert_that(d, is_(on_a_saturday())) def testFailsWithMismatchedDate(self): """Example of what happens with date that doesn't match.""" d = datetime.date(2008, 4, 6) assert_that(d, is_(on_a_saturday())) def testFailsWithNonDate(self): """Example of what happens with object that isn't a date.""" d = "oops" assert_that(d, is_(on_a_saturday())) if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/examples/ExampleWithAssertThat.py000066400000000000000000000010511451524142100222070ustar00rootroot00000000000000import sys sys.path.append("..") from hamcrest import * import unittest class ExampleWithAssertThat(unittest.TestCase): def testUsingAssertThat(self): assert_that("xx", is_("xx")) assert_that("yy", is_not("xx")) assert_that("i like cheese", contains_string("cheese")) def testCanAlsoSupplyDescriptiveReason(self): assert_that("xx", is_("xx"), "description") def testCanAlsoAssertPlainBooleans(self): assert_that(True, "This had better not fail") if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/pyproject.toml000066400000000000000000000075761451524142100165230ustar00rootroot00000000000000[build-system] requires = ["hatchling", "hatch-vcs"] build-backend = "hatchling.build" [project] name = "PyHamcrest" description = "Hamcrest framework for matcher objects" readme = "README.rst" requires-python = ">= 3.6" license = { file = "LICENSE.txt" } keywords = [ "hamcrest", "matchers", "pyunit", "unit", "test", "testing", "unittest", "unittesting", ] authors = [ { name = "Chris Rose", email="offline@offby1.net" }, { name = "Simon Brunning" }, { name = "Jon Reid" }, ] classifiers = [ "Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: Jython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development", "Topic :: Software Development :: Quality Assurance", "Topic :: Software Development :: Testing", ] dynamic = ["version"] [project.optional-dependencies] docs = ["sphinx~=4.0", "alabaster~=0.7"] tests = [ "pytest>=5.0", "pytest-sugar", "pytest-xdist", "coverage[toml]", # No point on Pypy thanks to https://github.com/python/typed_ast/issues/111 "pytest-mypy-plugins; platform_python_implementation != 'PyPy'", # Can't use 0.940: https://github.com/python/mypy/issues/12339 "mypy!=0.940; platform_python_implementation != 'PyPy'", "types-mock", "dataclasses; python_version<'3.7'", "types-dataclasses; python_version<'3.7'", "pyyaml", ] tests-numpy = [ "PyHamcrest[tests]", "numpy", ] dev = [ "PyHamcrest[docs,tests]", "towncrier", "twine", "pytest-mypy", "flake8", "black", "tox", "tox-asdf", "doc2dash", ] [project.urls] History = "https://github.com/hamcrest/PyHamcrest/blob/main/CHANGELOG.rst" Source = "https://github.com/hamcrest/PyHamcrest/" Issues = "https://github.com/hamcrest/PyHamcrest/issues" [tool.hatch.version] source = "vcs" raw-options = { local_scheme = "no-local-version" } [tool.hatch.build.hooks.vcs] version-file = "src/hamcrest/_version.py" template = """\ # coding: utf-8 # file generated by setuptools_scm # don't change, don't track in version control version = {version!r} # pragma: no mutate version_tuple = {version_tuple!r} # pragma: no mutate """ [tool.hatch.build.targets.sdist] exclude = [ "/changelog.d/*.rst", "/release.sh", "/.github", ] [tool.hatch.build.targets.wheel] exclude = [ "/examples", ] packages = [ "src/hamcrest", ] [tool.coverage.run] parallel = true branch = true source = ["hamcrest"] [tool.coverage.paths] source = ["src", ".tox/*/lib/*/site-packages"] [tool.coverage.report] show_missing = true skip_covered = true exclude_lines = [ # a more strict default pragma "\\# pragma: no cover\\b", # allow defensive code "^\\s*raise AssertionError\\b", "^\\s*raise NotImplementedError\\b", "^\\s*return NotImplemented\\b", "^\\s*raise$", # typing-related code "^if (False|TYPE_CHECKING):", ": \\.\\.\\.(\\s*#.*)?$", "^ +\\.\\.\\.$", "-> ['\"]?NoReturn['\"]?:", ] [tool.black] line_length = 100 [tool.interrogate] verbose = 2 fail-under = 100 whitelist-regex = ["test_.*"] [tool.isort] profile = "hamcrests" known_first_party = "hamcrest" known_third_party = ["hypothesis", "pytest", "setuptools", "six"] [tool.towncrier] package = "hamcrest" package_dir = "src" filename = "CHANGELOG.rst" directory = "changelog.d" issue_format = "`#{issue} `_" PyHamcrest-2.1.0/release.sh000077500000000000000000000006741451524142100155560ustar00rootroot00000000000000#!/usr/bin/env bash set -eu -o pipefail HERE="$( unset CDPATH cd "$(dirname "$0")" pwd )" cd "$HERE" HATCH_CURRENT=$(hatch version) TAG=${1:?"a tag must be provided. Consider using hatch's next: V$HATCH_CURRENT"} # towncrier needs the version to be tagged before running git tag "$TAG" # generate the changelog hatch run towncrier build --yes # re-tag git tag -f "$TAG" echo "To release, run 'git push origin --tags \"$TAG\"'" PyHamcrest-2.1.0/src/000077500000000000000000000000001451524142100143575ustar00rootroot00000000000000PyHamcrest-2.1.0/src/hamcrest/000077500000000000000000000000001451524142100161655ustar00rootroot00000000000000PyHamcrest-2.1.0/src/hamcrest/__init__.py000066400000000000000000000005231451524142100202760ustar00rootroot00000000000000from hamcrest.core import * from hamcrest.library import * from hamcrest import core, library from hamcrest._version import version __version__ = version __author__ = "Chris Rose" __copyright__ = "Copyright 2020 hamcrest.org" __license__ = "BSD, see License.txt" __all__ = [] __all__.extend(core.__all__) __all__.extend(library.__all__) PyHamcrest-2.1.0/src/hamcrest/core/000077500000000000000000000000001451524142100171155ustar00rootroot00000000000000PyHamcrest-2.1.0/src/hamcrest/core/__init__.py000066400000000000000000000006671451524142100212370ustar00rootroot00000000000000from 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", ] PyHamcrest-2.1.0/src/hamcrest/core/assert_that.py000066400000000000000000000055351451524142100220200ustar00rootroot00000000000000import warnings from typing import Optional, TypeVar, cast, overload from hamcrest.core.matcher import Matcher from hamcrest.core.string_description import StringDescription __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" # unittest integration; hide these frames from tracebacks __unittest = True # py.test integration; hide these frames from tracebacks __tracebackhide__ = True 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.) :param actual: The object to evaluate as the actual value. :param matcher: The matcher to satisfy as the expected condition. :param reason: Optional explanation to include in failure description. ``assert_that`` passes the actual value to the matcher for evaluation. If the matcher is not satisfied, an exception is thrown describing the mismatch. ``assert_that`` is designed to integrate well with PyUnit and other unit testing frameworks. The exception raised for an unmet assertion is an :py:exc:`AssertionError`, which PyUnit reports as a test failure. With a different set of parameters, ``assert_that`` can also verify a boolean condition: .. function:: assert_that(assertion[, reason]) :param assertion: Boolean condition to verify. :param reason: Optional explanation to include in failure description. This is equivalent to the :py:meth:`~unittest.TestCase.assertTrue` method of :py:class:`unittest.TestCase`, but offers greater flexibility in test writing by being a standalone function. """ if isinstance(matcher, Matcher): _assert_match(actual=actual_or_assertion, matcher=matcher, reason=reason) else: 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: 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: ") matcher.describe_mismatch(actual, description) description.append_text("\n") raise AssertionError(description) def _assert_bool(assertion: bool, reason: Optional[str] = None) -> None: if not assertion: if not reason: reason = "Assertion failed" raise AssertionError(reason) PyHamcrest-2.1.0/src/hamcrest/core/base_description.py000066400000000000000000000037541451524142100230150ustar00rootroot00000000000000from typing import Any, Iterable from hamcrest.core.description import Description 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: str) -> Description: self.append(text) return self def append_description_of(self, value: Any) -> Description: if not ismock(value) and hasmethod(value, "describe_to"): value.describe_to(self) elif isinstance(value, str): self.append(repr(value)) else: description = str(value) if description[:1] == "<" and description[-1:] == ">": self.append(description) else: self.append("<") self.append(description) self.append(">") return self def append_list(self, start: str, separator: str, end: str, list: Iterable[Any]) -> Description: separate = False self.append(start) for item in list: if separate: self.append(separator) self.append_description_of(item) separate = True self.append(end) return self def append(self, string: str) -> None: """Append the string to the description.""" raise NotImplementedError("append") 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: str) -> str: if ch == "'": return "'" elif ch == "\n": return "\\n" elif ch == "\r": return "\\r" elif ch == "\t": return "\\t" else: return ch PyHamcrest-2.1.0/src/hamcrest/core/base_matcher.py000066400000000000000000000033131451524142100221040ustar00rootroot00000000000000from 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" T = TypeVar("T") class BaseMatcher(Matcher[T]): """Base class for all :py:class:`~hamcrest.core.matcher.Matcher` implementations. Most implementations can just implement :py:obj:`_matches`, leaving the handling of any mismatch description to the ``matches`` method. But if it makes more sense to generate the mismatch description during the matching, override :py:meth:`~hamcrest.core.matcher.Matcher.matches` instead. """ def __str__(self) -> str: return tostring(self) def __repr__(self) -> str: """Returns matcher string representation.""" return "<{0}({1})>".format( self.__class__.__name__, shorten(tostring(self), 60, placeholder="...") ) 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: 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) PyHamcrest-2.1.0/src/hamcrest/core/core/000077500000000000000000000000001451524142100200455ustar00rootroot00000000000000PyHamcrest-2.1.0/src/hamcrest/core/core/__init__.py000066400000000000000000000017001451524142100221540ustar00rootroot00000000000000"""Fundamental matchers of objects and values, and composite matchers.""" from hamcrest.core.core.allof import all_of from hamcrest.core.core.anyof import any_of from hamcrest.core.core.described_as import described_as from hamcrest.core.core.is_ import is_ from hamcrest.core.core.isanything import anything from hamcrest.core.core.isequal import equal_to from hamcrest.core.core.isinstanceof import instance_of from hamcrest.core.core.isnone import none, not_none from hamcrest.core.core.isnot import is_not, not_ from hamcrest.core.core.issame import same_instance 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", ] PyHamcrest-2.1.0/src/hamcrest/core/core/allof.py000066400000000000000000000044171451524142100215220ustar00rootroot00000000000000from 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[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) 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(" ") 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 ") return not found_mismatch def describe_mismatch(self, item: T, mismatch_description: Description) -> None: self.matches(item, mismatch_description) def describe_to(self, description: Description) -> None: description.append_list("(", " and ", ")", self.matchers) 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. The matchers are evaluated from left to right using short-circuit evaluation, so evaluation stops as soon as a matcher returns ``False``. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ return AllOf(*[wrap_matcher(item) for item in items]) PyHamcrest-2.1.0/src/hamcrest/core/core/anyof.py000066400000000000000000000024641451524142100215410ustar00rootroot00000000000000from 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[T]): def __init__(self, *matchers: Matcher[T]) -> None: self.matchers = matchers 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) -> None: description.append_list("(", " or ", ")", self.matchers) 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. The matchers are evaluated from left to right using short-circuit evaluation, so evaluation stops as soon as a matcher returns ``True``. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ return AnyOf(*[wrap_matcher(item) for item in items]) PyHamcrest-2.1.0/src/hamcrest/core/core/described_as.py000066400000000000000000000036231451524142100230320ustar00rootroot00000000000000import 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]+)") 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: Any, mismatch_description: Optional[Description] = None) -> bool: return self.matcher.matches(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: Description) -> None: text_start = 0 for match in re.finditer(ARG_PATTERN, self.template): 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() if text_start < len(self.template): description.append_text(self.template[text_start:]) 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. :param matcher: The matcher to satisfy. :param value1,...: Optional comma-separated list of substitution values. The description may contain substitution placeholders %0, %1, etc. These will be replaced by any values that follow the matcher. """ return DescribedAs(description, matcher, *values) PyHamcrest-2.1.0/src/hamcrest/core/core/future.py000066400000000000000000000113061451524142100217320ustar00rootroot00000000000000import 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 PyHamcrest-2.1.0/src/hamcrest/core/core/is_.py000066400000000000000000000060021451524142100211670ustar00rootroot00000000000000from typing import Optional, Type, TypeVar, overload, Any 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" T = TypeVar("T") class Is(BaseMatcher[T]): def __init__(self, matcher: Matcher[T]) -> None: self.matcher = matcher def matches(self, item: T, mismatch_description: Optional[Description] = None) -> bool: return self.matcher.matches(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: Description): description.append_description_of(self.matcher) @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))``. :param x: The matcher to satisfy, or a type for :py:func:`~hamcrest.core.core.isinstanceof.instance_of` matching, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher compares the evaluated object to the given matcher. .. note:: PyHamcrest's ``is_`` matcher is unrelated to Python's ``is`` operator. The matcher for object identity is :py:func:`~hamcrest.core.core.issame.same_instance`. If the ``x`` argument is a matcher, its behavior is retained, but the test may be more expressive. For example:: assert_that(value, less_than(5)) assert_that(value, is_(less_than(5))) If the ``x`` argument is a type, it is wrapped in an :py:func:`~hamcrest.core.core.isinstanceof.instance_of` matcher. This makes the following statements equivalent:: assert_that(cheese, instance_of(Cheddar)) assert_that(cheese, is_(instance_of(Cheddar))) assert_that(cheese, is_(Cheddar)) Otherwise, if the ``x`` argument is not a matcher, it is wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher. This makes the following statements equivalent:: assert_that(cheese, equal_to(smelly)) assert_that(cheese, is_(equal_to(smelly))) assert_that(cheese, is_(smelly)) Choose the style that makes your expression most readable. This will vary depending on context. """ return Is(_wrap_value_or_type(x)) PyHamcrest-2.1.0/src/hamcrest/core/core/isanything.py000066400000000000000000000017071451524142100226010ustar00rootroot00000000000000from 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[Any]): def __init__(self, description: Optional[str]) -> None: self.description: str = description or "ANYTHING" def _matches(self, item: Any) -> bool: return True def describe_to(self, description: Description) -> None: description.append_text(self.description) def anything(description: Optional[str] = None) -> Matcher[Any]: """Matches anything. :param description: Optional string used to describe this matcher. This matcher always evaluates to ``True``. Specify this in composite matchers when the value of a particular element is unimportant. """ return IsAnything(description) PyHamcrest-2.1.0/src/hamcrest/core/core/isequal.py000066400000000000000000000020171451524142100220620ustar00rootroot00000000000000from 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[Any]): def __init__(self, equals: Any) -> None: self.object = equals def _matches(self, item: Any) -> bool: return item == self.object def describe_to(self, description: Description) -> None: nested_matcher = isinstance(self.object, Matcher) if nested_matcher: description.append_text("<") description.append_description_of(self.object) if nested_matcher: description.append_text(">") 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. This matcher compares the evaluated object to ``obj`` for equality.""" return IsEqual(obj) PyHamcrest-2.1.0/src/hamcrest/core/core/isinstanceof.py000066400000000000000000000023551451524142100231110ustar00rootroot00000000000000from 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" class IsInstanceOf(BaseMatcher[object]): def __init__(self, expected_type: Type) -> None: if not is_matchable_type(expected_type): raise TypeError("IsInstanceOf requires type") self.expected_type = expected_type def _matches(self, item: object) -> bool: return isinstance(item, self.expected_type) def describe_to(self, description: Description) -> None: description.append_text("an instance of ").append_text(self.expected_type.__name__) 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. This matcher checks whether the evaluated object is an instance of ``atype`` or an instance of any class that inherits from ``atype``. Example:: instance_of(str) """ return IsInstanceOf(atype) PyHamcrest-2.1.0/src/hamcrest/core/core/isnone.py000066400000000000000000000013511451524142100217120ustar00rootroot00000000000000from 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[Optional[Any]]): def _matches(self, item: Any) -> bool: return item is None def describe_to(self, description: Description) -> None: description.append_text("None") def none() -> Matcher[Optional[Any]]: """Matches if object is ``None``.""" return IsNone() def not_none() -> Matcher[Optional[Any]]: """Matches if object is not ``None``.""" return is_not(none()) PyHamcrest-2.1.0/src/hamcrest/core/core/isnot.py000066400000000000000000000042121451524142100215520ustar00rootroot00000000000000from 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" T = TypeVar("T") class IsNot(BaseMatcher[T]): def __init__(self, matcher: Matcher[T]) -> None: self.matcher = matcher def _matches(self, item: T) -> bool: return not self.matcher.matches(item) 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]: ... @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. :param match: The matcher to negate. This matcher compares the evaluated object to the negation of the given matcher. If the ``match`` argument is not a matcher, it is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality, and thus matches for inequality. Examples:: assert_that(cheese, is_not(equal_to(smelly))) assert_that(cheese, is_not(smelly)) """ return IsNot(_wrap_value_or_type(match)) def not_(match: Union[Matcher[T], T]) -> Matcher[T]: """Alias of :py:func:`is_not` for better readability of negations. Examples:: assert_that(alist, not_(has_item(item))) """ return is_not(match) PyHamcrest-2.1.0/src/hamcrest/core/core/issame.py000066400000000000000000000025001451524142100216750ustar00rootroot00000000000000from 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" T = TypeVar("T") class IsSame(BaseMatcher[T]): def __init__(self, obj: T) -> None: self.object = obj def _matches(self, item: T) -> bool: return item is 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: 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_description_of(item) 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. This matcher invokes the ``is`` identity operator to determine if the evaluated object is the the same object as ``obj``. """ return IsSame(obj) PyHamcrest-2.1.0/src/hamcrest/core/core/raises.py000066400000000000000000000123501451524142100217060ustar00rootroot00000000000000import 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.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[Callable[..., Any]]): def __init__( self, expected: Type[Exception], pattern: Optional[str] = None, matching: Optional[Matcher] = None, ) -> None: self.pattern = pattern self.matcher = matching self.expected = expected self.actual: Optional[BaseException] = None self.function: Optional[Callable[..., Any]] = None def _matches(self, function: Callable[..., Any]) -> bool: if not callable(function): return False self.function = cast(Callable[..., Any], ref(function)) return self._call_function(function) def _call_function(self, function: Callable[..., Any]) -> bool: self.actual = None try: function() except BaseException: self.actual = sys.exc_info()[1] if isinstance(self.actual, self.expected): if self.pattern is not None: 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) -> None: description.append_text("Expected a callable raising %s" % self.expected) 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() if function is None or function is not item: self.function = ref(item) if not self._call_function(item): return if self.actual is None: description.append_text("No exception raised.") 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 ") 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)) ) 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: Type[Exception], pattern=None, matching=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. 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(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, matching) class DeferredCallable(object): def __init__(self, func: Callable[..., Any]): self.func = func self.args: Tuple[Any, ...] = tuple() self.kwargs: Mapping[str, Any] = {} def __call__(self): self.func(*self.args, **self.kwargs) def with_args(self, *args, **kwargs): self.args = args self.kwargs = kwargs return self 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. :param func: The function or method to be called The arguments can be provided with a call to the `with_args` function on the returned object:: calling(my_method).with_args(arguments, and_='keywords') """ return DeferredCallable(func) PyHamcrest-2.1.0/src/hamcrest/core/description.py000066400000000000000000000027771451524142100220270ustar00rootroot00000000000000from typing import Any, Iterable __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class Description: """A description of a :py:class:`~hamcrest.core.matcher.Matcher`. A :py:class:`~hamcrest.core.matcher.Matcher` will describe itself to a description which can later be used for reporting. """ def append_text(self, text: str) -> "Description": """Appends some plain text to the description. :returns: ``self``, for chaining """ raise NotImplementedError("append_text") def append_description_of(self, value: Any) -> "Description": """Appends description of given value to this description. If the value implements :py:meth:`~hamcrest.core.selfdescribing.SelfDescribing.describe_to`, then it will be used. :returns: ``self``, for chaining """ raise NotImplementedError("append_description_of") 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. :param separator: String that will separate each object in the description. :param end: String that will end the list description. :param list: List of objects to be described. :returns: ``self``, for chaining """ raise NotImplementedError("append_list") PyHamcrest-2.1.0/src/hamcrest/core/helpers/000077500000000000000000000000001451524142100205575ustar00rootroot00000000000000PyHamcrest-2.1.0/src/hamcrest/core/helpers/__init__.py000066400000000000000000000002221451524142100226640ustar00rootroot00000000000000"""Utilities for writing Matchers.""" __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" PyHamcrest-2.1.0/src/hamcrest/core/helpers/hasmethod.py000066400000000000000000000005321451524142100231050ustar00rootroot00000000000000__author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" def hasmethod(obj: object, methodname: str) -> bool: """Does ``obj`` have a method named ``methodname``?""" if not hasattr(obj, methodname): return False method = getattr(obj, methodname) return callable(method) PyHamcrest-2.1.0/src/hamcrest/core/helpers/ismock.py000066400000000000000000000004771451524142100224260ustar00rootroot00000000000000from typing import Any, List, Type MOCKTYPES: List[Type] = [] try: from mock import Mock MOCKTYPES += [Mock] except ImportError: pass try: from unittest.mock import Mock MOCKTYPES += [Mock] except ImportError: pass def ismock(obj: Any) -> bool: return isinstance(obj, tuple(MOCKTYPES)) PyHamcrest-2.1.0/src/hamcrest/core/helpers/wrap_matcher.py000066400000000000000000000013541451524142100236100ustar00rootroot00000000000000from typing import Type, TypeVar, Union from hamcrest.core.base_matcher import Matcher from hamcrest.core.core.isequal import equal_to __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" T = TypeVar("T") 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 in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher. """ if isinstance(x, Matcher): return x else: return equal_to(x) def is_matchable_type(expected_type: Type) -> bool: if isinstance(expected_type, type): return True return False PyHamcrest-2.1.0/src/hamcrest/core/matcher.py000066400000000000000000000051501451524142100211130ustar00rootroot00000000000000from 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(Generic[T], SelfDescribing): """A matcher over acceptable values. A matcher is able to describe itself to give feedback when it fails. Matcher implementations should *not* directly implement this protocol. Instead, *extend* the :py:class:`~hamcrest.core.base_matcher.BaseMatcher` class, which will ensure that the :py:class:`~hamcrest.core.matcher.Matcher` API can grow to support new features and remain compatible with all :py:class:`~hamcrest.core.matcher.Matcher` implementations. """ 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 provided, it will generate a description of why the matcher has not 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") def describe_mismatch(self, item: T, mismatch_description: Description) -> None: """Generates a description of why the matcher has not accepted the item. The description will be part of a larger description of why a matching failed, so it should be concise. This method assumes that ``matches(item)`` is ``False``, but will not check this. :param item: The item that the :py:class:`~hamcrest.core.matcher.Matcher` has rejected. :param mismatch_description: The description to be built or appended to. """ 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") PyHamcrest-2.1.0/src/hamcrest/core/selfdescribing.py000066400000000000000000000011761451524142100224570ustar00rootroot00000000000000from hamcrest.core.description import Description __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class SelfDescribing: """The ability of an object to describe itself.""" 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 which this is just a component, so it should be worded appropriately. :param description: The description to be built or appended to. """ raise NotImplementedError("describe_to") PyHamcrest-2.1.0/src/hamcrest/core/selfdescribingvalue.py000066400000000000000000000016401451524142100235100ustar00rootroot00000000000000import 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" __license__ = "BSD, see License.txt" class SelfDescribingValue(SelfDescribing): """Wrap any value in a ``SelfDescribingValue`` to satisfy the :py:class:`~hamcrest.core.selfdescribing.SelfDescribing` interface. **Deprecated:** No need for this class now that :py:meth:`~hamcrest.core.description.Description.append_description_of` handles any type of value. """ def __init__(self, value: Any) -> None: warnings.warn("SelfDescribingValue no longer needed", DeprecationWarning) self.value = value def describe_to(self, description: Description) -> None: """Generates a description of the value.""" description.append_description_of(self.value) PyHamcrest-2.1.0/src/hamcrest/core/string_description.py000066400000000000000000000016541451524142100234060ustar00rootroot00000000000000from hamcrest.core.selfdescribing import SelfDescribing from .base_description import BaseDescription __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" def tostring(selfdescribing: SelfDescribing) -> str: """Returns the description of a :py:class:`~hamcrest.core.selfdescribing.SelfDescribing` object as a string. :param selfdescribing: The object to be described. :returns: The description of the object. """ return str(StringDescription().append_description_of(selfdescribing)) class StringDescription(BaseDescription): """A :py:class:`~hamcrest.core.description.Description` that is stored as a string. """ def __init__(self) -> None: self.out = "" def __str__(self) -> str: """Returns the description.""" return self.out def append(self, string: str) -> None: self.out += str(string) PyHamcrest-2.1.0/src/hamcrest/library/000077500000000000000000000000001451524142100176315ustar00rootroot00000000000000PyHamcrest-2.1.0/src/hamcrest/library/__init__.py000066400000000000000000000017471451524142100217530ustar00rootroot00000000000000"""Library of Matcher implementations.""" from hamcrest.core import * from hamcrest.library.collection import * from hamcrest.library.integration import * from hamcrest.library.number import * from hamcrest.library.object import * from hamcrest.library.text import * __author__ = "Jon Reid" __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", ] PyHamcrest-2.1.0/src/hamcrest/library/collection/000077500000000000000000000000001451524142100217645ustar00rootroot00000000000000PyHamcrest-2.1.0/src/hamcrest/library/collection/__init__.py000066400000000000000000000015141451524142100240760ustar00rootroot00000000000000"""Matchers of collections.""" from .is_empty import empty from .isdict_containing import has_entry from .isdict_containingentries import has_entries from .isdict_containingkey import has_key from .isdict_containingvalue import has_value from .isin import is_in 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 __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", ] PyHamcrest-2.1.0/src/hamcrest/library/collection/is_empty.py000066400000000000000000000020641451524142100241710ustar00rootroot00000000000000from 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[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)) except TypeError: if mismatch_description: mismatch_description.append_text("does not support length") return False def describe_to(self, description: Description) -> None: description.append_text("an empty collection") def empty() -> Matcher[Sized]: """ This matcher matches any collection-like object that responds to the __len__ method, and has a length of 0. """ return IsEmpty() PyHamcrest-2.1.0/src/hamcrest/library/collection/isdict_containing.py000066400000000000000000000070441451524142100260330ustar00rootroot00000000000000from 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" K = TypeVar("K", bound=Hashable) # TODO - covariant? V = TypeVar("V") 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, 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) -> 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: 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. :param key_match: The matcher to satisfy for the key, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. :param value_match: The matcher to satisfy for the value, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher iterates the evaluated dictionary, searching for any key-value entry that satisfies ``key_match`` and ``value_match``. If a matching entry is found, ``has_entry`` is satisfied. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. Examples:: has_entry(equal_to('foo'), equal_to(1)) has_entry('foo', 1) """ return IsDictContaining(wrap_matcher(key_match), wrap_matcher(value_match)) PyHamcrest-2.1.0/src/hamcrest/library/collection/isdict_containingentries.py000066400000000000000000000130711451524142100274220ustar00rootroot00000000000000from typing import Any, Hashable, Mapping, Optional, TypeVar, Union, overload 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" K = TypeVar("K", bound=Hashable) V = TypeVar("V") class IsDictContainingEntries(BaseMatcher[Mapping[K, V]]): def __init__(self, value_matchers) -> None: self.value_matchers = sorted(value_matchers.items()) def _not_a_dictionary( self, item: Mapping[K, V], mismatch_description: Optional[Description] ) -> bool: if mismatch_description: mismatch_description.append_description_of(item).append_text(" is not a mapping object") return False def matches( self, item: Mapping[K, V], mismatch_description: Optional[Description] = None ) -> bool: for key, value_matcher in self.value_matchers: try: if key not in item: if mismatch_description: 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(item, mismatch_description) try: actual_value = item[key] except TypeError: 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(" ") value_matcher.describe_mismatch(actual_value, mismatch_description) return False return True def describe_mismatch(self, item: Mapping[K, V], mismatch_description: Description) -> None: self.matches(item, mismatch_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) 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(", ") self.describe_keyvalue(key, value, description) first = False 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): """Matches if dictionary contains entries satisfying a dictionary of keys and corresponding value matchers. :param matcher_dict: A dictionary mapping keys to associated value matchers, or to expected values for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. Note that the keys must be actual keys, not matchers. Any value argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. Examples:: has_entries({'foo':equal_to(1), 'bar':equal_to(2)}) has_entries({'foo':1, 'bar':2}) ``has_entries`` also accepts a list of keyword arguments: .. function:: has_entries(keyword1=value_matcher1[, keyword2=value_matcher2[, ...]]) :param keyword1: A keyword to look up. :param valueMatcher1: The matcher to satisfy for the value, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. Examples:: has_entries(foo=equal_to(1), bar=equal_to(2)) has_entries(foo=1, bar=2) Finally, ``has_entries`` also accepts a list of alternating keys and their value matchers: .. function:: has_entries(key1, value_matcher1[, ...]) :param key1: A key (not a matcher) to look up. :param valueMatcher1: The matcher to satisfy for the value, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. Examples:: has_entries('foo', equal_to(1), 'bar', equal_to(2)) has_entries('foo', 1, 'bar', 2) """ if len(keys_valuematchers) == 1: try: base_dict = keys_valuematchers[0].copy() 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" ) else: if len(keys_valuematchers) % 2: 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] ) for key, value in kv_args.items(): base_dict[key] = wrap_matcher(value) return IsDictContainingEntries(base_dict) PyHamcrest-2.1.0/src/hamcrest/library/collection/isdict_containingkey.py000066400000000000000000000034451451524142100265450ustar00rootroot00000000000000from 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[Mapping[K, Any]]): def __init__(self, key_matcher: Matcher[K]) -> None: self.key_matcher = key_matcher 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) -> None: description.append_text("a dictionary containing key ").append_description_of( self.key_matcher ) 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. :param key_match: The matcher to satisfy for the key, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher iterates the evaluated dictionary, searching for any key-value entry whose key satisfies the given matcher. If a matching entry is found, ``has_key`` is satisfied. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. Examples:: has_key(equal_to('foo')) has_key('foo') """ return IsDictContainingKey(wrap_matcher(key_match)) PyHamcrest-2.1.0/src/hamcrest/library/collection/isdict_containingvalue.py000066400000000000000000000034531451524142100270700ustar00rootroot00000000000000from 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[Mapping[Any, V]]): def __init__(self, value_matcher: Matcher[V]) -> None: self.value_matcher = value_matcher 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) -> None: description.append_text("a dictionary containing value ").append_description_of( self.value_matcher ) def has_value(value: Union[V, Matcher[V]]) -> Matcher[Mapping[Any, V]]: """Matches if dictionary contains an entry whose value satisfies a given matcher. :param value_match: The matcher to satisfy for the value, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher iterates the evaluated dictionary, searching for any key-value entry whose value satisfies the given matcher. If a matching entry is found, ``has_value`` is satisfied. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. Examples:: has_value(equal_to('bar')) has_value('bar') """ return IsDictContainingValue(wrap_matcher(value)) PyHamcrest-2.1.0/src/hamcrest/library/collection/isin.py000066400000000000000000000017211451524142100233010ustar00rootroot00000000000000from 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[T]): def __init__(self, sequence: Sequence[T]) -> None: self.sequence = sequence def _matches(self, item: T) -> bool: return item in self.sequence def describe_to(self, description: Description) -> None: description.append_text("one of ").append_list("(", ", ", ")", self.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. This matcher invokes the ``in`` membership operator to determine if the evaluated object is a member of the sequence. """ return IsIn(sequence) PyHamcrest-2.1.0/src/hamcrest/library/collection/issequence_containing.py000066400000000000000000000065401451524142100267200ustar00rootroot00000000000000from typing import Sequence, TypeVar, Union, cast from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.core.allof import all_of 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[Sequence[T]]): def __init__(self, element_matcher: Matcher[T]) -> None: self.element_matcher = element_matcher def _matches(self, item: Sequence[T]) -> bool: try: for element in item: if self.element_matcher.matches(element): return True except TypeError: # not a sequence pass return False 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[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 _matches(self, item: Sequence[T]) -> bool: try: return self.matcher.matches(list(item)) except TypeError: return False def describe_mismatch(self, item: Sequence[T], mismatch_description: Description) -> None: self.matcher.describe_mismatch(item, mismatch_description) def describe_to(self, description: Description) -> None: self.matcher.describe_to(description) 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 :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher iterates the evaluated sequence, searching for any element that satisfies a given matcher. If a matching element is found, ``has_item`` is satisfied. If the ``match`` argument is not a matcher, it is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ return IsSequenceContaining(wrap_matcher(match)) 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. :param match1,...: A comma-separated list of matchers. This matcher iterates the given matchers, searching for any elements in the evaluated sequence that satisfy them. If each matcher is satisfied, then ``has_items`` is satisfied. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ matchers = [] for item in items: matchers.append(wrap_matcher(item)) return IsSequenceContainingEvery(*matchers) PyHamcrest-2.1.0/src/hamcrest/library/collection/issequence_containinginanyorder.py000066400000000000000000000074351451524142100310170ustar00rootroot00000000000000from typing import MutableSequence, Optional, Sequence, TypeVar, Union, cast 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 MatchInAnyOrder(object): 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: T) -> bool: return self.isnotsurplus(item) and self.ismatched(item) 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("[", ", ", "]", item) return False 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) return False return True 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) return False class IsSequenceContainingInAnyOrder(BaseMatcher[Sequence[T]]): def __init__(self, matchers: Sequence[Matcher[T]]) -> None: self.matchers = matchers def matches( self, item: Sequence[T], mismatch_description: Optional[Description] = None ) -> bool: try: sequence = list(item) matchsequence = MatchInAnyOrder(self.matchers, mismatch_description) 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( item, mismatch_description ) return False def describe_mismatch(self, item: Sequence[T], mismatch_description: Description) -> None: self.matches(item, mismatch_description) 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: Union[Matcher[T], T]) -> Matcher[Sequence[T]]: """Matches if sequences's elements, in any order, satisfy a given list of matchers. :param match1,...: A comma-separated list of matchers. This matcher iterates the evaluated sequence, seeing if each element satisfies any of the given matchers. The matchers are tried from left to right, and when a satisfied matcher is found, it is no longer a candidate for the remaining elements. If a one-to-one correspondence is established between elements and matchers, ``contains_inanyorder`` is satisfied. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ matchers = [] for item in items: matchers.append(wrap_matcher(item)) return IsSequenceContainingInAnyOrder(matchers) PyHamcrest-2.1.0/src/hamcrest/library/collection/issequence_containinginorder.py000066400000000000000000000073711451524142100303060ustar00rootroot00000000000000import 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" T = TypeVar("T") class MatchingInOrder(object): 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: T) -> bool: return self.isnotsurplus(item) and self.ismatched(item) 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] ) return False return True 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) + ": ") matcher.describe_mismatch(item, self.mismatch_description) return False self.next_match_index += 1 return True 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) return False return True class IsSequenceContainingInOrder(BaseMatcher[Sequence[T]]): def __init__(self, matchers: Sequence[Matcher[T]]) -> None: self.matchers = matchers def matches( self, item: Sequence[T], mismatch_description: Optional[Description] = None ) -> bool: try: matchsequence = MatchingInOrder(self.matchers, mismatch_description) for element in item: if not matchsequence.matches(element): return False return matchsequence.isfinished() except TypeError: if mismatch_description: super(IsSequenceContainingInOrder, self).describe_mismatch( item, mismatch_description ) return False def describe_mismatch(self, item: Sequence[T], mismatch_description: Description) -> None: self.matches(item, mismatch_description) def describe_to(self, description: Description) -> None: description.append_text("a sequence containing ").append_list("[", ", ", "]", self.matchers) 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. This matcher iterates the evaluated sequence and a given list of matchers, seeing if each element satisfies its corresponding matcher. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ matchers = [] for item in items: matchers.append(wrap_matcher(item)) return IsSequenceContainingInOrder(matchers) 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) PyHamcrest-2.1.0/src/hamcrest/library/collection/issequence_onlycontaining.py000066400000000000000000000034611451524142100276210ustar00rootroot00000000000000from typing import Sequence, TypeVar, Union from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.core.anyof import any_of 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[Sequence[T]]): def __init__(self, matcher: Matcher[T]) -> None: self.matcher = matcher def _matches(self, item: Sequence[T]) -> bool: try: sequence = list(item) if len(sequence) == 0: return False for element in sequence: if not self.matcher.matches(element): return False return True except TypeError: return False def describe_to(self, description: Description) -> None: description.append_text("a sequence containing items matching ").append_description_of( self.matcher ) 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. This matcher iterates the evaluated sequence, confirming whether each element satisfies any of the given matchers. Example:: only_contains(less_than(4)) will match ``[3,1,2]``. Any argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. """ matchers = [] for item in items: matchers.append(wrap_matcher(item)) return IsSequenceOnlyContaining(any_of(*matchers)) PyHamcrest-2.1.0/src/hamcrest/library/integration/000077500000000000000000000000001451524142100221545ustar00rootroot00000000000000PyHamcrest-2.1.0/src/hamcrest/library/integration/__init__.py000066400000000000000000000003651451524142100242710ustar00rootroot00000000000000"""Utilities for integrating Hamcrest with other libraries.""" from .match_equality import match_equality __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" __all__ = ["match_equality"] PyHamcrest-2.1.0/src/hamcrest/library/integration/match_equality.py000066400000000000000000000024531451524142100255430ustar00rootroot00000000000000from 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" __license__ = "BSD, see License.txt" __unittest = True class EqualityWrapper(object): def __init__(self, matcher: Matcher) -> None: self.matcher = matcher def __eq__(self, obj: Any) -> bool: return self.matcher.matches(obj) def __str__(self) -> str: return repr(self) def __repr__(self) -> str: return tostring(self.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 are not Hamcrest-aware. They might use the equality operator:: assert match_equality(matcher) == object Or they might provide a method that uses equality for its test:: library.method_that_tests_eq(match_equality(matcher)) One concrete example is integrating with the ``assert_called_with`` methods in Michael Foord's `mock `_ library. """ return EqualityWrapper(wrap_matcher(matcher)) PyHamcrest-2.1.0/src/hamcrest/library/number/000077500000000000000000000000001451524142100211215ustar00rootroot00000000000000PyHamcrest-2.1.0/src/hamcrest/library/number/__init__.py000066400000000000000000000006761451524142100232430ustar00rootroot00000000000000"""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, ) __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", ] PyHamcrest-2.1.0/src/hamcrest/library/number/iscloseto.py000066400000000000000000000052731451524142100235060ustar00rootroot00000000000000from 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: Any) -> bool: """Confirm that 'value' can be treated numerically; duck-test accordingly""" if isinstance(value, (float, complex, int)): return True try: _ = (fabs(value) + 0 - 0) * 1 return True except ArithmeticError: return True except Exception: return False class IsCloseTo(BaseMatcher[Number]): def __init__(self, value: Number, delta: Number) -> None: if not isnumeric(value): raise TypeError("IsCloseTo value must be numeric") if not isnumeric(delta): raise TypeError("IsCloseTo delta must be numeric") self.value = value self.delta = delta def _matches(self, item: Number) -> bool: if not isnumeric(item): return False return self._diff(item) <= self.delta 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 = 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]: ... @overload def close_to(value: Decimal, delta: Decimal) -> Matcher[Decimal]: ... def close_to(value, delta): """Matches if object is a number close to a given value, within a given delta. :param value: The value to compare against as the expected value. :param delta: The maximum delta between the values for which the numbers are considered close. This matcher compares the evaluated object against ``value`` to see if the difference is within a positive ``delta``. Example:: close_to(3.0, 0.25) """ return IsCloseTo(value, delta) PyHamcrest-2.1.0/src/hamcrest/library/number/ordering_comparison.py000066400000000000000000000037271451524142100255470ustar00rootroot00000000000000import 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[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: Any) -> bool: try: return self.comparison_function(item, self.value) except TypeError: return False 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: 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") 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") 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") 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") PyHamcrest-2.1.0/src/hamcrest/library/object/000077500000000000000000000000001451524142100210775ustar00rootroot00000000000000PyHamcrest-2.1.0/src/hamcrest/library/object/__init__.py000066400000000000000000000005651451524142100232160ustar00rootroot00000000000000"""Matchers that inspect objects and classes.""" from .haslength import has_length 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", ] PyHamcrest-2.1.0/src/hamcrest/library/object/haslength.py000066400000000000000000000035611451524142100234330ustar00rootroot00000000000000from 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[Sized]): def __init__(self, len_matcher: Matcher[int]) -> None: self.len_matcher = len_matcher 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: 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)) 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: 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 :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher invokes the :py:func:`len` function on the evaluated object to get its length, passing the result to a given matcher for evaluation. If the ``match`` argument is not a matcher, it is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for :equality. Examples:: has_length(greater_than(6)) has_length(5) """ return HasLength(wrap_matcher(match)) PyHamcrest-2.1.0/src/hamcrest/library/object/hasproperty.py000066400000000000000000000157511451524142100240420ustar00rootroot00000000000000from 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[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, item: object) -> bool: if item is None: return False if not hasattr(item, self.property_name): return False value = getattr(item, self.property_name) return self.value_matcher.matches(value) 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: object, mismatch_description: Description) -> None: if item is 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") return 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) def __str__(self): d = StringDescription() self.describe_to(d) return str(d) 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. :param name: The name of the property. :param match: Optional matcher to satisfy. This matcher determines if the evaluated object has a property with a given name. If no such property is found, ``has_property`` is not satisfied. If the property is found, its value is passed to a given matcher for evaluation. If the ``match`` argument is not a matcher, it is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. If the ``match`` argument is not provided, the :py:func:`~hamcrest.core.core.isanything.anything` matcher is used so that ``has_property`` is satisfied if a matching property is found. Examples:: has_property('name', starts_with('J')) has_property('name', 'Jon') has_property('name') """ if match is None: match = anything() 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. :param matcher_dict: A dictionary mapping keys to associated value matchers, or to expected values for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. Note that the keys must be actual keys, not matchers. Any value argument that is not a matcher is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. Examples:: has_properties({'foo':equal_to(1), 'bar':equal_to(2)}) has_properties({'foo':1, 'bar':2}) ``has_properties`` also accepts a list of keyword arguments: .. function:: has_properties(keyword1=value_matcher1[, keyword2=value_matcher2[, ...]]) :param keyword1: A keyword to look up. :param valueMatcher1: The matcher to satisfy for the value, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. Examples:: has_properties(foo=equal_to(1), bar=equal_to(2)) has_properties(foo=1, bar=2) Finally, ``has_properties`` also accepts a list of alternating keys and their value matchers: .. function:: has_properties(key1, value_matcher1[, ...]) :param key1: A key (not a matcher) to look up. :param valueMatcher1: The matcher to satisfy for the value, or an expected value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching. Examples:: has_properties('foo', equal_to(1), 'bar', equal_to(2)) has_properties('foo', 1, 'bar', 2) """ if len(keys_valuematchers) == 1: try: base_dict = keys_valuematchers[0].copy() 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" ) else: if len(keys_valuematchers) % 2: 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] ) 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 ") for i, (property_name, property_value_matcher) in enumerate(sorted(base_dict.items())): 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 ") 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) PyHamcrest-2.1.0/src/hamcrest/library/object/hasstring.py000066400000000000000000000025631451524142100234610ustar00rootroot00000000000000from 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[object]): def __init__(self, str_matcher: Matcher[str]) -> None: self.str_matcher = str_matcher def _matches(self, item: object) -> bool: return self.str_matcher.matches(str(item)) def describe_to(self, description: Description) -> None: description.append_text("an object with str ").append_description_of(self.str_matcher) 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 :py:func:`~hamcrest.core.core.isequal.equal_to` matching. This matcher invokes the :py:func:`str` function on the evaluated object to get its length, passing the result to a given matcher for evaluation. If the ``match`` argument is not a matcher, it is implicitly wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for equality. Examples:: has_string(starts_with('foo')) has_string('bar') """ return HasString(wrap_matcher(match)) PyHamcrest-2.1.0/src/hamcrest/library/text/000077500000000000000000000000001451524142100206155ustar00rootroot00000000000000PyHamcrest-2.1.0/src/hamcrest/library/text/__init__.py000066400000000000000000000012771451524142100227350ustar00rootroot00000000000000"""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 .stringmatches import matches_regexp 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", ] PyHamcrest-2.1.0/src/hamcrest/library/text/isequal_ignoring_case.py000066400000000000000000000025171451524142100255260ustar00rootroot00000000000000from 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 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: str) -> bool: if not isinstance(item, str): return False return self.lowered_string == item.lower() def describe_to(self, description: Description) -> None: description.append_description_of(self.original_string).append_text(" ignoring case") def equal_to_ignoring_case(string: str) -> Matcher[str]: """Matches if object is a string equal to a given string, ignoring case differences. :param string: The string to compare against as the expected value. This matcher first checks whether the evaluated object is a string. If so, it compares it with ``string``, ignoring differences of case. Example:: equal_to_ignoring_case("hello world") will match "heLLo WorlD". """ return IsEqualIgnoringCase(string) PyHamcrest-2.1.0/src/hamcrest/library/text/isequal_ignoring_whitespace.py000066400000000000000000000033601451524142100267440ustar00rootroot00000000000000from 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" def stripspace(string: str) -> str: result = "" last_was_space = True for character in string: if character.isspace(): if not last_was_space: result += " " last_was_space = True else: result += character last_was_space = False return result.strip() 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: str) -> bool: if not isinstance(item, str): return False return self.stripped_string == stripspace(item) def describe_to(self, description: Description) -> None: description.append_description_of(self.original_string).append_text(" ignoring whitespace") def equal_to_ignoring_whitespace(string: str) -> Matcher[str]: """Matches if object is a string equal to a given string, ignoring differences in whitespace. :param string: The string to compare against as the expected value. This matcher first checks whether the evaluated object is a string. If so, it compares it with ``string``, ignoring differences in runs of whitespace. Example:: equal_to_ignoring_whitespace("hello world") will match ``"hello world"``. """ return IsEqualIgnoringWhiteSpace(string) PyHamcrest-2.1.0/src/hamcrest/library/text/stringcontains.py000066400000000000000000000020141451524142100242310ustar00rootroot00000000000000from 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" class StringContains(SubstringMatcher): def __init__(self, substring) -> None: super(StringContains, self).__init__(substring) def _matches(self, item: str) -> bool: if not hasmethod(item, "find"): return False return item.find(self.substring) >= 0 def relationship(self): return "containing" def contains_string(substring: str) -> Matcher[str]: """Matches if object is a string containing a given string. :param string: The string to search for. This matcher first checks whether the evaluated object is a string. If so, it checks whether it contains ``string``. Example:: contains_string("def") will match "abcdefg". """ return StringContains(substring) PyHamcrest-2.1.0/src/hamcrest/library/text/stringcontainsinorder.py000066400000000000000000000033561451524142100256260ustar00rootroot00000000000000from 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 __author__ = "Romilly Cocking" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class StringContainsInOrder(BaseMatcher[str]): def __init__(self, *substrings) -> None: for substring in substrings: if not isinstance(substring, str): raise TypeError(self.__class__.__name__ + " requires string arguments") self.substrings = substrings def _matches(self, item: str) -> bool: if not hasmethod(item, "find"): return False from_index = 0 for substring in self.substrings: from_index = item.find(substring, from_index) if from_index == -1: return False return True def describe_to(self, description: Description) -> None: description.append_list("a string containing ", ", ", " in order", self.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. :param string1,...: A comma-separated list of strings. This matcher first checks whether the evaluated object is a string. If so, it checks whether it contains a given list of strings, in relative order to each other. The searches are performed starting from the beginning of the evaluated string. Example:: string_contains_in_order("bc", "fg", "jkl") will match "abcdefghijklm". """ return StringContainsInOrder(*substrings) PyHamcrest-2.1.0/src/hamcrest/library/text/stringendswith.py000066400000000000000000000020471451524142100242460ustar00rootroot00000000000000from 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" class StringEndsWith(SubstringMatcher): def __init__(self, substring) -> None: super(StringEndsWith, self).__init__(substring) def _matches(self, item: str) -> bool: if not hasmethod(item, "endswith"): return False return item.endswith(self.substring) def relationship(self): return "ending with" 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. This matcher first checks whether the evaluated object is a string. If so, it checks if ``string`` matches the ending characters of the evaluated object. Example:: ends_with("bar") will match "foobar". """ return StringEndsWith(string) PyHamcrest-2.1.0/src/hamcrest/library/text/stringmatches.py000066400000000000000000000023211451524142100240400ustar00rootroot00000000000000import re from typing import Pattern, Union from hamcrest.core.base_matcher import BaseMatcher 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[str]): def __init__(self, pattern) -> None: self.pattern = pattern def describe_to(self, description: Description) -> None: description.append_text("a string matching '").append_text( self.pattern.pattern ).append_text("'") def _matches(self, item: str) -> bool: return self.pattern.search(item) is not None def matches_regexp(pattern: Union[str, Pattern[str]]) -> Matcher[str]: """Matches if object is a string containing a match for a given regular expression. :param pattern: The regular expression to search for. This matcher first checks whether the evaluated object is a string. If so, it checks if the regular expression ``pattern`` matches anywhere within the evaluated object. """ if isinstance(pattern, str): pattern = re.compile(pattern) return StringMatchesPattern(pattern) PyHamcrest-2.1.0/src/hamcrest/library/text/stringstartswith.py000066400000000000000000000021021451524142100246250ustar00rootroot00000000000000from 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" class StringStartsWith(SubstringMatcher): def __init__(self, substring) -> None: super(StringStartsWith, self).__init__(substring) def _matches(self, item: str) -> bool: if not hasmethod(item, "startswith"): return False return item.startswith(self.substring) def relationship(self): return "starting with" 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. This matcher first checks whether the evaluated object is a string. If so, it checks if ``string`` matches the beginning characters of the evaluated object. Example:: starts_with("foo") will match "foobar". """ return StringStartsWith(substring) PyHamcrest-2.1.0/src/hamcrest/library/text/substringmatcher.py000066400000000000000000000014221451524142100245520ustar00rootroot00000000000000from abc import ABCMeta, abstractmethod from hamcrest.core.base_matcher import BaseMatcher from hamcrest.core.description import Description __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" 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) -> None: description.append_text("a string ").append_text(self.relationship()).append_text( " " ).append_description_of(self.substring) @abstractmethod def relationship(self): ... PyHamcrest-2.1.0/src/hamcrest/py.typed000066400000000000000000000000001451524142100176520ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/000077500000000000000000000000001451524142100147325ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/hamcrest_unit_test/000077500000000000000000000000001451524142100206365ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/hamcrest_unit_test/__init__.py000066400000000000000000000000021451524142100227370ustar00rootroot00000000000000# PyHamcrest-2.1.0/tests/hamcrest_unit_test/assert_that_test.py000066400000000000000000000043431451524142100245740ustar00rootroot00000000000000# encoding: utf-8 import unittest import warnings from hamcrest.core.assert_that import assert_that from hamcrest.core.core.isequal import equal_to def u(x): return x __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class AssertThatTest(unittest.TestCase): def testShouldBeSilentOnSuccessfulMatch(self): assert_that(1, equal_to(1)) def testAssertionErrorShouldDescribeExpectedAndActual(self): expected = "EXPECTED" actual = "ACTUAL" expectedMessage = "\nExpected: 'EXPECTED'\n but: was 'ACTUAL'\n" with self.assertRaises(AssertionError) as e: assert_that(actual, equal_to(expected)) self.assertEqual(expectedMessage, str(e.exception)) def testAssertionErrorShouldIncludeOptionalReason(self): expected = "EXPECTED" actual = "ACTUAL" expectedMessage = "REASON\nExpected: 'EXPECTED'\n but: was 'ACTUAL'\n" with self.assertRaises(AssertionError) as e: assert_that(actual, equal_to(expected), "REASON") self.assertEqual(expectedMessage, str(e.exception)) def testAssertionUnicodeEncodesProperly(self): expected = "EXPECTED" actual = u("\xdcnic\N{Latin Small Letter O with diaeresis}de") with self.assertRaises(AssertionError): assert_that(actual, equal_to(expected), "REASON") def testCanTestBoolDirectly(self): assert_that(True, "should accept True") with self.assertRaises(AssertionError) as e: assert_that(False, "FAILURE REASON") self.assertEqual("FAILURE REASON", str(e.exception)) def testCanTestBoolDirectlyWithoutReason(self): assert_that(True) with self.assertRaises(AssertionError) as e: assert_that(False) self.assertEqual("Assertion failed", str(e.exception)) def testWarnsForMatcherAsArg1(self): assert_that(True) with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") assert_that(equal_to(1)) self.assertEqual(len(w), 1) self.assertTrue("arg1 should be boolean" in str(w[-1].message)) if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/base_description_test.py000066400000000000000000000034711451524142100255710ustar00rootroot00000000000000# coding: utf-8 import platform from unittest.mock import sentinel import pytest from hamcrest.core.base_description import BaseDescription from hamcrest.core.helpers.ismock import MOCKTYPES from hamcrest.core.selfdescribing import SelfDescribing __author__ = "Chris Rose" __copyright__ = "Copyright 2015 hamcrest.org" __license__ = "BSD, see License.txt" class Collector(BaseDescription): def __init__(self): self.appended = [] def append(self, obj): self.appended.append(obj) class Described(SelfDescribing): def describe_to(self, desc): desc.append("described") @pytest.fixture def desc(): return Collector() def test_append_text_delegates(desc): desc.append_text(sentinel.Text) assert desc.appended == [sentinel.Text] @pytest.mark.parametrize( "described, appended", ( (Described(), "described"), ("unicode-py3", "'unicode-py3'"), (b"bytes-py3", ""), pytest.param( "\U0001F4A9", "'{0}'".format("\U0001F4A9"), marks=pytest.mark.skipif( platform.python_implementation() == "PyPy", reason="Inexplicable failure on PyPy. Not super important, I hope!", ), ), ), ) def test_append_description_types(desc, described, appended): desc.append_description_of(described) assert "".join(desc.appended) == appended @pytest.mark.parametrize("char, rep", (("'", r"'"), ("\n", r"\n"), ("\r", r"\r"), ("\t", r"\t"))) def test_string_in_python_syntax(desc, char, rep): desc.append_string_in_python_syntax(char) assert "".join(desc.appended) == "'{0}'".format(rep) @pytest.mark.parametrize("mock", MOCKTYPES) def test_describe_mock(desc, mock): m = mock() desc.append_description_of(m) assert "".join(desc.appended) == str(m) PyHamcrest-2.1.0/tests/hamcrest_unit_test/base_matcher_test.py000066400000000000000000000031611451524142100246650ustar00rootroot00000000000000if __name__ == "__main__": import sys sys.path.insert(0, "..") import unittest from hamcrest.core.base_matcher import BaseMatcher from hamcrest_unit_test.matcher_test import assert_match_description, assert_mismatch_description __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class FailingBaseMatcher(BaseMatcher): def describe_to(self, description): description.append_text("SOME DESCRIPTION") def _matches(self, item): return False class PassingBaseMatcher(BaseMatcher): def _matches(self, item): return True class BaseMatcherTest(unittest.TestCase): def testStrFunctionShouldDescribeMatcher(self): matcher = FailingBaseMatcher() self.assertEqual("SOME DESCRIPTION", str(matcher)) def testMismatchDescriptionShouldDescribeItem(self): assert_mismatch_description("was <99>", FailingBaseMatcher(), 99) def testMatchDescriptionShouldDescribeItem(self): assert_match_description("was <99>", PassingBaseMatcher(), 99) def testMatcherReprShouldDescribeMatcher(self): assert repr(FailingBaseMatcher()) == "" def testMatcherReprShouldTruncateLongDescription(self): class LongDescriptionMatcher(BaseMatcher): def describe_to(self, description): description.append_text("1234 " * 13) assert ( repr(LongDescriptionMatcher()) == "" ) if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/collection/000077500000000000000000000000001451524142100227715ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/hamcrest_unit_test/collection/__init__.py000066400000000000000000000000001451524142100250700ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/hamcrest_unit_test/collection/is_empty_test.py000066400000000000000000000032551451524142100262400ustar00rootroot00000000000000from hamcrest.library.collection.is_empty import empty from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Chris Rose" __copyright__ = "Copyright 2012 hamcrest.org" __license__ = "BSD, see License.txt" class LengthHaver(object): def __init__(self, len_): self._len = len_ def __len__(self): return self._len class EmptyCollectionTest(MatcherTest): def testReturnsTrueForEmptyStandardCollections(self): matcher = empty() self.assert_matches("empty tuple", matcher, ()) self.assert_matches("empty list", matcher, []) self.assert_matches("empty dictionary", matcher, {}) def testReturnsTrueForEmptyCollectionLike(self): matcher = empty() self.assert_matches("empty protocol object", matcher, LengthHaver(0)) def testReturnsFalseForNonEmptyStandardCollections(self): matcher = empty() self.assert_does_not_match("non-empty tuple", matcher, (1,)) self.assert_does_not_match("non-empty list", matcher, [1]) self.assert_does_not_match("empty dictionary", matcher, {1: 2}) def testReturnsFalseForNonEmptyCollectionLike(self): matcher = empty() self.assert_does_not_match("non-empty protocol object", matcher, LengthHaver(1)) def testHasReadableDescription(self): self.assert_description("an empty collection", empty()) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(empty(), []) def testDescribeMismatch(self): self.assert_mismatch_description("has 3 item(s)", empty(), [1, 2, 3]) self.assert_mismatch_description("does not support length", empty(), 1) PyHamcrest-2.1.0/tests/hamcrest_unit_test/collection/isdict_containing_test.py000066400000000000000000000047161451524142100301020ustar00rootroot00000000000000import unittest from hamcrest import starts_with from hamcrest.core.core.isequal import equal_to from hamcrest.library.collection.isdict_containing import has_entry from hamcrest_unit_test.matcher_test import ( MatcherTest, assert_match_description, assert_mismatch_description, ) from .quasidict import QuasiDictionary __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsDictContainingTest(MatcherTest): def testMatchesDictionaryContainingMatchingKeyAndValue(self): dict = {"a": 1, "b": 2} self.assert_matches("has a:1", has_entry(equal_to("a"), equal_to(1)), dict) self.assert_matches("has b:2", has_entry(equal_to("b"), equal_to(2)), dict) self.assert_does_not_match("no c:3", has_entry(equal_to("c"), equal_to(3)), dict) def testProvidesConvenientShortcutForMatchingWithEqualTo(self): dict = {"a": 1, "b": 2} self.assert_matches("has a:1", has_entry("a", equal_to(1)), dict) self.assert_matches("has b:2", has_entry(equal_to("b"), 2), dict) self.assert_does_not_match("no c:3", has_entry("c", 3), dict) def testMatchesAnyConformingDictionary(self): self.assert_matches("quasi-dictionary", has_entry(1, "1"), QuasiDictionary()) self.assert_does_not_match("non-dictionary", has_entry(1, "1"), object()) def testHasReadableDescription(self): self.assert_description("a dictionary containing ['a': <1>]", has_entry("a", 1)) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(has_entry("a", 1), {"a": 1}) def testMismatchDescriptionShowsActualArgument(self): self.assert_mismatch_description("was 'bad'", has_entry("a", 1), "bad") def testDescribeMismatch(self): self.assert_describe_mismatch("was 'bad'", has_entry("a", 1), "bad") def test_describe_single_matching_key_mismatching_value(self): assert_mismatch_description("value for 'a' was <2>", has_entry("a", 1), {"a": 2}) assert_mismatch_description( "value for 'aa' was <2>", has_entry(starts_with("a"), 1), {"aa": 2} ) assert_mismatch_description( "was <{'ab': 2, 'ac': 3}>", has_entry(starts_with("a"), 1), {"ab": 2, "ac": 3} ) def test_describe_match(self): assert_match_description("value for 'a' was <1>", has_entry("a", 1), {"a": 1, "b": 2}) if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/collection/isdict_containingentries_test.py000066400000000000000000000116461451524142100314740ustar00rootroot00000000000000if __name__ == "__main__": import sys sys.path.insert(0, "..") sys.path.insert(0, "../..") import unittest from hamcrest.core.core.isequal import equal_to from hamcrest.library.collection.isdict_containingentries import has_entries from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsDictContainingEntriesTest(MatcherTest): def testMatcherCreationRequiresEvenNumberOfPositionalArgs(self): self.assertRaises(ValueError, has_entries, "a", "b", "c") def testDoesNotMatchNonDictionary(self): self.assert_does_not_match("non-dictionary", has_entries("a", equal_to(1)), object()) def testMatchesDictLike(self): class DictLike(object): def __getitem__(self, key): return "value: " + str(key) def __contains__(self, key): return True self.assert_matches( "matches a dictionary-like object", has_entries("a", equal_to("value: a")), DictLike() ) def testMatchesUsingSingleDictionaryArgument(self): target = {"a": 1, "b": 2, "c": 3} self.assert_matches("has a & b", has_entries({"a": equal_to(1), "b": equal_to(2)}), target) self.assert_matches("has c & a", has_entries({"c": equal_to(3), "a": equal_to(1)}), target) self.assert_does_not_match( "no d:3", has_entries({"b": equal_to(2), "d": equal_to(3)}), target ) def testMatcheSingleDictionaryArgumentWithImplicitEqualTo(self): target = {"a": 1, "b": 2, "c": 3} self.assert_matches("has a & b", has_entries({"a": 1, "b": 2}), target) self.assert_matches("has c & a", has_entries({"c": 3, "a": 1}), target) self.assert_does_not_match("no d:3", has_entries({"b": 2, "d": 3}), target) def testMatchesUsingKwargs(self): target = {"a": 1, "b": 2, "c": 3} self.assert_matches("has a & b", has_entries(a=equal_to(1), b=equal_to(2)), target) self.assert_matches("has c & a", has_entries(c=equal_to(3), a=equal_to(1)), target) self.assert_does_not_match("no d:3", has_entries(b=equal_to(2), d=equal_to(3)), target) def testMatchesKwargsWithImplicitEqualTo(self): target = {"a": 1, "b": 2, "c": 3} self.assert_matches("has a & b", has_entries(a=1, b=2), target) self.assert_matches("has c & a", has_entries(c=3, a=1), target) self.assert_does_not_match("no d:3", has_entries(b=2, d=3), target) def testMatchesDictionaryContainingSingleKeyWithMatchingValue(self): target = {"a": 1, "b": 2} self.assert_matches("has a:1", has_entries("a", equal_to(1)), target) self.assert_matches("has b:2", has_entries("b", equal_to(2)), target) self.assert_does_not_match("no b:3", has_entries("b", equal_to(3)), target) self.assert_does_not_match("no c:2", has_entries("c", equal_to(2)), target) def testMatchesDictionaryContainingMultipleKeysWithMatchingValues(self): target = {"a": 1, "b": 2, "c": 3} self.assert_matches("has a & b", has_entries("a", equal_to(1), "b", equal_to(2)), target) self.assert_matches("has c & a", has_entries("c", equal_to(3), "a", equal_to(1)), target) self.assert_does_not_match( "no d:3", has_entries("b", equal_to(3), "d", equal_to(3)), target ) def testProvidesConvenientShortcutForMatchingWithEqualTo(self): target = {"a": 1, "b": 2, "c": 3} self.assert_matches("has a & b", has_entries("a", 1, "b", 2), target) self.assert_matches("has c & a", has_entries("c", 3, "a", 1), target) self.assert_does_not_match("no d:4", has_entries("b", 3, "d", 4), target) def testHasReadableDescription(self): self.assert_description( "a dictionary containing {'a': <1>, 'b': <2>}", has_entries("a", 1, "b", 2) ) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(has_entries("a", 1), {"a": 1}) def testMismatchDescriptionOfNonDictionaryShowsActualArgument(self): self.assert_mismatch_description( "'bad' is not a mapping object", has_entries("a", 1), "bad" ) def testMismatchDescriptionOfDictionaryWithNonMatchingValue(self): self.assert_mismatch_description("value for 'a' was <2>", has_entries("a", 1), {"a": 2}) def testDescribeMismatchOfNonDictionaryShowsActualArgument(self): self.assert_describe_mismatch("'bad' is not a mapping object", has_entries("a", 1), "bad") def testDescribeMismatchOfDictionaryWithoutKey(self): d = {"a": 1, "c": 3} self.assert_describe_mismatch("no 'b' key in <%s>" % (d,), has_entries("a", 1, "b", 2), d) def testDescribeMismatchOfDictionaryWithNonMatchingValue(self): self.assert_describe_mismatch("value for 'a' was <2>", has_entries("a", 1), {"a": 2}) if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/collection/isdict_containingkey_test.py000066400000000000000000000037011451524142100306040ustar00rootroot00000000000000import unittest from hamcrest.core.core.isequal import equal_to from hamcrest.library.collection.isdict_containingkey import has_key from hamcrest_unit_test.matcher_test import MatcherTest from .quasidict import QuasiDictionary __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsDictContainingKeyTest(MatcherTest): def testMatchesSingletonDictionaryContainingKey(self): dict = {"a": 1} self.assert_matches("same single key", has_key(equal_to("a")), dict) def testMatchesDictionaryContainingKey(self): dict = {"a": 1, "b": 2, "c": 3} self.assert_matches("Matches a", has_key(equal_to("a")), dict) self.assert_matches("Matches c", has_key(equal_to("c")), dict) def testProvidesConvenientShortcutForMatchingWithEqualTo(self): dict = {"a": 1, "b": 2, "c": 3} self.assert_matches("Matches c", has_key("c"), dict) def testDoesNotMatchEmptyDictionary(self): self.assert_does_not_match("empty", has_key("foo"), {}) def testDoesNotMatchDictionaryMissingKey(self): dict = {"a": 1, "b": 2, "c": 3} self.assert_does_not_match("no matching key", has_key("d"), dict) def testMatchesAnyConformingDictionary(self): self.assert_matches("quasi-dictionary", has_key(1), QuasiDictionary()) self.assert_does_not_match("non-dictionary", has_key(1), object()) def testHasReadableDescription(self): self.assert_description("a dictionary containing key 'a'", has_key("a")) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(has_key("a"), {"a": 1}) def testMismatchDescriptionShowsActualArgument(self): self.assert_mismatch_description("was 'bad'", has_key("a"), "bad") def testDescribeMismatch(self): self.assert_describe_mismatch("was 'bad'", has_key("a"), "bad") if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/collection/isdict_containingvalue_test.py000066400000000000000000000037331451524142100311350ustar00rootroot00000000000000import unittest from hamcrest.core.core.isequal import equal_to from hamcrest.library.collection.isdict_containingvalue import has_value from hamcrest_unit_test.matcher_test import MatcherTest from .quasidict import QuasiDictionary __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsDictContainingValueTest(MatcherTest): def testMatchesSingletonDictionaryContainingValue(self): dict = {"a": 1} self.assert_matches("same single value", has_value(equal_to(1)), dict) def testMatchesDictionaryContainingValue(self): dict = {"a": 1, "b": 2, "c": 3} self.assert_matches("Matches 1", has_value(equal_to(1)), dict) self.assert_matches("Matches 3", has_value(equal_to(3)), dict) def testProvidesConvenientShortcutForMatchingWithEqualTo(self): dict = {"a": 1, "b": 2, "c": 3} self.assert_matches("Matches 3", has_value(3), dict) def testDoesNotMatchEmptyDictionary(self): self.assert_does_not_match("empty", has_value(1), {}) def testDoesNotMatchDictionaryMissingValue(self): dict = {"a": 1, "b": 2, "c": 3} self.assert_does_not_match("no matching value", has_value(4), dict) def testMatchesAnyConformingDictionary(self): self.assert_matches("quasi-dictionary", has_value("1"), QuasiDictionary()) self.assert_does_not_match("non-dictionary", has_value("1"), object()) def testHasReadableDescription(self): self.assert_description("a dictionary containing value 'a'", has_value("a")) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(has_value(1), {"a": 1}) def testMismatchDescriptionShowsActualArgument(self): self.assert_mismatch_description("was 'bad'", has_value(1), "bad") def testDescribeMismatch(self): self.assert_describe_mismatch("was 'bad'", has_value(1), "bad") if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/collection/isin_test.py000066400000000000000000000026441451524142100253520ustar00rootroot00000000000000import unittest from hamcrest.library.collection.isin import is_in from hamcrest_unit_test.matcher_test import MatcherTest from .sequencemixin import GeneratorForm, SequenceForm __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" sequence = ("a", "b", "c") class IsInTestBase(object): def testReturnsTrueIfArgumentIsInSequence(self): matcher = is_in(self._sequence(*sequence)) self.assert_matches("has a", matcher, "a") self.assert_matches("has b", matcher, "b") self.assert_matches("has c", matcher, "c") self.assert_does_not_match("no d", matcher, "d") def testHasReadableDescription(self): self.assert_description("one of ('a', 'b', 'c')", is_in(self._sequence(*sequence))) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(is_in(self._sequence(*sequence)), "a") def testMismatchDescriptionShowsActualArgument(self): self.assert_mismatch_description("was 'bad'", is_in(self._sequence(*sequence)), "bad") def testDescribeMismatch(self): self.assert_describe_mismatch("was 'bad'", is_in(self._sequence(*sequence)), "bad") class IsInConcreteSequenceTest(MatcherTest, IsInTestBase, SequenceForm): pass class IsInGeneratorTest(MatcherTest, IsInTestBase, GeneratorForm): pass if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/collection/issequence_containing_test.py000066400000000000000000000103241451524142100307570ustar00rootroot00000000000000import unittest from hamcrest.core.core.isequal import equal_to from hamcrest.library.collection.issequence_containing import has_item, has_items from hamcrest_unit_test.matcher_test import MatcherTest from .quasisequence import QuasiSequence from .sequencemixin import GeneratorForm, SequenceForm __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsSequenceContainingTestBase(object): def testMatchesASequenceThatContainsAnElementMatchingTheGivenMatcher(self): self.assert_matches( "sequence contains 'a'", has_item(equal_to("a")), self._sequence("a", "b", "c") ) def testNoMatchIfSequenceDoesntContainAnElementMatchingTheGivenMatcher(self): self.assert_does_not_match( "sequence without 'a'", has_item(equal_to("a")), self._sequence("b", "c") ) self.assert_does_not_match("empty", has_item(equal_to("a")), []) def testProvidesConvenientShortcutForMatchingWithEqualTo(self): self.assert_matches("sequence contains 'a'", has_item("a"), self._sequence("a", "b", "c")) self.assert_does_not_match("sequence without 'a'", has_item("a"), self._sequence("b", "c")) def testMatchesAnyConformingSequence(self): self.assert_matches("quasi-sequence", has_item(1), QuasiSequence()) self.assert_does_not_match("non-sequence", has_item(1), object()) def testHasAReadableDescription(self): self.assert_description("a sequence containing 'a'", has_item("a")) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(has_item("a"), self._sequence("a", "b")) def testMismatchDescriptionShowsActualArgument(self): self.assert_mismatch_description("was <42>", has_item("a"), 42) def testDescribeMismatch(self): self.assert_describe_mismatch("was <42>", has_item("a"), 42) class IsConcreteSequenceContaining(MatcherTest, SequenceForm, IsSequenceContainingTestBase): pass class IsGeneratorContaining(MatcherTest, GeneratorForm, IsSequenceContainingTestBase): pass class IsSequenceContainingItemsTestBase(object): def testShouldMatchCollectionContainingAllItems(self): self.assert_matches( "contains all items", has_items(equal_to("a"), equal_to("b"), equal_to("c")), self._sequence("a", "b", "c"), ) def testProvidesConvenientShortcutForMatchingWithEqualTo(self): self.assert_matches( "Values automatically wrapped with equal_to", has_items("a", "b", "c"), self._sequence("a", "b", "c"), ) def testShouldMatchCollectionContainingAllItemsInDifferentOrder(self): self.assert_matches( "all items in different order", has_items("a", "b", "c"), self._sequence("c", "b", "a") ) def testShouldMatchCollectionContainingAllItemsPlusExtras(self): self.assert_matches( "all items plus extras", has_items("a", "b", "c"), self._sequence("e", "c", "b", "a", "d"), ) def testNoMatchIfCollectionDoesntSatisfyAllMatchers(self): self.assert_does_not_match( "missing 'a'", has_items("a", "b", "c"), self._sequence("e", "c", "b", "d") ) def testHasAReadableDescription(self): self.assert_description( "(a sequence containing 'a' and a sequence containing 'b')", has_items("a", "b") ) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(has_items("a", "b"), self._sequence("a", "b")) def testMismatchDescriptionShowsFirstUnmetMatcherAndActualArgument(self): self.assert_mismatch_description( "a sequence containing 'a' was <42>", has_items("a", "b"), 42 ) def testDescribeMismatch(self): self.assert_describe_mismatch("a sequence containing 'a' was <42>", has_items("a", "b"), 42) class IsConcreteSequenceContainingItemsTest( MatcherTest, IsSequenceContainingItemsTestBase, SequenceForm ): pass class IsGeneratorSequenceContainingItemsTest( MatcherTest, IsSequenceContainingItemsTestBase, GeneratorForm ): pass if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/collection/issequence_containinginanyorder_test.py000066400000000000000000000074371451524142100330650ustar00rootroot00000000000000import unittest from hamcrest import greater_than from hamcrest.core.core.isequal import equal_to from hamcrest.library.collection.issequence_containinginanyorder import contains_inanyorder from hamcrest_unit_test.matcher_test import MatcherTest from .quasisequence import QuasiSequence from .sequencemixin import GeneratorForm, SequenceForm __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsSequenceContainingInAnyOrderBase(object): def testMatchingSingleItemSequence(self): self.assert_matches( "Single item sequence", contains_inanyorder(equal_to(1)), self._sequence(1) ) def testMatchesSequenceInOrder(self): self.assert_matches( "In order", contains_inanyorder(equal_to(1), equal_to(2)), self._sequence(1, 2) ) def testMatchesSequenceOutOfOrder(self): self.assert_matches( "Out of order", contains_inanyorder(equal_to(1), equal_to(2)), self._sequence(2, 1) ) def testProvidesConvenientShortcutForMatchingWithEqualTo(self): self.assert_matches( "Values automatically wrapped with equal_to", contains_inanyorder(1, 2), self._sequence(2, 1), ) def testDoesNotMatchEmptySequence(self): self.assert_mismatch_description( "no item matches: <1>, <2> in []", contains_inanyorder(1, 2), self._sequence() ) def testEmptySequenceMatchesEmptySequence(self): self.assert_matches("Empty sequence", contains_inanyorder(), self._sequence()) def testDoesNotMatchIfOneOfMultipleItemsMismatch(self): self.assert_mismatch_description( "not matched: <4>", contains_inanyorder(1, 2, 3), self._sequence(1, 2, 4) ) def testDoesNotMatchWithMoreElementsThanExpected(self): self.assert_mismatch_description( "not matched: <2>", contains_inanyorder(1, 3), self._sequence(1, 2, 3) ) def testDoesNotMatchWithFewerElementsThanExpected(self): self.assert_mismatch_description( "no item matches: <4> in [<1>, <2>, <3>]", contains_inanyorder(1, 2, 3, 4), self._sequence(1, 2, 3), ) def testMatchesAnyConformingSequence(self): self.assert_matches("quasi-sequence", contains_inanyorder(1, 2), QuasiSequence()) self.assert_does_not_match("non-sequence", contains_inanyorder(1, 2), object()) def testHasAReadableDescription(self): self.assert_description( "a sequence over [<1>, <2>] in any order", contains_inanyorder(1, 2) ) def testDescribeMismatch(self): self.assert_describe_mismatch( "not matched: <3>", contains_inanyorder(1, 2), self._sequence(1, 3) ) def testDescribeMismatchOfNonSequence(self): self.assert_describe_mismatch("was <3>", contains_inanyorder(1, 2), 3) def testDescribeMismatchAfterMatch(self): matcher = contains_inanyorder(1, 2, 3) matcher.matches(self._sequence(3, 1)) self.assert_describe_mismatch( "no item matches: <2> in [<3>, <1>]", matcher, self._sequence(3, 1) ) def testIncomparableTypes(self): self.assert_matches("Incomparable types", contains_inanyorder(*[4, "a"]), ["a", 4]) def testIncomparableTypesInNestedMatcher(self): self.assert_matches( "Incomparable types in nested matcher", contains_inanyorder(*[greater_than(0), "a"]), ["a", 4], ) class IsConcreteSequenceContainingInAnyOrderTest( MatcherTest, IsSequenceContainingInAnyOrderBase, SequenceForm ): pass class IsGeneratorSequenceContainingInAnyOrderTest( MatcherTest, IsSequenceContainingInAnyOrderBase, GeneratorForm ): pass if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/collection/issequence_containinginorder_test.py000066400000000000000000000062651451524142100323530ustar00rootroot00000000000000import unittest from hamcrest.core.core.isequal import equal_to from hamcrest.library.collection.issequence_containinginorder import contains, contains_exactly from hamcrest_unit_test.matcher_test import MatcherTest from .quasisequence import QuasiSequence from .sequencemixin import GeneratorForm, SequenceForm __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsSequenceContainingInOrderTestBase(object): def testMatchingSingleItemSequence(self): self.assert_matches( "Single item sequence", contains_exactly(equal_to(1)), self._sequence(1) ) def testMatchingMultipleItemSequence(self): self.assert_matches( "Multiple item sequence", contains_exactly(equal_to(1), equal_to(2), equal_to(3)), self._sequence(1, 2, 3), ) def testProvidesConvenientShortcutForMatchingWithEqualTo(self): self.assert_matches( "Values automatically wrapped with equal_to", contains_exactly(1, 2, 3), self._sequence(1, 2, 3), ) def testDoesNotMatchWithMoreElementsThanExpected(self): self.assert_mismatch_description( "Not matched: <4>", contains_exactly(1, 2, 3), self._sequence(1, 2, 3, 4) ) def testDoesNotMatchWithFewerElementsThanExpected(self): self.assert_mismatch_description( "No item matched: <3>", contains_exactly(1, 2, 3), self._sequence(1, 2) ) def testDoesNotMatchIfSingleItemMismatches(self): self.assert_mismatch_description("item 0: was <3>", contains_exactly(4), self._sequence(3)) def testDoesNotMatchIfOneOfMultipleItemsMismatch(self): self.assert_mismatch_description( "item 2: was <4>", contains_exactly(1, 2, 3), self._sequence(1, 2, 4) ) def testDoesNotMatchEmptySequence(self): self.assert_mismatch_description( "No item matched: <4>", contains_exactly(4), self._sequence() ) def testEmptySequenceMatchesEmptySequence(self): self.assert_matches("Empty sequence", contains_exactly(), self._sequence()) def testMatchesAnyConformingSequence(self): self.assert_matches("quasi-sequence", contains_exactly(1, 2), QuasiSequence()) self.assert_does_not_match("non-sequence", contains_exactly(1, 2), object()) def testHasAReadableDescription(self): self.assert_description("a sequence containing [<1>, <2>]", contains_exactly(1, 2)) def testDescribeMismatch(self): self.assert_describe_mismatch( "item 1: was <3>", contains_exactly(1, 2), self._sequence(1, 3) ) def testDescribeMismatchOfNonSequence(self): self.assert_describe_mismatch("was <3>", contains_exactly(1, 2), 3) def testContainsDeprecated(self): self.assert_deprecated("deprecated - use contains_exactly(*items)", contains) class IsConcreteSequenceContainingInOrderTest( MatcherTest, IsSequenceContainingInOrderTestBase, SequenceForm ): pass class IsGeneratorSequenceContainingInOrderTest( MatcherTest, IsSequenceContainingInOrderTestBase, GeneratorForm ): pass if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/collection/issequence_onlycontaining_test.py000066400000000000000000000052641451524142100316700ustar00rootroot00000000000000import unittest from hamcrest.core.core.isequal import equal_to from hamcrest.library.collection.issequence_onlycontaining import only_contains from hamcrest.library.number.ordering_comparison import less_than from hamcrest_unit_test.matcher_test import MatcherTest from .quasisequence import QuasiSequence from .sequencemixin import GeneratorForm, SequenceForm __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsSequenceOnlyContainingTestBase(object): def testMatchesSingletonList(self): self.assert_matches("singleton list", only_contains(equal_to(1)), self._sequence(1)) def testMatchesAllItemsWithOneMatcher(self): self.assert_matches("one matcher", only_contains(less_than(3)), self._sequence(0, 1, 2)) def testMatchesAllItemsWithMultipleMatchers(self): self.assert_matches( "multiple matchers", only_contains(less_than(3), equal_to(7)), self._sequence(0, 7, 1, 2), ) def testProvidesConvenientShortcutForMatchingWithEqualTo(self): self.assert_matches( "Values automatically wrapped with equal_to", only_contains(less_than(3), 7), self._sequence(0, 7, 1, 2), ) def testDoesNotMatchListWithMismatchingItem(self): self.assert_does_not_match( "3 is not less than 3", only_contains(less_than(3)), self._sequence(1, 2, 3) ) def testDoesNotMatchEmptyList(self): self.assert_does_not_match("empty", only_contains("foo"), self._sequence()) def testMatchesAnyConformingSequence(self): class ObjectWithLenOnly(object): def __len__(self): return 20 self.assert_matches("quasi-sequence", only_contains(less_than(3)), QuasiSequence()) self.assert_does_not_match("non-sequence", only_contains(1), object()) self.assert_does_not_match( "non-sequence with length", only_contains(1), ObjectWithLenOnly() ) def testHasAReadableDescription(self): self.assert_description( "a sequence containing items matching (<1> or <2>)", only_contains(1, 2) ) def testDescribeMismatch(self): self.assert_describe_mismatch("was 'bad'", only_contains(1, 2), "bad") def testDescribeMismatchOfNonSequence(self): self.assert_describe_mismatch("was <3>", only_contains(1, 2), 3) class IsConcreteSequenceOnlyContainingTest( MatcherTest, IsSequenceOnlyContainingTestBase, SequenceForm ): pass class IsGeneratorSequenceOnlyContainingTest( MatcherTest, IsSequenceOnlyContainingTestBase, GeneratorForm ): pass if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/collection/quasidict.py000066400000000000000000000020611451524142100253300ustar00rootroot00000000000000from collections.abc import Iterator __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class QuasiDictionary(object): def items(self): return QuasiDictionaryItemIterator() def keys(self): return QuasiDictionaryKeyIterator() def values(self): return QuasiDictionaryValueIterator() class BaseQuasiDictionaryIterator(Iterator): def __init__(self): self.index = 1 def __iter__(self): return self def __next__(self): if self.index >= 3: raise StopIteration result = self.indexToResult() self.index += 1 return result class QuasiDictionaryItemIterator(BaseQuasiDictionaryIterator): def indexToResult(self): return (self.index, str(self.index)) class QuasiDictionaryKeyIterator(BaseQuasiDictionaryIterator): def indexToResult(self): return self.index class QuasiDictionaryValueIterator(BaseQuasiDictionaryIterator): def indexToResult(self): return str(self.index) PyHamcrest-2.1.0/tests/hamcrest_unit_test/collection/quasisequence.py000066400000000000000000000010741451524142100262200ustar00rootroot00000000000000from collections.abc import Iterator __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class QuasiSequence(object): def __iter__(self): return QuasiSequenceIterator() def __len__(self): return 2 class QuasiSequenceIterator(Iterator): def __init__(self): self.index = 1 def __iter__(self): return self def __next__(self): if self.index >= 3: raise StopIteration result = self.index self.index += 1 return result PyHamcrest-2.1.0/tests/hamcrest_unit_test/collection/sequencemixin.py000066400000000000000000000003141451524142100262160ustar00rootroot00000000000000class GeneratorForm(object): def _sequence(self, *objects): for i in objects: yield i class SequenceForm(object): def _sequence(self, *objects): return list(objects) PyHamcrest-2.1.0/tests/hamcrest_unit_test/core/000077500000000000000000000000001451524142100215665ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/hamcrest_unit_test/core/__init__.py000066400000000000000000000000001451524142100236650ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/hamcrest_unit_test/core/allof_test.py000066400000000000000000000061261451524142100243010ustar00rootroot00000000000000if __name__ == "__main__": import sys sys.path.insert(0, "..") sys.path.insert(0, "../..") import unittest from hamcrest.core.core.allof import AllOf, all_of from hamcrest.core.core.isequal import equal_to from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class AllOfTest(MatcherTest): def testMatchesIfArgumentSatisfiesBothOfTwoOtherMatchers(self): self.assert_matches("both matchers", all_of(equal_to("good"), equal_to("good")), "good") def testProvidesConvenientShortcutForMatchingWithEqualTo(self): self.assert_matches("both matchers", all_of("good", "good"), "good") def testNoMatchIfArgumentFailsToSatisfyEitherOfTwoOtherMatchers(self): self.assert_does_not_match( "first matcher", all_of(equal_to("bad"), equal_to("good")), "good" ) self.assert_does_not_match( "second matcher", all_of(equal_to("good"), equal_to("bad")), "good" ) self.assert_does_not_match( "either matcher", all_of(equal_to("bad"), equal_to("bad")), "good" ) def testMatchesIfArgumentSatisfiesAllOfManyOtherMatchers(self): self.assert_matches( "all matchers", all_of( equal_to("good"), equal_to("good"), equal_to("good"), equal_to("good"), equal_to("good"), ), "good", ) def testNoMatchIfArgumentFailsToSatisfyAllOfManyOtherMatchers(self): self.assert_does_not_match( "matcher in the middle", all_of( equal_to("good"), equal_to("good"), equal_to("good"), equal_to("bad"), equal_to("good"), equal_to("good"), ), "good", ) def testHasAReadableDescription(self): self.assert_description( "('good' and 'bad' and 'ugly')", all_of(equal_to("good"), equal_to("bad"), equal_to("ugly")), ) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(all_of(equal_to("good"), equal_to("good")), "good") def testMismatchDescriptionDescribesFirstFailingMatch(self): self.assert_mismatch_description( "'good' was 'bad'", all_of(equal_to("bad"), equal_to("good")), "bad" ) def testDescribeMismatch(self): self.assert_describe_mismatch( "'good' was 'bad'", all_of(equal_to("bad"), equal_to("good")), "bad" ) def testMismatchDescriptionOptionallyDescribesMultipleFailingMatches(self): self.assert_mismatch_description( "'bad' was 'indifferent' and 'good' was 'indifferent'", AllOf( equal_to("bad"), equal_to("indifferent"), equal_to("good"), describe_all_mismatches=True, ), "indifferent", ) if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/core/anyof_test.py000066400000000000000000000051351451524142100243170ustar00rootroot00000000000000if __name__ == "__main__": import sys sys.path.insert(0, "..") sys.path.insert(0, "../..") import unittest from hamcrest.core.core.anyof import any_of from hamcrest.core.core.isequal import equal_to from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class AnyOfTest(MatcherTest): def testMatchesIfArgumentSatisfiesEitherOrBothOfTwoOtherMatchers(self): self.assert_matches("first matcher", any_of(equal_to("good"), equal_to("bad")), "good") self.assert_matches("second matcher", any_of(equal_to("bad"), equal_to("good")), "good") self.assert_matches("both matchers", any_of(equal_to("good"), equal_to("good")), "good") def testProvidesConvenientShortcutForMatchingWithEqualTo(self): self.assert_matches("first matcher", any_of("good", "bad"), "good") self.assert_matches("second matcher", any_of("bad", "good"), "good") self.assert_matches("both matchers", any_of("good", "good"), "good") def testNoMatchIfArgumentFailsToSatisfyEitherOfTwoOtherMatchers(self): self.assert_does_not_match( "either matcher", any_of(equal_to("bad"), equal_to("bad")), "good" ) def testMatchesIfArgumentSatisfiesAnyOfManyOtherMatchers(self): self.assert_matches( "matcher in the middle", any_of( equal_to("bad"), equal_to("bad"), equal_to("good"), equal_to("bad"), equal_to("bad") ), "good", ) def testNoMatchIfArgumentFailsToSatisfyAnyOfManyOtherMatchers(self): self.assert_does_not_match( "all matchers", any_of( equal_to("bad"), equal_to("bad"), equal_to("bad"), equal_to("bad"), equal_to("bad") ), "good", ) def testHasAReadableDescription(self): self.assert_description( "('good' or 'bad' or 'ugly')", any_of(equal_to("good"), equal_to("bad"), equal_to("ugly")), ) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(any_of(equal_to("good"), equal_to("bad")), "good") def testMismatchDescriptionDescribesFirstFailingMatch(self): self.assert_mismatch_description( "was 'ugly'", any_of(equal_to("bad"), equal_to("good")), "ugly" ) def testDescribeMismatch(self): self.assert_describe_mismatch( "was 'ugly'", any_of(equal_to("bad"), equal_to("good")), "ugly" ) if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/core/described_as_test.py000066400000000000000000000033031451524142100256050ustar00rootroot00000000000000import unittest from hamcrest.core.core.described_as import described_as from hamcrest.core.core.isanything import anything from hamcrest_unit_test.matcher_test import MatcherTest from .nevermatch import NeverMatch __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class DescribedAsTest(MatcherTest): def testOverridesDescriptionOfNestedMatcherWithConstructorArgument(self): m1 = described_as("m1 description", anything()) m2 = described_as("m2 description", NeverMatch()) self.assert_description("m1 description", m1) self.assert_description("m2 description", m2) def testAppendsValuesToDescription(self): m = described_as("value 1 = %0, value 2 = %1", anything(), 33, 97) self.assert_description("value 1 = <33>, value 2 = <97>", m) def testDelegatesMatchingToNestedMatcher(self): m1 = described_as("irrelevant", anything()) m2 = described_as("irrelevant", NeverMatch()) self.assertTrue(m1.matches(object())) self.assertTrue(not m2.matches("hi")) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(described_as("irrelevant", anything()), object()) def testDelegatesMismatchDescriptionToNestedMatcher(self): self.assert_mismatch_description( NeverMatch.mismatch_description, described_as("irrelevant", NeverMatch()), "hi" ) def testDelegatesDescribeMismatchToNestedMatcher(self): self.assert_describe_mismatch( NeverMatch.mismatch_description, described_as("irrelevant", NeverMatch()), "hi" ) if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/core/future_test.py000066400000000000000000000157471451524142100245270ustar00rootroot00000000000000import sys import pytest import asyncio from hamcrest import has_properties from hamcrest.core.core.future import resolved, future_raising from hamcrest_unit_test.matcher_test import MatcherTest if __name__ == "__main__": sys.path.insert(0, "..") sys.path.insert(0, "../..") __author__ = "David Keijser" __copyright__ = "Copyright 2023 hamcrest.org" __license__ = "BSD, see License.txt" async def no_exception(*args, **kwargs): return async def raise_exception(*args, **kwargs): raise AssertionError(str(args) + str(kwargs)) async def raise_exception_with_properties(**kwargs): err = AssertionError("boom") for k, v in kwargs.items(): setattr(err, k, v) raise err # From python 3.8 this could be simplified by using unittest.IsolatedAsyncioTestCase class FutureExceptionTest(MatcherTest): def testMatchesIfFutureHasTheExactExceptionExpected(self): async def test(): self.assert_matches( "Right exception", future_raising(AssertionError), await resolved(raise_exception()), ) asyncio.get_event_loop().run_until_complete(test()) def testDoesNotMatchIfActualIsNotAFuture(self): async def test(): self.assert_does_not_match("Not a future", future_raising(TypeError), 23) asyncio.get_event_loop().run_until_complete(test()) def testDoesNotMatchIfFutureIsNotDone(self): future = asyncio.Future() self.assert_does_not_match("Unresolved future", future_raising(TypeError), future) def testDoesNotMatchIfFutureIsCancelled(self): future = asyncio.Future() future.cancel() self.assert_does_not_match("Cancelled future", future_raising(TypeError), future) @pytest.mark.skipif( not (3, 0) <= sys.version_info < (3, 7), reason="Message differs between Python versions" ) def testDoesNotMatchIfFutureHasTheWrongExceptionTypePy3(self): async def test(): self.assert_does_not_match( "Wrong exception", future_raising(IOError), await resolved(raise_exception()) ) expected_message = ( "AssertionError('(){}',) of type was raised instead" ) self.assert_mismatch_description( expected_message, future_raising(TypeError), await resolved(raise_exception()) ) asyncio.get_event_loop().run_until_complete(test()) @pytest.mark.skipif(sys.version_info < (3, 7), reason="Message differs between Python versions") def testDoesNotMatchIfFutureHasTheWrongExceptionTypePy37(self): async def test(): self.assert_does_not_match( "Wrong exception", future_raising(IOError), await resolved(raise_exception()) ) expected_message = ( "AssertionError('(){}') of type was raised instead" ) self.assert_mismatch_description( expected_message, future_raising(TypeError), await resolved(raise_exception()) ) asyncio.get_event_loop().run_until_complete(test()) def testMatchesIfFutureHasASubclassOfTheExpectedException(self): async def test(): self.assert_matches( "Subclassed Exception", future_raising(Exception), await resolved(raise_exception()), ) asyncio.get_event_loop().run_until_complete(test()) def testDoesNotMatchIfFutureDoesNotHaveException(self): async def test(): self.assert_does_not_match( "No exception", future_raising(ValueError), await resolved(no_exception()) ) asyncio.get_event_loop().run_until_complete(test()) def testDoesNotMatchExceptionIfRegularExpressionDoesNotMatch(self): async def test(): self.assert_does_not_match( "Bad regex", future_raising(AssertionError, "Phrase not found"), await resolved(raise_exception()), ) self.assert_mismatch_description( '''Correct assertion type raised, but the expected pattern ("Phrase not found") not found. Exception message was: "(){}"''', future_raising(AssertionError, "Phrase not found"), await resolved(raise_exception()), ) asyncio.get_event_loop().run_until_complete(test()) def testMatchesRegularExpressionToStringifiedException(self): async def test(): self.assert_matches( "Regex", future_raising(AssertionError, "(3, 1, 4)"), await resolved(raise_exception(3, 1, 4)), ) self.assert_matches( "Regex", future_raising(AssertionError, r"([\d, ]+)"), await resolved(raise_exception(3, 1, 4)), ) asyncio.get_event_loop().run_until_complete(test()) def testMachesIfExceptionMatchesAdditionalMatchers(self): async def test(): self.assert_matches( "Properties", future_raising(AssertionError, matching=has_properties(prip="prop")), await resolved(raise_exception_with_properties(prip="prop")), ) asyncio.get_event_loop().run_until_complete(test()) def testDoesNotMatchIfAdditionalMatchersDoesNotMatch(self): async def test(): self.assert_does_not_match( "Bad properties", future_raising(AssertionError, matching=has_properties(prop="prip")), await resolved(raise_exception_with_properties(prip="prop")), ) self.assert_mismatch_description( '''Correct assertion type raised, but an object with a property 'prop' matching 'prip' not found. Exception message was: "boom"''', future_raising(AssertionError, matching=has_properties(prop="prip")), await resolved(raise_exception_with_properties(prip="prop")), ) asyncio.get_event_loop().run_until_complete(test()) def testDoesNotMatchIfNeitherPatternOrMatcherMatch(self): async def test(): self.assert_does_not_match( "Bad pattern and properties", future_raising( AssertionError, pattern="asdf", matching=has_properties(prop="prip") ), await resolved(raise_exception_with_properties(prip="prop")), ) self.assert_mismatch_description( '''Correct assertion type raised, but the expected pattern ("asdf") and an object with a property 'prop' matching 'prip' not found. Exception message was: "boom"''', future_raising( AssertionError, pattern="asdf", matching=has_properties(prop="prip") ), await resolved(raise_exception_with_properties(prip="prop")), ) asyncio.get_event_loop().run_until_complete(test()) PyHamcrest-2.1.0/tests/hamcrest_unit_test/core/is_test.py000066400000000000000000000035061451524142100236160ustar00rootroot00000000000000import unittest from hamcrest.core.core.is_ import is_ from hamcrest.core.core.isequal import equal_to from hamcrest_unit_test.matcher_test import MatcherTest from .nevermatch import NeverMatch __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsTest(MatcherTest): def testDelegatesMatchingToNestedMatcher(self): self.assert_matches("should match", is_(equal_to(True)), True) self.assert_matches("should match", is_(equal_to(False)), False) self.assert_does_not_match("should not match", is_(equal_to(True)), False) self.assert_does_not_match("should not match", is_(equal_to(False)), True) def testDescriptionShouldPassThrough(self): self.assert_description("", is_(equal_to(True))) def testProvidesConvenientShortcutForIsEqualTo(self): self.assert_matches("should match", is_("A"), "A") self.assert_matches("should match", is_("B"), "B") self.assert_does_not_match("should not match", is_("A"), "B") self.assert_does_not_match("should not match", is_("B"), "A") self.assert_description("'A'", is_("A")) def testProvidesConvenientShortcutForIsInstanceOf(self): self.assert_matches("should match", is_(str), "A") self.assert_does_not_match("should not match", is_(int), "A") def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(is_("A"), "A") def testDelegatesMismatchDescriptionToNestedMatcher(self): self.assert_mismatch_description(NeverMatch.mismatch_description, is_(NeverMatch()), "hi") def testDelegatesDescribeMismatchToNestedMatcher(self): self.assert_describe_mismatch(NeverMatch.mismatch_description, is_(NeverMatch()), "hi") if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/core/isanything_test.py000066400000000000000000000020011451524142100253450ustar00rootroot00000000000000if __name__ == "__main__": import sys sys.path.insert(0, "..") sys.path.insert(0, "../..") import unittest from hamcrest.core.core.isanything import anything from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsAnythingTest(MatcherTest): def testAlwaysEvaluatesToTrue(self): self.assert_matches("None", anything(), None) self.assert_matches("object", anything(), object()) self.assert_matches("string", anything(), "hi") def testHasUsefulDefaultDescription(self): self.assert_description("ANYTHING", anything()) def testCanOverrideDescription(self): description = "DESCRIPTION" self.assert_description(description, anything(description)) def testMatchAlwaysSucceedsSoShouldNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(anything(), "hi") if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/core/isequal_test.py000066400000000000000000000047511451524142100246510ustar00rootroot00000000000000if __name__ == "__main__": import sys sys.path.insert(0, "..") sys.path.insert(0, "../..") import unittest from hamcrest.core.core.isequal import equal_to from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsEqualTest(MatcherTest): def testComparesObjectsUsingEquality(self): self.assert_matches("equal numbers", equal_to(1), 1) self.assert_does_not_match("unequal numbers", equal_to(1), 2) def testCanCompareNoneValues(self): self.assert_matches("None equals None", equal_to(None), None) self.assert_does_not_match("None as argument", equal_to("hi"), None) self.assert_does_not_match("None in equal_to", equal_to(None), "hi") def testHonorsArgumentEqImplementationEvenWithNone(self): class AlwaysEqual: def __eq__(self, obj): return True class NeverEqual: def __eq__(self, obj): return False self.assert_matches("always equal", equal_to(None), AlwaysEqual()) self.assert_does_not_match("never equal", equal_to(None), NeverEqual()) def testIncludesTheResultOfCallingToStringOnItsArgumentInTheDescription(self): argument_description = "ARGUMENT DESCRIPTION" class Argument: def __str__(self): return argument_description self.assert_description("", equal_to(Argument())) def testReturnsAnObviousDescriptionIfCreatedWithANestedMatcherByMistake(self): inner_matcher = equal_to("NestedMatcher") self.assert_description("<'NestedMatcher'>", equal_to(inner_matcher)) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(equal_to("hi"), "hi") def testMismatchDescriptionShowsActualArgument(self): self.assert_mismatch_description("was 'bad'", equal_to("good"), "bad") def testDescribeMismatch(self): self.assert_describe_mismatch("was 'bad'", equal_to("good"), "bad") def testEqualToWithEqualBytes(self): self.assert_matches("equal for b", equal_to("a"), "a") def testNotEqualToWithEqualBytes(self): self.assert_does_not_match("equal for b", equal_to("a"), "b") def testByteInequalityDescription(self): self.assert_mismatch_description("was <{0!r}>".format(b"b"), equal_to(b"a"), b"b") if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/core/isinstanceof_test.py000066400000000000000000000024501451524142100256650ustar00rootroot00000000000000import sys import unittest from hamcrest.core.core.isinstanceof import instance_of from hamcrest_unit_test.matcher_test import MatcherTest if __name__ == "__main__": sys.path.insert(0, "..") sys.path.insert(0, "../..") __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsInstanceOfTest(MatcherTest): def testEvaluatesToTrueIfArgumentIsInstanceOfASpecificClass(self): self.assert_matches("same class", instance_of(int), 1) self.assert_does_not_match("different class", instance_of(int), "hi") self.assert_does_not_match("None", instance_of(int), None) def testMatcherCreationRequiresType(self): self.assertRaises(TypeError, instance_of, "not a type") def testHasAReadableDescription(self): self.assert_description("an instance of int", instance_of(int)) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(instance_of(int), 3) def testMismatchDescriptionShowsActualArgument(self): self.assert_mismatch_description("was 'bad'", instance_of(int), "bad") def testDescribeMismatch(self): self.assert_describe_mismatch("was 'bad'", instance_of(int), "bad") if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/core/isnone_test.py000066400000000000000000000034551451524142100245010ustar00rootroot00000000000000if __name__ == "__main__": import sys sys.path.insert(0, "..") sys.path.insert(0, "../..") import unittest from hamcrest.core.core.isnone import none, not_none from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsNoneTest(MatcherTest): def testEvaluatesToTrueIfArgumentIsNone(self): self.assert_matches("None", none(), None) def testEvaluatesToFalseIfArgumentIsNotNone(self): self.assert_does_not_match("not None", none(), object()) def testHasAReadableDescription(self): self.assert_description("None", none()) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(none(), None) def testMismatchDescriptionShowsActualArgument(self): self.assert_mismatch_description("was 'bad'", none(), "bad") def testDescribeMismatch(self): self.assert_describe_mismatch("was 'bad'", none(), "bad") class NotNoneTest(MatcherTest): def testEvaluatesToTrueIfArgumentIsNotNone(self): self.assert_matches("not None", not_none(), object()) def testEvaluatesToFalseIfArgumentIsNone(self): self.assert_does_not_match("None", not_none(), None) def testHasAReadableDescription(self): self.assert_description("not None", not_none()) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(not_none(), "hi") def testMismatchDescriptionShowsActualArgument(self): self.assert_mismatch_description("but was ", not_none(), None) def testDescribeMismatch(self): self.assert_describe_mismatch("but was ", not_none(), None) if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/core/isnot_test.py000066400000000000000000000030071451524142100243330ustar00rootroot00000000000000if __name__ == "__main__": import sys sys.path.insert(0, "..") sys.path.insert(0, "../..") import unittest from hamcrest.core.core.isequal import equal_to from hamcrest.core.core.isnot import is_not from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsNotTest(MatcherTest): def testEvaluatesToTheTheLogicalNegationOfAnotherMatcher(self): self.assert_matches("invert mismatch", is_not(equal_to("A")), "B") self.assert_does_not_match("invert match", is_not(equal_to("A")), "A") def testProvidesConvenientShortcutForNotEqualTo(self): self.assert_matches("invert mismatch", is_not("A"), "B") self.assert_does_not_match("invert match", is_not("A"), "A") def testProvidesConvenientShortcutForNotInstanceOf(self): self.assert_matches("invert mismatch", is_not(str), 1) self.assert_does_not_match("invert match", is_not(str), "A") def testHasAReadableDescription(self): self.assert_description("not 'A'", is_not("A")) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(is_not("A"), "B") def testMismatchDescriptionShowsActualArgument(self): self.assert_mismatch_description("but was 'A'", is_not("A"), "A") def testDescribeMismatch(self): self.assert_describe_mismatch("but was 'A'", is_not("A"), "A") if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/core/issame_test.py000066400000000000000000000045361451524142100244700ustar00rootroot00000000000000if __name__ == "__main__": import sys sys.path.insert(0, "..") sys.path.insert(0, "../..") import re import unittest from hamcrest.core.core.issame import same_instance from hamcrest.core.string_description import StringDescription from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" ADDRESS_FORMAT = r"-?0x[0-9a-fA-F]+L?" class IsSameTest(MatcherTest): def testEvaluatesToTrueIfArgumentIsReferenceToASpecifiedObject(self): o1 = object() o2 = object() self.assert_matches("same", same_instance(o1), o1) self.assert_does_not_match("different", same_instance(o1), o2) def testDescriptionIncludesMemoryAddress(self): description = StringDescription() expected = re.compile("same instance as " + ADDRESS_FORMAT + " 'abc'") description.append_description_of(same_instance("abc")) self.assertTrue(expected.match(str(description))) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): o1 = object() self.assert_no_mismatch_description(same_instance(o1), o1) def testMismatchDescriptionShowsActualArgumentAddress(self): matcher = same_instance("foo") description = StringDescription() expected = re.compile("was " + ADDRESS_FORMAT + " 'hi'") result = matcher.matches("hi", description) self.assertFalse(result, "Precondition: Matcher should not match item") self.assertTrue(expected.match(str(description))) def testMismatchDescriptionWithNilShouldNotIncludeAddress(self): self.assert_mismatch_description("was ", same_instance("foo"), None) def testDescribeMismatch(self): matcher = same_instance("foo") description = StringDescription() expected = re.compile("was " + ADDRESS_FORMAT + " 'hi'") matcher.describe_mismatch("hi", description) expected = re.compile("was " + ADDRESS_FORMAT + " 'hi'") self.assertTrue( expected.match(str(description)), "Expected %s to match %s" % (str(matcher), str(description)), ) def testDescribeMismatchWithNilShouldNotIncludeAddress(self): self.assert_describe_mismatch("was ", same_instance("foo"), None) if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/core/nevermatch.py000066400000000000000000000010361451524142100242740ustar00rootroot00000000000000from hamcrest.core.base_matcher import BaseMatcher __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class NeverMatch(BaseMatcher): mismatch_description = "NEVERMATCH" def matches(self, item, mismatch_description=None): if mismatch_description: self.describe_mismatch(item, mismatch_description) return False def describe_mismatch(self, item, mismatch_description): mismatch_description.append_text(NeverMatch.mismatch_description) PyHamcrest-2.1.0/tests/hamcrest_unit_test/core/raises_test.py000066400000000000000000000170151451524142100244710ustar00rootroot00000000000000import sys import unittest import pytest from hamcrest import has_properties, not_ from hamcrest.core.core.raises import calling, raises from hamcrest_unit_test.matcher_test import MatcherTest, assert_mismatch_description if __name__ == "__main__": sys.path.insert(0, "..") sys.path.insert(0, "../..") __author__ = "Per Fagrell" __copyright__ = "Copyright 2013 hamcrest.org" __license__ = "BSD, see License.txt" def no_exception(*args, **kwargs): return def raise_exception(*args, **kwargs): raise AssertionError(str(args) + str(kwargs)) def raise_baseException(*args, **kwargs): raise SystemExit(str(args) + str(kwargs)) def raise_exception_with_properties(**kwargs): err = AssertionError("boom") for k, v in kwargs.items(): setattr(err, k, v) raise err class RaisesTest(MatcherTest): def testMatchesIfFunctionRaisesTheExactExceptionExpected(self): self.assert_matches("Right exception", raises(AssertionError), calling(raise_exception)) def testDoesNotMatchTypeErrorIfActualIsNotCallable(self): self.assert_does_not_match("Not callable", raises(TypeError), 23) @pytest.mark.skipif( not (3, 0) <= sys.version_info < (3, 7), reason="Message differs between Python versions" ) def testDoesNotMatchIfTheWrongExceptionTypeIsRaisedPy3(self): self.assert_does_not_match("Wrong exception", raises(IOError), calling(raise_exception)) expected_message = ( "AssertionError('(){}',) of type was raised instead" ) self.assert_mismatch_description( expected_message, raises(TypeError), calling(raise_exception) ) @pytest.mark.skipif(sys.version_info < (3, 7), reason="Message differs between Python versions") def testDoesNotMatchIfTheWrongExceptionTypeIsRaisedPy37(self): self.assert_does_not_match("Wrong exception", raises(IOError), calling(raise_exception)) expected_message = ( "AssertionError('(){}') of type was raised instead" ) self.assert_mismatch_description( expected_message, raises(TypeError), calling(raise_exception) ) def testMatchesIfFunctionRaisesASubclassOfTheExpectedException(self): self.assert_matches("Subclassed Exception", raises(Exception), calling(raise_exception)) def testMatchesIfFunctionRaisesASubclassOfTheExpectedBaseException(self): self.assert_matches( "Subclassed BasedException", raises(BaseException), calling(raise_baseException) ) def testDoesNotMatchIfFunctionDoesNotRaiseException(self): self.assert_does_not_match("No exception", raises(ValueError), calling(no_exception)) def testDoesNotMatchExceptionIfRegularExpressionDoesNotMatch(self): self.assert_does_not_match( "Bad regex", raises(AssertionError, "Phrase not found"), calling(raise_exception) ) self.assert_mismatch_description( '''Correct assertion type raised, but the expected pattern ("Phrase not found") not found. Exception message was: "(){}"''', raises(AssertionError, "Phrase not found"), calling(raise_exception), ) def testMatchesRegularExpressionToStringifiedException(self): self.assert_matches( "Regex", raises(AssertionError, "(3, 1, 4)"), calling(raise_exception).with_args(3, 1, 4), ) self.assert_matches( "Regex", raises(AssertionError, r"([\d, ]+)"), calling(raise_exception).with_args(3, 1, 4), ) def testMachesIfRaisedExceptionMatchesAdditionalMatchers(self): self.assert_matches( "Properties", raises(AssertionError, matching=has_properties(prip="prop")), calling(raise_exception_with_properties).with_args(prip="prop"), ) def testDoesNotMatchIfAdditionalMatchersDoesNotMatch(self): self.assert_does_not_match( "Bad properties", raises(AssertionError, matching=has_properties(prop="prip")), calling(raise_exception_with_properties).with_args(prip="prop"), ) self.assert_mismatch_description( '''Correct assertion type raised, but an object with a property 'prop' matching 'prip' not found. Exception message was: "boom"''', raises(AssertionError, matching=has_properties(prop="prip")), calling(raise_exception_with_properties).with_args(prip="prop"), ) def testDoesNotMatchIfNeitherPatternOrMatcherMatch(self): self.assert_does_not_match( "Bad pattern and properties", raises(AssertionError, pattern="asdf", matching=has_properties(prop="prip")), calling(raise_exception_with_properties).with_args(prip="prop"), ) self.assert_mismatch_description( '''Correct assertion type raised, but the expected pattern ("asdf") and an object with a property 'prop' matching 'prip' not found. Exception message was: "boom"''', raises(AssertionError, pattern="asdf", matching=has_properties(prop="prip")), calling(raise_exception_with_properties).with_args(prip="prop"), ) def testDescribeMismatchWillCallItemIfNotTheOriginalMatch(self): function = Callable() matcher = raises(AssertionError) matcher.describe_mismatch(function, object()) self.assertTrue(function.called) @pytest.mark.parametrize( "expected_message", [ pytest.param( "but AssertionError('(){}',) of type was raised.", marks=pytest.mark.skipif( sys.version_info >= (3, 0), reason="Message differs between Python versions" ), ), pytest.param( "but AssertionError('(){}',) of type was raised.", marks=pytest.mark.skipif( not (3, 0) <= sys.version_info < (3, 7), reason="Message differs between Python versions", ), ), pytest.param( "but AssertionError('(){}') of type was raised.", marks=pytest.mark.skipif( sys.version_info < (3, 7), reason="Message differs between Python versions" ), ), ], ) def test_gives_correct_message_when_wrapped_with_is_not(expected_message): assert_mismatch_description( expected_message, not_(raises(AssertionError)), calling(raise_exception) ) class CallingTest(unittest.TestCase): def testCallingDoesNotImmediatelyExecuteFunction(self): try: calling(raise_exception) except AssertionError: self.fail() else: pass def testCallingObjectCallsProvidedFunction(self): method = Callable() calling(method)() self.assertTrue(method.called) def testCallingWithFunctionReturnsObject(self): method = Callable() callable = calling(method) returned = callable.with_args(3, 1, 4, keyword1="arg1") self.assertEqual(returned, callable) def testCallingWithFunctionSetsArgumentList(self): method = Callable() calling(method).with_args(3, 1, 4, keyword1="arg1")() self.assertEqual(method.args, (3, 1, 4)) self.assertEqual(method.kwargs, {"keyword1": "arg1"}) class Callable(object): def __init__(self): self.called = False def __call__(self, *args, **kwargs): self.called = True self.args = args self.kwargs = kwargs PyHamcrest-2.1.0/tests/hamcrest_unit_test/integration/000077500000000000000000000000001451524142100231615ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/hamcrest_unit_test/integration/__init__.py000066400000000000000000000000001451524142100252600ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/hamcrest_unit_test/integration/match_equality_test.py000066400000000000000000000021421451524142100276020ustar00rootroot00000000000000if __name__ == "__main__": import sys sys.path.insert(0, "..") sys.path.insert(0, "../..") import unittest from hamcrest.core.core.isequal import equal_to from hamcrest.library.integration.match_equality import match_equality, tostring __author__ = "Chris Rose" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class MatchEqualityWrapperTest(unittest.TestCase): def testMatcherIsEqualWhenMatchesIsTrue(self): matcher = equal_to("bar") assert match_equality(matcher) == "bar" def testMatcherIsNotEqualWhenMatchesIsFalse(self): matcher = equal_to("bar") assert match_equality(matcher) != "foo" def testMatcherStringIsMatcherDescription(self): matcher = equal_to("bar") assert str(match_equality(matcher)) == tostring(matcher) def testMatcherReprIsMatcher(self): matcher = equal_to("bar") assert repr(match_equality(matcher)) == tostring(matcher) def testMatchesWhenProvidedAnObject(self): assert match_equality("bar") == "bar" if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/matcher_test.py000066400000000000000000000057371451524142100237060ustar00rootroot00000000000000import logging import unittest import warnings from hamcrest import anything, assert_that, has_item, has_properties, has_string from hamcrest.core.string_description import StringDescription log = logging.getLogger(__name__) __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" __tracebackhide__ = True class MatcherTest(unittest.TestCase): def assert_matches(self, message, matcher, arg): assert_matches(matcher, arg, message) def assert_does_not_match(self, message, matcher, arg): assert_does_not_match(matcher, arg, message) def assert_description(self, expected, matcher): assert_description(expected, matcher) def assert_no_mismatch_description(self, matcher, arg): assert_no_mismatch_description(matcher, arg) def assert_mismatch_description(self, expected, matcher, arg): assert_mismatch_description(expected, matcher, arg) def assert_describe_mismatch(self, expected, matcher, arg): assert_describe_mismatch(expected, matcher, arg) def assert_deprecated(self, message, matcher): assert_deprecated(message, matcher) def assert_matches(matcher, arg, message): try: assert matcher.matches(arg), message except AssertionError: description = StringDescription() matcher.describe_mismatch(arg, description) log.error(str(description)) raise def assert_does_not_match(matcher, arg, message): assert not matcher.matches(arg), message def assert_description(expected, matcher): description = StringDescription() description.append_description_of(matcher) assert expected == str(description) def assert_no_mismatch_description(matcher, arg): description = StringDescription() result = matcher.matches(arg, description) assert result, "Precondition: Matcher should match item" assert "" == str(description), "Expected no mismatch description" def assert_mismatch_description(expected, matcher, arg): description = StringDescription() result = matcher.matches(arg, description) assert not result, "Precondition: Matcher should not match item" assert expected == str(description) def assert_match_description(expected, matcher, item): result = matcher.matches(item, StringDescription()) assert result, "Precondition: Matcher should match item" description = StringDescription() matcher.describe_match(item, description) assert expected == str(description) def assert_describe_mismatch(expected, matcher, arg): description = StringDescription() matcher.describe_mismatch(arg, description) assert expected == str(description) def assert_deprecated(message, matcher): with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") matcher(anything()).matches("", StringDescription()) assert_that( w, has_item(has_properties(category=DeprecationWarning, message=has_string(message))) ) PyHamcrest-2.1.0/tests/hamcrest_unit_test/number/000077500000000000000000000000001451524142100221265ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/hamcrest_unit_test/number/__init__.py000066400000000000000000000000001451524142100242250ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/hamcrest_unit_test/number/iscloseto_test.py000066400000000000000000000137331451524142100255520ustar00rootroot00000000000000import unittest from hamcrest.library.number.iscloseto import Decimal, close_to, isnumeric from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class IsCloseToTest(MatcherTest): def testEvaluatesToTrueIfArgumentIsEqualToAValueWithinSomeError(self): matcher = close_to(1.0, 0.5) self.assert_matches("equal", matcher, 1.0) self.assert_matches("less but within delta", matcher, 0.5) self.assert_matches("greater but within delta", matcher, 1.5) self.assert_does_not_match("too small", matcher, 0.4) self.assert_does_not_match("too large", matcher, 1.6) def testMatcherCreationAcceptsOtherNumericTypes(self): close_to(int(5), int(1)) def testMatcherCreationRequiresNumbers(self): self.assertRaises(TypeError, close_to, "a", 0.5) self.assertRaises(TypeError, close_to, 1.0, "a") def testFailsIfMatchingAgainstNonNumber(self): self.assert_does_not_match("not a number", close_to(1.0, 0.5), "a") def testHasAReadableDescription(self): self.assert_description("a numeric value within <0.5> of <1.0>", close_to(1.0, 0.5)) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(close_to(1.0, 0.5), 1.0) def testMismatchDescriptionShowsActualDeltaIfArgumentIsNumeric(self): self.assert_mismatch_description("<1.7> differed by <0.7>", close_to(1.0, 0.5), 1.7) def testMismatchDescriptionShowsActualArgumentIfNotNumeric(self): self.assert_mismatch_description("was 'bad'", close_to(1.0, 0.5), "bad") def testDescribeMismatchShowsActualDeltaIfArgumentIsNumeric(self): self.assert_describe_mismatch("<1.7> differed by <0.7>", close_to(1.0, 0.5), 1.7) def testDescribeMismatchShowsActualArgumentIfNotNumeric(self): self.assert_describe_mismatch("was 'bad'", close_to(1.0, 0.5), "bad") def testMatcherSupportsDecimal(self): matcher = close_to(Decimal("1.0"), Decimal("0.5")) self.assert_matches("equal", matcher, Decimal("1.4")) try: import numpy as np NUMPY_AVAILABLE = True except ImportError: NUMPY_AVAILABLE = False class IsNumericTest(unittest.TestCase): @unittest.skipUnless(NUMPY_AVAILABLE, "Skipped because it needs NumPy") def test_numpy_numeric_type_int(self): self.assertTrue(isnumeric(np.int_(1)), "Platform integer (normally either int32 or int64)") @unittest.skipUnless(NUMPY_AVAILABLE, "Skipped because it needs NumPy") def test_numpy_numeric_type_int8(self): self.assertTrue(isnumeric(np.int8(1)), "Byte (-128 to 127)") @unittest.skipUnless(NUMPY_AVAILABLE, "Skipped because it needs NumPy") def test_numpy_numeric_type_int16(self): self.assertTrue(isnumeric(np.int16(1)), "Integer (-32768 to 32767)") @unittest.skipUnless(NUMPY_AVAILABLE, "Skipped because it needs NumPy") def test_numpy_numeric_type_int32(self): self.assertTrue(isnumeric(np.int32(1)), "Integer (-2147483648 to 2147483647)") @unittest.skipUnless(NUMPY_AVAILABLE, "Skipped because it needs NumPy") def test_numpy_numeric_type_int64(self): self.assertTrue( isnumeric(np.int64(1)), "Integer (9223372036854775808 to 9223372036854775807)" ) @unittest.skipUnless(NUMPY_AVAILABLE, "Skipped because it needs NumPy") def test_numpy_numeric_type_uint8(self): self.assertTrue(isnumeric(np.uint8(1)), "Unsigned integer (0 to 255)") @unittest.skipUnless(NUMPY_AVAILABLE, "Skipped because it needs NumPy") def test_numpy_numeric_type_uint16(self): self.assertTrue(isnumeric(np.uint16(1)), "Unsigned integer (0 to 65535)") @unittest.skipUnless(NUMPY_AVAILABLE, "Skipped because it needs NumPy") def test_numpy_numeric_type_uint32(self): self.assertTrue(isnumeric(np.uint32(1)), "Unsigned integer (0 to 4294967295)") @unittest.skipUnless(NUMPY_AVAILABLE, "Skipped because it needs NumPy") def test_numpy_numeric_type_uint64(self): self.assertTrue(isnumeric(np.uint64(1)), "Unsigned integer (0 to 18446744073709551615)") @unittest.skipUnless(NUMPY_AVAILABLE, "Skipped because it needs NumPy") def test_numpy_numeric_type_float(self): self.assertTrue(isnumeric(np.float_(1)), "Shorthand for float64.") @unittest.skipUnless(NUMPY_AVAILABLE, "Skipped because it needs NumPy") def test_numpy_numeric_type_float16(self): self.assertTrue( isnumeric(np.float16(1)), "Half precision float: sign bit, 5 bits exponent, 10 bits mantissa", ) @unittest.skipUnless(NUMPY_AVAILABLE, "Skipped because it needs NumPy") def test_numpy_numeric_type_float32(self): self.assertTrue( isnumeric(np.float32(1)), "Single precision float: sign bit, 8 bits exponent, 23 bits mantissa", ) @unittest.skipUnless(NUMPY_AVAILABLE, "Skipped because it needs NumPy") def test_numpy_numeric_type_float64(self): self.assertTrue( isnumeric(np.float64(1)), "Double precision float: sign bit, 11 bits exponent, 52 bits mantissa", ) @unittest.skipUnless(NUMPY_AVAILABLE, "Skipped because it needs NumPy") def test_numpy_numeric_type_complex(self): self.assertTrue(isnumeric(np.complex_(1)), "Shorthand for complex128.") @unittest.skipUnless(NUMPY_AVAILABLE, "Skipped because it needs NumPy") def test_numpy_numeric_type_complex64(self): self.assertTrue( isnumeric(np.complex64(1)), "Complex number, represented by two 32-bit floats (real and imaginary components)", ) @unittest.skipUnless(NUMPY_AVAILABLE, "Skipped because it needs NumPy") def test_numpy_numeric_type_complex128(self): self.assertTrue( isnumeric(np.complex128(1)), "Complex number, represented by two 64-bit floats (real and imaginary components)", ) if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/number/ordering_comparison_test.py000066400000000000000000000061271451524142100276100ustar00rootroot00000000000000if __name__ == "__main__": import sys sys.path.insert(0, "..") sys.path.insert(0, "../..") import unittest from datetime import date from hamcrest.library.number.ordering_comparison import ( greater_than, greater_than_or_equal_to, less_than, less_than_or_equal_to, ) from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class OrderingComparisonTest(MatcherTest): def testComparesObjectsForGreaterThan(self): self.assert_matches("match", greater_than(1), 2) self.assert_does_not_match("no match", greater_than(1), 1) def testComparesObjectsForLessThan(self): self.assert_matches("match", less_than(1), 0) self.assert_does_not_match("no match", less_than(1), 1) def testComparesObjectsForGreaterThanOrEqualTo(self): self.assert_matches("match", greater_than_or_equal_to(1), 2) self.assert_matches("match", greater_than_or_equal_to(1), 1) self.assert_does_not_match("no match", greater_than_or_equal_to(1), 0) def testComparesObjectsForLessThanOrEqualTo(self): self.assert_matches("match", less_than_or_equal_to(1), 0) self.assert_matches("match", less_than_or_equal_to(1), 1) self.assert_does_not_match("no match", less_than_or_equal_to(1), 2) def testSupportsDifferentTypesOfComparableObjects(self): self.assert_matches("strings", greater_than("bb"), "cc") self.assert_matches("dates", less_than(date.today()), date.min) def testHasAReadableDescription(self): self.assert_description("a value greater than <1>", greater_than(1)) self.assert_description("a value greater than or equal to <1>", greater_than_or_equal_to(1)) self.assert_description("a value less than <1>", less_than(1)) self.assert_description("a value less than or equal to <1>", less_than_or_equal_to(1)) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(greater_than(1), 2) self.assert_no_mismatch_description(less_than(1), 0) self.assert_no_mismatch_description(greater_than_or_equal_to(1), 1) self.assert_no_mismatch_description(less_than_or_equal_to(1), 1) def testMismatchDescription(self): self.assert_mismatch_description("was <0>", greater_than(1), 0) self.assert_mismatch_description("was <2>", less_than(1), 2) self.assert_mismatch_description("was <0>", greater_than_or_equal_to(1), 0) self.assert_mismatch_description("was <2>", less_than_or_equal_to(1), 2) def testDescribeMismatch(self): self.assert_describe_mismatch("was <0>", greater_than(1), 0) self.assert_describe_mismatch("was <2>", less_than(1), 2) self.assert_describe_mismatch("was <0>", greater_than_or_equal_to(1), 0) self.assert_describe_mismatch("was <2>", less_than_or_equal_to(1), 2) def testIncomparableTypes(self): self.assert_does_not_match("incomparable types", greater_than(1), "a") if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/object/000077500000000000000000000000001451524142100221045ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/hamcrest_unit_test/object/__init__.py000066400000000000000000000000001451524142100242030ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/hamcrest_unit_test/object/haslength_test.py000066400000000000000000000045161451524142100255000ustar00rootroot00000000000000if __name__ == "__main__": import sys sys.path.insert(0, "..") sys.path.insert(0, "../..") import unittest from hamcrest.core.core.isequal import equal_to from hamcrest.library.number.ordering_comparison import greater_than from hamcrest.library.object.haslength import has_length from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class FakeWithLen(object): def __init__(self, len): self.len = len def __len__(self): return self.len def __str__(self): return "FakeWithLen" class FakeWithoutLen(object): def __str__(self): return "FakeWithoutLen" class HasLengthTest(MatcherTest): def testPassesResultOfLenToNestedMatcher(self): self.assert_matches("equal", has_length(equal_to(42)), FakeWithLen(42)) self.assert_does_not_match("unequal", has_length(equal_to(42)), FakeWithLen(1)) def testProvidesConvenientShortcutForHasLengthEqualTo(self): self.assert_matches("equal", has_length(42), FakeWithLen(42)) self.assert_does_not_match("unequal", has_length(42), FakeWithLen(1)) def testDoesNotMatchObjectWithoutLen(self): self.assert_does_not_match("no length", has_length(42), object()) def testHasReadableDescription(self): self.assert_description( "an object with length of a value greater than <5>", has_length(greater_than(5)) ) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(has_length(3), "foo") def testMismatchDescriptionForItemWithWrongLength(self): self.assert_mismatch_description( "was with length of <4>", has_length(3), FakeWithLen(4) ) def testMismatchDescriptionForItemWithoutLength(self): self.assert_mismatch_description("was ", has_length(3), FakeWithoutLen()) def testDescribeMismatchForItemWithWrongLength(self): self.assert_describe_mismatch( "was with length of <4>", has_length(3), FakeWithLen(4) ) def testDescribeMismatchForItemWithoutLength(self): self.assert_describe_mismatch("was ", has_length(3), FakeWithoutLen()) if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/object/hasproperty_test.py000066400000000000000000000126011451524142100260750ustar00rootroot00000000000000if __name__ == "__main__": import sys sys.path.insert(0, "..") sys.path.insert(0, "../..") import unittest from hamcrest import greater_than from hamcrest.library.object.hasproperty import has_properties, has_property from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Chris Rose" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class OnePropertyOldStyle: field = "value" field2 = "value2" class ThreePropertiesNewStyle(object): field = "value" field2 = "value2" field3 = "value3" def __repr__(self): return "ThreePropertiesNewStyle" def __str__(self): return repr(self) class OverridingOldStyle: def __getattr__(self, name): if name == "field": return "value" if name == "field2": return "value2" raise AttributeError(name) class OverridingNewStyleGetAttr(object): def __getattr__(self, name): if name == "field": return "value" if name == "field2": return "value2" raise AttributeError(name) class OverridingNewStyleGetAttribute(object): def __getattribute__(self, name): if name == "field": return "value" if name == "field2": return "value2" raise AttributeError(name) class ObjectPropertyMatcher(object): match_sets = ( ("old-style: %s", OnePropertyOldStyle), ("new-style: %s", ThreePropertiesNewStyle), ("old-style, overriding: %s", OverridingOldStyle), ("new-style, using getattr: %s", OverridingNewStyleGetAttr), ("new-style, using getattribute: %s", OverridingNewStyleGetAttribute), ) def assert_matches_for_all_types(self, description, matcher): for description_fmt, target_class in self.match_sets: self.assert_matches(description_fmt % description, matcher, target_class()) def assert_does_not_match_for_all_types(self, description, matcher): for description_fmt, target_class in self.match_sets: self.assert_does_not_match(description_fmt % description, matcher, target_class()) class HasPropertyTest(MatcherTest, ObjectPropertyMatcher): def testHasPropertyWithoutValueMatcher(self): self.assert_matches_for_all_types("has property with name", has_property("field")) def testHasPropertyWithoutValueMatcherNegative(self): self.assert_does_not_match_for_all_types( "has property with name", has_property("not_there") ) def testHasPropertyWithValueMatcher(self): self.assert_matches_for_all_types( "has property with name and value", has_property("field", "value") ) def testHasPropertyWithValueMatcherNegative(self): self.assert_does_not_match_for_all_types( "has property with name", has_property("field", "not the value") ) def testDescription(self): self.assert_description( "an object with a property 'field' matching ANYTHING", has_property("field") ) self.assert_description( "an object with a property 'field' matching 'value'", has_property("field", "value") ) def testDescribeMissingProperty(self): self.assert_mismatch_description( " did not have the 'not_there' property", has_property("not_there"), ThreePropertiesNewStyle(), ) def testDescribePropertyValueMismatch(self): self.assert_mismatch_description( "property 'field' was 'value'", has_property("field", "another_value"), ThreePropertiesNewStyle(), ) def testMismatchDescription(self): self.assert_describe_mismatch( " did not have the 'not_there' property", has_property("not_there"), ThreePropertiesNewStyle(), ) def testNoMismatchDescriptionOnMatch(self): self.assert_no_mismatch_description( has_property("field", "value"), ThreePropertiesNewStyle() ) class HasPropertiesTest(MatcherTest, ObjectPropertyMatcher): def testMatcherCreationRequiresEvenNumberOfPositionalArguments(self): self.assertRaises(ValueError, has_properties, "a", "b", "c") def testMatchesUsingSingleDictionaryArgument(self): # import pdb; pdb.set_trace() self.assert_matches_for_all_types( "matches using a single-argument dictionary", has_properties({"field": "value", "field2": "value2"}), ) def testMatchesUsingKeywordArguments(self): self.assert_matches_for_all_types( "matches using a kwarg dict", has_properties(field="value", field2="value2") ) def testMismatchDescription(self): self.assert_describe_mismatch( "property 'field' was 'value' and property 'field3' was 'value3'", has_properties(field="different", field2="value2", field3="alsodifferent"), ThreePropertiesNewStyle(), ) def testDescription(self): self.assert_description("an object with a property 'a' matching <1>", has_properties(a=1)) self.assert_description( "an object with properties 'a' matching <1> " "and 'b' matching a value greater than <2>", has_properties(a=1, b=greater_than(2)), ) if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/object/hasstring_test.py000066400000000000000000000030321451524142100255150ustar00rootroot00000000000000if __name__ == "__main__": import sys sys.path.insert(0, "..") sys.path.insert(0, "../..") import unittest from hamcrest.core.core.isequal import equal_to from hamcrest.library.object.hasstring import has_string from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class FakeWithStr(object): def __str__(self): return "FakeWithStr" class HasStringTest(MatcherTest): def testPassesResultOfToStrToNestedMatcher(self): self.assert_matches("equal", has_string(equal_to("FakeWithStr")), FakeWithStr()) self.assert_does_not_match("unequal", has_string(equal_to("FakeWithStr")), 3) def testProvidesConvenientShortcutForHasStringEqualTo(self): self.assert_matches("equal", has_string("FakeWithStr"), FakeWithStr()) self.assert_does_not_match("unequal", has_string("FakeWithStr"), 3) def testHasReadableDescription(self): self.assert_description("an object with str 'foo'", has_string("foo")) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(has_string("FakeWithStr"), FakeWithStr()) def testMismatchDescription(self): self.assert_mismatch_description("was ", has_string("foo"), FakeWithStr()) def testDescribeMismatchDescription(self): self.assert_describe_mismatch("was ", has_string("foo"), FakeWithStr()) if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/string_description_test.py000066400000000000000000000035531451524142100261660ustar00rootroot00000000000000import re import unittest import pytest from hamcrest.core.selfdescribing import SelfDescribing from hamcrest.core.string_description import StringDescription __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" class FakeSelfDescribing(SelfDescribing): def describe_to(self, description): description.append_text("DESCRIPTION") class StringDescriptionTest(unittest.TestCase): def setUp(self): self.description = StringDescription() def testLetsSelfDescribingObjectDescribeItself(self): self.description.append_description_of(FakeSelfDescribing()) self.assertEqual("DESCRIPTION", str(self.description)) def testDescribesStringInQuotes(self): self.description.append_description_of("FOO") self.assertEqual("'FOO'", str(self.description)) def testWrapsNonSelfDescribingObjectInAngleBrackets(self): self.description.append_description_of(42) self.assertEqual("<42>", str(self.description)) def testShouldNotAddAngleBracketsIfObjectDescriptionAlreadyHasThem(self): self.description.append_description_of(object()) expected = re.compile("") self.assertTrue(expected.match(str(self.description))) def testDescribeUnicodeStringAsUnicode(self): self.description.append_description_of("\u05d0") self.assertEqual("'\u05d0'", str(self.description)) # below is a set of things that should append without error to string # descriptions @pytest.mark.parametrize("valid_input", (b"bytes", "unicode")) def test_description_append_valid_input(valid_input): desc = StringDescription() desc.append(valid_input) str(desc) def test_description_append_invalid_input(): desc = StringDescription() desc.append(chr(239)) if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/text/000077500000000000000000000000001451524142100216225ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/hamcrest_unit_test/text/__init__.py000066400000000000000000000000001451524142100237210ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/hamcrest_unit_test/text/isequal_ignoring_case_test.py000066400000000000000000000030561451524142100275710ustar00rootroot00000000000000import unittest from hamcrest.library.text.isequal_ignoring_case import equal_to_ignoring_case from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" matcher = equal_to_ignoring_case("heLLo") class IsEqualIgnoringCaseTest(MatcherTest): def testIgnoresCaseOfCharsInString(self): self.assert_matches("all upper", matcher, "HELLO") self.assert_matches("all lower", matcher, "hello") self.assert_matches("mixed up", matcher, "HelLo") self.assert_does_not_match("no match", matcher, "bye") def testFailsIfAdditionalWhitespaceIsPresent(self): self.assert_does_not_match("whitespace suffix", matcher, "heLLo ") self.assert_does_not_match("whitespace prefix", matcher, " heLLo") def testMatcherCreationRequiresString(self): self.assertRaises(TypeError, equal_to_ignoring_case, 3) def testFailsIfMatchingAgainstNonString(self): self.assert_does_not_match("non-string", matcher, object()) def testHasAReadableDescription(self): self.assert_description("'heLLo' ignoring case", matcher) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(matcher, "hello") def testMismatchDescription(self): self.assert_mismatch_description("was 'bad'", matcher, "bad") def testDescribeMismatch(self): self.assert_describe_mismatch("was 'bad'", matcher, "bad") if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/text/isequal_ignoring_whitespace_test.py000066400000000000000000000037741451524142100310210ustar00rootroot00000000000000import unittest from hamcrest.library.text.isequal_ignoring_whitespace import equal_to_ignoring_whitespace from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" matcher = equal_to_ignoring_whitespace("Hello World how\n are we? ") class IsEqualIgnoringWhiteSpaceTest(MatcherTest): def testPassesIfWordsAreSameButWhitespaceDiffers(self): self.assert_matches("less whitespace", matcher, "Hello World how are we?") self.assert_matches("more whitespace", matcher, " Hello World how are \n\n\twe?") def testFailsIfTextOtherThanWhitespaceDiffers(self): self.assert_does_not_match("wrong word", matcher, "Hello PLANET how are we?") self.assert_does_not_match("incomplete", matcher, "Hello World how are we") def testFailsIfWhitespaceIsAddedOrRemovedInMidWord(self): self.assert_does_not_match( "need whitespace between Hello and World", matcher, "HelloWorld how are we?" ) self.assert_does_not_match( "wrong whitespace within World", matcher, "Hello Wo rld how are we?" ) def testMatcherCreationRequiresString(self): self.assertRaises(TypeError, equal_to_ignoring_whitespace, 3) def testFailsIfMatchingAgainstNonString(self): self.assert_does_not_match("non-string", matcher, object()) def testDescribesItselfAsIgnoringWhiteSpace(self): self.assert_description( "'foo\\nbar' ignoring whitespace", equal_to_ignoring_whitespace("foo\nbar") ) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(equal_to_ignoring_whitespace("foo\nbar"), "foo bar") def testMismatchDescription(self): self.assert_mismatch_description("was 'bad'", matcher, "bad") def testDescribeMismatch(self): self.assert_describe_mismatch("was 'bad'", matcher, "bad") if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/text/stringcontains_test.py000066400000000000000000000034561451524142100263100ustar00rootroot00000000000000import pytest from hamcrest.library.text.stringcontains import contains_string from hamcrest_unit_test.matcher_test import ( assert_description, assert_does_not_match, assert_matches, assert_mismatch_description, assert_no_mismatch_description, ) __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" matcher_args = ("EXCERPT",) @pytest.fixture(scope="module", params=matcher_args) def matcher(request): return contains_string(request.param) TEST_MATCHING_STRINGS = ( ("EXCERPTEND",), ("STARTEXCERPTEND",), ("STARTEXCERPT",), ("EXCERPTEXCERPT",), ("EXCERPT",), ) TEST_MISMATCHING_STRINGS = (("whatever",), ("EXCERP",), (object(),)) @pytest.mark.parametrize(["text"], TEST_MATCHING_STRINGS) def test_evaluates_true_if_argument_contains_substring(text, matcher): assert_matches(matcher, text, "assert that %s matches %s" % (text, matcher)) @pytest.mark.parametrize(["text"], TEST_MISMATCHING_STRINGS) def test_evaluates_false_with_mismatch(text, matcher): assert_does_not_match(matcher, text, "%s was not in string %s" % (matcher, text)) def testMatcherCreationRequiresString(): with pytest.raises(TypeError): contains_string(3) def test_description(matcher): assert_description("a string containing 'EXCERPT'", matcher) def test_successful_match_does_not_have_mismatch_description(matcher): assert_no_mismatch_description(matcher, "EXCERPT") @pytest.mark.parametrize(["text"], TEST_MISMATCHING_STRINGS) def test_mismatch_description(matcher, text): if isinstance(text, str): check_str = "'%s'" % text else: check_str = "%s" % text assert_mismatch_description("was %s" % check_str, matcher, text) if __name__ == "__main__": import unittest unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/text/stringcontainsinorder_test.py000066400000000000000000000035711451524142100276710ustar00rootroot00000000000000from hamcrest.library.text import string_contains_in_order from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Romilly Cocking" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" matcher = string_contains_in_order("string one", "string two", "string three") class StringContainsInOrderTest(MatcherTest): def testMatchesIfOrderIsCorrect(self): self.assert_matches( "correct order", matcher, "string one then string two followed by string three" ) def testDoesNotMatchIfOrderIsIncorrect(self): self.assert_does_not_match( "incorrect order", matcher, "string two then string one followed by string three" ) def testDoesNotMatchIfExpectedSubstringsAreMissing(self): self.assert_does_not_match("missing string one", matcher, "string two then string three") self.assert_does_not_match("missing string two", matcher, "string one then string three") self.assert_does_not_match("missing string three", matcher, "string one then string two") def testMatcherCreationRequiresString(self): self.assertRaises(TypeError, string_contains_in_order, 3) def testFailsIfMatchingAgainstNonString(self): self.assert_does_not_match("non-string", matcher, object()) def testHasAReadableDescription(self): self.assert_description( "a string containing 'string one', 'string two', 'string three' in order", matcher ) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description( matcher, "string one then string two followed by string three" ) def testMismatchDescription(self): self.assert_mismatch_description("was 'bad'", matcher, "bad") def testDescribeMismatch(self): self.assert_describe_mismatch("was 'bad'", matcher, "bad") PyHamcrest-2.1.0/tests/hamcrest_unit_test/text/stringendswith_test.py000066400000000000000000000033721451524142100263140ustar00rootroot00000000000000import unittest from hamcrest.library.text.stringendswith import ends_with from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" EXCERPT = "EXCERPT" matcher = ends_with(EXCERPT) class StringEndsWithTest(MatcherTest): def testEvaluatesToTrueIfArgumentContainsSpecifiedSubstring(self): self.assert_does_not_match("excerpt at beginning", matcher, EXCERPT + "END") self.assert_matches("excerpt at end", matcher, "START" + EXCERPT) self.assert_does_not_match("excerpt in middle", matcher, "START" + EXCERPT + "END") self.assert_matches("excerpt repeated", matcher, EXCERPT + EXCERPT) self.assert_does_not_match("excerpt not in string", matcher, "whatever") self.assert_does_not_match("only part of excerpt is at end of string", matcher, EXCERPT[1:]) def testEvaluatesToTrueIfArgumentIsEqualToSubstring(self): self.assert_matches("excerpt is entire string", matcher, EXCERPT) def testMatcherCreationRequiresString(self): self.assertRaises(TypeError, ends_with, 3) def testFailsIfMatchingAgainstNonString(self): self.assert_does_not_match("non-string", matcher, object()) def testHasAReadableDescription(self): self.assert_description("a string ending with 'EXCERPT'", matcher) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(matcher, EXCERPT) def testMismatchDescription(self): self.assert_mismatch_description("was 'bad'", matcher, "bad") def testDescribeMismatch(self): self.assert_describe_mismatch("was 'bad'", matcher, "bad") if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/text/stringmatches_test.py000066400000000000000000000043071451524142100261120ustar00rootroot00000000000000if __name__ == "__main__": import sys sys.path.insert(0, "..") sys.path.insert(0, "../..") import re import unittest from hamcrest.library.text.stringmatches import matches_regexp from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Chris Rose" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" string_matcher = matches_regexp(r"--[a-z]+--") compiled_matcher = matches_regexp(re.compile(r"--[a-z]+--")) class StringMatchesTest(MatcherTest): def testMatchesWhenPatternIsFoundAtBeginning(self): self.assert_matches("pattern at beginning", string_matcher, "--a-----") def testMatchesWhenPatternIsFoundAtEnd(self): self.assert_matches("pattern at end", string_matcher, "-----a--") def testMatchesWhenPatternIsFoundInMiddle(self): self.assert_matches("pattern in the middle", string_matcher, "-----a-----") def testMismatchesWhenPatternIsNotPresent(self): self.assert_does_not_match("pattern nowhere", string_matcher, "--0--") def testMatchesUsingCompiledExpressions(self): self.assert_matches("pattern nowhere", compiled_matcher, "--a--") def testMismatchesUsingCompiledExpressions(self): self.assert_does_not_match("pattern nowhere", compiled_matcher, "--0--") def testStringHasAReadableDescription(self): self.assert_description("a string matching '--[a-z]+--'", string_matcher) def testPatternHasAReadableDescription(self): self.assert_description("a string matching '--[a-z]+--'", compiled_matcher) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(string_matcher, "--a--") def testStringMismatchDescription(self): self.assert_mismatch_description("was 'bad'", string_matcher, "bad") def testCompiledMismatchDescription(self): self.assert_mismatch_description("was 'bad'", compiled_matcher, "bad") def testStringDescribeMismatch(self): self.assert_describe_mismatch("was 'bad'", string_matcher, "bad") def testCompiledDescribeMismatch(self): self.assert_describe_mismatch("was 'bad'", compiled_matcher, "bad") if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/hamcrest_unit_test/text/stringstartswith_test.py000066400000000000000000000034321451524142100267000ustar00rootroot00000000000000import unittest from hamcrest.library.text.stringstartswith import starts_with from hamcrest_unit_test.matcher_test import MatcherTest __author__ = "Jon Reid" __copyright__ = "Copyright 2011 hamcrest.org" __license__ = "BSD, see License.txt" EXCERPT = "EXCERPT" matcher = starts_with(EXCERPT) stringstartswith = starts_with(EXCERPT) class StringStartsWithTest(MatcherTest): def testEvaluatesToTrueIfArgumentContainsSpecifiedSubstring(self): self.assert_matches("excerpt at beginning", matcher, EXCERPT + "END") self.assert_does_not_match("excerpt at end", matcher, "START" + EXCERPT) self.assert_does_not_match("excerpt in middle", matcher, "START" + EXCERPT + "END") self.assert_matches("excerpt repeated", matcher, EXCERPT + EXCERPT) self.assert_does_not_match("excerpt not in string", matcher, "whatever") self.assert_does_not_match("only part of excerpt", matcher, EXCERPT[1:]) def testEvaluatesToTrueIfArgumentIsEqualToSubstring(self): self.assert_matches("excerpt is entire string", matcher, EXCERPT) def testMatcherCreationRequiresString(self): self.assertRaises(TypeError, starts_with, 3) def testFailsIfMatchingAgainstNonString(self): self.assert_does_not_match("non-string", matcher, object()) def testHasAReadableDescription(self): self.assert_description("a string starting with 'EXCERPT'", matcher) def testSuccessfulMatchDoesNotGenerateMismatchDescription(self): self.assert_no_mismatch_description(matcher, EXCERPT) def testMismatchDescription(self): self.assert_mismatch_description("was 'bad'", matcher, "bad") def testDescribeMismatch(self): self.assert_describe_mismatch("was 'bad'", matcher, "bad") if __name__ == "__main__": unittest.main() PyHamcrest-2.1.0/tests/object_import.py000066400000000000000000000002421451524142100201420ustar00rootroot00000000000000try: class MyTest(object): pass except TypeError: print("Object class defined at {0}".format(getattr(object, "__file__", "NOWHERE"))) raise PyHamcrest-2.1.0/tests/type-hinting/000077500000000000000000000000001451524142100173515ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/type-hinting/core/000077500000000000000000000000001451524142100203015ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/type-hinting/core/core/000077500000000000000000000000001451524142100212315ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/type-hinting/core/core/test_is.yml000066400000000000000000000006271451524142100234330ustar00rootroot00000000000000- case: is # pypy + mypy doesn't work. See https://foss.heptapod.net/pypy/pypy/-/issues/3526 skip: platform.python_implementation() == "PyPy" main: | from hamcrest import assert_that, is_, empty from typing import Any, Sequence a: Sequence[Any] = [] b = 99 assert_that(a, is_(empty())) assert_that(b, is_(empty())) # E: Cannot infer type argument 1 of "assert_that" [misc] PyHamcrest-2.1.0/tests/type-hinting/core/test_assert_that.yml000066400000000000000000000006661451524142100244140ustar00rootroot00000000000000- case: assert_that # pypy + mypy doesn't work. See https://foss.heptapod.net/pypy/pypy/-/issues/3526 skip: platform.python_implementation() == "PyPy" main: | from hamcrest import assert_that, instance_of, starts_with assert_that("string", starts_with("str")) assert_that("str", instance_of(str)) assert_that(99, starts_with("str")) out: | main:5: error: Cannot infer type argument 1 of "assert_that" [misc] PyHamcrest-2.1.0/tests/type-hinting/library/000077500000000000000000000000001451524142100210155ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/type-hinting/library/collection/000077500000000000000000000000001451524142100231505ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/type-hinting/library/collection/test_empty.yml000066400000000000000000000005071451524142100260720ustar00rootroot00000000000000- case: empty # pypy + mypy doesn't work. See https://foss.heptapod.net/pypy/pypy/-/issues/3526 skip: platform.python_implementation() == "PyPy" main: | from hamcrest import assert_that, is_, empty assert_that([], empty()) assert_that(99, empty()) # E: Cannot infer type argument 1 of "assert_that" [misc] PyHamcrest-2.1.0/tests/type-hinting/library/collection/test_generics.yml000066400000000000000000000013651451524142100265360ustar00rootroot00000000000000- case: valid_has_items_has_properties skip: platform.python_implementation() == "PyPy" main: | from dataclasses import dataclass from hamcrest import assert_that, has_items, has_properties @dataclass class Example: name: str items = [Example("dave"), Example("wave")] a = assert_that(items, has_items(has_properties(name="dave"))) - case: valid_has_item_has_properties skip: platform.python_implementation() == "PyPy" main: | from dataclasses import dataclass from hamcrest import assert_that, has_item, has_properties @dataclass class Example: name: str items = [Example("dave"), Example("wave")] matcher = has_item(has_properties(name="dave")) a = assert_that(items, matcher) PyHamcrest-2.1.0/tests/type-hinting/library/text/000077500000000000000000000000001451524142100220015ustar00rootroot00000000000000PyHamcrest-2.1.0/tests/type-hinting/library/text/test_equal_to_ignoring_case.yml000066400000000000000000000010271451524142100302630ustar00rootroot00000000000000- case: equal_to_ignoring_case # pypy + mypy doesn't work. See https://foss.heptapod.net/pypy/pypy/-/issues/3526 skip: platform.python_implementation() == "PyPy" main: | from hamcrest import equal_to_ignoring_case reveal_type(equal_to_ignoring_case("")) equal_to_ignoring_case("") equal_to_ignoring_case(99) out: | main:3: note: Revealed type is "hamcrest.core.matcher.Matcher[builtins.str]" main:5: error: Argument 1 to "equal_to_ignoring_case" has incompatible type "int"; expected "str" [arg-type] PyHamcrest-2.1.0/tox.ini000066400000000000000000000104561451524142100151110ustar00rootroot00000000000000[pytest] addopts = -ra testpaths = tests xfail_strict = true filterwarnings = once::Warning ignore:::pympler[.*] looponfailroots = src tests # Keep docs in sync with docs env and .readthedocs.yml. [gh-actions] python = 3.7: py37, py37-numpy 3.8: py38, py38-numpy 3.9: py39, py39-numpy, lint, manifest, typing, changelog, docs 3.10: py310 3.11: py311 pypy-2: pypy2 pypy-3: pypy3 [tox] envlist = typing,lint,py37{,-numpy},py38{,-numpy},py39{,-numpy},py310{,-numpy},pypy{,-numpy},pypy3{,-numpy},manifest,docs,pypi-description,changelog,coverage-report isolated_build = True [testenv] # Prevent random setuptools/pip breakages like # https://github.com/pypa/setuptools/issues/1042 from breaking our builds. setenv = VIRTUALENV_NO_DOWNLOAD=1 extras = {env:TOX_AP_TEST_EXTRAS:tests} commands = python -m pytest {posargs} [testenv:py37-numpy] extras = tests-numpy commands = python -m pytest {posargs} [testenv:py38-numpy] extras = tests-numpy commands = python -m pytest {posargs} [testenv:py39-numpy] extras = tests-numpy commands = python -m pytest {posargs} [testenv:py37] # Python 3.6+ has a number of compile-time warnings on invalid string escapes. # PYTHONWARNINGS=d and --no-compile below make them visible during the Tox run. install_command = pip install --no-compile {opts} {packages} setenv = PYTHONWARNINGS=d extras = {env:TOX_AP_TEST_EXTRAS:tests} commands = coverage run -m pytest {posargs} [testenv:py38] # Python 3.6+ has a number of compile-time warnings on invalid string escapes. # PYTHONWARNINGS=d and --no-compile below make them visible during the Tox run. basepython = python3.8 install_command = pip install --no-compile {opts} {packages} setenv = PYTHONWARNINGS=d extras = {env:TOX_AP_TEST_EXTRAS:tests} commands = coverage run -m pytest {posargs} [testenv:py39] # Python 3.6+ has a number of compile-time warnings on invalid string escapes. # PYTHONWARNINGS=d and --no-compile below make them visible during the Tox run. basepython = python3.9 install_command = pip install --no-compile {opts} {packages} setenv = PYTHONWARNINGS=d extras = {env:TOX_AP_TEST_EXTRAS:tests} commands = coverage run -m pytest {posargs} [testenv:py310] # Python 3.6+ has a number of compile-time warnings on invalid string escapes. # PYTHONWARNINGS=d and --no-compile below make them visible during the Tox run. basepython = python3.10 install_command = pip install --no-compile {opts} {packages} setenv = PYTHONWARNINGS=d extras = {env:TOX_AP_TEST_EXTRAS:tests} commands = coverage run -m pytest {posargs} [testenv:py311] # Python 3.6+ has a number of compile-time warnings on invalid string escapes. # PYTHONWARNINGS=d and --no-compile below make them visible during the Tox run. basepython = python3.11 install_command = pip install --no-compile {opts} {packages} setenv = PYTHONWARNINGS=d extras = {env:TOX_AP_TEST_EXTRAS:tests} commands = coverage run -m pytest {posargs} [testenv:coverage-report] basepython = python3.11 skip_install = true deps = coverage[toml]>=5.0.2 commands = coverage combine coverage report [testenv:lint] basepython = python3.11 skip_install = true deps = pre-commit passenv = HOMEPATH # needed on Windows commands = pre-commit run --all-files [testenv:docs] # Keep basepython in sync with gh-actions and .readthedocs.yml. basepython = python3.11 extras = docs commands = sphinx-build -n -T -b html -d {envtmpdir}/doctrees doc doc/_build/html [testenv:manifest] basepython = python3.9 deps = check-manifest setuptools-scm skip_install = true commands = check-manifest --ignore src/hamcrest/_version.py [testenv:pypi-description] basepython = python3.9 skip_install = true deps = twine pip >= 18.0.0 commands = pip wheel -w {envtmpdir}/build --no-deps . twine check {envtmpdir}/build/* [testenv:changelog] basepython = python3.9 deps = towncrier importlib_resources<6 # TODO: remove once twisted/towncrier#528 is released skip_install = true commands = towncrier --draft [testenv:typing] basepython = python3.9 deps = mypy types-mock commands = mypy src/ [flake8] max-complexity = 15 max-line-length = 100 show-source = True enable-extensions = M,B,C,T,P ignore = C812,W503,P103,E1,E2,E3,E5 statistics = True per-file-ignores = src/*/__init__.py:F401,F403,F405 src/hamcrest/__init__.py:F401,F403