Hello community,
here is the log from the commit of package python-requests-mock for
openSUSE:Factory checked in at 2020-06-21 18:50:56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-requests-mock (Old)
and /work/SRC/openSUSE:Factory/.python-requests-mock.new.3606 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-requests-mock"
Sun Jun 21 18:50:56 2020 rev:14 rq:814547 version:1.8.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-requests-mock/python-requests-mock.changes
2019-09-23 12:17:09.929809159 +0200
+++
/work/SRC/openSUSE:Factory/.python-requests-mock.new.3606/python-requests-mock.changes
2020-06-21 19:06:14.312974279 +0200
@@ -1,0 +2,30 @@
+Sun Jun 14 09:11:15 UTC 2020 - Dirk Mueller <[email protected]>
+
+- update to 1.8.0:
+ * Remove requests 2.3 compatibility code
+ * Add release notes for reset function
+ * Add release note for session scoped mock
+ * Allow passing session as postiional argument
+ * Create bound method instead of a wrapper
+ * Added reset\_mock to \_RequestHistoryTracker and Adapter (#139)
+ * doc on session Mockers
+ * doc on nesting Mockers
+ * fix README.rst typo
+ * suggest Mocker for users unfamiliar with adapters
+ * update examples to mount adapter on 'mock://'
+ * fix global/session mock interactions and real\_http
+ * Added installation instructions
+ * Add release note for nested mocking
+ * fix redirects (#105) and mock nesting (#116)
+ * Mark IOReader object closed when using a stream
+ * Add the default response reason if not set
+ * Don't check that proxies are set in test
+ * Add StackOverflow tag to README
+ * Mention pytest fixture on the README
+ * Add background information to pytest doc
+ * docs: update examples to match Read the Docs
+ * Expose real\_http as a public property
+ * fix py27 error
+ * easier session scoped mock
+
+-------------------------------------------------------------------
Old:
----
requests-mock-1.7.0.tar.gz
New:
----
requests-mock-1.8.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-requests-mock.spec ++++++
--- /var/tmp/diff_new_pack.pfe2zY/_old 2020-06-21 19:06:14.732975643 +0200
+++ /var/tmp/diff_new_pack.pfe2zY/_new 2020-06-21 19:06:14.732975643 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-requests-mock
#
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-requests-mock
-Version: 1.7.0
+Version: 1.8.0
Release: 0
Summary: Module to mock out responses from the requests package
License: Apache-2.0
++++++ requests-mock-1.7.0.tar.gz -> requests-mock-1.8.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/AUTHORS
new/requests-mock-1.8.0/AUTHORS
--- old/requests-mock-1.7.0/AUTHORS 2019-09-01 09:48:16.000000000 +0200
+++ new/requests-mock-1.8.0/AUTHORS 2020-05-02 15:10:52.000000000 +0200
@@ -1,5 +1,7 @@
Alex Peters <[email protected]>
Andreas Jaeger <[email protected]>
+Arjan Keeman <[email protected]>
+Colas Le Guernic <[email protected]>
Darragh Bailey <[email protected]>
David Kremer <[email protected]>
Ian Cordasco <[email protected]>
@@ -15,10 +17,14 @@
Monty Taylor <[email protected]>
Noam <[email protected]>
Rick van de Loo <[email protected]>
+Ryan Brooke Payne <[email protected]>
Sebastian Kalinowski <[email protected]>
+Simon Willison <[email protected]>
Swapnil Kulkarni (coolsvap) <[email protected]>
Ville Skyttä <[email protected]>
boncheff <[email protected]>
+clslgrnc <[email protected]>
popokatapepel <[email protected]>
reedip <[email protected]>
+rfportilla <[email protected]>
voith <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/ChangeLog
new/requests-mock-1.8.0/ChangeLog
--- old/requests-mock-1.7.0/ChangeLog 2019-09-01 09:48:16.000000000 +0200
+++ new/requests-mock-1.8.0/ChangeLog 2020-05-02 15:10:52.000000000 +0200
@@ -1,6 +1,35 @@
CHANGES
=======
+1.8.0
+-----
+
+* Remove requests 2.3 compatibility code
+* Add release notes for reset function
+* Add release note for session scoped mock
+* Allow passing session as postiional argument
+* Create bound method instead of a wrapper
+* Added reset\_mock to \_RequestHistoryTracker and Adapter (#139)
+* doc on session Mockers
+* doc on nesting Mockers
+* fix README.rst typo
+* suggest Mocker for users unfamiliar with adapters
+* update examples to mount adapter on 'mock://'
+* fix global/session mock interactions and real\_http
+* Added installation instructions
+* Add release note for nested mocking
+* fix redirects (#105) and mock nesting (#116)
+* Mark IOReader object closed when using a stream
+* Add the default response reason if not set
+* Don't check that proxies are set in test
+* Add StackOverflow tag to README
+* Mention pytest fixture on the README
+* Add background information to pytest doc
+* docs: update examples to match Read the Docs
+* Expose real\_http as a public property
+* fix py27 error
+* easier session scoped mock
+
1.7.0
-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/PKG-INFO
new/requests-mock-1.8.0/PKG-INFO
--- old/requests-mock-1.7.0/PKG-INFO 2019-09-01 09:48:17.000000000 +0200
+++ new/requests-mock-1.8.0/PKG-INFO 2020-05-02 15:10:53.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: requests-mock
-Version: 1.7.0
+Version: 1.8.0
Summary: Mock out responses from the requests package
Home-page: https://requests-mock.readthedocs.io/
Author: Jamie Lennox
@@ -39,20 +39,21 @@
>>> session = requests.Session()
>>> adapter = requests_mock.Adapter()
- >>> session.mount('mock', adapter)
+ >>> session.mount('mock://', adapter)
>>> adapter.register_uri('GET', 'mock://test.com', text='data')
>>> resp = session.get('mock://test.com')
>>> resp.status_code, resp.text
(200, 'data')
- Obviously having all URLs be `mock://` prefixed isn't going to useful,
so you can use `requests_mock.mock` to get the adapter into place.
+ Obviously having all URLs be `mock://` prefixed isn't going to be
useful,
+ so you can use `requests_mock.Mocker` to get the adapter into place.
As a context manager:
.. code:: python
- >>> with requests_mock.mock() as m:
+ >>> with requests_mock.Mocker() as m:
... m.get('http://test.com', text='data')
... requests.get('http://test.com').text
...
@@ -62,7 +63,7 @@
.. code:: python
- >>> @requests_mock.mock()
+ >>> @requests_mock.Mocker()
... def test_func(m):
... m.get('http://test.com', text='data')
... return requests.get('http://test.com').text
@@ -70,6 +71,14 @@
>>> test_func()
'data'
+ Or as a pytest fixture:
+
+ .. code:: python
+
+ >>> def test_simple(requests_mock):
+ ... requests_mock.get('http://test.com', text='data')
+ ... assert 'data' == requests.get('http://test.com').text
+
For more information checkout the `docs`_.
Reporting Bugs
@@ -77,6 +86,11 @@
Development and bug tracking is performed on `GitHub`_.
+ Questions
+ =========
+
+ There is a tag dedicated to `requests-mock` on `StackOverflow`_ where
you can ask usage questions.
+
License
=======
@@ -95,6 +109,7 @@
.. _requests: http://python-requests.org
.. _docs: https://requests-mock.readthedocs.io/
.. _GitHub: https://github.com/jamielennox/requests-mock
+ .. _StackOverflow:
https://stackoverflow.com/questions/tagged/requests-mock
Platform: UNKNOWN
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/README.rst
new/requests-mock-1.8.0/README.rst
--- old/requests-mock-1.7.0/README.rst 2019-09-01 09:48:00.000000000 +0200
+++ new/requests-mock-1.8.0/README.rst 2020-05-02 15:10:34.000000000 +0200
@@ -31,20 +31,21 @@
>>> session = requests.Session()
>>> adapter = requests_mock.Adapter()
- >>> session.mount('mock', adapter)
+ >>> session.mount('mock://', adapter)
>>> adapter.register_uri('GET', 'mock://test.com', text='data')
>>> resp = session.get('mock://test.com')
>>> resp.status_code, resp.text
(200, 'data')
-Obviously having all URLs be `mock://` prefixed isn't going to useful, so you
can use `requests_mock.mock` to get the adapter into place.
+Obviously having all URLs be `mock://` prefixed isn't going to be useful,
+so you can use `requests_mock.Mocker` to get the adapter into place.
As a context manager:
.. code:: python
- >>> with requests_mock.mock() as m:
+ >>> with requests_mock.Mocker() as m:
... m.get('http://test.com', text='data')
... requests.get('http://test.com').text
...
@@ -54,7 +55,7 @@
.. code:: python
- >>> @requests_mock.mock()
+ >>> @requests_mock.Mocker()
... def test_func(m):
... m.get('http://test.com', text='data')
... return requests.get('http://test.com').text
@@ -62,6 +63,14 @@
>>> test_func()
'data'
+Or as a pytest fixture:
+
+.. code:: python
+
+ >>> def test_simple(requests_mock):
+ ... requests_mock.get('http://test.com', text='data')
+ ... assert 'data' == requests.get('http://test.com').text
+
For more information checkout the `docs`_.
Reporting Bugs
@@ -69,6 +78,11 @@
Development and bug tracking is performed on `GitHub`_.
+Questions
+=========
+
+There is a tag dedicated to `requests-mock` on `StackOverflow`_ where you can
ask usage questions.
+
License
=======
@@ -87,3 +101,4 @@
.. _requests: http://python-requests.org
.. _docs: https://requests-mock.readthedocs.io/
.. _GitHub: https://github.com/jamielennox/requests-mock
+.. _StackOverflow: https://stackoverflow.com/questions/tagged/requests-mock
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/RELEASENOTES.rst
new/requests-mock-1.8.0/RELEASENOTES.rst
--- old/requests-mock-1.7.0/RELEASENOTES.rst 2019-09-01 09:48:17.000000000
+0200
+++ new/requests-mock-1.8.0/RELEASENOTES.rst 2020-05-02 15:10:53.000000000
+0200
@@ -2,6 +2,75 @@
requests-mock
=============
+.. _requests-mock_1.8.0:
+
+1.8.0
+=====
+
+.. _requests-mock_1.8.0_Prelude:
+
+Prelude
+-------
+
+.. releasenotes/notes/explicit-nesting-behaviour-4d28c310dc4c463a.yaml @
b'b99eef22c5603dae28e35018166d95b40731ec7c'
+
+Makes explicit the behaviour of nested mocking.
+
+
+.. _requests-mock_1.8.0_New Features:
+
+New Features
+------------
+
+.. releasenotes/notes/add-reset-function-bcef01162cab0912.yaml @
b'aeca73aeb57752315a5b6cd123b00a24e81f8c39'
+
+- Add a reset/reset_mock function to the mocker and components so that users
+ can clear the calls and history from the Mocker without clearing all the
+ matching that has been used.
+
+.. releasenotes/notes/explicit-nesting-behaviour-4d28c310dc4c463a.yaml @
b'b99eef22c5603dae28e35018166d95b40731ec7c'
+
+- Nested mocks now has a defined behaviour which is essentially a classic
+ nesting behaviour. A mock works as normal, but in the same way that
+ real_http=True will escalate to the outer send (typically the real send) if
+ there is a mocker defined outside that will handle the calls.
+
+.. releasenotes/notes/session-scoped-mock-7f1c98d9a91bffc8.yaml @
b'35bfe56591f188dd169bad64b612688e55ec552c'
+
+- Allow mocking of only a single Session object. While there has always been
+ the option of adding just the Adapter to an existing Session, this is more
+ difficult to work with than the Mocker workflow that is typically used. You
+ can now pass a Session object to a Mocker and it will provide the standard
+ workflow but limited to just that object.
+
+.. releasenotes/notes/set-default-response-reason-f24556261bc7e9e5.yaml @
b'c2d3d248798087c6cf44e60f69679276e7a797c0'
+
+- When creating a response we now default the reason string to the appropriate
string based on the status code. This can still be provided manually.
+
+.. releasenotes/notes/set-real-http-on-mocker-01eb26b65697466d.yaml @
b'5788dcf191728e384a73f7dee100f482dfb79a7e'
+
+- Make real_http variable on Mocker object public. This means you can change
+ the value of the parameter after the object has been created. This will
+ allow setting it in situations like pytest where you may not be able to set
+ __init__ time options.
+
+
+.. _requests-mock_1.8.0_Bug Fixes:
+
+Bug Fixes
+---------
+
+.. releasenotes/notes/explicit-nesting-behaviour-4d28c310dc4c463a.yaml @
b'b99eef22c5603dae28e35018166d95b40731ec7c'
+
+- This fixes all known nesting bugs. They may not be perfect, however this is
+ now the explicit defined behaviour and so all related bugs are closed in
+ favour of this.
+
+.. releasenotes/notes/fix-iter-content-none-1e29754a75273b8c.yaml @
b'7a5fc638b606507a9a1dd2dc88e95df87dd2baa7'
+
+- 124 when using `response.iter_content(None)` the iterator would keep
returning b'' and never finish. In most code paths the b'' would indicate that
the stream is finished, but using None we have to close it ourselves.
+
+
.. _requests-mock_1.7.0:
1.7.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/doc/source/adapter.rst
new/requests-mock-1.8.0/doc/source/adapter.rst
--- old/requests-mock-1.7.0/doc/source/adapter.rst 2019-09-01
09:48:00.000000000 +0200
+++ new/requests-mock-1.8.0/doc/source/adapter.rst 2020-05-02
15:10:34.000000000 +0200
@@ -1,3 +1,5 @@
+.. _Adapter:
+
=============
Adapter Usage
=============
@@ -5,7 +7,18 @@
Creating an Adapter
===================
-The standard `requests`_ means of using an adapter is to
:py:meth:`~requests.Session.mount` it on a created session. This is not the
only way to load the adapter, however the same interactions will be used.
+The standard `requests`_ means of using a `transport adapter`_ is to `mount`_
it on a created session.
+This is not the only way to load the adapter, however the same interactions
will be used.
+
+When mounting an adapter, keep in mind that:
+
+* for a given URL, `requests`_ will use the adapter associated to the longest
matching prefix;
+* session are created with adapters for the :py:const:`http://` and
:py:const:`https://` prefixes
+ (and thus adapters mounted on :py:const:`http` or :py:const:`https` will
never be used);
+* `requests`_ only prepares URLs for *http* schemes (start with http and only
contains letters, numbers, and the + and - signs).
+ In particular :py:data:`params` won't work with the :py:const:`mock://`
scheme, but will with :py:const:`http+mock://`.
+
+If you are not familiar with adapters, prefer the mocker approach (see
:ref:`Mocker`).
.. doctest::
@@ -14,8 +27,10 @@
>>> session = requests.Session()
>>> adapter = requests_mock.Adapter()
- >>> session.mount('mock', adapter)
+ >>> session.mount('mock://', adapter)
At this point any requests made by the session to a URI starting with
`mock://` will be sent to our adapter.
.. _requests: http://python-requests.org
+.. _transport adapter:
https://requests.readthedocs.io/en/master/user/advanced/#transport-adapters
+.. _mount:
https://requests.readthedocs.io/en/master/api/#requests.Session.mount
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/doc/source/history.rst
new/requests-mock-1.8.0/doc/source/history.rst
--- old/requests-mock-1.7.0/doc/source/history.rst 2019-09-01
09:48:00.000000000 +0200
+++ new/requests-mock-1.8.0/doc/source/history.rst 2020-05-02
15:10:34.000000000 +0200
@@ -66,3 +66,50 @@
:cert: The client certificate or cert/key tuple for this request.
Note: That the default value of these attributes are the values that are
passed to the adapter and not what is passed to the request method. This means
that the default for allow_redirects is None (even though that is interpretted
as True) if unset, whereas the defautl for verify is True, and the default for
proxies the empty dict.
+
+Reset History
+===============
+
+For mocks, adapters, and matchers, the history can be reset. This can be
useful when testing complex code with multiple requests.
+
+For mocks, use "reset_mock" method.
+
+.. doctest::
+
+ >>> m.called
+ True
+ >>> m.reset_mock()
+ >>> m.called
+ False
+ >>> m.call_count
+ 0
+
+For adapters and matchers, there is a "reset" method. Resetting the adapter
also resets the associated matchers.
+
+.. doctest::
+
+ >>> adapter = requests_mock.adapter.Adapter()
+ >>> matcher = adapter.register_uri('GET', 'mock://test.com', text='resp')
+ >>> session = requests.Session()
+ >>> session.mount('mock://', adapter)
+ >>> session.get('mock://test.com')
+ >>> adapter.called
+ True
+ >>> adapter.reset()
+ >>> adapter.called
+ False
+ >>> matcher.called # Reset adapter also resets associated matchers
+ False
+
+However, resetting the matcher does not reset the adapter.
+
+.. doctest::
+
+ >>> session.get('mock://test.com')
+ >>> matcher.called
+ True
+ >>> matcher.reset()
+ >>> matcher.called
+ False
+ >>> adapter.called # Reset matcher does not reset adapter
+ True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/doc/source/matching.rst
new/requests-mock-1.8.0/doc/source/matching.rst
--- old/requests-mock-1.7.0/doc/source/matching.rst 2019-09-01
09:48:00.000000000 +0200
+++ new/requests-mock-1.8.0/doc/source/matching.rst 2020-05-02
15:10:34.000000000 +0200
@@ -12,7 +12,7 @@
>>> import requests_mock
>>> adapter = requests_mock.Adapter()
>>> session = requests.Session()
- >>> session.mount('mock', adapter)
+ >>> session.mount('mock://', adapter)
.. note::
@@ -29,6 +29,9 @@
adapter.register_uri('GET', url, ...)
+ If you are not familiar with `requests
<https://requests.readthedocs.io/>`_' adapters (see :ref:`Adapter`),
+ prefer the mocker approach (see :ref:`Mocker`).
+
.. doctest::
:hide:
@@ -36,7 +39,7 @@
>>> import requests_mock
>>> adapter = requests_mock.Adapter()
>>> session = requests.Session()
- >>> session.mount('mock', adapter)
+ >>> session.mount('mock://', adapter)
.. note::
@@ -94,7 +97,7 @@
>>> import requests_mock
>>> adapter = requests_mock.Adapter()
>>> session = requests.Session()
- >>> session.mount('mock', adapter)
+ >>> session.mount('mock://', adapter)
Query strings provided to a register will match so long as at least those
provided form part of the request.
@@ -145,7 +148,7 @@
>>> import requests_mock
>>> adapter = requests_mock.Adapter()
>>> session = requests.Session()
- >>> session.mount('mock', adapter)
+ >>> session.mount('mock://', adapter)
.. doctest::
@@ -178,7 +181,7 @@
>>> import requests_mock
>>> adapter = requests_mock.Adapter()
>>> session = requests.Session()
- >>> session.mount('mock', adapter)
+ >>> session.mount('mock://', adapter)
.. doctest::
@@ -204,7 +207,7 @@
>>> import requests_mock
>>> adapter = requests_mock.Adapter()
>>> session = requests.Session()
- >>> session.mount('mock', adapter)
+ >>> session.mount('mock://', adapter)
.. doctest::
@@ -230,7 +233,7 @@
>>> import requests_mock
>>> adapter = requests_mock.Adapter()
>>> session = requests.Session()
- >>> session.mount('mock', adapter)
+ >>> session.mount('mock://', adapter)
.. doctest::
@@ -265,7 +268,7 @@
>>> import requests_mock
>>> adapter = requests_mock.Adapter()
>>> session = requests.Session()
- >>> session.mount('mock', adapter)
+ >>> session.mount('mock://', adapter)
.. doctest::
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/doc/source/mocker.rst
new/requests-mock-1.8.0/doc/source/mocker.rst
--- old/requests-mock-1.7.0/doc/source/mocker.rst 2019-09-01
09:48:00.000000000 +0200
+++ new/requests-mock-1.8.0/doc/source/mocker.rst 2020-05-02
15:10:34.000000000 +0200
@@ -1,3 +1,5 @@
+.. _Mocker:
+
================
Using the Mocker
================
@@ -5,6 +7,11 @@
The mocker is a loading mechanism to ensure the adapter is correctly in place
to intercept calls from requests.
Its goal is to provide an interface that is as close to the real requests
library interface as possible.
+:py:class:`requests_mock.Mocker` takes two optional parameters:
+
+:real_http (bool): If True then any requests that are not handled by the
mocking adapter will be forwarded to the real server (see :ref:`RealHTTP`), or
the containing Mocker if applicable (see :ref:`NestingMockers`). Defaults to
False.
+:session (requests.Session): If set, only the given session instance is mocked
(see :ref:`SessionMocking`).
+
Activation
==========
@@ -125,12 +132,14 @@
These methods correspond to the HTTP method of your request, so to mock POST
requests you would use the :py:meth:`~requests_mock.MockerCore.post` function.
Further information about what can be matched from a request can be found at
:doc:`matching`
+.. _RealHTTP:
+
Real HTTP Requests
==================
-The Mocker object takes the following parameters:
-
-:real_http (bool): If True then any requests that are not handled by the
mocking adapter will be forwarded to the real server. Defaults to False.
+If :py:data:`real_http` is set to :py:const:`True`
+then any requests that are not handled by the mocking adapter will be
forwarded to the real server,
+or the containing Mocker if applicable (see :ref:`NestingMockers`).
.. doctest::
@@ -156,3 +165,73 @@
...
'resp'
200
+
+.. _NestingMockers:
+
+Nested Mockers
+==============
+
+*New in 1.8*
+
+When nesting mockers the innermost Mocker replaces all others.
+If :py:data:`real_http` is set to :py:const:`True`, at creation or for a given
resource,
+the request is passed to the containing Mocker.
+The containing Mocker can in turn:
+
+- serve the request;
+- raise :py:exc:`NoMockAddress`;
+- or pass the request to yet another Mocker (or to the unmocked
:py:class:`requests.Session`) if :py:data:`real_http` is set to
:py:const:`True`.
+
+.. doctest::
+
+ >>> url = "https://www.example.com/"
+ >>> with requests_mock.Mocker() as outer_mock:
+ ... outer_mock.get(url, text='outer')
+ ... with requests_mock.Mocker(real_http=True) as middle_mock:
+ ... with requests_mock.Mocker() as inner_mock:
+ ... inner_mock.get(url, real_http=True)
+ ... print(requests.get(url).text) # doctest: +SKIP
+ ...
+ 'outer'
+
+Most of the time nesting can be avoided by making the mocker object available
to subclasses/subfunctions.
+
+.. warning::
+ When starting/stopping mockers manually, make sure to stop innermost
mockers first.
+ A call from an active inner mocker with a stopped outer mocker leads to
undefined behavior.
+
+.. _SessionMocking:
+
+Mocking specific sessions
+=========================
+
+*New in 1.8*
+
+:py:class:`requests_mock.Mocker` can be used to mock specific sessions through
the :py:data:`session` parameter.
+
+.. doctest::
+
+ >>> url = "https://www.example.com/"
+ >>> with requests_mock.Mocker() as global_mock:
+ ... global_mock.get(url, text='global')
+ ... session = requests.Session()
+ ... print("requests.get before session mock:", requests.get(url).text)
+ ... print("session.get before session mock:", session.get(url).text)
+ ... with requests_mock.Mocker(session=session) as session_mock:
+ ... session_mock.get(url, text='session')
+ ... print("Within session mock:", requests.get(url).text)
+ ... print("Within session mock:", session.get(url).text)
+ ... print("After session mock:", requests.get(url).text)
+ ... print("After session mock:", session.get(url).text)
+ ...
+ 'requests.get before session mock: global'
+ 'session.get before session mock: global'
+ 'requests.get within session mock: global'
+ 'session.get within session mock: session'
+ 'requests.get after session mock: global'
+ 'session.get after session mock: global'
+
+
+
+.. note::
+ As an alternative, :py:class:`requests_mock.Adapter` instances can be
mounted on specific sessions (see :ref:`Adapter`).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/doc/source/overview.rst
new/requests-mock-1.8.0/doc/source/overview.rst
--- old/requests-mock-1.7.0/doc/source/overview.rst 2019-09-01
09:48:00.000000000 +0200
+++ new/requests-mock-1.8.0/doc/source/overview.rst 2020-05-02
15:10:34.000000000 +0200
@@ -13,3 +13,10 @@
.. _requests: http://python-requests.org
.. _pluggable transport adapters:
http://docs.python-requests.org/en/latest/user/advanced/#transport-adapters
+
+Installation
+============
+
+::
+
+ pip install requests-mock
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/doc/source/pytest.rst
new/requests-mock-1.8.0/doc/source/pytest.rst
--- old/requests-mock-1.7.0/doc/source/pytest.rst 2019-09-01
09:48:00.000000000 +0200
+++ new/requests-mock-1.8.0/doc/source/pytest.rst 2020-05-02
15:10:34.000000000 +0200
@@ -18,7 +18,12 @@
... assert 'data' == requests.get('http://test.com').text
...
+If you are unfamiliar with how pytest decorators work then please `read the
fixture documentation` first as it means that you should no longer use the
`@requests_mock.Mocker` syntax that is present in the documentation examples.
+This confusion between how `unittest`_ and `pytest`_ work is the biggest
source of complaint and is not a `requests-mock` inherent problem.
+
.. _pytest: https://pytest.org
+.. _unittest: https://docs.python.org/3/library/unittest.html
+.. _read the fixture documentation:
https://docs.pytest.org/en/latest/fixture.html
Configuration
=============
@@ -28,3 +33,53 @@
These options are:
`requests_mock_case_sensitive`: (bool) Turn on case sensitivity in path
matching.
+
+Background
+==========
+
+This section was initially copied from `StackOverflow`_
+
+`pytest`_ doesn't play along with function decorators that add positional
arguments to the test function.
+`pytest`_ considers all arguments that:
+
+- aren't bound to an instance or type as in instance or class methods;
+- don't have default values;
+- aren't bound with functools.partial;
+- aren't replaced with unittest.mock mocks
+
+to be replaced with fixture values, and will fail if it doesn't find a
suitable fixture for any argument. So stuff like
+
+.. code-block:: python
+
+ import functools
+ import pytest
+
+
+ def deco(func):
+ @functools.wraps(func)
+ def wrapper(*args, **kwargs):
+ args += ('spam',)
+ return func(*args, **kwargs)
+ return wrapper
+
+
+ @deco
+ def test_spam(spam_arg):
+ assert True
+
+will fail, and this is exactly what requests-mock does. A workaround to that
would be passing the mocker via keyword args:
+
+.. code-block:: python
+
+ import pytest
+ import requests_mock
+
+
+ @requests_mock.Mocker(kw='m')
+ def test_with_mock_and_fixtures(capsys, **kwargs):
+ m = kwargs['m']
+ ...
+
+however at this point it would simply be easier to use the provided pytest
decorator.
+
+.. _stackoverflow: https://stackoverflow.com/a/52065289/544047
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/doc/source/response.rst
new/requests-mock-1.8.0/doc/source/response.rst
--- old/requests-mock-1.7.0/doc/source/response.rst 2019-09-01
09:48:00.000000000 +0200
+++ new/requests-mock-1.8.0/doc/source/response.rst 2020-05-02
15:10:34.000000000 +0200
@@ -17,6 +17,9 @@
adapter.register_uri('GET', url, ...)
+ If you are not familiar with `requests
<https://requests.readthedocs.io/>`_' adapters (see :ref:`Adapter`),
+ prefer the mocker approach (see :ref:`Mocker`).
+
Registering Responses
=====================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-mock-1.7.0/releasenotes/notes/add-reset-function-bcef01162cab0912.yaml
new/requests-mock-1.8.0/releasenotes/notes/add-reset-function-bcef01162cab0912.yaml
---
old/requests-mock-1.7.0/releasenotes/notes/add-reset-function-bcef01162cab0912.yaml
1970-01-01 01:00:00.000000000 +0100
+++
new/requests-mock-1.8.0/releasenotes/notes/add-reset-function-bcef01162cab0912.yaml
2020-05-02 15:10:34.000000000 +0200
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ Add a reset/reset_mock function to the mocker and components so that users
+ can clear the calls and history from the Mocker without clearing all the
+ matching that has been used.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-mock-1.7.0/releasenotes/notes/explicit-nesting-behaviour-4d28c310dc4c463a.yaml
new/requests-mock-1.8.0/releasenotes/notes/explicit-nesting-behaviour-4d28c310dc4c463a.yaml
---
old/requests-mock-1.7.0/releasenotes/notes/explicit-nesting-behaviour-4d28c310dc4c463a.yaml
1970-01-01 01:00:00.000000000 +0100
+++
new/requests-mock-1.8.0/releasenotes/notes/explicit-nesting-behaviour-4d28c310dc4c463a.yaml
2020-05-02 15:10:34.000000000 +0200
@@ -0,0 +1,14 @@
+---
+prelude: >
+ Makes explicit the behaviour of nested mocking.
+features:
+ - |
+ Nested mocks now has a defined behaviour which is essentially a classic
+ nesting behaviour. A mock works as normal, but in the same way that
+ real_http=True will escalate to the outer send (typically the real send) if
+ there is a mocker defined outside that will handle the calls.
+fixes:
+ - |
+ This fixes all known nesting bugs. They may not be perfect, however this is
+ now the explicit defined behaviour and so all related bugs are closed in
+ favour of this.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-mock-1.7.0/releasenotes/notes/fix-iter-content-none-1e29754a75273b8c.yaml
new/requests-mock-1.8.0/releasenotes/notes/fix-iter-content-none-1e29754a75273b8c.yaml
---
old/requests-mock-1.7.0/releasenotes/notes/fix-iter-content-none-1e29754a75273b8c.yaml
1970-01-01 01:00:00.000000000 +0100
+++
new/requests-mock-1.8.0/releasenotes/notes/fix-iter-content-none-1e29754a75273b8c.yaml
2020-05-02 15:10:34.000000000 +0200
@@ -0,0 +1,5 @@
+---
+fixes:
+ - 124 when using `response.iter_content(None)` the iterator would keep
+ returning b'' and never finish. In most code paths the b'' would indicate
+ that the stream is finished, but using None we have to close it ourselves.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/releasenotes/notes/reno.cache
new/requests-mock-1.8.0/releasenotes/notes/reno.cache
--- old/requests-mock-1.7.0/releasenotes/notes/reno.cache 2019-09-01
09:48:17.000000000 +0200
+++ new/requests-mock-1.8.0/releasenotes/notes/reno.cache 2020-05-02
15:10:53.000000000 +0200
@@ -27,6 +27,15 @@
prelude: 'Increase the minimum required requests version to 2.3
'
+ releasenotes/notes/add-reset-function-bcef01162cab0912.yaml:
+ features:
+ - 'Add a reset/reset_mock function to the mocker and components so that
users
+
+ can clear the calls and history from the Mocker without clearing all the
+
+ matching that has been used.
+
+ '
releasenotes/notes/additional-matcher-5c5cd466a6d70080.yaml:
features:
- Allow specifying an `additional_matcher` to the mocker that will call a
function
@@ -48,6 +57,33 @@
- It is recommended you add `requests_mock.mock.case_sensitive = True` to
your
base test file to globally turn on case sensitive matching as this will
become
the default in a 2.X release.
+ releasenotes/notes/explicit-nesting-behaviour-4d28c310dc4c463a.yaml:
+ features:
+ - 'Nested mocks now has a defined behaviour which is essentially a classic
+
+ nesting behaviour. A mock works as normal, but in the same way that
+
+ real_http=True will escalate to the outer send (typically the real send)
if
+
+ there is a mocker defined outside that will handle the calls.
+
+ '
+ fixes:
+ - 'This fixes all known nesting bugs. They may not be perfect, however
this is
+
+ now the explicit defined behaviour and so all related bugs are closed in
+
+ favour of this.
+
+ '
+ prelude: 'Makes explicit the behaviour of nested mocking.
+
+ '
+ releasenotes/notes/fix-iter-content-none-1e29754a75273b8c.yaml:
+ fixes:
+ - 124 when using `response.iter_content(None)` the iterator would keep
returning
+ b'' and never finish. In most code paths the b'' would indicate that the
stream
+ is finished, but using None we have to close it ourselves.
releasenotes/notes/fix-pytest-version-discovery-43f27e7e162ed055.yaml:
fixes:
- Fixed a bug relating to how the pytest version was being discovered that
meant
@@ -101,6 +137,34 @@
features:
- The stream parameter is recorded when the request is sent and available
in request
history in the same was as parameters like verify or timeout.
+ releasenotes/notes/session-scoped-mock-7f1c98d9a91bffc8.yaml:
+ features:
+ - 'Allow mocking of only a single Session object. While there has always
been
+
+ the option of adding just the Adapter to an existing Session, this is
more
+
+ difficult to work with than the Mocker workflow that is typically used.
You
+
+ can now pass a Session object to a Mocker and it will provide the
standard
+
+ workflow but limited to just that object.
+
+ '
+ releasenotes/notes/set-default-response-reason-f24556261bc7e9e5.yaml:
+ features:
+ - When creating a response we now default the reason string to the
appropriate
+ string based on the status code. This can still be provided manually.
+ releasenotes/notes/set-real-http-on-mocker-01eb26b65697466d.yaml:
+ features:
+ - 'Make real_http variable on Mocker object public. This means you can
change
+
+ the value of the parameter after the object has been created. This will
+
+ allow setting it in situations like pytest where you may not be able to
set
+
+ __init__ time options.
+
+ '
releasenotes/notes/user-response-encoding-b2eea39404140164.yaml:
fixes:
- 'If you specified a charset in the Content-Type of a response it would be
@@ -114,6 +178,26 @@
'
notes:
- files:
+ - - releasenotes/notes/add-reset-function-bcef01162cab0912.yaml
+ - !!binary |
+ YWVjYTczYWViNTc3NTIzMTVhNWI2Y2QxMjNiMDBhMjRlODFmOGMzOQ==
+ - - releasenotes/notes/explicit-nesting-behaviour-4d28c310dc4c463a.yaml
+ - !!binary |
+ Yjk5ZWVmMjJjNTYwM2RhZTI4ZTM1MDE4MTY2ZDk1YjQwNzMxZWM3Yw==
+ - - releasenotes/notes/fix-iter-content-none-1e29754a75273b8c.yaml
+ - !!binary |
+ N2E1ZmM2MzhiNjA2NTA3YTlhMWRkMmRjODhlOTVkZjg3ZGQyYmFhNw==
+ - - releasenotes/notes/session-scoped-mock-7f1c98d9a91bffc8.yaml
+ - !!binary |
+ MzViZmU1NjU5MWYxODhkZDE2OWJhZDY0YjYxMjY4OGU1NWVjNTUyYw==
+ - - releasenotes/notes/set-default-response-reason-f24556261bc7e9e5.yaml
+ - !!binary |
+ YzJkM2QyNDg3OTgwODdjNmNmNDRlNjBmNjk2NzkyNzZlN2E3OTdjMA==
+ - - releasenotes/notes/set-real-http-on-mocker-01eb26b65697466d.yaml
+ - !!binary |
+ NTc4OGRjZjE5MTcyOGUzODRhNzNmN2RlZTEwMGY0ODJkZmI3OWE3ZQ==
+ version: 1.8.0
+- files:
- - releasenotes/notes/match-empty-query-string-e6d6976fe002da0b.yaml
- !!binary |
OTIxMGRmYzFjODMxYzRhZmRkNjk4ZGNkOWFjNjM3ZWUzNjAxOTQzOQ==
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-mock-1.7.0/releasenotes/notes/session-scoped-mock-7f1c98d9a91bffc8.yaml
new/requests-mock-1.8.0/releasenotes/notes/session-scoped-mock-7f1c98d9a91bffc8.yaml
---
old/requests-mock-1.7.0/releasenotes/notes/session-scoped-mock-7f1c98d9a91bffc8.yaml
1970-01-01 01:00:00.000000000 +0100
+++
new/requests-mock-1.8.0/releasenotes/notes/session-scoped-mock-7f1c98d9a91bffc8.yaml
2020-05-02 15:10:34.000000000 +0200
@@ -0,0 +1,8 @@
+---
+features:
+ - |
+ Allow mocking of only a single Session object. While there has always been
+ the option of adding just the Adapter to an existing Session, this is more
+ difficult to work with than the Mocker workflow that is typically used. You
+ can now pass a Session object to a Mocker and it will provide the standard
+ workflow but limited to just that object.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-mock-1.7.0/releasenotes/notes/set-default-response-reason-f24556261bc7e9e5.yaml
new/requests-mock-1.8.0/releasenotes/notes/set-default-response-reason-f24556261bc7e9e5.yaml
---
old/requests-mock-1.7.0/releasenotes/notes/set-default-response-reason-f24556261bc7e9e5.yaml
1970-01-01 01:00:00.000000000 +0100
+++
new/requests-mock-1.8.0/releasenotes/notes/set-default-response-reason-f24556261bc7e9e5.yaml
2020-05-02 15:10:34.000000000 +0200
@@ -0,0 +1,5 @@
+---
+features:
+ - When creating a response we now default the reason string to the
+ appropriate string based on the status code. This can still be provided
+ manually.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-mock-1.7.0/releasenotes/notes/set-real-http-on-mocker-01eb26b65697466d.yaml
new/requests-mock-1.8.0/releasenotes/notes/set-real-http-on-mocker-01eb26b65697466d.yaml
---
old/requests-mock-1.7.0/releasenotes/notes/set-real-http-on-mocker-01eb26b65697466d.yaml
1970-01-01 01:00:00.000000000 +0100
+++
new/requests-mock-1.8.0/releasenotes/notes/set-real-http-on-mocker-01eb26b65697466d.yaml
2020-05-02 15:10:34.000000000 +0200
@@ -0,0 +1,7 @@
+---
+features:
+ - |
+ Make real_http variable on Mocker object public. This means you can change
+ the value of the parameter after the object has been created. This will
+ allow setting it in situations like pytest where you may not be able to set
+ __init__ time options.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/requests_mock/adapter.py
new/requests-mock-1.8.0/requests_mock/adapter.py
--- old/requests-mock-1.7.0/requests_mock/adapter.py 2019-09-01
09:48:00.000000000 +0200
+++ new/requests-mock-1.8.0/requests_mock/adapter.py 2020-05-02
15:10:34.000000000 +0200
@@ -62,6 +62,9 @@
def call_count(self):
return len(self.request_history)
+ def reset(self):
+ self.request_history = []
+
class _RunRealHTTP(Exception):
"""A fake exception to jump out of mocking and allow a real request.
@@ -305,5 +308,10 @@
"""
self._matchers.append(matcher)
+ def reset(self):
+ super(Adapter, self).reset()
+ for matcher in self._matchers:
+ matcher.reset()
+
__all__ = ['Adapter']
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/requests_mock/compat.py
new/requests-mock-1.8.0/requests_mock/compat.py
--- old/requests-mock-1.7.0/requests_mock/compat.py 2019-09-01
09:48:00.000000000 +0200
+++ new/requests-mock-1.8.0/requests_mock/compat.py 2020-05-02
15:10:34.000000000 +0200
@@ -13,13 +13,6 @@
import requests
-def _versiontuple(v):
- return tuple(map(int, (v.split("."))))
-
-
-_requests_version = _versiontuple(requests.__version__)
-
-
class _FakeHTTPMessage(object):
def __init__(self, headers):
@@ -37,24 +30,3 @@
return [self.headers[name]]
except KeyError:
return failobj
-
-
-class _FakeHTTPResponse(object):
-
- def __init__(self, headers):
- self.msg = _FakeHTTPMessage(headers)
-
- def isclosed(self):
- # Don't let urllib try to close me
- return False
-
-
-if _requests_version < (2, 3):
- # NOTE(jamielennox): There is a problem with requests < 2.3.0 such that it
- # needs a httplib message for use with cookie extraction. It has been fixed
- # but it is needed until we can rely on a recent enough requests version.
-
- _fake_http_response = _FakeHTTPResponse({})
-
-else:
- _fake_http_response = None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/requests_mock/mocker.py
new/requests-mock-1.8.0/requests_mock/mocker.py
--- old/requests-mock-1.7.0/requests_mock/mocker.py 2019-09-01
09:48:00.000000000 +0200
+++ new/requests-mock-1.8.0/requests_mock/mocker.py 2020-05-02
15:10:34.000000000 +0200
@@ -13,6 +13,7 @@
import functools
import requests
+import six
from requests_mock import adapter
from requests_mock import exceptions
@@ -28,6 +29,18 @@
_original_send = requests.Session.send
+def _set_method(target, name, method):
+ """ Set a mocked method onto the target.
+
+ Target may be either an instance of a Session object of the
+ requests.Session class. First we Bind the method if it's an instance.
+ """
+ if not isinstance(target, type):
+ method = six.create_bound_method(method, target)
+
+ setattr(target, name, method)
+
+
class MockerCore(object):
"""A wrapper around common mocking functions.
@@ -42,6 +55,7 @@
'called',
'called_once',
'call_count',
+ 'reset',
}
case_sensitive = False
@@ -67,14 +81,18 @@
This will become the default in a 2.X release. See bug: #1584008.
"""
- def __init__(self, **kwargs):
+ def __init__(self, session=None, **kwargs):
+ if session and not isinstance(session, requests.Session):
+ raise TypeError("Only a requests.Session object can be mocked")
+
+ self._mock_target = session or requests.Session
self.case_sensitive = kwargs.pop('case_sensitive', self.case_sensitive)
self._adapter = (
kwargs.pop('adapter', None) or
adapter.Adapter(case_sensitive=self.case_sensitive)
)
- self._real_http = kwargs.pop('real_http', False)
+ self.real_http = kwargs.pop('real_http', False)
self._last_send = None
if kwargs:
@@ -88,14 +106,16 @@
if self._last_send:
raise RuntimeError('Mocker has already been started')
- self._last_send = requests.Session.send
+ # backup last `send` for restoration on `self.stop`
+ self._last_send = self._mock_target.send
+ self._last_get_adapter = self._mock_target.get_adapter
def _fake_get_adapter(session, url):
return self._adapter
def _fake_send(session, request, **kwargs):
- real_get_adapter = requests.Session.get_adapter
- requests.Session.get_adapter = _fake_get_adapter
+ # mock get_adapter
+ _set_method(session, "get_adapter", _fake_get_adapter)
# NOTE(jamielennox): self._last_send vs _original_send. Whilst it
# seems like here we would use _last_send there is the possibility
@@ -110,28 +130,40 @@
try:
return _original_send(session, request, **kwargs)
except exceptions.NoMockAddress:
- if not self._real_http:
+ if not self.real_http:
raise
except adapter._RunRealHTTP:
# this mocker wants you to run the request through the real
# requests library rather than the mocking. Let it.
pass
finally:
- requests.Session.get_adapter = real_get_adapter
+ # restore get_adapter
+ _set_method(session, "get_adapter", self._last_get_adapter)
- return _original_send(session, request, **kwargs)
+ # if we are here it means we must run the real http request
+ # Or, with nested mocks, to the parent mock, that is why we use
+ # _last_send here instead of _original_send
+ if isinstance(self._mock_target, type):
+ return self._last_send(session, request, **kwargs)
+ else:
+ return self._last_send(request, **kwargs)
- requests.Session.send = _fake_send
+ _set_method(self._mock_target, "send", _fake_send)
def stop(self):
"""Stop mocking requests.
This should have no impact if mocking has not been started.
+ When nesting mockers, make sure to stop the innermost first.
"""
if self._last_send:
- requests.Session.send = self._last_send
+ self._mock_target.send = self._last_send
self._last_send = None
+ # for familiarity with MagicMock
+ def reset_mock(self):
+ self.reset()
+
def __getattr__(self, name):
if name in self._PROXY_FUNCS:
try:
@@ -208,7 +240,7 @@
"""
m = Mocker(
kw=self._kw,
- real_http=self._real_http,
+ real_http=self.real_http,
case_sensitive=self.case_sensitive
)
return m
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/requests_mock/response.py
new/requests-mock-1.8.0/requests_mock/response.py
--- old/requests-mock-1.7.0/requests_mock/response.py 2019-09-01
09:48:00.000000000 +0200
+++ new/requests-mock-1.8.0/requests_mock/response.py 2020-05-02
15:10:34.000000000 +0200
@@ -117,7 +117,15 @@
return six.b('')
# not a new style object in python 2
- return six.BytesIO.read(self, *args, **kwargs)
+ result = six.BytesIO.read(self, *args, **kwargs)
+
+ # when using resp.iter_content(None) it'll go through a different
+ # request path in urllib3. This path checks whether the object is
+ # marked closed instead of the return value. see gh124.
+ if result == six.b(''):
+ self.close()
+
+ return result
def create_response(request, **kwargs):
@@ -162,13 +170,17 @@
if content is not None:
body = _IOReader(content)
if not raw:
- raw = HTTPResponse(status=kwargs.get('status_code', _DEFAULT_STATUS),
+ status = kwargs.get('status_code', _DEFAULT_STATUS)
+ reason = kwargs.get('reason',
+ six.moves.http_client.responses.get(status))
+
+ raw = HTTPResponse(status=status,
+ reason=reason,
headers=headers,
- reason=kwargs.get('reason'),
body=body or _IOReader(six.b('')),
decode_content=False,
preload_content=False,
- original_response=compat._fake_http_response)
+ original_response=None)
response = _http_adapter.build_response(request, raw)
response.connection = connection
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/requests_mock.egg-info/PKG-INFO
new/requests-mock-1.8.0/requests_mock.egg-info/PKG-INFO
--- old/requests-mock-1.7.0/requests_mock.egg-info/PKG-INFO 2019-09-01
09:48:16.000000000 +0200
+++ new/requests-mock-1.8.0/requests_mock.egg-info/PKG-INFO 2020-05-02
15:10:52.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: requests-mock
-Version: 1.7.0
+Version: 1.8.0
Summary: Mock out responses from the requests package
Home-page: https://requests-mock.readthedocs.io/
Author: Jamie Lennox
@@ -39,20 +39,21 @@
>>> session = requests.Session()
>>> adapter = requests_mock.Adapter()
- >>> session.mount('mock', adapter)
+ >>> session.mount('mock://', adapter)
>>> adapter.register_uri('GET', 'mock://test.com', text='data')
>>> resp = session.get('mock://test.com')
>>> resp.status_code, resp.text
(200, 'data')
- Obviously having all URLs be `mock://` prefixed isn't going to useful,
so you can use `requests_mock.mock` to get the adapter into place.
+ Obviously having all URLs be `mock://` prefixed isn't going to be
useful,
+ so you can use `requests_mock.Mocker` to get the adapter into place.
As a context manager:
.. code:: python
- >>> with requests_mock.mock() as m:
+ >>> with requests_mock.Mocker() as m:
... m.get('http://test.com', text='data')
... requests.get('http://test.com').text
...
@@ -62,7 +63,7 @@
.. code:: python
- >>> @requests_mock.mock()
+ >>> @requests_mock.Mocker()
... def test_func(m):
... m.get('http://test.com', text='data')
... return requests.get('http://test.com').text
@@ -70,6 +71,14 @@
>>> test_func()
'data'
+ Or as a pytest fixture:
+
+ .. code:: python
+
+ >>> def test_simple(requests_mock):
+ ... requests_mock.get('http://test.com', text='data')
+ ... assert 'data' == requests.get('http://test.com').text
+
For more information checkout the `docs`_.
Reporting Bugs
@@ -77,6 +86,11 @@
Development and bug tracking is performed on `GitHub`_.
+ Questions
+ =========
+
+ There is a tag dedicated to `requests-mock` on `StackOverflow`_ where
you can ask usage questions.
+
License
=======
@@ -95,6 +109,7 @@
.. _requests: http://python-requests.org
.. _docs: https://requests-mock.readthedocs.io/
.. _GitHub: https://github.com/jamielennox/requests-mock
+ .. _StackOverflow:
https://stackoverflow.com/questions/tagged/requests-mock
Platform: UNKNOWN
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-mock-1.7.0/requests_mock.egg-info/SOURCES.txt
new/requests-mock-1.8.0/requests_mock.egg-info/SOURCES.txt
--- old/requests-mock-1.7.0/requests_mock.egg-info/SOURCES.txt 2019-09-01
09:48:17.000000000 +0200
+++ new/requests-mock-1.8.0/requests_mock.egg-info/SOURCES.txt 2020-05-02
15:10:53.000000000 +0200
@@ -35,8 +35,11 @@
releasenotes/notes/Add-called_once-property-a69546448cbd5542.yaml
releasenotes/notes/Allow-pickling-response-fe751b0a760a5001.yaml
releasenotes/notes/Bump-minimum-requests-2.3-70fd287f6ea1a12e.yaml
+releasenotes/notes/add-reset-function-bcef01162cab0912.yaml
releasenotes/notes/additional-matcher-5c5cd466a6d70080.yaml
releasenotes/notes/case-insensitive-matching-a3143221359bbf2d.yaml
+releasenotes/notes/explicit-nesting-behaviour-4d28c310dc4c463a.yaml
+releasenotes/notes/fix-iter-content-none-1e29754a75273b8c.yaml
releasenotes/notes/fix-pytest-version-discovery-43f27e7e162ed055.yaml
releasenotes/notes/fixture-extras-699a5b5fb5bd6aab.yaml
releasenotes/notes/match-empty-query-string-e6d6976fe002da0b.yaml
@@ -45,6 +48,9 @@
releasenotes/notes/pytest-7e35da8c5f2cd428.yaml
releasenotes/notes/repo-move-15e956e1d54c048b.yaml
releasenotes/notes/request-history-stream-f1d75b33adcd7e97.yaml
+releasenotes/notes/session-scoped-mock-7f1c98d9a91bffc8.yaml
+releasenotes/notes/set-default-response-reason-f24556261bc7e9e5.yaml
+releasenotes/notes/set-real-http-on-mocker-01eb26b65697466d.yaml
releasenotes/notes/user-response-encoding-b2eea39404140164.yaml
requests_mock/__init__.py
requests_mock/adapter.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/requests_mock.egg-info/pbr.json
new/requests-mock-1.8.0/requests_mock.egg-info/pbr.json
--- old/requests-mock-1.7.0/requests_mock.egg-info/pbr.json 2019-09-01
09:48:16.000000000 +0200
+++ new/requests-mock-1.8.0/requests_mock.egg-info/pbr.json 2020-05-02
15:10:52.000000000 +0200
@@ -1 +1 @@
-{"git_version": "c1457d6", "is_release": true}
\ No newline at end of file
+{"git_version": "1b9a732", "is_release": false}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/tests/pytest/test_with_pytest.py
new/requests-mock-1.8.0/tests/pytest/test_with_pytest.py
--- old/requests-mock-1.7.0/tests/pytest/test_with_pytest.py 2019-09-01
09:48:00.000000000 +0200
+++ new/requests-mock-1.8.0/tests/pytest/test_with_pytest.py 2020-05-02
15:10:34.000000000 +0200
@@ -1,4 +1,12 @@
+try:
+ from http import HTTPStatus
+ HTTP_STATUS_FOUND = HTTPStatus.FOUND
+except ImportError:
+ from httplib import FOUND as HTTP_STATUS_FOUND
+
+import pytest
import requests
+import requests_mock
def test_simple(requests_mock):
@@ -6,6 +14,55 @@
assert 'data' == requests.get('https://httpbin.org/get').text
+def test_redirect_and_nesting():
+ url_inner = "inner_mock://example.test/"
+ url_middle = "middle_mock://example.test/"
+ url_outer = "outer_mock://example.test/"
+ url = "https://www.example.com/"
+ with requests_mock.Mocker() as outer_mock:
+ outer_mock.get(url, text='outer' + url)
+ outer_mock.get(url_outer, text='outer' + url_outer)
+
+ with requests_mock.Mocker(real_http=True) as middle_mock:
+ middle_mock.get(url_middle, text='middle' + url_middle)
+
+ with requests_mock.Mocker() as inner_mock:
+ inner_mock.post(url_inner, status_code=HTTP_STATUS_FOUND,
headers={'location': url})
+ inner_mock.get(url, real_http=True)
+
+ assert 'outer' + url == requests.post(url_inner).text # nosec
+ with pytest.raises(requests_mock.NoMockAddress):
+ requests.get(url_middle)
+ with pytest.raises(requests_mock.NoMockAddress):
+ requests.get(url_outer)
+
+ # back to middle mock
+ with pytest.raises(requests_mock.NoMockAddress):
+ requests.post(url_inner)
+ assert 'middle' + url_middle == requests.get(url_middle).text #
nosec
+ assert 'outer' + url_outer == requests.get(url_outer).text # nosec
+
+ # back to outter mock
+ with pytest.raises(requests_mock.NoMockAddress):
+ requests.post(url_inner)
+ with pytest.raises(requests_mock.NoMockAddress):
+ requests.get(url_middle)
+ assert 'outer' + url_outer == requests.get(url_outer).text # nosec
+
+
+def test_mixed_mocks():
+ url = 'mock://example.test/'
+ with requests_mock.Mocker() as global_mock:
+ global_mock.get(url, text='global')
+ session = requests.Session()
+ text = session.get(url).text
+ assert text == 'global' # nosec
+ with requests_mock.Mocker(session=session) as session_mock:
+ session_mock.get(url, real_http=True)
+ text = session.get(url).text
+ assert text == 'global' # nosec
+
+
class TestClass(object):
def configure(self, requests_mock):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/tests/test_adapter.py
new/requests-mock-1.8.0/tests/test_adapter.py
--- old/requests-mock-1.7.0/tests/test_adapter.py 2019-09-01
09:48:00.000000000 +0200
+++ new/requests-mock-1.8.0/tests/test_adapter.py 2020-05-02
15:10:34.000000000 +0200
@@ -383,6 +383,28 @@
self.assertTrue(self.adapter.called)
self.assertFalse(m.called_once)
+ def test_reset_reverts_call_count(self):
+ # Create matchers and add calls to history
+ call_count = 3
+ matcher_count = 3
+ for i in range(matcher_count):
+ url = self.url + str(i)
+ self.adapter.register_uri('GET', url, text='resp')
+ for _ in range(call_count):
+ self.session.get(url)
+
+ # Verify call counts on adapter and matchers
+ self.assertEqual(self.adapter.call_count, matcher_count * call_count)
+ for matcher in self.adapter._matchers:
+ self.assertEqual(matcher.call_count, call_count)
+
+ self.adapter.reset()
+
+ # Verify call counts are 0 after reset
+ self.assertEqual(self.adapter.call_count, 0)
+ for matcher in self.adapter._matchers:
+ self.assertEqual(matcher.call_count, 0)
+
def test_adapter_picks_correct_adapter(self):
good = '%s://test3.url/' % self.PREFIX
self.adapter.register_uri('GET',
@@ -659,3 +681,27 @@
self.assertEqual(netloc, self.adapter.last_request.netloc)
self.assertEqual(path, self.adapter.last_request.path)
self.assertEqual(query, self.adapter.last_request.query)
+
+ def test_stream_none(self):
+ text = 'hello world'
+
+ self.adapter.register_uri('GET',
+ self.url,
+ text=text,
+ headers=self.headers)
+
+ resp = self.session.get(self.url, stream=True)
+ resps = [c for c in resp.iter_content(None, decode_unicode=True)]
+ self.assertEqual([text], resps)
+
+ def test_stream_size(self):
+ text = 'hello world'
+
+ self.adapter.register_uri('GET',
+ self.url,
+ text=text,
+ headers=self.headers)
+
+ resp = self.session.get(self.url, stream=True)
+ resps = [c for c in resp.iter_content(3, decode_unicode=True)]
+ self.assertEqual(['hel', 'lo ', 'wor', 'ld'], resps)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/tests/test_matcher.py
new/requests-mock-1.8.0/tests/test_matcher.py
--- old/requests-mock-1.7.0/tests/test_matcher.py 2019-09-01
09:48:00.000000000 +0200
+++ new/requests-mock-1.8.0/tests/test_matcher.py 2020-05-02
15:10:34.000000000 +0200
@@ -14,6 +14,7 @@
from requests_mock import adapter
from . import base
+from requests_mock.response import _MatcherResponse
ANY = adapter.ANY
@@ -294,3 +295,23 @@
matcher_method='POST',
request_data='goodbye world',
additional_matcher=test_match_body)
+
+ def test_reset_reverts_count(self):
+ url = 'mock://test/site/'
+ matcher = adapter._Matcher('GET',
+ url,
+ [_MatcherResponse()],
+ complete_qs=False,
+ additional_matcher=None,
+ request_headers={},
+ real_http=False,
+ case_sensitive=False)
+ request = adapter._RequestObjectProxy._create('GET', url)
+
+ call_count = 3
+ for _ in range(call_count):
+ matcher(request)
+
+ self.assertEqual(matcher.call_count, call_count)
+ matcher.reset()
+ self.assertEqual(matcher.call_count, 0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/tests/test_mocker.py
new/requests-mock-1.8.0/tests/test_mocker.py
--- old/requests-mock-1.7.0/tests/test_mocker.py 2019-09-01
09:48:00.000000000 +0200
+++ new/requests-mock-1.8.0/tests/test_mocker.py 2020-05-02
15:10:34.000000000 +0200
@@ -49,6 +49,66 @@
self.assertMockStopped()
mocker.stop()
+ def test_with_session(self):
+ url = 'http://test.url/path'
+ url_inner = 'http://test.url/inner'
+ url_outer = 'http://test.url/outer'
+ with requests_mock.Mocker() as global_mock:
+ global_mock.get(url_outer, text='global')
+
+ session_a = requests.Session()
+ session_b = requests.Session()
+
+ session_a_original_send = session_a.send
+ session_b_original_send = session_b.send
+ self.assertNotEqual(session_a_original_send,
session_b_original_send)
+
+ mocker_a = requests_mock.Mocker(session=session_a)
+ mocker_b = requests_mock.Mocker(session=session_b)
+
+ mocker_a.start()
+ mocker_b.start()
+
+ mocker_a.register_uri('GET', url, text='resp_a')
+ mocker_a.register_uri('GET', url_outer, real_http=True)
+ mocker_b.register_uri('GET', url, text='resp_b')
+
+ with requests_mock.Mocker(session=session_b) as mocker_b_inner:
+ mocker_b_inner.register_uri('GET', url, real_http=True)
+ mocker_b_inner.register_uri('GET', url_inner,
text='resp_b_inner')
+
+ self.assertEqual('resp_a', session_a.get(url).text)
+ self.assertEqual('resp_b', session_b.get(url).text)
+ self.assertRaises(exceptions.NoMockAddress,
+ session_a.get,
+ url_inner)
+ self.assertEqual('resp_b_inner', session_b.get(url_inner).text)
+
+ self.assertEqual('resp_a', session_a.get(url).text)
+ self.assertEqual('resp_b', session_b.get(url).text)
+ self.assertRaises(exceptions.NoMockAddress,
+ session_a.get,
+ url_inner)
+ self.assertRaises(exceptions.NoMockAddress,
+ session_b.get,
+ url_inner)
+ self.assertEqual('global', session_a.get(url_outer).text)
+ self.assertRaises(exceptions.NoMockAddress,
+ session_b.get,
+ url_outer)
+
+ self.assertNotEqual(session_a.send, session_a_original_send)
+ self.assertNotEqual(session_b.send, session_b_original_send)
+ self.assertNotEqual(session_a.send, session_b.send)
+
+ mocker_a.stop()
+ mocker_b.stop()
+
+ self.assertEqual(session_a.send, session_a_original_send)
+ self.assertEqual(session_b.send, session_b_original_send)
+ self.assertEqual(requests.Session.send, original_send)
+
+
def test_with_context_manager(self):
self.assertMockStopped()
with requests_mock.Mocker() as m:
@@ -76,6 +136,40 @@
self.assertEqual(test_text, resp.text)
self.assertEqual(test_bytes, resp.content)
+ @mock.patch('requests.adapters.HTTPAdapter.send')
+ def test_real_http_changes(self, real_send):
+ url = 'http://www.google.com/'
+ test_text = 'real http data'
+ test_bytes = test_text.encode('utf-8')
+
+ req = requests.Request(method='GET', url=url)
+ real_send.return_value = response.create_response(req.prepare(),
+ status_code=200,
+ content=test_bytes)
+
+ with requests_mock.Mocker() as m:
+ # real_http defaults to false so should raise NoMockAddress
+
+ self.assertRaises(exceptions.NoMockAddress,
+ requests.get,
+ url)
+
+ self.assertEqual(1, m.call_count)
+ self.assertEqual(0, real_send.call_count)
+
+ # change the value of real_http mid test
+ m.real_http = True
+
+ # fetch the url again and it should go through to the real url that
+ # we've mocked out at a lower level.
+ resp = requests.get(url)
+
+ self.assertEqual(1, real_send.call_count)
+ self.assertEqual(url, real_send.call_args[0][0].url)
+
+ self.assertEqual(test_text, resp.text)
+ self.assertEqual(test_bytes, resp.content)
+
@requests_mock.mock()
def test_with_test_decorator(self, m):
self._do_test(m)
@@ -207,7 +301,19 @@
copy_of_mocker = mocker.copy()
self.assertIsNot(copy_of_mocker, mocker)
self.assertEqual(copy_of_mocker._kw, mocker._kw)
- self.assertEqual(copy_of_mocker._real_http, mocker._real_http)
+ self.assertEqual(copy_of_mocker.real_http, mocker.real_http)
+
+ @requests_mock.mock()
+ def test_reset_mock_reverts_call_count(self, request_mock):
+ url = 'http://test.url/path'
+ request_mock.get(url, text='resp')
+ requests.get(url)
+
+ self.assertEqual(request_mock.call_count, 1)
+
+ # reset count and verify it is 0
+ request_mock.reset_mock()
+ self.assertEqual(request_mock.call_count, 0)
class MockerHttpMethodsTests(base.TestCase):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/tests/test_request.py
new/requests-mock-1.8.0/tests/test_request.py
--- old/requests-mock-1.7.0/tests/test_request.py 2019-09-01
09:48:00.000000000 +0200
+++ new/requests-mock-1.8.0/tests/test_request.py 2020-05-02
15:10:34.000000000 +0200
@@ -55,7 +55,10 @@
self.assertIs(False, req.stream)
# actually it's an OrderedDict, but equality works fine
- self.assertEqual({}, req.proxies)
+ # Skipping this check - it's problematic based on people's environments
+ # and in CI systems where there are proxies set up at the environment
+ # level. gh #127
+ # self.assertEqual({}, req.proxies)
def test_allow_redirects(self):
req = self.do_request(allow_redirects=False, status_code=300)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-mock-1.7.0/tests/test_response.py
new/requests-mock-1.8.0/tests/test_response.py
--- old/requests-mock-1.7.0/tests/test_response.py 2019-09-01
09:48:00.000000000 +0200
+++ new/requests-mock-1.8.0/tests/test_response.py 2020-05-02
15:10:34.000000000 +0200
@@ -130,3 +130,25 @@
resp = self.create_response(headers=headers,
text="<html><body></body></html")
self.assertEqual('ISO-8859-1', resp.encoding)
+
+ def test_default_reason(self):
+ resp = self.create_response()
+ self.assertEqual('OK', resp.reason)
+
+ def test_custom_reason(self):
+ reason = 'Live long and prosper'
+ resp = self.create_response(status_code=201, reason=reason)
+
+ self.assertEqual(201, resp.status_code)
+ self.assertEqual(reason, resp.reason)
+
+ def test_some_other_response_reasons(self):
+ reasons = {
+ 301: 'Moved Permanently',
+ 410: 'Gone',
+ 503: 'Service Unavailable',
+ }
+
+ for code, reason in six.iteritems(reasons):
+ self.assertEqual(reason,
+ self.create_response(status_code=code).reason)