Hello community, here is the log from the commit of package python-apiron for openSUSE:Factory checked in at 2020-08-31 16:50:46 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-apiron (Old) and /work/SRC/openSUSE:Factory/.python-apiron.new.3399 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-apiron" Mon Aug 31 16:50:46 2020 rev:2 rq:830623 version:5.1.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-apiron/python-apiron.changes 2019-12-04 14:19:58.598417730 +0100 +++ /work/SRC/openSUSE:Factory/.python-apiron.new.3399/python-apiron.changes 2020-08-31 16:51:08.632380417 +0200 @@ -1,0 +2,11 @@ +Mon Aug 31 04:37:49 UTC 2020 - Steve Kowalik <[email protected]> + +- Update to 5.1.0: + * Ability to specify proxies for a Service definition so all calls to the + service use the defined proxies + * Ability to specify auth for a Service definition so all calls to the + service use the defined authentication + * Ability to specify return_raw_response_object at the endpoint level, + overridden by any value specified at call time + +------------------------------------------------------------------- Old: ---- apiron-5.0.0.tar.gz New: ---- apiron-5.1.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-apiron.spec ++++++ --- /var/tmp/diff_new_pack.fwEVfY/_old 2020-08-31 16:51:09.432380805 +0200 +++ /var/tmp/diff_new_pack.fwEVfY/_new 2020-08-31 16:51:09.436380807 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-apiron # -# Copyright (c) 2019 SUSE LLC +# Copyright (c) 2020 SUSE LLC # Copyright (c) 2019 Dr. Axel Braun <[email protected]> # # All modifications and additions to the file contributed by third parties @@ -21,11 +21,10 @@ %define skip_python2 1 %define modname apiron Name: python-%{modname} -Version: 5.0.0 +Version: 5.1.0 Release: 0 Summary: Apiron helps you cook a tasty client for RESTful APIs License: MIT -Group: Development/Languages/Python URL: https://github.com/ithaka/apiron Source: https://files.pythonhosted.org/packages/source/a/apiron/%{modname}-%{version}.tar.gz BuildRequires: %{python_module pytest-cov} ++++++ apiron-5.0.0.tar.gz -> apiron-5.1.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apiron-5.0.0/LICENSE new/apiron-5.1.0/LICENSE --- old/apiron-5.0.0/LICENSE 2019-12-02 19:02:20.000000000 +0100 +++ new/apiron-5.1.0/LICENSE 2020-07-14 18:03:27.000000000 +0200 @@ -1,4 +1,4 @@ -Copyright 2018 Ithaka Harbors, Inc. +Copyright 2018-2020 Ithaka Harbors, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apiron-5.0.0/PKG-INFO new/apiron-5.1.0/PKG-INFO --- old/apiron-5.0.0/PKG-INFO 2019-12-02 19:02:58.015397500 +0100 +++ new/apiron-5.1.0/PKG-INFO 2020-07-14 18:04:08.247610600 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: apiron -Version: 5.0.0 +Version: 5.1.0 Summary: apiron helps you cook a tasty client for RESTful APIs. Just don't wash it with SOAP. Home-page: https://github.com/ithaka/apiron Author: Ithaka Harbors, Inc. @@ -74,7 +74,7 @@ This package is available under the MIT license. For more information, [view the full license and copyright notice](./LICENSE). - Copyright 2018 Ithaka Harbors, Inc. + Copyright 2018-2020 Ithaka Harbors, Inc. Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apiron-5.0.0/README.md new/apiron-5.1.0/README.md --- old/apiron-5.0.0/README.md 2019-12-02 19:02:20.000000000 +0100 +++ new/apiron-5.1.0/README.md 2020-07-14 18:03:27.000000000 +0200 @@ -63,4 +63,4 @@ This package is available under the MIT license. For more information, [view the full license and copyright notice](./LICENSE). -Copyright 2018 Ithaka Harbors, Inc. +Copyright 2018-2020 Ithaka Harbors, Inc. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apiron-5.0.0/pyproject.toml new/apiron-5.1.0/pyproject.toml --- old/apiron-5.0.0/pyproject.toml 1970-01-01 01:00:00.000000000 +0100 +++ new/apiron-5.1.0/pyproject.toml 2020-07-14 18:03:27.000000000 +0200 @@ -0,0 +1,3 @@ +[tool.black] +line-length = 120 +target-version = ['py36', 'py37', 'py38'] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apiron-5.0.0/setup.cfg new/apiron-5.1.0/setup.cfg --- old/apiron-5.0.0/setup.cfg 2019-12-02 19:02:58.015397500 +0100 +++ new/apiron-5.1.0/setup.cfg 2020-07-14 18:04:08.247610600 +0200 @@ -1,6 +1,6 @@ [metadata] name = apiron -version = 5.0.0 +version = 5.1.0 description = apiron helps you cook a tasty client for RESTful APIs. Just don't wash it with SOAP. author = Ithaka Harbors, Inc. author_email = [email protected] @@ -44,6 +44,7 @@ test = pytest==5.2.2 pytest-cov==2.8.1 + pytest-randomly==3.4.0 docs = importlib-metadata==0.23 sphinx==2.2.1 @@ -63,7 +64,7 @@ [tool:pytest] testpaths = tests -addopts = -ra -q --strict --cov +addopts = -ra --strict --cov xfail_strict = True [tox:tox] @@ -82,8 +83,8 @@ [testenv:lint] extras = lint commands = - pyflakes src/apiron tests - black --check src/apiron tests + pyflakes {posargs:src tests} + black {posargs:--check src tests} [egg_info] tag_build = diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apiron-5.0.0/setup.py new/apiron-5.1.0/setup.py --- old/apiron-5.0.0/setup.py 2019-12-02 19:02:20.000000000 +0100 +++ new/apiron-5.1.0/setup.py 2020-07-14 18:03:27.000000000 +0200 @@ -1,2 +1,3 @@ from setuptools import setup + setup() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apiron-5.0.0/src/apiron/client.py new/apiron-5.1.0/src/apiron/client.py --- old/apiron-5.0.0/src/apiron/client.py 2019-12-02 19:02:20.000000000 +0100 +++ new/apiron-5.1.0/src/apiron/client.py 2020-07-14 18:03:27.000000000 +0200 @@ -145,7 +145,7 @@ timeout_spec=DEFAULT_TIMEOUT, logger=None, allow_redirects=True, - return_raw_response_object=False, + return_raw_response_object=None, **kwargs, ): """ @@ -224,6 +224,8 @@ method = method or endpoint.default_method + auth = auth or session.auth or service.auth + request = build_request_object( session, service, @@ -246,6 +248,7 @@ timeout=(timeout_spec.connection_timeout, timeout_spec.read_timeout), stream=getattr(endpoint, "streaming", False), allow_redirects=allow_redirects, + proxies=session.proxies or service.proxies, ) logger.info( @@ -264,4 +267,11 @@ if encoding: response.encoding = encoding - return response if return_raw_response_object else endpoint.format_response(response) + # Use the explicitly passed in option, if any + # Otherwise, use the endpoint's setting + if return_raw_response_object is None: + return_raw_response = endpoint.return_raw_response_object + else: + return_raw_response = return_raw_response_object + + return response if return_raw_response else endpoint.format_response(response) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apiron-5.0.0/src/apiron/endpoint/endpoint.py new/apiron-5.1.0/src/apiron/endpoint/endpoint.py --- old/apiron-5.0.0/src/apiron/endpoint/endpoint.py 2019-12-02 19:02:20.000000000 +0100 +++ new/apiron-5.1.0/src/apiron/endpoint/endpoint.py 2020-07-14 18:03:27.000000000 +0200 @@ -23,7 +23,14 @@ def __call__(self): raise TypeError("Endpoints are only callable in conjunction with a Service class.") - def __init__(self, path="/", default_method="GET", default_params=None, required_params=None): + def __init__( + self, + path="/", + default_method="GET", + default_params=None, + required_params=None, + return_raw_response_object=False, + ): """ :param str path: The URL path for this endpoint, without the protocol or domain @@ -36,6 +43,10 @@ :param required_params: An iterable of required parameter names. Calling an endpoint without its required parameters raises an exception. + :param bool return_raw_response_object: + Whether to return a :class:`requests.Response` object or call :func:`format_response` on it first. + This can be overridden when calling the endpoint. + (Default ``False``) """ self.default_method = default_method @@ -50,6 +61,7 @@ self.path = path self.default_params = default_params or {} self.required_params = required_params or set() + self.return_raw_response_object = return_raw_response_object def format_response(self, response): """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apiron-5.0.0/src/apiron/service/base.py new/apiron-5.1.0/src/apiron/service/base.py --- old/apiron-5.0.0/src/apiron/service/base.py 2019-12-02 19:02:20.000000000 +0100 +++ new/apiron-5.1.0/src/apiron/service/base.py 2020-07-14 18:03:27.000000000 +0200 @@ -19,6 +19,8 @@ class ServiceBase(metaclass=ServiceMeta): required_headers = {} + auth = () + proxies = {} @classmethod def get_hosts(cls): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apiron-5.0.0/src/apiron.egg-info/PKG-INFO new/apiron-5.1.0/src/apiron.egg-info/PKG-INFO --- old/apiron-5.0.0/src/apiron.egg-info/PKG-INFO 2019-12-02 19:02:57.000000000 +0100 +++ new/apiron-5.1.0/src/apiron.egg-info/PKG-INFO 2020-07-14 18:04:08.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: apiron -Version: 5.0.0 +Version: 5.1.0 Summary: apiron helps you cook a tasty client for RESTful APIs. Just don't wash it with SOAP. Home-page: https://github.com/ithaka/apiron Author: Ithaka Harbors, Inc. @@ -74,7 +74,7 @@ This package is available under the MIT license. For more information, [view the full license and copyright notice](./LICENSE). - Copyright 2018 Ithaka Harbors, Inc. + Copyright 2018-2020 Ithaka Harbors, Inc. Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apiron-5.0.0/src/apiron.egg-info/SOURCES.txt new/apiron-5.1.0/src/apiron.egg-info/SOURCES.txt --- old/apiron-5.0.0/src/apiron.egg-info/SOURCES.txt 2019-12-02 19:02:57.000000000 +0100 +++ new/apiron-5.1.0/src/apiron.egg-info/SOURCES.txt 2020-07-14 18:04:08.000000000 +0200 @@ -1,6 +1,7 @@ LICENSE MANIFEST.in README.md +pyproject.toml setup.cfg setup.py src/apiron/__init__.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apiron-5.0.0/src/apiron.egg-info/requires.txt new/apiron-5.1.0/src/apiron.egg-info/requires.txt --- old/apiron-5.0.0/src/apiron.egg-info/requires.txt 2019-12-02 19:02:57.000000000 +0100 +++ new/apiron-5.1.0/src/apiron.egg-info/requires.txt 2020-07-14 18:04:08.000000000 +0200 @@ -12,3 +12,4 @@ [test] pytest==5.2.2 pytest-cov==2.8.1 +pytest-randomly==3.4.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apiron-5.0.0/tests/service/test_base.py new/apiron-5.1.0/tests/service/test_base.py --- old/apiron-5.0.0/tests/service/test_base.py 2019-12-02 19:02:20.000000000 +0100 +++ new/apiron-5.1.0/tests/service/test_base.py 2020-07-14 18:03:27.000000000 +0200 @@ -3,7 +3,7 @@ from apiron import Endpoint, Service, ServiceBase [email protected](scope="class") [email protected] def service(): class SomeService(Service): domain = "http://foo.com" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apiron-5.0.0/tests/test_client.py new/apiron-5.1.0/tests/test_client.py --- old/apiron-5.0.0/tests/test_client.py 2019-12-02 19:02:20.000000000 +0100 +++ new/apiron-5.1.0/tests/test_client.py 2020-07-14 18:03:27.000000000 +0200 @@ -22,215 +22,287 @@ return endpoint -class TestClient: - @mock.patch("requests.sessions.Session", autospec=True) - def test_get_adapted_session(self, mock_session): - adapter = mock.Mock() - adapted_session = client.get_adapted_session(adapter) - assert adapter == adapted_session.get_adapter("http://foo.com") - assert adapter == adapted_session.get_adapter("https://foo.com") - - def test_get_required_headers(self, mock_endpoint): - service = mock.Mock() - service.required_headers = {"one": "two"} - mock_endpoint.required_headers = {"foo": "bar"} - expected_headers = {} - expected_headers.update(service.required_headers) - expected_headers.update(mock_endpoint.required_headers) - assert expected_headers == client.get_required_headers(service, mock_endpoint) - - @mock.patch("apiron.client.requests.Request") - @mock.patch("apiron.client.get_required_headers") - def test_build_request_object_passes_arguments_to_request_constructor( - self, mock_get_required_headers, mock_request_constructor, mock_endpoint - ): - session = mock.Mock() - - service = mock.Mock() - service.get_hosts.return_value = ["http://host1.biz"] - - mock_endpoint.default_method = "POST" - mock_endpoint.required_headers = {"header": "value"} - mock_endpoint.required_params = set() - - params = {"baz": "qux"} - mock_endpoint.get_merged_params.return_value = params - data = "I am a data" - files = {"file_name": io.BytesIO(b"this is a test")} - json = {"raw": "data"} - headers = {"Accept": "stuff"} - cookies = {"chocolate-chip": "yes"} - auth = mock.Mock() - - mock_get_required_headers.return_value = {"header": "value"} - expected_headers = {} - expected_headers.update(headers) - expected_headers.update(mock_endpoint.required_headers) - - with mock.patch.object(session, "prepare_request") as mock_prepare_request: - client.build_request_object( - session, - service, - mock_endpoint, - params=params, - data=data, - files=files, - json=json, - headers=headers, - cookies=cookies, - auth=auth, - foo="bar", - ) - - mock_request_constructor.assert_called_once_with( - url="http://host1.biz/foo/", - method=mock_endpoint.default_method, - headers=expected_headers, - cookies=cookies, - params=params, - data=data, - files=files, - json=json, - auth=auth, - ) - - assert 1 == mock_prepare_request.call_count - - @mock.patch("apiron.client.Timeout") - @mock.patch("apiron.client.get_adapted_session") - @mock.patch("apiron.client.build_request_object") - @mock.patch("requests.adapters.HTTPAdapter", autospec=True) - @mock.patch("requests.Session", autospec=True) - def test_call( - self, - MockSession, - MockAdapter, - mock_build_request_object, - mock_get_adapted_session, - mock_timeout, - mock_response, - mock_endpoint, - ): - service = mock.Mock() - service.get_hosts.return_value = ["http://host1.biz"] - - mock_endpoint.default_method = "GET" - mock_endpoint.streaming = True - - request = mock.Mock() - request.url = "http://host1.biz/foo/" - mock_build_request_object.return_value = request - - mock_logger = mock.Mock() - - mock_response.status_code = 200 - mock_response.url = "http://host1.biz/foo/" - - mock_session = MockSession() - mock_session.send.return_value = mock_response - mock_get_adapted_session.return_value = mock_session - - client.call(service, mock_endpoint, timeout_spec=mock_timeout, logger=mock_logger) - - mock_get_adapted_session.assert_called_once_with(MockAdapter()) - mock_session.send.assert_called_once_with( - request, - timeout=(mock_timeout.connection_timeout, mock_timeout.read_timeout), - stream=mock_endpoint.streaming, - allow_redirects=True, [email protected] +def mock_logger(): + return mock.Mock() + + [email protected]("requests.sessions.Session", autospec=True) +def test_get_adapted_session(mock_session): + adapter = mock.Mock() + adapted_session = client.get_adapted_session(adapter) + assert adapter == adapted_session.get_adapter("http://foo.com") + assert adapter == adapted_session.get_adapter("https://foo.com") + + +def test_get_required_headers(mock_endpoint): + service = mock.Mock() + service.required_headers = {"one": "two"} + mock_endpoint.required_headers = {"foo": "bar"} + expected_headers = {} + expected_headers.update(service.required_headers) + expected_headers.update(mock_endpoint.required_headers) + assert expected_headers == client.get_required_headers(service, mock_endpoint) + + [email protected]("apiron.client.requests.Request") [email protected]("apiron.client.get_required_headers") +def test_build_request_object_passes_arguments_to_request_constructor( + mock_get_required_headers, mock_request_constructor, mock_endpoint +): + session = mock.Mock() + + service = mock.Mock() + service.get_hosts.return_value = ["http://host1.biz"] + + mock_endpoint.default_method = "POST" + mock_endpoint.required_headers = {"header": "value"} + mock_endpoint.required_params = set() + + params = {"baz": "qux"} + mock_endpoint.get_merged_params.return_value = params + data = "I am a data" + files = {"file_name": io.BytesIO(b"this is a test")} + json = {"raw": "data"} + headers = {"Accept": "stuff"} + cookies = {"chocolate-chip": "yes"} + auth = mock.Mock() + + mock_get_required_headers.return_value = {"header": "value"} + expected_headers = {} + expected_headers.update(headers) + expected_headers.update(mock_endpoint.required_headers) + + with mock.patch.object(session, "prepare_request") as mock_prepare_request: + client.build_request_object( + session, + service, + mock_endpoint, + params=params, + data=data, + files=files, + json=json, + headers=headers, + cookies=cookies, + auth=auth, + foo="bar", ) - mock_logger.info.assert_any_call("GET http://host1.biz/foo/") - mock_logger.info.assert_any_call("200 http://host1.biz/foo/") + mock_request_constructor.assert_called_once_with( + url="http://host1.biz/foo/", + method=mock_endpoint.default_method, + headers=expected_headers, + cookies=cookies, + params=params, + data=data, + files=files, + json=json, + auth=auth, + ) - mock_endpoint.default_method = "POST" - request.method = "POST" + assert 1 == mock_prepare_request.call_count - client.call(service, mock_endpoint, session=mock_session, timeout_spec=mock_timeout, logger=mock_logger) - mock_session.send.assert_any_call( - request, - timeout=(mock_timeout.connection_timeout, mock_timeout.read_timeout), - stream=mock_endpoint.streaming, - allow_redirects=True, - ) [email protected]("apiron.client.Timeout") [email protected]("apiron.client.get_adapted_session") [email protected]("apiron.client.build_request_object") [email protected]("requests.adapters.HTTPAdapter", autospec=True) [email protected]("requests.Session", autospec=True) +def test_call( + MockSession, + MockAdapter, + mock_build_request_object, + mock_get_adapted_session, + mock_timeout, + mock_response, + mock_endpoint, + mock_logger, +): + service = mock.Mock() + service.get_hosts.return_value = ["http://host1.biz"] - mock_logger.info.assert_any_call("GET http://host1.biz/foo/") - mock_logger.info.assert_any_call("200 http://host1.biz/foo/") + mock_endpoint.default_method = "GET" + mock_endpoint.streaming = True - request.method = "PUT" + request = mock.Mock() + request.url = "http://host1.biz/foo/" + mock_build_request_object.return_value = request - client.call( - service, mock_endpoint, method="PUT", session=mock_session, timeout_spec=mock_timeout, logger=mock_logger - ) + mock_response.status_code = 200 + mock_response.url = "http://host1.biz/foo/" - mock_session.send.assert_any_call( - request, - timeout=(mock_timeout.connection_timeout, mock_timeout.read_timeout), - stream=mock_endpoint.streaming, - allow_redirects=True, - ) + mock_session = MockSession() + mock_session.send.return_value = mock_response + mock_session.proxies = {} + mock_session.auth = () + mock_get_adapted_session.return_value = mock_session - @mock.patch("apiron.client.get_adapted_session") - def test_call_with_existing_session(self, mock_get_adapted_session, mock_response, mock_endpoint): - service = mock.Mock() - service.get_hosts.return_value = ["http://host1.biz"] - service.required_headers = {} + client.call(service, mock_endpoint, timeout_spec=mock_timeout, logger=mock_logger) - mock_logger = mock.Mock() + mock_get_adapted_session.assert_called_once_with(MockAdapter()) + mock_session.send.assert_called_once_with( + request, + timeout=(mock_timeout.connection_timeout, mock_timeout.read_timeout), + stream=mock_endpoint.streaming, + allow_redirects=True, + proxies=service.proxies, + ) - session = mock.Mock() - session.send.return_value = mock_response + mock_logger.info.assert_any_call("GET http://host1.biz/foo/") + mock_logger.info.assert_any_call("200 http://host1.biz/foo/") - client.call(service, mock_endpoint, session=session, logger=mock_logger) + mock_endpoint.default_method = "POST" + request.method = "POST" - assert not mock_get_adapted_session.called - assert not session.close.called + client.call(service, mock_endpoint, session=mock_session, timeout_spec=mock_timeout, logger=mock_logger) - def test_call_with_explicit_encoding(self, mock_response, mock_endpoint): - service = mock.Mock() - service.get_hosts.return_value = ["http://host1.biz"] - service.required_headers = {} + mock_session.send.assert_any_call( + request, + timeout=(mock_timeout.connection_timeout, mock_timeout.read_timeout), + stream=mock_endpoint.streaming, + allow_redirects=True, + proxies=service.proxies, + ) - session = mock.Mock() - session.send.return_value = mock_response + mock_logger.info.assert_any_call("GET http://host1.biz/foo/") + mock_logger.info.assert_any_call("200 http://host1.biz/foo/") - client.call(service, mock_endpoint, session=session, logger=mock.Mock(), encoding="FAKE-CODEC") + request.method = "PUT" - assert "FAKE-CODEC" == mock_response.encoding + client.call( + service, mock_endpoint, method="PUT", session=mock_session, timeout_spec=mock_timeout, logger=mock_logger + ) - def test_build_request_object_raises_no_host_exception(self): - service = mock.Mock() - service.get_hosts.return_value = [] + mock_session.send.assert_any_call( + request, + timeout=(mock_timeout.connection_timeout, mock_timeout.read_timeout), + stream=mock_endpoint.streaming, + allow_redirects=True, + proxies=service.proxies, + ) - with pytest.raises(NoHostsAvailableException): - client.build_request_object(None, service, None) - def test_choose_host_returns_one_of_the_available_hosts(self): - hosts = ["foo", "bar", "baz"] - service = mock.Mock() - service.get_hosts.return_value = hosts - assert client.choose_host(service) in hosts [email protected]("apiron.client.build_request_object") [email protected]("apiron.client.get_adapted_session") [email protected]("requests.Session", autospec=True) +def test_call_auth_priority( + MockSession, mock_get_adapted_session, mock_build_request_object, mock_endpoint, mock_logger +): + service = mock.Mock() + service.get_hosts.return_value = ["http://host1.biz"] + service.required_headers = {} + service.auth = ("service-user", "p455w0rd!") - def test_choose_host_raises_exception_when_no_hosts_available(self): - service = mock.Mock() - service.get_hosts.return_value = [] - with pytest.raises(NoHostsAvailableException): - client.choose_host(service) + mock_session = MockSession() + mock_session.proxies = {} + mock_session.auth = ("session-user", "p455w0rd!") - def test_call_when_raw_response_object_requested(self, mock_response, mock_endpoint): - service = mock.Mock() - service.get_hosts.return_value = ["http://host1.biz"] - service.required_headers = {} + mock_get_adapted_session.return_value = mock_session - session = mock.Mock() - session.send.return_value = mock_response + client.call(service, mock_endpoint, auth=("direct-user", "p455w0rd!"), session=mock_session, logger=mock_logger) + assert mock_build_request_object.call_args[1]["auth"] == ("direct-user", "p455w0rd!") - response = client.call( - service, mock_endpoint, session=session, logger=mock.Mock(), return_raw_response_object=True - ) + client.call(service, mock_endpoint, session=mock_session, logger=mock_logger) + assert mock_build_request_object.call_args[1]["auth"] == ("session-user", "p455w0rd!") + + mock_session.auth = () + client.call(service, mock_endpoint, logger=mock_logger) + assert mock_build_request_object.call_args[1]["auth"] == ("service-user", "p455w0rd!") + + [email protected]("apiron.client.get_adapted_session") +def test_call_with_existing_session(mock_get_adapted_session, mock_response, mock_endpoint, mock_logger): + service = mock.Mock() + service.get_hosts.return_value = ["http://host1.biz"] + service.required_headers = {} + + session = mock.Mock() + session.send.return_value = mock_response + + client.call(service, mock_endpoint, session=session, logger=mock_logger) + + assert not mock_get_adapted_session.called + assert not session.close.called + + +def test_call_with_explicit_encoding(mock_response, mock_endpoint, mock_logger): + service = mock.Mock() + service.get_hosts.return_value = ["http://host1.biz"] + service.required_headers = {} + + session = mock.Mock() + session.send.return_value = mock_response + + client.call(service, mock_endpoint, session=session, logger=mock_logger, encoding="FAKE-CODEC") + + assert "FAKE-CODEC" == mock_response.encoding + + +def test_build_request_object_raises_no_host_exception(): + service = mock.Mock() + service.get_hosts.return_value = [] + + with pytest.raises(NoHostsAvailableException): + client.build_request_object(None, service, None) + + +def test_choose_host_returns_one_of_the_available_hosts(): + hosts = ["foo", "bar", "baz"] + service = mock.Mock() + service.get_hosts.return_value = hosts + assert client.choose_host(service) in hosts + + +def test_choose_host_raises_exception_when_no_hosts_available(): + service = mock.Mock() + service.get_hosts.return_value = [] + with pytest.raises(NoHostsAvailableException): + client.choose_host(service) + + +def test_call_when_raw_response_object_requested(mock_response, mock_endpoint, mock_logger): + service = mock.Mock() + service.get_hosts.return_value = ["http://host1.biz"] + service.required_headers = {} + + session = mock.Mock() + session.send.return_value = mock_response + + response = client.call(service, mock_endpoint, session=session, logger=mock_logger, return_raw_response_object=True) + + assert response is mock_response + + +def test_call_when_raw_response_object_requested_on_endpoint(mock_response, mock_endpoint): + service = mock.Mock() + service.get_hosts.return_value = ["http://host1.biz"] + service.required_headers = {} + + session = mock.Mock() + session.send.return_value = mock_response + + mock_endpoint.return_raw_response_object = True + + response = client.call(service, mock_endpoint, session=session, logger=mock.Mock()) + + assert response is mock_response + + +def test_return_raw_response_object_in_call_overrides_endpoint(mock_response, mock_endpoint): + service = mock.Mock() + service.get_hosts.return_value = ["http://host1.biz"] + service.required_headers = {} + + session = mock.Mock() + session.send.return_value = mock_response + + mock_endpoint.return_raw_response_object = False + + response = client.call( + service, mock_endpoint, session=session, logger=mock.Mock(), return_raw_response_object=True, + ) - assert response is mock_response + assert response is mock_response @pytest.mark.parametrize(
