Metadata-Version: 2.1
Name: pook
Version: 1.2.1
Summary: HTTP traffic mocking and expectations made easy
Home-page: https://github.com/h2non/pook
Author: Tomas Aparicio
Author-email: tomas@aparicio.me
License: MIT
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: OS Independent
Classifier: Development Status :: 5 - Production/Stable
Classifier: Natural Language :: English
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Software Development
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Description-Content-Type: text/x-rst
License-File: LICENSE
Requires-Dist: jsonschema>=2.5.1
Requires-Dist: xmltodict>=0.11.0
Requires-Dist: furl>=0.5.6

pook |PyPI| |Coverage Status| |Documentation Status| |Stability| |Quality| |Versions|
=====================================================================================

Versatile, expressive and hackable utility library for HTTP traffic mocking
and expectations made easy in `Python`_. Heavily inspired by `gock`_.

To get started, read the `documentation`_, `how it works`_, `FAQ`_ or `examples`_.

Features
--------

-  Simple, expressive and fluent API.
-  Provides both Pythonic and chainable DSL API styles.
-  Full-featured HTTP response definitions and expectations.
-  Matches any HTTP protocol primitive (URL, method, query params, headers, body...).
-  Full regular expressions capable mock expectations matching.
-  Supports most popular HTTP clients via interceptor adapters.
-  Configurable volatile, persistent or TTL limited mocks.
-  Works with any testing framework/engine (unittest, pytest, nosetests...).
-  First-class JSON & XML support matching and responses.
-  Supports JSON Schema body matching.
-  Works in both runtime and testing environments.
-  Can be used as decorator and/or via context managers.
-  Supports real networking mode with optional traffic filtering.
-  Map/filter mocks easily for generic or custom mock expectations.
-  Custom user-defined mock matcher functions.
-  Simulated raised error exceptions.
-  Network delay simulation (only available for ``aiohttp``).
-  Pluggable and hackable API.
-  Customizable HTTP traffic mock interceptor engine.
-  Supports third-party mocking engines, such as `mocket`_.
-  Fits good for painless test doubles.
-  Does not support WebSocket traffic mocking.
-  Works with +3.6 (including PyPy).
-  Dependency-less: just 3 small dependencies for JSONSchema, XML tree comparison, and URL parsing.


Supported HTTP clients
----------------------

``pook`` can work with multiple mock engines, however it provides a
built-in one by default, which currently supports traffic mocking in
the following HTTP clients:

-  ✔  `urllib3`_ v1+
-  ✔  `requests`_ v2+
-  ✔  `aiohttp`_ v1+ - v2+
-  ✔  `urllib`_ / `http.client`_ v2/3
-  ✘  `pycurl`_ (see `#16`_)

More HTTP clients can be supported progressively.

**Note**: only recent HTTP client package versions were tested.

Installation
------------

Using ``pip`` package manager (requires pip 1.8+):

.. code:: bash

    pip install --upgrade pook

Or install the latest sources from Github:

.. code:: bash

    pip install -e git+git://github.com/h2non/pook.git#egg=pook


Getting started
---------------

See ReadTheDocs documentation:

|Documentation Status|


API
---

See `annotated API reference`_ documention.


Examples
--------

See `examples`_ documentation for full featured code and use case examples.

Basic mocking:

.. code:: python

    import pook
    import requests

    @pook.on
    def test_my_api():
        mock = pook.get('http://twitter.com/api/1/foobar', reply=404, response_json={'error': 'not found'})

        resp = requests.get('http://twitter.com/api/1/foobar')
        assert resp.status_code == 404
        assert resp.json() == {"error": "not found"}
        assert mock.calls == 1

Using the chainable API DSL:

.. code:: python

    import pook
    import requests

    @pook.on
    def test_my_api():
        mock = (pook.get('http://twitter.com/api/1/foobar')
                  .reply(404)
                  .json({'error': 'not found'}))

        resp = requests.get('http://twitter.com/api/1/foobar')
        assert resp.json() == {"error": "not found"}
        assert mock.calls == 1

Using the decorator:

.. code:: python

    import pook
    import requests

    @pook.get('http://httpbin.org/status/500', reply=204)
    @pook.get('http://httpbin.org/status/400', reply=200)
    def fetch(url):
        return requests.get(url)

    res = fetch('http://httpbin.org/status/400')
    print('#1 status:', res.status_code)

    res = fetch('http://httpbin.org/status/500')
    print('#2 status:', res.status_code)


Simple ``unittest`` integration:

.. code:: python

    import pook
    import unittest
    import requests


    class TestUnitTestEngine(unittest.TestCase):

        @pook.on
        def test_request(self):
            pook.get('server.com/foo').reply(204)
            res = requests.get('http://server.com/foo')
            self.assertEqual(res.status_code, 204)

        def test_request_with_context_manager(self):
            with pook.use():
                pook.get('server.com/bar', reply=204)
                res = requests.get('http://server.com/bar')
                self.assertEqual(res.status_code, 204)


Using the context manager for isolated HTTP traffic interception blocks:

.. code:: python

    import pook
    import requests

    # Enable HTTP traffic interceptor
    with pook.use():
        pook.get('http://httpbin.org/status/500', reply=204)

        res = requests.get('http://httpbin.org/status/500')
        print('#1 status:', res.status_code)

    # Interception-free HTTP traffic
    res = requests.get('http://httpbin.org/status/200')
    print('#2 status:', res.status_code)

Example using `mocket`_ Python library as underlying mock engine:

.. code:: python

    import pook
    import requests
    from mocket.plugins.pook_mock_engine import MocketEngine

    # Use mocket library as underlying mock engine
    pook.set_mock_engine(MocketEngine)

    # Explicitly enable pook HTTP mocking (optional)
    pook.on()

    # Target server URL to mock out
    url = 'http://twitter.com/api/1/foobar'

    # Define your mock
    mock = pook.get(url,
                    reply=404, times=2,
                    headers={'content-type': 'application/json'},
                    response_json={'error': 'foo'})

    # Run first HTTP request
    requests.get(url)
    assert mock.calls == 1

    # Run second HTTP request
    res = requests.get(url)
    assert mock.calls == 2

    # Assert response data
    assert res.status_code == 404
    assert res.json() == {'error': 'foo'}

    # Explicitly disable pook (optional)
    pook.off()


Example using Hy language (Lisp dialect for Python):

.. code:: hy

    (import [pook])
    (import [requests])

    (defn request [url &optional [status 404]]
      (doto (.mock pook url) (.reply status))
      (let [res (.get requests url)]
        (. res status_code)))

    (defn run []
      (with [(.use pook)]
        (print "Status:" (request "http://server.com/foo" :status 204))))

    ;; Run test program
    (defmain [&args] (run))


Development
-----------

Clone the repository:

.. code:: bash

    git clone git@github.com:h2non/pook.git


Install dependencies:

.. code:: bash

    pip install -r requirements.txt -r requirements-dev.txt


Install Python dependencies:

.. code:: bash

    make install


Lint code:

.. code:: bash

    make lint


Run tests:

.. code:: bash

    make test


Generate documentation:

.. code:: bash

    make htmldocs


License
-------

MIT - Tomas Aparicio

.. _Go: https://golang.org
.. _Python: http://python.org
.. _gock: https://github.com/h2non/gock
.. _annotated API reference: http://pook.readthedocs.io/en/latest/api.html
.. _#16: https://github.com/h2non/pook/issues/16
.. _examples: http://pook.readthedocs.io/en/latest/examples.html
.. _aiohttp: https://github.com/KeepSafe/aiohttp
.. _requests: http://docs.python-requests.org/en/master/
.. _urllib3: https://github.com/shazow/urllib3
.. _urllib: https://docs.python.org/3/library/urllib.html
.. _http.client: https://docs.python.org/3/library/http.client.html
.. _pycurl: http://pycurl.io
.. _documentation: http://pook.readthedocs.io/en/latest/
.. _FAQ: http://pook.readthedocs.io/en/latest/faq.html
.. _how it works: http://pook.readthedocs.io/en/latest/how_it_works.html
.. _mocket: https://github.com/mindflayer/python-mocket

.. |PyPI| image:: https://img.shields.io/pypi/v/pook.svg?maxAge=2592000?style=flat-square
   :target: https://pypi.python.org/pypi/pook
.. |Coverage Status| image:: https://coveralls.io/repos/github/h2non/pook/badge.svg?branch=master
   :target: https://coveralls.io/github/h2non/pook?branch=master
.. |Documentation Status| image:: https://img.shields.io/badge/docs-latest-green.svg?style=flat
   :target: http://pook.readthedocs.io/en/latest/?badge=latest
.. |Quality| image:: https://codeclimate.com/github/h2non/pook/badges/gpa.svg
   :target: https://codeclimate.com/github/h2non/pook
   :alt: Code Climate
.. |Stability| image:: https://img.shields.io/pypi/status/pook.svg
   :target: https://pypi.python.org/pypi/pook
   :alt: Stability
.. |Versions| image:: https://img.shields.io/pypi/pyversions/pook.svg
   :target: https://pypi.python.org/pypi/pook
   :alt: Python Versions



v1.2.1 / 2023-12-23
===================

  * Fix usage of regex values in header matchers (#97)
  * Fix urllib SSL handling (#98)

v1.2.0 / 2023-12-17
===================

  * feat(api): add support for binary bodies (#88)
  * fix(urllib3): don't put non-strings into HTTP header dict (#87)
  * refactor: drop Python 3.5 support (#92). Note: Python 3.5 had been supported for some time. The change here only makes the documentation accurately reflect that 3.5 is not supported.

v1.1.0 / 2023-01-01
===================

  * chore(version): bump minor v1.1.0
  * Switch to Python >= 3.5 and fix latest aiohttp compatability (#83)
  * fix: remove print call (#81)

v1.0.2 / 2021-09-10
===================

  * fix(urllib3): interceptor is never really disabled (#68)
  * Closes #75 Re consider @fluent decorator (#76)
  * fix(#69): use match keyword in pytest.raises
  * fix(History): invalid rst syntax

v1.0.1 / 2020-03-24
-------------------

  * fix(aiohttp): compatible with non aiohttp projects (#67)
  * feat(History): add release changes

v1.0.0 / 2020-03-18
-------------------

  * fix(aiohttp): use latest version, allow Python 3.5+ for async http client

v0.2.8 / 2019-10-31
-------------------

  * fix collections import warning (#61)

v0.2.7 / 2019-10-21
-------------------

  * fix collections import warning (#61)

v0.2.6 / 2019-02-01
-------------------

  * Add mock.reply(new_response=True) to reset response definition object

v0.2.5 / 2017-10-19
-------------------

  * refactor(setup): remove extra install dependency
  * Fix py27 compatibility (#49)
  * Add activate_async decorator (#48)
  * fix typo in pook.mock.Mock.ismatched.__doc__ (#47)
  * fix README example (#46)

v0.2.4 / 2017-10-03
-------------------

* fix(#45): regex URL issue
* fix(travis): allow failures in pypy
* feat(docs): add sponsor banner
* refactor(History): normalize style

v0.2.3 / 2017-04-28
-------------------

* feat(docs): add supported version for aiohttp
* Merge branch 'master' of https://github.com/h2non/pook
* fix(api): export missing symbol "disable_network"
* Update README.rst (#43)

v0.2.2 / 2017-04-03
-------------------

* refactor(compare): disable maxDiff length limit while comparing values

v0.2.1 / 2017-03-25
-------------------

* fix(engine): enable new mock engine on register if needed
* fix(engine): remove activate argument before instantiating the Mock

v0.2.0 / 2017-03-18
-------------------

* refactor(engine): do not activate engine on mock declaration if not explicitly requested. This introduces a behavioral library change: you must explicitly use ``pook.on()`` to enable `pook` mock engine.

v0.1.14 / 2017-03-17
--------------------

* feat(docs): list supported HTTP client versions
* fix(#41): disable mocks after decorator call invokation
* feat(examples): add mock context manager example file
* feat(#40): support context manager definitions
* feat(#39): improve unmatched request output
* feat(docs): add mocket example file
* feat(#33): add mocket examples and documentation

v0.1.13 / 2017-01-29
--------------------

* fix(api): `mock.calls` property should be an `int`.

v0.1.12 / 2017-01-28
--------------------

* feat(#33): proxy mock definitions into mock.Request
* refactor(api): `pook.unmatched_requests()` now returns a `list` instead of a lazy `tuple`.

v0.1.11 / 2017-01-14
--------------------

* refactor(query)
* fix(#37): fix URL comparison
* fix(#38): proper mock engine interface validation.

v0.1.10 / 2017-01-13
--------------------

* fix(#37): decode byte bodies
* feat(setup.py): add author email

v0.1.9 / 2017-01-06
-------------------

* fix(Makefile): remove proper egg file
* feat(package): add wheel package distribution support
* feat(docs): add documentation links

v0.1.8 / 2016-12-24
-------------------

* fix(assertion): extract regex pattern only when required
* feat(examples): add regular expression example

v0.1.7 / 2016-12-18
-------------------

* feat(#33): add support for user defined custom mock engine

v0.1.6 / 2016-12-14
-------------------

* fix(setup.py): force utf-8 encoding
* feat(setup.py): add encoding header
* feat(api): add debug mode
* refactor(docs): minor enhancements
* refactor(tests): update URL matcher test cases
* refactor(docs): add note about HTTP clients and update features list
* fix(setup.py): remove encoding param
* fix(tests): use strict equality assertion

0.1.5 / 2016-12-12
------------------

* fix(matchers): fix matching issue in URL.
* refactor(assertion): regex expression based matching must be explicitly enabled.
* feat(tests): add initial matchers tests.

0.1.4 / 2016-12-08
------------------

* refactor(README): minor changes
* fix(setup.py): lint error
* fix(#32): use explicit encoding while reading files in setup.py

0.1.3 / 2016-12-08
------------------

* fix(core): several bug fixes.
* feat(core): add pending features and major refactors.
* feat(matchers): use ``unittest.TestCase`` matching engine by default.

0.1.2 / 2016-12-01
------------------

* fix(matchers): runtime missing variable.

0.1.1 / 2016-12-01
------------------

* fix: Python 2 dictionary iteration syntax.
* feat(docs): add more examples.
* fix(matchers): better regular expression comparison support.

0.1.0 / 2016-11-30
------------------

* First version (still beta)

0.1.0-rc.1 / 2016-11-27
-----------------------

* First release candidate version (still beta)
