Hello community,
here is the log from the commit of package python-requests-toolbelt for
openSUSE:Factory checked in at 2019-05-10 09:14:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-requests-toolbelt (Old)
and /work/SRC/openSUSE:Factory/.python-requests-toolbelt.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-requests-toolbelt"
Fri May 10 09:14:14 2019 rev:4 rq:701116 version:0.9.1
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-requests-toolbelt/python-requests-toolbelt.changes
2017-07-04 11:58:26.460974825 +0200
+++
/work/SRC/openSUSE:Factory/.python-requests-toolbelt.new.5148/python-requests-toolbelt.changes
2019-05-10 09:14:16.447801717 +0200
@@ -1,0 +2,30 @@
+Mon May 6 14:06:37 UTC 2019 - Tomáš Chvátal <[email protected]>
+
+- Add patch to fix tests fix-tests.patch
+- Use pytest to execute the tests, same as the upstream
+
+-------------------------------------------------------------------
+Thu Apr 25 19:57:47 UTC 2019 - Dirk Mueller <[email protected]>
+
+- update to 0.9.1:
+ - Fix import of pyOpenSSL shim from urllib3 for PKCS12 adapter
+ - Add X509 Adapter that can handle PKCS12
+ - Add stateless solution for streaming files by MultipartEncoder from one
host to another (in chunks)
+ - Update link to example
+ - Move import of ``ABCs`` from collections into version-specific part of
+ _compat module
+ - Fix backwards incompatibility in ``get_encodings_from_content``
+ - Correct callback documentation for ``MultipartEncoderMonitor``
+ - Fix bug when ``MultipartEncoder`` is asked to encode zero parts
+ - Correct the type of non string request body dumps
+ - Removed content from being stored in MultipartDecoder
+ - Fix bug by enabling support for contenttype with capital letters.
+ - Coerce proxy URL to bytes before dumping request
+ - Avoid bailing out with exception upon empty response reason
+ - Corrected Pool documentation
+ - Corrected parentheses match in example usage
+ - Fix "oject" to "object" in ``MultipartEncoder``
+ - Fix URL for the project after the move
+ - Add fix for OSX TCPKeepAliveAdapter
+
+-------------------------------------------------------------------
Old:
----
requests-toolbelt-0.8.0.tar.gz
New:
----
fix-tests.patch
requests-toolbelt-0.9.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-requests-toolbelt.spec ++++++
--- /var/tmp/diff_new_pack.ZQSsHq/_old 2019-05-10 09:14:17.667805200 +0200
+++ /var/tmp/diff_new_pack.ZQSsHq/_new 2019-05-10 09:14:17.671805212 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-requests-toolbelt
#
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -12,31 +12,32 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-requests-toolbelt
-Version: 0.8.0
+Version: 0.9.1
Release: 0
Summary: A utility belt for advanced users of python3-requests
License: Apache-2.0
Group: Development/Languages/Python
-Url: https://toolbelt.readthedocs.org
+URL: https://github.com/requests/toolbelt
Source:
https://files.pythonhosted.org/packages/source/r/requests-toolbelt/requests-toolbelt-%{version}.tar.gz
-BuildRequires: %{python_module requests >= 2.0.1}
+Patch0: fix-tests.patch
+BuildRequires: %{python_module requests >= 2.12.2}
BuildRequires: %{python_module setuptools}
+BuildRequires: fdupes
+BuildRequires: python-rpm-macros
+Requires: python-requests >= 2.12.2
+BuildArch: noarch
# SECTION test requirements
-BuildRequires: %{python_module betamax}
+BuildRequires: %{python_module betamax >= 0.5.0}
BuildRequires: %{python_module mock}
+BuildRequires: %{python_module pyOpenSSL}
BuildRequires: %{python_module pytest}
# /SECTION
-BuildRequires: fdupes
-BuildRequires: python-rpm-macros
-Requires: python-requests >= 2.0.1
-BuildRoot: %{_tmppath}/%{name}-%{version}-build
-BuildArch: noarch
%python_subpackages
%description
@@ -47,21 +48,24 @@
%prep
%setup -q -n requests-toolbelt-%{version}
+%patch0 -p1
rm -rf requests_toolbelt.egg-info
+# requires network access
+rm -v tests/test_multipart_encoder.py
%build
%python_build
%install
%python_install
-%python_expand %fdupes -s %{buildroot}%{$python_sitelib}
+%python_expand %fdupes %{buildroot}%{$python_sitelib}
%check
-%python_exec setup.py test
+%pytest
%files %{python_files}
-%defattr(-,root,root,-)
-%doc AUTHORS.rst HISTORY.rst LICENSE README.rst
+%license LICENSE
+%doc README.rst
%{python_sitelib}/*
%changelog
++++++ fix-tests.patch ++++++
From c4f918572751151eb3bfc7dfa94580b3e2867a9e Mon Sep 17 00:00:00 2001
From: Jon Dufresne <[email protected]>
Date: Sun, 3 Feb 2019 09:02:24 -0800
Subject: [PATCH] Fix unhandled exceptions from threads during tests
A queue.Queue() object was not always passed to SessionThread. In this
case, SessionThread._make_request() would raise an exception trying to
call methods on the expected object. Now, always pass a usable object to
SessionThread.
Previously appeared as:
Traceback (most recent call last):
File "/usr/lib64/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "/usr/lib64/python3.7/threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "toolbelt/requests_toolbelt/threaded/thread.py", line 41, in
_make_request
kwargs = self._jobs.get_nowait()
AttributeError: 'NoneType' object has no attribute 'get_nowait'
Exception in thread cd08fad6-d21d-41b0-921e-737a149b12be:
Traceback (most recent call last):
File "/usr/lib64/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "/usr/lib64/python3.7/threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "toolbelt/requests_toolbelt/threaded/thread.py", line 41, in
_make_request
kwargs = self._jobs.get_nowait()
AttributeError: 'NoneType' object has no attribute 'get_nowait'
Exception in thread 4fb72f0d-ba1c-4a78-97a2-4a7283ea01fe:
Traceback (most recent call last):
File "/usr/lib64/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "/usr/lib64/python3.7/threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "toolbelt/requests_toolbelt/threaded/thread.py", line 41, in
_make_request
kwargs = self._jobs.get_nowait()
AttributeError: 'NoneType' object has no attribute 'get_nowait'
Exception in thread 5f3711af-0c01-4821-9e25-8074bbbf769b:
Traceback (most recent call last):
File "/usr/lib64/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "/usr/lib64/python3.7/threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "toolbelt/requests_toolbelt/threaded/thread.py", line 41, in
_make_request
kwargs = self._jobs.get_nowait()
AttributeError: 'NoneType' object has no attribute 'get_nowait'
---
tests/threaded/test_pool.py | 15 ++++++++++-----
tests/threaded/test_thread.py | 5 ++++-
2 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/tests/threaded/test_pool.py b/tests/threaded/test_pool.py
index b0653bb..b949dd8 100644
--- a/tests/threaded/test_pool.py
+++ b/tests/threaded/test_pool.py
@@ -26,32 +26,37 @@ def test_requires_positive_number_of_processes(self):
def test_number_of_processes_can_be_arbitrary(self):
"""Show that the number of processes can be set."""
- p = pool.Pool(None, num_processes=100)
+ job_queue = queue.Queue()
+ p = pool.Pool(job_queue, num_processes=100)
assert p._processes == 100
assert len(p._pool) == 100
- p = pool.Pool(None, num_processes=1)
+ job_queue = queue.Queue()
+ p = pool.Pool(job_queue, num_processes=1)
assert p._processes == 1
assert len(p._pool) == 1
def test_initializer_is_called(self):
"""Ensure that the initializer function is called."""
+ job_queue = queue.Queue()
initializer = mock.MagicMock()
- pool.Pool(None, num_processes=1, initializer=initializer)
+ pool.Pool(job_queue, num_processes=1, initializer=initializer)
assert initializer.called is True
initializer.assert_called_once_with(mock.ANY)
def test_auth_generator_is_called(self):
"""Ensure that the auth_generator function is called."""
+ job_queue = queue.Queue()
auth_generator = mock.MagicMock()
- pool.Pool(None, num_processes=1, auth_generator=auth_generator)
+ pool.Pool(job_queue, num_processes=1, auth_generator=auth_generator)
assert auth_generator.called is True
auth_generator.assert_called_once_with(mock.ANY)
def test_session_is_called(self):
"""Ensure that the session function is called."""
+ job_queue = queue.Queue()
session = mock.MagicMock()
- pool.Pool(None, num_processes=1, session=session)
+ pool.Pool(job_queue, num_processes=1, session=session)
assert session.called is True
session.assert_called_once_with()
diff --git a/tests/threaded/test_thread.py b/tests/threaded/test_thread.py
index bb92f7f..fd7e96b 100644
--- a/tests/threaded/test_thread.py
+++ b/tests/threaded/test_thread.py
@@ -19,6 +19,8 @@ def _make_mocks():
def _initialize_a_session_thread(session=None, job_queue=None,
response_queue=None, exception_queue=None):
+ if job_queue is None:
+ job_queue = queue.Queue()
with mock.patch.object(threading, 'Thread') as Thread:
thread_instance = mock.MagicMock()
Thread.return_value = thread_instance
@@ -52,10 +54,11 @@ def test_thread_initialization(self):
def test_is_alive_proxies_to_worker(self):
"""Test that we proxy the is_alive method to the Thread."""
+ job_queue = queue.Queue()
with mock.patch.object(threading, 'Thread') as Thread:
thread_instance = mock.MagicMock()
Thread.return_value = thread_instance
- st = thread.SessionThread(None, None, None, None)
+ st = thread.SessionThread(None, job_queue, None, None)
st.is_alive()
thread_instance.is_alive.assert_called_once_with()
++++++ requests-toolbelt-0.8.0.tar.gz -> requests-toolbelt-0.9.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-toolbelt-0.8.0/AUTHORS.rst
new/requests-toolbelt-0.9.1/AUTHORS.rst
--- old/requests-toolbelt-0.8.0/AUTHORS.rst 2017-01-19 15:23:03.000000000
+0100
+++ new/requests-toolbelt-0.9.1/AUTHORS.rst 2019-01-29 18:43:40.000000000
+0100
@@ -41,3 +41,13 @@
- Mike Lambert (@mikelambert)
- Ryan Barrett (https://snarfed.org/)
+
+- Victor Grau Serrat (@lacabra)
+
+- Yorgos Pagles <[email protected]>
+
+- Thomas Hauk <[email protected]>
+
+- Achim Herwig <[email protected]>
+
+- Ryan Ashley <rashley-iqt>
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-toolbelt-0.8.0/HISTORY.rst
new/requests-toolbelt-0.9.1/HISTORY.rst
--- old/requests-toolbelt-0.8.0/HISTORY.rst 2017-05-20 23:31:29.000000000
+0200
+++ new/requests-toolbelt-0.9.1/HISTORY.rst 2019-01-30 02:28:28.000000000
+0100
@@ -1,6 +1,48 @@
History
=======
+0.9.1 -- 2019-01-29
+-------------------
+
+Fixed Bugs
+~~~~~~~~~~
+
+- Fix import of pyOpenSSL shim from urllib3 for PKCS12 adapter
+
+0.9.0 -- 2019-01-29
+-------------------
+
+New Features
+~~~~~~~~~~~~
+
+- Add X509 Adapter that can handle PKCS12
+- Add stateless solution for streaming files by MultipartEncoder from one host
to another (in chunks)
+
+Fixed Bugs
+~~~~~~~~~~
+
+- Update link to example
+- Move import of ``ABCs`` from collections into version-specific part of
+ _compat module
+- Fix backwards incompatibility in ``get_encodings_from_content``
+- Correct callback documentation for ``MultipartEncoderMonitor``
+- Fix bug when ``MultipartEncoder`` is asked to encode zero parts
+- Correct the type of non string request body dumps
+- Removed content from being stored in MultipartDecoder
+- Fix bug by enabling support for contenttype with capital letters.
+- Coerce proxy URL to bytes before dumping request
+- Avoid bailing out with exception upon empty response reason
+- Corrected Pool documentation
+- Corrected parentheses match in example usage
+- Fix "oject" to "object" in ``MultipartEncoder``
+- Fix URL for the project after the move
+- Add fix for OSX TCPKeepAliveAdapter
+
+Miscellaneous
+~~~~~~~~~~~~~
+
+- Remove py33 from testing and add Python 3.6 and nightly testing to the
travis matrix.
+
0.8.0 -- 2017-05-20
-------------------
@@ -20,7 +62,7 @@
- Fix backwards incompatibility in ``get_encodings_from_content``
.. _0.8.0 milestone:
- https://github.com/sigmavirus24/requests-toolbelt/milestones/0.8.0
+ https://github.com/requests/toolbelt/milestones/0.8.0
0.7.1 -- 2017-02-13
-------------------
@@ -40,7 +82,7 @@
.. links
.. _0.7.1 milestone:
- https://github.com/sigmavirus24/requests-toolbelt/milestone/9
+ https://github.com/requests/toolbelt/milestone/9
0.7.0 -- 2016-07-21
-------------------
@@ -69,7 +111,7 @@
.. _0.7.0 milestone:
- https://github.com/sigmavirus24/requests-toolbelt/milestones/0.7.0
+ https://github.com/requests/toolbelt/milestones/0.7.0
0.6.2 -- 2016-05-10
-------------------
@@ -123,7 +165,7 @@
.. _0.6.0 milestone:
- https://github.com/sigmavirus24/requests-toolbelt/milestones/0.6.0
+ https://github.com/requests/toolbelt/milestones/0.6.0
0.5.1 -- 2015-12-16
-------------------
@@ -138,13 +180,13 @@
.. _0.5.1 milestone:
- https://github.com/sigmavirus24/requests-toolbelt/milestones/0.5.1
+ https://github.com/requests/toolbelt/milestones/0.5.1
0.5.0 -- 2015-11-24
-------------------
More information about this release can be found on the `milestone
-<https://github.com/sigmavirus24/requests-toolbelt/issues?utf8=%E2%9C%93&q=is%3Aall+milestone%3A0.5+>`_
+<https://github.com/requests/toolbelt/issues?utf8=%E2%9C%93&q=is%3Aall+milestone%3A0.5+>`_
for 0.5.0.
New Features
@@ -183,7 +225,7 @@
-------------------
For more information about this release, please see `milestone 0.4.0
-<https://github.com/sigmavirus24/requests-toolbelt/issues?q=milestone%3A0.4>`_
+<https://github.com/requests/toolbelt/issues?q=milestone%3A0.4>`_
on the project's page.
New Features
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-toolbelt-0.8.0/PKG-INFO
new/requests-toolbelt-0.9.1/PKG-INFO
--- old/requests-toolbelt-0.8.0/PKG-INFO 2017-05-20 23:32:33.000000000
+0200
+++ new/requests-toolbelt-0.9.1/PKG-INFO 2019-01-30 02:29:41.000000000
+0100
@@ -1,13 +1,13 @@
Metadata-Version: 1.1
Name: requests-toolbelt
-Version: 0.8.0
+Version: 0.9.1
Summary: A utility belt for advanced users of python-requests
Home-page: https://toolbelt.readthedocs.org
Author: Ian Cordasco, Cory Benfield
Author-email: [email protected]
License: Apache 2.0
-Description: requests toolbelt
- =================
+Description: The Requests Toolbelt
+ =====================
This is just a collection of utilities for `python-requests`_, but
don't
really belong in ``requests`` proper. The minimum tested requests
version is
@@ -118,13 +118,58 @@
<https://toolbelt.readthedocs.org/en/latest/contributing.html>`_ for
contributing to this project.
+ Please report any bugs on the `issue tracker`_
+
.. _Cory Benfield's blog:
https://lukasa.co.uk/2013/01/Choosing_SSL_Version_In_Requests/
.. _python-requests: https://github.com/kennethreitz/requests
+ .. _issue tracker: https://github.com/requests/toolbelt/issues
History
=======
+ 0.9.1 -- 2019-01-29
+ -------------------
+
+ Fixed Bugs
+ ~~~~~~~~~~
+
+ - Fix import of pyOpenSSL shim from urllib3 for PKCS12 adapter
+
+ 0.9.0 -- 2019-01-29
+ -------------------
+
+ New Features
+ ~~~~~~~~~~~~
+
+ - Add X509 Adapter that can handle PKCS12
+ - Add stateless solution for streaming files by MultipartEncoder from
one host to another (in chunks)
+
+ Fixed Bugs
+ ~~~~~~~~~~
+
+ - Update link to example
+ - Move import of ``ABCs`` from collections into version-specific part
of
+ _compat module
+ - Fix backwards incompatibility in ``get_encodings_from_content``
+ - Correct callback documentation for ``MultipartEncoderMonitor``
+ - Fix bug when ``MultipartEncoder`` is asked to encode zero parts
+ - Correct the type of non string request body dumps
+ - Removed content from being stored in MultipartDecoder
+ - Fix bug by enabling support for contenttype with capital letters.
+ - Coerce proxy URL to bytes before dumping request
+ - Avoid bailing out with exception upon empty response reason
+ - Corrected Pool documentation
+ - Corrected parentheses match in example usage
+ - Fix "oject" to "object" in ``MultipartEncoder``
+ - Fix URL for the project after the move
+ - Add fix for OSX TCPKeepAliveAdapter
+
+ Miscellaneous
+ ~~~~~~~~~~~~~
+
+ - Remove py33 from testing and add Python 3.6 and nightly testing to
the travis matrix.
+
0.8.0 -- 2017-05-20
-------------------
@@ -144,7 +189,7 @@
- Fix backwards incompatibility in ``get_encodings_from_content``
.. _0.8.0 milestone:
- https://github.com/sigmavirus24/requests-toolbelt/milestones/0.8.0
+ https://github.com/requests/toolbelt/milestones/0.8.0
0.7.1 -- 2017-02-13
-------------------
@@ -164,7 +209,7 @@
.. links
.. _0.7.1 milestone:
- https://github.com/sigmavirus24/requests-toolbelt/milestone/9
+ https://github.com/requests/toolbelt/milestone/9
0.7.0 -- 2016-07-21
-------------------
@@ -193,7 +238,7 @@
.. _0.7.0 milestone:
- https://github.com/sigmavirus24/requests-toolbelt/milestones/0.7.0
+ https://github.com/requests/toolbelt/milestones/0.7.0
0.6.2 -- 2016-05-10
-------------------
@@ -247,7 +292,7 @@
.. _0.6.0 milestone:
- https://github.com/sigmavirus24/requests-toolbelt/milestones/0.6.0
+ https://github.com/requests/toolbelt/milestones/0.6.0
0.5.1 -- 2015-12-16
-------------------
@@ -262,13 +307,13 @@
.. _0.5.1 milestone:
- https://github.com/sigmavirus24/requests-toolbelt/milestones/0.5.1
+ https://github.com/requests/toolbelt/milestones/0.5.1
0.5.0 -- 2015-11-24
-------------------
More information about this release can be found on the `milestone
-
<https://github.com/sigmavirus24/requests-toolbelt/issues?utf8=%E2%9C%93&q=is%3Aall+milestone%3A0.5+>`_
+
<https://github.com/requests/toolbelt/issues?utf8=%E2%9C%93&q=is%3Aall+milestone%3A0.5+>`_
for 0.5.0.
New Features
@@ -307,7 +352,7 @@
-------------------
For more information about this release, please see `milestone 0.4.0
-
<https://github.com/sigmavirus24/requests-toolbelt/issues?q=milestone%3A0.4>`_
+ <https://github.com/requests/toolbelt/issues?q=milestone%3A0.4>`_
on the project's page.
New Features
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-toolbelt-0.8.0/README.rst
new/requests-toolbelt-0.9.1/README.rst
--- old/requests-toolbelt-0.8.0/README.rst 2017-01-19 15:23:03.000000000
+0100
+++ new/requests-toolbelt-0.9.1/README.rst 2017-06-03 02:35:47.000000000
+0200
@@ -1,5 +1,5 @@
-requests toolbelt
-=================
+The Requests Toolbelt
+=====================
This is just a collection of utilities for `python-requests`_, but don't
really belong in ``requests`` proper. The minimum tested requests version is
@@ -110,5 +110,8 @@
<https://toolbelt.readthedocs.org/en/latest/contributing.html>`_ for
contributing to this project.
+Please report any bugs on the `issue tracker`_
+
.. _Cory Benfield's blog:
https://lukasa.co.uk/2013/01/Choosing_SSL_Version_In_Requests/
.. _python-requests: https://github.com/kennethreitz/requests
+.. _issue tracker: https://github.com/requests/toolbelt/issues
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-toolbelt-0.8.0/dev-requirements.txt
new/requests-toolbelt-0.9.1/dev-requirements.txt
--- old/requests-toolbelt-0.8.0/dev-requirements.txt 2017-01-19
15:23:03.000000000 +0100
+++ new/requests-toolbelt-0.9.1/dev-requirements.txt 2019-01-29
18:43:40.000000000 +0100
@@ -1,3 +1,4 @@
pytest
mock
+pyopenssl
git+git://github.com/sigmavirus24/betamax
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-toolbelt-0.8.0/docs/adapters.rst
new/requests-toolbelt-0.9.1/docs/adapters.rst
--- old/requests-toolbelt-0.8.0/docs/adapters.rst 2017-03-25
12:07:58.000000000 +0100
+++ new/requests-toolbelt-0.9.1/docs/adapters.rst 2019-01-29
18:43:40.000000000 +0100
@@ -21,6 +21,8 @@
- :class:`requests_toolbelt.adapters.host_header_ssl.HostHeaderSSLAdapter`
+- :class:`requests_toolbelt.adapters.x509.X509Adapter`
+
AppEngineAdapter
----------------
@@ -243,3 +245,25 @@
.. autoclass:: requests_toolbelt.adapters.socket_options.TCPKeepAliveAdapter
+X509Adapter
+-----------
+
+Requests supports SSL Verification using a certificate in .pem format by
default.
+In some cases it is necessary to pass a full cert chain as part of a request
or it
+is deemed too great a risk to decrypt the certificate into a .pem file.
+
+For such use cases we have created
+:class:`~requests_toolbelt.adapters.x509.X509Adapter`.
+Example usage:
+
+.. code-block:: python
+
+ import requests
+ from requests_toolbelt.adapters.x509 import X509Adapter
+ s = requests.Session()
+ a = X509Adapter(max_retries=3,
+ cert_bytes=b'...', pk_bytes=b'...', encoding='...')
+ s.mount('https://', a)
+
+.. autoclass:: requests_toolbelt.adapters.x509.X509Adapter
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-toolbelt-0.8.0/docs/contributing.rst
new/requests-toolbelt-0.9.1/docs/contributing.rst
--- old/requests-toolbelt-0.8.0/docs/contributing.rst 2017-01-19
15:23:03.000000000 +0100
+++ new/requests-toolbelt-0.9.1/docs/contributing.rst 2017-06-03
02:35:47.000000000 +0200
@@ -155,7 +155,7 @@
squash your commits or may squash them for you and perform a manual
merge.
-.. _GitHub: https://github.com/sigmavirus24/requests-toolbelt
+.. _GitHub: https://github.com/requests/toolbelt
.. _GitLab: https://gitlab.com/sigmavirus24/toolbelt
.. _tox: https://tox.readthedocs.org/en/latest/
.. _pytest: http://pytest.org/latest/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-toolbelt-0.8.0/docs/uploading-data.rst
new/requests-toolbelt-0.9.1/docs/uploading-data.rst
--- old/requests-toolbelt-0.8.0/docs/uploading-data.rst 2017-01-19
15:23:03.000000000 +0100
+++ new/requests-toolbelt-0.9.1/docs/uploading-data.rst 2019-01-29
18:43:40.000000000 +0100
@@ -109,7 +109,7 @@
.. autoclass:: requests_toolbelt.multipart.encoder.MultipartEncoderMonitor
.. _an example using clint:
-
https://gitlab.com/sigmavirus24/toolbelt/blob/master/examples/monitor/progress_bar.py
+
https://github.com/requests/toolbelt/blob/master/examples/monitor/progress_bar.py
Streaming Data from a Generator
-------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-toolbelt-0.8.0/requests_toolbelt/__init__.py
new/requests-toolbelt-0.9.1/requests_toolbelt/__init__.py
--- old/requests-toolbelt-0.8.0/requests_toolbelt/__init__.py 2017-05-20
23:20:06.000000000 +0200
+++ new/requests-toolbelt-0.9.1/requests_toolbelt/__init__.py 2019-01-30
02:27:51.000000000 +0100
@@ -22,7 +22,7 @@
__authors__ = 'Ian Cordasco, Cory Benfield'
__license__ = 'Apache v2.0'
__copyright__ = 'Copyright 2014 Ian Cordasco, Cory Benfield'
-__version__ = '0.8.0'
+__version__ = '0.9.1'
__version_info__ = tuple(int(i) for i in __version__.split('.'))
__all__ = [
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-toolbelt-0.8.0/requests_toolbelt/_compat.py
new/requests-toolbelt-0.9.1/requests_toolbelt/_compat.py
--- old/requests-toolbelt-0.8.0/requests_toolbelt/_compat.py 2017-01-19
15:23:03.000000000 +0100
+++ new/requests-toolbelt-0.9.1/requests_toolbelt/_compat.py 2019-01-30
02:26:45.000000000 +0100
@@ -8,7 +8,6 @@
This module is private. If you use it, and something breaks, you were
warned
"""
-from collections import Mapping, MutableMapping
import sys
import requests
@@ -50,12 +49,26 @@
except ImportError:
from urllib3.contrib import appengine as gaecontrib
+if requests.__build__ < 0x021200:
+ PyOpenSSLContext = None
+else:
+ try:
+ from requests.packages.urllib3.contrib.pyopenssl \
+ import PyOpenSSLContext
+ except ImportError:
+ try:
+ from urllib3.contrib.pyopenssl import PyOpenSSLContext
+ except ImportError:
+ PyOpenSSLContext = None
+
PY3 = sys.version_info > (3, 0)
if PY3:
+ from collections.abc import Mapping, MutableMapping
import queue
from urllib.parse import urlencode, urljoin
else:
+ from collections import Mapping, MutableMapping
import Queue as queue
from urllib import urlencode
from urlparse import urljoin
@@ -307,4 +320,5 @@
'urlencode',
'gaecontrib',
'urljoin',
+ 'PyOpenSSLContext',
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-toolbelt-0.8.0/requests_toolbelt/adapters/socket_options.py
new/requests-toolbelt-0.9.1/requests_toolbelt/adapters/socket_options.py
--- old/requests-toolbelt-0.8.0/requests_toolbelt/adapters/socket_options.py
2017-01-19 15:23:03.000000000 +0100
+++ new/requests-toolbelt-0.9.1/requests_toolbelt/adapters/socket_options.py
2017-06-03 02:35:47.000000000 +0200
@@ -2,6 +2,7 @@
"""The implementation of the SocketOptionsAdapter."""
import socket
import warnings
+import sys
import requests
from requests import adapters
@@ -103,13 +104,23 @@
interval = kwargs.pop('interval', 20)
count = kwargs.pop('count', 5)
socket_options = socket_options + [
- (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),
- (socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, interval),
- (socket.IPPROTO_TCP, socket.TCP_KEEPCNT, count),
+ (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
]
- # NOTE(Ian): Apparently OSX does not have this constant defined, so we
- # set it conditionally.
+ # NOTE(Ian): OSX does not have these constants defined, so we
+ # set them conditionally.
+ if getattr(socket, 'TCP_KEEPINTVL', None) is not None:
+ socket_options += [(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL,
+ interval)]
+ elif sys.platform == 'darwin':
+ # On OSX, TCP_KEEPALIVE from netinet/tcp.h is not exported
+ # by python's socket module
+ TCP_KEEPALIVE = getattr(socket, 'TCP_KEEPALIVE', 0x10)
+ socket_options += [(socket.IPPROTO_TCP, TCP_KEEPALIVE, interval)]
+
+ if getattr(socket, 'TCP_KEEPCNT', None) is not None:
+ socket_options += [(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, count)]
+
if getattr(socket, 'TCP_KEEPIDLE', None) is not None:
socket_options += [(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, idle)]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-toolbelt-0.8.0/requests_toolbelt/adapters/source.py
new/requests-toolbelt-0.9.1/requests_toolbelt/adapters/source.py
--- old/requests-toolbelt-0.8.0/requests_toolbelt/adapters/source.py
2017-01-19 15:23:03.000000000 +0100
+++ new/requests-toolbelt-0.9.1/requests_toolbelt/adapters/source.py
2018-01-05 13:36:25.000000000 +0100
@@ -40,7 +40,7 @@
s = requests.Session()
s.mount('http://', SourceAddressAdapter('10.10.10.10'))
- s.mount('https://', SourceAddressAdapter(('10.10.10.10', 8999))
+ s.mount('https://', SourceAddressAdapter(('10.10.10.10', 8999)))
"""
def __init__(self, source_address, **kwargs):
if isinstance(source_address, basestring):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-toolbelt-0.8.0/requests_toolbelt/adapters/x509.py
new/requests-toolbelt-0.9.1/requests_toolbelt/adapters/x509.py
--- old/requests-toolbelt-0.8.0/requests_toolbelt/adapters/x509.py
1970-01-01 01:00:00.000000000 +0100
+++ new/requests-toolbelt-0.9.1/requests_toolbelt/adapters/x509.py
2019-01-29 18:43:40.000000000 +0100
@@ -0,0 +1,178 @@
+# -*- coding: utf-8 -*-
+"""A X509Adapter for use with the requests library.
+
+This file contains an implementation of the X509Adapter that will
+allow users to authenticate a request using an arbitrary
+X.509 certificate without needing to convert it to a .pem file
+
+"""
+
+from OpenSSL.crypto import PKey, X509
+from cryptography import x509
+from cryptography.hazmat.primitives.serialization import (load_pem_private_key,
+ load_der_private_key)
+from cryptography.hazmat.primitives.serialization import Encoding
+from cryptography.hazmat.backends import default_backend
+
+from datetime import datetime
+from requests.adapters import HTTPAdapter
+import requests
+
+from .._compat import PyOpenSSLContext
+from .. import exceptions as exc
+
+"""
+importing the protocol constants from _ssl instead of ssl because only the
+constants are needed and to handle issues caused by importing from ssl on
+the 2.7.x line.
+"""
+try:
+ from _ssl import PROTOCOL_TLS as PROTOCOL
+except ImportError:
+ from _ssl import PROTOCOL_SSLv23 as PROTOCOL
+
+
+class X509Adapter(HTTPAdapter):
+ r"""Adapter for use with X.509 certificates.
+
+ Provides an interface for Requests sessions to contact HTTPS urls and
+ authenticate with an X.509 cert by implementing the Transport Adapter
+ interface. This class will need to be manually instantiated and mounted
+ to the session
+
+ :param pool_connections: The number of urllib3 connection pools to
+ cache.
+ :param pool_maxsize: The maximum number of connections to save in the
+ pool.
+ :param max_retries: The maximum number of retries each connection
+ should attempt. Note, this applies only to failed DNS lookups,
+ socket connections and connection timeouts, never to requests where
+ data has made it to the server. By default, Requests does not retry
+ failed connections. If you need granular control over the
+ conditions under which we retry a request, import urllib3's
+ ``Retry`` class and pass that instead.
+ :param pool_block: Whether the connection pool should block for
+ connections.
+
+ :param bytes cert_bytes:
+ bytes object containing contents of a cryptography.x509Certificate
+ object using the encoding specified by the ``encoding`` parameter.
+ :param bytes pk_bytes:
+ bytes object containing contents of a object that implements
+ ``cryptography.hazmat.primitives.serialization.PrivateFormat``
+ using the encoding specified by the ``encoding`` parameter.
+ :param password:
+ string or utf8 encoded bytes containing the passphrase used for the
+ private key. None if unencrypted. Defaults to None.
+ :param encoding:
+ Enumeration detailing the encoding method used on the ``cert_bytes``
+ parameter. Can be either PEM or DER. Defaults to PEM.
+ :type encoding:
+ :class: `cryptography.hazmat.primitives.serialization.Encoding`
+
+ Usage::
+
+ >>> import requests
+ >>> from requests_toolbelt.adapters.x509 import X509Adapter
+ >>> s = requests.Session()
+ >>> a = X509Adapter(max_retries=3,
+ cert_bytes=b'...', pk_bytes=b'...', encoding='...'
+ >>> s.mount('https://', a)
+ """
+
+ def __init__(self, *args, **kwargs):
+ self._check_version()
+ cert_bytes = kwargs.pop('cert_bytes', None)
+ pk_bytes = kwargs.pop('pk_bytes', None)
+ password = kwargs.pop('password', None)
+ encoding = kwargs.pop('encoding', Encoding.PEM)
+
+ password_bytes = None
+
+ if cert_bytes is None or not isinstance(cert_bytes, bytes):
+ raise ValueError('Invalid cert content provided. '
+ 'You must provide an X.509 cert '
+ 'formatted as a byte array.')
+ if pk_bytes is None or not isinstance(pk_bytes, bytes):
+ raise ValueError('Invalid private key content provided. '
+ 'You must provide a private key '
+ 'formatted as a byte array.')
+
+ if isinstance(password, bytes):
+ password_bytes = password
+ elif password:
+ password_bytes = password.encode('utf8')
+
+ self.ssl_context = create_ssl_context(cert_bytes, pk_bytes,
+ password_bytes, encoding)
+
+ super(X509Adapter, self).__init__(*args, **kwargs)
+
+ def init_poolmanager(self, *args, **kwargs):
+ if self.ssl_context:
+ kwargs['ssl_context'] = self.ssl_context
+ return super(X509Adapter, self).init_poolmanager(*args, **kwargs)
+
+ def proxy_manager_for(self, *args, **kwargs):
+ if self.ssl_context:
+ kwargs['ssl_context'] = self.ssl_context
+ return super(X509Adapter, self).proxy_manager_for(*args, **kwargs)
+
+ def _check_version(self):
+ if PyOpenSSLContext is None:
+ raise exc.VersionMismatchError(
+ "The X509Adapter requires at least Requests 2.12.0 to be "
+ "installed. Version {0} was found instead.".format(
+ requests.__version__
+ )
+ )
+
+
+def check_cert_dates(cert):
+ """Verify that the supplied client cert is not invalid."""
+
+ now = datetime.utcnow()
+ if cert.not_valid_after < now or cert.not_valid_before > now:
+ raise ValueError('Client certificate expired: Not After: '
+ '{0:%Y-%m-%d %H:%M:%SZ} '
+ 'Not Before: {1:%Y-%m-%d %H:%M:%SZ}'
+ .format(cert.not_valid_after, cert.not_valid_before))
+
+
+def create_ssl_context(cert_byes, pk_bytes, password=None,
+ encoding=Encoding.PEM):
+ """Create an SSL Context with the supplied cert/password.
+
+ :param cert_bytes array of bytes containing the cert encoded
+ using the method supplied in the ``encoding`` parameter
+ :param pk_bytes array of bytes containing the private key encoded
+ using the method supplied in the ``encoding`` parameter
+ :param password array of bytes containing the passphrase to be used
+ with the supplied private key. None if unencrypted.
+ Defaults to None.
+ :param encoding ``cryptography.hazmat.primitives.serialization.Encoding``
+ details the encoding method used on the ``cert_bytes`` and
+ ``pk_bytes`` parameters. Can be either PEM or DER.
+ Defaults to PEM.
+ """
+ backend = default_backend()
+
+ cert = None
+ key = None
+ if encoding == Encoding.PEM:
+ cert = x509.load_pem_x509_certificate(cert_byes, backend)
+ key = load_pem_private_key(pk_bytes, password, backend)
+ elif encoding == Encoding.DER:
+ cert = x509.load_der_x509_certificate(cert_byes, backend)
+ key = load_der_private_key(pk_bytes, password, backend)
+ else:
+ raise ValueError('Invalid encoding provided: Must be PEM or DER')
+
+ if not (cert and key):
+ raise ValueError('Cert and key could not be parsed from '
+ 'provided data')
+ check_cert_dates(cert)
+ ssl_context = PyOpenSSLContext(PROTOCOL)
+ ssl_context._ctx.use_certificate(X509.from_cryptography(cert))
+ ssl_context._ctx.use_privatekey(PKey.from_cryptography_key(key))
+ return ssl_context
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-toolbelt-0.8.0/requests_toolbelt/multipart/decoder.py
new/requests-toolbelt-0.9.1/requests_toolbelt/multipart/decoder.py
--- old/requests-toolbelt-0.8.0/requests_toolbelt/multipart/decoder.py
2017-02-10 22:55:25.000000000 +0100
+++ new/requests-toolbelt-0.9.1/requests_toolbelt/multipart/decoder.py
2018-10-08 13:43:24.000000000 +0200
@@ -45,7 +45,7 @@
subpart of a multipart response. It is expected that these will
generally be created by objects of the ``MultipartDecoder`` class.
- Like ``Response``, there is a ``CaseInsensitiveDict`` object named header,
+ Like ``Response``, there is a ``CaseInsensitiveDict`` object named headers,
``content`` to access bytes, ``text`` to access unicode, and ``encoding``
to access the unicode codec.
@@ -85,7 +85,7 @@
response = request.get(url)
decoder = MultipartDecoder.from_response(response)
for part in decoder.parts:
- print(part.header['content-type'])
+ print(part.headers['content-type'])
If the multipart content is not from a response, basic usage is::
@@ -93,7 +93,7 @@
decoder = MultipartDecoder(content, content_type)
for part in decoder.parts:
- print(part.header['content-type'])
+ print(part.headers['content-type'])
For both these usages, there is an optional ``encoding`` parameter. This is
a string, which is the name of the unicode codec to use (default is
@@ -101,8 +101,6 @@
"""
def __init__(self, content, content_type, encoding='utf-8'):
- #: Original content
- self.content = content
#: Original Content-Type header
self.content_type = content_type
#: Response body encoding
@@ -110,12 +108,12 @@
#: Parsed parts of the multipart response body
self.parts = tuple()
self._find_boundary()
- self._parse_body()
+ self._parse_body(content)
def _find_boundary(self):
ct_info = tuple(x.strip() for x in self.content_type.split(';'))
mimetype = ct_info[0]
- if mimetype.split('/')[0] != 'multipart':
+ if mimetype.split('/')[0].lower() != 'multipart':
raise NonMultipartContentTypeException(
"Unexpected mimetype in content-type: '{0}'".format(mimetype)
)
@@ -135,7 +133,7 @@
else:
return part
- def _parse_body(self):
+ def _parse_body(self, content):
boundary = b''.join((b'--', self.boundary))
def body_part(part):
@@ -148,7 +146,7 @@
part[:4] != b'--\r\n' and
part != b'--')
- parts = self.content.split(b''.join((b'\r\n', boundary)))
+ parts = content.split(b''.join((b'\r\n', boundary)))
self.parts = tuple(body_part(x) for x in parts if test_part(x))
@classmethod
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-toolbelt-0.8.0/requests_toolbelt/multipart/encoder.py
new/requests-toolbelt-0.9.1/requests_toolbelt/multipart/encoder.py
--- old/requests-toolbelt-0.8.0/requests_toolbelt/multipart/encoder.py
2017-01-19 15:23:03.000000000 +0100
+++ new/requests-toolbelt-0.9.1/requests_toolbelt/multipart/encoder.py
2018-10-08 13:43:24.000000000 +0200
@@ -12,14 +12,20 @@
import os
from uuid import uuid4
+import requests
+
from .._compat import fields
+class FileNotSupportedError(Exception):
+ """File not supported error."""
+
+
class MultipartEncoder(object):
"""
- The ``MultipartEncoder`` oject is a generic interface to the engine that
+ The ``MultipartEncoder`` object is a generic interface to the engine that
will create a ``multipart/form-data`` body for you.
The basic usage is:
@@ -74,7 +80,7 @@
please weigh in on `this issue`_.
.. _this issue:
- https://github.com/sigmavirus24/requests-toolbelt/issues/75
+ https://github.com/requests/toolbelt/issues/75
"""
@@ -136,7 +142,7 @@
As such, we now calculate the length lazily as a property.
.. _bug #80:
- https://github.com/sigmavirus24/requests-toolbelt/issues/80
+ https://github.com/requests/toolbelt/issues/80
"""
# If _len isn't already calculated, calculate, return, and set it
return self._len or self._calculate_length()
@@ -184,7 +190,7 @@
part = self._current_part or self._next_part()
while amount == -1 or amount > 0:
written = 0
- if not part.bytes_left_to_write():
+ if part and not part.bytes_left_to_write():
written += self._write(b'\r\n')
written += self._write_boundary()
part = self._next_part()
@@ -333,13 +339,13 @@
MultipartEncoderMonitor)
import requests
- def callback(encoder, bytes_read):
+ def callback(monitor):
# Do something with this information
pass
m = MultipartEncoder(fields={'field0': 'value0'})
monitor = MultipartEncoderMonitor(m, callback)
- headers = {'Content-Type': montior.content_type}
+ headers = {'Content-Type': monitor.content_type}
r = requests.post('https://httpbin.org/post', data=monitor,
headers=headers)
@@ -351,7 +357,7 @@
from requests_toolbelt import MultipartEncoderMonitor
import requests
- def callback(encoder, bytes_read):
+ def callback(monitor):
# Do something with this information
pass
@@ -568,3 +574,82 @@
def read(self, length=-1):
return self.fd.read(length)
+
+
+class FileFromURLWrapper(object):
+ """File from URL wrapper.
+
+ The :class:`FileFromURLWrapper` object gives you the ability to stream file
+ from provided URL in chunks by :class:`MultipartEncoder`.
+ Provide a stateless solution for streaming file from one server to another.
+ You can use the :class:`FileFromURLWrapper` without a session or with
+ a session as demonstated by the examples below:
+
+ .. code-block:: python
+ # no session
+
+ import requests
+ from requests_toolbelt import MultipartEncoder, FileFromURLWrapper
+
+ url = 'https://httpbin.org/image/png'
+ streaming_encoder = MultipartEncoder(
+ fields={
+ 'file': FileFromURLWrapper(url)
+ }
+ )
+ r = requests.post(
+ 'https://httpbin.org/post', data=streaming_encoder,
+ headers={'Content-Type': streaming_encoder.content_type}
+ )
+
+ .. code-block:: python
+ # using a session
+
+ import requests
+ from requests_toolbelt import MultipartEncoder, FileFromURLWrapper
+
+ session = requests.Session()
+ url = 'https://httpbin.org/image/png'
+ streaming_encoder = MultipartEncoder(
+ fields={
+ 'file': FileFromURLWrapper(url, session=session)
+ }
+ )
+ r = session.post(
+ 'https://httpbin.org/post', data=streaming_encoder,
+ headers={'Content-Type': streaming_encoder.content_type}
+ )
+
+ """
+
+ def __init__(self, file_url, session=None):
+ self.session = session or requests.Session()
+ requested_file = self._request_for_file(file_url)
+ self.len = int(requested_file.headers['content-length'])
+ self.raw_data = requested_file.raw
+
+ def _request_for_file(self, file_url):
+ """Make call for file under provided URL."""
+ response = self.session.get(file_url, stream=True)
+ content_length = response.headers.get('content-length', None)
+ if content_length is None:
+ error_msg = (
+ "Data from provided URL {url} is not supported. Lack of "
+ "content-length Header in requested file response.".format(
+ url=file_url)
+ )
+ raise FileNotSupportedError(error_msg)
+ elif not content_length.isdigit():
+ error_msg = (
+ "Data from provided URL {url} is not supported. content-length"
+ " header value is not a digit.".format(url=file_url)
+ )
+ raise FileNotSupportedError(error_msg)
+ return response
+
+ def read(self, chunk_size):
+ """Read file in chunks."""
+ chunk_size = chunk_size if chunk_size >= 0 else self.len
+ chunk = self.raw_data.read(chunk_size) or b''
+ self.len -= len(chunk) if chunk else 0 # left to read
+ return chunk
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-toolbelt-0.8.0/requests_toolbelt/threaded/__init__.py
new/requests-toolbelt-0.9.1/requests_toolbelt/threaded/__init__.py
--- old/requests-toolbelt-0.8.0/requests_toolbelt/threaded/__init__.py
2017-01-19 15:23:03.000000000 +0100
+++ new/requests-toolbelt-0.9.1/requests_toolbelt/threaded/__init__.py
2017-06-03 02:35:47.000000000 +0200
@@ -14,7 +14,7 @@
'url': 'https://api.github.com/users/sigmavirus24',
'method': 'GET',
}, {
- 'url': 'https://api.github.com/repos/sigmavirus24/requests-toolbelt',
+ 'url': 'https://api.github.com/repos/requests/toolbelt',
'method': 'GET',
}, {
'url': 'https://google.com',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-toolbelt-0.8.0/requests_toolbelt/threaded/pool.py
new/requests-toolbelt-0.9.1/requests_toolbelt/threaded/pool.py
--- old/requests-toolbelt-0.8.0/requests_toolbelt/threaded/pool.py
2017-01-19 15:23:03.000000000 +0100
+++ new/requests-toolbelt-0.9.1/requests_toolbelt/threaded/pool.py
2018-01-05 13:36:25.000000000 +0100
@@ -18,7 +18,7 @@
:param auth_generator:
Function used to generate new auth credentials for the session.
:type auth_generator: collections.Callable
- :param int num_threads:
+ :param int num_process:
Number of threads to create.
:param session:
:type session: requests.Session
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-toolbelt-0.8.0/requests_toolbelt/utils/dump.py
new/requests-toolbelt-0.9.1/requests_toolbelt/utils/dump.py
--- old/requests-toolbelt-0.8.0/requests_toolbelt/utils/dump.py 2017-01-19
15:23:03.000000000 +0100
+++ new/requests-toolbelt-0.9.1/requests_toolbelt/utils/dump.py 2019-01-29
18:43:33.000000000 +0100
@@ -44,7 +44,8 @@
uri = compat.urlparse(url)
proxy_url = proxy_info.get('request_path')
if proxy_url is not None:
- return proxy_url, uri
+ request_path = _coerce_to_bytes(proxy_url)
+ return request_path, uri
request_path = _coerce_to_bytes(uri.path)
if uri.query:
@@ -79,7 +80,7 @@
else:
# In the event that the body is a file-like object, let's not try
# to read everything into memory.
- bytearr.extend('<< Request body is not a string-like type >>')
+ bytearr.extend(b'<< Request body is not a string-like type >>')
bytearr.extend(b'\r\n')
@@ -109,7 +110,8 @@
def _coerce_to_bytes(data):
if not isinstance(data, bytes) and hasattr(data, 'encode'):
data = data.encode('utf-8')
- return data
+ # Don't bail out with an exception if data is None
+ return data if data is not None else b''
def dump_response(response, request_prefix=b'< ', response_prefix=b'> ',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-toolbelt-0.8.0/requests_toolbelt.egg-info/PKG-INFO
new/requests-toolbelt-0.9.1/requests_toolbelt.egg-info/PKG-INFO
--- old/requests-toolbelt-0.8.0/requests_toolbelt.egg-info/PKG-INFO
2017-05-20 23:32:32.000000000 +0200
+++ new/requests-toolbelt-0.9.1/requests_toolbelt.egg-info/PKG-INFO
2019-01-30 02:29:41.000000000 +0100
@@ -1,13 +1,13 @@
Metadata-Version: 1.1
Name: requests-toolbelt
-Version: 0.8.0
+Version: 0.9.1
Summary: A utility belt for advanced users of python-requests
Home-page: https://toolbelt.readthedocs.org
Author: Ian Cordasco, Cory Benfield
Author-email: [email protected]
License: Apache 2.0
-Description: requests toolbelt
- =================
+Description: The Requests Toolbelt
+ =====================
This is just a collection of utilities for `python-requests`_, but
don't
really belong in ``requests`` proper. The minimum tested requests
version is
@@ -118,13 +118,58 @@
<https://toolbelt.readthedocs.org/en/latest/contributing.html>`_ for
contributing to this project.
+ Please report any bugs on the `issue tracker`_
+
.. _Cory Benfield's blog:
https://lukasa.co.uk/2013/01/Choosing_SSL_Version_In_Requests/
.. _python-requests: https://github.com/kennethreitz/requests
+ .. _issue tracker: https://github.com/requests/toolbelt/issues
History
=======
+ 0.9.1 -- 2019-01-29
+ -------------------
+
+ Fixed Bugs
+ ~~~~~~~~~~
+
+ - Fix import of pyOpenSSL shim from urllib3 for PKCS12 adapter
+
+ 0.9.0 -- 2019-01-29
+ -------------------
+
+ New Features
+ ~~~~~~~~~~~~
+
+ - Add X509 Adapter that can handle PKCS12
+ - Add stateless solution for streaming files by MultipartEncoder from
one host to another (in chunks)
+
+ Fixed Bugs
+ ~~~~~~~~~~
+
+ - Update link to example
+ - Move import of ``ABCs`` from collections into version-specific part
of
+ _compat module
+ - Fix backwards incompatibility in ``get_encodings_from_content``
+ - Correct callback documentation for ``MultipartEncoderMonitor``
+ - Fix bug when ``MultipartEncoder`` is asked to encode zero parts
+ - Correct the type of non string request body dumps
+ - Removed content from being stored in MultipartDecoder
+ - Fix bug by enabling support for contenttype with capital letters.
+ - Coerce proxy URL to bytes before dumping request
+ - Avoid bailing out with exception upon empty response reason
+ - Corrected Pool documentation
+ - Corrected parentheses match in example usage
+ - Fix "oject" to "object" in ``MultipartEncoder``
+ - Fix URL for the project after the move
+ - Add fix for OSX TCPKeepAliveAdapter
+
+ Miscellaneous
+ ~~~~~~~~~~~~~
+
+ - Remove py33 from testing and add Python 3.6 and nightly testing to
the travis matrix.
+
0.8.0 -- 2017-05-20
-------------------
@@ -144,7 +189,7 @@
- Fix backwards incompatibility in ``get_encodings_from_content``
.. _0.8.0 milestone:
- https://github.com/sigmavirus24/requests-toolbelt/milestones/0.8.0
+ https://github.com/requests/toolbelt/milestones/0.8.0
0.7.1 -- 2017-02-13
-------------------
@@ -164,7 +209,7 @@
.. links
.. _0.7.1 milestone:
- https://github.com/sigmavirus24/requests-toolbelt/milestone/9
+ https://github.com/requests/toolbelt/milestone/9
0.7.0 -- 2016-07-21
-------------------
@@ -193,7 +238,7 @@
.. _0.7.0 milestone:
- https://github.com/sigmavirus24/requests-toolbelt/milestones/0.7.0
+ https://github.com/requests/toolbelt/milestones/0.7.0
0.6.2 -- 2016-05-10
-------------------
@@ -247,7 +292,7 @@
.. _0.6.0 milestone:
- https://github.com/sigmavirus24/requests-toolbelt/milestones/0.6.0
+ https://github.com/requests/toolbelt/milestones/0.6.0
0.5.1 -- 2015-12-16
-------------------
@@ -262,13 +307,13 @@
.. _0.5.1 milestone:
- https://github.com/sigmavirus24/requests-toolbelt/milestones/0.5.1
+ https://github.com/requests/toolbelt/milestones/0.5.1
0.5.0 -- 2015-11-24
-------------------
More information about this release can be found on the `milestone
-
<https://github.com/sigmavirus24/requests-toolbelt/issues?utf8=%E2%9C%93&q=is%3Aall+milestone%3A0.5+>`_
+
<https://github.com/requests/toolbelt/issues?utf8=%E2%9C%93&q=is%3Aall+milestone%3A0.5+>`_
for 0.5.0.
New Features
@@ -307,7 +352,7 @@
-------------------
For more information about this release, please see `milestone 0.4.0
-
<https://github.com/sigmavirus24/requests-toolbelt/issues?q=milestone%3A0.4>`_
+ <https://github.com/requests/toolbelt/issues?q=milestone%3A0.4>`_
on the project's page.
New Features
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-toolbelt-0.8.0/requests_toolbelt.egg-info/SOURCES.txt
new/requests-toolbelt-0.9.1/requests_toolbelt.egg-info/SOURCES.txt
--- old/requests-toolbelt-0.8.0/requests_toolbelt.egg-info/SOURCES.txt
2017-05-20 23:32:33.000000000 +0200
+++ new/requests-toolbelt-0.9.1/requests_toolbelt.egg-info/SOURCES.txt
2019-01-30 02:29:41.000000000 +0100
@@ -42,6 +42,7 @@
requests_toolbelt/adapters/socket_options.py
requests_toolbelt/adapters/source.py
requests_toolbelt/adapters/ssl.py
+requests_toolbelt/adapters/x509.py
requests_toolbelt/auth/__init__.py
requests_toolbelt/auth/_digest_auth_compat.py
requests_toolbelt/auth/guess.py
@@ -84,6 +85,8 @@
tests/test_ssladapter.py
tests/test_streaming_iterator.py
tests/test_user_agent.py
+tests/test_x509_adapter.py
+tests/cassettes/file_for_download.json
tests/cassettes/http2bin_cookies.json
tests/cassettes/http2bin_fingerprint.json
tests/cassettes/httpbin_guess_auth_basic.json
@@ -93,6 +96,9 @@
tests/cassettes/redirect_request_for_dump_all.json
tests/cassettes/simple_get_request.json
tests/cassettes/stream_response_to_file.json
+tests/cassettes/test_x509_adapter_der.json
+tests/cassettes/test_x509_adapter_pem.json
+tests/certs/test_cert.p12
tests/threaded/__init__.py
tests/threaded/test_api.py
tests/threaded/test_pool.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-toolbelt-0.8.0/requests_toolbelt.egg-info/requires.txt
new/requests-toolbelt-0.9.1/requests_toolbelt.egg-info/requires.txt
--- old/requests-toolbelt-0.8.0/requests_toolbelt.egg-info/requires.txt
2017-05-20 23:32:32.000000000 +0200
+++ new/requests-toolbelt-0.9.1/requests_toolbelt.egg-info/requires.txt
2019-01-30 02:29:41.000000000 +0100
@@ -1 +1 @@
-requests>=2.0.1,<3.0.0
+requests<3.0.0,>=2.0.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-toolbelt-0.8.0/tests/cassettes/file_for_download.json
new/requests-toolbelt-0.9.1/tests/cassettes/file_for_download.json
--- old/requests-toolbelt-0.8.0/tests/cassettes/file_for_download.json
1970-01-01 01:00:00.000000000 +0100
+++ new/requests-toolbelt-0.9.1/tests/cassettes/file_for_download.json
2018-10-08 13:43:24.000000000 +0200
@@ -0,0 +1 @@
+{"http_interactions": [{"request": {"uri":
"https://stxnext.com/static/img/logo.830ebe551641.svg", "body": {"encoding":
"utf-8", "string": ""}, "method": "GET", "headers": {"User-Agent":
["python-requests/2.2.1 CPython/3.5.2 Darwin/17.3.0"], "Accept-Encoding":
["gzip, deflate, compress"], "Accept": ["*/*"]}}, "recorded_at":
"2018-01-04T23:00:12", "response": {"url":
"https://stxnext.com/static/img/logo.830ebe551641.svg", "status": {"message":
"OK", "code": 200}, "body": {"encoding": null, "string": "<svg
xmlns=\"http://www.w3.org/2000/svg\"
xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"-16169 -10492.84 144.98
39.947\"><defs><style>.a{fill:url(#a);}</style><linearGradient id=\"a\"
x2=\"1\" y2=\"1\" gradientUnits=\"objectBoundingBox\"><stop offset=\"0\"
stop-color=\"#15c9c2\"/><stop offset=\"1\"
stop-color=\"#39769b\"/></linearGradient></defs><path class=\"a\"
d=\"M88.841,54.948V48.514a3.665,3.665,0,0,1,1.541-.336,2.169,2.169,0,0,1,2.266,2.435A2.182,2.182,0,0,1,90.435,53.1a2.9,2.9,0,0,1-.85-.125v1.974Zm.744-6.019v3.46a2.558,2.558,0,0,0,.8.125c1,0,1.523-.807,1.523-1.9s-.525-1.84-1.506-1.84h-.041A1.986,1.986,0,0,0,89.585,48.929ZM62.838,54.948l.717-1.9-1.788-4.769h.805l1.187,3.472a5.008,5.008,0,0,1,.167.682h.019a5.01,5.01,0,0,1,.167-.682l1.177-3.472h.815l-2.5,6.672Zm-5.749,0V48.514a3.669,3.669,0,0,1,1.541-.336A2.169,2.169,0,0,1,60.9,50.613,2.185,2.185,0,0,1,58.683,53.1a2.9,2.9,0,0,1-.85-.125v1.974Zm.74-6.019v3.46a2.558,2.558,0,0,0,.8.125c1,0,1.523-.807,1.523-1.9s-.529-1.84-1.513-1.84H58.6A1.986,1.986,0,0,0,57.829,48.929Zm79.213,4.213a2.19,2.19,0,0,1-2.282-2.487c0-1.462.788-2.478,2.08-2.478a1.825,1.825,0,0,1,1.9,2.044c0,.1,0,.205-.008.318l-3.257.469a1.5,1.5,0,0,0,1.6,1.532,2.886,2.886,0,0,0,1.3-.292l.23.557a3.431,3.431,0,0,1-1.484.336ZM135.432,50.5l2.6-.366c-.011-.944-.488-1.386-1.2-1.386C135.989,48.744,135.45,49.416,135.432,50.5ZM130.4,52.8l.265-.567a2.665,2.665,0,0,0,1.143.3c.611,0,1.018-.3,1.018-.77,0-.5-.407-.7-.965-.9-.673-.248-1.336-.549-1.336-1.408,0-.744.575-1.279,1.585-1.279a2.6,2.6,0,0,1,1.327.336l-.257.523a2.054,2.054,0,0,0-1-.283c-.576,0-.9.309-.9.707,0,.5.388.682.913.875.708.265,1.4.549,1.4,1.434.006.823-.649,1.372-1.772,1.372A3.261,3.261,0,0,1,130.4,52.8Zm-3.008.34c-1.187,0-1.841-.523-1.841-1.672V48.276h.744v3.2c0,.707.366,1.043,1.1,1.043a2.914,2.914,0,0,0,1.008-.158V48.276h.73V52.8a4.263,4.263,0,0,1-1.664.34Zm-7.256-2.487c0-1.417.708-2.478,2.028-2.478s2.026,1.061,2.026,2.478-.709,2.487-2.026,2.487S120.14,52.071,120.14,50.655Zm.735-.007c0,1.1.424,1.884,1.292,1.884s1.291-.788,1.291-1.884-.425-1.866-1.291-1.866v0C121.3,48.779,120.875,49.549,120.875,50.648Zm-12.187,2.494a2.19,2.19,0,0,1-2.282-2.487c0-1.462.788-2.478,2.08-2.478a1.825,1.825,0,0,1,1.9,2.044c0,.1,0,.205-.009.318l-3.256.469a1.494,1.494,0,0,0,1.6,1.532,2.886,2.886,0,0,0,1.3-.292l.23.557a3.431,3.431,0,0,1-1.484.336ZM107.079,50.5l2.6-.366c-.01-.944-.488-1.386-1.2-1.386C107.636,48.744,107.1,49.416,107.079,50.5Zm-13.249.159c0-1.417.708-2.478,2.028-2.478s2.026,1.061,2.026,2.478-.707,2.487-2.026,2.487S93.83,52.071,93.83,50.655Zm.735-.007c0,1.1.424,1.884,1.292,1.884s1.291-.788,1.291-1.884-.424-1.866-1.291-1.866v0C94.989,48.779,94.565,49.549,94.565,50.648Zm-18.973.007c0-1.417.708-2.478,2.028-2.478s2.032,1.061,2.032,2.478-.715,2.487-2.032,2.487S75.592,52.071,75.592,50.655Zm.735-.007c0,1.1.424,1.884,1.292,1.884s1.292-.788,1.292-1.884-.426-1.866-1.292-1.866v0C76.752,48.779,76.328,49.549,76.328,50.648ZM68.85,53.1a1.149,1.149,0,0,1-1.257-1.292V48.833H66.9v-.557h.688V47.123l.716-.239v1.389h1.027v.557H68.306v2.939a.634.634,0,0,0,.716.673,1.006,1.006,0,0,0,.309-.044v.619a1.308,1.308,0,0,1-.453.081Zm15.078-.053V49.823c0-.638-.39-1.044-1.158-1.044a2.968,2.968,0,0,0-1.018.169v4.1h-.745V48.513a4.5,4.5,0,0,1,1.753-.336c1.257,0,1.9.584,1.9,1.585v3.289Zm34.114-3.212c0-.7-.461-1.037-1.187-1.037a2.036,2.036,0,0,0-.989.265v3.983h-.744V46.1h.744v2.376A2.616,2.616,0,0,1,117,48.191c1.1,0,1.778.557,1.778,1.585v3.265l-.734,0Zm-6.285,3.212V48.513a4.493,4.493,0,0,1,1.743-.336,3.273,3.273,0,0,1,.47.034l-.143.621a2.031,2.031,0,0,0-.424-.034,2.461,2.461,0,0,0-.9.15v4.1Zm-8.485,0-.974-3.327a5.884,5.884,0,0,1-.14-.654h-.019s-.062.354-.15.654l-.974,3.327h-.753l-1.45-4.769h.744l.93,3.371a7.42,7.42,0,0,1,.15.732h.019s.07-.407.158-.732l.974-3.371h.709l.966,3.371c.088.318.167.732.167.732h.019a6.418,6.418,0,0,1,.143-.732l.947-3.371h.731l-1.442,4.769ZM73.5,49.833c0-.7-.461-1.037-1.187-1.037a2.044,2.044,0,0,0-.991.265v3.983h-.744V46.1h.744v2.376a2.612,2.612,0,0,1,1.133-.283c1.1,0,1.778.557,1.778,1.585v3.265l-.734,0Zm-27.141-6,8.837-14.534L46.91,15.475h7.926l7.925,13.819L54.32,43.828Zm-15.478,0V21.688H23.911V15.474H44.819v6.213H37.846V43.828ZM0,40.086l4.455-4.463c1.473,1.473,4.064,1.99,6.331,1.99,2.741,0,4.062-.913,4.062-2.548a2.4,2.4,0,0,0-.548-1.671,3.133,3.133,0,0,0-1.872-.757L9,32.158A9.631,9.631,0,0,1,3.31,29.651a7.847,7.847,0,0,1-1.953-5.7C1.358,18.778,5.26,15,11.712,15c4.06,0,7.127.956,9.558,3.385l-4.387,4.385C15.092,20.98,12.742,21.1,11.506,21.1c-2.429,0-3.424,1.394-3.424,2.63a1.868,1.868,0,0,0,.557,1.315,3.179,3.179,0,0,0,1.952.836l3.426.48a9.569,9.569,0,0,1,5.576,2.348c1.513,1.473,2.111,3.584,2.111,6.213,0,5.761-4.982,8.907-10.95,8.907C6.412,43.828,2.866,43.031,0,40.086Zm111.6,3.73,6.958-11.665-6.518-11.076h2.81l5.048,8.975,5.046-8.975h2.812L121.2,32.15l7.027,11.658-2.812.006L119.9,34.265l-5.558,9.55Zm24.376,0V23.245h-6.579V21.074h15.588v2.171H138.4V43.814ZM95.878,21.074H109.99v2.173h-11.7v8.018h9.966v2.165H98.3v8.21H110v2.173l-14.123,0ZM90.192,43.814,78.12,25.571V43.808H75.692V21.074h2.3L90.069,39.247V21.074H92.5V43.814ZM63.528,43.8l-2.683-5.029,3.7-6.344,6.611,11.379Zm-2.7-24.291,2.094-4.046h7.919L64.668,26.125Z\"
transform=\"translate(-16169 -10507.84)\"/></svg>"}, "headers": {"date":
["Thu, 04 Jan 2018 23:00:15 GMT"], "strict-transport-security": ["max-age=0;
includeSubdomains; preload"], "last-modified": ["Wed, 22 Nov 2017 09:22:00
GMT"], "content-type": ["image/svg+xml"], "content-length": ["5177"]}}}],
"recorded_with": "betamax/0.8.0"}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-toolbelt-0.8.0/tests/cassettes/test_x509_adapter_der.json
new/requests-toolbelt-0.9.1/tests/cassettes/test_x509_adapter_der.json
--- old/requests-toolbelt-0.8.0/tests/cassettes/test_x509_adapter_der.json
1970-01-01 01:00:00.000000000 +0100
+++ new/requests-toolbelt-0.9.1/tests/cassettes/test_x509_adapter_der.json
2019-01-29 18:43:40.000000000 +0100
@@ -0,0 +1 @@
+{"http_interactions": [{"request": {"body": {"encoding": "utf-8", "string":
""}, "headers": {"User-Agent": ["python-requests/2.21.0"], "Accept-Encoding":
["gzip, deflate"], "Accept": ["*/*"], "Connection": ["keep-alive"]}, "method":
"GET", "uri": "https://pkiprojecttest01.dev.labs.internal/"}, "response":
{"body": {"encoding": "ISO-8859-1", "base64_string":
"H4sIAAAAAAAAA7NRdPF3DokMcFXIKMnNseOygVJJ+SmVdlxArqFdSGpxiY0+kAHkFoB5CsGlycmpxcU2+gUgQX2IYqAasBEAYvDs5FMAAAA=",
"string": ""}, "headers": {"Server": ["nginx/1.10.3 (Ubuntu)"], "Date": ["Thu,
20 Dec 2018 20:02:30 GMT"], "Content-Type": ["text/html"], "Last-Modified":
["Mon, 19 Nov 2018 20:48:30 GMT"], "Transfer-Encoding": ["chunked"],
"Connection": ["keep-alive"], "ETag": ["W/\"5bf3219e-53\""],
"Content-Encoding": ["gzip"]}, "status": {"code": 200, "message": "OK"}, "url":
"https://pkiprojecttest01.dev.labs.internal/"}, "recorded_at":
"2018-12-20T20:02:30"}], "recorded_with": "betamax/0.8.1"}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-toolbelt-0.8.0/tests/cassettes/test_x509_adapter_pem.json
new/requests-toolbelt-0.9.1/tests/cassettes/test_x509_adapter_pem.json
--- old/requests-toolbelt-0.8.0/tests/cassettes/test_x509_adapter_pem.json
1970-01-01 01:00:00.000000000 +0100
+++ new/requests-toolbelt-0.9.1/tests/cassettes/test_x509_adapter_pem.json
2019-01-29 18:43:40.000000000 +0100
@@ -0,0 +1 @@
+{"http_interactions": [{"request": {"body": {"encoding": "utf-8", "string":
""}, "headers": {"User-Agent": ["python-requests/2.21.0"], "Accept-Encoding":
["gzip, deflate"], "Accept": ["*/*"], "Connection": ["keep-alive"]}, "method":
"GET", "uri": "https://pkiprojecttest01.dev.labs.internal/"}, "response":
{"body": {"encoding": "ISO-8859-1", "base64_string":
"H4sIAAAAAAAAA7NRdPF3DokMcFXIKMnNseOygVJJ+SmVdlxArqFdSGpxiY0+kAHkFoB5CsGlycmpxcU2+gUgQX2IYqAasBEAYvDs5FMAAAA=",
"string": ""}, "headers": {"Server": ["nginx/1.10.3 (Ubuntu)"], "Date": ["Thu,
20 Dec 2018 20:02:30 GMT"], "Content-Type": ["text/html"], "Last-Modified":
["Mon, 19 Nov 2018 20:48:30 GMT"], "Transfer-Encoding": ["chunked"],
"Connection": ["keep-alive"], "ETag": ["W/\"5bf3219e-53\""],
"Content-Encoding": ["gzip"]}, "status": {"code": 200, "message": "OK"}, "url":
"https://pkiprojecttest01.dev.labs.internal/"}, "recorded_at":
"2018-12-20T20:02:30"}], "recorded_with": "betamax/0.8.1"}
\ No newline at end of file
Binary files old/requests-toolbelt-0.8.0/tests/certs/test_cert.p12 and
new/requests-toolbelt-0.9.1/tests/certs/test_cert.p12 differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-toolbelt-0.8.0/tests/test_dump.py
new/requests-toolbelt-0.9.1/tests/test_dump.py
--- old/requests-toolbelt-0.8.0/tests/test_dump.py 2017-01-19
15:23:03.000000000 +0100
+++ new/requests-toolbelt-0.9.1/tests/test_dump.py 2019-01-29
18:43:33.000000000 +0100
@@ -211,6 +211,26 @@
assert b'request:GET / HTTP/1.1\r\n' in array
assert b'request:Host: example.com\r\n' in array
+ def test_dump_non_string_request_data(self):
+ """Build up the request data into a bytearray."""
+ self.configure_request(
+ url='http://example.com/',
+ method='POST',
+ body=1
+ )
+
+ array = bytearray()
+ prefixes = dump.PrefixSettings('request:', 'response:')
+ dump._dump_request_data(
+ request=self.request,
+ prefixes=prefixes,
+ bytearr=array,
+ proxy_info={},
+ )
+ assert b'request:POST / HTTP/1.1\r\n' in array
+ assert b'request:Host: example.com\r\n' in array
+ assert b'<< Request body is not a string-like type >>\r\n' in array
+
def test_dump_request_data_with_proxy_info(self):
"""Build up the request data into a bytearray."""
self.configure_request(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-toolbelt-0.8.0/tests/test_multipart_decoder.py
new/requests-toolbelt-0.9.1/tests/test_multipart_decoder.py
--- old/requests-toolbelt-0.8.0/tests/test_multipart_decoder.py 2017-01-19
15:23:03.000000000 +0100
+++ new/requests-toolbelt-0.9.1/tests/test_multipart_decoder.py 2018-01-05
13:36:25.000000000 +0100
@@ -162,3 +162,30 @@
assert decoder_2.parts[0].headers[b'Header-1'] == b'Header-Value-1'
assert len(decoder_2.parts[1].headers) == 0
assert decoder_2.parts[1].content == b'Body 2, Line 1'
+
+ def test_from_responsecaplarge(self):
+ response = mock.NonCallableMagicMock(spec=requests.Response)
+ response.headers = {
+ 'content-type': 'Multipart/Related; boundary="samp1"'
+ }
+ cnt = io.BytesIO()
+ cnt.write(b'\r\n--samp1\r\n')
+ cnt.write(b'Header-1: Header-Value-1\r\n')
+ cnt.write(b'Header-2: Header-Value-2\r\n')
+ cnt.write(b'\r\n')
+ cnt.write(b'Body 1, Line 1\r\n')
+ cnt.write(b'Body 1, Line 2\r\n')
+ cnt.write(b'--samp1\r\n')
+ cnt.write(b'\r\n')
+ cnt.write(b'Body 2, Line 1\r\n')
+ cnt.write(b'--samp1--\r\n')
+ response.content = cnt.getvalue()
+ decoder_2 = MultipartDecoder.from_response(response)
+ assert decoder_2.content_type == response.headers['content-type']
+ assert (
+ decoder_2.parts[0].content == b'Body 1, Line 1\r\nBody 1, Line 2'
+ )
+ assert decoder_2.parts[0].headers[b'Header-1'] == b'Header-Value-1'
+ assert len(decoder_2.parts[1].headers) == 0
+ assert decoder_2.parts[1].content == b'Body 2, Line 1'
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/requests-toolbelt-0.8.0/tests/test_multipart_encoder.py
new/requests-toolbelt-0.9.1/tests/test_multipart_encoder.py
--- old/requests-toolbelt-0.8.0/tests/test_multipart_encoder.py 2017-01-19
15:23:03.000000000 +0100
+++ new/requests-toolbelt-0.9.1/tests/test_multipart_encoder.py 2018-10-08
13:43:24.000000000 +0200
@@ -1,8 +1,16 @@
# -*- coding: utf-8 -*-
import unittest
import io
-from requests_toolbelt.multipart.encoder import CustomBytesIO, MultipartEncoder
+
+import requests
+
+from requests_toolbelt.multipart.encoder import (
+ CustomBytesIO, MultipartEncoder, FileFromURLWrapper, FileNotSupportedError)
from requests_toolbelt._compat import filepost
+from . import get_betamax
+
+
+preserve_bytes = {'preserve_exact_body_bytes': True}
class LargeFileMock(object):
@@ -81,6 +89,44 @@
assert self.instance.read() == s
+class TestFileFromURLWrapper(unittest.TestCase):
+ def setUp(self):
+ s = requests.Session()
+ self.recorder = get_betamax(s)
+
+ def test_read_file(self):
+ url = ('https://stxnext.com/static/img/logo.830ebe551641.svg')
+ with self.recorder.use_cassette(
+ 'file_for_download', **preserve_bytes):
+ self.instance = FileFromURLWrapper(url)
+ assert self.instance.len == 5177
+ chunk = self.instance.read(20)
+ assert chunk == b'<svg xmlns="http://w'
+ assert self.instance.len == 5157
+ chunk = self.instance.read(0)
+ assert chunk == b''
+ assert self.instance.len == 5157
+ chunk = self.instance.read(10)
+ assert chunk == b'ww.w3.org/'
+ assert self.instance.len == 5147
+
+ def test_no_content_length_header(self):
+ url = (
+ 'https://api.github.com/repos/sigmavirus24/github3.py/releases/'
+ 'assets/37944'
+ )
+ with self.recorder.use_cassette(
+ 'stream_response_to_file', **preserve_bytes):
+ with self.assertRaises(FileNotSupportedError) as context:
+ FileFromURLWrapper(url)
+ assert context.exception.__str__() == (
+ 'Data from provided URL https://api.github.com/repos/s'
+ 'igmavirus24/github3.py/releases/assets/37944 is not '
+ 'supported. Lack of content-length Header in requested'
+ ' file response.'
+ )
+
+
class TestMultipartEncoder(unittest.TestCase):
def setUp(self):
self.parts = [('field', 'value'), ('other_field', 'other_value')]
@@ -145,6 +191,16 @@
m = MultipartEncoder([('field', 'foo'), ('file', fd)])
assert m.read() is not None
+ def test_reads_file_from_url_wrapper(self):
+ s = requests.Session()
+ recorder = get_betamax(s)
+ url = ('https://stxnext.com/static/img/logo.830ebe551641.svg')
+ with recorder.use_cassette(
+ 'file_for_download'):
+ m = MultipartEncoder(
+ [('field', 'foo'), ('file', FileFromURLWrapper(url))])
+ assert m.read() is not None
+
def test_reads_open_file_objects_with_a_specified_filename(self):
with open('setup.py', 'rb') as fd:
m = MultipartEncoder(
@@ -219,7 +275,7 @@
def test_handles_empty_unicode_values(self):
"""Verify that the Encoder can handle empty unicode strings.
- See https://github.com/sigmavirus24/requests-toolbelt/issues/46 for
+ See https://github.com/requests/toolbelt/issues/46 for
more context.
"""
fields = [(b'test'.decode('utf-8'), b''.decode('utf-8'))]
@@ -229,7 +285,7 @@
def test_accepts_custom_content_type(self):
"""Verify that the Encoder handles custom content-types.
- See https://github.com/sigmavirus24/requests-toolbelt/issues/52
+ See https://github.com/requests/toolbelt/issues/52
"""
fields = [
(b'test'.decode('utf-8'), (b'filename'.decode('utf-8'),
@@ -243,7 +299,7 @@
def test_accepts_custom_headers(self):
"""Verify that the Encoder handles custom headers.
- See https://github.com/sigmavirus24/requests-toolbelt/issues/52
+ See https://github.com/requests/toolbelt/issues/52
"""
fields = [
(b'test'.decode('utf-8'), (b'filename'.decode('utf-8'),
@@ -255,6 +311,12 @@
output = m.read().decode('utf-8')
assert output.index('X-My-Header: my-value\r\n') > 0
+ def test_no_parts(self):
+ fields = []
+ boundary = '--90967316f8404798963cce746a4f4ef9'
+ m = MultipartEncoder(fields=fields, boundary=boundary)
+ output = m.read().decode('utf-8')
+ assert output == '----90967316f8404798963cce746a4f4ef9--\r\n'
if __name__ == '__main__':
unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-toolbelt-0.8.0/tests/test_x509_adapter.py
new/requests-toolbelt-0.9.1/tests/test_x509_adapter.py
--- old/requests-toolbelt-0.8.0/tests/test_x509_adapter.py 1970-01-01
01:00:00.000000000 +0100
+++ new/requests-toolbelt-0.9.1/tests/test_x509_adapter.py 2019-01-29
18:43:40.000000000 +0100
@@ -0,0 +1,67 @@
+# -*- coding: utf-8 -*-
+import requests
+import unittest
+import pytest
+
+from OpenSSL.crypto import load_pkcs12
+from cryptography.hazmat.primitives.serialization import (Encoding,
+ PrivateFormat,
+ NoEncryption,
+
BestAvailableEncryption)
+
+from requests_toolbelt import exceptions as exc
+from requests_toolbelt.adapters.x509 import X509Adapter
+from . import get_betamax
+
+REQUESTS_SUPPORTS_SSL_CONTEXT = requests.__build__ >= 0x021200
+
+
+class TestX509Adapter(unittest.TestCase):
+ """Tests a simple requests.get() call using a .p12 cert.
+ """
+ def setUp(self):
+ with open('./tests/certs/test_cert.p12', 'rb') as pkcs12_file:
+ self.pkcs12_data = pkcs12_file.read()
+
+ self.pkcs12_password_bytes = "test".encode('utf8')
+ self.session = requests.Session()
+
+ @pytest.mark.skipif(not REQUESTS_SUPPORTS_SSL_CONTEXT,
+ reason="Requires Requests v2.12.0 or later")
+ def test_x509_pem(self):
+ p12 = load_pkcs12(self.pkcs12_data, self.pkcs12_password_bytes)
+ cert_bytes =
p12.get_certificate().to_cryptography().public_bytes(Encoding.PEM)
+ pk_bytes = p12.get_privatekey().\
+ to_cryptography_key().\
+ private_bytes(Encoding.PEM, PrivateFormat.PKCS8,
+
BestAvailableEncryption(self.pkcs12_password_bytes))
+
+ adapter = X509Adapter(max_retries=3, cert_bytes=cert_bytes,
+ pk_bytes=pk_bytes,
password=self.pkcs12_password_bytes)
+ self.session.mount('https://', adapter)
+ recorder = get_betamax(self.session)
+ with recorder.use_cassette('test_x509_adapter_pem'):
+ r =
self.session.get('https://pkiprojecttest01.dev.labs.internal/', verify=False)
+
+ assert r.status_code == 200
+ assert r.text
+
+ @pytest.mark.skipif(not REQUESTS_SUPPORTS_SSL_CONTEXT,
+ reason="Requires Requests v2.12.0 or later")
+ def test_x509_der(self):
+ p12 = load_pkcs12(self.pkcs12_data, self.pkcs12_password_bytes)
+ cert_bytes =
p12.get_certificate().to_cryptography().public_bytes(Encoding.DER)
+ pk_bytes =
p12.get_privatekey().to_cryptography_key().private_bytes(Encoding.DER,
PrivateFormat.PKCS8, NoEncryption())
+ adapter = X509Adapter(max_retries=3, cert_bytes=cert_bytes,
pk_bytes=pk_bytes, encoding=Encoding.DER)
+ self.session.mount('https://', adapter)
+ recorder = get_betamax(self.session)
+ with recorder.use_cassette('test_x509_adapter_der'):
+ r =
self.session.get('https://pkiprojecttest01.dev.labs.internal/', verify=False)
+
+ assert r.status_code == 200
+ assert r.text
+
+ @pytest.mark.skipif(REQUESTS_SUPPORTS_SSL_CONTEXT, reason="Will not raise
exc")
+ def test_requires_new_enough_requests(self):
+ with pytest.raises(exc.VersionMismatchError):
+ X509Adapter()
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/requests-toolbelt-0.8.0/tox.ini
new/requests-toolbelt-0.9.1/tox.ini
--- old/requests-toolbelt-0.8.0/tox.ini 2017-01-19 15:23:03.000000000 +0100
+++ new/requests-toolbelt-0.9.1/tox.ini 2019-01-30 02:28:21.000000000 +0100
@@ -1,5 +1,5 @@
[tox]
-envlist = py27,py33,py34,py35,pypy,{py27,py34}-flake8,docstrings
+envlist = py27,py34,py35,py36,pypy,{py27,py34}-flake8,docstrings
[testenv]
pip_pre = False
@@ -7,8 +7,11 @@
requests{env:REQUESTS_VERSION:>=2.0.1,<3.0.0}
pytest
mock
+ pyopenssl
+ ndg-httpsclient
betamax>0.5.0
-commands = py.test {posargs}
+commands =
+ py.test {posargs}
[testenv:py27-flake8]
basepython = python2.7
@@ -32,6 +35,7 @@
deps =
sphinx>=1.3.0
sphinx_rtd_theme
+ pyopenssl
.
commands =
sphinx-build -E -c docs -b html docs/ docs/_build/html