From a48aadaaed5127aa08a762bb55b69b30905a6c51 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Tue, 28 Apr 2015 23:29:55 +0200 Subject: [PATCH 1/9] utils: Add basic format proxy helper --- mopidy/utils/http.py | 25 +++++++++++++++++++++++++ tests/utils/test_http.py | 20 ++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 mopidy/utils/http.py create mode 100644 tests/utils/test_http.py diff --git a/mopidy/utils/http.py b/mopidy/utils/http.py new file mode 100644 index 00000000..bc6d38f4 --- /dev/null +++ b/mopidy/utils/http.py @@ -0,0 +1,25 @@ +from __future__ import unicode_literals + + +def format_proxy(proxy_config): + """Convert a Mopidy proxy config to the commonly used proxy string format. + + Outputs ``scheme://host:port``, ``scheme://user:pass@host:port`` or + :class:`None` depending on the proxy config provided. + """ + if not proxy_config.get('hostname'): + return None + + if proxy_config.get('username') and proxy_config.get('password'): + template = '{scheme}://{username}:{password}@{hostname}:{port}' + else: + template = '{scheme}://{hostname}:{port}' + + port = proxy_config.get('port', 80) + if port < 0: + port = 80 + + return template.format(scheme=proxy_config.get('scheme', 'http'), + username=proxy_config.get('username'), + password=proxy_config.get('password'), + hostname=proxy_config['hostname'], port=port) diff --git a/tests/utils/test_http.py b/tests/utils/test_http.py new file mode 100644 index 00000000..b63ebf31 --- /dev/null +++ b/tests/utils/test_http.py @@ -0,0 +1,20 @@ +from __future__ import unicode_literals + +import pytest + +from mopidy.utils import http + + +@pytest.mark.parametrize("config,expected", [ + ({}, None), + ({'hostname': 'proxy.lan'}, 'http://proxy.lan:80'), + ({'scheme': 'https', 'hostname': 'proxy.lan'}, 'https://proxy.lan:80'), + ({'username': 'user', 'hostname': 'proxy.lan'}, 'http://proxy.lan:80'), + ({'password': 'pass', 'hostname': 'proxy.lan'}, 'http://proxy.lan:80'), + ({'hostname': 'proxy.lan', 'port': 8080}, 'http://proxy.lan:8080'), + ({'hostname': 'proxy.lan', 'port': -1}, 'http://proxy.lan:80'), + ({'username': 'user', 'password': 'pass', 'hostname': 'proxy.lan'}, + 'http://user:pass@proxy.lan:80'), +]) +def test_format_proxy(config, expected): + assert http.format_proxy(config) == expected From 5153d9e19fd890c174be51cc0ac6ae807f54f2b2 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Tue, 28 Apr 2015 23:51:19 +0200 Subject: [PATCH 2/9] utils: Add format_user_agent helper --- mopidy/utils/http.py | 20 ++++++++++++++++++++ tests/utils/test_http.py | 11 +++++++++++ 2 files changed, 31 insertions(+) diff --git a/mopidy/utils/http.py b/mopidy/utils/http.py index bc6d38f4..f0c658e7 100644 --- a/mopidy/utils/http.py +++ b/mopidy/utils/http.py @@ -1,5 +1,11 @@ from __future__ import unicode_literals +import platform + +import mopidy + +"Helpers for configuring HTTP clients used in Mopidy extensions." + def format_proxy(proxy_config): """Convert a Mopidy proxy config to the commonly used proxy string format. @@ -23,3 +29,17 @@ def format_proxy(proxy_config): username=proxy_config.get('username'), password=proxy_config.get('password'), hostname=proxy_config['hostname'], port=port) + + +def format_user_agent(name=None): + """Construct a User-Agent suitable for use in client code. + + This will identify use by the provided name (which should be + ``dist_name/version``), Mopidy version and Python version. + """ + parts = ['Mopidy/%s' % (mopidy.__version__), + '%s/%s' % (platform.python_implementation(), + platform.python_version())] + if name: + parts.insert(0, name) + return ' '.join(parts) diff --git a/tests/utils/test_http.py b/tests/utils/test_http.py index b63ebf31..cf97e57c 100644 --- a/tests/utils/test_http.py +++ b/tests/utils/test_http.py @@ -1,5 +1,7 @@ from __future__ import unicode_literals +import re + import pytest from mopidy.utils import http @@ -18,3 +20,12 @@ from mopidy.utils import http ]) def test_format_proxy(config, expected): assert http.format_proxy(config) == expected + + +@pytest.mark.parametrize("name,expected", [ + (None, r'^Mopidy/[^ ]+ CPython|/[^ ]+$'), + ('Foo', r'^Foo Mopidy/[^ ]+ CPython|/[^ ]+$'), + ('Foo/1.2.3', r'^Foo/1.2.3 Mopidy/[^ ]+ CPython|/[^ ]+$'), +]) +def test_format_user_agent(name, expected): + assert re.match(expected, http.format_user_agent(name)) From 8434896f2ddf298ca61f8fd0186c57461370d9f4 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Tue, 28 Apr 2015 23:53:06 +0200 Subject: [PATCH 3/9] docs: Add http helpers to changelog --- docs/changelog.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index f1b11179..ef0c85b4 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -27,6 +27,7 @@ Core API ``tl_track`` versions of the calls. (Fixes: :issue:`1131` PR: :issue:`1136`, :issue:`1140`) + Models ------ @@ -38,6 +39,12 @@ Models reuse instances. For the test data set this was developed against, a library of ~14000 tracks, went from needing ~75MB to ~17MB. (Fixes: :issue:`348`) +Utils +----- + +- Add :func:`mopidy.utils.http.format_proxy` and + :func:`mopidy.utils.http.format_user_agent`. (Part of: :issue:`1156`) + Internal changes ---------------- From 8cf9da3d555b375ae72a782b094d6377cedd1a59 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Wed, 29 Apr 2015 00:27:56 +0200 Subject: [PATCH 4/9] utils: Fix corner case in format_proxy scheme handling --- mopidy/utils/http.py | 2 +- tests/utils/test_http.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mopidy/utils/http.py b/mopidy/utils/http.py index f0c658e7..096a37a0 100644 --- a/mopidy/utils/http.py +++ b/mopidy/utils/http.py @@ -25,7 +25,7 @@ def format_proxy(proxy_config): if port < 0: port = 80 - return template.format(scheme=proxy_config.get('scheme', 'http'), + return template.format(scheme=proxy_config.get('scheme') or 'http', username=proxy_config.get('username'), password=proxy_config.get('password'), hostname=proxy_config['hostname'], port=port) diff --git a/tests/utils/test_http.py b/tests/utils/test_http.py index cf97e57c..dee09c3c 100644 --- a/tests/utils/test_http.py +++ b/tests/utils/test_http.py @@ -10,6 +10,7 @@ from mopidy.utils import http @pytest.mark.parametrize("config,expected", [ ({}, None), ({'hostname': 'proxy.lan'}, 'http://proxy.lan:80'), + ({'scheme': None, 'hostname': 'proxy.lan'}, 'http://proxy.lan:80'), ({'scheme': 'https', 'hostname': 'proxy.lan'}, 'https://proxy.lan:80'), ({'username': 'user', 'hostname': 'proxy.lan'}, 'http://proxy.lan:80'), ({'password': 'pass', 'hostname': 'proxy.lan'}, 'http://proxy.lan:80'), From 9182a7870e51a28a3da22c7a9e82679d7d90c307 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Wed, 29 Apr 2015 00:38:06 +0200 Subject: [PATCH 5/9] utils: Support opting out of adding auth to proxy --- mopidy/utils/http.py | 15 +++++++++------ tests/utils/test_http.py | 6 ++++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/mopidy/utils/http.py b/mopidy/utils/http.py index 096a37a0..d0b3cb4c 100644 --- a/mopidy/utils/http.py +++ b/mopidy/utils/http.py @@ -7,24 +7,27 @@ import mopidy "Helpers for configuring HTTP clients used in Mopidy extensions." -def format_proxy(proxy_config): +def format_proxy(proxy_config, auth=True): """Convert a Mopidy proxy config to the commonly used proxy string format. Outputs ``scheme://host:port``, ``scheme://user:pass@host:port`` or :class:`None` depending on the proxy config provided. + + You can also opt out of getting the basic auth by setting ``auth`` to + :type:`False`. """ if not proxy_config.get('hostname'): return None - if proxy_config.get('username') and proxy_config.get('password'): - template = '{scheme}://{username}:{password}@{hostname}:{port}' - else: - template = '{scheme}://{hostname}:{port}' - port = proxy_config.get('port', 80) if port < 0: port = 80 + if proxy_config.get('username') and proxy_config.get('password') and auth: + template = '{scheme}://{username}:{password}@{hostname}:{port}' + else: + template = '{scheme}://{hostname}:{port}' + return template.format(scheme=proxy_config.get('scheme') or 'http', username=proxy_config.get('username'), password=proxy_config.get('password'), diff --git a/tests/utils/test_http.py b/tests/utils/test_http.py index dee09c3c..4553dc05 100644 --- a/tests/utils/test_http.py +++ b/tests/utils/test_http.py @@ -23,6 +23,12 @@ def test_format_proxy(config, expected): assert http.format_proxy(config) == expected +def test_format_proxy_without_auth(): + config = {'username': 'user', 'password': 'pass', 'hostname': 'proxy.lan'} + formated_proxy = http.format_proxy(config, auth=False) + assert formated_proxy == 'http://proxy.lan:80' + + @pytest.mark.parametrize("name,expected", [ (None, r'^Mopidy/[^ ]+ CPython|/[^ ]+$'), ('Foo', r'^Foo Mopidy/[^ ]+ CPython|/[^ ]+$'), From 924269616b3eb637eade8f8f5368be501cfe5fc7 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Wed, 29 Apr 2015 00:38:23 +0200 Subject: [PATCH 6/9] audio: Use proxy helper in audio utils --- mopidy/audio/utils.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/mopidy/audio/utils.py b/mopidy/audio/utils.py index 1a8bf6a7..6266b64f 100644 --- a/mopidy/audio/utils.py +++ b/mopidy/audio/utils.py @@ -10,6 +10,7 @@ import gst # noqa from mopidy import compat from mopidy.models import Album, Artist, Track +from mopidy.utils import http logger = logging.getLogger(__name__) @@ -142,11 +143,7 @@ def setup_proxy(element, config): if not hasattr(element.props, 'proxy') or not config.get('hostname'): return - proxy = "%s://%s:%d" % (config.get('scheme', 'http'), - config.get('hostname'), - config.get('port', 80)) - - element.set_property('proxy', proxy) + element.set_property('proxy', http.format_proxy(config, auth=False)) element.set_property('proxy-id', config.get('username')) element.set_property('proxy-pw', config.get('password')) From 382aa0a775ec9c766afd24366cd844e00c82820d Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Sat, 9 May 2015 00:44:16 +0200 Subject: [PATCH 7/9] httpclient: Move to top level module --- docs/changelog.rst | 4 ++-- mopidy/audio/utils.py | 5 ++--- mopidy/{utils/http.py => httpclient.py} | 0 tests/{utils/test_http.py => test_httpclient.py} | 8 ++++---- 4 files changed, 8 insertions(+), 9 deletions(-) rename mopidy/{utils/http.py => httpclient.py} (100%) rename tests/{utils/test_http.py => test_httpclient.py} (84%) diff --git a/docs/changelog.rst b/docs/changelog.rst index ef0c85b4..48ca9ff7 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -42,8 +42,8 @@ Models Utils ----- -- Add :func:`mopidy.utils.http.format_proxy` and - :func:`mopidy.utils.http.format_user_agent`. (Part of: :issue:`1156`) +- Add :func:`mopidy.httpclient.format_proxy` and + :func:`mopidy.httpclient.format_user_agent`. (Part of: :issue:`1156`) Internal changes ---------------- diff --git a/mopidy/audio/utils.py b/mopidy/audio/utils.py index 6266b64f..3b9ea30f 100644 --- a/mopidy/audio/utils.py +++ b/mopidy/audio/utils.py @@ -8,9 +8,8 @@ import pygst pygst.require('0.10') import gst # noqa -from mopidy import compat +from mopidy import compat, httpclient from mopidy.models import Album, Artist, Track -from mopidy.utils import http logger = logging.getLogger(__name__) @@ -143,7 +142,7 @@ def setup_proxy(element, config): if not hasattr(element.props, 'proxy') or not config.get('hostname'): return - element.set_property('proxy', http.format_proxy(config, auth=False)) + element.set_property('proxy', httpclient.format_proxy(config, auth=False)) element.set_property('proxy-id', config.get('username')) element.set_property('proxy-pw', config.get('password')) diff --git a/mopidy/utils/http.py b/mopidy/httpclient.py similarity index 100% rename from mopidy/utils/http.py rename to mopidy/httpclient.py diff --git a/tests/utils/test_http.py b/tests/test_httpclient.py similarity index 84% rename from tests/utils/test_http.py rename to tests/test_httpclient.py index 4553dc05..4497ceda 100644 --- a/tests/utils/test_http.py +++ b/tests/test_httpclient.py @@ -4,7 +4,7 @@ import re import pytest -from mopidy.utils import http +from mopidy.utils import httpclient @pytest.mark.parametrize("config,expected", [ @@ -20,12 +20,12 @@ from mopidy.utils import http 'http://user:pass@proxy.lan:80'), ]) def test_format_proxy(config, expected): - assert http.format_proxy(config) == expected + assert httpclient.format_proxy(config) == expected def test_format_proxy_without_auth(): config = {'username': 'user', 'password': 'pass', 'hostname': 'proxy.lan'} - formated_proxy = http.format_proxy(config, auth=False) + formated_proxy = httpclient.format_proxy(config, auth=False) assert formated_proxy == 'http://proxy.lan:80' @@ -35,4 +35,4 @@ def test_format_proxy_without_auth(): ('Foo/1.2.3', r'^Foo/1.2.3 Mopidy/[^ ]+ CPython|/[^ ]+$'), ]) def test_format_user_agent(name, expected): - assert re.match(expected, http.format_user_agent(name)) + assert re.match(expected, httpclient.format_user_agent(name)) From bb19e99af56a0fe98175165dc62a2cf6bab686c9 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Sat, 9 May 2015 00:48:11 +0200 Subject: [PATCH 8/9] docs: Add httpclient to API docs --- docs/api/httpclient.rst | 9 +++++++++ docs/api/index.rst | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 docs/api/httpclient.rst diff --git a/docs/api/httpclient.rst b/docs/api/httpclient.rst new file mode 100644 index 00000000..85e258c3 --- /dev/null +++ b/docs/api/httpclient.rst @@ -0,0 +1,9 @@ +.. _httpclient-helper: + +************************************************ +:mod:`mopidy.httpclient` --- HTTP Client helpers +************************************************ + +.. automodule:: mopidy.httpclient + :synopsis: HTTP Client helpers for Mopidy its Extensions. + :members: diff --git a/docs/api/index.rst b/docs/api/index.rst index 3a79af5d..d4bd2f61 100644 --- a/docs/api/index.rst +++ b/docs/api/index.rst @@ -54,6 +54,7 @@ Utilities .. toctree:: - config commands + config + httpclient zeroconf From 95dc30288ccea40290dedb3edd7937da72be2117 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Sat, 9 May 2015 00:52:29 +0200 Subject: [PATCH 9/9] httpclient: Fix import in tests --- tests/test_httpclient.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_httpclient.py b/tests/test_httpclient.py index 4497ceda..63591f80 100644 --- a/tests/test_httpclient.py +++ b/tests/test_httpclient.py @@ -4,7 +4,7 @@ import re import pytest -from mopidy.utils import httpclient +from mopidy import httpclient @pytest.mark.parametrize("config,expected", [