From de80c33753bcd96804500748ae80865104ade8c4 Mon Sep 17 00:00:00 2001 From: Alexandre Petitjean Date: Mon, 29 Jul 2013 09:57:32 +0200 Subject: [PATCH 1/8] Add proxy/port to configuration --- mopidy/backends/spotify/session_manager.py | 7 ++++++- mopidy/config/__init__.py | 1 + mopidy/config/convert.py | 1 + mopidy/config/default.conf | 1 + mopidy/config/types.py | 8 ++++++-- 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/mopidy/backends/spotify/session_manager.py b/mopidy/backends/spotify/session_manager.py index 8f520896..3e8f1b67 100644 --- a/mopidy/backends/spotify/session_manager.py +++ b/mopidy/backends/spotify/session_manager.py @@ -33,9 +33,14 @@ class SpotifySessionManager(process.BaseThread, PyspotifySessionManager): self.cache_location = config['spotify']['cache_dir'] self.settings_location = config['spotify']['cache_dir'] + # Add proxy port only if available + full_proxy = config['proxy']['hostname'] + if 'port' in config['proxy']: + full_proxy = full_proxy + ':' + str(config['proxy']['port']) + PyspotifySessionManager.__init__( self, config['spotify']['username'], config['spotify']['password'], - proxy=config['proxy']['hostname'], + proxy=full_proxy, proxy_username=config['proxy']['username'], proxy_password=config['proxy']['password']) diff --git a/mopidy/config/__init__.py b/mopidy/config/__init__.py index e9ae7d86..7ccaa3f3 100644 --- a/mopidy/config/__init__.py +++ b/mopidy/config/__init__.py @@ -29,6 +29,7 @@ _proxy_schema = ConfigSchema('proxy') _proxy_schema['hostname'] = Hostname(optional=True) _proxy_schema['username'] = String(optional=True) _proxy_schema['password'] = Secret(optional=True) +_proxy_schema['port'] = Port(optional=True) # NOTE: if multiple outputs ever comes something like LogLevelConfigSchema #_outputs_schema = config.AudioOutputConfigSchema() diff --git a/mopidy/config/convert.py b/mopidy/config/convert.py index 6cb20fcd..3c3edb85 100644 --- a/mopidy/config/convert.py +++ b/mopidy/config/convert.py @@ -39,6 +39,7 @@ def convert(settings): helper('audio/output', 'OUTPUT') helper('proxy/hostname', 'SPOTIFY_PROXY_HOST') + helper('proxy/port', 'SPOTIFY_PROXY_PORT') helper('proxy/username', 'SPOTIFY_PROXY_USERNAME') helper('proxy/password', 'SPOTIFY_PROXY_PASSWORD') diff --git a/mopidy/config/default.conf b/mopidy/config/default.conf index b525ef47..204c789b 100644 --- a/mopidy/config/default.conf +++ b/mopidy/config/default.conf @@ -16,3 +16,4 @@ output = autoaudiosink hostname = username = password = +port = \ No newline at end of file diff --git a/mopidy/config/types.py b/mopidy/config/types.py index ec0be1de..3dff0908 100644 --- a/mopidy/config/types.py +++ b/mopidy/config/types.py @@ -117,7 +117,10 @@ class Integer(ConfigValue): self._choices = choices def deserialize(self, value): - value = int(value) + try: + value = int(value) + except: + value = 0 validators.validate_choice(value, self._choices) validators.validate_minimum(value, self._minimum) validators.validate_maximum(value, self._maximum) @@ -222,7 +225,8 @@ class Port(Integer): allocate a port for us. """ # TODO: consider probing if port is free or not? - def __init__(self, choices=None): + def __init__(self, choices=None, optional=False): + self._required = not optional super(Port, self).__init__( minimum=0, maximum=2 ** 16 - 1, choices=choices) From 05733cf844cb8f90eaf4174c05908eb6e6227daa Mon Sep 17 00:00:00 2001 From: Alexandre Petitjean Date: Mon, 29 Jul 2013 22:22:28 +0200 Subject: [PATCH 2/8] correct remarks from #481 --- mopidy/backends/spotify/session_manager.py | 10 ++++---- mopidy/config/__init__.py | 2 +- mopidy/config/default.conf | 2 +- mopidy/config/types.py | 27 +++++++++++++++++----- 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/mopidy/backends/spotify/session_manager.py b/mopidy/backends/spotify/session_manager.py index 3e8f1b67..dff29fad 100644 --- a/mopidy/backends/spotify/session_manager.py +++ b/mopidy/backends/spotify/session_manager.py @@ -33,10 +33,12 @@ class SpotifySessionManager(process.BaseThread, PyspotifySessionManager): self.cache_location = config['spotify']['cache_dir'] self.settings_location = config['spotify']['cache_dir'] - # Add proxy port only if available - full_proxy = config['proxy']['hostname'] - if 'port' in config['proxy']: - full_proxy = full_proxy + ':' + str(config['proxy']['port']) + full_proxy = '' + if config['proxy']['hostname']: + full_proxy = config['proxy']['hostname'] + # Add proxy port only if available + if config['proxy']['port']: + full_proxy = full_proxy + ':' + str(config['proxy']['port']) PyspotifySessionManager.__init__( self, config['spotify']['username'], config['spotify']['password'], diff --git a/mopidy/config/__init__.py b/mopidy/config/__init__.py index 7ccaa3f3..35a1d8e0 100644 --- a/mopidy/config/__init__.py +++ b/mopidy/config/__init__.py @@ -29,7 +29,7 @@ _proxy_schema = ConfigSchema('proxy') _proxy_schema['hostname'] = Hostname(optional=True) _proxy_schema['username'] = String(optional=True) _proxy_schema['password'] = Secret(optional=True) -_proxy_schema['port'] = Port(optional=True) +_proxy_schema['port'] = Port() # NOTE: if multiple outputs ever comes something like LogLevelConfigSchema #_outputs_schema = config.AudioOutputConfigSchema() diff --git a/mopidy/config/default.conf b/mopidy/config/default.conf index 204c789b..4a259c49 100644 --- a/mopidy/config/default.conf +++ b/mopidy/config/default.conf @@ -16,4 +16,4 @@ output = autoaudiosink hostname = username = password = -port = \ No newline at end of file +port = diff --git a/mopidy/config/types.py b/mopidy/config/types.py index 3dff0908..8309a591 100644 --- a/mopidy/config/types.py +++ b/mopidy/config/types.py @@ -117,10 +117,7 @@ class Integer(ConfigValue): self._choices = choices def deserialize(self, value): - try: - value = int(value) - except: - value = 0 + value = int(value) validators.validate_choice(value, self._choices) validators.validate_minimum(value, self._minimum) validators.validate_maximum(value, self._maximum) @@ -225,11 +222,29 @@ class Port(Integer): allocate a port for us. """ # TODO: consider probing if port is free or not? - def __init__(self, choices=None, optional=False): - self._required = not optional + def __init__(self, choices=None): super(Port, self).__init__( minimum=0, maximum=2 ** 16 - 1, choices=choices) + def deserialize(self, value): + # in case of no value is given, just return nothing + if not len(value): + return value + # now we can try to convert + try: + value = int(value) + except ValueError: + try: + value = socket.getservbyname(value, 'tcp') + except socket.error: + raise ValueError('must be a valid port number') + else: + validators.validate_choice(value, self._choices) + validators.validate_minimum(value, self._minimum) + validators.validate_maximum(value, self._maximum) + return value + + class Path(ConfigValue): """File system path From f9da3fe3e922a8a8df1f893769b8f645952d74c2 Mon Sep 17 00:00:00 2001 From: Alexandre Petitjean Date: Tue, 30 Jul 2013 08:17:10 +0200 Subject: [PATCH 3/8] implement remarks for #481, also add scheme as requested in #472 --- mopidy/backends/spotify/session_manager.py | 6 ++++-- mopidy/config/__init__.py | 4 +++- mopidy/config/default.conf | 3 ++- mopidy/config/types.py | 1 - 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/mopidy/backends/spotify/session_manager.py b/mopidy/backends/spotify/session_manager.py index dff29fad..130164fb 100644 --- a/mopidy/backends/spotify/session_manager.py +++ b/mopidy/backends/spotify/session_manager.py @@ -36,9 +36,11 @@ class SpotifySessionManager(process.BaseThread, PyspotifySessionManager): full_proxy = '' if config['proxy']['hostname']: full_proxy = config['proxy']['hostname'] - # Add proxy port only if available + # Add proxy port and scheme only if available if config['proxy']['port']: - full_proxy = full_proxy + ':' + str(config['proxy']['port']) + full_proxy += ':' + str(config['proxy']['port']) + if config['proxy']['scheme']: + full_proxy = config['proxy']['scheme'] + "://" + full_proxy PyspotifySessionManager.__init__( self, config['spotify']['username'], config['spotify']['password'], diff --git a/mopidy/config/__init__.py b/mopidy/config/__init__.py index 35a1d8e0..582a1a03 100644 --- a/mopidy/config/__init__.py +++ b/mopidy/config/__init__.py @@ -26,10 +26,12 @@ _audio_schema['mixer_track'] = String(optional=True) _audio_schema['output'] = String() _proxy_schema = ConfigSchema('proxy') +_proxy_schema['scheme'] = String(optional=True, + choices=['', 'https', 'socks4', 'socks5']) _proxy_schema['hostname'] = Hostname(optional=True) +_proxy_schema['port'] = Port() _proxy_schema['username'] = String(optional=True) _proxy_schema['password'] = Secret(optional=True) -_proxy_schema['port'] = Port() # NOTE: if multiple outputs ever comes something like LogLevelConfigSchema #_outputs_schema = config.AudioOutputConfigSchema() diff --git a/mopidy/config/default.conf b/mopidy/config/default.conf index 4a259c49..8d2101fb 100644 --- a/mopidy/config/default.conf +++ b/mopidy/config/default.conf @@ -13,7 +13,8 @@ mixer_track = output = autoaudiosink [proxy] +scheme = hostname = +port = username = password = -port = diff --git a/mopidy/config/types.py b/mopidy/config/types.py index 8309a591..ba8b8f2a 100644 --- a/mopidy/config/types.py +++ b/mopidy/config/types.py @@ -245,7 +245,6 @@ class Port(Integer): return value - class Path(ConfigValue): """File system path From bb3242d15aef348ddc3df2605c80bb136cfcd854 Mon Sep 17 00:00:00 2001 From: Alexandre Petitjean Date: Tue, 30 Jul 2013 08:37:24 +0200 Subject: [PATCH 4/8] correct default port config for proxy and deserialize function --- mopidy/config/default.conf | 2 +- mopidy/config/types.py | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/mopidy/config/default.conf b/mopidy/config/default.conf index 8d2101fb..d241323a 100644 --- a/mopidy/config/default.conf +++ b/mopidy/config/default.conf @@ -15,6 +15,6 @@ output = autoaudiosink [proxy] scheme = hostname = -port = +port = http username = password = diff --git a/mopidy/config/types.py b/mopidy/config/types.py index ba8b8f2a..8715c8da 100644 --- a/mopidy/config/types.py +++ b/mopidy/config/types.py @@ -227,10 +227,6 @@ class Port(Integer): minimum=0, maximum=2 ** 16 - 1, choices=choices) def deserialize(self, value): - # in case of no value is given, just return nothing - if not len(value): - return value - # now we can try to convert try: value = int(value) except ValueError: @@ -238,10 +234,10 @@ class Port(Integer): value = socket.getservbyname(value, 'tcp') except socket.error: raise ValueError('must be a valid port number') - else: - validators.validate_choice(value, self._choices) - validators.validate_minimum(value, self._minimum) - validators.validate_maximum(value, self._maximum) + + validators.validate_choice(value, self._choices) + validators.validate_minimum(value, self._minimum) + validators.validate_maximum(value, self._maximum) return value From 786d7c1ae0adcc5b0e0652ab767256777393706d Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Tue, 30 Jul 2013 23:21:08 +0200 Subject: [PATCH 5/8] Change docs license to Apache License, Version 2.0 I've looked through all contributions to the docs. Any contributions not by Thomas Adamcik or myself are trivial (e.g. typo fixes) or have mostly been replaced by later changes. Thus I'm comfortable with changing the license with the agreement of Thomas Adamcik. By changing the documentation license to be the same as the source code license, we avoid ambiguities around the license of e.g. docstrings which are written as part of the source code but are included in the generated docs. --- docs/conf.py | 2 +- docs/index.rst | 2 +- docs/license.rst | 10 ++++++++++ docs/licenses.rst | 34 ---------------------------------- 4 files changed, 12 insertions(+), 36 deletions(-) create mode 100644 docs/license.rst delete mode 100644 docs/licenses.rst diff --git a/docs/conf.py b/docs/conf.py index c0dba916..f3e4166c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -101,7 +101,7 @@ master_doc = 'index' # General information about the project. project = 'Mopidy' -copyright = '2010-2013, Stein Magnus Jodal and contributors' +copyright = '2009-2013, Stein Magnus Jodal and contributors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/docs/index.rst b/docs/index.rst index fb91244d..ca40c96c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -48,7 +48,7 @@ About :maxdepth: 1 authors - licenses + license changelog versioning diff --git a/docs/license.rst b/docs/license.rst new file mode 100644 index 00000000..98928f63 --- /dev/null +++ b/docs/license.rst @@ -0,0 +1,10 @@ +******* +License +******* + +Mopidy is copyright 2009-2013 Stein Magnus Jodal and contributors. For a list +of contributors, see :doc:`authors`. For details on who have contributed what, +please refer to our git repository. + +Mopidy is licensed under the `Apache License, Version 2.0 +`_. diff --git a/docs/licenses.rst b/docs/licenses.rst deleted file mode 100644 index fc2530e5..00000000 --- a/docs/licenses.rst +++ /dev/null @@ -1,34 +0,0 @@ -******** -Licenses -******** - -For a list of contributors, see :doc:`authors`. For details on who have -contributed what, please refer to our git repository. - -Source code license -=================== - -Copyright 2009-2013 Stein Magnus Jodal and contributors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - -Documentation license -===================== - -Copyright 2010-2013 Stein Magnus Jodal and contributors - -This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 -Unported License. To view a copy of this license, visit -http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to Creative -Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. From 97848bc1a2bf80896680ad45bac9933e3f782d83 Mon Sep 17 00:00:00 2001 From: Alexandre Petitjean Date: Wed, 31 Jul 2013 10:05:20 +0200 Subject: [PATCH 6/8] String config value can be optionnal AND have a choices list Integer value can be optionnal --- mopidy/backends/spotify/session_manager.py | 1 - mopidy/config/__init__.py | 4 ++-- mopidy/config/default.conf | 2 +- mopidy/config/types.py | 26 +++++++--------------- 4 files changed, 11 insertions(+), 22 deletions(-) diff --git a/mopidy/backends/spotify/session_manager.py b/mopidy/backends/spotify/session_manager.py index 130164fb..125b6ada 100644 --- a/mopidy/backends/spotify/session_manager.py +++ b/mopidy/backends/spotify/session_manager.py @@ -36,7 +36,6 @@ class SpotifySessionManager(process.BaseThread, PyspotifySessionManager): full_proxy = '' if config['proxy']['hostname']: full_proxy = config['proxy']['hostname'] - # Add proxy port and scheme only if available if config['proxy']['port']: full_proxy += ':' + str(config['proxy']['port']) if config['proxy']['scheme']: diff --git a/mopidy/config/__init__.py b/mopidy/config/__init__.py index 582a1a03..dfdae6a7 100644 --- a/mopidy/config/__init__.py +++ b/mopidy/config/__init__.py @@ -27,9 +27,9 @@ _audio_schema['output'] = String() _proxy_schema = ConfigSchema('proxy') _proxy_schema['scheme'] = String(optional=True, - choices=['', 'https', 'socks4', 'socks5']) + choices=['http', 'https', 'socks4', 'socks5']) _proxy_schema['hostname'] = Hostname(optional=True) -_proxy_schema['port'] = Port() +_proxy_schema['port'] = Port(optional=True) _proxy_schema['username'] = String(optional=True) _proxy_schema['password'] = Secret(optional=True) diff --git a/mopidy/config/default.conf b/mopidy/config/default.conf index d241323a..3899c2c5 100644 --- a/mopidy/config/default.conf +++ b/mopidy/config/default.conf @@ -15,6 +15,6 @@ output = autoaudiosink [proxy] scheme = hostname = -port = http +port = username = password = diff --git a/mopidy/config/types.py b/mopidy/config/types.py index 8715c8da..29651940 100644 --- a/mopidy/config/types.py +++ b/mopidy/config/types.py @@ -71,9 +71,9 @@ class String(ConfigValue): def deserialize(self, value): value = decode(value).strip() validators.validate_required(value, self._required) - validators.validate_choice(value, self._choices) if not value: return None + validators.validate_choice(value, self._choices) return value def serialize(self, value, display=False): @@ -111,12 +111,16 @@ class Secret(ConfigValue): class Integer(ConfigValue): """Integer value.""" - def __init__(self, minimum=None, maximum=None, choices=None): + def __init__(self, minimum=None, maximum=None, choices=None, optional=False): + self._required = not optional self._minimum = minimum self._maximum = maximum self._choices = choices def deserialize(self, value): + validators.validate_required(value, self._required) + if not value: + return None value = int(value) validators.validate_choice(value, self._choices) validators.validate_minimum(value, self._minimum) @@ -222,23 +226,9 @@ class Port(Integer): allocate a port for us. """ # TODO: consider probing if port is free or not? - def __init__(self, choices=None): + def __init__(self, choices=None, optional=False): super(Port, self).__init__( - minimum=0, maximum=2 ** 16 - 1, choices=choices) - - def deserialize(self, value): - try: - value = int(value) - except ValueError: - try: - value = socket.getservbyname(value, 'tcp') - except socket.error: - raise ValueError('must be a valid port number') - - validators.validate_choice(value, self._choices) - validators.validate_minimum(value, self._minimum) - validators.validate_maximum(value, self._maximum) - return value + minimum=0, maximum=2 ** 16 - 1, choices=choices, optional=optional) class Path(ConfigValue): From c66e2a5b0fce548a653bab26245da38f84c52da0 Mon Sep 17 00:00:00 2001 From: Alexandre Petitjean Date: Wed, 31 Jul 2013 23:11:29 +0200 Subject: [PATCH 7/8] add some tests about optionnal integer and optionnal+choices string --- tests/config/types_test.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/config/types_test.py b/tests/config/types_test.py index 88c8f067..d915b4f2 100644 --- a/tests/config/types_test.py +++ b/tests/config/types_test.py @@ -98,6 +98,11 @@ class StringTest(unittest.TestCase): self.assertIsInstance(result, bytes) self.assertEqual(b'', result) + def test_deserialize_enforces_choices_optionnal(self): + value = types.String(optional=True, choices=['foo', 'bar', 'baz']) + self.assertEqual(None, value.deserialize(b'')) + self.assertRaises(ValueError, value.deserialize, b'foobar') + class SecretTest(unittest.TestCase): def test_deserialize_passes_through(self): @@ -163,6 +168,10 @@ class IntegerTest(unittest.TestCase): self.assertEqual(5, value.deserialize('5')) self.assertRaises(ValueError, value.deserialize, '15') + def test_deserialize_respects_optional(self): + value = types.Integer(optional=True) + self.assertEqual(None, value.deserialize('')) + class BooleanTest(unittest.TestCase): def test_deserialize_conversion_success(self): From da86015a2b400e2be0fb27838527faeb4d202ad9 Mon Sep 17 00:00:00 2001 From: AlexandreP2101 Date: Thu, 1 Aug 2013 08:47:22 +0200 Subject: [PATCH 8/8] Correct typo --- tests/config/types_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/config/types_test.py b/tests/config/types_test.py index d915b4f2..74e9672d 100644 --- a/tests/config/types_test.py +++ b/tests/config/types_test.py @@ -98,7 +98,7 @@ class StringTest(unittest.TestCase): self.assertIsInstance(result, bytes) self.assertEqual(b'', result) - def test_deserialize_enforces_choices_optionnal(self): + def test_deserialize_enforces_choices_optional(self): value = types.String(optional=True, choices=['foo', 'bar', 'baz']) self.assertEqual(None, value.deserialize(b'')) self.assertRaises(ValueError, value.deserialize, b'foobar')