aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/requests-mock/py3
diff options
context:
space:
mode:
authoralexv-smirnov <alex@ydb.tech>2023-12-01 12:02:50 +0300
committeralexv-smirnov <alex@ydb.tech>2023-12-01 13:28:10 +0300
commit0e578a4c44d4abd539d9838347b9ebafaca41dfb (patch)
treea0c1969c37f818c830ebeff9c077eacf30be6ef8 /contrib/python/requests-mock/py3
parent84f2d3d4cc985e63217cff149bd2e6d67ae6fe22 (diff)
downloadydb-0e578a4c44d4abd539d9838347b9ebafaca41dfb.tar.gz
Change "ya.make"
Diffstat (limited to 'contrib/python/requests-mock/py3')
-rw-r--r--contrib/python/requests-mock/py3/.dist-info/METADATA144
-rw-r--r--contrib/python/requests-mock/py3/.dist-info/entry_points.txt2
-rw-r--r--contrib/python/requests-mock/py3/.dist-info/top_level.txt1
-rw-r--r--contrib/python/requests-mock/py3/AUTHORS50
-rw-r--r--contrib/python/requests-mock/py3/LICENSE180
-rw-r--r--contrib/python/requests-mock/py3/README.rst101
-rw-r--r--contrib/python/requests-mock/py3/requests_mock/__init__.py37
-rw-r--r--contrib/python/requests-mock/py3/requests_mock/adapter.py323
-rw-r--r--contrib/python/requests-mock/py3/requests_mock/compat.py30
-rw-r--r--contrib/python/requests-mock/py3/requests_mock/contrib/__init__.py0
-rw-r--r--contrib/python/requests-mock/py3/requests_mock/contrib/_pytest_plugin.py86
-rw-r--r--contrib/python/requests-mock/py3/requests_mock/contrib/fixture.py27
-rw-r--r--contrib/python/requests-mock/py3/requests_mock/exceptions.py30
-rw-r--r--contrib/python/requests-mock/py3/requests_mock/mocker.py342
-rw-r--r--contrib/python/requests-mock/py3/requests_mock/py.typed0
-rw-r--r--contrib/python/requests-mock/py3/requests_mock/request.py178
-rw-r--r--contrib/python/requests-mock/py3/requests_mock/response.py281
-rw-r--r--contrib/python/requests-mock/py3/ya.make54
18 files changed, 1866 insertions, 0 deletions
diff --git a/contrib/python/requests-mock/py3/.dist-info/METADATA b/contrib/python/requests-mock/py3/.dist-info/METADATA
new file mode 100644
index 00000000000..d8eadeaec20
--- /dev/null
+++ b/contrib/python/requests-mock/py3/.dist-info/METADATA
@@ -0,0 +1,144 @@
+Metadata-Version: 2.1
+Name: requests-mock
+Version: 1.11.0
+Summary: Mock out responses from the requests package
+Home-page: https://requests-mock.readthedocs.io/
+Author: Jamie Lennox
+Author-email: jamielennox@gmail.com
+License: Apache-2
+Project-URL: Source, https://github.com/jamielennox/requests-mock
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: Information Technology
+Classifier: License :: OSI Approved :: Apache Software License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.4
+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 :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
+Classifier: Topic :: Software Development :: Testing
+License-File: LICENSE
+Requires-Dist: requests (<3,>=2.3)
+Requires-Dist: six
+Provides-Extra: fixture
+Requires-Dist: fixtures ; extra == 'fixture'
+Provides-Extra: test
+Requires-Dist: fixtures ; extra == 'test'
+Requires-Dist: purl ; extra == 'test'
+Requires-Dist: pytest ; extra == 'test'
+Requires-Dist: sphinx ; extra == 'test'
+Requires-Dist: testtools ; extra == 'test'
+Requires-Dist: requests-futures ; extra == 'test'
+Requires-Dist: mock ; (( python_version < '3.3')) and extra == 'test'
+
+===============================
+requests-mock
+===============================
+
+.. image:: https://badge.fury.io/py/requests-mock.png
+ :target: https://pypi.org/project/requests-mock/
+
+Intro
+=====
+
+`requests-mock` provides a building block to stub out the HTTP `requests`_ portions of your testing code.
+You should checkout the `docs`_ for more information.
+
+The Basics
+==========
+
+Everything in `requests`_ eventually goes through an adapter to do the transport work.
+`requests-mock` creates a custom `adapter` that allows you to predefine responses when certain URIs are called.
+
+There are then a number of methods provided to get the adapter used.
+
+A simple example:
+
+.. code:: python
+
+ >>> import requests
+ >>> import requests_mock
+
+ >>> session = requests.Session()
+ >>> adapter = requests_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 be useful,
+so you can use `requests_mock.Mocker` to get the adapter into place.
+
+As a context manager:
+
+.. code:: python
+
+ >>> with requests_mock.Mocker() as m:
+ ... m.get('http://test.com', text='data')
+ ... requests.get('http://test.com').text
+ ...
+ 'data'
+
+Or as a decorator:
+
+.. code:: python
+
+ >>> @requests_mock.Mocker()
+ ... def test_func(m):
+ ... m.get('http://test.com', text='data')
+ ... return requests.get('http://test.com').text
+ ...
+ >>> 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
+==============
+
+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
+=======
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may
+not use this file except in compliance with the License. You may obtain
+a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations
+under the License.
+
+.. _requests: https://requests.readthedocs.io
+.. _docs: https://requests-mock.readthedocs.io/
+.. _GitHub: https://github.com/jamielennox/requests-mock
+.. _StackOverflow: https://stackoverflow.com/questions/tagged/requests-mock
+
diff --git a/contrib/python/requests-mock/py3/.dist-info/entry_points.txt b/contrib/python/requests-mock/py3/.dist-info/entry_points.txt
new file mode 100644
index 00000000000..b157e5a5ec9
--- /dev/null
+++ b/contrib/python/requests-mock/py3/.dist-info/entry_points.txt
@@ -0,0 +1,2 @@
+[pytest11]
+requests_mock = requests_mock.contrib._pytest_plugin
diff --git a/contrib/python/requests-mock/py3/.dist-info/top_level.txt b/contrib/python/requests-mock/py3/.dist-info/top_level.txt
new file mode 100644
index 00000000000..65a92dd61d2
--- /dev/null
+++ b/contrib/python/requests-mock/py3/.dist-info/top_level.txt
@@ -0,0 +1 @@
+requests_mock
diff --git a/contrib/python/requests-mock/py3/AUTHORS b/contrib/python/requests-mock/py3/AUTHORS
new file mode 100644
index 00000000000..ae2e02a6123
--- /dev/null
+++ b/contrib/python/requests-mock/py3/AUTHORS
@@ -0,0 +1,50 @@
+Adam Johnson <me@adamj.eu>
+Alex Peters <alex@peters.net>
+Allan Lewis <allanlewis99@gmail.com>
+Andreas Jaeger <aj@suse.com>
+Andrii Oriekhov <andriyorehov@gmail.com>
+Arjan Keeman <arjan.keeman@falckon.nl>
+Axel H <noirbizarre@users.noreply.github.com>
+Christian Clauss <cclauss@me.com>
+Colas Le Guernic <clslgrnc@users.noreply.github.com>
+Cyrille Corpet <cyrille@bayesimpact.org>
+Darragh Bailey <dbailey@hpe.com>
+David Kremer <courrier@david-kremer.fr>
+Ian Cordasco <ian.cordasco@rackspace.com>
+Ilya Konstantinov <ilya.konstantinov@gmail.com>
+Jamie Lennox <jamie.lennox@agoda.com>
+Jamie Lennox <jamie@vibrato.com.au>
+Jamie Lennox <jamielennox@gmail.com>
+Jamie Lennox <jamielennox@redhat.com>
+Janne Pulkkinen <janne.pulkkinen@protonmail.com>
+Janonymous <janonymous.codevulture@gmail.com>
+Jelle van der Waa <jelle@archlinux.org>
+Jeremy Stanley <fungi@yuggoth.org>
+Jochen Kupperschmidt <homework@nwsnet.de>
+Joel Andrews <oldsneerjaw@gmail.com>
+Jon Dufresne <jon.dufresne@gmail.com>
+Kenny Nguyen <kkenny.nguyen@pm.me>
+Louis Taylor <louis@kragniz.eu>
+Manuel Kaufmann <humitos@gmail.com>
+Matthias Bilger <matthias@bilger.info>
+Michał Górny <mgorny@gentoo.org>
+Miroslav Šedivý <6774676+eumiro@users.noreply.github.com>
+Monty Taylor <mordred@inaugust.com>
+Noam <noamkush@gmail.com>
+Pascal Corpet <pascal@bayesimpact.org>
+Peter Hodge <peter.hodge84@gmail.com>
+Petre Mierlutiu <petrem@users.noreply.github.com>
+Rick van de Loo <rickvandeloo@gmail.com>
+Ryan Brooke Payne <ryan.payne@daveramsey.com>
+Sebastian Kalinowski <sebastian@kalinowski.eu>
+Simon Willison <swillison@gmail.com>
+Stefaan Lippens <stefaan.lippens@vito.be>
+Swapnil Kulkarni (coolsvap) <me@coolsvap.net>
+Ville Skyttä <ville.skytta@iki.fi>
+boncheff <boncheff@users.noreply.github.com>
+clslgrnc <clslgrnc@users.noreply.github.com>
+dongfangtianyu <7629022+dongfangtianyu@users.noreply.github.com>
+popokatapepel <jan-seins@hotmail.de>
+reedip <reedip.banerjee@nectechnologies.in>
+rfportilla <rfportilla@yahoo.com>
+voith <voithjm1@gmail.com>
diff --git a/contrib/python/requests-mock/py3/LICENSE b/contrib/python/requests-mock/py3/LICENSE
new file mode 100644
index 00000000000..d88b5784ba5
--- /dev/null
+++ b/contrib/python/requests-mock/py3/LICENSE
@@ -0,0 +1,180 @@
+Copyright (c) 2014, Jamie Lennox
+All rights reserved.
+
+
+ Apache License
+ Version 2.0, January 2004
+ https://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+
diff --git a/contrib/python/requests-mock/py3/README.rst b/contrib/python/requests-mock/py3/README.rst
new file mode 100644
index 00000000000..1281d339a59
--- /dev/null
+++ b/contrib/python/requests-mock/py3/README.rst
@@ -0,0 +1,101 @@
+===============================
+requests-mock
+===============================
+
+.. image:: https://badge.fury.io/py/requests-mock.png
+ :target: https://pypi.org/project/requests-mock/
+
+Intro
+=====
+
+`requests-mock` provides a building block to stub out the HTTP `requests`_ portions of your testing code.
+You should checkout the `docs`_ for more information.
+
+The Basics
+==========
+
+Everything in `requests`_ eventually goes through an adapter to do the transport work.
+`requests-mock` creates a custom `adapter` that allows you to predefine responses when certain URIs are called.
+
+There are then a number of methods provided to get the adapter used.
+
+A simple example:
+
+.. code:: python
+
+ >>> import requests
+ >>> import requests_mock
+
+ >>> session = requests.Session()
+ >>> adapter = requests_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 be useful,
+so you can use `requests_mock.Mocker` to get the adapter into place.
+
+As a context manager:
+
+.. code:: python
+
+ >>> with requests_mock.Mocker() as m:
+ ... m.get('http://test.com', text='data')
+ ... requests.get('http://test.com').text
+ ...
+ 'data'
+
+Or as a decorator:
+
+.. code:: python
+
+ >>> @requests_mock.Mocker()
+ ... def test_func(m):
+ ... m.get('http://test.com', text='data')
+ ... return requests.get('http://test.com').text
+ ...
+ >>> 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
+==============
+
+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
+=======
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may
+not use this file except in compliance with the License. You may obtain
+a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations
+under the License.
+
+.. _requests: https://requests.readthedocs.io
+.. _docs: https://requests-mock.readthedocs.io/
+.. _GitHub: https://github.com/jamielennox/requests-mock
+.. _StackOverflow: https://stackoverflow.com/questions/tagged/requests-mock
diff --git a/contrib/python/requests-mock/py3/requests_mock/__init__.py b/contrib/python/requests-mock/py3/requests_mock/__init__.py
new file mode 100644
index 00000000000..799b752ee7c
--- /dev/null
+++ b/contrib/python/requests-mock/py3/requests_mock/__init__.py
@@ -0,0 +1,37 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from requests_mock.adapter import Adapter, ANY
+from requests_mock.exceptions import MockException, NoMockAddress
+from requests_mock.mocker import mock, Mocker, MockerCore
+from requests_mock.mocker import DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT
+from requests_mock.response import create_response, CookieJar
+
+
+__all__ = ['Adapter',
+ 'ANY',
+ 'create_response',
+ 'CookieJar',
+ 'mock',
+ 'Mocker',
+ 'MockerCore',
+ 'MockException',
+ 'NoMockAddress',
+
+ 'DELETE',
+ 'GET',
+ 'HEAD',
+ 'OPTIONS',
+ 'PATCH',
+ 'POST',
+ 'PUT',
+ ]
diff --git a/contrib/python/requests-mock/py3/requests_mock/adapter.py b/contrib/python/requests-mock/py3/requests_mock/adapter.py
new file mode 100644
index 00000000000..e0560b22265
--- /dev/null
+++ b/contrib/python/requests-mock/py3/requests_mock/adapter.py
@@ -0,0 +1,323 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import weakref
+
+from requests.adapters import BaseAdapter
+from requests.utils import requote_uri
+import six
+from six.moves.urllib import parse as urlparse
+
+from requests_mock import exceptions
+from requests_mock.request import _RequestObjectProxy
+from requests_mock.response import _MatcherResponse
+
+import logging
+
+logger = logging.getLogger(__name__)
+
+try:
+ import purl
+ purl_types = (purl.URL,)
+except ImportError:
+ purl = None
+ purl_types = ()
+
+ANY = object()
+
+
+class _RequestHistoryTracker(object):
+
+ def __init__(self):
+ self.request_history = []
+
+ def _add_to_history(self, request):
+ self.request_history.append(request)
+
+ @property
+ def last_request(self):
+ """Retrieve the latest request sent"""
+ try:
+ return self.request_history[-1]
+ except IndexError:
+ return None
+
+ @property
+ def called(self):
+ return self.call_count > 0
+
+ @property
+ def called_once(self):
+ return self.call_count == 1
+
+ @property
+ 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.
+
+ This exception is caught at the mocker level and allows it to execute this
+ request through the real requests mechanism rather than the mocker.
+
+ It should never be exposed to a user.
+ """
+
+
+class _Matcher(_RequestHistoryTracker):
+ """Contains all the information about a provided URL to match."""
+
+ def __init__(self, method, url, responses, complete_qs, request_headers,
+ additional_matcher, real_http, case_sensitive):
+ """
+ :param bool complete_qs: Match the entire query string. By default URLs
+ match if all the provided matcher query arguments are matched and
+ extra query arguments are ignored. Set complete_qs to true to
+ require that the entire query string needs to match.
+ """
+ super(_Matcher, self).__init__()
+
+ self._method = method
+ self._url = url
+ self._responses = responses
+ self._complete_qs = complete_qs
+ self._request_headers = request_headers
+ self._real_http = real_http
+ self._additional_matcher = additional_matcher
+
+ # url can be a regex object or ANY so don't always run urlparse
+ if isinstance(url, six.string_types):
+ url_parts = urlparse.urlparse(url)
+ self._scheme = url_parts.scheme.lower()
+ self._netloc = url_parts.netloc.lower()
+ self._path = requote_uri(url_parts.path or '/')
+ self._query = url_parts.query
+
+ if not case_sensitive:
+ self._path = self._path.lower()
+ self._query = self._query.lower()
+
+ elif isinstance(url, purl_types):
+ self._scheme = url.scheme()
+ self._netloc = url.netloc()
+ self._path = url.path()
+ self._query = url.query()
+
+ if not case_sensitive:
+ self._path = self._path.lower()
+ self._query = self._query.lower()
+
+ else:
+ self._scheme = None
+ self._netloc = None
+ self._path = None
+ self._query = None
+
+ def _match_method(self, request):
+ if self._method is ANY:
+ return True
+
+ if request.method.lower() == self._method.lower():
+ return True
+
+ return False
+
+ def _match_url(self, request):
+ if self._url is ANY:
+ return True
+
+ # regular expression matching
+ if hasattr(self._url, 'search'):
+ return self._url.search(request.url) is not None
+
+ # scheme is always matched case insensitive
+ if self._scheme and request.scheme.lower() != self._scheme:
+ return False
+
+ # netloc is always matched case insensitive
+ if self._netloc and request.netloc.lower() != self._netloc:
+ return False
+
+ if (request.path or '/') != self._path:
+ return False
+
+ # construct our own qs structure as we remove items from it below
+ request_qs = urlparse.parse_qs(request.query, keep_blank_values=True)
+ matcher_qs = urlparse.parse_qs(self._query, keep_blank_values=True)
+
+ for k, vals in six.iteritems(matcher_qs):
+ for v in vals:
+ try:
+ request_qs.get(k, []).remove(v)
+ except ValueError:
+ return False
+
+ if self._complete_qs:
+ for v in six.itervalues(request_qs):
+ if v:
+ return False
+
+ return True
+
+ def _match_headers(self, request):
+ for k, vals in six.iteritems(self._request_headers):
+
+ try:
+ header = request.headers[k]
+ except KeyError:
+ # NOTE(jamielennox): This seems to be a requests 1.2/2
+ # difference, in 2 they are just whatever the user inputted in
+ # 1 they are bytes. Let's optionally handle both and look at
+ # removing this when we depend on requests 2.
+ if not isinstance(k, six.text_type):
+ return False
+
+ try:
+ header = request.headers[k.encode('utf-8')]
+ except KeyError:
+ return False
+
+ if header != vals:
+ return False
+
+ return True
+
+ def _match_additional(self, request):
+ if callable(self._additional_matcher):
+ return self._additional_matcher(request)
+
+ if self._additional_matcher is not None:
+ raise TypeError("Unexpected format of additional matcher.")
+
+ return True
+
+ def _match(self, request):
+ return (self._match_method(request) and
+ self._match_url(request) and
+ self._match_headers(request) and
+ self._match_additional(request))
+
+ def __call__(self, request):
+ if not self._match(request):
+ return None
+
+ # doing this before _add_to_history means real requests are not stored
+ # in the request history. I'm not sure what is better here.
+ if self._real_http:
+ raise _RunRealHTTP()
+
+ if len(self._responses) > 1:
+ response_matcher = self._responses.pop(0)
+ else:
+ response_matcher = self._responses[0]
+
+ self._add_to_history(request)
+ return response_matcher.get_response(request)
+
+
+class Adapter(BaseAdapter, _RequestHistoryTracker):
+ """A fake adapter than can return predefined responses.
+
+ """
+ def __init__(self, case_sensitive=False):
+ super(Adapter, self).__init__()
+ self._case_sensitive = case_sensitive
+ self._matchers = []
+
+ def send(self, request, **kwargs):
+ request = _RequestObjectProxy(request,
+ case_sensitive=self._case_sensitive,
+ **kwargs)
+ self._add_to_history(request)
+
+ for matcher in reversed(self._matchers):
+ try:
+ resp = matcher(request)
+ except Exception:
+ request._matcher = weakref.ref(matcher)
+ raise
+
+ if resp is not None:
+ request._matcher = weakref.ref(matcher)
+ resp.connection = self
+ logger.debug('{} {} {}'.format(request._request.method,
+ request._request.url,
+ resp.status_code))
+ return resp
+
+ raise exceptions.NoMockAddress(request)
+
+ def close(self):
+ pass
+
+ def register_uri(self, method, url, response_list=None, **kwargs):
+ """Register a new URI match and fake response.
+
+ :param str method: The HTTP method to match.
+ :param str url: The URL to match.
+ """
+ complete_qs = kwargs.pop('complete_qs', False)
+ additional_matcher = kwargs.pop('additional_matcher', None)
+ request_headers = kwargs.pop('request_headers', {})
+ real_http = kwargs.pop('_real_http', False)
+ json_encoder = kwargs.pop('json_encoder', None)
+
+ if response_list and kwargs:
+ raise RuntimeError('You should specify either a list of '
+ 'responses OR response kwargs. Not both.')
+ elif real_http and (response_list or kwargs):
+ raise RuntimeError('You should specify either response data '
+ 'OR real_http. Not both.')
+ elif not response_list:
+ if json_encoder is not None:
+ kwargs['json_encoder'] = json_encoder
+ response_list = [] if real_http else [kwargs]
+
+ # NOTE(jamielennox): case_sensitive is not present as a kwarg because i
+ # think there would be an edge case where the adapter and register_uri
+ # had different values.
+ # Ideally case_sensitive would be a value passed to match() however
+ # this would change the contract of matchers so we pass ito to the
+ # proxy and the matcher separately.
+ responses = [_MatcherResponse(**k) for k in response_list]
+ matcher = _Matcher(method,
+ url,
+ responses,
+ case_sensitive=self._case_sensitive,
+ complete_qs=complete_qs,
+ additional_matcher=additional_matcher,
+ request_headers=request_headers,
+ real_http=real_http)
+ self.add_matcher(matcher)
+ return matcher
+
+ def add_matcher(self, matcher):
+ """Register a custom matcher.
+
+ A matcher is a callable that takes a `requests.Request` and returns a
+ `requests.Response` if it matches or None if not.
+
+ :param callable matcher: The matcher to execute.
+ """
+ self._matchers.append(matcher)
+
+ def reset(self):
+ super(Adapter, self).reset()
+ for matcher in self._matchers:
+ matcher.reset()
+
+
+__all__ = ['Adapter']
diff --git a/contrib/python/requests-mock/py3/requests_mock/compat.py b/contrib/python/requests-mock/py3/requests_mock/compat.py
new file mode 100644
index 00000000000..8b6293af157
--- /dev/null
+++ b/contrib/python/requests-mock/py3/requests_mock/compat.py
@@ -0,0 +1,30 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+class _FakeHTTPMessage(object):
+
+ def __init__(self, headers):
+ self.headers = headers
+
+ def getheaders(self, name):
+ try:
+ return [self.headers[name]]
+ except KeyError:
+ return []
+
+ def get_all(self, name, failobj=None):
+ # python 3 only, overrides email.message.Message.get_all
+ try:
+ return [self.headers[name]]
+ except KeyError:
+ return failobj
diff --git a/contrib/python/requests-mock/py3/requests_mock/contrib/__init__.py b/contrib/python/requests-mock/py3/requests_mock/contrib/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/contrib/python/requests-mock/py3/requests_mock/contrib/__init__.py
diff --git a/contrib/python/requests-mock/py3/requests_mock/contrib/_pytest_plugin.py b/contrib/python/requests-mock/py3/requests_mock/contrib/_pytest_plugin.py
new file mode 100644
index 00000000000..bb6cd2b973e
--- /dev/null
+++ b/contrib/python/requests-mock/py3/requests_mock/contrib/_pytest_plugin.py
@@ -0,0 +1,86 @@
+import pytest
+
+
+# RHEL 7 ships pytest 2.7 which doesn't have the 'bool' type to addini. This
+# broke pytest for EPEL: https://bugzilla.redhat.com/show_bug.cgi?id=1605138
+# If it's older than 2.9 we handle bool conversion ourselves. Remove this when
+# we can rely on a newer pytest.
+#
+# Version 3 is also where the @yield_fixture decorator was deprecated and you
+# can now just use @fixture, so we handle both of those cases as well.
+
+try:
+ _pytest_version = tuple([
+ int(x) for x in pytest.__version__.split('.')[:2]
+ ])
+ _pytest29 = _pytest_version >= (2, 9)
+ _pytest30 = _pytest_version >= (3, 0)
+except Exception:
+ _pytest29 = False
+ _pytest30 = False
+
+
+if not _pytest29:
+ _case_type = None
+ _case_default = 'false'
+
+ # Copied from pytest 2.9.0 where bool was introduced. It's what happens
+ # internally if we specify a bool type argument.
+ def _strtobool(val):
+ """Convert a string representation of truth to true (1) or false (0).
+
+ True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
+ are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
+ 'val' is anything else.
+
+ .. note:: copied from distutils.util
+ """
+ val = val.lower()
+ if val in ('y', 'yes', 't', 'true', 'on', '1'):
+ return 1
+ elif val in ('n', 'no', 'f', 'false', 'off', '0'):
+ return 0
+ else:
+ raise ValueError("invalid truth value %r" % (val,))
+
+ def _bool_value(value):
+ return bool(_strtobool(value.strip()))
+
+else:
+ _case_type = 'bool'
+ _case_default = False
+
+ def _bool_value(value):
+ return value
+
+
+if _pytest30:
+ _fixture_type = pytest.fixture
+else:
+ _fixture_type = pytest.yield_fixture
+
+
+def pytest_addoption(parser):
+ parser.addini('requests_mock_case_sensitive',
+ 'Use case sensitive matching in requests_mock',
+ type=_case_type,
+ default=_case_default)
+
+
+@_fixture_type(scope='function') # executed on every test
+def requests_mock(request):
+ """Mock out the requests component of your code with defined responses.
+
+ Mocks out any requests made through the python requests library with useful
+ responses for unit testing. See:
+ https://requests-mock.readthedocs.io/en/latest/
+ """
+ # pytest plugins get loaded immediately. If we import requests_mock it
+ # imports requests and then SSL which prevents gevent patching. Late load.
+ import requests_mock as rm_module
+
+ case_sensitive = request.config.getini('requests_mock_case_sensitive')
+ kw = {'case_sensitive': _bool_value(case_sensitive)}
+
+ with rm_module.Mocker(**kw) as m:
+ yield m
diff --git a/contrib/python/requests-mock/py3/requests_mock/contrib/fixture.py b/contrib/python/requests-mock/py3/requests_mock/contrib/fixture.py
new file mode 100644
index 00000000000..0c239475664
--- /dev/null
+++ b/contrib/python/requests-mock/py3/requests_mock/contrib/fixture.py
@@ -0,0 +1,27 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import fixtures
+
+from requests_mock import mocker
+
+
+class Fixture(fixtures.Fixture, mocker.MockerCore):
+
+ def __init__(self, **kwargs):
+ fixtures.Fixture.__init__(self)
+ mocker.MockerCore.__init__(self, **kwargs)
+
+ def setUp(self):
+ super(Fixture, self).setUp()
+ self.start()
+ self.addCleanup(self.stop)
diff --git a/contrib/python/requests-mock/py3/requests_mock/exceptions.py b/contrib/python/requests-mock/py3/requests_mock/exceptions.py
new file mode 100644
index 00000000000..feeb1aa312f
--- /dev/null
+++ b/contrib/python/requests-mock/py3/requests_mock/exceptions.py
@@ -0,0 +1,30 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+class MockException(Exception):
+ """Base Exception for library"""
+
+
+class NoMockAddress(MockException):
+ """The requested URL was not mocked"""
+
+ def __init__(self, request):
+ self.request = request
+
+ def __str__(self):
+ return "No mock address: %s %s" % (self.request.method,
+ self.request.url)
+
+
+class InvalidRequest(MockException):
+ """This call cannot be made under a mocked environment"""
diff --git a/contrib/python/requests-mock/py3/requests_mock/mocker.py b/contrib/python/requests-mock/py3/requests_mock/mocker.py
new file mode 100644
index 00000000000..d3bc85538e3
--- /dev/null
+++ b/contrib/python/requests-mock/py3/requests_mock/mocker.py
@@ -0,0 +1,342 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import contextlib
+import functools
+import sys
+import threading
+import types
+
+import requests
+import six
+
+from requests_mock import adapter
+from requests_mock import exceptions
+
+DELETE = 'DELETE'
+GET = 'GET'
+HEAD = 'HEAD'
+OPTIONS = 'OPTIONS'
+PATCH = 'PATCH'
+POST = 'POST'
+PUT = 'PUT'
+
+_original_send = requests.Session.send
+
+# NOTE(phodge): we need to use an RLock (reentrant lock) here because
+# requests.Session.send() is reentrant. See further comments where we
+# monkeypatch get_adapter()
+_send_lock = threading.RLock()
+
+
+@contextlib.contextmanager
+def threading_rlock(timeout):
+ kwargs = {}
+ if sys.version_info.major >= 3:
+ # python2 doesn't support the timeout argument
+ kwargs['timeout'] = timeout
+
+ if not _send_lock.acquire(**kwargs):
+ m = "Could not acquire threading lock - possible deadlock scenario"
+ raise Exception(m)
+
+ try:
+ yield
+ finally:
+ _send_lock.release()
+
+
+def _is_bound_method(method):
+ """
+ bound_method 's self is a obj
+ unbound_method 's self is None
+ """
+ if isinstance(method, types.MethodType) and six.get_method_self(method):
+ return True
+ return False
+
+
+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 method is a bound_method, can direct setattr
+ """
+ if not isinstance(target, type) and not _is_bound_method(method):
+ method = six.create_bound_method(method, target)
+
+ setattr(target, name, method)
+
+
+class MockerCore(object):
+ """A wrapper around common mocking functions.
+
+ Automate the process of mocking the requests library. This will keep the
+ same general options available and prevent repeating code.
+ """
+
+ _PROXY_FUNCS = {
+ 'last_request',
+ 'add_matcher',
+ 'request_history',
+ 'called',
+ 'called_once',
+ 'call_count',
+ 'reset',
+ }
+
+ case_sensitive = False
+ """case_sensitive handles a backwards incompatible bug. The URL used to
+ match against our matches and that is saved in request_history is always
+ lowercased. This is incorrect as it reports incorrect history to the user
+ and doesn't allow case sensitive path matching.
+
+ Unfortunately fixing this change is backwards incompatible in the 1.X
+ series as people may rely on this behaviour. To work around this you can
+ globally set:
+
+ requests_mock.mock.case_sensitive = True
+
+ or for pytest set in your configuration:
+
+ [pytest]
+ requests_mock_case_sensitive = True
+
+ which will prevent the lowercase being executed and return case sensitive
+ url and query information.
+
+ This will become the default in a 2.X release. See bug: #1584008.
+ """
+
+ 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._json_encoder = kwargs.pop('json_encoder', None)
+ self.real_http = kwargs.pop('real_http', False)
+ self._last_send = None
+
+ if kwargs:
+ raise TypeError('Unexpected Arguments: %s' % ', '.join(kwargs))
+
+ def start(self):
+ """Start mocking requests.
+
+ Install the adapter and the wrappers required to intercept requests.
+ """
+ if self._last_send:
+ raise RuntimeError('Mocker has already been started')
+
+ # 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):
+ # NOTE(phodge): we need to use a threading lock here in case there
+ # are multiple threads running - one thread could restore the
+ # original get_adapter() just as a second thread is about to
+ # execute _original_send() below
+ with threading_rlock(timeout=10):
+ # mock get_adapter
+ #
+ # NOTE(phodge): requests.Session.send() is actually
+ # reentrant due to how it resolves redirects with nested
+ # calls to send(), however the reentry occurs _after_ the
+ # call to self.get_adapter(), so it doesn't matter that we
+ # will restore _last_get_adapter before a nested send() has
+ # completed as long as we monkeypatch get_adapter() each
+ # time immediately before calling original send() like we
+ # are doing here.
+ _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 that the user has messed up and is somehow
+ # nesting their mockers. If we call last_send at this point
+ # then we end up calling this function again and the outer
+ # level adapter ends up winning. All we really care about here
+ # is that our adapter is in place before calling send so we
+ # always jump directly to the real function so that our most
+ # recently patched send call ends up putting in the most recent
+ # adapter. It feels funny, but it works.
+
+ try:
+ return _original_send(session, request, **kwargs)
+ except exceptions.NoMockAddress:
+ 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:
+ # restore get_adapter
+ _set_method(session, "get_adapter", self._last_get_adapter)
+
+ # 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)
+
+ _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:
+ 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:
+ return getattr(self._adapter, name)
+ except AttributeError:
+ pass
+
+ raise AttributeError(name)
+
+ def register_uri(self, *args, **kwargs):
+ # you can pass real_http here, but it's private to pass direct to the
+ # adapter, because if you pass direct to the adapter you'll see the exc
+ kwargs['_real_http'] = kwargs.pop('real_http', False)
+ kwargs.setdefault('json_encoder', self._json_encoder)
+ return self._adapter.register_uri(*args, **kwargs)
+
+ def request(self, *args, **kwargs):
+ return self.register_uri(*args, **kwargs)
+
+ def get(self, *args, **kwargs):
+ return self.request(GET, *args, **kwargs)
+
+ def options(self, *args, **kwargs):
+ return self.request(OPTIONS, *args, **kwargs)
+
+ def head(self, *args, **kwargs):
+ return self.request(HEAD, *args, **kwargs)
+
+ def post(self, *args, **kwargs):
+ return self.request(POST, *args, **kwargs)
+
+ def put(self, *args, **kwargs):
+ return self.request(PUT, *args, **kwargs)
+
+ def patch(self, *args, **kwargs):
+ return self.request(PATCH, *args, **kwargs)
+
+ def delete(self, *args, **kwargs):
+ return self.request(DELETE, *args, **kwargs)
+
+
+class Mocker(MockerCore):
+ """The standard entry point for mock Adapter loading.
+ """
+
+ #: Defines with what should method name begin to be patched
+ TEST_PREFIX = 'test'
+
+ def __init__(self, **kwargs):
+ """Create a new mocker adapter.
+
+ :param str kw: Pass the mock object through to the decorated function
+ as this named keyword argument, rather than a positional argument.
+ :param bool real_http: True to send the request to the real requested
+ uri if there is not a mock installed for it. Defaults to False.
+ """
+ self._kw = kwargs.pop('kw', None)
+ super(Mocker, self).__init__(**kwargs)
+
+ def __enter__(self):
+ self.start()
+ return self
+
+ def __exit__(self, type, value, traceback):
+ self.stop()
+
+ def __call__(self, obj):
+ if isinstance(obj, type):
+ return self.decorate_class(obj)
+
+ return self.decorate_callable(obj)
+
+ def copy(self):
+ """Returns an exact copy of current mock
+ """
+ m = type(self)(
+ kw=self._kw,
+ real_http=self.real_http,
+ case_sensitive=self.case_sensitive
+ )
+ return m
+
+ def decorate_callable(self, func):
+ """Decorates a callable
+
+ :param callable func: callable to decorate
+ """
+ @functools.wraps(func)
+ def inner(*args, **kwargs):
+ with self.copy() as m:
+ if self._kw:
+ kwargs[self._kw] = m
+ else:
+ args = list(args)
+ args.append(m)
+
+ return func(*args, **kwargs)
+
+ return inner
+
+ def decorate_class(self, klass):
+ """Decorates methods in a class with request_mock
+
+ Method will be decorated only if it name begins with `TEST_PREFIX`
+
+ :param object klass: class which methods will be decorated
+ """
+ for attr_name in dir(klass):
+ if not attr_name.startswith(self.TEST_PREFIX):
+ continue
+
+ attr = getattr(klass, attr_name)
+ if not hasattr(attr, '__call__'):
+ continue
+
+ m = self.copy()
+ setattr(klass, attr_name, m(attr))
+
+ return klass
+
+
+mock = Mocker
diff --git a/contrib/python/requests-mock/py3/requests_mock/py.typed b/contrib/python/requests-mock/py3/requests_mock/py.typed
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/contrib/python/requests-mock/py3/requests_mock/py.typed
diff --git a/contrib/python/requests-mock/py3/requests_mock/request.py b/contrib/python/requests-mock/py3/requests_mock/request.py
new file mode 100644
index 00000000000..05cbc3d4a35
--- /dev/null
+++ b/contrib/python/requests-mock/py3/requests_mock/request.py
@@ -0,0 +1,178 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import copy
+import json
+
+import requests
+import six
+from six.moves.urllib import parse as urlparse
+
+
+class _RequestObjectProxy(object):
+ """A wrapper around a requests.Request that gives some extra information.
+
+ This will be important both for matching and so that when it's save into
+ the request_history users will be able to access these properties.
+ """
+
+ def __init__(self, request, **kwargs):
+ self._request = request
+ self._matcher = None
+ self._url_parts_ = None
+ self._qs = None
+
+ # All of these params should always exist but we use a default
+ # to make the test setup easier.
+ self._timeout = kwargs.pop('timeout', None)
+ self._allow_redirects = kwargs.pop('allow_redirects', None)
+ self._verify = kwargs.pop('verify', None)
+ self._stream = kwargs.pop('stream', None)
+ self._cert = kwargs.pop('cert', None)
+ self._proxies = copy.deepcopy(kwargs.pop('proxies', {}))
+
+ # FIXME(jamielennox): This is part of bug #1584008 and should default
+ # to True (or simply removed) in a major version bump.
+ self._case_sensitive = kwargs.pop('case_sensitive', False)
+
+ def __getattr__(self, name):
+ # there should be a better way to exclude this, but I don't want to
+ # implement __setstate__ just not forward it to the request. You can't
+ # actually define the method and raise AttributeError there either.
+ if name in ('__setstate__',):
+ raise AttributeError(name)
+
+ return getattr(self._request, name)
+
+ @property
+ def _url_parts(self):
+ if self._url_parts_ is None:
+ url = self._request.url
+
+ if not self._case_sensitive:
+ url = url.lower()
+
+ self._url_parts_ = urlparse.urlparse(url)
+
+ return self._url_parts_
+
+ @property
+ def scheme(self):
+ return self._url_parts.scheme
+
+ @property
+ def netloc(self):
+ return self._url_parts.netloc
+
+ @property
+ def hostname(self):
+ try:
+ return self.netloc.split(':')[0]
+ except IndexError:
+ return ''
+
+ @property
+ def port(self):
+ components = self.netloc.split(':')
+
+ try:
+ return int(components[1])
+ except (IndexError, ValueError):
+ pass
+
+ if self.scheme == 'https':
+ return 443
+ if self.scheme == 'http':
+ return 80
+
+ # The default return shouldn't matter too much because if you are
+ # wanting to test this value you really should be explicitly setting it
+ # somewhere. 0 at least is a boolean False and an int.
+ return 0
+
+ @property
+ def path(self):
+ return self._url_parts.path
+
+ @property
+ def query(self):
+ return self._url_parts.query
+
+ @property
+ def qs(self):
+ if self._qs is None:
+ self._qs = urlparse.parse_qs(self.query, keep_blank_values=True)
+
+ return self._qs
+
+ @property
+ def timeout(self):
+ return self._timeout
+
+ @property
+ def allow_redirects(self):
+ return self._allow_redirects
+
+ @property
+ def verify(self):
+ return self._verify
+
+ @property
+ def stream(self):
+ return self._stream
+
+ @property
+ def cert(self):
+ return self._cert
+
+ @property
+ def proxies(self):
+ return self._proxies
+
+ @classmethod
+ def _create(cls, *args, **kwargs):
+ return cls(requests.Request(*args, **kwargs).prepare())
+
+ @property
+ def text(self):
+ body = self.body
+
+ if isinstance(body, six.binary_type):
+ body = body.decode('utf-8')
+
+ return body
+
+ def json(self, **kwargs):
+ return json.loads(self.text, **kwargs)
+
+ def __getstate__(self):
+ # Can't pickle a weakref, but it's a weakref so ok to drop it.
+ d = self.__dict__.copy()
+ d['_matcher'] = None
+ return d
+
+ @property
+ def matcher(self):
+ """The matcher that this request was handled by.
+
+ The matcher object is handled by a weakref. It will return the matcher
+ object if it is still available - so if the mock is still in place. If
+ the matcher is not available it will return None.
+ """
+ # if unpickled or not from a response this will be None
+ if self._matcher is None:
+ return None
+
+ return self._matcher()
+
+ def __str__(self):
+ return "{0.method} {0.url}".format(self._request)
diff --git a/contrib/python/requests-mock/py3/requests_mock/response.py b/contrib/python/requests-mock/py3/requests_mock/response.py
new file mode 100644
index 00000000000..58555392731
--- /dev/null
+++ b/contrib/python/requests-mock/py3/requests_mock/response.py
@@ -0,0 +1,281 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import json as jsonutils
+
+from requests.adapters import HTTPAdapter
+from requests.cookies import MockRequest, MockResponse
+from requests.cookies import RequestsCookieJar
+from requests.cookies import merge_cookies, cookiejar_from_dict
+from requests.packages.urllib3.response import HTTPResponse
+from requests.utils import get_encoding_from_headers
+import six
+
+from requests_mock import compat
+from requests_mock import exceptions
+
+_BODY_ARGS = frozenset(['raw', 'body', 'content', 'text', 'json'])
+_HTTP_ARGS = frozenset([
+ 'status_code',
+ 'reason',
+ 'headers',
+ 'cookies',
+ 'json_encoder',
+])
+
+_DEFAULT_STATUS = 200
+_http_adapter = HTTPAdapter()
+
+
+class CookieJar(RequestsCookieJar):
+
+ def set(self, name, value, **kwargs):
+ """Add a cookie to the Jar.
+
+ :param str name: cookie name/key.
+ :param str value: cookie value.
+ :param int version: Integer or None. Netscape cookies have version 0.
+ RFC 2965 and RFC 2109 cookies have a version cookie-attribute of 1.
+ However, note that cookielib may 'downgrade' RFC 2109 cookies to
+ Netscape cookies, in which case version is 0.
+ :param str port: String representing a port or a set of ports
+ (eg. '80', or '80,8080'),
+ :param str domain: The domain the cookie should apply to.
+ :param str path: Cookie path (a string, eg. '/acme/rocket_launchers').
+ :param bool secure: True if cookie should only be returned over a
+ secure connection.
+ :param int expires: Integer expiry date in seconds since epoch or None.
+ :param bool discard: True if this is a session cookie.
+ :param str comment: String comment from the server explaining the
+ function of this cookie.
+ :param str comment_url: URL linking to a comment from the server
+ explaining the function of this cookie.
+ """
+ # just here to provide the function documentation
+ return super(CookieJar, self).set(name, value, **kwargs)
+
+
+def _check_body_arguments(**kwargs):
+ # mutual exclusion, only 1 body method may be provided
+ provided = [x for x in _BODY_ARGS if kwargs.pop(x, None) is not None]
+
+ if len(provided) > 1:
+ raise RuntimeError('You may only supply one body element. You '
+ 'supplied %s' % ', '.join(provided))
+
+ extra = [x for x in kwargs if x not in _HTTP_ARGS]
+
+ if extra:
+ raise TypeError('Too many arguments provided. Unexpected '
+ 'arguments %s.' % ', '.join(extra))
+
+
+class _FakeConnection(object):
+ """An object that can mock the necessary parts of a socket interface."""
+
+ def send(self, request, **kwargs):
+ msg = 'This response was created without a connection. You are ' \
+ 'therefore unable to make a request directly on that connection.'
+ raise exceptions.InvalidRequest(msg)
+
+ def close(self):
+ pass
+
+
+def _extract_cookies(request, response, cookies):
+ """Add cookies to the response.
+
+ Cookies in requests are extracted from the headers in the original_response
+ httplib.HTTPMessage which we don't create so we have to do this step
+ manually.
+ """
+ # This will add cookies set manually via the Set-Cookie or Set-Cookie2
+ # header but this only allows 1 cookie to be set.
+ http_message = compat._FakeHTTPMessage(response.headers)
+ response.cookies.extract_cookies(MockResponse(http_message),
+ MockRequest(request))
+
+ # This allows you to pass either a CookieJar or a dictionary to request_uri
+ # or directly to create_response. To allow more than one cookie to be set.
+ if cookies:
+ merge_cookies(response.cookies, cookies)
+
+
+class _IOReader(six.BytesIO):
+ """A reader that makes a BytesIO look like a HTTPResponse.
+
+ A HTTPResponse will return an empty string when you read from it after
+ the socket has been closed. A BytesIO will raise a ValueError. For
+ compatibility we want to do the same thing a HTTPResponse does.
+ """
+
+ def read(self, *args, **kwargs):
+ if self.closed:
+ return six.b('')
+
+ # if the file is open, but you asked for zero bytes read you should get
+ # back zero without closing the stream.
+ if len(args) > 0 and args[0] == 0:
+ return six.b('')
+
+ # not a new style object in python 2
+ 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):
+ """
+ :param int status_code: The status code to return upon a successful
+ match. Defaults to 200.
+ :param HTTPResponse raw: A HTTPResponse object to return upon a
+ successful match.
+ :param io.IOBase body: An IO object with a read() method that can
+ return a body on successful match.
+ :param bytes content: A byte string to return upon a successful match.
+ :param unicode text: A text string to return upon a successful match.
+ :param object json: A python object to be converted to a JSON string
+ and returned upon a successful match.
+ :param class json_encoder: Encoder object to use for JOSON.
+ :param dict headers: A dictionary object containing headers that are
+ returned upon a successful match.
+ :param CookieJar cookies: A cookie jar with cookies to set on the
+ response.
+
+ :returns requests.Response: A response object that can
+ be returned to requests.
+ """
+ connection = kwargs.pop('connection', _FakeConnection())
+
+ _check_body_arguments(**kwargs)
+
+ raw = kwargs.pop('raw', None)
+ body = kwargs.pop('body', None)
+ content = kwargs.pop('content', None)
+ text = kwargs.pop('text', None)
+ json = kwargs.pop('json', None)
+ headers = kwargs.pop('headers', {})
+ encoding = None
+
+ if content is not None and not isinstance(content, six.binary_type):
+ raise TypeError('Content should be binary data')
+ if text is not None and not isinstance(text, six.string_types):
+ raise TypeError('Text should be string data')
+
+ if json is not None:
+ encoder = kwargs.pop('json_encoder', None) or jsonutils.JSONEncoder
+ text = jsonutils.dumps(json, cls=encoder)
+ if text is not None:
+ encoding = get_encoding_from_headers(headers) or 'utf-8'
+ content = text.encode(encoding)
+ if content is not None:
+ body = _IOReader(content)
+ if not raw:
+ 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,
+ body=body or _IOReader(six.b('')),
+ decode_content=False,
+ enforce_content_length=False,
+ preload_content=False,
+ original_response=None)
+
+ response = _http_adapter.build_response(request, raw)
+ response.connection = connection
+
+ if encoding and not response.encoding:
+ response.encoding = encoding
+
+ _extract_cookies(request, response, kwargs.get('cookies'))
+
+ return response
+
+
+class _Context(object):
+ """Stores the data being used to process a current URL match."""
+
+ def __init__(self, headers, status_code, reason, cookies):
+ self.headers = headers
+ self.status_code = status_code
+ self.reason = reason
+ self.cookies = cookies
+
+
+class _MatcherResponse(object):
+
+ def __init__(self, **kwargs):
+ self._exc = kwargs.pop('exc', None)
+
+ # If the user is asking for an exception to be thrown then prevent them
+ # specifying any sort of body or status response as it won't be used.
+ # This may be protecting the user too much but can be removed later.
+ if self._exc and kwargs:
+ raise TypeError('Cannot provide other arguments with exc.')
+
+ _check_body_arguments(**kwargs)
+ self._params = kwargs
+
+ # whilst in general you shouldn't do type checking in python this
+ # makes sure we don't end up with differences between the way types
+ # are handled between python 2 and 3.
+ content = self._params.get('content')
+ text = self._params.get('text')
+
+ if content is not None and not (callable(content) or
+ isinstance(content, six.binary_type)):
+ raise TypeError('Content should be a callback or binary data')
+
+ if text is not None and not (callable(text) or
+ isinstance(text, six.string_types)):
+ raise TypeError('Text should be a callback or string data')
+
+ def get_response(self, request):
+ # if an error was requested then raise that instead of doing response
+ if self._exc:
+ raise self._exc
+
+ # If a cookie dict is passed convert it into a CookieJar so that the
+ # cookies object available in a callback context is always a jar.
+ cookies = self._params.get('cookies', CookieJar())
+ if isinstance(cookies, dict):
+ cookies = cookiejar_from_dict(cookies, CookieJar())
+
+ context = _Context(self._params.get('headers', {}).copy(),
+ self._params.get('status_code', _DEFAULT_STATUS),
+ self._params.get('reason'),
+ cookies)
+
+ # if a body element is a callback then execute it
+ def _call(f, *args, **kwargs):
+ return f(request, context, *args, **kwargs) if callable(f) else f
+
+ return create_response(request,
+ json=_call(self._params.get('json')),
+ text=_call(self._params.get('text')),
+ content=_call(self._params.get('content')),
+ body=_call(self._params.get('body')),
+ raw=self._params.get('raw'),
+ json_encoder=self._params.get('json_encoder'),
+ status_code=context.status_code,
+ reason=context.reason,
+ headers=context.headers,
+ cookies=context.cookies)
diff --git a/contrib/python/requests-mock/py3/ya.make b/contrib/python/requests-mock/py3/ya.make
new file mode 100644
index 00000000000..b022b84019b
--- /dev/null
+++ b/contrib/python/requests-mock/py3/ya.make
@@ -0,0 +1,54 @@
+# Generated by devtools/yamaker (pypi).
+
+PY3_LIBRARY()
+
+VERSION(1.11.0)
+
+LICENSE(Apache-2.0)
+
+PEERDIR(
+ contrib/python/requests
+ contrib/python/six
+)
+
+NO_LINT()
+
+NO_CHECK_IMPORTS(
+ requests_mock.contrib._pytest_plugin
+ requests_mock.contrib.fixture
+)
+
+PY_SRCS(
+ TOP_LEVEL
+ requests_mock/__init__.py
+ requests_mock/__init__.pyi
+ requests_mock/adapter.py
+ requests_mock/adapter.pyi
+ requests_mock/compat.py
+ requests_mock/contrib/__init__.py
+ requests_mock/contrib/_pytest_plugin.py
+ requests_mock/contrib/_pytest_plugin.pyi
+ requests_mock/contrib/fixture.py
+ requests_mock/exceptions.py
+ requests_mock/exceptions.pyi
+ requests_mock/mocker.py
+ requests_mock/mocker.pyi
+ requests_mock/request.py
+ requests_mock/request.pyi
+ requests_mock/response.py
+ requests_mock/response.pyi
+)
+
+RESOURCE_FILES(
+ PREFIX contrib/python/requests-mock/py3/
+ .dist-info/METADATA
+ .dist-info/entry_points.txt
+ .dist-info/top_level.txt
+ requests_mock/py.typed
+)
+
+END()
+
+RECURSE_FOR_TESTS(
+ tests
+)