diff --git a/bin/mopidy-scan b/bin/mopidy-scan index 869aa662..001ea372 100755 --- a/bin/mopidy-scan +++ b/bin/mopidy-scan @@ -1,5 +1,7 @@ #!/usr/bin/env python +from __future__ import unicode_literals + import sys import logging @@ -8,20 +10,26 @@ from mopidy.utils.log import setup_console_logging, setup_root_logger from mopidy.scanner import Scanner, translator from mopidy.frontends.mpd.translator import tracks_to_tag_cache_format + setup_root_logger() setup_console_logging(2) + tracks = [] + def store(data): track = translator(data) tracks.append(track) - logging.debug(u'Added %s', track.uri) + logging.debug('Added %s', track.uri) + def debug(uri, error, debug): - logging.error(u'Failed %s: %s - %s', uri, error, debug) + logging.error('Failed %s: %s - %s', uri, error, debug) + + +logging.info('Scanning %s', settings.LOCAL_MUSIC_PATH) -logging.info(u'Scanning %s', settings.LOCAL_MUSIC_PATH) scanner = Scanner(settings.LOCAL_MUSIC_PATH, store, debug) try: @@ -29,10 +37,12 @@ try: except KeyboardInterrupt: scanner.stop() -logging.info(u'Done') + +logging.info('Done') + for a in tracks_to_tag_cache_format(tracks): if len(a) == 1: - print (u'%s' % a).encode('utf-8') + print ('%s' % a).encode('utf-8') else: - print (u'%s: %s' % a).encode('utf-8') + print ('%s: %s' % a).encode('utf-8') diff --git a/docs/api/backends.rst b/docs/api/backends.rst index c296fb78..0dc4900d 100644 --- a/docs/api/backends.rst +++ b/docs/api/backends.rst @@ -19,10 +19,10 @@ Playback provider :members: -Stored playlists provider -========================= +Playlists provider +================== -.. autoclass:: mopidy.backends.base.BaseStoredPlaylistsProvider +.. autoclass:: mopidy.backends.base.BasePlaylistsProvider :members: diff --git a/docs/api/concepts.rst b/docs/api/concepts.rst index 203418de..68718935 100644 --- a/docs/api/concepts.rst +++ b/docs/api/concepts.rst @@ -43,17 +43,17 @@ every request from a frontend it calls out to one or more backends which does the real work, and when the backends respond, the core actor is responsible for combining the responses into a single response to the requesting frontend. -The core actor also keeps track of the current playlist, since it doesn't -belong to a specific backend. +The core actor also keeps track of the tracklist, since it doesn't belong to a +specific backend. See :ref:`core-api` for more details. .. digraph:: core_architecture - Core -> "Current\nplaylist\ncontroller" + Core -> "Tracklist\ncontroller" Core -> "Library\ncontroller" Core -> "Playback\ncontroller" - Core -> "Stored\nplaylists\ncontroller" + Core -> "Playlists\ncontroller" "Library\ncontroller" -> "Local backend" "Library\ncontroller" -> "Spotify backend" @@ -62,8 +62,8 @@ See :ref:`core-api` for more details. "Playback\ncontroller" -> "Spotify backend" "Playback\ncontroller" -> Audio - "Stored\nplaylists\ncontroller" -> "Local backend" - "Stored\nplaylists\ncontroller" -> "Spotify backend" + "Playlists\ncontroller" -> "Local backend" + "Playlists\ncontroller" -> "Spotify backend" Backends @@ -80,12 +80,12 @@ See :ref:`backend-api` for more details. "Local backend" -> "Local\nlibrary\nprovider" -> "Local disk" "Local backend" -> "Local\nplayback\nprovider" -> "Local disk" - "Local backend" -> "Local\nstored\nplaylists\nprovider" -> "Local disk" + "Local backend" -> "Local\nplaylists\nprovider" -> "Local disk" "Local\nplayback\nprovider" -> Audio "Spotify backend" -> "Spotify\nlibrary\nprovider" -> "Spotify service" "Spotify backend" -> "Spotify\nplayback\nprovider" -> "Spotify service" - "Spotify backend" -> "Spotify\nstored\nplaylists\nprovider" -> "Spotify service" + "Spotify backend" -> "Spotify\nplaylists\nprovider" -> "Spotify service" "Spotify\nplayback\nprovider" -> Audio diff --git a/docs/api/core.rst b/docs/api/core.rst index eb1b9683..de85557c 100644 --- a/docs/api/core.rst +++ b/docs/api/core.rst @@ -26,21 +26,21 @@ seek, and volume control. :members: -Current playlist controller -=========================== +Tracklist controller +==================== -Manages everything related to the currently loaded playlist. +Manages everything related to the tracks we are currently playing. -.. autoclass:: mopidy.core.CurrentPlaylistController +.. autoclass:: mopidy.core.TracklistController :members: -Stored playlists controller -=========================== +Playlists controller +==================== -Manages stored playlist. +Manages persistence of playlists. -.. autoclass:: mopidy.core.StoredPlaylistsController +.. autoclass:: mopidy.core.PlaylistsController :members: diff --git a/docs/changes.rst b/docs/changes.rst index 3499fb04..42478178 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -93,6 +93,24 @@ backends: :attr:`mopidy.settings.DEBUG_THREAD` setting a ``SIGUSR1`` signal will dump the traceback for all running threads. +- Make the entire code base use unicode strings by default, and only fall back + to bytestrings where it is required. Another step closer to Python 3. + +- The settings validator will now allow any setting prefixed with ``CUSTOM_`` + to exist in the settings file. + +- The MPD commands ``search`` and ``find`` now allows the key ``file``, which + is used by ncmpcpp instead of ``filename``. + +- The Spotify backend now returns the track if you search for the Spotify track + URI. (Fixes: :issue:`233`) + +- Renamed "current playlist" to "tracklist" everywhere, including the core API + used by frontends. + +- Renamed "stored playlists" to "playlists" everywhere, including the core API + used by frontends. + **Bug fixes** - :issue:`218`: The MPD commands ``listplaylist`` and ``listplaylistinfo`` now @@ -101,6 +119,9 @@ backends: - The MPD command ``plchanges`` always returned the entire playlist. It now returns an empty response when the client has seen the latest version. +- MPD no longer lowercases search queries. This broke e.g. search by URI, where + casing may be essential. + v0.8.1 (2012-10-30) =================== diff --git a/docs/conf.py b/docs/conf.py index 7e626d99..04d15067 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,6 +12,8 @@ # All configuration values have a default; values that are commented out # serve to show the default. +from __future__ import unicode_literals + import os import sys @@ -95,8 +97,8 @@ source_suffix = '.rst' master_doc = 'index' # General information about the project. -project = u'Mopidy' -copyright = u'2010-2012, Stein Magnus Jodal and contributors' +project = 'Mopidy' +copyright = '2010-2012, 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 @@ -237,8 +239,8 @@ latex_documents = [ ( 'index', 'Mopidy.tex', - u'Mopidy Documentation', - u'Stein Magnus Jodal', + 'Mopidy Documentation', + 'Stein Magnus Jodal', 'manual' ), ] diff --git a/docs/development.rst b/docs/development.rst index 5c01d6d0..1211cec4 100644 --- a/docs/development.rst +++ b/docs/development.rst @@ -84,6 +84,22 @@ contributing. Code style ========== +- Always import ``unicode_literals`` and use unicode literals for everything + except where you're explicitly working with bytes, which are marked with the + ``b`` prefix. + + Do this:: + + from __future__ import unicode_literals + + foo = 'I am a unicode string, which is a sane default' + bar = b'I am a bytestring' + + Not this:: + + foo = u'I am a unicode string' + bar = 'I am a bytestring, but was it intentional?' + - Follow :pep:`8` unless otherwise noted. `pep8.py `_ or `flake8 `_ can be used to check your code diff --git a/docs/settings.rst b/docs/settings.rst index 5bc63d7f..cb47a71f 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -153,7 +153,7 @@ plugins, ending in a summary line:: Next, you should be able to produce a audible tone by running:: - gst-launch-0.10 audiotestsrc ! sudioresample ! autoaudiosink + gst-launch-0.10 audiotestsrc ! audioresample ! autoaudiosink If you cannot hear any sound when running this command, you won't hear any sound from Mopidy either, as Mopidy by default uses GStreamer's @@ -200,6 +200,21 @@ can use with the ``gst-launch-0.10`` command can be plugged into :attr:`mopidy.settings.OUTPUT`. +Custom settings +=============== + +Mopidy's settings validator will stop you from defining any settings in your +settings file that Mopidy doesn't know about. This may sound obnoxious, but it +helps you detect typos in your settings, and deprecated settings that should be +removed or updated. + +If you're extending Mopidy in some way, and want to use Mopidy's settings +system, you can prefix your settings with ``CUSTOM_`` to get around the +settings validator. We recommend that you choose names like +``CUSTOM_MYAPP_MYSETTING`` so that multiple custom extensions to Mopidy can be +used at the same time without any danger of naming collisions. + + Available settings ================== diff --git a/mopidy/__init__.py b/mopidy/__init__.py index 3010acf4..072a604c 100644 --- a/mopidy/__init__.py +++ b/mopidy/__init__.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + # pylint: disable = E0611,F0401 from distutils.version import StrictVersion as SV # pylint: enable = E0611,F0401 @@ -9,13 +11,13 @@ import pykka if not (2, 6) <= sys.version_info < (3,): sys.exit( - u'Mopidy requires Python >= 2.6, < 3, but found %s' % + 'Mopidy requires Python >= 2.6, < 3, but found %s' % '.'.join(map(str, sys.version_info[:3]))) if (isinstance(pykka.__version__, basestring) and not SV('1.0') <= SV(pykka.__version__) < SV('2.0')): sys.exit( - u'Mopidy requires Pykka >= 1.0, < 2, but found %s' % pykka.__version__) + 'Mopidy requires Pykka >= 1.0, < 2, but found %s' % pykka.__version__) warnings.filterwarnings('ignore', 'could not open display') diff --git a/mopidy/__main__.py b/mopidy/__main__.py index de905d15..952f158c 100644 --- a/mopidy/__main__.py +++ b/mopidy/__main__.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import logging import optparse import os @@ -62,7 +64,7 @@ def main(): except exceptions.SettingsError as ex: logger.error(ex.message) except KeyboardInterrupt: - logger.info(u'Interrupted. Exiting...') + logger.info('Interrupted. Exiting...') except Exception as ex: logger.exception(ex) finally: @@ -76,7 +78,7 @@ def main(): def parse_options(): parser = optparse.OptionParser( - version=u'Mopidy %s' % versioning.get_version()) + version='Mopidy %s' % versioning.get_version()) parser.add_option( '--help-gst', action='store_true', dest='help_gst', @@ -114,15 +116,15 @@ def parse_options(): def check_old_folders(): - old_settings_folder = os.path.expanduser(u'~/.mopidy') + old_settings_folder = os.path.expanduser('~/.mopidy') if not os.path.isdir(old_settings_folder): return logger.warning( - u'Old settings folder found at %s, settings.py should be moved ' - u'to %s, any cache data should be deleted. See release notes for ' - u'further instructions.', old_settings_folder, path.SETTINGS_PATH) + 'Old settings folder found at %s, settings.py should be moved ' + 'to %s, any cache data should be deleted. See release notes for ' + 'further instructions.', old_settings_folder, path.SETTINGS_PATH) def setup_settings(interactive): @@ -171,7 +173,7 @@ def setup_frontends(core): try: importing.get_class(frontend_class_name).start(core=core) except exceptions.OptionalDependencyError as ex: - logger.info(u'Disabled: %s (%s)', frontend_class_name, ex) + logger.info('Disabled: %s (%s)', frontend_class_name, ex) def stop_frontends(): diff --git a/mopidy/audio/__init__.py b/mopidy/audio/__init__.py index ba76bd84..c3fbc0c9 100644 --- a/mopidy/audio/__init__.py +++ b/mopidy/audio/__init__.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + # flake8: noqa from .actor import Audio from .listener import AudioListener diff --git a/mopidy/audio/actor.py b/mopidy/audio/actor.py index 852d5d57..a7b4e8d8 100644 --- a/mopidy/audio/actor.py +++ b/mopidy/audio/actor.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import pygst pygst.require('0.10') import gst @@ -70,9 +72,9 @@ class Audio(pykka.ThreadingActor): # These caps matches the audio data provided by libspotify default_caps = gst.Caps( - 'audio/x-raw-int, endianness=(int)1234, channels=(int)2, ' - 'width=(int)16, depth=(int)16, signed=(boolean)true, ' - 'rate=(int)44100') + b'audio/x-raw-int, endianness=(int)1234, channels=(int)2, ' + b'width=(int)16, depth=(int)16, signed=(boolean)true, ' + b'rate=(int)44100') source = element.get_property('source') source.set_property('caps', default_caps) @@ -109,7 +111,7 @@ class Audio(pykka.ThreadingActor): return # We assume that the bin will contain a single mixer. - mixer = mixerbin.get_by_interface('GstMixer') + mixer = mixerbin.get_by_interface(b'GstMixer') if not mixer: logger.warning( 'Did not find any audio mixers in "%s"', settings.MIXER) @@ -162,14 +164,14 @@ class Audio(pykka.ThreadingActor): self._trigger_reached_end_of_stream_event() elif message.type == gst.MESSAGE_ERROR: error, debug = message.parse_error() - logger.error(u'%s %s', error, debug) + logger.error('%s %s', error, debug) self.stop_playback() elif message.type == gst.MESSAGE_WARNING: error, debug = message.parse_warning() - logger.warning(u'%s %s', error, debug) + logger.warning('%s %s', error, debug) def _trigger_reached_end_of_stream_event(self): - logger.debug(u'Triggering reached end of stream event') + logger.debug('Triggering reached end of stream event') AudioListener.send('reached_end_of_stream') def set_uri(self, uri): @@ -327,7 +329,7 @@ class Audio(pykka.ThreadingActor): :rtype: int in range [0..100] or :class:`None` """ if self._software_mixing: - return round(self._playbin.get_property('volume') * 100) + return int(round(self._playbin.get_property('volume') * 100)) if self._mixer is None: return None @@ -389,12 +391,12 @@ class Audio(pykka.ThreadingActor): # Default to blank data to trick shoutcast into clearing any previous # values it might have. - taglist[gst.TAG_ARTIST] = u' ' - taglist[gst.TAG_TITLE] = u' ' - taglist[gst.TAG_ALBUM] = u' ' + taglist[gst.TAG_ARTIST] = ' ' + taglist[gst.TAG_TITLE] = ' ' + taglist[gst.TAG_ALBUM] = ' ' if artists: - taglist[gst.TAG_ARTIST] = u', '.join([a.name for a in artists]) + taglist[gst.TAG_ARTIST] = ', '.join([a.name for a in artists]) if track.name: taglist[gst.TAG_TITLE] = track.name diff --git a/mopidy/audio/listener.py b/mopidy/audio/listener.py index 54fe058d..42c85e1e 100644 --- a/mopidy/audio/listener.py +++ b/mopidy/audio/listener.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import pykka diff --git a/mopidy/audio/mixers/__init__.py b/mopidy/audio/mixers/__init__.py index 034b0fa9..feaccc3d 100644 --- a/mopidy/audio/mixers/__init__.py +++ b/mopidy/audio/mixers/__init__.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import pygst pygst.require('0.10') import gst diff --git a/mopidy/audio/mixers/auto.py b/mopidy/audio/mixers/auto.py index 05294801..bd61445e 100644 --- a/mopidy/audio/mixers/auto.py +++ b/mopidy/audio/mixers/auto.py @@ -12,6 +12,8 @@ This is Mopidy's default mixer. to ``autoaudiomixer`` to use this mixer. """ +from __future__ import unicode_literals + import pygst pygst.require('0.10') import gst diff --git a/mopidy/audio/mixers/fake.py b/mopidy/audio/mixers/fake.py index 10710466..948ab82e 100644 --- a/mopidy/audio/mixers/fake.py +++ b/mopidy/audio/mixers/fake.py @@ -9,6 +9,8 @@ - Set :attr:`mopidy.settings.MIXER` to ``fakemixer`` to use this mixer. """ +from __future__ import unicode_literals + import pygst pygst.require('0.10') import gobject diff --git a/mopidy/audio/mixers/nad.py b/mopidy/audio/mixers/nad.py index 1a807e39..b5cb522d 100644 --- a/mopidy/audio/mixers/nad.py +++ b/mopidy/audio/mixers/nad.py @@ -45,6 +45,8 @@ Configuration examples:: u'source=aux speakers-a=on speakers-b=off') """ +from __future__ import unicode_literals + import logging import pygst @@ -107,7 +109,7 @@ class NadMixer(gst.Element, gst.ImplementsInterface, gst.interfaces.Mixer): def do_change_state(self, transition): if transition == gst.STATE_CHANGE_NULL_TO_READY: if serial is None: - logger.warning(u'nadmixer dependency python-serial not found') + logger.warning('nadmixer dependency python-serial not found') return gst.STATE_CHANGE_FAILURE self._start_nad_talker() return gst.STATE_CHANGE_SUCCESS @@ -164,7 +166,7 @@ class NadTalker(pykka.ThreadingActor): self._set_device_to_known_state() def _open_connection(self): - logger.info(u'NAD amplifier: Connecting through "%s"', self.port) + logger.info('NAD amplifier: Connecting through "%s"', self.port) self._device = serial.Serial( port=self.port, baudrate=self.BAUDRATE, @@ -183,7 +185,7 @@ class NadTalker(pykka.ThreadingActor): def _get_device_model(self): model = self._ask_device('Main.Model') - logger.info(u'NAD amplifier: Connected to model "%s"', model) + logger.info('NAD amplifier: Connected to model "%s"', model) return model def _power_device_on(self): @@ -212,19 +214,19 @@ class NadTalker(pykka.ThreadingActor): if current_nad_volume is None: current_nad_volume = self.VOLUME_LEVELS if current_nad_volume == self.VOLUME_LEVELS: - logger.info(u'NAD amplifier: Calibrating by setting volume to 0') + logger.info('NAD amplifier: Calibrating by setting volume to 0') self._nad_volume = current_nad_volume if self._decrease_volume(): current_nad_volume -= 1 if current_nad_volume == 0: - logger.info(u'NAD amplifier: Done calibrating') + logger.info('NAD amplifier: Done calibrating') else: self.actor_ref.proxy().calibrate_volume(current_nad_volume) def set_volume(self, volume): # Increase or decrease the amplifier volume until it matches the given # target volume. - logger.debug(u'Setting volume to %d' % volume) + logger.debug('Setting volume to %d' % volume) target_nad_volume = int(round(volume * self.VOLUME_LEVELS / 100.0)) if self._nad_volume is None: return # Calibration needed @@ -250,12 +252,12 @@ class NadTalker(pykka.ThreadingActor): if self._ask_device(key) == value: return logger.info( - u'NAD amplifier: Setting "%s" to "%s" (attempt %d/3)', + 'NAD amplifier: Setting "%s" to "%s" (attempt %d/3)', key, value, attempt) self._command_device(key, value) if self._ask_device(key) != value: logger.info( - u'NAD amplifier: Gave up on setting "%s" to "%s"', + 'NAD amplifier: Gave up on setting "%s" to "%s"', key, value) def _ask_device(self, key): diff --git a/mopidy/audio/mixers/utils.py b/mopidy/audio/mixers/utils.py index c257ffd7..8d0ce280 100644 --- a/mopidy/audio/mixers/utils.py +++ b/mopidy/audio/mixers/utils.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import pygst pygst.require('0.10') import gst diff --git a/mopidy/backends/__init__.py b/mopidy/backends/__init__.py index e69de29b..baffc488 100644 --- a/mopidy/backends/__init__.py +++ b/mopidy/backends/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/mopidy/backends/base.py b/mopidy/backends/base.py index de33e6e5..8250a24c 100644 --- a/mopidy/backends/base.py +++ b/mopidy/backends/base.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import copy @@ -9,20 +11,36 @@ class Backend(object): audio = None #: The library provider. An instance of - # :class:`mopidy.backends.base.BaseLibraryProvider`. + #: :class:`mopidy.backends.base.BaseLibraryProvider`, or :class:`None` if + #: the backend doesn't provide a library. library = None #: The playback provider. An instance of - #: :class:`mopidy.backends.base.BasePlaybackProvider`. + #: :class:`mopidy.backends.base.BasePlaybackProvider`, or :class:`None` if + #: the backend doesn't provide playback. playback = None - #: The stored playlists provider. An instance of - #: :class:`mopidy.backends.base.BaseStoredPlaylistsProvider`. - stored_playlists = None + #: The playlists provider. An instance of + #: :class:`mopidy.backends.base.BasePlaylistsProvider`, or class:`None` if + #: the backend doesn't provide playlists. + playlists = None #: List of URI schemes this backend can handle. uri_schemes = [] + # Because the providers is marked as pykka_traversible, we can't get() them + # from another actor, and need helper methods to check if the providers are + # set or None. + + def has_library(self): + return self.library is not None + + def has_playback(self): + return self.playback is not None + + def has_playlists(self): + return self.playlists is not None + class BaseLibraryProvider(object): """ @@ -149,7 +167,7 @@ class BasePlaybackProvider(object): return self.audio.get_position().get() -class BaseStoredPlaylistsProvider(object): +class BasePlaylistsProvider(object): """ :param backend: backend the controller is a part of :type backend: :class:`mopidy.backends.base.Backend` @@ -164,7 +182,7 @@ class BaseStoredPlaylistsProvider(object): @property def playlists(self): """ - Currently stored playlists. + Currently available playlists. Read/write. List of :class:`mopidy.models.Playlist`. """ @@ -176,7 +194,7 @@ class BaseStoredPlaylistsProvider(object): def create(self, name): """ - See :meth:`mopidy.core.StoredPlaylistsController.create`. + See :meth:`mopidy.core.PlaylistsController.create`. *MUST be implemented by subclass.* """ @@ -184,7 +202,7 @@ class BaseStoredPlaylistsProvider(object): def delete(self, uri): """ - See :meth:`mopidy.core.StoredPlaylistsController.delete`. + See :meth:`mopidy.core.PlaylistsController.delete`. *MUST be implemented by subclass.* """ @@ -192,7 +210,7 @@ class BaseStoredPlaylistsProvider(object): def lookup(self, uri): """ - See :meth:`mopidy.core.StoredPlaylistsController.lookup`. + See :meth:`mopidy.core.PlaylistsController.lookup`. *MUST be implemented by subclass.* """ @@ -200,7 +218,7 @@ class BaseStoredPlaylistsProvider(object): def refresh(self): """ - See :meth:`mopidy.core.StoredPlaylistsController.refresh`. + See :meth:`mopidy.core.PlaylistsController.refresh`. *MUST be implemented by subclass.* """ @@ -208,7 +226,7 @@ class BaseStoredPlaylistsProvider(object): def save(self, playlist): """ - See :meth:`mopidy.core.StoredPlaylistsController.save`. + See :meth:`mopidy.core.PlaylistsController.save`. *MUST be implemented by subclass.* """ diff --git a/mopidy/backends/dummy.py b/mopidy/backends/dummy.py index 51129200..af8f7487 100644 --- a/mopidy/backends/dummy.py +++ b/mopidy/backends/dummy.py @@ -14,6 +14,8 @@ The backend handles URIs starting with ``dummy:``. - None """ +from __future__ import unicode_literals + import pykka from mopidy.backends import base @@ -26,9 +28,9 @@ class DummyBackend(pykka.ThreadingActor, base.Backend): self.library = DummyLibraryProvider(backend=self) self.playback = DummyPlaybackProvider(audio=audio, backend=self) - self.stored_playlists = DummyStoredPlaylistsProvider(backend=self) + self.playlists = DummyPlaylistsProvider(backend=self) - self.uri_schemes = [u'dummy'] + self.uri_schemes = ['dummy'] class DummyLibraryProvider(base.BaseLibraryProvider): @@ -78,7 +80,7 @@ class DummyPlaybackProvider(base.BasePlaybackProvider): return self._time_position -class DummyStoredPlaylistsProvider(base.BaseStoredPlaylistsProvider): +class DummyPlaylistsProvider(base.BasePlaylistsProvider): def create(self, name): playlist = Playlist(name=name) self._playlists.append(playlist) diff --git a/mopidy/backends/local/__init__.py b/mopidy/backends/local/__init__.py index 6f049474..8ee58d3b 100644 --- a/mopidy/backends/local/__init__.py +++ b/mopidy/backends/local/__init__.py @@ -20,5 +20,7 @@ https://github.com/mopidy/mopidy/issues?labels=Local+backend - :attr:`mopidy.settings.LOCAL_TAG_CACHE_FILE` """ +from __future__ import unicode_literals + # flake8: noqa from .actor import LocalBackend diff --git a/mopidy/backends/local/actor.py b/mopidy/backends/local/actor.py index 70351ed1..75baeab2 100644 --- a/mopidy/backends/local/actor.py +++ b/mopidy/backends/local/actor.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import logging import pykka @@ -5,9 +7,9 @@ import pykka from mopidy.backends import base from .library import LocalLibraryProvider -from .stored_playlists import LocalStoredPlaylistsProvider +from .playlists import LocalPlaylistsProvider -logger = logging.getLogger(u'mopidy.backends.local') +logger = logging.getLogger('mopidy.backends.local') class LocalBackend(pykka.ThreadingActor, base.Backend): @@ -16,6 +18,6 @@ class LocalBackend(pykka.ThreadingActor, base.Backend): self.library = LocalLibraryProvider(backend=self) self.playback = base.BasePlaybackProvider(audio=audio, backend=self) - self.stored_playlists = LocalStoredPlaylistsProvider(backend=self) + self.playlists = LocalPlaylistsProvider(backend=self) - self.uri_schemes = [u'file'] + self.uri_schemes = ['file'] diff --git a/mopidy/backends/local/library.py b/mopidy/backends/local/library.py index 9abdf7ed..3454ca76 100644 --- a/mopidy/backends/local/library.py +++ b/mopidy/backends/local/library.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import logging from mopidy import settings @@ -6,7 +8,7 @@ from mopidy.models import Playlist, Album from .translator import parse_mpd_tag_cache -logger = logging.getLogger(u'mopidy.backends.local') +logger = logging.getLogger('mopidy.backends.local') class LocalLibraryProvider(base.BaseLibraryProvider): @@ -30,7 +32,7 @@ class LocalLibraryProvider(base.BaseLibraryProvider): try: return self._uri_mapping[uri] except KeyError: - logger.debug(u'Failed to lookup %r', uri) + logger.debug('Failed to lookup %r', uri) return None def find_exact(self, **query): @@ -59,7 +61,7 @@ class LocalLibraryProvider(base.BaseLibraryProvider): result_tracks = filter(album_filter, result_tracks) elif field == 'artist': result_tracks = filter(artist_filter, result_tracks) - elif field in ('uri', 'filename'): + elif field == 'uri': result_tracks = filter(uri_filter, result_tracks) elif field == 'any': result_tracks = filter(any_filter, result_tracks) @@ -93,7 +95,7 @@ class LocalLibraryProvider(base.BaseLibraryProvider): result_tracks = filter(album_filter, result_tracks) elif field == 'artist': result_tracks = filter(artist_filter, result_tracks) - elif field in ('uri', 'filename'): + elif field == 'uri': result_tracks = filter(uri_filter, result_tracks) elif field == 'any': result_tracks = filter(any_filter, result_tracks) diff --git a/mopidy/backends/local/stored_playlists.py b/mopidy/backends/local/playlists.py similarity index 94% rename from mopidy/backends/local/stored_playlists.py rename to mopidy/backends/local/playlists.py index 04406c32..05873a98 100644 --- a/mopidy/backends/local/stored_playlists.py +++ b/mopidy/backends/local/playlists.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import glob import logging import os @@ -11,12 +13,12 @@ from mopidy.utils import formatting, path from .translator import parse_m3u -logger = logging.getLogger(u'mopidy.backends.local') +logger = logging.getLogger('mopidy.backends.local') -class LocalStoredPlaylistsProvider(base.BaseStoredPlaylistsProvider): +class LocalPlaylistsProvider(base.BasePlaylistsProvider): def __init__(self, *args, **kwargs): - super(LocalStoredPlaylistsProvider, self).__init__(*args, **kwargs) + super(LocalPlaylistsProvider, self).__init__(*args, **kwargs) self._path = settings.LOCAL_PLAYLIST_PATH self.refresh() diff --git a/mopidy/backends/local/translator.py b/mopidy/backends/local/translator.py index 01aad440..21e389ea 100644 --- a/mopidy/backends/local/translator.py +++ b/mopidy/backends/local/translator.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import logging from mopidy.models import Track, Artist, Album @@ -68,19 +70,19 @@ def parse_mpd_tag_cache(tag_cache, music_dir=''): current = {} state = None - for line in contents.split('\n'): - if line == 'songList begin': + for line in contents.split(b'\n'): + if line == b'songList begin': state = 'songs' continue - elif line == 'songList end': + elif line == b'songList end': state = None continue elif not state: continue - key, value = line.split(': ', 1) + key, value = line.split(b': ', 1) - if key == 'key': + if key == b'key': _convert_mpd_data(current, tracks, music_dir) current.clear() diff --git a/mopidy/backends/spotify/__init__.py b/mopidy/backends/spotify/__init__.py index 28813bc2..fa6feb99 100644 --- a/mopidy/backends/spotify/__init__.py +++ b/mopidy/backends/spotify/__init__.py @@ -30,5 +30,7 @@ https://github.com/mopidy/mopidy/issues?labels=Spotify+backend - :attr:`mopidy.settings.SPOTIFY_PASSWORD` """ +from __future__ import unicode_literals + # flake8: noqa from .actor import SpotifyBackend diff --git a/mopidy/backends/spotify/actor.py b/mopidy/backends/spotify/actor.py index 943600fc..5fc5cc4f 100644 --- a/mopidy/backends/spotify/actor.py +++ b/mopidy/backends/spotify/actor.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import logging import pykka @@ -18,13 +20,13 @@ class SpotifyBackend(pykka.ThreadingActor, base.Backend): from .library import SpotifyLibraryProvider from .playback import SpotifyPlaybackProvider from .session_manager import SpotifySessionManager - from .stored_playlists import SpotifyStoredPlaylistsProvider + from .playlists import SpotifyPlaylistsProvider self.library = SpotifyLibraryProvider(backend=self) self.playback = SpotifyPlaybackProvider(audio=audio, backend=self) - self.stored_playlists = SpotifyStoredPlaylistsProvider(backend=self) + self.playlists = SpotifyPlaylistsProvider(backend=self) - self.uri_schemes = [u'spotify'] + self.uri_schemes = ['spotify'] # Fail early if settings are not present username = settings.SPOTIFY_USERNAME @@ -34,8 +36,8 @@ class SpotifyBackend(pykka.ThreadingActor, base.Backend): username, password, audio=audio, backend_ref=self.actor_ref) def on_start(self): - logger.info(u'Mopidy uses SPOTIFY(R) CORE') - logger.debug(u'Connecting to Spotify') + logger.info('Mopidy uses SPOTIFY(R) CORE') + logger.debug('Connecting to Spotify') self.spotify.start() def on_stop(self): diff --git a/mopidy/backends/spotify/container_manager.py b/mopidy/backends/spotify/container_manager.py index e3388e0b..e8d1ed0b 100644 --- a/mopidy/backends/spotify/container_manager.py +++ b/mopidy/backends/spotify/container_manager.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import logging from spotify.manager import SpotifyContainerManager as \ @@ -13,21 +15,21 @@ class SpotifyContainerManager(PyspotifyContainerManager): def container_loaded(self, container, userdata): """Callback used by pyspotify""" - logger.debug(u'Callback called: playlist container loaded') + logger.debug('Callback called: playlist container loaded') - self.session_manager.refresh_stored_playlists() + self.session_manager.refresh_playlists() count = 0 for playlist in self.session_manager.session.playlist_container(): if playlist.type() == 'playlist': self.session_manager.playlist_manager.watch(playlist) count += 1 - logger.debug(u'Watching %d playlist(s) for changes', count) + logger.debug('Watching %d playlist(s) for changes', count) def playlist_added(self, container, playlist, position, userdata): """Callback used by pyspotify""" logger.debug( - u'Callback called: playlist added at position %d', position) + 'Callback called: playlist added at position %d', position) # container_loaded() is called after this callback, so we do not need # to handle this callback. @@ -35,7 +37,7 @@ class SpotifyContainerManager(PyspotifyContainerManager): userdata): """Callback used by pyspotify""" logger.debug( - u'Callback called: playlist "%s" moved from position %d to %d', + 'Callback called: playlist "%s" moved from position %d to %d', playlist.name(), old_position, new_position) # container_loaded() is called after this callback, so we do not need # to handle this callback. @@ -43,7 +45,7 @@ class SpotifyContainerManager(PyspotifyContainerManager): def playlist_removed(self, container, playlist, position, userdata): """Callback used by pyspotify""" logger.debug( - u'Callback called: playlist "%s" removed from position %d', + 'Callback called: playlist "%s" removed from position %d', playlist.name(), position) # container_loaded() is called after this callback, so we do not need # to handle this callback. diff --git a/mopidy/backends/spotify/library.py b/mopidy/backends/spotify/library.py index bf057bee..67c390fc 100644 --- a/mopidy/backends/spotify/library.py +++ b/mopidy/backends/spotify/library.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import logging import Queue @@ -16,7 +18,7 @@ class SpotifyTrack(Track): def __init__(self, uri): super(SpotifyTrack, self).__init__() self._spotify_track = Link.from_string(uri).as_track() - self._unloaded_track = Track(uri=uri, name=u'[loading...]') + self._unloaded_track = Track(uri=uri, name='[loading...]') self._track = None @property @@ -57,7 +59,7 @@ class SpotifyLibraryProvider(base.BaseLibraryProvider): try: return SpotifyTrack(uri) except SpotifyError as e: - logger.debug(u'Failed to lookup "%s": %s', uri, e) + logger.debug('Failed to lookup "%s": %s', uri, e) return None def refresh(self, uri=None): @@ -66,29 +68,36 @@ class SpotifyLibraryProvider(base.BaseLibraryProvider): def search(self, **query): if not query: # Since we can't search for the entire Spotify library, we return - # all tracks in the stored playlists when the query is empty. + # all tracks in the playlists when the query is empty. tracks = [] - for playlist in self.backend.stored_playlists.playlists: + for playlist in self.backend.playlists.playlists: tracks += playlist.tracks return Playlist(tracks=tracks) spotify_query = [] for (field, values) in query.iteritems(): - if field == u'track': - field = u'title' - if field == u'date': - field = u'year' + if field == 'uri': + tracks = [] + for value in values: + track = self.lookup(value) + if track: + tracks.append(track) + return Playlist(tracks=tracks) + elif field == 'track': + field = 'title' + elif field == 'date': + field = 'year' if not hasattr(values, '__iter__'): values = [values] for value in values: - if field == u'any': + if field == 'any': spotify_query.append(value) - elif field == u'year': + elif field == 'year': value = int(value.split('-')[0]) # Extract year - spotify_query.append(u'%s:%d' % (field, value)) + spotify_query.append('%s:%d' % (field, value)) else: - spotify_query.append(u'%s:"%s"' % (field, value)) - spotify_query = u' '.join(spotify_query) - logger.debug(u'Spotify search query: %s' % spotify_query) + spotify_query.append('%s:"%s"' % (field, value)) + spotify_query = ' '.join(spotify_query) + logger.debug('Spotify search query: %s' % spotify_query) queue = Queue.Queue() self.backend.spotify.search(spotify_query, queue) try: diff --git a/mopidy/backends/spotify/playback.py b/mopidy/backends/spotify/playback.py index 40868745..de82464a 100644 --- a/mopidy/backends/spotify/playback.py +++ b/mopidy/backends/spotify/playback.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import logging import time diff --git a/mopidy/backends/spotify/playlist_manager.py b/mopidy/backends/spotify/playlist_manager.py index 645a574c..6cd6d4ed 100644 --- a/mopidy/backends/spotify/playlist_manager.py +++ b/mopidy/backends/spotify/playlist_manager.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import datetime import logging @@ -14,90 +16,90 @@ class SpotifyPlaylistManager(PyspotifyPlaylistManager): def tracks_added(self, playlist, tracks, position, userdata): """Callback used by pyspotify""" logger.debug( - u'Callback called: ' - u'%d track(s) added to position %d in playlist "%s"', + 'Callback called: ' + '%d track(s) added to position %d in playlist "%s"', len(tracks), position, playlist.name()) - self.session_manager.refresh_stored_playlists() + self.session_manager.refresh_playlists() def tracks_moved(self, playlist, tracks, new_position, userdata): """Callback used by pyspotify""" logger.debug( - u'Callback called: ' - u'%d track(s) moved to position %d in playlist "%s"', + 'Callback called: ' + '%d track(s) moved to position %d in playlist "%s"', len(tracks), new_position, playlist.name()) - self.session_manager.refresh_stored_playlists() + self.session_manager.refresh_playlists() def tracks_removed(self, playlist, tracks, userdata): """Callback used by pyspotify""" logger.debug( - u'Callback called: ' - u'%d track(s) removed from playlist "%s"', + 'Callback called: ' + '%d track(s) removed from playlist "%s"', len(tracks), playlist.name()) - self.session_manager.refresh_stored_playlists() + self.session_manager.refresh_playlists() def playlist_renamed(self, playlist, userdata): """Callback used by pyspotify""" logger.debug( - u'Callback called: Playlist renamed to "%s"', playlist.name()) - self.session_manager.refresh_stored_playlists() + 'Callback called: Playlist renamed to "%s"', playlist.name()) + self.session_manager.refresh_playlists() def playlist_state_changed(self, playlist, userdata): """Callback used by pyspotify""" logger.debug( - u'Callback called: The state of playlist "%s" changed', + 'Callback called: The state of playlist "%s" changed', playlist.name()) def playlist_update_in_progress(self, playlist, done, userdata): """Callback used by pyspotify""" if done: logger.debug( - u'Callback called: Update of playlist "%s" done', + 'Callback called: Update of playlist "%s" done', playlist.name()) else: logger.debug( - u'Callback called: Update of playlist "%s" in progress', + 'Callback called: Update of playlist "%s" in progress', playlist.name()) def playlist_metadata_updated(self, playlist, userdata): """Callback used by pyspotify""" logger.debug( - u'Callback called: Metadata updated for playlist "%s"', + 'Callback called: Metadata updated for playlist "%s"', playlist.name()) def track_created_changed(self, playlist, position, user, when, userdata): """Callback used by pyspotify""" when = datetime.datetime.fromtimestamp(when) logger.debug( - u'Callback called: Created by/when for track %d in playlist ' - u'"%s" changed to user "N/A" and time "%s"', + 'Callback called: Created by/when for track %d in playlist ' + '"%s" changed to user "N/A" and time "%s"', position, playlist.name(), when) def track_message_changed(self, playlist, position, message, userdata): """Callback used by pyspotify""" logger.debug( - u'Callback called: Message for track %d in playlist ' - u'"%s" changed to "%s"', position, playlist.name(), message) + 'Callback called: Message for track %d in playlist ' + '"%s" changed to "%s"', position, playlist.name(), message) def track_seen_changed(self, playlist, position, seen, userdata): """Callback used by pyspotify""" logger.debug( - u'Callback called: Seen attribute for track %d in playlist ' - u'"%s" changed to "%s"', position, playlist.name(), seen) + 'Callback called: Seen attribute for track %d in playlist ' + '"%s" changed to "%s"', position, playlist.name(), seen) def description_changed(self, playlist, description, userdata): """Callback used by pyspotify""" logger.debug( - u'Callback called: Description changed for playlist "%s" to "%s"', + 'Callback called: Description changed for playlist "%s" to "%s"', playlist.name(), description) def subscribers_changed(self, playlist, userdata): """Callback used by pyspotify""" logger.debug( - u'Callback called: Subscribers changed for playlist "%s"', + 'Callback called: Subscribers changed for playlist "%s"', playlist.name()) def image_changed(self, playlist, image, userdata): """Callback used by pyspotify""" logger.debug( - u'Callback called: Image changed for playlist "%s"', + 'Callback called: Image changed for playlist "%s"', playlist.name()) diff --git a/mopidy/backends/spotify/stored_playlists.py b/mopidy/backends/spotify/playlists.py similarity index 60% rename from mopidy/backends/spotify/stored_playlists.py rename to mopidy/backends/spotify/playlists.py index 9a2328c4..2c31caa8 100644 --- a/mopidy/backends/spotify/stored_playlists.py +++ b/mopidy/backends/spotify/playlists.py @@ -1,11 +1,13 @@ +from __future__ import unicode_literals + from mopidy.backends import base -class SpotifyStoredPlaylistsProvider(base.BaseStoredPlaylistsProvider): +class SpotifyPlaylistsProvider(base.BasePlaylistsProvider): def create(self, name): pass # TODO - def delete(self, playlist): + def delete(self, uri): pass # TODO def lookup(self, uri): @@ -14,8 +16,5 @@ class SpotifyStoredPlaylistsProvider(base.BaseStoredPlaylistsProvider): def refresh(self): pass # TODO - def rename(self, playlist, new_name): - pass # TODO - def save(self, playlist): pass # TODO diff --git a/mopidy/backends/spotify/session_manager.py b/mopidy/backends/spotify/session_manager.py index 23b99d48..cd3d97db 100644 --- a/mopidy/backends/spotify/session_manager.py +++ b/mopidy/backends/spotify/session_manager.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import logging import os import threading @@ -50,14 +52,14 @@ class SpotifySessionManager(process.BaseThread, PyspotifySessionManager): def logged_in(self, session, error): """Callback used by pyspotify""" if error: - logger.error(u'Spotify login error: %s', error) + logger.error('Spotify login error: %s', error) return - logger.info(u'Connected to Spotify') + logger.info('Connected to Spotify') self.session = session logger.debug( - u'Preferred Spotify bitrate is %s kbps', + 'Preferred Spotify bitrate is %s kbps', settings.SPOTIFY_BITRATE) self.session.set_preferred_bitrate(BITRATES[settings.SPOTIFY_BITRATE]) @@ -70,30 +72,30 @@ class SpotifySessionManager(process.BaseThread, PyspotifySessionManager): def logged_out(self, session): """Callback used by pyspotify""" - logger.info(u'Disconnected from Spotify') + logger.info('Disconnected from Spotify') def metadata_updated(self, session): """Callback used by pyspotify""" - logger.debug(u'Callback called: Metadata updated') + logger.debug('Callback called: Metadata updated') def connection_error(self, session, error): """Callback used by pyspotify""" if error is None: - logger.info(u'Spotify connection OK') + logger.info('Spotify connection OK') else: - logger.error(u'Spotify connection error: %s', error) + logger.error('Spotify connection error: %s', error) self.backend.playback.pause() def message_to_user(self, session, message): """Callback used by pyspotify""" - logger.debug(u'User message: %s', message.strip()) + logger.debug('User message: %s', message.strip()) def music_delivery(self, session, frames, frame_size, num_frames, sample_type, sample_rate, channels): """Callback used by pyspotify""" # pylint: disable = R0913 # Too many arguments (8/5) - assert sample_type == 0, u'Expects 16-bit signed integer samples' + assert sample_type == 0, 'Expects 16-bit signed integer samples' capabilites = """ audio/x-raw-int, endianness=(int)1234, @@ -111,40 +113,39 @@ class SpotifySessionManager(process.BaseThread, PyspotifySessionManager): def play_token_lost(self, session): """Callback used by pyspotify""" - logger.debug(u'Play token lost') + logger.debug('Play token lost') self.backend.playback.pause() def log_message(self, session, data): """Callback used by pyspotify""" - logger.debug(u'System message: %s' % data.strip()) + logger.debug('System message: %s' % data.strip()) if 'offline-mgr' in data and 'files unlocked' in data: # XXX This is a very very fragile and ugly hack, but we get no # proper event when libspotify is done with initial data loading. - # We delay the expensive refresh of Mopidy's stored playlists until - # this message arrives. This way, we avoid doing the refresh once - # for every playlist or other change. This reduces the time from + # We delay the expensive refresh of Mopidy's playlists until this + # message arrives. This way, we avoid doing the refresh once for + # every playlist or other change. This reduces the time from # startup until the Spotify backend is ready from 35s to 12s in one # test with clean Spotify cache. In cases with an outdated cache - # the time improvements should be a lot better. + # the time improvements should be a lot greater. self._initial_data_receive_completed = True - self.refresh_stored_playlists() + self.refresh_playlists() def end_of_track(self, session): """Callback used by pyspotify""" - logger.debug(u'End of data stream reached') + logger.debug('End of data stream reached') self.audio.emit_end_of_stream() - def refresh_stored_playlists(self): - """Refresh the stored playlists in the backend with fresh meta data - from Spotify""" + def refresh_playlists(self): + """Refresh the playlists in the backend with data from Spotify""" if not self._initial_data_receive_completed: - logger.debug(u'Still getting data; skipped refresh of playlists') + logger.debug('Still getting data; skipped refresh of playlists') return playlists = map( translator.to_mopidy_playlist, self.session.playlist_container()) playlists = filter(None, playlists) - self.backend.stored_playlists.playlists = playlists - logger.info(u'Loaded %d Spotify playlist(s)', len(playlists)) + self.backend.playlists.playlists = playlists + logger.info('Loaded %d Spotify playlist(s)', len(playlists)) def search(self, query, queue): """Search method used by Mopidy backend""" @@ -161,6 +162,6 @@ class SpotifySessionManager(process.BaseThread, PyspotifySessionManager): def logout(self): """Log out from spotify""" - logger.debug(u'Logging out from Spotify') + logger.debug('Logging out from Spotify') if self.session: self.session.logout() diff --git a/mopidy/backends/spotify/translator.py b/mopidy/backends/spotify/translator.py index 4ad92fe9..834b34d8 100644 --- a/mopidy/backends/spotify/translator.py +++ b/mopidy/backends/spotify/translator.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from spotify import Link from mopidy import settings @@ -9,7 +11,7 @@ def to_mopidy_artist(spotify_artist): return uri = str(Link.from_artist(spotify_artist)) if not spotify_artist.is_loaded(): - return Artist(uri=uri, name=u'[loading...]') + return Artist(uri=uri, name='[loading...]') return Artist(uri=uri, name=spotify_artist.name()) @@ -18,7 +20,7 @@ def to_mopidy_album(spotify_album): return uri = str(Link.from_album(spotify_album)) if not spotify_album.is_loaded(): - return Album(uri=uri, name=u'[loading...]') + return Album(uri=uri, name='[loading...]') return Album( uri=uri, name=spotify_album.name(), @@ -31,7 +33,7 @@ def to_mopidy_track(spotify_track): return uri = str(Link.from_track(spotify_track, 0)) if not spotify_track.is_loaded(): - return Track(uri=uri, name=u'[loading...]') + return Track(uri=uri, name='[loading...]') spotify_album = spotify_track.album() if spotify_album is not None and spotify_album.is_loaded(): date = spotify_album.year() @@ -53,7 +55,7 @@ def to_mopidy_playlist(spotify_playlist): return uri = str(Link.from_playlist(spotify_playlist)) if not spotify_playlist.is_loaded(): - return Playlist(uri=uri, name=u'[loading...]') + return Playlist(uri=uri, name='[loading...]') return Playlist( uri=uri, name=spotify_playlist.name(), diff --git a/mopidy/core/__init__.py b/mopidy/core/__init__.py index 7fecfd79..f49bbbe7 100644 --- a/mopidy/core/__init__.py +++ b/mopidy/core/__init__.py @@ -1,7 +1,9 @@ +from __future__ import unicode_literals + # flake8: noqa from .actor import Core -from .current_playlist import CurrentPlaylistController from .library import LibraryController from .listener import CoreListener from .playback import PlaybackController, PlaybackState -from .stored_playlists import StoredPlaylistsController +from .playlists import PlaylistsController +from .tracklist import TracklistController diff --git a/mopidy/core/actor.py b/mopidy/core/actor.py index 482868ad..4307ffb1 100644 --- a/mopidy/core/actor.py +++ b/mopidy/core/actor.py @@ -1,20 +1,18 @@ +from __future__ import unicode_literals + import itertools import pykka from mopidy.audio import AudioListener -from .current_playlist import CurrentPlaylistController from .library import LibraryController from .playback import PlaybackController -from .stored_playlists import StoredPlaylistsController +from .playlists import PlaylistsController +from .tracklist import TracklistController class Core(pykka.ThreadingActor, AudioListener): - #: The current playlist controller. An instance of - #: :class:`mopidy.core.CurrentPlaylistController`. - current_playlist = None - #: The library controller. An instance of # :class:`mopidy.core.LibraryController`. library = None @@ -23,25 +21,29 @@ class Core(pykka.ThreadingActor, AudioListener): #: :class:`mopidy.core.PlaybackController`. playback = None - #: The stored playlists controller. An instance of - #: :class:`mopidy.core.StoredPlaylistsController`. - stored_playlists = None + #: The playlists controller. An instance of + #: :class:`mopidy.core.PlaylistsController`. + playlists = None + + #: The tracklist controller. An instance of + #: :class:`mopidy.core.TracklistController`. + tracklist = None def __init__(self, audio=None, backends=None): super(Core, self).__init__() self.backends = Backends(backends) - self.current_playlist = CurrentPlaylistController(core=self) - self.library = LibraryController(backends=self.backends, core=self) self.playback = PlaybackController( audio=audio, backends=self.backends, core=self) - self.stored_playlists = StoredPlaylistsController( + self.playlists = PlaylistsController( backends=self.backends, core=self) + self.tracklist = TracklistController(core=self) + @property def uri_schemes(self): """List of URI schemes we can handle""" @@ -58,10 +60,18 @@ class Backends(list): def __init__(self, backends): super(Backends, self).__init__(backends) + # These lists keeps the backends in the original order, but only + # includes those which implements the required backend provider. Since + # it is important to keep the order, we can't simply use .values() on + # the X_by_uri_scheme dicts below. + self.with_library = [b for b in backends if b.has_library().get()] + self.with_playback = [b for b in backends if b.has_playback().get()] + self.with_playlists = [b for b in backends + if b.has_playlists().get()] + self.by_uri_scheme = {} for backend in backends: - uri_schemes = backend.uri_schemes.get() - for uri_scheme in uri_schemes: + for uri_scheme in backend.uri_schemes.get(): assert uri_scheme not in self.by_uri_scheme, ( 'Cannot add URI scheme %s for %s, ' 'it is already handled by %s' @@ -69,3 +79,15 @@ class Backends(list): uri_scheme, backend.__class__.__name__, self.by_uri_scheme[uri_scheme].__class__.__name__) self.by_uri_scheme[uri_scheme] = backend + + self.with_library_by_uri_scheme = {} + self.with_playback_by_uri_scheme = {} + self.with_playlists_by_uri_scheme = {} + + for uri_scheme, backend in self.by_uri_scheme.items(): + if backend.has_library().get(): + self.with_library_by_uri_scheme[uri_scheme] = backend + if backend.has_playback().get(): + self.with_playback_by_uri_scheme[uri_scheme] = backend + if backend.has_playlists().get(): + self.with_playlists_by_uri_scheme[uri_scheme] = backend diff --git a/mopidy/core/library.py b/mopidy/core/library.py index f7514fd8..58263fd1 100644 --- a/mopidy/core/library.py +++ b/mopidy/core/library.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import itertools import urlparse @@ -15,7 +17,7 @@ class LibraryController(object): def _get_backend(self, uri): uri_scheme = urlparse.urlparse(uri).scheme - return self.backends.by_uri_scheme.get(uri_scheme, None) + return self.backends.with_library_by_uri_scheme.get(uri_scheme, None) def find_exact(self, **query): """ @@ -34,7 +36,8 @@ class LibraryController(object): :type query: dict :rtype: :class:`mopidy.models.Playlist` """ - futures = [b.library.find_exact(**query) for b in self.backends] + futures = [b.library.find_exact(**query) + for b in self.backends.with_library] results = pykka.get_all(futures) return Playlist(tracks=[ track for playlist in results for track in playlist.tracks]) @@ -65,7 +68,8 @@ class LibraryController(object): if backend: backend.library.refresh(uri).get() else: - futures = [b.library.refresh(uri) for b in self.backends] + futures = [b.library.refresh(uri) + for b in self.backends.with_library] pykka.get_all(futures) def search(self, **query): @@ -85,7 +89,8 @@ class LibraryController(object): :type query: dict :rtype: :class:`mopidy.models.Playlist` """ - futures = [b.library.search(**query) for b in self.backends] + futures = [b.library.search(**query) + for b in self.backends.with_library] results = pykka.get_all(futures) track_lists = [playlist.tracks for playlist in results] tracks = list(itertools.chain(*track_lists)) diff --git a/mopidy/core/listener.py b/mopidy/core/listener.py index ed7dae2f..9c8bf4bc 100644 --- a/mopidy/core/listener.py +++ b/mopidy/core/listener.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import pykka diff --git a/mopidy/core/playback.py b/mopidy/core/playback.py index 74f4bebd..54364ec2 100644 --- a/mopidy/core/playback.py +++ b/mopidy/core/playback.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import logging import random import urlparse @@ -28,13 +30,13 @@ class PlaybackState(object): """ #: Constant representing the paused state. - PAUSED = u'paused' + PAUSED = 'paused' #: Constant representing the playing state. - PLAYING = u'playing' + PLAYING = 'playing' #: Constant representing the stopped state. - STOPPED = u'stopped' + STOPPED = 'stopped' class PlaybackController(object): @@ -51,9 +53,9 @@ class PlaybackController(object): #: The currently playing or selected track. #: - #: A two-tuple of (CPID integer, :class:`mopidy.models.Track`) or + #: A two-tuple of (TLID integer, :class:`mopidy.models.Track`) or #: :class:`None`. - current_cp_track = None + current_tl_track = None #: :class:`True` #: Tracks are selected at random from the playlist. @@ -86,53 +88,52 @@ class PlaybackController(object): self._volume = None def _get_backend(self): - if self.current_cp_track is None: + if self.current_tl_track is None: return None - uri = self.current_cp_track.track.uri + uri = self.current_tl_track.track.uri uri_scheme = urlparse.urlparse(uri).scheme - return self.backends.by_uri_scheme[uri_scheme] + return self.backends.with_playback_by_uri_scheme.get(uri_scheme, None) - def _get_cpid(self, cp_track): - if cp_track is None: + def _get_tlid(self, tl_track): + if tl_track is None: return None - return cp_track.cpid + return tl_track.tlid - def _get_track(self, cp_track): - if cp_track is None: + def _get_track(self, tl_track): + if tl_track is None: return None - return cp_track.track + return tl_track.track @property - def current_cpid(self): + def current_tlid(self): """ - The CPID (current playlist ID) of the currently playing or selected + The TLID (tracklist ID) of the currently playing or selected track. - Read-only. Extracted from :attr:`current_cp_track` for convenience. + Read-only. Extracted from :attr:`current_tl_track` for convenience. """ - return self._get_cpid(self.current_cp_track) + return self._get_tlid(self.current_tl_track) @property def current_track(self): """ The currently playing or selected :class:`mopidy.models.Track`. - Read-only. Extracted from :attr:`current_cp_track` for convenience. + Read-only. Extracted from :attr:`current_tl_track` for convenience. """ - return self._get_track(self.current_cp_track) + return self._get_track(self.current_tl_track) @property - def current_playlist_position(self): + def tracklist_position(self): """ - The position of the current track in the current playlist. + The position of the current track in the tracklist. Read-only. """ - if self.current_cp_track is None: + if self.current_tl_track is None: return None try: - return self.core.current_playlist.cp_tracks.index( - self.current_cp_track) + return self.core.tracklist.tl_tracks.index(self.current_tl_track) except ValueError: return None @@ -142,49 +143,48 @@ class PlaybackController(object): The track that will be played at the end of the current track. Read-only. A :class:`mopidy.models.Track` extracted from - :attr:`cp_track_at_eot` for convenience. + :attr:`tl_track_at_eot` for convenience. """ - return self._get_track(self.cp_track_at_eot) + return self._get_track(self.tl_track_at_eot) @property - def cp_track_at_eot(self): + def tl_track_at_eot(self): """ The track that will be played at the end of the current track. - Read-only. A two-tuple of (CPID integer, :class:`mopidy.models.Track`). + Read-only. A two-tuple of (TLID integer, :class:`mopidy.models.Track`). - Not necessarily the same track as :attr:`cp_track_at_next`. + Not necessarily the same track as :attr:`tl_track_at_next`. """ # pylint: disable = R0911 # Too many return statements - cp_tracks = self.core.current_playlist.cp_tracks + tl_tracks = self.core.tracklist.tl_tracks - if not cp_tracks: + if not tl_tracks: return None if self.random and not self._shuffled: if self.repeat or self._first_shuffle: logger.debug('Shuffling tracks') - self._shuffled = cp_tracks + self._shuffled = tl_tracks random.shuffle(self._shuffled) self._first_shuffle = False if self.random and self._shuffled: return self._shuffled[0] - if self.current_cp_track is None: - return cp_tracks[0] + if self.current_tl_track is None: + return tl_tracks[0] if self.repeat and self.single: - return cp_tracks[self.current_playlist_position] + return tl_tracks[self.tracklist_position] if self.repeat and not self.single: - return cp_tracks[ - (self.current_playlist_position + 1) % len(cp_tracks)] + return tl_tracks[(self.tracklist_position + 1) % len(tl_tracks)] try: - return cp_tracks[self.current_playlist_position + 1] + return tl_tracks[self.tracklist_position + 1] except IndexError: return None @@ -194,46 +194,45 @@ class PlaybackController(object): The track that will be played if calling :meth:`next()`. Read-only. A :class:`mopidy.models.Track` extracted from - :attr:`cp_track_at_next` for convenience. + :attr:`tl_track_at_next` for convenience. """ - return self._get_track(self.cp_track_at_next) + return self._get_track(self.tl_track_at_next) @property - def cp_track_at_next(self): + def tl_track_at_next(self): """ The track that will be played if calling :meth:`next()`. - Read-only. A two-tuple of (CPID integer, :class:`mopidy.models.Track`). + Read-only. A two-tuple of (TLID integer, :class:`mopidy.models.Track`). For normal playback this is the next track in the playlist. If repeat is enabled the next track can loop around the playlist. When random is enabled this should be a random track, all tracks should be played once before the list repeats. """ - cp_tracks = self.core.current_playlist.cp_tracks + tl_tracks = self.core.tracklist.tl_tracks - if not cp_tracks: + if not tl_tracks: return None if self.random and not self._shuffled: if self.repeat or self._first_shuffle: logger.debug('Shuffling tracks') - self._shuffled = cp_tracks + self._shuffled = tl_tracks random.shuffle(self._shuffled) self._first_shuffle = False if self.random and self._shuffled: return self._shuffled[0] - if self.current_cp_track is None: - return cp_tracks[0] + if self.current_tl_track is None: + return tl_tracks[0] if self.repeat: - return cp_tracks[ - (self.current_playlist_position + 1) % len(cp_tracks)] + return tl_tracks[(self.tracklist_position + 1) % len(tl_tracks)] try: - return cp_tracks[self.current_playlist_position + 1] + return tl_tracks[self.tracklist_position + 1] except IndexError: return None @@ -243,29 +242,28 @@ class PlaybackController(object): The track that will be played if calling :meth:`previous()`. Read-only. A :class:`mopidy.models.Track` extracted from - :attr:`cp_track_at_previous` for convenience. + :attr:`tl_track_at_previous` for convenience. """ - return self._get_track(self.cp_track_at_previous) + return self._get_track(self.tl_track_at_previous) @property - def cp_track_at_previous(self): + def tl_track_at_previous(self): """ The track that will be played if calling :meth:`previous()`. - A two-tuple of (CPID integer, :class:`mopidy.models.Track`). + A two-tuple of (TLID integer, :class:`mopidy.models.Track`). For normal playback this is the previous track in the playlist. If random and/or consume is enabled it should return the current track instead. """ if self.repeat or self.consume or self.random: - return self.current_cp_track + return self.current_tl_track - if self.current_playlist_position in (None, 0): + if self.tracklist_position in (None, 0): return None - return self.core.current_playlist.cp_tracks[ - self.current_playlist_position - 1] + return self.core.tracklist.tl_tracks[self.tracklist_position - 1] @property def state(self): @@ -290,7 +288,7 @@ class PlaybackController(object): @state.setter # noqa def state(self, new_state): (old_state, self._state) = (self.state, new_state) - logger.debug(u'Changing state: %s -> %s', old_state, new_state) + logger.debug('Changing state: %s -> %s', old_state, new_state) self._trigger_playback_state_changed(old_state, new_state) @@ -298,9 +296,10 @@ class PlaybackController(object): def time_position(self): """Time position in milliseconds.""" backend = self._get_backend() - if backend is None: + if backend: + return backend.playback.get_time_position().get() + else: return 0 - return backend.playback.get_time_position().get() @property def volume(self): @@ -319,12 +318,12 @@ class PlaybackController(object): # For testing self._volume = volume - def change_track(self, cp_track, on_error_step=1): + def change_track(self, tl_track, on_error_step=1): """ Change to the given track, keeping the current playback state. - :param cp_track: track to change to - :type cp_track: two-tuple (CPID integer, :class:`mopidy.models.Track`) + :param tl_track: track to change to + :type tl_track: two-tuple (TLID integer, :class:`mopidy.models.Track`) or :class:`None` :param on_error_step: direction to step at play error, 1 for next track (default), -1 for previous track @@ -333,7 +332,7 @@ class PlaybackController(object): """ old_state = self.state self.stop() - self.current_cp_track = cp_track + self.current_tl_track = tl_track if old_state == PlaybackState.PLAYING: self.play(on_error_step=on_error_step) elif old_state == PlaybackState.PAUSED: @@ -346,18 +345,18 @@ class PlaybackController(object): if self.state == PlaybackState.STOPPED: return - original_cp_track = self.current_cp_track + original_tl_track = self.current_tl_track - if self.cp_track_at_eot: + if self.tl_track_at_eot: self._trigger_track_playback_ended() - self.play(self.cp_track_at_eot) + self.play(self.tl_track_at_eot) else: self.stop(clear_current_track=True) if self.consume: - self.core.current_playlist.remove(cpid=original_cp_track.cpid) + self.core.tracklist.remove(tlid=original_tl_track.tlid) - def on_current_playlist_change(self): + def on_tracklist_change(self): """ Tell the playback controller that the current playlist has changed. @@ -366,9 +365,9 @@ class PlaybackController(object): self._first_shuffle = True self._shuffled = [] - if (not self.core.current_playlist.cp_tracks or - self.current_cp_track not in - self.core.current_playlist.cp_tracks): + if (not self.core.tracklist.tl_tracks or + self.current_tl_track not in + self.core.tracklist.tl_tracks): self.stop(clear_current_track=True) def next(self): @@ -378,58 +377,59 @@ class PlaybackController(object): The current playback state will be kept. If it was playing, playing will continue. If it was paused, it will still be paused, etc. """ - if self.cp_track_at_next: + if self.tl_track_at_next: self._trigger_track_playback_ended() - self.change_track(self.cp_track_at_next) + self.change_track(self.tl_track_at_next) else: self.stop(clear_current_track=True) def pause(self): """Pause playback.""" backend = self._get_backend() - if backend is None or backend.playback.pause().get(): + if not backend or backend.playback.pause().get(): self.state = PlaybackState.PAUSED self._trigger_track_playback_paused() - def play(self, cp_track=None, on_error_step=1): + def play(self, tl_track=None, on_error_step=1): """ Play the given track, or if the given track is :class:`None`, play the currently active track. - :param cp_track: track to play - :type cp_track: two-tuple (CPID integer, :class:`mopidy.models.Track`) + :param tl_track: track to play + :type tl_track: two-tuple (TLID integer, :class:`mopidy.models.Track`) or :class:`None` :param on_error_step: direction to step at play error, 1 for next track (default), -1 for previous track :type on_error_step: int, -1 or 1 """ - if cp_track is not None: - assert cp_track in self.core.current_playlist.cp_tracks - elif cp_track is None: + if tl_track is not None: + assert tl_track in self.core.tracklist.tl_tracks + elif tl_track is None: if self.state == PlaybackState.PAUSED: return self.resume() - elif self.current_cp_track is not None: - cp_track = self.current_cp_track - elif self.current_cp_track is None and on_error_step == 1: - cp_track = self.cp_track_at_next - elif self.current_cp_track is None and on_error_step == -1: - cp_track = self.cp_track_at_previous + elif self.current_tl_track is not None: + tl_track = self.current_tl_track + elif self.current_tl_track is None and on_error_step == 1: + tl_track = self.tl_track_at_next + elif self.current_tl_track is None and on_error_step == -1: + tl_track = self.tl_track_at_previous - if cp_track is not None: - self.current_cp_track = cp_track + if tl_track is not None: + self.current_tl_track = tl_track self.state = PlaybackState.PLAYING - if not self._get_backend().playback.play(cp_track.track).get(): + backend = self._get_backend() + if not backend or not backend.playback.play(tl_track.track).get(): # Track is not playable if self.random and self._shuffled: - self._shuffled.remove(cp_track) + self._shuffled.remove(tl_track) if on_error_step == 1: self.next() elif on_error_step == -1: self.previous() - if self.random and self.current_cp_track in self._shuffled: - self._shuffled.remove(self.current_cp_track) + if self.random and self.current_tl_track in self._shuffled: + self._shuffled.remove(self.current_tl_track) self._trigger_track_playback_started() @@ -441,12 +441,14 @@ class PlaybackController(object): will continue. If it was paused, it will still be paused, etc. """ self._trigger_track_playback_ended() - self.change_track(self.cp_track_at_previous, on_error_step=-1) + self.change_track(self.tl_track_at_previous, on_error_step=-1) def resume(self): """If paused, resume playing the current track.""" - if (self.state == PlaybackState.PAUSED and - self._get_backend().playback.resume().get()): + if self.state != PlaybackState.PAUSED: + return + backend = self._get_backend() + if backend and backend.playback.resume().get(): self.state = PlaybackState.PLAYING self._trigger_track_playback_resumed() @@ -458,7 +460,7 @@ class PlaybackController(object): :type time_position: int :rtype: :class:`True` if successful, else :class:`False` """ - if not self.core.current_playlist.tracks: + if not self.core.tracklist.tracks: return False if self.state == PlaybackState.STOPPED: @@ -472,7 +474,11 @@ class PlaybackController(object): self.next() return True - success = self._get_backend().playback.seek(time_position).get() + backend = self._get_backend() + if not backend: + return False + + success = backend.playback.seek(time_position).get() if success: self._trigger_seeked(time_position) return success @@ -486,14 +492,15 @@ class PlaybackController(object): :type clear_current_track: boolean """ if self.state != PlaybackState.STOPPED: - if self._get_backend().playback.stop().get(): + backend = self._get_backend() + if not backend or backend.playback.stop().get(): self._trigger_track_playback_ended() self.state = PlaybackState.STOPPED if clear_current_track: - self.current_cp_track = None + self.current_tl_track = None def _trigger_track_playback_paused(self): - logger.debug(u'Triggering track playback paused event') + logger.debug('Triggering track playback paused event') if self.current_track is None: return listener.CoreListener.send( @@ -501,7 +508,7 @@ class PlaybackController(object): track=self.current_track, time_position=self.time_position) def _trigger_track_playback_resumed(self): - logger.debug(u'Triggering track playback resumed event') + logger.debug('Triggering track playback resumed event') if self.current_track is None: return listener.CoreListener.send( @@ -509,14 +516,14 @@ class PlaybackController(object): track=self.current_track, time_position=self.time_position) def _trigger_track_playback_started(self): - logger.debug(u'Triggering track playback started event') + logger.debug('Triggering track playback started event') if self.current_track is None: return listener.CoreListener.send( 'track_playback_started', track=self.current_track) def _trigger_track_playback_ended(self): - logger.debug(u'Triggering track playback ended event') + logger.debug('Triggering track playback ended event') if self.current_track is None: return listener.CoreListener.send( @@ -524,15 +531,15 @@ class PlaybackController(object): track=self.current_track, time_position=self.time_position) def _trigger_playback_state_changed(self, old_state, new_state): - logger.debug(u'Triggering playback state change event') + logger.debug('Triggering playback state change event') listener.CoreListener.send( 'playback_state_changed', old_state=old_state, new_state=new_state) def _trigger_options_changed(self): - logger.debug(u'Triggering options changed event') + logger.debug('Triggering options changed event') listener.CoreListener.send('options_changed') def _trigger_seeked(self, time_position): - logger.debug(u'Triggering seeked event') + logger.debug('Triggering seeked event') listener.CoreListener.send('seeked', time_position=time_position) diff --git a/mopidy/core/stored_playlists.py b/mopidy/core/playlists.py similarity index 75% rename from mopidy/core/stored_playlists.py rename to mopidy/core/playlists.py index 8c04d5ad..069150e5 100644 --- a/mopidy/core/stored_playlists.py +++ b/mopidy/core/playlists.py @@ -1,10 +1,12 @@ +from __future__ import unicode_literals + import itertools import urlparse import pykka -class StoredPlaylistsController(object): +class PlaylistsController(object): pykka_traversable = True def __init__(self, backends, core): @@ -14,11 +16,12 @@ class StoredPlaylistsController(object): @property def playlists(self): """ - Currently stored playlists. + The available playlists. Read-only. List of :class:`mopidy.models.Playlist`. """ - futures = [b.stored_playlists.playlists for b in self.backends] + futures = [b.playlists.playlists + for b in self.backends.with_playlists] results = pykka.get_all(futures) return list(itertools.chain(*results)) @@ -40,11 +43,11 @@ class StoredPlaylistsController(object): :type uri_scheme: string :rtype: :class:`mopidy.models.Playlist` """ - if uri_scheme in self.backends.by_uri_scheme: + if uri_scheme in self.backends.with_playlists_by_uri_scheme: backend = self.backends.by_uri_scheme[uri_scheme] else: - backend = self.backends[0] - return backend.stored_playlists.create(name).get() + backend = self.backends.with_playlists[0] + return backend.playlists.create(name).get() def delete(self, uri): """ @@ -57,13 +60,14 @@ class StoredPlaylistsController(object): :type uri: string """ uri_scheme = urlparse.urlparse(uri).scheme - if uri_scheme in self.backends.by_uri_scheme: - backend = self.backends.by_uri_scheme[uri_scheme] - backend.stored_playlists.delete(uri).get() + backend = self.backends.with_playlists_by_uri_scheme.get( + uri_scheme, None) + if backend: + backend.playlists.delete(uri).get() def get(self, **criteria): """ - Get playlist by given criterias from the set of stored playlists. + Get playlist by given criterias from the set of playlists. Raises :exc:`LookupError` if a unique match is not found. @@ -93,23 +97,24 @@ class StoredPlaylistsController(object): def lookup(self, uri): """ - Lookup playlist with given URI in both the set of stored playlists and - in any other playlist sources. Returns :class:`None` if not found. + Lookup playlist with given URI in both the set of playlists and in any + other playlist sources. Returns :class:`None` if not found. :param uri: playlist URI :type uri: string :rtype: :class:`mopidy.models.Playlist` or :class:`None` """ uri_scheme = urlparse.urlparse(uri).scheme - backend = self.backends.by_uri_scheme.get(uri_scheme, None) + backend = self.backends.with_playlists_by_uri_scheme.get( + uri_scheme, None) if backend: - return backend.stored_playlists.lookup(uri).get() + return backend.playlists.lookup(uri).get() else: return None def refresh(self, uri_scheme=None): """ - Refresh the stored playlists in :attr:`playlists`. + Refresh the playlists in :attr:`playlists`. If ``uri_scheme`` is :class:`None`, all backends are asked to refresh. If ``uri_scheme`` is an URI scheme handled by a backend, only that @@ -120,16 +125,18 @@ class StoredPlaylistsController(object): :type uri_scheme: string """ if uri_scheme is None: - futures = [b.stored_playlists.refresh() for b in self.backends] + futures = [b.playlists.refresh() + for b in self.backends.with_playlists] pykka.get_all(futures) else: - if uri_scheme in self.backends.by_uri_scheme: - backend = self.backends.by_uri_scheme[uri_scheme] - backend.stored_playlists.refresh().get() + backend = self.backends.with_playlists_by_uri_scheme.get( + uri_scheme, None) + if backend: + backend.playlists.refresh().get() def save(self, playlist): """ - Save the playlist to the set of stored playlists. + Save the playlist. For a playlist to be saveable, it must have the ``uri`` attribute set. You should not set the ``uri`` atribute yourself, but use playlist @@ -152,7 +159,7 @@ class StoredPlaylistsController(object): if playlist.uri is None: return uri_scheme = urlparse.urlparse(playlist.uri).scheme - if uri_scheme not in self.backends.by_uri_scheme: - return - backend = self.backends.by_uri_scheme[uri_scheme] - return backend.stored_playlists.save(playlist).get() + backend = self.backends.with_playlists_by_uri_scheme.get( + uri_scheme, None) + if backend: + return backend.playlists.save(playlist).get() diff --git a/mopidy/core/current_playlist.py b/mopidy/core/tracklist.py similarity index 69% rename from mopidy/core/current_playlist.py rename to mopidy/core/tracklist.py index fb296a52..529d2a7a 100644 --- a/mopidy/core/current_playlist.py +++ b/mopidy/core/tracklist.py @@ -1,8 +1,10 @@ +from __future__ import unicode_literals + from copy import copy import logging import random -from mopidy.models import CpTrack +from mopidy.models import TlTrack from . import listener @@ -10,23 +12,23 @@ from . import listener logger = logging.getLogger('mopidy.core') -class CurrentPlaylistController(object): +class TracklistController(object): pykka_traversable = True def __init__(self, core): self.core = core - self.cp_id = 0 - self._cp_tracks = [] + self.tlid = 0 + self._tl_tracks = [] self._version = 0 @property - def cp_tracks(self): + def tl_tracks(self): """ - List of two-tuples of (CPID integer, :class:`mopidy.models.Track`). + List of two-tuples of (TLID integer, :class:`mopidy.models.Track`). Read-only. """ - return [copy(cp_track) for cp_track in self._cp_tracks] + return [copy(tl_track) for tl_track in self._tl_tracks] @property def tracks(self): @@ -35,14 +37,14 @@ class CurrentPlaylistController(object): Read-only. """ - return [cp_track.track for cp_track in self._cp_tracks] + return [tl_track.track for tl_track in self._tl_tracks] @property def length(self): """ Length of the current playlist. """ - return len(self._cp_tracks) + return len(self._tl_tracks) @property def version(self): @@ -55,7 +57,7 @@ class CurrentPlaylistController(object): @version.setter # noqa def version(self, version): self._version = version - self.core.playback.on_current_playlist_change() + self.core.playback.on_tracklist_change() self._trigger_playlist_changed() def add(self, track, at_position=None, increase_version=True): @@ -69,20 +71,20 @@ class CurrentPlaylistController(object): :type at_position: int or :class:`None` :param increase_version: if the playlist version should be increased :type increase_version: :class:`True` or :class:`False` - :rtype: two-tuple of (CPID integer, :class:`mopidy.models.Track`) that + :rtype: two-tuple of (TLID integer, :class:`mopidy.models.Track`) that was added to the current playlist playlist """ - assert at_position <= len(self._cp_tracks), \ - u'at_position can not be greater than playlist length' - cp_track = CpTrack(self.cp_id, track) + assert at_position <= len(self._tl_tracks), \ + 'at_position can not be greater than playlist length' + tl_track = TlTrack(self.tlid, track) if at_position is not None: - self._cp_tracks.insert(at_position, cp_track) + self._tl_tracks.insert(at_position, tl_track) else: - self._cp_tracks.append(cp_track) + self._tl_tracks.append(tl_track) if increase_version: self.version += 1 - self.cp_id += 1 - return cp_track + self.tlid += 1 + return tl_track def append(self, tracks): """ @@ -99,7 +101,7 @@ class CurrentPlaylistController(object): def clear(self): """Clear the current playlist.""" - self._cp_tracks = [] + self._tl_tracks = [] self.version += 1 def get(self, **criteria): @@ -110,7 +112,7 @@ class CurrentPlaylistController(object): Examples:: - get(cpid=7) # Returns track with CPID 7 + get(tlid=7) # Returns track with TLID 7 # (current playlist ID) get(id=1) # Returns track with ID 1 get(uri='xyz') # Returns track with URI 'xyz' @@ -118,12 +120,12 @@ class CurrentPlaylistController(object): :param criteria: on or more criteria to match by :type criteria: dict - :rtype: two-tuple (CPID integer, :class:`mopidy.models.Track`) + :rtype: two-tuple (TLID integer, :class:`mopidy.models.Track`) """ - matches = self._cp_tracks + matches = self._tl_tracks for (key, value) in criteria.iteritems(): - if key == 'cpid': - matches = filter(lambda ct: ct.cpid == value, matches) + if key == 'tlid': + matches = filter(lambda ct: ct.tlid == value, matches) else: matches = filter( lambda ct: getattr(ct.track, key) == value, matches) @@ -132,22 +134,22 @@ class CurrentPlaylistController(object): criteria_string = ', '.join( ['%s=%s' % (k, v) for (k, v) in criteria.iteritems()]) if len(matches) == 0: - raise LookupError(u'"%s" match no tracks' % criteria_string) + raise LookupError('"%s" match no tracks' % criteria_string) else: - raise LookupError(u'"%s" match multiple tracks' % criteria_string) + raise LookupError('"%s" match multiple tracks' % criteria_string) - def index(self, cp_track): + def index(self, tl_track): """ - Get index of the given (CPID integer, :class:`mopidy.models.Track`) + Get index of the given (TLID integer, :class:`mopidy.models.Track`) two-tuple in the current playlist. Raises :exc:`ValueError` if not found. - :param cp_track: track to find the index of - :type cp_track: two-tuple (CPID integer, :class:`mopidy.models.Track`) + :param tl_track: track to find the index of + :type tl_track: two-tuple (TLID integer, :class:`mopidy.models.Track`) :rtype: int """ - return self._cp_tracks.index(cp_track) + return self._tl_tracks.index(tl_track) def move(self, start, end, to_position): """ @@ -163,21 +165,21 @@ class CurrentPlaylistController(object): if start == end: end += 1 - cp_tracks = self._cp_tracks + tl_tracks = self._tl_tracks assert start < end, 'start must be smaller than end' assert start >= 0, 'start must be at least zero' - assert end <= len(cp_tracks), \ + assert end <= len(tl_tracks), \ 'end can not be larger than playlist length' assert to_position >= 0, 'to_position must be at least zero' - assert to_position <= len(cp_tracks), \ + assert to_position <= len(tl_tracks), \ 'to_position can not be larger than playlist length' - new_cp_tracks = cp_tracks[:start] + cp_tracks[end:] - for cp_track in cp_tracks[start:end]: - new_cp_tracks.insert(to_position, cp_track) + new_tl_tracks = tl_tracks[:start] + tl_tracks[end:] + for tl_track in tl_tracks[start:end]: + new_tl_tracks.insert(to_position, tl_track) to_position += 1 - self._cp_tracks = new_cp_tracks + self._tl_tracks = new_tl_tracks self.version += 1 def remove(self, **criteria): @@ -189,9 +191,9 @@ class CurrentPlaylistController(object): :param criteria: on or more criteria to match by :type criteria: dict """ - cp_track = self.get(**criteria) - position = self._cp_tracks.index(cp_track) - del self._cp_tracks[position] + tl_track = self.get(**criteria) + position = self._tl_tracks.index(tl_track) + del self._tl_tracks[position] self.version += 1 def shuffle(self, start=None, end=None): @@ -204,7 +206,7 @@ class CurrentPlaylistController(object): :param end: position after last track to shuffle :type end: int or :class:`None` """ - cp_tracks = self._cp_tracks + tl_tracks = self._tl_tracks if start is not None and end is not None: assert start < end, 'start must be smaller than end' @@ -213,14 +215,14 @@ class CurrentPlaylistController(object): assert start >= 0, 'start must be at least zero' if end is not None: - assert end <= len(cp_tracks), 'end can not be larger than ' + \ + assert end <= len(tl_tracks), 'end can not be larger than ' + \ 'playlist length' - before = cp_tracks[:start or 0] - shuffled = cp_tracks[start:end] - after = cp_tracks[end or len(cp_tracks):] + before = tl_tracks[:start or 0] + shuffled = tl_tracks[start:end] + after = tl_tracks[end or len(tl_tracks):] random.shuffle(shuffled) - self._cp_tracks = before + shuffled + after + self._tl_tracks = before + shuffled + after self.version += 1 def slice(self, start, end): @@ -232,10 +234,10 @@ class CurrentPlaylistController(object): :type start: int :param end: position after last track to include in slice :type end: int - :rtype: two-tuple of (CPID integer, :class:`mopidy.models.Track`) + :rtype: two-tuple of (TLID integer, :class:`mopidy.models.Track`) """ - return [copy(cp_track) for cp_track in self._cp_tracks[start:end]] + return [copy(tl_track) for tl_track in self._tl_tracks[start:end]] def _trigger_playlist_changed(self): - logger.debug(u'Triggering playlist changed event') + logger.debug('Triggering playlist changed event') listener.CoreListener.send('playlist_changed') diff --git a/mopidy/exceptions.py b/mopidy/exceptions.py index 6e0c575e..b8d183fb 100644 --- a/mopidy/exceptions.py +++ b/mopidy/exceptions.py @@ -1,3 +1,6 @@ +from __future__ import unicode_literals + + class MopidyException(Exception): def __init__(self, message, *args, **kwargs): super(MopidyException, self).__init__(message, *args, **kwargs) diff --git a/mopidy/frontends/__init__.py b/mopidy/frontends/__init__.py index e69de29b..baffc488 100644 --- a/mopidy/frontends/__init__.py +++ b/mopidy/frontends/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/mopidy/frontends/http/api.py b/mopidy/frontends/http/api.py index 1c0aa85b..caaf69e2 100644 --- a/mopidy/frontends/http/api.py +++ b/mopidy/frontends/http/api.py @@ -65,16 +65,16 @@ class TrackListResource(object): @cherrypy.tools.json_out() def GET(self): - cp_tracks_future = self.core.current_playlist.cp_tracks - current_cp_track_future = self.core.playback.current_cp_track + tl_tracks_future = self.core.tracklist.tl_tracks + current_tl_track_future = self.core.playback.current_tl_track tracks = [] - for cp_track in cp_tracks_future.get(): - track = cp_track.track.serialize() - track['cpid'] = cp_track.cpid + for tl_track in tl_tracks_future.get(): + track = tl_track.track.serialize() + track['tlid'] = tl_track.tlid tracks.append(track) - current_cp_track = current_cp_track_future.get() + current_tl_track = current_tl_track_future.get() return { - 'currentTrackCpid': current_cp_track and current_cp_track.cpid, + 'currentTrackTlid': current_tl_track and current_tl_track.tlid, 'tracks': tracks, } @@ -87,7 +87,7 @@ class PlaylistsResource(object): @cherrypy.tools.json_out() def GET(self): - playlists = self.core.stored_playlists.playlists.get() + playlists = self.core.playlists.playlists.get() return { 'playlists': [p.serialize() for p in playlists], } diff --git a/mopidy/frontends/lastfm.py b/mopidy/frontends/lastfm.py index aaf55ec1..7f367262 100644 --- a/mopidy/frontends/lastfm.py +++ b/mopidy/frontends/lastfm.py @@ -22,6 +22,8 @@ Make sure :attr:`mopidy.settings.FRONTENDS` includes the Last.fm frontend. """ +from __future__ import unicode_literals + import logging import time @@ -54,21 +56,21 @@ class LastfmFrontend(pykka.ThreadingActor, CoreListener): self.lastfm = pylast.LastFMNetwork( api_key=API_KEY, api_secret=API_SECRET, username=username, password_hash=password_hash) - logger.info(u'Connected to Last.fm') + logger.info('Connected to Last.fm') except exceptions.SettingsError as e: - logger.info(u'Last.fm scrobbler not started') - logger.debug(u'Last.fm settings error: %s', e) + logger.info('Last.fm scrobbler not started') + logger.debug('Last.fm settings error: %s', e) self.stop() except (pylast.NetworkError, pylast.MalformedResponseError, pylast.WSError) as e: - logger.error(u'Error during Last.fm setup: %s', e) + logger.error('Error during Last.fm setup: %s', e) self.stop() def track_playback_started(self, track): artists = ', '.join([a.name for a in track.artists]) duration = track.length and track.length // 1000 or 0 self.last_start_time = int(time.time()) - logger.debug(u'Now playing track: %s - %s', artists, track.name) + logger.debug('Now playing track: %s - %s', artists, track.name) try: self.lastfm.update_now_playing( artists, @@ -79,22 +81,22 @@ class LastfmFrontend(pykka.ThreadingActor, CoreListener): mbid=(track.musicbrainz_id or '')) except (pylast.ScrobblingError, pylast.NetworkError, pylast.MalformedResponseError, pylast.WSError) as e: - logger.warning(u'Error submitting playing track to Last.fm: %s', e) + logger.warning('Error submitting playing track to Last.fm: %s', e) def track_playback_ended(self, track, time_position): artists = ', '.join([a.name for a in track.artists]) duration = track.length and track.length // 1000 or 0 time_position = time_position // 1000 if duration < 30: - logger.debug(u'Track too short to scrobble. (30s)') + logger.debug('Track too short to scrobble. (30s)') return if time_position < duration // 2 and time_position < 240: logger.debug( - u'Track not played long enough to scrobble. (50% or 240s)') + 'Track not played long enough to scrobble. (50% or 240s)') return if self.last_start_time is None: self.last_start_time = int(time.time()) - duration - logger.debug(u'Scrobbling track: %s - %s', artists, track.name) + logger.debug('Scrobbling track: %s - %s', artists, track.name) try: self.lastfm.scrobble( artists, @@ -106,4 +108,4 @@ class LastfmFrontend(pykka.ThreadingActor, CoreListener): mbid=(track.musicbrainz_id or '')) except (pylast.ScrobblingError, pylast.NetworkError, pylast.MalformedResponseError, pylast.WSError) as e: - logger.warning(u'Error submitting played track to Last.fm: %s', e) + logger.warning('Error submitting played track to Last.fm: %s', e) diff --git a/mopidy/frontends/mpd/__init__.py b/mopidy/frontends/mpd/__init__.py index a6cfd386..572192ef 100644 --- a/mopidy/frontends/mpd/__init__.py +++ b/mopidy/frontends/mpd/__init__.py @@ -21,5 +21,7 @@ Make sure :attr:`mopidy.settings.FRONTENDS` includes frontend. """ +from __future__ import unicode_literals + # flake8: noqa from .actor import MpdFrontend diff --git a/mopidy/frontends/mpd/actor.py b/mopidy/frontends/mpd/actor.py index e136ddee..3ba6378c 100644 --- a/mopidy/frontends/mpd/actor.py +++ b/mopidy/frontends/mpd/actor.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import logging import sys @@ -24,11 +26,11 @@ class MpdFrontend(pykka.ThreadingActor, CoreListener): max_connections=settings.MPD_SERVER_MAX_CONNECTIONS) except IOError as error: logger.error( - u'MPD server startup failed: %s', + 'MPD server startup failed: %s', encoding.locale_decode(error)) sys.exit(1) - logger.info(u'MPD server running at [%s]:%s', hostname, port) + logger.info('MPD server running at [%s]:%s', hostname, port) def on_stop(self): process.stop_actors_by_class(session.MpdSession) diff --git a/mopidy/frontends/mpd/dispatcher.py b/mopidy/frontends/mpd/dispatcher.py index 148fe443..4f0001ac 100644 --- a/mopidy/frontends/mpd/dispatcher.py +++ b/mopidy/frontends/mpd/dispatcher.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import logging import re @@ -52,8 +54,8 @@ class MpdDispatcher(object): response = [] for subsystem in subsystems: - response.append(u'changed: %s' % subsystem) - response.append(u'OK') + response.append('changed: %s' % subsystem) + response.append('OK') self.context.subscriptions = set() self.context.events = set() self.context.session.send_lines(response) @@ -103,26 +105,26 @@ class MpdDispatcher(object): response = self._call_next_filter(request, response, filter_chain) if (self._is_receiving_command_list(request) or self._is_processing_command_list(request)): - if response and response[-1] == u'OK': + if response and response[-1] == 'OK': response = response[:-1] return response def _is_receiving_command_list(self, request): return ( - self.command_list_receiving and request != u'command_list_end') + self.command_list_receiving and request != 'command_list_end') def _is_processing_command_list(self, request): return ( self.command_list_index is not None and - request != u'command_list_end') + request != 'command_list_end') ### Filter: idle def _idle_filter(self, request, response, filter_chain): if self._is_currently_idle() and not self._noidle.match(request): logger.debug( - u'Client sent us %s, only %s is allowed while in ' - u'the idle state', repr(request), repr(u'noidle')) + 'Client sent us %s, only %s is allowed while in ' + 'the idle state', repr(request), repr('noidle')) self.context.session.close() return [] @@ -144,11 +146,11 @@ class MpdDispatcher(object): def _add_ok_filter(self, request, response, filter_chain): response = self._call_next_filter(request, response, filter_chain) if not self._has_error(response): - response.append(u'OK') + response.append('OK') return response def _has_error(self, response): - return response and response[-1].startswith(u'ACK') + return response and response[-1].startswith('ACK') ### Filter: call handler @@ -157,7 +159,7 @@ class MpdDispatcher(object): response = self._format_response(self._call_handler(request)) return self._call_next_filter(request, response, filter_chain) except pykka.ActorDeadError as e: - logger.warning(u'Tried to communicate with dead actor.') + logger.warning('Tried to communicate with dead actor.') raise exceptions.MpdSystemError(e) def _call_handler(self, request): @@ -173,7 +175,7 @@ class MpdDispatcher(object): command_name = request.split(' ')[0] if command_name in [command.name for command in protocol.mpd_commands]: raise exceptions.MpdArgError( - u'incorrect arguments', command=command_name) + 'incorrect arguments', command=command_name) raise exceptions.MpdUnknownCommand(command=command_name) def _format_response(self, response): @@ -202,10 +204,10 @@ class MpdDispatcher(object): def _format_lines(self, line): if isinstance(line, dict): - return [u'%s: %s' % (key, value) for (key, value) in line.items()] + return ['%s: %s' % (key, value) for (key, value) in line.items()] if isinstance(line, tuple): (key, value) = line - return [u'%s: %s' % (key, value)] + return ['%s: %s' % (key, value)] return [line] diff --git a/mopidy/frontends/mpd/exceptions.py b/mopidy/frontends/mpd/exceptions.py index 5925d6bc..db3212d8 100644 --- a/mopidy/frontends/mpd/exceptions.py +++ b/mopidy/frontends/mpd/exceptions.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy.exceptions import MopidyException @@ -19,7 +21,7 @@ class MpdAckError(MopidyException): error_code = 0 - def __init__(self, message=u'', index=0, command=u''): + def __init__(self, message='', index=0, command=''): super(MpdAckError, self).__init__(message, index, command) self.message = message self.index = index @@ -31,7 +33,7 @@ class MpdAckError(MopidyException): ACK [%(error_code)i@%(index)i] {%(command)s} description """ - return u'ACK [%i@%i] {%s} %s' % ( + return 'ACK [%i@%i] {%s} %s' % ( self.__class__.error_code, self.index, self.command, self.message) @@ -48,7 +50,7 @@ class MpdPermissionError(MpdAckError): def __init__(self, *args, **kwargs): super(MpdPermissionError, self).__init__(*args, **kwargs) - self.message = u'you don\'t have permission for "%s"' % self.command + self.message = 'you don\'t have permission for "%s"' % self.command class MpdUnknownCommand(MpdAckError): @@ -56,8 +58,8 @@ class MpdUnknownCommand(MpdAckError): def __init__(self, *args, **kwargs): super(MpdUnknownCommand, self).__init__(*args, **kwargs) - self.message = u'unknown command "%s"' % self.command - self.command = u'' + self.message = 'unknown command "%s"' % self.command + self.command = '' class MpdNoExistError(MpdAckError): @@ -73,4 +75,4 @@ class MpdNotImplemented(MpdAckError): def __init__(self, *args, **kwargs): super(MpdNotImplemented, self).__init__(*args, **kwargs) - self.message = u'Not implemented' + self.message = 'Not implemented' diff --git a/mopidy/frontends/mpd/protocol/__init__.py b/mopidy/frontends/mpd/protocol/__init__.py index 968a7dac..3a9f3674 100644 --- a/mopidy/frontends/mpd/protocol/__init__.py +++ b/mopidy/frontends/mpd/protocol/__init__.py @@ -10,17 +10,19 @@ implement our own MPD server which is compatible with the numerous existing `MPD clients `_. """ +from __future__ import unicode_literals + from collections import namedtuple import re #: The MPD protocol uses UTF-8 for encoding all data. -ENCODING = u'UTF-8' +ENCODING = 'UTF-8' #: The MPD protocol uses ``\n`` as line terminator. -LINE_TERMINATOR = u'\n' +LINE_TERMINATOR = '\n' #: The MPD protocol version is 0.16.0. -VERSION = u'0.16.0' +VERSION = '0.16.0' MpdCommand = namedtuple('MpdCommand', ['name', 'auth_required']) @@ -55,7 +57,7 @@ def handle_request(pattern, auth_required=True): mpd_commands.add( MpdCommand(name=match.group(), auth_required=auth_required)) if pattern in request_handlers: - raise ValueError(u'Tried to redefine handler for %s with %s' % ( + raise ValueError('Tried to redefine handler for %s with %s' % ( pattern, func)) request_handlers[pattern] = func func.__doc__ = ' - *Pattern:* ``%s``\n\n%s' % ( diff --git a/mopidy/frontends/mpd/protocol/audio_output.py b/mopidy/frontends/mpd/protocol/audio_output.py index 7e50c8c0..b4d491e5 100644 --- a/mopidy/frontends/mpd/protocol/audio_output.py +++ b/mopidy/frontends/mpd/protocol/audio_output.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy.frontends.mpd.protocol import handle_request from mopidy.frontends.mpd.exceptions import MpdNotImplemented diff --git a/mopidy/frontends/mpd/protocol/command_list.py b/mopidy/frontends/mpd/protocol/command_list.py index d422f97e..8d5769ef 100644 --- a/mopidy/frontends/mpd/protocol/command_list.py +++ b/mopidy/frontends/mpd/protocol/command_list.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy.frontends.mpd.protocol import handle_request from mopidy.frontends.mpd.exceptions import MpdUnknownCommand @@ -40,10 +42,10 @@ def command_list_end(context): command, current_command_list_index=index) command_list_response.extend(response) if (command_list_response and - command_list_response[-1].startswith(u'ACK')): + command_list_response[-1].startswith('ACK')): return command_list_response if command_list_ok: - command_list_response.append(u'list_OK') + command_list_response.append('list_OK') return command_list_response diff --git a/mopidy/frontends/mpd/protocol/connection.py b/mopidy/frontends/mpd/protocol/connection.py index 3228807f..f7898d21 100644 --- a/mopidy/frontends/mpd/protocol/connection.py +++ b/mopidy/frontends/mpd/protocol/connection.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy import settings from mopidy.frontends.mpd.protocol import handle_request from mopidy.frontends.mpd.exceptions import ( @@ -25,7 +27,7 @@ def kill(context): Kills MPD. """ - raise MpdPermissionError(command=u'kill') + raise MpdPermissionError(command='kill') @handle_request(r'^password "(?P[^"]+)"$', auth_required=False) @@ -41,7 +43,7 @@ def password_(context, password): if password == settings.MPD_SERVER_PASSWORD: context.dispatcher.authenticated = True else: - raise MpdPasswordError(u'incorrect password', command=u'password') + raise MpdPasswordError('incorrect password', command='password') @handle_request(r'^ping$', auth_required=False) diff --git a/mopidy/frontends/mpd/protocol/current_playlist.py b/mopidy/frontends/mpd/protocol/current_playlist.py index 5a88d41b..1a3f4f7b 100644 --- a/mopidy/frontends/mpd/protocol/current_playlist.py +++ b/mopidy/frontends/mpd/protocol/current_playlist.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy.frontends.mpd import translator from mopidy.frontends.mpd.exceptions import ( MpdArgError, MpdNoExistError, MpdNotImplemented) @@ -20,14 +22,11 @@ def add(context, uri): """ if not uri: return - for uri_scheme in context.core.uri_schemes.get(): - if uri.startswith(uri_scheme): - track = context.core.library.lookup(uri).get() - if track is not None: - context.core.current_playlist.add(track) - return - raise MpdNoExistError( - u'directory or file not found', command=u'add') + track = context.core.library.lookup(uri).get() + if track: + context.core.tracklist.add(track) + return + raise MpdNoExistError('directory or file not found', command='add') @handle_request(r'^addid "(?P[^"]*)"( "(?P\d+)")*$') @@ -50,17 +49,16 @@ def addid(context, uri, songpos=None): - ``addid ""`` should return an error. """ if not uri: - raise MpdNoExistError(u'No such song', command=u'addid') + raise MpdNoExistError('No such song', command='addid') if songpos is not None: songpos = int(songpos) track = context.core.library.lookup(uri).get() if track is None: - raise MpdNoExistError(u'No such song', command=u'addid') - if songpos and songpos > context.core.current_playlist.length.get(): - raise MpdArgError(u'Bad song index', command=u'addid') - cp_track = context.core.current_playlist.add( - track, at_position=songpos).get() - return ('Id', cp_track.cpid) + raise MpdNoExistError('No such song', command='addid') + if songpos and songpos > context.core.tracklist.length.get(): + raise MpdArgError('Bad song index', command='addid') + tl_track = context.core.tracklist.add(track, at_position=songpos).get() + return ('Id', tl_track.tlid) @handle_request(r'^delete "(?P\d+):(?P\d+)*"$') @@ -76,12 +74,12 @@ def delete_range(context, start, end=None): if end is not None: end = int(end) else: - end = context.core.current_playlist.length.get() - cp_tracks = context.core.current_playlist.slice(start, end).get() - if not cp_tracks: - raise MpdArgError(u'Bad song index', command=u'delete') - for (cpid, _) in cp_tracks: - context.core.current_playlist.remove(cpid=cpid) + end = context.core.tracklist.length.get() + tl_tracks = context.core.tracklist.slice(start, end).get() + if not tl_tracks: + raise MpdArgError('Bad song index', command='delete') + for (tlid, _) in tl_tracks: + context.core.tracklist.remove(tlid=tlid) @handle_request(r'^delete "(?P\d+)"$') @@ -89,15 +87,15 @@ def delete_songpos(context, songpos): """See :meth:`delete_range`""" try: songpos = int(songpos) - (cpid, _) = context.core.current_playlist.slice( + (tlid, _) = context.core.tracklist.slice( songpos, songpos + 1).get()[0] - context.core.current_playlist.remove(cpid=cpid) + context.core.tracklist.remove(tlid=tlid) except IndexError: - raise MpdArgError(u'Bad song index', command=u'delete') + raise MpdArgError('Bad song index', command='delete') -@handle_request(r'^deleteid "(?P\d+)"$') -def deleteid(context, cpid): +@handle_request(r'^deleteid "(?P\d+)"$') +def deleteid(context, tlid): """ *musicpd.org, current playlist section:* @@ -106,12 +104,12 @@ def deleteid(context, cpid): Deletes the song ``SONGID`` from the playlist """ try: - cpid = int(cpid) - if context.core.playback.current_cpid.get() == cpid: + tlid = int(tlid) + if context.core.playback.current_tlid.get() == tlid: context.core.playback.next() - return context.core.current_playlist.remove(cpid=cpid).get() + return context.core.tracklist.remove(tlid=tlid).get() except LookupError: - raise MpdNoExistError(u'No such song', command=u'deleteid') + raise MpdNoExistError('No such song', command='deleteid') @handle_request(r'^clear$') @@ -123,7 +121,7 @@ def clear(context): Clears the current playlist. """ - context.core.current_playlist.clear() + context.core.tracklist.clear() @handle_request(r'^move "(?P\d+):(?P\d+)*" "(?P\d+)"$') @@ -137,11 +135,11 @@ def move_range(context, start, to, end=None): ``TO`` in the playlist. """ if end is None: - end = context.core.current_playlist.length.get() + end = context.core.tracklist.length.get() start = int(start) end = int(end) to = int(to) - context.core.current_playlist.move(start, end, to) + context.core.tracklist.move(start, end, to) @handle_request(r'^move "(?P\d+)" "(?P\d+)"$') @@ -149,11 +147,11 @@ def move_songpos(context, songpos, to): """See :meth:`move_range`.""" songpos = int(songpos) to = int(to) - context.core.current_playlist.move(songpos, songpos + 1, to) + context.core.tracklist.move(songpos, songpos + 1, to) -@handle_request(r'^moveid "(?P\d+)" "(?P\d+)"$') -def moveid(context, cpid, to): +@handle_request(r'^moveid "(?P\d+)" "(?P\d+)"$') +def moveid(context, tlid, to): """ *musicpd.org, current playlist section:* @@ -163,11 +161,11 @@ def moveid(context, cpid, to): the playlist. If ``TO`` is negative, it is relative to the current song in the playlist (if there is one). """ - cpid = int(cpid) + tlid = int(tlid) to = int(to) - cp_track = context.core.current_playlist.get(cpid=cpid).get() - position = context.core.current_playlist.index(cp_track).get() - context.core.current_playlist.move(position, position + 1, to) + tl_track = context.core.tracklist.get(tlid=tlid).get() + position = context.core.tracklist.index(tl_track).get() + context.core.tracklist.move(position, position + 1, to) @handle_request(r'^playlist$') @@ -202,16 +200,16 @@ def playlistfind(context, tag, needle): """ if tag == 'filename': try: - cp_track = context.core.current_playlist.get(uri=needle).get() - position = context.core.current_playlist.index(cp_track).get() - return translator.track_to_mpd_format(cp_track, position=position) + tl_track = context.core.tracklist.get(uri=needle).get() + position = context.core.tracklist.index(tl_track).get() + return translator.track_to_mpd_format(tl_track, position=position) except LookupError: return None raise MpdNotImplemented # TODO -@handle_request(r'^playlistid( "(?P\d+)")*$') -def playlistid(context, cpid=None): +@handle_request(r'^playlistid( "(?P\d+)")*$') +def playlistid(context, tlid=None): """ *musicpd.org, current playlist section:* @@ -220,17 +218,17 @@ def playlistid(context, cpid=None): Displays a list of songs in the playlist. ``SONGID`` is optional and specifies a single song to display info for. """ - if cpid is not None: + if tlid is not None: try: - cpid = int(cpid) - cp_track = context.core.current_playlist.get(cpid=cpid).get() - position = context.core.current_playlist.index(cp_track).get() - return translator.track_to_mpd_format(cp_track, position=position) + tlid = int(tlid) + tl_track = context.core.tracklist.get(tlid=tlid).get() + position = context.core.tracklist.index(tl_track).get() + return translator.track_to_mpd_format(tl_track, position=position) except LookupError: - raise MpdNoExistError(u'No such song', command=u'playlistid') + raise MpdNoExistError('No such song', command='playlistid') else: return translator.tracks_to_mpd_format( - context.core.current_playlist.cp_tracks.get()) + context.core.tracklist.tl_tracks.get()) @handle_request(r'^playlistinfo$') @@ -254,20 +252,20 @@ def playlistinfo(context, songpos=None, start=None, end=None): """ if songpos is not None: songpos = int(songpos) - cp_track = context.core.current_playlist.cp_tracks.get()[songpos] - return translator.track_to_mpd_format(cp_track, position=songpos) + tl_track = context.core.tracklist.tl_tracks.get()[songpos] + return translator.track_to_mpd_format(tl_track, position=songpos) else: if start is None: start = 0 start = int(start) - if not (0 <= start <= context.core.current_playlist.length.get()): - raise MpdArgError(u'Bad song index', command=u'playlistinfo') + if not (0 <= start <= context.core.tracklist.length.get()): + raise MpdArgError('Bad song index', command='playlistinfo') if end is not None: end = int(end) - if end > context.core.current_playlist.length.get(): + if end > context.core.tracklist.length.get(): end = None - cp_tracks = context.core.current_playlist.cp_tracks.get() - return translator.tracks_to_mpd_format(cp_tracks, start, end) + tl_tracks = context.core.tracklist.tl_tracks.get() + return translator.tracks_to_mpd_format(tl_tracks, start, end) @handle_request(r'^playlistsearch "(?P[^"]+)" "(?P[^"]+)"$') @@ -307,9 +305,9 @@ def plchanges(context, version): - Calls ``plchanges "-1"`` two times per second to get the entire playlist. """ # XXX Naive implementation that returns all tracks as changed - if int(version) < context.core.current_playlist.version.get(): + if int(version) < context.core.tracklist.version.get(): return translator.tracks_to_mpd_format( - context.core.current_playlist.cp_tracks.get()) + context.core.tracklist.tl_tracks.get()) @handle_request(r'^plchangesposid "(?P\d+)"$') @@ -327,12 +325,12 @@ def plchangesposid(context, version): ``playlistlength`` returned by status command. """ # XXX Naive implementation that returns all tracks as changed - if int(version) != context.core.current_playlist.version.get(): + if int(version) != context.core.tracklist.version.get(): result = [] - for (position, (cpid, _)) in enumerate( - context.core.current_playlist.cp_tracks.get()): - result.append((u'cpos', position)) - result.append((u'Id', cpid)) + for (position, (tlid, _)) in enumerate( + context.core.tracklist.tl_tracks.get()): + result.append(('cpos', position)) + result.append(('Id', tlid)) return result @@ -351,7 +349,7 @@ def shuffle(context, start=None, end=None): start = int(start) if end is not None: end = int(end) - context.core.current_playlist.shuffle(start, end) + context.core.tracklist.shuffle(start, end) @handle_request(r'^swap "(?P\d+)" "(?P\d+)"$') @@ -365,19 +363,19 @@ def swap(context, songpos1, songpos2): """ songpos1 = int(songpos1) songpos2 = int(songpos2) - tracks = context.core.current_playlist.tracks.get() + tracks = context.core.tracklist.tracks.get() song1 = tracks[songpos1] song2 = tracks[songpos2] del tracks[songpos1] tracks.insert(songpos1, song2) del tracks[songpos2] tracks.insert(songpos2, song1) - context.core.current_playlist.clear() - context.core.current_playlist.append(tracks) + context.core.tracklist.clear() + context.core.tracklist.append(tracks) -@handle_request(r'^swapid "(?P\d+)" "(?P\d+)"$') -def swapid(context, cpid1, cpid2): +@handle_request(r'^swapid "(?P\d+)" "(?P\d+)"$') +def swapid(context, tlid1, tlid2): """ *musicpd.org, current playlist section:* @@ -385,10 +383,10 @@ def swapid(context, cpid1, cpid2): Swaps the positions of ``SONG1`` and ``SONG2`` (both song ids). """ - cpid1 = int(cpid1) - cpid2 = int(cpid2) - cp_track1 = context.core.current_playlist.get(cpid=cpid1).get() - cp_track2 = context.core.current_playlist.get(cpid=cpid2).get() - position1 = context.core.current_playlist.index(cp_track1).get() - position2 = context.core.current_playlist.index(cp_track2).get() + tlid1 = int(tlid1) + tlid2 = int(tlid2) + tl_track1 = context.core.tracklist.get(tlid=tlid1).get() + tl_track2 = context.core.tracklist.get(tlid=tlid2).get() + position1 = context.core.tracklist.index(tl_track1).get() + position2 = context.core.tracklist.index(tl_track2).get() swap(context, position1, position2) diff --git a/mopidy/frontends/mpd/protocol/empty.py b/mopidy/frontends/mpd/protocol/empty.py index f2ee4757..dfd610a9 100644 --- a/mopidy/frontends/mpd/protocol/empty.py +++ b/mopidy/frontends/mpd/protocol/empty.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy.frontends.mpd.protocol import handle_request diff --git a/mopidy/frontends/mpd/protocol/music_db.py b/mopidy/frontends/mpd/protocol/music_db.py index a5d5b214..00559e13 100644 --- a/mopidy/frontends/mpd/protocol/music_db.py +++ b/mopidy/frontends/mpd/protocol/music_db.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import re import shlex @@ -11,19 +13,21 @@ def _build_query(mpd_query): Parses a MPD query string and converts it to the Mopidy query format. """ query_pattern = ( - r'"?(?:[Aa]lbum|[Aa]rtist|[Ff]ilename|[Tt]itle|[Aa]ny)"? "[^"]+"') + r'"?(?:[Aa]lbum|[Aa]rtist|[Ff]ile[name]*|[Tt]itle|[Aa]ny)"? "[^"]+"') query_parts = re.findall(query_pattern, mpd_query) query_part_pattern = ( - r'"?(?P([Aa]lbum|[Aa]rtist|[Ff]ilename|[Tt]itle|[Aa]ny))"? ' + r'"?(?P([Aa]lbum|[Aa]rtist|[Ff]ile[name]*|[Tt]itle|[Aa]ny))"? ' r'"(?P[^"]+)"') query = {} for query_part in query_parts: m = re.match(query_part_pattern, query_part) field = m.groupdict()['field'].lower() - if field == u'title': - field = u'track' + if field == 'title': + field = 'track' + elif field in ('file', 'filename'): + field = 'uri' field = str(field) # Needed for kwargs keys on OS X and Windows - what = m.groupdict()['what'].lower() + what = m.groupdict()['what'] if field in query: query[field].append(what) else: @@ -45,7 +49,7 @@ def count(context, tag, needle): @handle_request( - r'^find (?P("?([Aa]lbum|[Aa]rtist|[Dd]ate|[Ff]ilename|' + r'^find (?P("?([Aa]lbum|[Aa]rtist|[Dd]ate|[Ff]ile[name]*|' r'[Tt]itle|[Aa]ny)"? "[^"]+"\s?)+)$') def find(context, mpd_query): """ @@ -70,6 +74,7 @@ def find(context, mpd_query): *ncmpcpp:* - also uses the search type "date". + - uses "file" instead of "filename". """ query = _build_query(mpd_query) return playlist_to_mpd_format( @@ -183,13 +188,13 @@ def list_(context, field, mpd_query=None): """ field = field.lower() query = _list_build_query(field, mpd_query) - if field == u'artist': + if field == 'artist': return _list_artist(context, query) - elif field == u'album': + elif field == 'album': return _list_album(context, query) - elif field == u'date': + elif field == 'date': return _list_date(context, query) - elif field == u'genre': + elif field == 'genre': pass # TODO We don't have genre in our internal data structures yet @@ -202,16 +207,16 @@ def _list_build_query(field, mpd_query): tokens = shlex.split(mpd_query.encode('utf-8')) except ValueError as error: if str(error) == 'No closing quotation': - raise MpdArgError(u'Invalid unquoted character', command=u'list') + raise MpdArgError('Invalid unquoted character', command='list') else: raise tokens = [t.decode('utf-8') for t in tokens] if len(tokens) == 1: - if field == u'album': + if field == 'album': return {'artist': [tokens[0]]} else: raise MpdArgError( - u'should be "Album" for 3 arguments', command=u'list') + 'should be "Album" for 3 arguments', command='list') elif len(tokens) % 2 == 0: query = {} while tokens: @@ -219,15 +224,15 @@ def _list_build_query(field, mpd_query): key = str(key) # Needed for kwargs keys on OS X and Windows value = tokens[1] tokens = tokens[2:] - if key not in (u'artist', u'album', u'date', u'genre'): - raise MpdArgError(u'not able to parse args', command=u'list') + if key not in ('artist', 'album', 'date', 'genre'): + raise MpdArgError('not able to parse args', command='list') if key in query: query[key].append(value) else: query[key] = [value] return query else: - raise MpdArgError(u'not able to parse args', command=u'list') + raise MpdArgError('not able to parse args', command='list') def _list_artist(context, query): @@ -235,7 +240,7 @@ def _list_artist(context, query): playlist = context.core.library.find_exact(**query).get() for track in playlist.tracks: for artist in track.artists: - artists.add((u'Artist', artist.name)) + artists.add(('Artist', artist.name)) return artists @@ -244,7 +249,7 @@ def _list_album(context, query): playlist = context.core.library.find_exact(**query).get() for track in playlist.tracks: if track.album is not None: - albums.add((u'Album', track.album.name)) + albums.add(('Album', track.album.name)) return albums @@ -253,7 +258,7 @@ def _list_date(context, query): playlist = context.core.library.find_exact(**query).get() for track in playlist.tracks: if track.date is not None: - dates.add((u'Date', track.date)) + dates.add(('Date', track.date)) return dates @@ -300,7 +305,7 @@ def lsinfo(context, uri=None): directories located at the root level, for both ``lsinfo``, ``lsinfo ""``, and ``lsinfo "/"``. """ - if uri is None or uri == u'/' or uri == u'': + if uri is None or uri == '/' or uri == '': return stored_playlists.listplaylists(context) raise MpdNotImplemented # TODO @@ -318,7 +323,7 @@ def rescan(context, uri=None): @handle_request( - r'^search (?P("?([Aa]lbum|[Aa]rtist|[Dd]ate|[Ff]ilename|' + r'^search (?P("?([Aa]lbum|[Aa]rtist|[Dd]ate|[Ff]ile[name]*|' r'[Tt]itle|[Aa]ny)"? "[^"]+"\s?)+)$') def search(context, mpd_query): """ @@ -346,6 +351,7 @@ def search(context, mpd_query): *ncmpcpp:* - also uses the search type "date". + - uses "file" instead of "filename". """ query = _build_query(mpd_query) return playlist_to_mpd_format( diff --git a/mopidy/frontends/mpd/protocol/playback.py b/mopidy/frontends/mpd/protocol/playback.py index 7851ebe0..74ecfb1c 100644 --- a/mopidy/frontends/mpd/protocol/playback.py +++ b/mopidy/frontends/mpd/protocol/playback.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy.core import PlaybackState from mopidy.frontends.mpd.protocol import handle_request from mopidy.frontends.mpd.exceptions import ( @@ -127,9 +129,9 @@ def play(context): return context.core.playback.play().get() -@handle_request(r'^playid (?P-?\d+)$') -@handle_request(r'^playid "(?P-?\d+)"$') -def playid(context, cpid): +@handle_request(r'^playid (?P-?\d+)$') +@handle_request(r'^playid "(?P-?\d+)"$') +def playid(context, tlid): """ *musicpd.org, playback section:* @@ -146,14 +148,14 @@ def playid(context, cpid): - ``playid "-1"`` when stopped without a current track, e.g. after playlist replacement, starts playback at the first track. """ - cpid = int(cpid) - if cpid == -1: + tlid = int(tlid) + if tlid == -1: return _play_minus_one(context) try: - cp_track = context.core.current_playlist.get(cpid=cpid).get() - return context.core.playback.play(cp_track).get() + tl_track = context.core.tracklist.get(tlid=tlid).get() + return context.core.playback.play(tl_track).get() except LookupError: - raise MpdNoExistError(u'No such song', command=u'playid') + raise MpdNoExistError('No such song', command='playid') @handle_request(r'^play (?P-?\d+)$') @@ -183,11 +185,10 @@ def playpos(context, songpos): if songpos == -1: return _play_minus_one(context) try: - cp_track = context.core.current_playlist.slice( - songpos, songpos + 1).get()[0] - return context.core.playback.play(cp_track).get() + tl_track = context.core.tracklist.slice(songpos, songpos + 1).get()[0] + return context.core.playback.play(tl_track).get() except IndexError: - raise MpdArgError(u'Bad song index', command=u'play') + raise MpdArgError('Bad song index', command='play') def _play_minus_one(context): @@ -195,12 +196,12 @@ def _play_minus_one(context): return # Nothing to do elif (context.core.playback.state.get() == PlaybackState.PAUSED): return context.core.playback.resume().get() - elif context.core.playback.current_cp_track.get() is not None: - cp_track = context.core.playback.current_cp_track.get() - return context.core.playback.play(cp_track).get() - elif context.core.current_playlist.slice(0, 1).get(): - cp_track = context.core.current_playlist.slice(0, 1).get()[0] - return context.core.playback.play(cp_track).get() + elif context.core.playback.current_tl_track.get() is not None: + tl_track = context.core.playback.current_tl_track.get() + return context.core.playback.play(tl_track).get() + elif context.core.tracklist.slice(0, 1).get(): + tl_track = context.core.tracklist.slice(0, 1).get()[0] + return context.core.playback.play(tl_track).get() else: return # Fail silently @@ -311,7 +312,7 @@ def replay_gain_status(context): Prints replay gain options. Currently, only the variable ``replay_gain_mode`` is returned. """ - return u'off' # TODO + return 'off' # TODO @handle_request(r'^seek (?P\d+) (?P\d+)$') @@ -329,13 +330,13 @@ def seek(context, songpos, seconds): - issues ``seek 1 120`` without quotes around the arguments. """ - if context.core.playback.current_playlist_position != songpos: + if context.core.playback.tracklist_position != songpos: playpos(context, songpos) context.core.playback.seek(int(seconds) * 1000) -@handle_request(r'^seekid "(?P\d+)" "(?P\d+)"$') -def seekid(context, cpid, seconds): +@handle_request(r'^seekid "(?P\d+)" "(?P\d+)"$') +def seekid(context, tlid, seconds): """ *musicpd.org, playback section:* @@ -343,8 +344,8 @@ def seekid(context, cpid, seconds): Seeks to the position ``TIME`` (in seconds) of song ``SONGID``. """ - if context.core.playback.current_cpid != cpid: - playid(context, cpid) + if context.core.playback.current_tlid != tlid: + playid(context, tlid) context.core.playback.seek(int(seconds) * 1000) diff --git a/mopidy/frontends/mpd/protocol/reflection.py b/mopidy/frontends/mpd/protocol/reflection.py index bc18eb3a..5af86a1a 100644 --- a/mopidy/frontends/mpd/protocol/reflection.py +++ b/mopidy/frontends/mpd/protocol/reflection.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy.frontends.mpd.protocol import handle_request, mpd_commands from mopidy.frontends.mpd.exceptions import MpdNotImplemented @@ -93,5 +95,5 @@ def urlhandlers(context): Gets a list of available URL handlers. """ return [ - (u'handler', uri_scheme) + ('handler', uri_scheme) for uri_scheme in context.core.uri_schemes.get()] diff --git a/mopidy/frontends/mpd/protocol/status.py b/mopidy/frontends/mpd/protocol/status.py index b8e207d1..34e2fa64 100644 --- a/mopidy/frontends/mpd/protocol/status.py +++ b/mopidy/frontends/mpd/protocol/status.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import pykka from mopidy.core import PlaybackState @@ -34,10 +36,10 @@ def currentsong(context): Displays the song info of the current song (same song that is identified in status). """ - current_cp_track = context.core.playback.current_cp_track.get() - if current_cp_track is not None: - position = context.core.playback.current_playlist_position.get() - return track_to_mpd_format(current_cp_track, position=position) + current_tl_track = context.core.playback.current_tl_track.get() + if current_tl_track is not None: + position = context.core.playback.tracklist_position.get() + return track_to_mpd_format(current_tl_track, position=position) @handle_request(r'^idle$') @@ -94,7 +96,7 @@ def idle(context, subsystems=None): context.subscriptions = set() for subsystem in active: - response.append(u'changed: %s' % subsystem) + response.append('changed: %s' % subsystem) return response @@ -173,17 +175,17 @@ def status(context): decimal places for millisecond precision. """ futures = { - 'current_playlist.length': context.core.current_playlist.length, - 'current_playlist.version': context.core.current_playlist.version, + 'tracklist.length': context.core.tracklist.length, + 'tracklist.version': context.core.tracklist.version, 'playback.volume': context.core.playback.volume, 'playback.consume': context.core.playback.consume, 'playback.random': context.core.playback.random, 'playback.repeat': context.core.playback.repeat, 'playback.single': context.core.playback.single, 'playback.state': context.core.playback.state, - 'playback.current_cp_track': context.core.playback.current_cp_track, - 'playback.current_playlist_position': ( - context.core.playback.current_playlist_position), + 'playback.current_tl_track': context.core.playback.current_tl_track, + 'playback.tracklist_position': ( + context.core.playback.tracklist_position), 'playback.time_position': context.core.playback.time_position, } pykka.get_all(futures.values()) @@ -198,7 +200,7 @@ def status(context): ('xfade', _status_xfade(futures)), ('state', _status_state(futures)), ] - if futures['playback.current_cp_track'].get() is not None: + if futures['playback.current_tl_track'].get() is not None: result.append(('song', _status_songpos(futures))) result.append(('songid', _status_songid(futures))) if futures['playback.state'].get() in ( @@ -210,9 +212,9 @@ def status(context): def _status_bitrate(futures): - current_cp_track = futures['playback.current_cp_track'].get() - if current_cp_track is not None: - return current_cp_track.track.bitrate + current_tl_track = futures['playback.current_tl_track'].get() + if current_tl_track is not None: + return current_tl_track.track.bitrate def _status_consume(futures): @@ -223,11 +225,11 @@ def _status_consume(futures): def _status_playlist_length(futures): - return futures['current_playlist.length'].get() + return futures['tracklist.length'].get() def _status_playlist_version(futures): - return futures['current_playlist.version'].get() + return futures['tracklist.version'].get() def _status_random(futures): @@ -243,45 +245,45 @@ def _status_single(futures): def _status_songid(futures): - current_cp_track = futures['playback.current_cp_track'].get() - if current_cp_track is not None: - return current_cp_track.cpid + current_tl_track = futures['playback.current_tl_track'].get() + if current_tl_track is not None: + return current_tl_track.tlid else: return _status_songpos(futures) def _status_songpos(futures): - return futures['playback.current_playlist_position'].get() + return futures['playback.tracklist_position'].get() def _status_state(futures): state = futures['playback.state'].get() if state == PlaybackState.PLAYING: - return u'play' + return 'play' elif state == PlaybackState.STOPPED: - return u'stop' + return 'stop' elif state == PlaybackState.PAUSED: - return u'pause' + return 'pause' def _status_time(futures): - return u'%d:%d' % ( + return '%d:%d' % ( futures['playback.time_position'].get() // 1000, _status_time_total(futures) // 1000) def _status_time_elapsed(futures): - return u'%.3f' % (futures['playback.time_position'].get() / 1000.0) + return '%.3f' % (futures['playback.time_position'].get() / 1000.0) def _status_time_total(futures): - current_cp_track = futures['playback.current_cp_track'].get() - if current_cp_track is None: + current_tl_track = futures['playback.current_tl_track'].get() + if current_tl_track is None: return 0 - elif current_cp_track.track.length is None: + elif current_tl_track.track.length is None: return 0 else: - return current_cp_track.track.length + return current_tl_track.track.length def _status_volume(futures): diff --git a/mopidy/frontends/mpd/protocol/stickers.py b/mopidy/frontends/mpd/protocol/stickers.py index 074a306d..439d8d5b 100644 --- a/mopidy/frontends/mpd/protocol/stickers.py +++ b/mopidy/frontends/mpd/protocol/stickers.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy.frontends.mpd.protocol import handle_request from mopidy.frontends.mpd.exceptions import MpdNotImplemented diff --git a/mopidy/frontends/mpd/protocol/stored_playlists.py b/mopidy/frontends/mpd/protocol/stored_playlists.py index 17e5abf7..b8ac8c4c 100644 --- a/mopidy/frontends/mpd/protocol/stored_playlists.py +++ b/mopidy/frontends/mpd/protocol/stored_playlists.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import datetime as dt from mopidy.frontends.mpd.exceptions import MpdNoExistError, MpdNotImplemented @@ -22,10 +24,10 @@ def listplaylist(context, name): file: relative/path/to/file3.mp3 """ try: - playlist = context.core.stored_playlists.get(name=name).get() + playlist = context.core.playlists.get(name=name).get() return ['file: %s' % t.uri for t in playlist.tracks] except LookupError: - raise MpdNoExistError(u'No such playlist', command=u'listplaylist') + raise MpdNoExistError('No such playlist', command='listplaylist') @handle_request(r'^listplaylistinfo (?P\S+)$') @@ -44,11 +46,10 @@ def listplaylistinfo(context, name): Album, Artist, Track """ try: - playlist = context.core.stored_playlists.get(name=name).get() + playlist = context.core.playlists.get(name=name).get() return playlist_to_mpd_format(playlist) except LookupError: - raise MpdNoExistError( - u'No such playlist', command=u'listplaylistinfo') + raise MpdNoExistError('No such playlist', command='listplaylistinfo') @handle_request(r'^listplaylists$') @@ -73,8 +74,8 @@ def listplaylists(context): Last-Modified: 2010-02-06T02:11:08Z """ result = [] - for playlist in context.core.stored_playlists.playlists.get(): - result.append((u'playlist', playlist.name)) + for playlist in context.core.playlists.playlists.get(): + result.append(('playlist', playlist.name)) last_modified = ( playlist.last_modified or dt.datetime.now()).isoformat() # Remove microseconds @@ -82,7 +83,7 @@ def listplaylists(context): # Add time zone information # TODO Convert to UTC before adding Z last_modified = last_modified + 'Z' - result.append((u'Last-Modified', last_modified)) + result.append(('Last-Modified', last_modified)) return result @@ -100,10 +101,10 @@ def load(context, name): - ``load`` appends the given playlist to the current playlist. """ try: - playlist = context.core.stored_playlists.get(name=name).get() - context.core.current_playlist.append(playlist.tracks) + playlist = context.core.playlists.get(name=name).get() + context.core.tracklist.append(playlist.tracks) except LookupError: - raise MpdNoExistError(u'No such playlist', command=u'load') + raise MpdNoExistError('No such playlist', command='load') @handle_request(r'^playlistadd "(?P[^"]+)" "(?P[^"]+)"$') diff --git a/mopidy/frontends/mpd/session.py b/mopidy/frontends/mpd/session.py index 5d535f75..8a5deecd 100644 --- a/mopidy/frontends/mpd/session.py +++ b/mopidy/frontends/mpd/session.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import logging from mopidy.frontends.mpd import dispatcher, protocol @@ -21,18 +23,18 @@ class MpdSession(network.LineProtocol): self.dispatcher = dispatcher.MpdDispatcher(session=self, core=core) def on_start(self): - logger.info(u'New MPD connection from [%s]:%s', self.host, self.port) - self.send_lines([u'OK MPD %s' % protocol.VERSION]) + logger.info('New MPD connection from [%s]:%s', self.host, self.port) + self.send_lines(['OK MPD %s' % protocol.VERSION]) def on_line_received(self, line): - logger.debug(u'Request from [%s]:%s: %s', self.host, self.port, line) + logger.debug('Request from [%s]:%s: %s', self.host, self.port, line) response = self.dispatcher.handle_request(line) if not response: return logger.debug( - u'Response to [%s]:%s: %s', self.host, self.port, + 'Response to [%s]:%s: %s', self.host, self.port, formatting.indent(self.terminator.join(response))) self.send_lines(response) @@ -45,8 +47,8 @@ class MpdSession(network.LineProtocol): return super(MpdSession, self).decode(line.decode('string_escape')) except ValueError: logger.warning( - u'Stopping actor due to unescaping error, data ' - u'supplied by client was not valid.') + 'Stopping actor due to unescaping error, data ' + 'supplied by client was not valid.') self.stop() def close(self): diff --git a/mopidy/frontends/mpd/translator.py b/mopidy/frontends/mpd/translator.py index 0ab28271..36b00772 100644 --- a/mopidy/frontends/mpd/translator.py +++ b/mopidy/frontends/mpd/translator.py @@ -1,9 +1,11 @@ +from __future__ import unicode_literals + import os import re from mopidy import settings from mopidy.frontends.mpd import protocol -from mopidy.models import CpTrack +from mopidy.models import TlTrack from mopidy.utils.path import mtime as get_mtime, uri_to_path, split_path @@ -12,7 +14,7 @@ def track_to_mpd_format(track, position=None): Format track for output to MPD client. :param track: the track - :type track: :class:`mopidy.models.Track` or :class:`mopidy.models.CpTrack` + :type track: :class:`mopidy.models.Track` or :class:`mopidy.models.TlTrack` :param position: track's position in playlist :type position: integer :param key: if we should set key @@ -21,10 +23,10 @@ def track_to_mpd_format(track, position=None): :type mtime: boolean :rtype: list of two-tuples """ - if isinstance(track, CpTrack): - (cpid, track) = track + if isinstance(track, TlTrack): + (tlid, track) = track else: - (cpid, track) = (None, track) + (tlid, track) = (None, track) result = [ ('file', track.uri or ''), ('Time', track.length and (track.length // 1000) or 0), @@ -41,9 +43,9 @@ def track_to_mpd_format(track, position=None): if track.album is not None and track.album.artists: artists = artists_to_mpd_format(track.album.artists) result.append(('AlbumArtist', artists)) - if position is not None and cpid is not None: + if position is not None and tlid is not None: result.append(('Pos', position)) - result.append(('Id', cpid)) + result.append(('Id', tlid)) if track.album is not None and track.album.musicbrainz_id is not None: result.append(('MUSICBRAINZ_ALBUMID', track.album.musicbrainz_id)) # FIXME don't use first and best artist? @@ -93,7 +95,7 @@ def artists_to_mpd_format(artists): """ artists = list(artists) artists.sort(key=lambda a: a.name) - return u', '.join([a.name for a in artists if a.name]) + return ', '.join([a.name for a in artists if a.name]) def tracks_to_mpd_format(tracks, start=0, end=None): @@ -104,7 +106,7 @@ def tracks_to_mpd_format(tracks, start=0, end=None): :param tracks: the tracks :type tracks: list of :class:`mopidy.models.Track` or - :class:`mopidy.models.CpTrack` + :class:`mopidy.models.TlTrack` :param start: position of first track to include in output :type start: int (positive or negative) :param end: position after last track to include in output @@ -178,7 +180,7 @@ def _add_to_tag_cache(result, folders, files): def tracks_to_directory_tree(tracks): directories = ({}, []) for track in tracks: - path = u'' + path = '' current = directories local_folder = settings.LOCAL_MUSIC_PATH diff --git a/mopidy/frontends/mpris/__init__.py b/mopidy/frontends/mpris/__init__.py index 38deac7a..2be6efea 100644 --- a/mopidy/frontends/mpris/__init__.py +++ b/mopidy/frontends/mpris/__init__.py @@ -50,5 +50,7 @@ Now you can control Mopidy through the player object. Examples: player.Quit(dbus_interface='org.mpris.MediaPlayer2') """ +from __future__ import unicode_literals + # flake8: noqa from .actor import MprisFrontend diff --git a/mopidy/frontends/mpris/actor.py b/mopidy/frontends/mpris/actor.py index 5d8d5492..81a44fbb 100644 --- a/mopidy/frontends/mpris/actor.py +++ b/mopidy/frontends/mpris/actor.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import logging import pykka @@ -12,7 +14,7 @@ try: import indicate except ImportError as import_error: indicate = None # noqa - logger.debug(u'Startup notification will not be sent (%s)', import_error) + logger.debug('Startup notification will not be sent (%s)', import_error) class MprisFrontend(pykka.ThreadingActor, CoreListener): @@ -27,20 +29,20 @@ class MprisFrontend(pykka.ThreadingActor, CoreListener): self.mpris_object = objects.MprisObject(self.core) self._send_startup_notification() except Exception as e: - logger.error(u'MPRIS frontend setup failed (%s)', e) + logger.error('MPRIS frontend setup failed (%s)', e) self.stop() def on_stop(self): - logger.debug(u'Removing MPRIS object from D-Bus connection...') + logger.debug('Removing MPRIS object from D-Bus connection...') if self.mpris_object: self.mpris_object.remove_from_connection() self.mpris_object = None - logger.debug(u'Removed MPRIS object from D-Bus connection') + logger.debug('Removed MPRIS object from D-Bus connection') def _send_startup_notification(self): """ Send startup notification using libindicate to make Mopidy appear in - e.g. `Ubuntu's sound menu `_. + e.g. `Ubunt's sound menu `_. A reference to the libindicate server is kept for as long as Mopidy is running. When Mopidy exits, the server will be unreferenced and Mopidy @@ -48,12 +50,12 @@ class MprisFrontend(pykka.ThreadingActor, CoreListener): """ if not indicate: return - logger.debug(u'Sending startup notification...') + logger.debug('Sending startup notification...') self.indicate_server = indicate.Server() self.indicate_server.set_type('music.mopidy') self.indicate_server.set_desktop_file(settings.DESKTOP_FILE) self.indicate_server.show() - logger.debug(u'Startup notification sent') + logger.debug('Startup notification sent') def _emit_properties_changed(self, *changed_properties): if self.mpris_object is None: @@ -65,25 +67,25 @@ class MprisFrontend(pykka.ThreadingActor, CoreListener): objects.PLAYER_IFACE, dict(props_with_new_values), []) def track_playback_paused(self, track, time_position): - logger.debug(u'Received track playback paused event') + logger.debug('Received track playback paused event') self._emit_properties_changed('PlaybackStatus') def track_playback_resumed(self, track, time_position): - logger.debug(u'Received track playback resumed event') + logger.debug('Received track playback resumed event') self._emit_properties_changed('PlaybackStatus') def track_playback_started(self, track): - logger.debug(u'Received track playback started event') + logger.debug('Received track playback started event') self._emit_properties_changed('PlaybackStatus', 'Metadata') def track_playback_ended(self, track, time_position): - logger.debug(u'Received track playback ended event') + logger.debug('Received track playback ended event') self._emit_properties_changed('PlaybackStatus', 'Metadata') def volume_changed(self): - logger.debug(u'Received volume changed event') + logger.debug('Received volume changed event') self._emit_properties_changed('Volume') def seeked(self, time_position_in_ms): - logger.debug(u'Received seeked event') + logger.debug('Received seeked event') self.mpris_object.Seeked(time_position_in_ms * 1000) diff --git a/mopidy/frontends/mpris/objects.py b/mopidy/frontends/mpris/objects.py index 4d4efe1e..235dd80a 100644 --- a/mopidy/frontends/mpris/objects.py +++ b/mopidy/frontends/mpris/objects.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import logging import os @@ -75,17 +77,17 @@ class MprisObject(dbus.service.Object): } def _connect_to_dbus(self): - logger.debug(u'Connecting to D-Bus...') + logger.debug('Connecting to D-Bus...') mainloop = dbus.mainloop.glib.DBusGMainLoop() bus_name = dbus.service.BusName( BUS_NAME, dbus.SessionBus(mainloop=mainloop)) - logger.info(u'Connected to D-Bus') + logger.info('Connected to D-Bus') return bus_name - def _get_track_id(self, cp_track): - return '/com/mopidy/track/%d' % cp_track.cpid + def _get_track_id(self, tl_track): + return '/com/mopidy/track/%d' % tl_track.tlid - def _get_cpid(self, track_id): + def _get_tlid(self, track_id): assert track_id.startswith('/com/mopidy/track/') return track_id.split('/')[-1] @@ -95,7 +97,7 @@ class MprisObject(dbus.service.Object): in_signature='ss', out_signature='v') def Get(self, interface, prop): logger.debug( - u'%s.Get(%s, %s) called', + '%s.Get(%s, %s) called', dbus.PROPERTIES_IFACE, repr(interface), repr(prop)) (getter, _) = self.properties[interface][prop] if callable(getter): @@ -107,7 +109,7 @@ class MprisObject(dbus.service.Object): in_signature='s', out_signature='a{sv}') def GetAll(self, interface): logger.debug( - u'%s.GetAll(%s) called', dbus.PROPERTIES_IFACE, repr(interface)) + '%s.GetAll(%s) called', dbus.PROPERTIES_IFACE, repr(interface)) getters = {} for key, (getter, _) in self.properties[interface].iteritems(): getters[key] = getter() if callable(getter) else getter @@ -117,7 +119,7 @@ class MprisObject(dbus.service.Object): in_signature='ssv', out_signature='') def Set(self, interface, prop, value): logger.debug( - u'%s.Set(%s, %s, %s) called', + '%s.Set(%s, %s, %s) called', dbus.PROPERTIES_IFACE, repr(interface), repr(prop), repr(value)) _, setter = self.properties[interface][prop] if setter is not None: @@ -130,7 +132,7 @@ class MprisObject(dbus.service.Object): def PropertiesChanged(self, interface, changed_properties, invalidated_properties): logger.debug( - u'%s.PropertiesChanged(%s, %s, %s) signaled', + '%s.PropertiesChanged(%s, %s, %s) signaled', dbus.PROPERTIES_IFACE, interface, changed_properties, invalidated_properties) @@ -138,12 +140,12 @@ class MprisObject(dbus.service.Object): @dbus.service.method(dbus_interface=ROOT_IFACE) def Raise(self): - logger.debug(u'%s.Raise called', ROOT_IFACE) + logger.debug('%s.Raise called', ROOT_IFACE) # Do nothing, as we do not have a GUI @dbus.service.method(dbus_interface=ROOT_IFACE) def Quit(self): - logger.debug(u'%s.Quit called', ROOT_IFACE) + logger.debug('%s.Quit called', ROOT_IFACE) exit_process() ### Root interface properties @@ -158,33 +160,33 @@ class MprisObject(dbus.service.Object): @dbus.service.method(dbus_interface=PLAYER_IFACE) def Next(self): - logger.debug(u'%s.Next called', PLAYER_IFACE) + logger.debug('%s.Next called', PLAYER_IFACE) if not self.get_CanGoNext(): - logger.debug(u'%s.Next not allowed', PLAYER_IFACE) + logger.debug('%s.Next not allowed', PLAYER_IFACE) return self.core.playback.next().get() @dbus.service.method(dbus_interface=PLAYER_IFACE) def Previous(self): - logger.debug(u'%s.Previous called', PLAYER_IFACE) + logger.debug('%s.Previous called', PLAYER_IFACE) if not self.get_CanGoPrevious(): - logger.debug(u'%s.Previous not allowed', PLAYER_IFACE) + logger.debug('%s.Previous not allowed', PLAYER_IFACE) return self.core.playback.previous().get() @dbus.service.method(dbus_interface=PLAYER_IFACE) def Pause(self): - logger.debug(u'%s.Pause called', PLAYER_IFACE) + logger.debug('%s.Pause called', PLAYER_IFACE) if not self.get_CanPause(): - logger.debug(u'%s.Pause not allowed', PLAYER_IFACE) + logger.debug('%s.Pause not allowed', PLAYER_IFACE) return self.core.playback.pause().get() @dbus.service.method(dbus_interface=PLAYER_IFACE) def PlayPause(self): - logger.debug(u'%s.PlayPause called', PLAYER_IFACE) + logger.debug('%s.PlayPause called', PLAYER_IFACE) if not self.get_CanPause(): - logger.debug(u'%s.PlayPause not allowed', PLAYER_IFACE) + logger.debug('%s.PlayPause not allowed', PLAYER_IFACE) return state = self.core.playback.state.get() if state == PlaybackState.PLAYING: @@ -196,17 +198,17 @@ class MprisObject(dbus.service.Object): @dbus.service.method(dbus_interface=PLAYER_IFACE) def Stop(self): - logger.debug(u'%s.Stop called', PLAYER_IFACE) + logger.debug('%s.Stop called', PLAYER_IFACE) if not self.get_CanControl(): - logger.debug(u'%s.Stop not allowed', PLAYER_IFACE) + logger.debug('%s.Stop not allowed', PLAYER_IFACE) return self.core.playback.stop().get() @dbus.service.method(dbus_interface=PLAYER_IFACE) def Play(self): - logger.debug(u'%s.Play called', PLAYER_IFACE) + logger.debug('%s.Play called', PLAYER_IFACE) if not self.get_CanPlay(): - logger.debug(u'%s.Play not allowed', PLAYER_IFACE) + logger.debug('%s.Play not allowed', PLAYER_IFACE) return state = self.core.playback.state.get() if state == PlaybackState.PAUSED: @@ -216,9 +218,9 @@ class MprisObject(dbus.service.Object): @dbus.service.method(dbus_interface=PLAYER_IFACE) def Seek(self, offset): - logger.debug(u'%s.Seek called', PLAYER_IFACE) + logger.debug('%s.Seek called', PLAYER_IFACE) if not self.get_CanSeek(): - logger.debug(u'%s.Seek not allowed', PLAYER_IFACE) + logger.debug('%s.Seek not allowed', PLAYER_IFACE) return offset_in_milliseconds = offset // 1000 current_position = self.core.playback.time_position.get() @@ -227,29 +229,29 @@ class MprisObject(dbus.service.Object): @dbus.service.method(dbus_interface=PLAYER_IFACE) def SetPosition(self, track_id, position): - logger.debug(u'%s.SetPosition called', PLAYER_IFACE) + logger.debug('%s.SetPosition called', PLAYER_IFACE) if not self.get_CanSeek(): - logger.debug(u'%s.SetPosition not allowed', PLAYER_IFACE) + logger.debug('%s.SetPosition not allowed', PLAYER_IFACE) return position = position // 1000 - current_cp_track = self.core.playback.current_cp_track.get() - if current_cp_track is None: + current_tl_track = self.core.playback.current_tl_track.get() + if current_tl_track is None: return - if track_id != self._get_track_id(current_cp_track): + if track_id != self._get_track_id(current_tl_track): return if position < 0: return - if current_cp_track.track.length < position: + if current_tl_track.track.length < position: return self.core.playback.seek(position) @dbus.service.method(dbus_interface=PLAYER_IFACE) def OpenUri(self, uri): - logger.debug(u'%s.OpenUri called', PLAYER_IFACE) + logger.debug('%s.OpenUri called', PLAYER_IFACE) if not self.get_CanPlay(): # NOTE The spec does not explictly require this check, but guarding # the other methods doesn't help much if OpenUri is open for use. - logger.debug(u'%s.Play not allowed', PLAYER_IFACE) + logger.debug('%s.Play not allowed', PLAYER_IFACE) return # NOTE Check if URI has MIME type known to the backend, if MIME support # is added to the backend. @@ -258,16 +260,16 @@ class MprisObject(dbus.service.Object): return track = self.core.library.lookup(uri).get() if track is not None: - cp_track = self.core.current_playlist.add(track).get() - self.core.playback.play(cp_track) + tl_track = self.core.tracklist.add(track).get() + self.core.playback.play(tl_track) else: - logger.debug(u'Track with URI "%s" not found in library.', uri) + logger.debug('Track with URI "%s" not found in library.', uri) ### Player interface signals @dbus.service.signal(dbus_interface=PLAYER_IFACE, signature='x') def Seeked(self, position): - logger.debug(u'%s.Seeked signaled', PLAYER_IFACE) + logger.debug('%s.Seeked signaled', PLAYER_IFACE) # Do nothing, as just calling the method is enough to emit the signal. ### Player interface properties @@ -294,7 +296,7 @@ class MprisObject(dbus.service.Object): def set_LoopStatus(self, value): if not self.get_CanControl(): - logger.debug(u'Setting %s.LoopStatus not allowed', PLAYER_IFACE) + logger.debug('Setting %s.LoopStatus not allowed', PLAYER_IFACE) return if value == 'None': self.core.playback.repeat = False @@ -310,7 +312,7 @@ class MprisObject(dbus.service.Object): if not self.get_CanControl(): # NOTE The spec does not explictly require this check, but it was # added to be consistent with all the other property setters. - logger.debug(u'Setting %s.Rate not allowed', PLAYER_IFACE) + logger.debug('Setting %s.Rate not allowed', PLAYER_IFACE) return if value == 0: self.Pause() @@ -320,7 +322,7 @@ class MprisObject(dbus.service.Object): def set_Shuffle(self, value): if not self.get_CanControl(): - logger.debug(u'Setting %s.Shuffle not allowed', PLAYER_IFACE) + logger.debug('Setting %s.Shuffle not allowed', PLAYER_IFACE) return if value: self.core.playback.random = True @@ -328,12 +330,12 @@ class MprisObject(dbus.service.Object): self.core.playback.random = False def get_Metadata(self): - current_cp_track = self.core.playback.current_cp_track.get() - if current_cp_track is None: + current_tl_track = self.core.playback.current_tl_track.get() + if current_tl_track is None: return {'mpris:trackid': ''} else: - (_, track) = current_cp_track - metadata = {'mpris:trackid': self._get_track_id(current_cp_track)} + (_, track) = current_tl_track + metadata = {'mpris:trackid': self._get_track_id(current_tl_track)} if track.length: metadata['mpris:length'] = track.length * 1000 if track.uri: @@ -364,7 +366,7 @@ class MprisObject(dbus.service.Object): def set_Volume(self, value): if not self.get_CanControl(): - logger.debug(u'Setting %s.Volume not allowed', PLAYER_IFACE) + logger.debug('Setting %s.Volume not allowed', PLAYER_IFACE) return if value is None: return @@ -382,15 +384,15 @@ class MprisObject(dbus.service.Object): if not self.get_CanControl(): return False return ( - self.core.playback.cp_track_at_next.get() != - self.core.playback.current_cp_track.get()) + self.core.playback.tl_track_at_next.get() != + self.core.playback.current_tl_track.get()) def get_CanGoPrevious(self): if not self.get_CanControl(): return False return ( - self.core.playback.cp_track_at_previous.get() != - self.core.playback.current_cp_track.get()) + self.core.playback.tl_track_at_previous.get() != + self.core.playback.current_tl_track.get()) def get_CanPlay(self): if not self.get_CanControl(): diff --git a/mopidy/models.py b/mopidy/models.py index 77561fe3..511ce847 100644 --- a/mopidy/models.py +++ b/mopidy/models.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from collections import namedtuple @@ -14,7 +16,7 @@ class ImmutableObject(object): for key, value in kwargs.items(): if not hasattr(self, key): raise TypeError( - u"__init__() got an unexpected keyword argument '%s'" % + '__init__() got an unexpected keyword argument "%s"' % key) self.__dict__[key] = value @@ -73,7 +75,7 @@ class ImmutableObject(object): data[key] = values.pop(key) if values: raise TypeError( - u"copy() got an unexpected keyword argument '%s'" % key) + 'copy() got an unexpected keyword argument "%s"' % key) return self.__class__(**data) def serialize(self): @@ -149,7 +151,7 @@ class Album(ImmutableObject): super(Album, self).__init__(*args, **kwargs) -CpTrack = namedtuple('CpTrack', ['cpid', 'track']) +TlTrack = namedtuple('TlTrack', ['tlid', 'track']) class Track(ImmutableObject): diff --git a/mopidy/scanner.py b/mopidy/scanner.py index 2c12d26a..e5e484e5 100644 --- a/mopidy/scanner.py +++ b/mopidy/scanner.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import gobject gobject.threads_init() @@ -62,7 +64,7 @@ class Scanner(object): fakesink = gst.element_factory_make('fakesink') self.uribin = gst.element_factory_make('uridecodebin') - self.uribin.set_property('caps', gst.Caps('audio/x-raw-int')) + self.uribin.set_property('caps', gst.Caps(b'audio/x-raw-int')) self.uribin.connect( 'pad-added', self.process_new_pad, fakesink.get_pad('sink')) diff --git a/mopidy/settings.py b/mopidy/settings.py index 3603eda6..04706bb6 100644 --- a/mopidy/settings.py +++ b/mopidy/settings.py @@ -7,6 +7,8 @@ All available settings and their default values. file called ``~/.config/mopidy/settings.py`` and redefine settings there. """ +from __future__ import unicode_literals + #: List of playback backends to use. See :ref:`backend-implementations` for all #: available backends. #: @@ -20,21 +22,21 @@ All available settings and their default values. #: u'mopidy.backends.spotify.SpotifyBackend', #: ) BACKENDS = ( - u'mopidy.backends.local.LocalBackend', - u'mopidy.backends.spotify.SpotifyBackend', + 'mopidy.backends.local.LocalBackend', + 'mopidy.backends.spotify.SpotifyBackend', ) #: The log format used for informational logging. #: #: See http://docs.python.org/2/library/logging.html#formatter-objects for #: details on the format. -CONSOLE_LOG_FORMAT = u'%(levelname)-8s %(message)s' +CONSOLE_LOG_FORMAT = '%(levelname)-8s %(message)s' #: The log format used for debug logging. #: #: See http://docs.python.org/library/logging.html#formatter-objects for #: details on the format. -DEBUG_LOG_FORMAT = u'%(levelname)-8s %(asctime)s' + \ +DEBUG_LOG_FORMAT = '%(levelname)-8s %(asctime)s' + \ ' [%(process)d:%(threadName)s] %(name)s\n %(message)s' #: The file to dump debug log data to when Mopidy is run with the @@ -43,7 +45,7 @@ DEBUG_LOG_FORMAT = u'%(levelname)-8s %(asctime)s' + \ #: Default:: #: #: DEBUG_LOG_FILENAME = u'mopidy.log' -DEBUG_LOG_FILENAME = u'mopidy.log' +DEBUG_LOG_FILENAME = 'mopidy.log' #: If we should start a background thread that dumps thread's traceback when we #: get a SIGUSR1. Mainly a debug tool for figuring out deadlocks. @@ -60,7 +62,7 @@ DEBUG_THREAD = False #: Default:: #: #: DESKTOP_FILE = u'/usr/share/applications/mopidy.desktop' -DESKTOP_FILE = u'/usr/share/applications/mopidy.desktop' +DESKTOP_FILE = '/usr/share/applications/mopidy.desktop' #: List of server frontends to use. See :ref:`frontend-implementations` for #: available frontends. @@ -73,9 +75,9 @@ DESKTOP_FILE = u'/usr/share/applications/mopidy.desktop' #: u'mopidy.frontends.mpris.MprisFrontend', #: ) FRONTENDS = ( - u'mopidy.frontends.mpd.MpdFrontend', - u'mopidy.frontends.lastfm.LastfmFrontend', - u'mopidy.frontends.mpris.MprisFrontend', + 'mopidy.frontends.mpd.MpdFrontend', + 'mopidy.frontends.lastfm.LastfmFrontend', + 'mopidy.frontends.mpris.MprisFrontend', ) #: Which address Mopidy's HTTP server should bind to. @@ -114,12 +116,12 @@ HTTP_SERVER_STATIC_DIR = None #: Your `Last.fm `_ username. #: #: Used by :mod:`mopidy.frontends.lastfm`. -LASTFM_USERNAME = u'' +LASTFM_USERNAME = '' #: Your `Last.fm `_ password. #: #: Used by :mod:`mopidy.frontends.lastfm`. -LASTFM_PASSWORD = u'' +LASTFM_PASSWORD = '' #: Path to folder with local music. #: @@ -128,7 +130,7 @@ LASTFM_PASSWORD = u'' #: Default:: #: #: LOCAL_MUSIC_PATH = u'$XDG_MUSIC_DIR' -LOCAL_MUSIC_PATH = u'$XDG_MUSIC_DIR' +LOCAL_MUSIC_PATH = '$XDG_MUSIC_DIR' #: Path to playlist folder with m3u files for local music. #: @@ -137,7 +139,7 @@ LOCAL_MUSIC_PATH = u'$XDG_MUSIC_DIR' #: Default:: #: #: LOCAL_PLAYLIST_PATH = u'$XDG_DATA_DIR/mopidy/playlists' -LOCAL_PLAYLIST_PATH = u'$XDG_DATA_DIR/mopidy/playlists' +LOCAL_PLAYLIST_PATH = '$XDG_DATA_DIR/mopidy/playlists' #: Path to tag cache for local music. #: @@ -146,7 +148,7 @@ LOCAL_PLAYLIST_PATH = u'$XDG_DATA_DIR/mopidy/playlists' #: Default:: #: #: LOCAL_TAG_CACHE_FILE = u'$XDG_DATA_DIR/mopidy/tag_cache' -LOCAL_TAG_CACHE_FILE = u'$XDG_DATA_DIR/mopidy/tag_cache' +LOCAL_TAG_CACHE_FILE = '$XDG_DATA_DIR/mopidy/tag_cache' #: Audio mixer to use. #: @@ -159,7 +161,7 @@ LOCAL_TAG_CACHE_FILE = u'$XDG_DATA_DIR/mopidy/tag_cache' #: Default:: #: #: MIXER = u'autoaudiomixer' -MIXER = u'autoaudiomixer' +MIXER = 'autoaudiomixer' #: Audio mixer track to use. #: @@ -186,7 +188,7 @@ MIXER_TRACK = None #: Listens on all IPv4 interfaces. #: ``::`` #: Listens on all interfaces, both IPv4 and IPv6. -MPD_SERVER_HOSTNAME = u'127.0.0.1' +MPD_SERVER_HOSTNAME = '127.0.0.1' #: Which TCP port Mopidy's MPD server should listen to. #: @@ -218,7 +220,7 @@ MPD_SERVER_MAX_CONNECTIONS = 20 #: Default:: #: #: OUTPUT = u'autoaudiosink' -OUTPUT = u'autoaudiosink' +OUTPUT = 'autoaudiosink' #: Path to the Spotify cache. #: @@ -227,17 +229,17 @@ OUTPUT = u'autoaudiosink' #: Default:: #: #: SPOTIFY_CACHE_PATH = u'$XDG_CACHE_DIR/mopidy/spotify' -SPOTIFY_CACHE_PATH = u'$XDG_CACHE_DIR/mopidy/spotify' +SPOTIFY_CACHE_PATH = '$XDG_CACHE_DIR/mopidy/spotify' #: Your Spotify Premium username. #: #: Used by :mod:`mopidy.backends.spotify`. -SPOTIFY_USERNAME = u'' +SPOTIFY_USERNAME = '' #: Your Spotify Premium password. #: #: Used by :mod:`mopidy.backends.spotify`. -SPOTIFY_PASSWORD = u'' +SPOTIFY_PASSWORD = '' #: Spotify preferred bitrate. #: diff --git a/mopidy/utils/__init__.py b/mopidy/utils/__init__.py index e69de29b..baffc488 100644 --- a/mopidy/utils/__init__.py +++ b/mopidy/utils/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/mopidy/utils/deps.py b/mopidy/utils/deps.py index 32949f55..41fd513d 100644 --- a/mopidy/utils/deps.py +++ b/mopidy/utils/deps.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import os import platform import sys diff --git a/mopidy/utils/encoding.py b/mopidy/utils/encoding.py index 888896c5..a21b3384 100644 --- a/mopidy/utils/encoding.py +++ b/mopidy/utils/encoding.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import locale diff --git a/mopidy/utils/formatting.py b/mopidy/utils/formatting.py index 9091bc2a..ba311fb5 100644 --- a/mopidy/utils/formatting.py +++ b/mopidy/utils/formatting.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import re import unicodedata @@ -6,7 +8,7 @@ def indent(string, places=4, linebreak='\n'): lines = string.split(linebreak) if len(lines) == 1: return string - result = u'' + result = '' for line in lines: result += linebreak + ' ' * places + line return result diff --git a/mopidy/utils/importing.py b/mopidy/utils/importing.py index 3df6abe4..591071a1 100644 --- a/mopidy/utils/importing.py +++ b/mopidy/utils/importing.py @@ -1,6 +1,9 @@ +from __future__ import unicode_literals + import logging import sys + logger = logging.getLogger('mopidy.utils') diff --git a/mopidy/utils/log.py b/mopidy/utils/log.py index 6bb29f8a..ae4ea0d9 100644 --- a/mopidy/utils/log.py +++ b/mopidy/utils/log.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import logging import logging.handlers @@ -14,9 +16,9 @@ def setup_logging(verbosity_level, save_debug_log): # New in Python 2.7 logging.captureWarnings(True) logger = logging.getLogger('mopidy.utils.log') - logger.info(u'Starting Mopidy %s', versioning.get_version()) - logger.info(u'%(name)s: %(version)s', deps.platform_info()) - logger.info(u'%(name)s: %(version)s', deps.python_info()) + logger.info('Starting Mopidy %s', versioning.get_version()) + logger.info('%(name)s: %(version)s', deps.platform_info()) + logger.info('%(name)s: %(version)s', deps.python_info()) def setup_root_logger(): diff --git a/mopidy/utils/network.py b/mopidy/utils/network.py index e56f6a81..91831871 100644 --- a/mopidy/utils/network.py +++ b/mopidy/utils/network.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import errno import gobject import logging @@ -26,8 +28,8 @@ def try_ipv6_socket(): return True except IOError as error: logger.debug( - u'Platform supports IPv6, but socket creation failed, ' - u'disabling: %s', + 'Platform supports IPv6, but socket creation failed, ' + 'disabling: %s', encoding.locale_decode(error)) return False @@ -107,7 +109,7 @@ class Server(object): def reject_connection(self, sock, addr): # FIXME provide more context in logging? - logger.warning(u'Rejected connection from [%s]:%s', addr[0], addr[1]) + logger.warning('Rejected connection from [%s]:%s', addr[0], addr[1]) try: sock.close() except socket.error: @@ -190,7 +192,7 @@ class Connection(object): except socket.error as e: if e.errno in (errno.EWOULDBLOCK, errno.EINTR): return data - self.stop(u'Unexpected client error: %s' % e) + self.stop('Unexpected client error: %s' % e) return '' def enable_timeout(self): @@ -219,7 +221,7 @@ class Connection(object): gobject.IO_IN | gobject.IO_ERR | gobject.IO_HUP, self.recv_callback) except socket.error as e: - self.stop(u'Problem with connection: %s' % e) + self.stop('Problem with connection: %s' % e) def disable_recv(self): if self.recv_id is None: @@ -237,7 +239,7 @@ class Connection(object): gobject.IO_OUT | gobject.IO_ERR | gobject.IO_HUP, self.send_callback) except socket.error as e: - self.stop(u'Problem with connection: %s' % e) + self.stop('Problem with connection: %s' % e) def disable_send(self): if self.send_id is None: @@ -248,30 +250,30 @@ class Connection(object): def recv_callback(self, fd, flags): if flags & (gobject.IO_ERR | gobject.IO_HUP): - self.stop(u'Bad client flags: %s' % flags) + self.stop('Bad client flags: %s' % flags) return True try: data = self.sock.recv(4096) except socket.error as e: if e.errno not in (errno.EWOULDBLOCK, errno.EINTR): - self.stop(u'Unexpected client error: %s' % e) + self.stop('Unexpected client error: %s' % e) return True if not data: - self.stop(u'Client most likely disconnected.') + self.stop('Client most likely disconnected.') return True try: self.actor_ref.tell({'received': data}) except pykka.ActorDeadError: - self.stop(u'Actor is dead.') + self.stop('Actor is dead.') return True def send_callback(self, fd, flags): if flags & (gobject.IO_ERR | gobject.IO_HUP): - self.stop(u'Bad client flags: %s' % flags) + self.stop('Bad client flags: %s' % flags) return True # If with can't get the lock, simply try again next time socket is @@ -289,7 +291,7 @@ class Connection(object): return True def timeout_callback(self): - self.stop(u'Client timeout out after %s seconds' % self.timeout) + self.stop('Client timeout out after %s seconds' % self.timeout) return False @@ -356,7 +358,7 @@ class LineProtocol(pykka.ThreadingActor): def on_stop(self): """Ensure that cleanup when actor stops.""" - self.connection.stop(u'Actor is shutting down.') + self.connection.stop('Actor is shutting down.') def parse_lines(self): """Consume new data and yield any lines found.""" @@ -375,8 +377,8 @@ class LineProtocol(pykka.ThreadingActor): return line.encode(self.encoding) except UnicodeError: logger.warning( - u'Stopping actor due to encode problem, data ' - u'supplied by client was not valid %s', + 'Stopping actor due to encode problem, data ' + 'supplied by client was not valid %s', self.encoding) self.stop() @@ -390,14 +392,14 @@ class LineProtocol(pykka.ThreadingActor): return line.decode(self.encoding) except UnicodeError: logger.warning( - u'Stopping actor due to decode problem, data ' - u'supplied by client was not valid %s', + 'Stopping actor due to decode problem, data ' + 'supplied by client was not valid %s', self.encoding) self.stop() def join_lines(self, lines): if not lines: - return u'' + return '' return self.terminator.join(lines) + self.terminator def send_lines(self, lines): diff --git a/mopidy/utils/path.py b/mopidy/utils/path.py index 1092534f..0c06eedd 100644 --- a/mopidy/utils/path.py +++ b/mopidy/utils/path.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import logging import os import re @@ -25,10 +27,10 @@ def get_or_create_folder(folder): folder = os.path.expanduser(folder) if os.path.isfile(folder): raise OSError( - u'A file with the same name as the desired dir, ' - u'"%s", already exists.' % folder) + 'A file with the same name as the desired dir, ' + '"%s", already exists.' % folder) elif not os.path.isdir(folder): - logger.info(u'Creating dir %s', folder) + logger.info('Creating dir %s', folder) os.makedirs(folder, 0755) return folder @@ -36,7 +38,7 @@ def get_or_create_folder(folder): def get_or_create_file(filename): filename = os.path.expanduser(filename) if not os.path.isfile(filename): - logger.info(u'Creating file %s', filename) + logger.info('Creating file %s', filename) open(filename, 'w') return filename diff --git a/mopidy/utils/process.py b/mopidy/utils/process.py index c6b27533..27e312de 100644 --- a/mopidy/utils/process.py +++ b/mopidy/utils/process.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import logging import signal import sys @@ -10,26 +12,29 @@ from pykka.registry import ActorRegistry from mopidy import exceptions + logger = logging.getLogger('mopidy.utils.process') + SIGNALS = dict((k, v) for v, k in signal.__dict__.iteritems() if v.startswith('SIG') and not v.startswith('SIG_')) + def exit_process(): - logger.debug(u'Interrupting main...') + logger.debug('Interrupting main...') thread.interrupt_main() - logger.debug(u'Interrupted main') + logger.debug('Interrupted main') def exit_handler(signum, frame): """A :mod:`signal` handler which will exit the program on signal.""" - logger.info(u'Got %s signal', SIGNALS[signum]) + logger.info('Got %s signal', SIGNALS[signum]) exit_process() def stop_actors_by_class(klass): actors = ActorRegistry.get_by_class(klass) - logger.debug(u'Stopping %d instance(s) of %s', len(actors), klass.__name__) + logger.debug('Stopping %d instance(s) of %s', len(actors), klass.__name__) for actor in actors: actor.stop() @@ -38,15 +43,15 @@ def stop_remaining_actors(): num_actors = len(ActorRegistry.get_all()) while num_actors: logger.error( - u'There are actor threads still running, this is probably a bug') + 'There are actor threads still running, this is probably a bug') logger.debug( - u'Seeing %d actor and %d non-actor thread(s): %s', + 'Seeing %d actor and %d non-actor thread(s): %s', num_actors, threading.active_count() - num_actors, ', '.join([t.name for t in threading.enumerate()])) - logger.debug(u'Stopping %d actor(s)...', num_actors) + logger.debug('Stopping %d actor(s)...', num_actors) ActorRegistry.stop_all() num_actors = len(ActorRegistry.get_all()) - logger.debug(u'All actors stopped.') + logger.debug('All actors stopped.') class BaseThread(threading.Thread): @@ -56,11 +61,11 @@ class BaseThread(threading.Thread): self.daemon = True def run(self): - logger.debug(u'%s: Starting thread', self.name) + logger.debug('%s: Starting thread', self.name) try: self.run_inside_try() except KeyboardInterrupt: - logger.info(u'Interrupted by user') + logger.info('Interrupted by user') except exceptions.SettingsError as e: logger.error(e.message) except ImportError as e: @@ -69,11 +74,12 @@ class BaseThread(threading.Thread): logger.warning(e) except Exception as e: logger.exception(e) - logger.debug(u'%s: Exiting thread', self.name) + logger.debug('%s: Exiting thread', self.name) def run_inside_try(self): raise NotImplementedError + class DebugThread(threading.Thread): daemon = True name = 'DebugThread' @@ -81,7 +87,7 @@ class DebugThread(threading.Thread): event = threading.Event() def handler(self, signum, frame): - logger.info(u'Got %s signal', SIGNALS[signum]) + logger.info('Got %s signal', SIGNALS[signum]) self.event.set() def run(self): diff --git a/mopidy/utils/settings.py b/mopidy/utils/settings.py index 5760106b..fee5252d 100644 --- a/mopidy/utils/settings.py +++ b/mopidy/utils/settings.py @@ -1,6 +1,6 @@ # Absolute import needed to import ~/.config/mopidy/settings.py and not # ourselves -from __future__ import absolute_import +from __future__ import absolute_import, unicode_literals import copy import getpass @@ -53,11 +53,11 @@ class SettingsProxy(object): current = self.current # bind locally to avoid copying+updates if attr not in current: - raise exceptions.SettingsError(u'Setting "%s" is not set.' % attr) + raise exceptions.SettingsError('Setting "%s" is not set.' % attr) value = current[attr] if isinstance(value, basestring) and len(value) == 0: - raise exceptions.SettingsError(u'Setting "%s" is empty.' % attr) + raise exceptions.SettingsError('Setting "%s" is empty.' % attr) if not value: return value if attr.endswith('_PATH') or attr.endswith('_FILE'): @@ -75,17 +75,17 @@ class SettingsProxy(object): self._read_missing_settings_from_stdin(self.current, self.runtime) if self.get_errors(): logger.error( - u'Settings validation errors: %s', + 'Settings validation errors: %s', formatting.indent(self.get_errors_as_string())) - raise exceptions.SettingsError(u'Settings validation failed.') + raise exceptions.SettingsError('Settings validation failed.') def _read_missing_settings_from_stdin(self, current, runtime): for setting, value in sorted(current.iteritems()): if isinstance(value, basestring) and len(value) == 0: - runtime[setting] = self._read_from_stdin(setting + u': ') + runtime[setting] = self._read_from_stdin(setting + ': ') def _read_from_stdin(self, prompt): - if u'_PASSWORD' in prompt: + if '_PASSWORD' in prompt: return ( getpass.getpass(prompt) .decode(sys.stdin.encoding, 'ignore')) @@ -101,7 +101,7 @@ class SettingsProxy(object): def get_errors_as_string(self): lines = [] for (setting, error) in self.get_errors().iteritems(): - lines.append(u'%s: %s' % (setting, error)) + lines.append('%s: %s' % (setting, error)) return '\n'.join(lines) @@ -121,7 +121,6 @@ def validate_settings(defaults, settings): errors = {} changed = { - 'CUSTOM_OUTPUT': 'OUTPUT', 'DUMP_LOG_FILENAME': 'DEBUG_LOG_FILENAME', 'DUMP_LOG_FORMAT': 'DEBUG_LOG_FORMAT', 'FRONTEND': 'FRONTENDS', @@ -151,37 +150,37 @@ def validate_settings(defaults, settings): for setting, value in settings.iteritems(): if setting in changed: if changed[setting] is None: - errors[setting] = u'Deprecated setting. It may be removed.' + errors[setting] = 'Deprecated setting. It may be removed.' else: - errors[setting] = u'Deprecated setting. Use %s.' % ( + errors[setting] = 'Deprecated setting. Use %s.' % ( changed[setting],) elif setting == 'OUTPUTS': errors[setting] = ( - u'Deprecated setting, please change to OUTPUT. OUTPUT expects ' - u'a GStreamer bin description string for your desired output.') + 'Deprecated setting, please change to OUTPUT. OUTPUT expects ' + 'a GStreamer bin description string for your desired output.') elif setting == 'SPOTIFY_BITRATE': if value not in (96, 160, 320): errors[setting] = ( - u'Unavailable Spotify bitrate. Available bitrates are 96, ' - u'160, and 320.') + 'Unavailable Spotify bitrate. Available bitrates are 96, ' + '160, and 320.') elif setting.startswith('SHOUTCAST_OUTPUT_'): errors[setting] = ( - u'Deprecated setting, please set the value via the GStreamer ' - u'bin in OUTPUT.') + 'Deprecated setting, please set the value via the GStreamer ' + 'bin in OUTPUT.') elif setting in list_of_one_or_more: if not value: - errors[setting] = u'Must contain at least one value.' + errors[setting] = 'Must contain at least one value.' - elif setting not in defaults: - errors[setting] = u'Unknown setting.' + elif setting not in defaults and not setting.startswith('CUSTOM_'): + errors[setting] = 'Unknown setting.' suggestion = did_you_mean(setting, defaults) if suggestion: - errors[setting] += u' Did you mean %s?' % suggestion + errors[setting] += ' Did you mean %s?' % suggestion return errors @@ -204,20 +203,20 @@ def format_settings_list(settings): for (key, value) in sorted(settings.current.iteritems()): default_value = settings.default.get(key) masked_value = mask_value_if_secret(key, value) - lines.append(u'%s: %s' % ( + lines.append('%s: %s' % ( key, formatting.indent(pprint.pformat(masked_value), places=2))) if value != default_value and default_value is not None: lines.append( - u' Default: %s' % + ' Default: %s' % formatting.indent(pprint.pformat(default_value), places=4)) if errors.get(key) is not None: - lines.append(u' Error: %s' % errors[key]) + lines.append(' Error: %s' % errors[key]) return '\n'.join(lines) def mask_value_if_secret(key, value): if key.endswith('PASSWORD') and value: - return u'********' + return '********' else: return value diff --git a/mopidy/utils/versioning.py b/mopidy/utils/versioning.py index 8e7d55bd..3ad72458 100644 --- a/mopidy/utils/versioning.py +++ b/mopidy/utils/versioning.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from subprocess import PIPE, Popen from mopidy import __version__ diff --git a/setup.py b/setup.py index 99fb7f49..6135df31 100644 --- a/setup.py +++ b/setup.py @@ -2,6 +2,8 @@ Most of this file is taken from the Django project, which is BSD licensed. """ +from __future__ import unicode_literals + from distutils.core import setup from distutils.command.install_data import install_data from distutils.command.install import INSTALL_SCHEMES @@ -64,18 +66,17 @@ for scheme in INSTALL_SCHEMES.values(): # an easy way to do this. packages, data_files = [], [] root_dir = os.path.dirname(__file__) -if root_dir != '': +if root_dir != b'': os.chdir(root_dir) -project_dir = 'mopidy' - +project_dir = b'mopidy' for dirpath, dirnames, filenames in os.walk(project_dir): # Ignore dirnames that start with '.' for i, dirname in enumerate(dirnames): - if dirname.startswith('.'): + if dirname.startswith(b'.'): del dirnames[i] - if '__init__.py' in filenames: - packages.append('.'.join(fullsplit(dirpath))) + if b'__init__.py' in filenames: + packages.append(b'.'.join(fullsplit(dirpath))) elif filenames: data_files.append([ dirpath, [os.path.join(dirpath, f) for f in filenames]]) @@ -87,7 +88,7 @@ setup( author='Stein Magnus Jodal', author_email='stein.magnus@jodal.no', packages=packages, - package_data={'mopidy': ['backends/spotify/spotify_appkey.key']}, + package_data={b'mopidy': ['backends/spotify/spotify_appkey.key']}, cmdclass=cmdclasses, data_files=data_files, scripts=['bin/mopidy', 'bin/mopidy-scan'], diff --git a/tests/__init__.py b/tests/__init__.py index 5d9ea2b5..7f7a9c36 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import os import sys diff --git a/tests/__main__.py b/tests/__main__.py index 69113580..11757cbb 100644 --- a/tests/__main__.py +++ b/tests/__main__.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import nose import yappi diff --git a/tests/audio_test.py b/tests/audio_test.py index 852ce36b..b8b65e83 100644 --- a/tests/audio_test.py +++ b/tests/audio_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy import audio, settings from mopidy.utils.path import path_to_uri diff --git a/tests/backends/__init__.py b/tests/backends/__init__.py index e69de29b..baffc488 100644 --- a/tests/backends/__init__.py +++ b/tests/backends/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/tests/backends/base/__init__.py b/tests/backends/base/__init__.py index 84eee193..ec3ec1df 100644 --- a/tests/backends/base/__init__.py +++ b/tests/backends/base/__init__.py @@ -1,7 +1,10 @@ +from __future__ import unicode_literals + + def populate_playlist(func): def wrapper(self): for track in self.tracks: - self.core.current_playlist.add(track) + self.core.tracklist.add(track) return func(self) wrapper.__name__ = func.__name__ diff --git a/tests/backends/base/library.py b/tests/backends/base/library.py index b7510dbb..0b32186f 100644 --- a/tests/backends/base/library.py +++ b/tests/backends/base/library.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import pykka from mopidy import core @@ -79,13 +81,13 @@ class LibraryControllerTest(object): result = self.library.find_exact(album=['album2']) self.assertEqual(result, Playlist(tracks=self.tracks[1:2])) - def test_find_exact_filename(self): - track_1_filename = 'file://' + path_to_data_dir('uri1') - result = self.library.find_exact(filename=track_1_filename) + def test_find_exact_uri(self): + track_1_uri = 'file://' + path_to_data_dir('uri1') + result = self.library.find_exact(uri=track_1_uri) self.assertEqual(result, Playlist(tracks=self.tracks[:1])) - track_2_filename = 'file://' + path_to_data_dir('uri2') - result = self.library.find_exact(filename=track_2_filename) + track_2_uri = 'file://' + path_to_data_dir('uri2') + result = self.library.find_exact(uri=track_2_uri) self.assertEqual(result, Playlist(tracks=self.tracks[1:2])) def test_find_exact_wrong_type(self): @@ -146,13 +148,6 @@ class LibraryControllerTest(object): result = self.library.search(uri=['RI2']) self.assertEqual(result, Playlist(tracks=self.tracks[1:2])) - def test_search_filename(self): - result = self.library.search(filename=['RI1']) - self.assertEqual(result, Playlist(tracks=self.tracks[:1])) - - result = self.library.search(filename=['RI2']) - self.assertEqual(result, Playlist(tracks=self.tracks[1:2])) - def test_search_any(self): result = self.library.search(any=['Tist1']) self.assertEqual(result, Playlist(tracks=self.tracks[:1])) diff --git a/tests/backends/base/playback.py b/tests/backends/base/playback.py index cd55668c..21e377d9 100644 --- a/tests/backends/base/playback.py +++ b/tests/backends/base/playback.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import mock import random import time @@ -20,7 +22,7 @@ class PlaybackControllerTest(object): self.backend = self.backend_class.start(audio=self.audio).proxy() self.core = core.Core(backends=[self.backend]) self.playback = self.core.playback - self.current_playlist = self.core.current_playlist + self.tracklist = self.core.tracklist assert len(self.tracks) >= 3, \ 'Need at least three tracks to run tests.' @@ -51,13 +53,13 @@ class PlaybackControllerTest(object): @populate_playlist def test_play_track_state(self): self.assertEqual(self.playback.state, PlaybackState.STOPPED) - self.playback.play(self.current_playlist.cp_tracks[-1]) + self.playback.play(self.tracklist.tl_tracks[-1]) self.assertEqual(self.playback.state, PlaybackState.PLAYING) @populate_playlist def test_play_track_return_value(self): self.assertEqual(self.playback.play( - self.current_playlist.cp_tracks[-1]), None) + self.tracklist.tl_tracks[-1]), None) @populate_playlist def test_play_when_playing(self): @@ -93,7 +95,7 @@ class PlaybackControllerTest(object): @populate_playlist def test_play_track_sets_current_track(self): - self.playback.play(self.current_playlist.cp_tracks[-1]) + self.playback.play(self.tracklist.tl_tracks[-1]) self.assertEqual(self.playback.current_track, self.tracks[-1]) @populate_playlist @@ -106,12 +108,12 @@ class PlaybackControllerTest(object): @populate_playlist def test_current_track_after_completed_playlist(self): - self.playback.play(self.current_playlist.cp_tracks[-1]) + self.playback.play(self.tracklist.tl_tracks[-1]) self.playback.on_end_of_track() self.assertEqual(self.playback.state, PlaybackState.STOPPED) self.assertEqual(self.playback.current_track, None) - self.playback.play(self.current_playlist.cp_tracks[-1]) + self.playback.play(self.tracklist.tl_tracks[-1]) self.playback.next() self.assertEqual(self.playback.state, PlaybackState.STOPPED) self.assertEqual(self.playback.current_track, None) @@ -160,7 +162,7 @@ class PlaybackControllerTest(object): def test_previous_skips_to_previous_track_on_failure(self): # If backend's play() returns False, it is a failure. self.backend.playback.play = lambda track: track != self.tracks[1] - self.playback.play(self.current_playlist.cp_tracks[2]) + self.playback.play(self.tracklist.tl_tracks[2]) self.assertEqual(self.playback.current_track, self.tracks[2]) self.playback.previous() self.assertNotEqual(self.playback.current_track, self.tracks[1]) @@ -170,13 +172,13 @@ class PlaybackControllerTest(object): def test_next(self): self.playback.play() - old_position = self.playback.current_playlist_position + old_position = self.playback.tracklist_position old_uri = self.playback.current_track.uri self.playback.next() self.assertEqual( - self.playback.current_playlist_position, old_position + 1) + self.playback.tracklist_position, old_position + 1) self.assertNotEqual(self.playback.current_track.uri, old_uri) @populate_playlist @@ -196,7 +198,7 @@ class PlaybackControllerTest(object): for i, track in enumerate(self.tracks): self.assertEqual(self.playback.state, PlaybackState.PLAYING) self.assertEqual(self.playback.current_track, track) - self.assertEqual(self.playback.current_playlist_position, i) + self.assertEqual(self.playback.tracklist_position, i) self.playback.next() @@ -252,7 +254,7 @@ class PlaybackControllerTest(object): @populate_playlist def test_next_track_at_end_of_playlist(self): self.playback.play() - for _ in self.current_playlist.cp_tracks[1:]: + for _ in self.tracklist.tl_tracks[1:]: self.playback.next() self.assertEqual(self.playback.track_at_next, None) @@ -275,7 +277,7 @@ class PlaybackControllerTest(object): self.playback.consume = True self.playback.play() self.playback.next() - self.assertIn(self.tracks[0], self.current_playlist.tracks) + self.assertIn(self.tracks[0], self.tracklist.tracks) @populate_playlist def test_next_with_single_and_repeat(self): @@ -299,20 +301,20 @@ class PlaybackControllerTest(object): random.seed(1) self.playback.random = True self.assertEqual(self.playback.track_at_next, self.tracks[2]) - self.current_playlist.append(self.tracks[:1]) + self.tracklist.append(self.tracks[:1]) self.assertEqual(self.playback.track_at_next, self.tracks[1]) @populate_playlist def test_end_of_track(self): self.playback.play() - old_position = self.playback.current_playlist_position + old_position = self.playback.tracklist_position old_uri = self.playback.current_track.uri self.playback.on_end_of_track() self.assertEqual( - self.playback.current_playlist_position, old_position + 1) + self.playback.tracklist_position, old_position + 1) self.assertNotEqual(self.playback.current_track.uri, old_uri) @populate_playlist @@ -332,7 +334,7 @@ class PlaybackControllerTest(object): for i, track in enumerate(self.tracks): self.assertEqual(self.playback.state, PlaybackState.PLAYING) self.assertEqual(self.playback.current_track, track) - self.assertEqual(self.playback.current_playlist_position, i) + self.assertEqual(self.playback.tracklist_position, i) self.playback.on_end_of_track() @@ -388,7 +390,7 @@ class PlaybackControllerTest(object): @populate_playlist def test_end_of_track_track_at_end_of_playlist(self): self.playback.play() - for _ in self.current_playlist.cp_tracks[1:]: + for _ in self.tracklist.tl_tracks[1:]: self.playback.on_end_of_track() self.assertEqual(self.playback.track_at_next, None) @@ -411,7 +413,7 @@ class PlaybackControllerTest(object): self.playback.consume = True self.playback.play() self.playback.on_end_of_track() - self.assertNotIn(self.tracks[0], self.current_playlist.tracks) + self.assertNotIn(self.tracks[0], self.tracklist.tracks) @populate_playlist def test_end_of_track_with_random(self): @@ -427,7 +429,7 @@ class PlaybackControllerTest(object): random.seed(1) self.playback.random = True self.assertEqual(self.playback.track_at_next, self.tracks[2]) - self.current_playlist.append(self.tracks[:1]) + self.tracklist.append(self.tracks[:1]) self.assertEqual(self.playback.track_at_next, self.tracks[1]) @populate_playlist @@ -488,36 +490,36 @@ class PlaybackControllerTest(object): self.assertEqual(self.playback.current_track, self.tracks[1]) @populate_playlist - def test_initial_current_playlist_position(self): - self.assertEqual(self.playback.current_playlist_position, None) + def test_initial_tracklist_position(self): + self.assertEqual(self.playback.tracklist_position, None) @populate_playlist - def test_current_playlist_position_during_play(self): + def test_tracklist_position_during_play(self): self.playback.play() - self.assertEqual(self.playback.current_playlist_position, 0) + self.assertEqual(self.playback.tracklist_position, 0) @populate_playlist - def test_current_playlist_position_after_next(self): + def test_tracklist_position_after_next(self): self.playback.play() self.playback.next() - self.assertEqual(self.playback.current_playlist_position, 1) + self.assertEqual(self.playback.tracklist_position, 1) @populate_playlist - def test_current_playlist_position_at_end_of_playlist(self): - self.playback.play(self.current_playlist.cp_tracks[-1]) + def test_tracklist_position_at_end_of_playlist(self): + self.playback.play(self.tracklist.tl_tracks[-1]) self.playback.on_end_of_track() - self.assertEqual(self.playback.current_playlist_position, None) + self.assertEqual(self.playback.tracklist_position, None) - def test_on_current_playlist_change_gets_called(self): - callback = self.playback.on_current_playlist_change + def test_on_tracklist_change_gets_called(self): + callback = self.playback.on_tracklist_change def wrapper(): wrapper.called = True return callback() wrapper.called = False - self.playback.on_current_playlist_change = wrapper - self.current_playlist.append([Track()]) + self.playback.on_tracklist_change = wrapper + self.tracklist.append([Track()]) self.assert_(wrapper.called) @@ -531,25 +533,25 @@ class PlaybackControllerTest(object): self.assertEqual('end_of_track', message['command']) @populate_playlist - def test_on_current_playlist_change_when_playing(self): + def test_on_tracklist_change_when_playing(self): self.playback.play() current_track = self.playback.current_track - self.current_playlist.append([self.tracks[2]]) + self.tracklist.append([self.tracks[2]]) self.assertEqual(self.playback.state, PlaybackState.PLAYING) self.assertEqual(self.playback.current_track, current_track) @populate_playlist - def test_on_current_playlist_change_when_stopped(self): - self.current_playlist.append([self.tracks[2]]) + def test_on_tracklist_change_when_stopped(self): + self.tracklist.append([self.tracks[2]]) self.assertEqual(self.playback.state, PlaybackState.STOPPED) self.assertEqual(self.playback.current_track, None) @populate_playlist - def test_on_current_playlist_change_when_paused(self): + def test_on_tracklist_change_when_paused(self): self.playback.play() self.playback.pause() current_track = self.playback.current_track - self.current_playlist.append([self.tracks[2]]) + self.tracklist.append([self.tracks[2]]) self.assertEqual(self.playback.state, PlaybackState.PAUSED) self.assertEqual(self.playback.current_track, current_track) @@ -640,7 +642,7 @@ class PlaybackControllerTest(object): @populate_playlist def test_seek_when_playing_updates_position(self): - length = self.current_playlist.tracks[0].length + length = self.tracklist.tracks[0].length self.playback.play() self.playback.seek(length - 1000) position = self.playback.time_position @@ -655,7 +657,7 @@ class PlaybackControllerTest(object): @populate_playlist def test_seek_when_paused_updates_position(self): - length = self.current_playlist.tracks[0].length + length = self.tracklist.tracks[0].length self.playback.play() self.playback.pause() self.playback.seek(length - 1000) @@ -685,8 +687,8 @@ class PlaybackControllerTest(object): @populate_playlist def test_seek_beyond_end_of_song_for_last_track(self): - self.playback.play(self.current_playlist.cp_tracks[-1]) - self.playback.seek(self.current_playlist.tracks[-1].length * 100) + self.playback.play(self.tracklist.tl_tracks[-1]) + self.playback.seek(self.tracklist.tracks[-1].length * 100) self.assertEqual(self.playback.state, PlaybackState.STOPPED) @unittest.SkipTest @@ -772,9 +774,9 @@ class PlaybackControllerTest(object): def test_playlist_is_empty_after_all_tracks_are_played_with_consume(self): self.playback.consume = True self.playback.play() - for _ in range(len(self.current_playlist.tracks)): + for _ in range(len(self.tracklist.tracks)): self.playback.on_end_of_track() - self.assertEqual(len(self.current_playlist.tracks), 0) + self.assertEqual(len(self.tracklist.tracks), 0) @populate_playlist def test_play_with_random(self): @@ -809,7 +811,7 @@ class PlaybackControllerTest(object): @populate_playlist def test_end_of_playlist_stops(self): - self.playback.play(self.current_playlist.cp_tracks[-1]) + self.playback.play(self.tracklist.tl_tracks[-1]) self.playback.on_end_of_track() self.assertEqual(self.playback.state, PlaybackState.STOPPED) diff --git a/tests/backends/base/stored_playlists.py b/tests/backends/base/playlists.py similarity index 52% rename from tests/backends/base/stored_playlists.py rename to tests/backends/base/playlists.py index 267a025c..473caf8c 100644 --- a/tests/backends/base/stored_playlists.py +++ b/tests/backends/base/playlists.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import os import shutil import tempfile @@ -11,7 +13,7 @@ from mopidy.models import Playlist from tests import unittest, path_to_data_dir -class StoredPlaylistsControllerTest(object): +class PlaylistsControllerTest(object): def setUp(self): settings.LOCAL_PLAYLIST_PATH = tempfile.mkdtemp() settings.LOCAL_TAG_CACHE_FILE = path_to_data_dir('library_tag_cache') @@ -20,7 +22,6 @@ class StoredPlaylistsControllerTest(object): self.audio = mock.Mock(spec=audio.Audio) self.backend = self.backend_class.start(audio=self.audio).proxy() self.core = core.Core(backends=[self.backend]) - self.stored = self.core.stored_playlists def tearDown(self): pykka.ActorRegistry.stop_all() @@ -31,74 +32,74 @@ class StoredPlaylistsControllerTest(object): settings.runtime.clear() def test_create_returns_playlist_with_name_set(self): - playlist = self.stored.create(u'test') + playlist = self.core.playlists.create('test') self.assertEqual(playlist.name, 'test') def test_create_returns_playlist_with_uri_set(self): - playlist = self.stored.create(u'test') + playlist = self.core.playlists.create('test') self.assert_(playlist.uri) def test_create_adds_playlist_to_playlists_collection(self): - playlist = self.stored.create(u'test') - self.assert_(self.stored.playlists) - self.assertIn(playlist, self.stored.playlists) + playlist = self.core.playlists.create('test') + self.assert_(self.core.playlists.playlists) + self.assertIn(playlist, self.core.playlists.playlists) def test_playlists_empty_to_start_with(self): - self.assert_(not self.stored.playlists) + self.assert_(not self.core.playlists.playlists) def test_delete_non_existant_playlist(self): - self.stored.delete('file:///unknown/playlist') + self.core.playlists.delete('file:///unknown/playlist') def test_delete_playlist_removes_it_from_the_collection(self): - playlist = self.stored.create(u'test') - self.assertIn(playlist, self.stored.playlists) + playlist = self.core.playlists.create('test') + self.assertIn(playlist, self.core.playlists.playlists) - self.stored.delete(playlist.uri) + self.core.playlists.delete(playlist.uri) - self.assertNotIn(playlist, self.stored.playlists) + self.assertNotIn(playlist, self.core.playlists.playlists) def test_get_without_criteria(self): - test = self.stored.get + test = self.core.playlists.get self.assertRaises(LookupError, test) def test_get_with_wrong_cirteria(self): - test = lambda: self.stored.get(name='foo') + test = lambda: self.core.playlists.get(name='foo') self.assertRaises(LookupError, test) def test_get_with_right_criteria(self): - playlist1 = self.stored.create(u'test') - playlist2 = self.stored.get(name='test') + playlist1 = self.core.playlists.create('test') + playlist2 = self.core.playlists.get(name='test') self.assertEqual(playlist1, playlist2) def test_get_by_name_returns_unique_match(self): playlist = Playlist(name='b') - self.backend.stored_playlists.playlists = [ + self.backend.playlists.playlists = [ Playlist(name='a'), playlist] - self.assertEqual(playlist, self.stored.get(name='b')) + self.assertEqual(playlist, self.core.playlists.get(name='b')) def test_get_by_name_returns_first_of_multiple_matches(self): playlist = Playlist(name='b') - self.backend.stored_playlists.playlists = [ + self.backend.playlists.playlists = [ playlist, Playlist(name='a'), Playlist(name='b')] try: - self.stored.get(name='b') - self.fail(u'Should raise LookupError if multiple matches') + self.core.playlists.get(name='b') + self.fail('Should raise LookupError if multiple matches') except LookupError as e: - self.assertEqual(u'"name=b" match multiple playlists', e[0]) + self.assertEqual('"name=b" match multiple playlists', e[0]) def test_get_by_name_raises_keyerror_if_no_match(self): - self.backend.stored_playlists.playlists = [ + self.backend.playlists.playlists = [ Playlist(name='a'), Playlist(name='b')] try: - self.stored.get(name='c') - self.fail(u'Should raise LookupError if no match') + self.core.playlists.get(name='c') + self.fail('Should raise LookupError if no match') except LookupError as e: - self.assertEqual(u'"name=c" match no playlists', e[0]) + self.assertEqual('"name=c" match no playlists', e[0]) def test_lookup_finds_playlist_by_uri(self): - original_playlist = self.stored.create(u'test') + original_playlist = self.core.playlists.create('test') - looked_up_playlist = self.stored.lookup(original_playlist.uri) + looked_up_playlist = self.core.playlists.lookup(original_playlist.uri) self.assertEqual(original_playlist, looked_up_playlist) @@ -106,14 +107,14 @@ class StoredPlaylistsControllerTest(object): def test_refresh(self): pass - def test_save_replaces_stored_playlist_with_updated_playlist(self): - playlist1 = self.stored.create(u'test1') - self.assertIn(playlist1, self.stored.playlists) + def test_save_replaces_existing_playlist_with_updated_playlist(self): + playlist1 = self.core.playlists.create('test1') + self.assertIn(playlist1, self.core.playlists.playlists) - playlist2 = playlist1.copy(name=u'test2') - playlist2 = self.stored.save(playlist2) - self.assertNotIn(playlist1, self.stored.playlists) - self.assertIn(playlist2, self.stored.playlists) + playlist2 = playlist1.copy(name='test2') + playlist2 = self.core.playlists.save(playlist2) + self.assertNotIn(playlist1, self.core.playlists.playlists) + self.assertIn(playlist2, self.core.playlists.playlists) @unittest.SkipTest def test_playlist_with_unknown_track(self): diff --git a/tests/backends/base/current_playlist.py b/tests/backends/base/tracklist.py similarity index 86% rename from tests/backends/base/current_playlist.py rename to tests/backends/base/tracklist.py index 2ba77ee3..64ab10d4 100644 --- a/tests/backends/base/current_playlist.py +++ b/tests/backends/base/tracklist.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import mock import random @@ -5,19 +7,19 @@ import pykka from mopidy import audio, core from mopidy.core import PlaybackState -from mopidy.models import CpTrack, Playlist, Track +from mopidy.models import TlTrack, Playlist, Track from tests.backends.base import populate_playlist -class CurrentPlaylistControllerTest(object): +class TracklistControllerTest(object): tracks = [] def setUp(self): self.audio = mock.Mock(spec=audio.Audio) self.backend = self.backend_class.start(audio=self.audio).proxy() self.core = core.Core(audio=audio, backends=[self.backend]) - self.controller = self.core.current_playlist + self.controller = self.core.tracklist self.playback = self.core.playback assert len(self.tracks) == 3, 'Need three tracks to run tests.' @@ -26,25 +28,25 @@ class CurrentPlaylistControllerTest(object): pykka.ActorRegistry.stop_all() def test_length(self): - self.assertEqual(0, len(self.controller.cp_tracks)) + self.assertEqual(0, len(self.controller.tl_tracks)) self.assertEqual(0, self.controller.length) self.controller.append(self.tracks) - self.assertEqual(3, len(self.controller.cp_tracks)) + self.assertEqual(3, len(self.controller.tl_tracks)) self.assertEqual(3, self.controller.length) def test_add(self): for track in self.tracks: - cp_track = self.controller.add(track) + tl_track = self.controller.add(track) self.assertEqual(track, self.controller.tracks[-1]) - self.assertEqual(cp_track, self.controller.cp_tracks[-1]) - self.assertEqual(track, cp_track.track) + self.assertEqual(tl_track, self.controller.tl_tracks[-1]) + self.assertEqual(track, tl_track.track) def test_add_at_position(self): for track in self.tracks[:-1]: - cp_track = self.controller.add(track, 0) + tl_track = self.controller.add(track, 0) self.assertEqual(track, self.controller.tracks[0]) - self.assertEqual(cp_track, self.controller.cp_tracks[0]) - self.assertEqual(track, cp_track.track) + self.assertEqual(tl_track, self.controller.tl_tracks[0]) + self.assertEqual(track, tl_track.track) @populate_playlist def test_add_at_position_outside_of_playlist(self): @@ -53,14 +55,14 @@ class CurrentPlaylistControllerTest(object): self.assertRaises(AssertionError, test) @populate_playlist - def test_get_by_cpid(self): - cp_track = self.controller.cp_tracks[1] - self.assertEqual(cp_track, self.controller.get(cpid=cp_track.cpid)) + def test_get_by_tlid(self): + tl_track = self.controller.tl_tracks[1] + self.assertEqual(tl_track, self.controller.get(tlid=tl_track.tlid)) @populate_playlist def test_get_by_uri(self): - cp_track = self.controller.cp_tracks[1] - self.assertEqual(cp_track, self.controller.get(uri=cp_track.track.uri)) + tl_track = self.controller.tl_tracks[1] + self.assertEqual(tl_track, self.controller.get(uri=tl_track.track.uri)) @populate_playlist def test_get_by_uri_raises_error_for_invalid_uri(self): @@ -93,18 +95,18 @@ class CurrentPlaylistControllerTest(object): self.controller.append([Track(uri='z'), track, track]) try: self.controller.get(uri='a') - self.fail(u'Should raise LookupError if multiple matches') + self.fail('Should raise LookupError if multiple matches') except LookupError as e: - self.assertEqual(u'"uri=a" match multiple tracks', e[0]) + self.assertEqual('"uri=a" match multiple tracks', e[0]) def test_get_by_uri_raises_error_if_no_match(self): self.controller.playlist = Playlist( tracks=[Track(uri='z'), Track(uri='y')]) try: self.controller.get(uri='a') - self.fail(u'Should raise LookupError if no match') + self.fail('Should raise LookupError if no match') except LookupError as e: - self.assertEqual(u'"uri=a" match no tracks', e[0]) + self.assertEqual('"uri=a" match no tracks', e[0]) def test_get_by_multiple_criteria_returns_elements_matching_all(self): track1 = Track(uri='a', name='x') @@ -122,7 +124,7 @@ class CurrentPlaylistControllerTest(object): self.controller.append([track1, track2, track3]) self.assertEqual(track2, self.controller.get(uri='b')[1]) - def test_append_appends_to_the_current_playlist(self): + def test_append_appends_to_the_tracklist(self): self.controller.append([Track(uri='a'), Track(uri='b')]) self.assertEqual(len(self.controller.tracks), 2) self.controller.append([Track(uri='c'), Track(uri='d')]) @@ -152,15 +154,15 @@ class CurrentPlaylistControllerTest(object): self.assertEqual(self.playback.current_track, None) def test_index_returns_index_of_track(self): - cp_tracks = [] + tl_tracks = [] for track in self.tracks: - cp_tracks.append(self.controller.add(track)) - self.assertEquals(0, self.controller.index(cp_tracks[0])) - self.assertEquals(1, self.controller.index(cp_tracks[1])) - self.assertEquals(2, self.controller.index(cp_tracks[2])) + tl_tracks.append(self.controller.add(track)) + self.assertEquals(0, self.controller.index(tl_tracks[0])) + self.assertEquals(1, self.controller.index(tl_tracks[1])) + self.assertEquals(2, self.controller.index(tl_tracks[2])) def test_index_raises_value_error_if_item_not_found(self): - test = lambda: self.controller.index(CpTrack(0, Track())) + test = lambda: self.controller.index(TlTrack(0, Track())) self.assertRaises(ValueError, test) @populate_playlist diff --git a/tests/backends/events_test.py b/tests/backends/events_test.py index 600dbf6c..417c5251 100644 --- a/tests/backends/events_test.py +++ b/tests/backends/events_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import mock import pykka @@ -19,14 +21,14 @@ class BackendEventsTest(unittest.TestCase): pykka.ActorRegistry.stop_all() def test_pause_sends_track_playback_paused_event(self, send): - self.core.current_playlist.add(Track(uri='dummy:a')) + self.core.tracklist.add(Track(uri='dummy:a')) self.core.playback.play().get() send.reset_mock() self.core.playback.pause().get() self.assertEqual(send.call_args[0][0], 'track_playback_paused') def test_resume_sends_track_playback_resumed(self, send): - self.core.current_playlist.add(Track(uri='dummy:a')) + self.core.tracklist.add(Track(uri='dummy:a')) self.core.playback.play() self.core.playback.pause().get() send.reset_mock() @@ -34,20 +36,20 @@ class BackendEventsTest(unittest.TestCase): self.assertEqual(send.call_args[0][0], 'track_playback_resumed') def test_play_sends_track_playback_started_event(self, send): - self.core.current_playlist.add(Track(uri='dummy:a')) + self.core.tracklist.add(Track(uri='dummy:a')) send.reset_mock() self.core.playback.play().get() self.assertEqual(send.call_args[0][0], 'track_playback_started') def test_stop_sends_track_playback_ended_event(self, send): - self.core.current_playlist.add(Track(uri='dummy:a')) + self.core.tracklist.add(Track(uri='dummy:a')) self.core.playback.play().get() send.reset_mock() self.core.playback.stop().get() self.assertEqual(send.call_args_list[0][0][0], 'track_playback_ended') def test_seek_sends_seeked_event(self, send): - self.core.current_playlist.add(Track(uri='dummy:a', length=40000)) + self.core.tracklist.add(Track(uri='dummy:a', length=40000)) self.core.playback.play().get() send.reset_mock() self.core.playback.seek(1000).get() diff --git a/tests/backends/local/__init__.py b/tests/backends/local/__init__.py index d2213297..684e12d8 100644 --- a/tests/backends/local/__init__.py +++ b/tests/backends/local/__init__.py @@ -1,6 +1,9 @@ +from __future__ import unicode_literals + from mopidy.utils.path import path_to_uri from tests import path_to_data_dir + song = path_to_data_dir('song%s.wav') generate_song = lambda i: path_to_uri(song % i) diff --git a/tests/backends/local/library_test.py b/tests/backends/local/library_test.py index 75cebdbc..7324d85f 100644 --- a/tests/backends/local/library_test.py +++ b/tests/backends/local/library_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy import settings from mopidy.backends.local import LocalBackend diff --git a/tests/backends/local/playback_test.py b/tests/backends/local/playback_test.py index fea93ae3..285270ce 100644 --- a/tests/backends/local/playback_test.py +++ b/tests/backends/local/playback_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy import settings from mopidy.backends.local import LocalBackend from mopidy.core import PlaybackState @@ -25,7 +27,7 @@ class LocalPlaybackControllerTest(PlaybackControllerTest, unittest.TestCase): def add_track(self, path): uri = path_to_uri(path_to_data_dir(path)) track = Track(uri=uri, length=4464) - self.current_playlist.add(track) + self.tracklist.add(track) def test_uri_scheme(self): self.assertIn('file', self.core.uri_schemes) diff --git a/tests/backends/local/stored_playlists_test.py b/tests/backends/local/playlists.py similarity index 67% rename from tests/backends/local/stored_playlists_test.py rename to tests/backends/local/playlists.py index cd1ecd3c..fcc39132 100644 --- a/tests/backends/local/stored_playlists_test.py +++ b/tests/backends/local/playlists.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import os from mopidy import settings @@ -6,13 +8,13 @@ from mopidy.models import Track from mopidy.utils.path import path_to_uri from tests import unittest, path_to_data_dir -from tests.backends.base.stored_playlists import ( - StoredPlaylistsControllerTest) +from tests.backends.base.playlists import ( + PlaylistsControllerTest) from tests.backends.local import generate_song -class LocalStoredPlaylistsControllerTest( - StoredPlaylistsControllerTest, unittest.TestCase): +class LocalPlaylistsControllerTest( + PlaylistsControllerTest, unittest.TestCase): backend_class = LocalBackend @@ -20,38 +22,38 @@ class LocalStoredPlaylistsControllerTest( path = os.path.join(settings.LOCAL_PLAYLIST_PATH, 'test.m3u') self.assertFalse(os.path.exists(path)) - self.stored.create(u'test') + self.core.playlists.create('test') self.assertTrue(os.path.exists(path)) def test_create_slugifies_playlist_name(self): path = os.path.join(settings.LOCAL_PLAYLIST_PATH, 'test-foo-bar.m3u') self.assertFalse(os.path.exists(path)) - playlist = self.stored.create(u'test FOO baR') - self.assertEqual(u'test-foo-bar', playlist.name) + playlist = self.core.playlists.create('test FOO baR') + self.assertEqual('test-foo-bar', playlist.name) self.assertTrue(os.path.exists(path)) def test_create_slugifies_names_which_tries_to_change_directory(self): path = os.path.join(settings.LOCAL_PLAYLIST_PATH, 'test-foo-bar.m3u') self.assertFalse(os.path.exists(path)) - playlist = self.stored.create(u'../../test FOO baR') - self.assertEqual(u'test-foo-bar', playlist.name) + playlist = self.core.playlists.create('../../test FOO baR') + self.assertEqual('test-foo-bar', playlist.name) self.assertTrue(os.path.exists(path)) def test_saved_playlist_is_persisted(self): path1 = os.path.join(settings.LOCAL_PLAYLIST_PATH, 'test1.m3u') path2 = os.path.join(settings.LOCAL_PLAYLIST_PATH, 'test2-foo-bar.m3u') - playlist = self.stored.create(u'test1') + playlist = self.core.playlists.create('test1') self.assertTrue(os.path.exists(path1)) self.assertFalse(os.path.exists(path2)) - playlist = playlist.copy(name=u'test2 FOO baR') - playlist = self.stored.save(playlist) + playlist = playlist.copy(name='test2 FOO baR') + playlist = self.core.playlists.save(playlist) - self.assertEqual(u'test2-foo-bar', playlist.name) + self.assertEqual('test2-foo-bar', playlist.name) self.assertFalse(os.path.exists(path1)) self.assertTrue(os.path.exists(path2)) @@ -59,19 +61,19 @@ class LocalStoredPlaylistsControllerTest( path = os.path.join(settings.LOCAL_PLAYLIST_PATH, 'test.m3u') self.assertFalse(os.path.exists(path)) - playlist = self.stored.create(u'test') + playlist = self.core.playlists.create('test') self.assertTrue(os.path.exists(path)) - self.stored.delete(playlist.uri) + self.core.playlists.delete(playlist.uri) self.assertFalse(os.path.exists(path)) def test_playlist_contents_is_written_to_disk(self): track = Track(uri=generate_song(1)) track_path = track.uri[len('file://'):] - playlist = self.stored.create(u'test') + playlist = self.core.playlists.create('test') playlist_path = playlist.uri[len('file://'):] playlist = playlist.copy(tracks=[track]) - playlist = self.stored.save(playlist) + playlist = self.core.playlists.save(playlist) with open(playlist_path) as playlist_file: contents = playlist_file.read() @@ -82,20 +84,20 @@ class LocalStoredPlaylistsControllerTest( playlist_path = os.path.join(settings.LOCAL_PLAYLIST_PATH, 'test.m3u') track = Track(uri=path_to_uri(path_to_data_dir('uri2'))) - playlist = self.stored.create(u'test') + playlist = self.core.playlists.create('test') playlist = playlist.copy(tracks=[track]) - playlist = self.stored.save(playlist) + playlist = self.core.playlists.save(playlist) backend = self.backend_class(audio=self.audio) - self.assert_(backend.stored_playlists.playlists) + self.assert_(backend.playlists.playlists) self.assertEqual( path_to_uri(playlist_path), - backend.stored_playlists.playlists[0].uri) + backend.playlists.playlists[0].uri) self.assertEqual( - playlist.name, backend.stored_playlists.playlists[0].name) + playlist.name, backend.playlists.playlists[0].name) self.assertEqual( - track.uri, backend.stored_playlists.playlists[0].tracks[0].uri) + track.uri, backend.playlists.playlists[0].tracks[0].uri) @unittest.SkipTest def test_santitising_of_playlist_filenames(self): diff --git a/tests/backends/local/current_playlist_test.py b/tests/backends/local/tracklist_test.py similarity index 56% rename from tests/backends/local/current_playlist_test.py rename to tests/backends/local/tracklist_test.py index 52fa9eb5..f5330f52 100644 --- a/tests/backends/local/current_playlist_test.py +++ b/tests/backends/local/tracklist_test.py @@ -1,23 +1,23 @@ +from __future__ import unicode_literals + from mopidy import settings from mopidy.backends.local import LocalBackend from mopidy.models import Track from tests import unittest -from tests.backends.base.current_playlist import CurrentPlaylistControllerTest +from tests.backends.base.tracklist import TracklistControllerTest from tests.backends.local import generate_song -class LocalCurrentPlaylistControllerTest(CurrentPlaylistControllerTest, - unittest.TestCase): - +class LocalTracklistControllerTest(TracklistControllerTest, unittest.TestCase): backend_class = LocalBackend tracks = [ Track(uri=generate_song(i), length=4464) for i in range(1, 4)] def setUp(self): settings.BACKENDS = ('mopidy.backends.local.LocalBackend',) - super(LocalCurrentPlaylistControllerTest, self).setUp() + super(LocalTracklistControllerTest, self).setUp() def tearDown(self): - super(LocalCurrentPlaylistControllerTest, self).tearDown() + super(LocalTracklistControllerTest, self).tearDown() settings.runtime.clear() diff --git a/tests/backends/local/translator_test.py b/tests/backends/local/translator_test.py index 6f754399..e18b13fe 100644 --- a/tests/backends/local/translator_test.py +++ b/tests/backends/local/translator_test.py @@ -1,5 +1,7 @@ # encoding: utf-8 +from __future__ import unicode_literals + import os import tempfile @@ -12,7 +14,7 @@ from tests import unittest, path_to_data_dir data_dir = path_to_data_dir('') song1_path = path_to_data_dir('song1.mp3') song2_path = path_to_data_dir('song2.mp3') -encoded_path = path_to_data_dir(u'æøå.mp3') +encoded_path = path_to_data_dir('æøå.mp3') song1_uri = path_to_uri(song1_path) song2_uri = path_to_uri(song2_path) encoded_uri = path_to_uri(encoded_path) @@ -138,10 +140,10 @@ class MPDTagCacheToTracksTest(unittest.TestCase): path_to_data_dir('utf8_tag_cache'), path_to_data_dir('')) uri = path_to_uri(path_to_data_dir('song1.mp3')) - artists = [Artist(name=u'æøå')] - album = Album(name=u'æøå', artists=artists) + artists = [Artist(name='æøå')] + album = Album(name='æøå', artists=artists) track = Track( - uri=uri, name=u'æøå', artists=artists, album=album, length=4000) + uri=uri, name='æøå', artists=artists, album=album, length=4000) self.assertEqual(track, list(tracks)[0]) diff --git a/tests/core/__init__.py b/tests/core/__init__.py index e69de29b..baffc488 100644 --- a/tests/core/__init__.py +++ b/tests/core/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/tests/core/actor_test.py b/tests/core/actor_test.py index 8212c1da..d86b8702 100644 --- a/tests/core/actor_test.py +++ b/tests/core/actor_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import mock import pykka @@ -26,8 +28,8 @@ class CoreActorTest(unittest.TestCase): self.assertIn('dummy2', result) def test_backends_with_colliding_uri_schemes_fails(self): - self.backend1.__class__.__name__ = 'B1' - self.backend2.__class__.__name__ = 'B2' + self.backend1.__class__.__name__ = b'B1' + self.backend2.__class__.__name__ = b'B2' self.backend2.uri_schemes.get.return_value = ['dummy1', 'dummy2'] self.assertRaisesRegexp( AssertionError, diff --git a/tests/core/library_test.py b/tests/core/library_test.py index 04f19909..7886b85c 100644 --- a/tests/core/library_test.py +++ b/tests/core/library_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import mock from mopidy.backends import base @@ -19,7 +21,13 @@ class CoreLibraryTest(unittest.TestCase): self.library2 = mock.Mock(spec=base.BaseLibraryProvider) self.backend2.library = self.library2 - self.core = Core(audio=None, backends=[self.backend1, self.backend2]) + # A backend without the optional library provider + self.backend3 = mock.Mock() + self.backend3.uri_schemes.get.return_value = ['dummy3'] + self.backend3.has_library().get.return_value = False + + self.core = Core(audio=None, backends=[ + self.backend1, self.backend2, self.backend3]) def test_lookup_selects_dummy1_backend(self): self.core.library.lookup('dummy1:a') @@ -33,6 +41,13 @@ class CoreLibraryTest(unittest.TestCase): self.assertFalse(self.library1.lookup.called) self.library2.lookup.assert_called_once_with('dummy2:a') + def test_lookup_fails_for_dummy3_track(self): + result = self.core.library.lookup('dummy3:a') + + self.assertIsNone(result) + self.assertFalse(self.library1.lookup.called) + self.assertFalse(self.library2.lookup.called) + def test_refresh_with_uri_selects_dummy1_backend(self): self.core.library.refresh('dummy1:a') @@ -45,6 +60,12 @@ class CoreLibraryTest(unittest.TestCase): self.assertFalse(self.library1.refresh.called) self.library2.refresh.assert_called_once_with('dummy2:a') + def test_refresh_with_uri_fails_silently_for_dummy3_uri(self): + self.core.library.refresh('dummy3:a') + + self.assertFalse(self.library1.refresh.called) + self.assertFalse(self.library2.refresh.called) + def test_refresh_without_uri_calls_all_backends(self): self.core.library.refresh() diff --git a/tests/core/listener_test.py b/tests/core/listener_test.py index 2abd9479..0bc3f8fd 100644 --- a/tests/core/listener_test.py +++ b/tests/core/listener_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy.core import CoreListener, PlaybackState from mopidy.models import Track diff --git a/tests/core/playback_test.py b/tests/core/playback_test.py index b3a75773..8e83f971 100644 --- a/tests/core/playback_test.py +++ b/tests/core/playback_test.py @@ -1,7 +1,9 @@ +from __future__ import unicode_literals + import mock from mopidy.backends import base -from mopidy.core import Core +from mopidy.core import Core, PlaybackState from mopidy.models import Track from tests import unittest @@ -19,46 +21,70 @@ class CorePlaybackTest(unittest.TestCase): self.playback2 = mock.Mock(spec=base.BasePlaybackProvider) self.backend2.playback = self.playback2 + # A backend without the optional playback provider + self.backend3 = mock.Mock() + self.backend3.uri_schemes.get.return_value = ['dummy3'] + self.backend3.has_playback().get.return_value = False + self.tracks = [ - Track(uri='dummy1://foo', length=40000), - Track(uri='dummy1://bar', length=40000), - Track(uri='dummy2://foo', length=40000), - Track(uri='dummy2://bar', length=40000), + Track(uri='dummy1:a', length=40000), + Track(uri='dummy2:a', length=40000), + Track(uri='dummy3:a', length=40000), # Unplayable + Track(uri='dummy1:b', length=40000), ] - self.core = Core(audio=None, backends=[self.backend1, self.backend2]) - self.core.current_playlist.append(self.tracks) + self.core = Core(audio=None, backends=[ + self.backend1, self.backend2, self.backend3]) + self.core.tracklist.append(self.tracks) - self.cp_tracks = self.core.current_playlist.cp_tracks + self.tl_tracks = self.core.tracklist.tl_tracks + self.unplayable_tl_track = self.tl_tracks[2] def test_play_selects_dummy1_backend(self): - self.core.playback.play(self.cp_tracks[0]) + self.core.playback.play(self.tl_tracks[0]) self.playback1.play.assert_called_once_with(self.tracks[0]) self.assertFalse(self.playback2.play.called) def test_play_selects_dummy2_backend(self): - self.core.playback.play(self.cp_tracks[2]) + self.core.playback.play(self.tl_tracks[1]) self.assertFalse(self.playback1.play.called) - self.playback2.play.assert_called_once_with(self.tracks[2]) + self.playback2.play.assert_called_once_with(self.tracks[1]) + + def test_play_skips_to_next_on_unplayable_track(self): + self.core.playback.play(self.unplayable_tl_track) + + self.playback1.play.assert_called_once_with(self.tracks[3]) + self.assertFalse(self.playback2.play.called) + + self.assertEqual(self.core.playback.current_tl_track, + self.tl_tracks[3]) def test_pause_selects_dummy1_backend(self): - self.core.playback.play(self.cp_tracks[0]) + self.core.playback.play(self.tl_tracks[0]) self.core.playback.pause() self.playback1.pause.assert_called_once_with() self.assertFalse(self.playback2.pause.called) def test_pause_selects_dummy2_backend(self): - self.core.playback.play(self.cp_tracks[2]) + self.core.playback.play(self.tl_tracks[1]) self.core.playback.pause() self.assertFalse(self.playback1.pause.called) self.playback2.pause.assert_called_once_with() + def test_pause_changes_state_even_if_track_is_unplayable(self): + self.core.playback.current_tl_track = self.unplayable_tl_track + self.core.playback.pause() + + self.assertEqual(self.core.playback.state, PlaybackState.PAUSED) + self.assertFalse(self.playback1.pause.called) + self.assertFalse(self.playback2.pause.called) + def test_resume_selects_dummy1_backend(self): - self.core.playback.play(self.cp_tracks[0]) + self.core.playback.play(self.tl_tracks[0]) self.core.playback.pause() self.core.playback.resume() @@ -66,43 +92,70 @@ class CorePlaybackTest(unittest.TestCase): self.assertFalse(self.playback2.resume.called) def test_resume_selects_dummy2_backend(self): - self.core.playback.play(self.cp_tracks[2]) + self.core.playback.play(self.tl_tracks[1]) self.core.playback.pause() self.core.playback.resume() self.assertFalse(self.playback1.resume.called) self.playback2.resume.assert_called_once_with() + def test_resume_does_nothing_if_track_is_unplayable(self): + self.core.playback.current_tl_track = self.unplayable_tl_track + self.core.playback.state = PlaybackState.PAUSED + self.core.playback.resume() + + self.assertEqual(self.core.playback.state, PlaybackState.PAUSED) + self.assertFalse(self.playback1.resume.called) + self.assertFalse(self.playback2.resume.called) + def test_stop_selects_dummy1_backend(self): - self.core.playback.play(self.cp_tracks[0]) + self.core.playback.play(self.tl_tracks[0]) self.core.playback.stop() self.playback1.stop.assert_called_once_with() self.assertFalse(self.playback2.stop.called) def test_stop_selects_dummy2_backend(self): - self.core.playback.play(self.cp_tracks[2]) + self.core.playback.play(self.tl_tracks[1]) self.core.playback.stop() self.assertFalse(self.playback1.stop.called) self.playback2.stop.assert_called_once_with() + def test_stop_changes_state_even_if_track_is_unplayable(self): + self.core.playback.current_tl_track = self.unplayable_tl_track + self.core.playback.state = PlaybackState.PAUSED + self.core.playback.stop() + + self.assertEqual(self.core.playback.state, PlaybackState.STOPPED) + self.assertFalse(self.playback1.stop.called) + self.assertFalse(self.playback2.stop.called) + def test_seek_selects_dummy1_backend(self): - self.core.playback.play(self.cp_tracks[0]) + self.core.playback.play(self.tl_tracks[0]) self.core.playback.seek(10000) self.playback1.seek.assert_called_once_with(10000) self.assertFalse(self.playback2.seek.called) def test_seek_selects_dummy2_backend(self): - self.core.playback.play(self.cp_tracks[2]) + self.core.playback.play(self.tl_tracks[1]) self.core.playback.seek(10000) self.assertFalse(self.playback1.seek.called) self.playback2.seek.assert_called_once_with(10000) + def test_seek_fails_for_unplayable_track(self): + self.core.playback.current_tl_track = self.unplayable_tl_track + self.core.playback.state = PlaybackState.PLAYING + success = self.core.playback.seek(1000) + + self.assertFalse(success) + self.assertFalse(self.playback1.seek.called) + self.assertFalse(self.playback2.seek.called) + def test_time_position_selects_dummy1_backend(self): - self.core.playback.play(self.cp_tracks[0]) + self.core.playback.play(self.tl_tracks[0]) self.core.playback.seek(10000) self.core.playback.time_position @@ -110,9 +163,18 @@ class CorePlaybackTest(unittest.TestCase): self.assertFalse(self.playback2.get_time_position.called) def test_time_position_selects_dummy2_backend(self): - self.core.playback.play(self.cp_tracks[2]) + self.core.playback.play(self.tl_tracks[1]) self.core.playback.seek(10000) self.core.playback.time_position self.assertFalse(self.playback1.get_time_position.called) self.playback2.get_time_position.assert_called_once_with() + + def test_time_position_returns_0_if_track_is_unplayable(self): + self.core.playback.current_tl_track = self.unplayable_tl_track + + result = self.core.playback.time_position + + self.assertEqual(result, 0) + self.assertFalse(self.playback1.get_time_position.called) + self.assertFalse(self.playback2.get_time_position.called) diff --git a/tests/core/stored_playlists_test.py b/tests/core/playlists.py similarity index 58% rename from tests/core/stored_playlists_test.py rename to tests/core/playlists.py index b0d48512..949625fe 100644 --- a/tests/core/stored_playlists_test.py +++ b/tests/core/playlists.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import mock from mopidy.backends import base @@ -7,17 +9,23 @@ from mopidy.models import Playlist, Track from tests import unittest -class StoredPlaylistsTest(unittest.TestCase): +class PlaylistsTest(unittest.TestCase): def setUp(self): self.backend1 = mock.Mock() self.backend1.uri_schemes.get.return_value = ['dummy1'] - self.sp1 = mock.Mock(spec=base.BaseStoredPlaylistsProvider) - self.backend1.stored_playlists = self.sp1 + self.sp1 = mock.Mock(spec=base.BasePlaylistsProvider) + self.backend1.playlists = self.sp1 self.backend2 = mock.Mock() self.backend2.uri_schemes.get.return_value = ['dummy2'] - self.sp2 = mock.Mock(spec=base.BaseStoredPlaylistsProvider) - self.backend2.stored_playlists = self.sp2 + self.sp2 = mock.Mock(spec=base.BasePlaylistsProvider) + self.backend2.playlists = self.sp2 + + # A backend without the optional playlists provider + self.backend3 = mock.Mock() + self.backend3.uri_schemes.get.return_value = ['dummy3'] + self.backend3.has_playlists().get.return_value = False + self.backend3.playlists = None self.pl1a = Playlist(tracks=[Track(uri='dummy1:a')]) self.pl1b = Playlist(tracks=[Track(uri='dummy1:b')]) @@ -27,10 +35,11 @@ class StoredPlaylistsTest(unittest.TestCase): self.pl2b = Playlist(tracks=[Track(uri='dummy2:b')]) self.sp2.playlists.get.return_value = [self.pl2a, self.pl2b] - self.core = Core(audio=None, backends=[self.backend1, self.backend2]) + self.core = Core(audio=None, backends=[ + self.backend3, self.backend1, self.backend2]) def test_get_playlists_combines_result_from_backends(self): - result = self.core.stored_playlists.playlists + result = self.core.playlists.playlists self.assertIn(self.pl1a, result) self.assertIn(self.pl1b, result) @@ -42,7 +51,7 @@ class StoredPlaylistsTest(unittest.TestCase): self.sp1.create().get.return_value = playlist self.sp1.reset_mock() - result = self.core.stored_playlists.create('foo') + result = self.core.playlists.create('foo') self.assertEqual(playlist, result) self.sp1.create.assert_called_once_with('foo') @@ -53,56 +62,86 @@ class StoredPlaylistsTest(unittest.TestCase): self.sp2.create().get.return_value = playlist self.sp2.reset_mock() - result = self.core.stored_playlists.create('foo', uri_scheme='dummy2') + result = self.core.playlists.create('foo', uri_scheme='dummy2') self.assertEqual(playlist, result) self.assertFalse(self.sp1.create.called) self.sp2.create.assert_called_once_with('foo') + def test_create_with_unsupported_uri_scheme_uses_first_backend(self): + playlist = Playlist() + self.sp1.create().get.return_value = playlist + self.sp1.reset_mock() + + result = self.core.playlists.create('foo', uri_scheme='dummy3') + + self.assertEqual(playlist, result) + self.sp1.create.assert_called_once_with('foo') + self.assertFalse(self.sp2.create.called) + def test_delete_selects_the_dummy1_backend(self): - self.core.stored_playlists.delete('dummy1:a') + self.core.playlists.delete('dummy1:a') self.sp1.delete.assert_called_once_with('dummy1:a') self.assertFalse(self.sp2.delete.called) def test_delete_selects_the_dummy2_backend(self): - self.core.stored_playlists.delete('dummy2:a') + self.core.playlists.delete('dummy2:a') self.assertFalse(self.sp1.delete.called) self.sp2.delete.assert_called_once_with('dummy2:a') def test_delete_with_unknown_uri_scheme_does_nothing(self): - self.core.stored_playlists.delete('unknown:a') + self.core.playlists.delete('unknown:a') + + self.assertFalse(self.sp1.delete.called) + self.assertFalse(self.sp2.delete.called) + + def test_delete_ignores_backend_without_playlist_support(self): + self.core.playlists.delete('dummy3:a') self.assertFalse(self.sp1.delete.called) self.assertFalse(self.sp2.delete.called) def test_lookup_selects_the_dummy1_backend(self): - self.core.stored_playlists.lookup('dummy1:a') + self.core.playlists.lookup('dummy1:a') self.sp1.lookup.assert_called_once_with('dummy1:a') self.assertFalse(self.sp2.lookup.called) def test_lookup_selects_the_dummy2_backend(self): - self.core.stored_playlists.lookup('dummy2:a') + self.core.playlists.lookup('dummy2:a') self.assertFalse(self.sp1.lookup.called) self.sp2.lookup.assert_called_once_with('dummy2:a') + def test_lookup_track_in_backend_without_playlists_fails(self): + result = self.core.playlists.lookup('dummy3:a') + + self.assertIsNone(result) + self.assertFalse(self.sp1.lookup.called) + self.assertFalse(self.sp2.lookup.called) + def test_refresh_without_uri_scheme_refreshes_all_backends(self): - self.core.stored_playlists.refresh() + self.core.playlists.refresh() self.sp1.refresh.assert_called_once_with() self.sp2.refresh.assert_called_once_with() def test_refresh_with_uri_scheme_refreshes_matching_backend(self): - self.core.stored_playlists.refresh(uri_scheme='dummy2') + self.core.playlists.refresh(uri_scheme='dummy2') self.assertFalse(self.sp1.refresh.called) self.sp2.refresh.assert_called_once_with() def test_refresh_with_unknown_uri_scheme_refreshes_nothing(self): - self.core.stored_playlists.refresh(uri_scheme='foobar') + self.core.playlists.refresh(uri_scheme='foobar') + + self.assertFalse(self.sp1.refresh.called) + self.assertFalse(self.sp2.refresh.called) + + def test_refresh_ignores_backend_without_playlist_support(self): + self.core.playlists.refresh(uri_scheme='dummy3') self.assertFalse(self.sp1.refresh.called) self.assertFalse(self.sp2.refresh.called) @@ -112,7 +151,7 @@ class StoredPlaylistsTest(unittest.TestCase): self.sp1.save().get.return_value = playlist self.sp1.reset_mock() - result = self.core.stored_playlists.save(playlist) + result = self.core.playlists.save(playlist) self.assertEqual(playlist, result) self.sp1.save.assert_called_once_with(playlist) @@ -123,21 +162,28 @@ class StoredPlaylistsTest(unittest.TestCase): self.sp2.save().get.return_value = playlist self.sp2.reset_mock() - result = self.core.stored_playlists.save(playlist) + result = self.core.playlists.save(playlist) self.assertEqual(playlist, result) self.assertFalse(self.sp1.save.called) self.sp2.save.assert_called_once_with(playlist) def test_save_does_nothing_if_playlist_uri_is_unset(self): - result = self.core.stored_playlists.save(Playlist()) + result = self.core.playlists.save(Playlist()) self.assertIsNone(result) self.assertFalse(self.sp1.save.called) self.assertFalse(self.sp2.save.called) def test_save_does_nothing_if_playlist_uri_has_unknown_scheme(self): - result = self.core.stored_playlists.save(Playlist(uri='foobar:a')) + result = self.core.playlists.save(Playlist(uri='foobar:a')) + + self.assertIsNone(result) + self.assertFalse(self.sp1.save.called) + self.assertFalse(self.sp2.save.called) + + def test_save_ignores_backend_without_playlist_support(self): + result = self.core.playlists.save(Playlist(uri='dummy3:a')) self.assertIsNone(result) self.assertFalse(self.sp1.save.called) diff --git a/tests/frontends/__init__.py b/tests/frontends/__init__.py index e69de29b..baffc488 100644 --- a/tests/frontends/__init__.py +++ b/tests/frontends/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/tests/frontends/http/api_test.py b/tests/frontends/http/api_test.py index 14f94773..88aa5682 100644 --- a/tests/frontends/http/api_test.py +++ b/tests/frontends/http/api_test.py @@ -14,10 +14,10 @@ class ApiResourceTest(unittest.TestCase): self.core = core.Core.start(backends=[self.backend]).proxy() self.api = api.ApiResource(core=self.core) - self.core.stored_playlists.create('x') - self.core.stored_playlists.create('y') - self.core.stored_playlists.create('z') - self.core.current_playlist.append([ + self.core.playlists.create('x') + self.core.playlists.create('y') + self.core.playlists.create('z') + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b'), Track(uri='dummy:c'), @@ -86,30 +86,30 @@ class ApiResourceTest(unittest.TestCase): self.assertEqual(37, result['properties']['volume']) - def test_tracklist_returns_current_playlist(self): + def test_tracklist_returns_tracklist(self): result = self.api.tracklist.GET() self.assertIn('tracks', result) self.assertEqual(3, len(result['tracks'])) self.assertEqual('dummy:a', result['tracks'][0]['uri']) - self.assertEqual(0, result['tracks'][0]['cpid']) + self.assertEqual(0, result['tracks'][0]['tlid']) self.assertEqual('dummy:b', result['tracks'][1]['uri']) - self.assertEqual(1, result['tracks'][1]['cpid']) + self.assertEqual(1, result['tracks'][1]['tlid']) self.assertEqual('dummy:c', result['tracks'][2]['uri']) - self.assertEqual(2, result['tracks'][2]['cpid']) + self.assertEqual(2, result['tracks'][2]['tlid']) def test_tracklist_includes_current_track(self): self.core.playback.play() result = self.api.tracklist.GET() - self.assertIn('currentTrackCpid', result) - self.assertEqual(0, result['currentTrackCpid']) + self.assertIn('currentTrackTlid', result) + self.assertEqual(0, result['currentTrackTlid']) - def test_playlists_returns_stored_playlists(self): + def test_playlists_returns_playlists(self): result = self.api.playlists.GET() self.assertIn('playlists', result) diff --git a/tests/frontends/mpd/__init__.py b/tests/frontends/mpd/__init__.py index e69de29b..baffc488 100644 --- a/tests/frontends/mpd/__init__.py +++ b/tests/frontends/mpd/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/tests/frontends/mpd/dispatcher_test.py b/tests/frontends/mpd/dispatcher_test.py index 9b047641..3404db95 100644 --- a/tests/frontends/mpd/dispatcher_test.py +++ b/tests/frontends/mpd/dispatcher_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import pykka from mopidy import core @@ -34,7 +36,7 @@ class MpdDispatcherTest(unittest.TestCase): except MpdAckError as e: self.assertEqual( e.get_mpd_ack(), - u'ACK [5@0] {} unknown command "an_unknown_command"') + 'ACK [5@0] {} unknown command "an_unknown_command"') def test_find_handler_for_known_command_returns_handler_and_kwargs(self): expected_handler = lambda x: None @@ -48,11 +50,11 @@ class MpdDispatcherTest(unittest.TestCase): def test_handling_unknown_request_yields_error(self): result = self.dispatcher.handle_request('an unhandled request') - self.assertEqual(result[0], u'ACK [5@0] {} unknown command "an"') + self.assertEqual(result[0], 'ACK [5@0] {} unknown command "an"') def test_handling_known_request(self): expected = 'magic' request_handlers['known request'] = lambda x: expected result = self.dispatcher.handle_request('known request') - self.assertIn(u'OK', result) + self.assertIn('OK', result) self.assertIn(expected, result) diff --git a/tests/frontends/mpd/exception_test.py b/tests/frontends/mpd/exception_test.py index 8fb0c933..fe834673 100644 --- a/tests/frontends/mpd/exception_test.py +++ b/tests/frontends/mpd/exception_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy.frontends.mpd.exceptions import ( MpdAckError, MpdPermissionError, MpdUnknownCommand, MpdSystemError, MpdNotImplemented) @@ -9,35 +11,35 @@ class MpdExceptionsTest(unittest.TestCase): def test_key_error_wrapped_in_mpd_ack_error(self): try: try: - raise KeyError(u'Track X not found') + raise KeyError('Track X not found') except KeyError as e: raise MpdAckError(e[0]) except MpdAckError as e: - self.assertEqual(e.message, u'Track X not found') + self.assertEqual(e.message, 'Track X not found') def test_mpd_not_implemented_is_a_mpd_ack_error(self): try: raise MpdNotImplemented except MpdAckError as e: - self.assertEqual(e.message, u'Not implemented') + self.assertEqual(e.message, 'Not implemented') def test_get_mpd_ack_with_default_values(self): e = MpdAckError('A description') - self.assertEqual(e.get_mpd_ack(), u'ACK [0@0] {} A description') + self.assertEqual(e.get_mpd_ack(), 'ACK [0@0] {} A description') def test_get_mpd_ack_with_values(self): try: raise MpdAckError('A description', index=7, command='foo') except MpdAckError as e: - self.assertEqual(e.get_mpd_ack(), u'ACK [0@7] {foo} A description') + self.assertEqual(e.get_mpd_ack(), 'ACK [0@7] {foo} A description') def test_mpd_unknown_command(self): try: - raise MpdUnknownCommand(command=u'play') + raise MpdUnknownCommand(command='play') except MpdAckError as e: self.assertEqual( e.get_mpd_ack(), - u'ACK [5@0] {} unknown command "play"') + 'ACK [5@0] {} unknown command "play"') def test_mpd_system_error(self): try: @@ -45,7 +47,7 @@ class MpdExceptionsTest(unittest.TestCase): except MpdSystemError as e: self.assertEqual( e.get_mpd_ack(), - u'ACK [52@0] {} foo') + 'ACK [52@0] {} foo') def test_mpd_permission_error(self): try: @@ -53,4 +55,4 @@ class MpdExceptionsTest(unittest.TestCase): except MpdPermissionError as e: self.assertEqual( e.get_mpd_ack(), - u'ACK [4@0] {foo} you don\'t have permission for "foo"') + 'ACK [4@0] {foo} you don\'t have permission for "foo"') diff --git a/tests/frontends/mpd/protocol/__init__.py b/tests/frontends/mpd/protocol/__init__.py index f7b055fc..00594206 100644 --- a/tests/frontends/mpd/protocol/__init__.py +++ b/tests/frontends/mpd/protocol/__init__.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import mock import pykka @@ -46,20 +48,20 @@ class BaseTestCase(unittest.TestCase): def assertInResponse(self, value): self.assertIn( value, self.connection.response, - u'Did not find %s in %s' % ( + 'Did not find %s in %s' % ( repr(value), repr(self.connection.response))) def assertOnceInResponse(self, value): matched = len([r for r in self.connection.response if r == value]) self.assertEqual( 1, matched, - u'Expected to find %s once in %s' % ( + 'Expected to find %s once in %s' % ( repr(value), repr(self.connection.response))) def assertNotInResponse(self, value): self.assertNotIn( value, self.connection.response, - u'Found %s in %s' % ( + 'Found %s in %s' % ( repr(value), repr(self.connection.response))) def assertEqualResponse(self, value): diff --git a/tests/frontends/mpd/protocol/audio_output_test.py b/tests/frontends/mpd/protocol/audio_output_test.py index 3bb8dce8..11cd249e 100644 --- a/tests/frontends/mpd/protocol/audio_output_test.py +++ b/tests/frontends/mpd/protocol/audio_output_test.py @@ -1,18 +1,20 @@ +from __future__ import unicode_literals + from tests.frontends.mpd import protocol class AudioOutputHandlerTest(protocol.BaseTestCase): def test_enableoutput(self): - self.sendRequest(u'enableoutput "0"') - self.assertInResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('enableoutput "0"') + self.assertInResponse('ACK [0@0] {} Not implemented') def test_disableoutput(self): - self.sendRequest(u'disableoutput "0"') - self.assertInResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('disableoutput "0"') + self.assertInResponse('ACK [0@0] {} Not implemented') def test_outputs(self): - self.sendRequest(u'outputs') - self.assertInResponse(u'outputid: 0') - self.assertInResponse(u'outputname: None') - self.assertInResponse(u'outputenabled: 1') - self.assertInResponse(u'OK') + self.sendRequest('outputs') + self.assertInResponse('outputid: 0') + self.assertInResponse('outputname: None') + self.assertInResponse('outputenabled: 1') + self.assertInResponse('OK') diff --git a/tests/frontends/mpd/protocol/authentication_test.py b/tests/frontends/mpd/protocol/authentication_test.py index 0f0d9c86..26b03f45 100644 --- a/tests/frontends/mpd/protocol/authentication_test.py +++ b/tests/frontends/mpd/protocol/authentication_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy import settings from tests.frontends.mpd import protocol @@ -7,28 +9,28 @@ class AuthenticationTest(protocol.BaseTestCase): def test_authentication_with_valid_password_is_accepted(self): settings.MPD_SERVER_PASSWORD = u'topsecret' - self.sendRequest(u'password "topsecret"') + self.sendRequest('password "topsecret"') self.assertTrue(self.dispatcher.authenticated) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_authentication_with_invalid_password_is_not_accepted(self): settings.MPD_SERVER_PASSWORD = u'topsecret' - self.sendRequest(u'password "secret"') + self.sendRequest('password "secret"') self.assertFalse(self.dispatcher.authenticated) - self.assertEqualResponse(u'ACK [3@0] {password} incorrect password') + self.assertEqualResponse('ACK [3@0] {password} incorrect password') def test_authentication_with_anything_when_password_check_turned_off(self): settings.MPD_SERVER_PASSWORD = None - self.sendRequest(u'any request at all') + self.sendRequest('any request at all') self.assertTrue(self.dispatcher.authenticated) self.assertEqualResponse('ACK [5@0] {} unknown command "any"') def test_anything_when_not_authenticated_should_fail(self): settings.MPD_SERVER_PASSWORD = u'topsecret' - self.sendRequest(u'any request at all') + self.sendRequest('any request at all') self.assertFalse(self.dispatcher.authenticated) self.assertEqualResponse( u'ACK [4@0] {any} you don\'t have permission for "any"') @@ -36,26 +38,26 @@ class AuthenticationTest(protocol.BaseTestCase): def test_close_is_allowed_without_authentication(self): settings.MPD_SERVER_PASSWORD = u'topsecret' - self.sendRequest(u'close') + self.sendRequest('close') self.assertFalse(self.dispatcher.authenticated) def test_commands_is_allowed_without_authentication(self): settings.MPD_SERVER_PASSWORD = u'topsecret' - self.sendRequest(u'commands') + self.sendRequest('commands') self.assertFalse(self.dispatcher.authenticated) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_notcommands_is_allowed_without_authentication(self): settings.MPD_SERVER_PASSWORD = u'topsecret' - self.sendRequest(u'notcommands') + self.sendRequest('notcommands') self.assertFalse(self.dispatcher.authenticated) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_ping_is_allowed_without_authentication(self): settings.MPD_SERVER_PASSWORD = u'topsecret' - self.sendRequest(u'ping') + self.sendRequest('ping') self.assertFalse(self.dispatcher.authenticated) - self.assertInResponse(u'OK') + self.assertInResponse('OK') diff --git a/tests/frontends/mpd/protocol/command_list_test.py b/tests/frontends/mpd/protocol/command_list_test.py index dbd7f9c9..222dcb61 100644 --- a/tests/frontends/mpd/protocol/command_list_test.py +++ b/tests/frontends/mpd/protocol/command_list_test.py @@ -1,59 +1,61 @@ +from __future__ import unicode_literals + from tests.frontends.mpd import protocol class CommandListsTest(protocol.BaseTestCase): def test_command_list_begin(self): - response = self.sendRequest(u'command_list_begin') + response = self.sendRequest('command_list_begin') self.assertEquals([], response) def test_command_list_end(self): - self.sendRequest(u'command_list_begin') - self.sendRequest(u'command_list_end') - self.assertInResponse(u'OK') + self.sendRequest('command_list_begin') + self.sendRequest('command_list_end') + self.assertInResponse('OK') def test_command_list_end_without_start_first_is_an_unknown_command(self): - self.sendRequest(u'command_list_end') + self.sendRequest('command_list_end') self.assertEqualResponse( - u'ACK [5@0] {} unknown command "command_list_end"') + 'ACK [5@0] {} unknown command "command_list_end"') def test_command_list_with_ping(self): - self.sendRequest(u'command_list_begin') + self.sendRequest('command_list_begin') self.assertTrue(self.dispatcher.command_list_receiving) self.assertFalse(self.dispatcher.command_list_ok) self.assertEqual([], self.dispatcher.command_list) - self.sendRequest(u'ping') - self.assertIn(u'ping', self.dispatcher.command_list) + self.sendRequest('ping') + self.assertIn('ping', self.dispatcher.command_list) - self.sendRequest(u'command_list_end') - self.assertInResponse(u'OK') + self.sendRequest('command_list_end') + self.assertInResponse('OK') self.assertFalse(self.dispatcher.command_list_receiving) self.assertFalse(self.dispatcher.command_list_ok) self.assertEqual([], self.dispatcher.command_list) def test_command_list_with_error_returns_ack_with_correct_index(self): - self.sendRequest(u'command_list_begin') - self.sendRequest(u'play') # Known command - self.sendRequest(u'paly') # Unknown command - self.sendRequest(u'command_list_end') - self.assertEqualResponse(u'ACK [5@1] {} unknown command "paly"') + self.sendRequest('command_list_begin') + self.sendRequest('play') # Known command + self.sendRequest('paly') # Unknown command + self.sendRequest('command_list_end') + self.assertEqualResponse('ACK [5@1] {} unknown command "paly"') def test_command_list_ok_begin(self): - response = self.sendRequest(u'command_list_ok_begin') + response = self.sendRequest('command_list_ok_begin') self.assertEquals([], response) def test_command_list_ok_with_ping(self): - self.sendRequest(u'command_list_ok_begin') + self.sendRequest('command_list_ok_begin') self.assertTrue(self.dispatcher.command_list_receiving) self.assertTrue(self.dispatcher.command_list_ok) self.assertEqual([], self.dispatcher.command_list) - self.sendRequest(u'ping') - self.assertIn(u'ping', self.dispatcher.command_list) + self.sendRequest('ping') + self.assertIn('ping', self.dispatcher.command_list) - self.sendRequest(u'command_list_end') - self.assertInResponse(u'list_OK') - self.assertInResponse(u'OK') + self.sendRequest('command_list_end') + self.assertInResponse('list_OK') + self.assertInResponse('OK') self.assertFalse(self.dispatcher.command_list_receiving) self.assertFalse(self.dispatcher.command_list_ok) self.assertEqual([], self.dispatcher.command_list) diff --git a/tests/frontends/mpd/protocol/connection_test.py b/tests/frontends/mpd/protocol/connection_test.py index 9b8972d3..840ce48f 100644 --- a/tests/frontends/mpd/protocol/connection_test.py +++ b/tests/frontends/mpd/protocol/connection_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mock import patch from mopidy import settings @@ -8,37 +10,37 @@ from tests.frontends.mpd import protocol class ConnectionHandlerTest(protocol.BaseTestCase): def test_close_closes_the_client_connection(self): with patch.object(self.session, 'close') as close_mock: - self.sendRequest(u'close') + self.sendRequest('close') close_mock.assertEqualResponsecalled_once_with() - self.assertEqualResponse(u'OK') + self.assertEqualResponse('OK') def test_empty_request(self): - self.sendRequest(u'') - self.assertEqualResponse(u'OK') + self.sendRequest('') + self.assertEqualResponse('OK') - self.sendRequest(u' ') - self.assertEqualResponse(u'OK') + self.sendRequest(' ') + self.assertEqualResponse('OK') def test_kill(self): - self.sendRequest(u'kill') + self.sendRequest('kill') self.assertEqualResponse( - u'ACK [4@0] {kill} you don\'t have permission for "kill"') + 'ACK [4@0] {kill} you don\'t have permission for "kill"') def test_valid_password_is_accepted(self): - settings.MPD_SERVER_PASSWORD = u'topsecret' - self.sendRequest(u'password "topsecret"') - self.assertEqualResponse(u'OK') + settings.MPD_SERVER_PASSWORD = 'topsecret' + self.sendRequest('password "topsecret"') + self.assertEqualResponse('OK') def test_invalid_password_is_not_accepted(self): - settings.MPD_SERVER_PASSWORD = u'topsecret' - self.sendRequest(u'password "secret"') - self.assertEqualResponse(u'ACK [3@0] {password} incorrect password') + settings.MPD_SERVER_PASSWORD = 'topsecret' + self.sendRequest('password "secret"') + self.assertEqualResponse('ACK [3@0] {password} incorrect password') def test_any_password_is_not_accepted_when_password_check_turned_off(self): settings.MPD_SERVER_PASSWORD = None - self.sendRequest(u'password "secret"') - self.assertEqualResponse(u'ACK [3@0] {password} incorrect password') + self.sendRequest('password "secret"') + self.assertEqualResponse('ACK [3@0] {password} incorrect password') def test_ping(self): - self.sendRequest(u'ping') - self.assertEqualResponse(u'OK') + self.sendRequest('ping') + self.assertEqualResponse('OK') diff --git a/tests/frontends/mpd/protocol/current_playlist_test.py b/tests/frontends/mpd/protocol/current_playlist_test.py index bd58cf2d..2b6fdbd5 100644 --- a/tests/frontends/mpd/protocol/current_playlist_test.py +++ b/tests/frontends/mpd/protocol/current_playlist_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy.models import Track from tests.frontends.mpd import protocol @@ -8,498 +10,498 @@ class CurrentPlaylistHandlerTest(protocol.BaseTestCase): needle = Track(uri='dummy://foo') self.backend.library.dummy_library = [ Track(), Track(), needle, Track()] - self.core.current_playlist.append( + self.core.tracklist.append( [Track(), Track(), Track(), Track(), Track()]) - self.assertEqual(len(self.core.current_playlist.tracks.get()), 5) + self.assertEqual(len(self.core.tracklist.tracks.get()), 5) - self.sendRequest(u'add "dummy://foo"') - self.assertEqual(len(self.core.current_playlist.tracks.get()), 6) - self.assertEqual(self.core.current_playlist.tracks.get()[5], needle) - self.assertEqualResponse(u'OK') + self.sendRequest('add "dummy://foo"') + self.assertEqual(len(self.core.tracklist.tracks.get()), 6) + self.assertEqual(self.core.tracklist.tracks.get()[5], needle) + self.assertEqualResponse('OK') def test_add_with_uri_not_found_in_library_should_ack(self): - self.sendRequest(u'add "dummy://foo"') + self.sendRequest('add "dummy://foo"') self.assertEqualResponse( - u'ACK [50@0] {add} directory or file not found') + 'ACK [50@0] {add} directory or file not found') def test_add_with_empty_uri_should_add_all_known_tracks_and_ok(self): - self.sendRequest(u'add ""') + self.sendRequest('add ""') # TODO check that we add all tracks (we currently don't) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_addid_without_songpos(self): needle = Track(uri='dummy://foo') self.backend.library.dummy_library = [ Track(), Track(), needle, Track()] - self.core.current_playlist.append( + self.core.tracklist.append( [Track(), Track(), Track(), Track(), Track()]) - self.assertEqual(len(self.core.current_playlist.tracks.get()), 5) + self.assertEqual(len(self.core.tracklist.tracks.get()), 5) - self.sendRequest(u'addid "dummy://foo"') - self.assertEqual(len(self.core.current_playlist.tracks.get()), 6) - self.assertEqual(self.core.current_playlist.tracks.get()[5], needle) + self.sendRequest('addid "dummy://foo"') + self.assertEqual(len(self.core.tracklist.tracks.get()), 6) + self.assertEqual(self.core.tracklist.tracks.get()[5], needle) self.assertInResponse( - u'Id: %d' % self.core.current_playlist.cp_tracks.get()[5][0]) - self.assertInResponse(u'OK') + 'Id: %d' % self.core.tracklist.tl_tracks.get()[5][0]) + self.assertInResponse('OK') def test_addid_with_empty_uri_acks(self): - self.sendRequest(u'addid ""') - self.assertEqualResponse(u'ACK [50@0] {addid} No such song') + self.sendRequest('addid ""') + self.assertEqualResponse('ACK [50@0] {addid} No such song') def test_addid_with_songpos(self): needle = Track(uri='dummy://foo') self.backend.library.dummy_library = [ Track(), Track(), needle, Track()] - self.core.current_playlist.append( + self.core.tracklist.append( [Track(), Track(), Track(), Track(), Track()]) - self.assertEqual(len(self.core.current_playlist.tracks.get()), 5) + self.assertEqual(len(self.core.tracklist.tracks.get()), 5) - self.sendRequest(u'addid "dummy://foo" "3"') - self.assertEqual(len(self.core.current_playlist.tracks.get()), 6) - self.assertEqual(self.core.current_playlist.tracks.get()[3], needle) + self.sendRequest('addid "dummy://foo" "3"') + self.assertEqual(len(self.core.tracklist.tracks.get()), 6) + self.assertEqual(self.core.tracklist.tracks.get()[3], needle) self.assertInResponse( - u'Id: %d' % self.core.current_playlist.cp_tracks.get()[3][0]) - self.assertInResponse(u'OK') + 'Id: %d' % self.core.tracklist.tl_tracks.get()[3][0]) + self.assertInResponse('OK') def test_addid_with_songpos_out_of_bounds_should_ack(self): needle = Track(uri='dummy://foo') self.backend.library.dummy_library = [ Track(), Track(), needle, Track()] - self.core.current_playlist.append( + self.core.tracklist.append( [Track(), Track(), Track(), Track(), Track()]) - self.assertEqual(len(self.core.current_playlist.tracks.get()), 5) + self.assertEqual(len(self.core.tracklist.tracks.get()), 5) - self.sendRequest(u'addid "dummy://foo" "6"') - self.assertEqualResponse(u'ACK [2@0] {addid} Bad song index') + self.sendRequest('addid "dummy://foo" "6"') + self.assertEqualResponse('ACK [2@0] {addid} Bad song index') def test_addid_with_uri_not_found_in_library_should_ack(self): - self.sendRequest(u'addid "dummy://foo"') - self.assertEqualResponse(u'ACK [50@0] {addid} No such song') + self.sendRequest('addid "dummy://foo"') + self.assertEqualResponse('ACK [50@0] {addid} No such song') def test_clear(self): - self.core.current_playlist.append( + self.core.tracklist.append( [Track(), Track(), Track(), Track(), Track()]) - self.assertEqual(len(self.core.current_playlist.tracks.get()), 5) + self.assertEqual(len(self.core.tracklist.tracks.get()), 5) - self.sendRequest(u'clear') - self.assertEqual(len(self.core.current_playlist.tracks.get()), 0) + self.sendRequest('clear') + self.assertEqual(len(self.core.tracklist.tracks.get()), 0) self.assertEqual(self.core.playback.current_track.get(), None) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_delete_songpos(self): - self.core.current_playlist.append( + self.core.tracklist.append( [Track(), Track(), Track(), Track(), Track()]) - self.assertEqual(len(self.core.current_playlist.tracks.get()), 5) + self.assertEqual(len(self.core.tracklist.tracks.get()), 5) self.sendRequest( - u'delete "%d"' % self.core.current_playlist.cp_tracks.get()[2][0]) - self.assertEqual(len(self.core.current_playlist.tracks.get()), 4) - self.assertInResponse(u'OK') + 'delete "%d"' % self.core.tracklist.tl_tracks.get()[2][0]) + self.assertEqual(len(self.core.tracklist.tracks.get()), 4) + self.assertInResponse('OK') def test_delete_songpos_out_of_bounds(self): - self.core.current_playlist.append( + self.core.tracklist.append( [Track(), Track(), Track(), Track(), Track()]) - self.assertEqual(len(self.core.current_playlist.tracks.get()), 5) + self.assertEqual(len(self.core.tracklist.tracks.get()), 5) - self.sendRequest(u'delete "5"') - self.assertEqual(len(self.core.current_playlist.tracks.get()), 5) - self.assertEqualResponse(u'ACK [2@0] {delete} Bad song index') + self.sendRequest('delete "5"') + self.assertEqual(len(self.core.tracklist.tracks.get()), 5) + self.assertEqualResponse('ACK [2@0] {delete} Bad song index') def test_delete_open_range(self): - self.core.current_playlist.append( + self.core.tracklist.append( [Track(), Track(), Track(), Track(), Track()]) - self.assertEqual(len(self.core.current_playlist.tracks.get()), 5) + self.assertEqual(len(self.core.tracklist.tracks.get()), 5) - self.sendRequest(u'delete "1:"') - self.assertEqual(len(self.core.current_playlist.tracks.get()), 1) - self.assertInResponse(u'OK') + self.sendRequest('delete "1:"') + self.assertEqual(len(self.core.tracklist.tracks.get()), 1) + self.assertInResponse('OK') def test_delete_closed_range(self): - self.core.current_playlist.append( + self.core.tracklist.append( [Track(), Track(), Track(), Track(), Track()]) - self.assertEqual(len(self.core.current_playlist.tracks.get()), 5) + self.assertEqual(len(self.core.tracklist.tracks.get()), 5) - self.sendRequest(u'delete "1:3"') - self.assertEqual(len(self.core.current_playlist.tracks.get()), 3) - self.assertInResponse(u'OK') + self.sendRequest('delete "1:3"') + self.assertEqual(len(self.core.tracklist.tracks.get()), 3) + self.assertInResponse('OK') def test_delete_range_out_of_bounds(self): - self.core.current_playlist.append( + self.core.tracklist.append( [Track(), Track(), Track(), Track(), Track()]) - self.assertEqual(len(self.core.current_playlist.tracks.get()), 5) + self.assertEqual(len(self.core.tracklist.tracks.get()), 5) - self.sendRequest(u'delete "5:7"') - self.assertEqual(len(self.core.current_playlist.tracks.get()), 5) - self.assertEqualResponse(u'ACK [2@0] {delete} Bad song index') + self.sendRequest('delete "5:7"') + self.assertEqual(len(self.core.tracklist.tracks.get()), 5) + self.assertEqualResponse('ACK [2@0] {delete} Bad song index') def test_deleteid(self): - self.core.current_playlist.append([Track(), Track()]) - self.assertEqual(len(self.core.current_playlist.tracks.get()), 2) + self.core.tracklist.append([Track(), Track()]) + self.assertEqual(len(self.core.tracklist.tracks.get()), 2) - self.sendRequest(u'deleteid "1"') - self.assertEqual(len(self.core.current_playlist.tracks.get()), 1) - self.assertInResponse(u'OK') + self.sendRequest('deleteid "1"') + self.assertEqual(len(self.core.tracklist.tracks.get()), 1) + self.assertInResponse('OK') def test_deleteid_does_not_exist(self): - self.core.current_playlist.append([Track(), Track()]) - self.assertEqual(len(self.core.current_playlist.tracks.get()), 2) + self.core.tracklist.append([Track(), Track()]) + self.assertEqual(len(self.core.tracklist.tracks.get()), 2) - self.sendRequest(u'deleteid "12345"') - self.assertEqual(len(self.core.current_playlist.tracks.get()), 2) - self.assertEqualResponse(u'ACK [50@0] {deleteid} No such song') + self.sendRequest('deleteid "12345"') + self.assertEqual(len(self.core.tracklist.tracks.get()), 2) + self.assertEqualResponse('ACK [50@0] {deleteid} No such song') def test_move_songpos(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(name='a'), Track(name='b'), Track(name='c'), Track(name='d'), Track(name='e'), Track(name='f'), ]) - self.sendRequest(u'move "1" "0"') - tracks = self.core.current_playlist.tracks.get() + self.sendRequest('move "1" "0"') + tracks = self.core.tracklist.tracks.get() self.assertEqual(tracks[0].name, 'b') self.assertEqual(tracks[1].name, 'a') self.assertEqual(tracks[2].name, 'c') self.assertEqual(tracks[3].name, 'd') self.assertEqual(tracks[4].name, 'e') self.assertEqual(tracks[5].name, 'f') - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_move_open_range(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(name='a'), Track(name='b'), Track(name='c'), Track(name='d'), Track(name='e'), Track(name='f'), ]) - self.sendRequest(u'move "2:" "0"') - tracks = self.core.current_playlist.tracks.get() + self.sendRequest('move "2:" "0"') + tracks = self.core.tracklist.tracks.get() self.assertEqual(tracks[0].name, 'c') self.assertEqual(tracks[1].name, 'd') self.assertEqual(tracks[2].name, 'e') self.assertEqual(tracks[3].name, 'f') self.assertEqual(tracks[4].name, 'a') self.assertEqual(tracks[5].name, 'b') - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_move_closed_range(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(name='a'), Track(name='b'), Track(name='c'), Track(name='d'), Track(name='e'), Track(name='f'), ]) - self.sendRequest(u'move "1:3" "0"') - tracks = self.core.current_playlist.tracks.get() + self.sendRequest('move "1:3" "0"') + tracks = self.core.tracklist.tracks.get() self.assertEqual(tracks[0].name, 'b') self.assertEqual(tracks[1].name, 'c') self.assertEqual(tracks[2].name, 'a') self.assertEqual(tracks[3].name, 'd') self.assertEqual(tracks[4].name, 'e') self.assertEqual(tracks[5].name, 'f') - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_moveid(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(name='a'), Track(name='b'), Track(name='c'), Track(name='d'), Track(name='e'), Track(name='f'), ]) - self.sendRequest(u'moveid "4" "2"') - tracks = self.core.current_playlist.tracks.get() + self.sendRequest('moveid "4" "2"') + tracks = self.core.tracklist.tracks.get() self.assertEqual(tracks[0].name, 'a') self.assertEqual(tracks[1].name, 'b') self.assertEqual(tracks[2].name, 'e') self.assertEqual(tracks[3].name, 'c') self.assertEqual(tracks[4].name, 'd') self.assertEqual(tracks[5].name, 'f') - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_playlist_returns_same_as_playlistinfo(self): - playlist_response = self.sendRequest(u'playlist') - playlistinfo_response = self.sendRequest(u'playlistinfo') + playlist_response = self.sendRequest('playlist') + playlistinfo_response = self.sendRequest('playlistinfo') self.assertEqual(playlist_response, playlistinfo_response) def test_playlistfind(self): - self.sendRequest(u'playlistfind "tag" "needle"') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('playlistfind "tag" "needle"') + self.assertEqualResponse('ACK [0@0] {} Not implemented') - def test_playlistfind_by_filename_not_in_current_playlist(self): - self.sendRequest(u'playlistfind "filename" "file:///dev/null"') - self.assertEqualResponse(u'OK') + def test_playlistfind_by_filename_not_in_tracklist(self): + self.sendRequest('playlistfind "filename" "file:///dev/null"') + self.assertEqualResponse('OK') def test_playlistfind_by_filename_without_quotes(self): - self.sendRequest(u'playlistfind filename "file:///dev/null"') - self.assertEqualResponse(u'OK') + self.sendRequest('playlistfind filename "file:///dev/null"') + self.assertEqualResponse('OK') - def test_playlistfind_by_filename_in_current_playlist(self): - self.core.current_playlist.append([ + def test_playlistfind_by_filename_in_tracklist(self): + self.core.tracklist.append([ Track(uri='file:///exists')]) - self.sendRequest(u'playlistfind filename "file:///exists"') - self.assertInResponse(u'file: file:///exists') - self.assertInResponse(u'Id: 0') - self.assertInResponse(u'Pos: 0') - self.assertInResponse(u'OK') + self.sendRequest('playlistfind filename "file:///exists"') + self.assertInResponse('file: file:///exists') + self.assertInResponse('Id: 0') + self.assertInResponse('Pos: 0') + self.assertInResponse('OK') def test_playlistid_without_songid(self): - self.core.current_playlist.append([Track(name='a'), Track(name='b')]) + self.core.tracklist.append([Track(name='a'), Track(name='b')]) - self.sendRequest(u'playlistid') - self.assertInResponse(u'Title: a') - self.assertInResponse(u'Title: b') - self.assertInResponse(u'OK') + self.sendRequest('playlistid') + self.assertInResponse('Title: a') + self.assertInResponse('Title: b') + self.assertInResponse('OK') def test_playlistid_with_songid(self): - self.core.current_playlist.append([Track(name='a'), Track(name='b')]) + self.core.tracklist.append([Track(name='a'), Track(name='b')]) - self.sendRequest(u'playlistid "1"') - self.assertNotInResponse(u'Title: a') - self.assertNotInResponse(u'Id: 0') - self.assertInResponse(u'Title: b') - self.assertInResponse(u'Id: 1') - self.assertInResponse(u'OK') + self.sendRequest('playlistid "1"') + self.assertNotInResponse('Title: a') + self.assertNotInResponse('Id: 0') + self.assertInResponse('Title: b') + self.assertInResponse('Id: 1') + self.assertInResponse('OK') def test_playlistid_with_not_existing_songid_fails(self): - self.core.current_playlist.append([Track(name='a'), Track(name='b')]) + self.core.tracklist.append([Track(name='a'), Track(name='b')]) - self.sendRequest(u'playlistid "25"') - self.assertEqualResponse(u'ACK [50@0] {playlistid} No such song') + self.sendRequest('playlistid "25"') + self.assertEqualResponse('ACK [50@0] {playlistid} No such song') def test_playlistinfo_without_songpos_or_range(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(name='a'), Track(name='b'), Track(name='c'), Track(name='d'), Track(name='e'), Track(name='f'), ]) - self.sendRequest(u'playlistinfo') - self.assertInResponse(u'Title: a') - self.assertInResponse(u'Pos: 0') - self.assertInResponse(u'Title: b') - self.assertInResponse(u'Pos: 1') - self.assertInResponse(u'Title: c') - self.assertInResponse(u'Pos: 2') - self.assertInResponse(u'Title: d') - self.assertInResponse(u'Pos: 3') - self.assertInResponse(u'Title: e') - self.assertInResponse(u'Pos: 4') - self.assertInResponse(u'Title: f') - self.assertInResponse(u'Pos: 5') - self.assertInResponse(u'OK') + self.sendRequest('playlistinfo') + self.assertInResponse('Title: a') + self.assertInResponse('Pos: 0') + self.assertInResponse('Title: b') + self.assertInResponse('Pos: 1') + self.assertInResponse('Title: c') + self.assertInResponse('Pos: 2') + self.assertInResponse('Title: d') + self.assertInResponse('Pos: 3') + self.assertInResponse('Title: e') + self.assertInResponse('Pos: 4') + self.assertInResponse('Title: f') + self.assertInResponse('Pos: 5') + self.assertInResponse('OK') def test_playlistinfo_with_songpos(self): # Make the track's CPID not match the playlist position - self.core.current_playlist.cp_id = 17 - self.core.current_playlist.append([ + self.core.tracklist.tlid = 17 + self.core.tracklist.append([ Track(name='a'), Track(name='b'), Track(name='c'), Track(name='d'), Track(name='e'), Track(name='f'), ]) - self.sendRequest(u'playlistinfo "4"') - self.assertNotInResponse(u'Title: a') - self.assertNotInResponse(u'Pos: 0') - self.assertNotInResponse(u'Title: b') - self.assertNotInResponse(u'Pos: 1') - self.assertNotInResponse(u'Title: c') - self.assertNotInResponse(u'Pos: 2') - self.assertNotInResponse(u'Title: d') - self.assertNotInResponse(u'Pos: 3') - self.assertInResponse(u'Title: e') - self.assertInResponse(u'Pos: 4') - self.assertNotInResponse(u'Title: f') - self.assertNotInResponse(u'Pos: 5') - self.assertInResponse(u'OK') + self.sendRequest('playlistinfo "4"') + self.assertNotInResponse('Title: a') + self.assertNotInResponse('Pos: 0') + self.assertNotInResponse('Title: b') + self.assertNotInResponse('Pos: 1') + self.assertNotInResponse('Title: c') + self.assertNotInResponse('Pos: 2') + self.assertNotInResponse('Title: d') + self.assertNotInResponse('Pos: 3') + self.assertInResponse('Title: e') + self.assertInResponse('Pos: 4') + self.assertNotInResponse('Title: f') + self.assertNotInResponse('Pos: 5') + self.assertInResponse('OK') def test_playlistinfo_with_negative_songpos_same_as_playlistinfo(self): - response1 = self.sendRequest(u'playlistinfo "-1"') - response2 = self.sendRequest(u'playlistinfo') + response1 = self.sendRequest('playlistinfo "-1"') + response2 = self.sendRequest('playlistinfo') self.assertEqual(response1, response2) def test_playlistinfo_with_open_range(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(name='a'), Track(name='b'), Track(name='c'), Track(name='d'), Track(name='e'), Track(name='f'), ]) - self.sendRequest(u'playlistinfo "2:"') - self.assertNotInResponse(u'Title: a') - self.assertNotInResponse(u'Pos: 0') - self.assertNotInResponse(u'Title: b') - self.assertNotInResponse(u'Pos: 1') - self.assertInResponse(u'Title: c') - self.assertInResponse(u'Pos: 2') - self.assertInResponse(u'Title: d') - self.assertInResponse(u'Pos: 3') - self.assertInResponse(u'Title: e') - self.assertInResponse(u'Pos: 4') - self.assertInResponse(u'Title: f') - self.assertInResponse(u'Pos: 5') - self.assertInResponse(u'OK') + self.sendRequest('playlistinfo "2:"') + self.assertNotInResponse('Title: a') + self.assertNotInResponse('Pos: 0') + self.assertNotInResponse('Title: b') + self.assertNotInResponse('Pos: 1') + self.assertInResponse('Title: c') + self.assertInResponse('Pos: 2') + self.assertInResponse('Title: d') + self.assertInResponse('Pos: 3') + self.assertInResponse('Title: e') + self.assertInResponse('Pos: 4') + self.assertInResponse('Title: f') + self.assertInResponse('Pos: 5') + self.assertInResponse('OK') def test_playlistinfo_with_closed_range(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(name='a'), Track(name='b'), Track(name='c'), Track(name='d'), Track(name='e'), Track(name='f'), ]) - self.sendRequest(u'playlistinfo "2:4"') - self.assertNotInResponse(u'Title: a') - self.assertNotInResponse(u'Title: b') - self.assertInResponse(u'Title: c') - self.assertInResponse(u'Title: d') - self.assertNotInResponse(u'Title: e') - self.assertNotInResponse(u'Title: f') - self.assertInResponse(u'OK') + self.sendRequest('playlistinfo "2:4"') + self.assertNotInResponse('Title: a') + self.assertNotInResponse('Title: b') + self.assertInResponse('Title: c') + self.assertInResponse('Title: d') + self.assertNotInResponse('Title: e') + self.assertNotInResponse('Title: f') + self.assertInResponse('OK') def test_playlistinfo_with_too_high_start_of_range_returns_arg_error(self): - self.sendRequest(u'playlistinfo "10:20"') - self.assertEqualResponse(u'ACK [2@0] {playlistinfo} Bad song index') + self.sendRequest('playlistinfo "10:20"') + self.assertEqualResponse('ACK [2@0] {playlistinfo} Bad song index') def test_playlistinfo_with_too_high_end_of_range_returns_ok(self): - self.sendRequest(u'playlistinfo "0:20"') - self.assertInResponse(u'OK') + self.sendRequest('playlistinfo "0:20"') + self.assertInResponse('OK') def test_playlistsearch(self): - self.sendRequest(u'playlistsearch "any" "needle"') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('playlistsearch "any" "needle"') + self.assertEqualResponse('ACK [0@0] {} Not implemented') def test_playlistsearch_without_quotes(self): - self.sendRequest(u'playlistsearch any "needle"') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('playlistsearch any "needle"') + self.assertEqualResponse('ACK [0@0] {} Not implemented') def test_plchanges_with_lower_version_returns_changes(self): - self.core.current_playlist.append( + self.core.tracklist.append( [Track(name='a'), Track(name='b'), Track(name='c')]) - self.sendRequest(u'plchanges "0"') - self.assertInResponse(u'Title: a') - self.assertInResponse(u'Title: b') - self.assertInResponse(u'Title: c') - self.assertInResponse(u'OK') + self.sendRequest('plchanges "0"') + self.assertInResponse('Title: a') + self.assertInResponse('Title: b') + self.assertInResponse('Title: c') + self.assertInResponse('OK') def test_plchanges_with_equal_version_returns_nothing(self): - self.core.current_playlist.append( + self.core.tracklist.append( [Track(name='a'), Track(name='b'), Track(name='c')]) - self.assertEqual(self.core.current_playlist.version.get(), 1) - self.sendRequest(u'plchanges "1"') - self.assertNotInResponse(u'Title: a') - self.assertNotInResponse(u'Title: b') - self.assertNotInResponse(u'Title: c') - self.assertInResponse(u'OK') + self.assertEqual(self.core.tracklist.version.get(), 1) + self.sendRequest('plchanges "1"') + self.assertNotInResponse('Title: a') + self.assertNotInResponse('Title: b') + self.assertNotInResponse('Title: c') + self.assertInResponse('OK') def test_plchanges_with_greater_version_returns_nothing(self): - self.core.current_playlist.append( + self.core.tracklist.append( [Track(name='a'), Track(name='b'), Track(name='c')]) - self.assertEqual(self.core.current_playlist.version.get(), 1) - self.sendRequest(u'plchanges "2"') - self.assertNotInResponse(u'Title: a') - self.assertNotInResponse(u'Title: b') - self.assertNotInResponse(u'Title: c') - self.assertInResponse(u'OK') + self.assertEqual(self.core.tracklist.version.get(), 1) + self.sendRequest('plchanges "2"') + self.assertNotInResponse('Title: a') + self.assertNotInResponse('Title: b') + self.assertNotInResponse('Title: c') + self.assertInResponse('OK') def test_plchanges_with_minus_one_returns_entire_playlist(self): - self.core.current_playlist.append( + self.core.tracklist.append( [Track(name='a'), Track(name='b'), Track(name='c')]) - self.sendRequest(u'plchanges "-1"') - self.assertInResponse(u'Title: a') - self.assertInResponse(u'Title: b') - self.assertInResponse(u'Title: c') - self.assertInResponse(u'OK') + self.sendRequest('plchanges "-1"') + self.assertInResponse('Title: a') + self.assertInResponse('Title: b') + self.assertInResponse('Title: c') + self.assertInResponse('OK') def test_plchanges_without_quotes_works(self): - self.core.current_playlist.append( + self.core.tracklist.append( [Track(name='a'), Track(name='b'), Track(name='c')]) - self.sendRequest(u'plchanges 0') - self.assertInResponse(u'Title: a') - self.assertInResponse(u'Title: b') - self.assertInResponse(u'Title: c') - self.assertInResponse(u'OK') + self.sendRequest('plchanges 0') + self.assertInResponse('Title: a') + self.assertInResponse('Title: b') + self.assertInResponse('Title: c') + self.assertInResponse('OK') def test_plchangesposid(self): - self.core.current_playlist.append([Track(), Track(), Track()]) + self.core.tracklist.append([Track(), Track(), Track()]) - self.sendRequest(u'plchangesposid "0"') - cp_tracks = self.core.current_playlist.cp_tracks.get() - self.assertInResponse(u'cpos: 0') - self.assertInResponse(u'Id: %d' % cp_tracks[0][0]) - self.assertInResponse(u'cpos: 2') - self.assertInResponse(u'Id: %d' % cp_tracks[1][0]) - self.assertInResponse(u'cpos: 2') - self.assertInResponse(u'Id: %d' % cp_tracks[2][0]) - self.assertInResponse(u'OK') + self.sendRequest('plchangesposid "0"') + tl_tracks = self.core.tracklist.tl_tracks.get() + self.assertInResponse('cpos: 0') + self.assertInResponse('Id: %d' % tl_tracks[0][0]) + self.assertInResponse('cpos: 2') + self.assertInResponse('Id: %d' % tl_tracks[1][0]) + self.assertInResponse('cpos: 2') + self.assertInResponse('Id: %d' % tl_tracks[2][0]) + self.assertInResponse('OK') def test_shuffle_without_range(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(name='a'), Track(name='b'), Track(name='c'), Track(name='d'), Track(name='e'), Track(name='f'), ]) - version = self.core.current_playlist.version.get() + version = self.core.tracklist.version.get() - self.sendRequest(u'shuffle') - self.assertLess(version, self.core.current_playlist.version.get()) - self.assertInResponse(u'OK') + self.sendRequest('shuffle') + self.assertLess(version, self.core.tracklist.version.get()) + self.assertInResponse('OK') def test_shuffle_with_open_range(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(name='a'), Track(name='b'), Track(name='c'), Track(name='d'), Track(name='e'), Track(name='f'), ]) - version = self.core.current_playlist.version.get() + version = self.core.tracklist.version.get() - self.sendRequest(u'shuffle "4:"') - self.assertLess(version, self.core.current_playlist.version.get()) - tracks = self.core.current_playlist.tracks.get() + self.sendRequest('shuffle "4:"') + self.assertLess(version, self.core.tracklist.version.get()) + tracks = self.core.tracklist.tracks.get() self.assertEqual(tracks[0].name, 'a') self.assertEqual(tracks[1].name, 'b') self.assertEqual(tracks[2].name, 'c') self.assertEqual(tracks[3].name, 'd') - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_shuffle_with_closed_range(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(name='a'), Track(name='b'), Track(name='c'), Track(name='d'), Track(name='e'), Track(name='f'), ]) - version = self.core.current_playlist.version.get() + version = self.core.tracklist.version.get() - self.sendRequest(u'shuffle "1:3"') - self.assertLess(version, self.core.current_playlist.version.get()) - tracks = self.core.current_playlist.tracks.get() + self.sendRequest('shuffle "1:3"') + self.assertLess(version, self.core.tracklist.version.get()) + tracks = self.core.tracklist.tracks.get() self.assertEqual(tracks[0].name, 'a') self.assertEqual(tracks[3].name, 'd') self.assertEqual(tracks[4].name, 'e') self.assertEqual(tracks[5].name, 'f') - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_swap(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(name='a'), Track(name='b'), Track(name='c'), Track(name='d'), Track(name='e'), Track(name='f'), ]) - self.sendRequest(u'swap "1" "4"') - tracks = self.core.current_playlist.tracks.get() + self.sendRequest('swap "1" "4"') + tracks = self.core.tracklist.tracks.get() self.assertEqual(tracks[0].name, 'a') self.assertEqual(tracks[1].name, 'e') self.assertEqual(tracks[2].name, 'c') self.assertEqual(tracks[3].name, 'd') self.assertEqual(tracks[4].name, 'b') self.assertEqual(tracks[5].name, 'f') - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_swapid(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(name='a'), Track(name='b'), Track(name='c'), Track(name='d'), Track(name='e'), Track(name='f'), ]) - self.sendRequest(u'swapid "1" "4"') - tracks = self.core.current_playlist.tracks.get() + self.sendRequest('swapid "1" "4"') + tracks = self.core.tracklist.tracks.get() self.assertEqual(tracks[0].name, 'a') self.assertEqual(tracks[1].name, 'e') self.assertEqual(tracks[2].name, 'c') self.assertEqual(tracks[3].name, 'd') self.assertEqual(tracks[4].name, 'b') self.assertEqual(tracks[5].name, 'f') - self.assertInResponse(u'OK') + self.assertInResponse('OK') diff --git a/tests/frontends/mpd/protocol/idle_test.py b/tests/frontends/mpd/protocol/idle_test.py index ae23c88e..e6910988 100644 --- a/tests/frontends/mpd/protocol/idle_test.py +++ b/tests/frontends/mpd/protocol/idle_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mock import patch from mopidy.frontends.mpd.protocol.status import SUBSYSTEMS @@ -27,180 +29,180 @@ class IdleHandlerTest(protocol.BaseTestCase): self.assertNoResponse() def test_idle(self): - self.sendRequest(u'idle') + self.sendRequest('idle') self.assertEqualSubscriptions(SUBSYSTEMS) self.assertNoEvents() self.assertNoResponse() def test_idle_disables_timeout(self): - self.sendRequest(u'idle') + self.sendRequest('idle') self.connection.disable_timeout.assert_called_once_with() def test_noidle(self): - self.sendRequest(u'noidle') + self.sendRequest('noidle') self.assertNoSubscriptions() self.assertNoEvents() self.assertNoResponse() def test_idle_player(self): - self.sendRequest(u'idle player') + self.sendRequest('idle player') self.assertEqualSubscriptions(['player']) self.assertNoEvents() self.assertNoResponse() def test_idle_player_playlist(self): - self.sendRequest(u'idle player playlist') + self.sendRequest('idle player playlist') self.assertEqualSubscriptions(['player', 'playlist']) self.assertNoEvents() self.assertNoResponse() def test_idle_then_noidle(self): - self.sendRequest(u'idle') - self.sendRequest(u'noidle') + self.sendRequest('idle') + self.sendRequest('noidle') self.assertNoSubscriptions() self.assertNoEvents() - self.assertOnceInResponse(u'OK') + self.assertOnceInResponse('OK') def test_idle_then_noidle_enables_timeout(self): - self.sendRequest(u'idle') - self.sendRequest(u'noidle') + self.sendRequest('idle') + self.sendRequest('noidle') self.connection.enable_timeout.assert_called_once_with() def test_idle_then_play(self): with patch.object(self.session, 'stop') as stop_mock: - self.sendRequest(u'idle') - self.sendRequest(u'play') + self.sendRequest('idle') + self.sendRequest('play') stop_mock.assert_called_once_with() def test_idle_then_idle(self): with patch.object(self.session, 'stop') as stop_mock: - self.sendRequest(u'idle') - self.sendRequest(u'idle') + self.sendRequest('idle') + self.sendRequest('idle') stop_mock.assert_called_once_with() def test_idle_player_then_play(self): with patch.object(self.session, 'stop') as stop_mock: - self.sendRequest(u'idle player') - self.sendRequest(u'play') + self.sendRequest('idle player') + self.sendRequest('play') stop_mock.assert_called_once_with() def test_idle_then_player(self): - self.sendRequest(u'idle') - self.idleEvent(u'player') + self.sendRequest('idle') + self.idleEvent('player') self.assertNoSubscriptions() self.assertNoEvents() - self.assertOnceInResponse(u'changed: player') - self.assertOnceInResponse(u'OK') + self.assertOnceInResponse('changed: player') + self.assertOnceInResponse('OK') def test_idle_player_then_event_player(self): - self.sendRequest(u'idle player') - self.idleEvent(u'player') + self.sendRequest('idle player') + self.idleEvent('player') self.assertNoSubscriptions() self.assertNoEvents() - self.assertOnceInResponse(u'changed: player') - self.assertOnceInResponse(u'OK') + self.assertOnceInResponse('changed: player') + self.assertOnceInResponse('OK') def test_idle_player_then_noidle(self): - self.sendRequest(u'idle player') - self.sendRequest(u'noidle') + self.sendRequest('idle player') + self.sendRequest('noidle') self.assertNoSubscriptions() self.assertNoEvents() - self.assertOnceInResponse(u'OK') + self.assertOnceInResponse('OK') def test_idle_player_playlist_then_noidle(self): - self.sendRequest(u'idle player playlist') - self.sendRequest(u'noidle') + self.sendRequest('idle player playlist') + self.sendRequest('noidle') self.assertNoEvents() self.assertNoSubscriptions() - self.assertOnceInResponse(u'OK') + self.assertOnceInResponse('OK') def test_idle_player_playlist_then_player(self): - self.sendRequest(u'idle player playlist') - self.idleEvent(u'player') + self.sendRequest('idle player playlist') + self.idleEvent('player') self.assertNoEvents() self.assertNoSubscriptions() - self.assertOnceInResponse(u'changed: player') - self.assertNotInResponse(u'changed: playlist') - self.assertOnceInResponse(u'OK') + self.assertOnceInResponse('changed: player') + self.assertNotInResponse('changed: playlist') + self.assertOnceInResponse('OK') def test_idle_playlist_then_player(self): - self.sendRequest(u'idle playlist') - self.idleEvent(u'player') + self.sendRequest('idle playlist') + self.idleEvent('player') self.assertEqualEvents(['player']) self.assertEqualSubscriptions(['playlist']) self.assertNoResponse() def test_idle_playlist_then_player_then_playlist(self): - self.sendRequest(u'idle playlist') - self.idleEvent(u'player') - self.idleEvent(u'playlist') + self.sendRequest('idle playlist') + self.idleEvent('player') + self.idleEvent('playlist') self.assertNoEvents() self.assertNoSubscriptions() - self.assertNotInResponse(u'changed: player') - self.assertOnceInResponse(u'changed: playlist') - self.assertOnceInResponse(u'OK') + self.assertNotInResponse('changed: player') + self.assertOnceInResponse('changed: playlist') + self.assertOnceInResponse('OK') def test_player(self): - self.idleEvent(u'player') + self.idleEvent('player') self.assertEqualEvents(['player']) self.assertNoSubscriptions() self.assertNoResponse() def test_player_then_idle_player(self): - self.idleEvent(u'player') - self.sendRequest(u'idle player') + self.idleEvent('player') + self.sendRequest('idle player') self.assertNoEvents() self.assertNoSubscriptions() - self.assertOnceInResponse(u'changed: player') - self.assertNotInResponse(u'changed: playlist') - self.assertOnceInResponse(u'OK') + self.assertOnceInResponse('changed: player') + self.assertNotInResponse('changed: playlist') + self.assertOnceInResponse('OK') def test_player_then_playlist(self): - self.idleEvent(u'player') - self.idleEvent(u'playlist') + self.idleEvent('player') + self.idleEvent('playlist') self.assertEqualEvents(['player', 'playlist']) self.assertNoSubscriptions() self.assertNoResponse() def test_player_then_idle(self): - self.idleEvent(u'player') - self.sendRequest(u'idle') + self.idleEvent('player') + self.sendRequest('idle') self.assertNoEvents() self.assertNoSubscriptions() - self.assertOnceInResponse(u'changed: player') - self.assertOnceInResponse(u'OK') + self.assertOnceInResponse('changed: player') + self.assertOnceInResponse('OK') def test_player_then_playlist_then_idle(self): - self.idleEvent(u'player') - self.idleEvent(u'playlist') - self.sendRequest(u'idle') + self.idleEvent('player') + self.idleEvent('playlist') + self.sendRequest('idle') self.assertNoEvents() self.assertNoSubscriptions() - self.assertOnceInResponse(u'changed: player') - self.assertOnceInResponse(u'changed: playlist') - self.assertOnceInResponse(u'OK') + self.assertOnceInResponse('changed: player') + self.assertOnceInResponse('changed: playlist') + self.assertOnceInResponse('OK') def test_player_then_idle_playlist(self): - self.idleEvent(u'player') - self.sendRequest(u'idle playlist') + self.idleEvent('player') + self.sendRequest('idle playlist') self.assertEqualEvents(['player']) self.assertEqualSubscriptions(['playlist']) self.assertNoResponse() def test_player_then_idle_playlist_then_noidle(self): - self.idleEvent(u'player') - self.sendRequest(u'idle playlist') - self.sendRequest(u'noidle') + self.idleEvent('player') + self.sendRequest('idle playlist') + self.sendRequest('noidle') self.assertNoEvents() self.assertNoSubscriptions() - self.assertOnceInResponse(u'OK') + self.assertOnceInResponse('OK') def test_player_then_playlist_then_idle_playlist(self): - self.idleEvent(u'player') - self.idleEvent(u'playlist') - self.sendRequest(u'idle playlist') + self.idleEvent('player') + self.idleEvent('playlist') + self.sendRequest('idle playlist') self.assertNoEvents() self.assertNoSubscriptions() - self.assertNotInResponse(u'changed: player') - self.assertOnceInResponse(u'changed: playlist') - self.assertOnceInResponse(u'OK') + self.assertNotInResponse('changed: player') + self.assertOnceInResponse('changed: playlist') + self.assertOnceInResponse('OK') diff --git a/tests/frontends/mpd/protocol/music_db_test.py b/tests/frontends/mpd/protocol/music_db_test.py index 088502c4..7059c855 100644 --- a/tests/frontends/mpd/protocol/music_db_test.py +++ b/tests/frontends/mpd/protocol/music_db_test.py @@ -1,344 +1,370 @@ +from __future__ import unicode_literals + from tests.frontends.mpd import protocol class MusicDatabaseHandlerTest(protocol.BaseTestCase): def test_count(self): - self.sendRequest(u'count "tag" "needle"') - self.assertInResponse(u'songs: 0') - self.assertInResponse(u'playtime: 0') - self.assertInResponse(u'OK') + self.sendRequest('count "tag" "needle"') + self.assertInResponse('songs: 0') + self.assertInResponse('playtime: 0') + self.assertInResponse('OK') def test_findadd(self): - self.sendRequest(u'findadd "album" "what"') - self.assertInResponse(u'OK') + self.sendRequest('findadd "album" "what"') + self.assertInResponse('OK') def test_listall(self): - self.sendRequest(u'listall "file:///dev/urandom"') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('listall "file:///dev/urandom"') + self.assertEqualResponse('ACK [0@0] {} Not implemented') def test_listallinfo(self): - self.sendRequest(u'listallinfo "file:///dev/urandom"') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('listallinfo "file:///dev/urandom"') + self.assertEqualResponse('ACK [0@0] {} Not implemented') def test_lsinfo_without_path_returns_same_as_listplaylists(self): - lsinfo_response = self.sendRequest(u'lsinfo') - listplaylists_response = self.sendRequest(u'listplaylists') + lsinfo_response = self.sendRequest('lsinfo') + listplaylists_response = self.sendRequest('listplaylists') self.assertEqual(lsinfo_response, listplaylists_response) def test_lsinfo_with_empty_path_returns_same_as_listplaylists(self): - lsinfo_response = self.sendRequest(u'lsinfo ""') - listplaylists_response = self.sendRequest(u'listplaylists') + lsinfo_response = self.sendRequest('lsinfo ""') + listplaylists_response = self.sendRequest('listplaylists') self.assertEqual(lsinfo_response, listplaylists_response) def test_lsinfo_for_root_returns_same_as_listplaylists(self): - lsinfo_response = self.sendRequest(u'lsinfo "/"') - listplaylists_response = self.sendRequest(u'listplaylists') + lsinfo_response = self.sendRequest('lsinfo "/"') + listplaylists_response = self.sendRequest('listplaylists') self.assertEqual(lsinfo_response, listplaylists_response) def test_update_without_uri(self): - self.sendRequest(u'update') - self.assertInResponse(u'updating_db: 0') - self.assertInResponse(u'OK') + self.sendRequest('update') + self.assertInResponse('updating_db: 0') + self.assertInResponse('OK') def test_update_with_uri(self): - self.sendRequest(u'update "file:///dev/urandom"') - self.assertInResponse(u'updating_db: 0') - self.assertInResponse(u'OK') + self.sendRequest('update "file:///dev/urandom"') + self.assertInResponse('updating_db: 0') + self.assertInResponse('OK') def test_rescan_without_uri(self): - self.sendRequest(u'rescan') - self.assertInResponse(u'updating_db: 0') - self.assertInResponse(u'OK') + self.sendRequest('rescan') + self.assertInResponse('updating_db: 0') + self.assertInResponse('OK') def test_rescan_with_uri(self): - self.sendRequest(u'rescan "file:///dev/urandom"') - self.assertInResponse(u'updating_db: 0') - self.assertInResponse(u'OK') + self.sendRequest('rescan "file:///dev/urandom"') + self.assertInResponse('updating_db: 0') + self.assertInResponse('OK') class MusicDatabaseFindTest(protocol.BaseTestCase): def test_find_album(self): - self.sendRequest(u'find "album" "what"') - self.assertInResponse(u'OK') + self.sendRequest('find "album" "what"') + self.assertInResponse('OK') def test_find_album_without_quotes(self): - self.sendRequest(u'find album "what"') - self.assertInResponse(u'OK') + self.sendRequest('find album "what"') + self.assertInResponse('OK') def test_find_artist(self): - self.sendRequest(u'find "artist" "what"') - self.assertInResponse(u'OK') + self.sendRequest('find "artist" "what"') + self.assertInResponse('OK') def test_find_artist_without_quotes(self): - self.sendRequest(u'find artist "what"') - self.assertInResponse(u'OK') + self.sendRequest('find artist "what"') + self.assertInResponse('OK') + + def test_find_filename(self): + self.sendRequest('find "filename" "afilename"') + self.assertInResponse('OK') + + def test_find_filename_without_quotes(self): + self.sendRequest('find filename "afilename"') + self.assertInResponse('OK') + + def test_find_file(self): + self.sendRequest('find "file" "afilename"') + self.assertInResponse('OK') + + def test_find_file_without_quotes(self): + self.sendRequest('find file "afilename"') + self.assertInResponse('OK') def test_find_title(self): - self.sendRequest(u'find "title" "what"') - self.assertInResponse(u'OK') + self.sendRequest('find "title" "what"') + self.assertInResponse('OK') def test_find_title_without_quotes(self): - self.sendRequest(u'find title "what"') - self.assertInResponse(u'OK') + self.sendRequest('find title "what"') + self.assertInResponse('OK') def test_find_date(self): - self.sendRequest(u'find "date" "2002-01-01"') - self.assertInResponse(u'OK') + self.sendRequest('find "date" "2002-01-01"') + self.assertInResponse('OK') def test_find_date_without_quotes(self): - self.sendRequest(u'find date "2002-01-01"') - self.assertInResponse(u'OK') + self.sendRequest('find date "2002-01-01"') + self.assertInResponse('OK') def test_find_date_with_capital_d_and_incomplete_date(self): - self.sendRequest(u'find Date "2005"') - self.assertInResponse(u'OK') + self.sendRequest('find Date "2005"') + self.assertInResponse('OK') def test_find_else_should_fail(self): - self.sendRequest(u'find "somethingelse" "what"') - self.assertEqualResponse(u'ACK [2@0] {find} incorrect arguments') + self.sendRequest('find "somethingelse" "what"') + self.assertEqualResponse('ACK [2@0] {find} incorrect arguments') def test_find_album_and_artist(self): - self.sendRequest(u'find album "album_what" artist "artist_what"') - self.assertInResponse(u'OK') + self.sendRequest('find album "album_what" artist "artist_what"') + self.assertInResponse('OK') class MusicDatabaseListTest(protocol.BaseTestCase): def test_list_foo_returns_ack(self): - self.sendRequest(u'list "foo"') - self.assertEqualResponse(u'ACK [2@0] {list} incorrect arguments') + self.sendRequest('list "foo"') + self.assertEqualResponse('ACK [2@0] {list} incorrect arguments') ### Artist def test_list_artist_with_quotes(self): - self.sendRequest(u'list "artist"') - self.assertInResponse(u'OK') + self.sendRequest('list "artist"') + self.assertInResponse('OK') def test_list_artist_without_quotes(self): - self.sendRequest(u'list artist') - self.assertInResponse(u'OK') + self.sendRequest('list artist') + self.assertInResponse('OK') def test_list_artist_without_quotes_and_capitalized(self): - self.sendRequest(u'list Artist') - self.assertInResponse(u'OK') + self.sendRequest('list Artist') + self.assertInResponse('OK') def test_list_artist_with_query_of_one_token(self): - self.sendRequest(u'list "artist" "anartist"') + self.sendRequest('list "artist" "anartist"') self.assertEqualResponse( - u'ACK [2@0] {list} should be "Album" for 3 arguments') + 'ACK [2@0] {list} should be "Album" for 3 arguments') def test_list_artist_with_unknown_field_in_query_returns_ack(self): - self.sendRequest(u'list "artist" "foo" "bar"') - self.assertEqualResponse(u'ACK [2@0] {list} not able to parse args') + self.sendRequest('list "artist" "foo" "bar"') + self.assertEqualResponse('ACK [2@0] {list} not able to parse args') def test_list_artist_by_artist(self): - self.sendRequest(u'list "artist" "artist" "anartist"') - self.assertInResponse(u'OK') + self.sendRequest('list "artist" "artist" "anartist"') + self.assertInResponse('OK') def test_list_artist_by_album(self): - self.sendRequest(u'list "artist" "album" "analbum"') - self.assertInResponse(u'OK') + self.sendRequest('list "artist" "album" "analbum"') + self.assertInResponse('OK') def test_list_artist_by_full_date(self): - self.sendRequest(u'list "artist" "date" "2001-01-01"') - self.assertInResponse(u'OK') + self.sendRequest('list "artist" "date" "2001-01-01"') + self.assertInResponse('OK') def test_list_artist_by_year(self): - self.sendRequest(u'list "artist" "date" "2001"') - self.assertInResponse(u'OK') + self.sendRequest('list "artist" "date" "2001"') + self.assertInResponse('OK') def test_list_artist_by_genre(self): - self.sendRequest(u'list "artist" "genre" "agenre"') - self.assertInResponse(u'OK') + self.sendRequest('list "artist" "genre" "agenre"') + self.assertInResponse('OK') def test_list_artist_by_artist_and_album(self): self.sendRequest( - u'list "artist" "artist" "anartist" "album" "analbum"') - self.assertInResponse(u'OK') + 'list "artist" "artist" "anartist" "album" "analbum"') + self.assertInResponse('OK') ### Album def test_list_album_with_quotes(self): - self.sendRequest(u'list "album"') - self.assertInResponse(u'OK') + self.sendRequest('list "album"') + self.assertInResponse('OK') def test_list_album_without_quotes(self): - self.sendRequest(u'list album') - self.assertInResponse(u'OK') + self.sendRequest('list album') + self.assertInResponse('OK') def test_list_album_without_quotes_and_capitalized(self): - self.sendRequest(u'list Album') - self.assertInResponse(u'OK') + self.sendRequest('list Album') + self.assertInResponse('OK') def test_list_album_with_artist_name(self): - self.sendRequest(u'list "album" "anartist"') - self.assertInResponse(u'OK') + self.sendRequest('list "album" "anartist"') + self.assertInResponse('OK') def test_list_album_by_artist(self): - self.sendRequest(u'list "album" "artist" "anartist"') - self.assertInResponse(u'OK') + self.sendRequest('list "album" "artist" "anartist"') + self.assertInResponse('OK') def test_list_album_by_album(self): - self.sendRequest(u'list "album" "album" "analbum"') - self.assertInResponse(u'OK') + self.sendRequest('list "album" "album" "analbum"') + self.assertInResponse('OK') def test_list_album_by_full_date(self): - self.sendRequest(u'list "album" "date" "2001-01-01"') - self.assertInResponse(u'OK') + self.sendRequest('list "album" "date" "2001-01-01"') + self.assertInResponse('OK') def test_list_album_by_year(self): - self.sendRequest(u'list "album" "date" "2001"') - self.assertInResponse(u'OK') + self.sendRequest('list "album" "date" "2001"') + self.assertInResponse('OK') def test_list_album_by_genre(self): - self.sendRequest(u'list "album" "genre" "agenre"') - self.assertInResponse(u'OK') + self.sendRequest('list "album" "genre" "agenre"') + self.assertInResponse('OK') def test_list_album_by_artist_and_album(self): self.sendRequest( - u'list "album" "artist" "anartist" "album" "analbum"') - self.assertInResponse(u'OK') + 'list "album" "artist" "anartist" "album" "analbum"') + self.assertInResponse('OK') ### Date def test_list_date_with_quotes(self): - self.sendRequest(u'list "date"') - self.assertInResponse(u'OK') + self.sendRequest('list "date"') + self.assertInResponse('OK') def test_list_date_without_quotes(self): - self.sendRequest(u'list date') - self.assertInResponse(u'OK') + self.sendRequest('list date') + self.assertInResponse('OK') def test_list_date_without_quotes_and_capitalized(self): - self.sendRequest(u'list Date') - self.assertInResponse(u'OK') + self.sendRequest('list Date') + self.assertInResponse('OK') def test_list_date_with_query_of_one_token(self): - self.sendRequest(u'list "date" "anartist"') + self.sendRequest('list "date" "anartist"') self.assertEqualResponse( - u'ACK [2@0] {list} should be "Album" for 3 arguments') + 'ACK [2@0] {list} should be "Album" for 3 arguments') def test_list_date_by_artist(self): - self.sendRequest(u'list "date" "artist" "anartist"') - self.assertInResponse(u'OK') + self.sendRequest('list "date" "artist" "anartist"') + self.assertInResponse('OK') def test_list_date_by_album(self): - self.sendRequest(u'list "date" "album" "analbum"') - self.assertInResponse(u'OK') + self.sendRequest('list "date" "album" "analbum"') + self.assertInResponse('OK') def test_list_date_by_full_date(self): - self.sendRequest(u'list "date" "date" "2001-01-01"') - self.assertInResponse(u'OK') + self.sendRequest('list "date" "date" "2001-01-01"') + self.assertInResponse('OK') def test_list_date_by_year(self): - self.sendRequest(u'list "date" "date" "2001"') - self.assertInResponse(u'OK') + self.sendRequest('list "date" "date" "2001"') + self.assertInResponse('OK') def test_list_date_by_genre(self): - self.sendRequest(u'list "date" "genre" "agenre"') - self.assertInResponse(u'OK') + self.sendRequest('list "date" "genre" "agenre"') + self.assertInResponse('OK') def test_list_date_by_artist_and_album(self): - self.sendRequest(u'list "date" "artist" "anartist" "album" "analbum"') - self.assertInResponse(u'OK') + self.sendRequest('list "date" "artist" "anartist" "album" "analbum"') + self.assertInResponse('OK') ### Genre def test_list_genre_with_quotes(self): - self.sendRequest(u'list "genre"') - self.assertInResponse(u'OK') + self.sendRequest('list "genre"') + self.assertInResponse('OK') def test_list_genre_without_quotes(self): - self.sendRequest(u'list genre') - self.assertInResponse(u'OK') + self.sendRequest('list genre') + self.assertInResponse('OK') def test_list_genre_without_quotes_and_capitalized(self): - self.sendRequest(u'list Genre') - self.assertInResponse(u'OK') + self.sendRequest('list Genre') + self.assertInResponse('OK') def test_list_genre_with_query_of_one_token(self): - self.sendRequest(u'list "genre" "anartist"') + self.sendRequest('list "genre" "anartist"') self.assertEqualResponse( - u'ACK [2@0] {list} should be "Album" for 3 arguments') + 'ACK [2@0] {list} should be "Album" for 3 arguments') def test_list_genre_by_artist(self): - self.sendRequest(u'list "genre" "artist" "anartist"') - self.assertInResponse(u'OK') + self.sendRequest('list "genre" "artist" "anartist"') + self.assertInResponse('OK') def test_list_genre_by_album(self): - self.sendRequest(u'list "genre" "album" "analbum"') - self.assertInResponse(u'OK') + self.sendRequest('list "genre" "album" "analbum"') + self.assertInResponse('OK') def test_list_genre_by_full_date(self): - self.sendRequest(u'list "genre" "date" "2001-01-01"') - self.assertInResponse(u'OK') + self.sendRequest('list "genre" "date" "2001-01-01"') + self.assertInResponse('OK') def test_list_genre_by_year(self): - self.sendRequest(u'list "genre" "date" "2001"') - self.assertInResponse(u'OK') + self.sendRequest('list "genre" "date" "2001"') + self.assertInResponse('OK') def test_list_genre_by_genre(self): - self.sendRequest(u'list "genre" "genre" "agenre"') - self.assertInResponse(u'OK') + self.sendRequest('list "genre" "genre" "agenre"') + self.assertInResponse('OK') def test_list_genre_by_artist_and_album(self): self.sendRequest( - u'list "genre" "artist" "anartist" "album" "analbum"') - self.assertInResponse(u'OK') + 'list "genre" "artist" "anartist" "album" "analbum"') + self.assertInResponse('OK') class MusicDatabaseSearchTest(protocol.BaseTestCase): def test_search_album(self): - self.sendRequest(u'search "album" "analbum"') - self.assertInResponse(u'OK') + self.sendRequest('search "album" "analbum"') + self.assertInResponse('OK') def test_search_album_without_quotes(self): - self.sendRequest(u'search album "analbum"') - self.assertInResponse(u'OK') + self.sendRequest('search album "analbum"') + self.assertInResponse('OK') def test_search_artist(self): - self.sendRequest(u'search "artist" "anartist"') - self.assertInResponse(u'OK') + self.sendRequest('search "artist" "anartist"') + self.assertInResponse('OK') def test_search_artist_without_quotes(self): - self.sendRequest(u'search artist "anartist"') - self.assertInResponse(u'OK') + self.sendRequest('search artist "anartist"') + self.assertInResponse('OK') def test_search_filename(self): - self.sendRequest(u'search "filename" "afilename"') - self.assertInResponse(u'OK') + self.sendRequest('search "filename" "afilename"') + self.assertInResponse('OK') def test_search_filename_without_quotes(self): - self.sendRequest(u'search filename "afilename"') - self.assertInResponse(u'OK') + self.sendRequest('search filename "afilename"') + self.assertInResponse('OK') + + def test_search_file(self): + self.sendRequest('search "file" "afilename"') + self.assertInResponse('OK') + + def test_search_file_without_quotes(self): + self.sendRequest('search file "afilename"') + self.assertInResponse('OK') def test_search_title(self): - self.sendRequest(u'search "title" "atitle"') - self.assertInResponse(u'OK') + self.sendRequest('search "title" "atitle"') + self.assertInResponse('OK') def test_search_title_without_quotes(self): - self.sendRequest(u'search title "atitle"') - self.assertInResponse(u'OK') + self.sendRequest('search title "atitle"') + self.assertInResponse('OK') def test_search_any(self): - self.sendRequest(u'search "any" "anything"') - self.assertInResponse(u'OK') + self.sendRequest('search "any" "anything"') + self.assertInResponse('OK') def test_search_any_without_quotes(self): - self.sendRequest(u'search any "anything"') - self.assertInResponse(u'OK') + self.sendRequest('search any "anything"') + self.assertInResponse('OK') def test_search_date(self): - self.sendRequest(u'search "date" "2002-01-01"') - self.assertInResponse(u'OK') + self.sendRequest('search "date" "2002-01-01"') + self.assertInResponse('OK') def test_search_date_without_quotes(self): - self.sendRequest(u'search date "2002-01-01"') - self.assertInResponse(u'OK') + self.sendRequest('search date "2002-01-01"') + self.assertInResponse('OK') def test_search_date_with_capital_d_and_incomplete_date(self): - self.sendRequest(u'search Date "2005"') - self.assertInResponse(u'OK') + self.sendRequest('search Date "2005"') + self.assertInResponse('OK') def test_search_else_should_fail(self): - self.sendRequest(u'search "sometype" "something"') - self.assertEqualResponse(u'ACK [2@0] {search} incorrect arguments') + self.sendRequest('search "sometype" "something"') + self.assertEqualResponse('ACK [2@0] {search} incorrect arguments') diff --git a/tests/frontends/mpd/protocol/playback_test.py b/tests/frontends/mpd/protocol/playback_test.py index 202ac649..51468390 100644 --- a/tests/frontends/mpd/protocol/playback_test.py +++ b/tests/frontends/mpd/protocol/playback_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy.core import PlaybackState from mopidy.models import Track @@ -12,140 +14,140 @@ STOPPED = PlaybackState.STOPPED class PlaybackOptionsHandlerTest(protocol.BaseTestCase): def test_consume_off(self): - self.sendRequest(u'consume "0"') + self.sendRequest('consume "0"') self.assertFalse(self.core.playback.consume.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_consume_off_without_quotes(self): - self.sendRequest(u'consume 0') + self.sendRequest('consume 0') self.assertFalse(self.core.playback.consume.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_consume_on(self): - self.sendRequest(u'consume "1"') + self.sendRequest('consume "1"') self.assertTrue(self.core.playback.consume.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_consume_on_without_quotes(self): - self.sendRequest(u'consume 1') + self.sendRequest('consume 1') self.assertTrue(self.core.playback.consume.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_crossfade(self): - self.sendRequest(u'crossfade "10"') - self.assertInResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('crossfade "10"') + self.assertInResponse('ACK [0@0] {} Not implemented') def test_random_off(self): - self.sendRequest(u'random "0"') + self.sendRequest('random "0"') self.assertFalse(self.core.playback.random.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_random_off_without_quotes(self): - self.sendRequest(u'random 0') + self.sendRequest('random 0') self.assertFalse(self.core.playback.random.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_random_on(self): - self.sendRequest(u'random "1"') + self.sendRequest('random "1"') self.assertTrue(self.core.playback.random.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_random_on_without_quotes(self): - self.sendRequest(u'random 1') + self.sendRequest('random 1') self.assertTrue(self.core.playback.random.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_repeat_off(self): - self.sendRequest(u'repeat "0"') + self.sendRequest('repeat "0"') self.assertFalse(self.core.playback.repeat.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_repeat_off_without_quotes(self): - self.sendRequest(u'repeat 0') + self.sendRequest('repeat 0') self.assertFalse(self.core.playback.repeat.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_repeat_on(self): - self.sendRequest(u'repeat "1"') + self.sendRequest('repeat "1"') self.assertTrue(self.core.playback.repeat.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_repeat_on_without_quotes(self): - self.sendRequest(u'repeat 1') + self.sendRequest('repeat 1') self.assertTrue(self.core.playback.repeat.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_setvol_below_min(self): - self.sendRequest(u'setvol "-10"') + self.sendRequest('setvol "-10"') self.assertEqual(0, self.core.playback.volume.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_setvol_min(self): - self.sendRequest(u'setvol "0"') + self.sendRequest('setvol "0"') self.assertEqual(0, self.core.playback.volume.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_setvol_middle(self): - self.sendRequest(u'setvol "50"') + self.sendRequest('setvol "50"') self.assertEqual(50, self.core.playback.volume.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_setvol_max(self): - self.sendRequest(u'setvol "100"') + self.sendRequest('setvol "100"') self.assertEqual(100, self.core.playback.volume.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_setvol_above_max(self): - self.sendRequest(u'setvol "110"') + self.sendRequest('setvol "110"') self.assertEqual(100, self.core.playback.volume.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_setvol_plus_is_ignored(self): - self.sendRequest(u'setvol "+10"') + self.sendRequest('setvol "+10"') self.assertEqual(10, self.core.playback.volume.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_setvol_without_quotes(self): - self.sendRequest(u'setvol 50') + self.sendRequest('setvol 50') self.assertEqual(50, self.core.playback.volume.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_single_off(self): - self.sendRequest(u'single "0"') + self.sendRequest('single "0"') self.assertFalse(self.core.playback.single.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_single_off_without_quotes(self): - self.sendRequest(u'single 0') + self.sendRequest('single 0') self.assertFalse(self.core.playback.single.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_single_on(self): - self.sendRequest(u'single "1"') + self.sendRequest('single "1"') self.assertTrue(self.core.playback.single.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_single_on_without_quotes(self): - self.sendRequest(u'single 1') + self.sendRequest('single 1') self.assertTrue(self.core.playback.single.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_replay_gain_mode_off(self): - self.sendRequest(u'replay_gain_mode "off"') - self.assertInResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('replay_gain_mode "off"') + self.assertInResponse('ACK [0@0] {} Not implemented') def test_replay_gain_mode_track(self): - self.sendRequest(u'replay_gain_mode "track"') - self.assertInResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('replay_gain_mode "track"') + self.assertInResponse('ACK [0@0] {} Not implemented') def test_replay_gain_mode_album(self): - self.sendRequest(u'replay_gain_mode "album"') - self.assertInResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('replay_gain_mode "album"') + self.assertInResponse('ACK [0@0] {} Not implemented') def test_replay_gain_status_default(self): - self.sendRequest(u'replay_gain_status') - self.assertInResponse(u'OK') - self.assertInResponse(u'off') + self.sendRequest('replay_gain_status') + self.assertInResponse('OK') + self.assertInResponse('off') @unittest.SkipTest def test_replay_gain_status_off(self): @@ -162,84 +164,84 @@ class PlaybackOptionsHandlerTest(protocol.BaseTestCase): class PlaybackControlHandlerTest(protocol.BaseTestCase): def test_next(self): - self.sendRequest(u'next') - self.assertInResponse(u'OK') + self.sendRequest('next') + self.assertInResponse('OK') def test_pause_off(self): - self.core.current_playlist.append([Track(uri='dummy:a')]) + self.core.tracklist.append([Track(uri='dummy:a')]) - self.sendRequest(u'play "0"') - self.sendRequest(u'pause "1"') - self.sendRequest(u'pause "0"') + self.sendRequest('play "0"') + self.sendRequest('pause "1"') + self.sendRequest('pause "0"') self.assertEqual(PLAYING, self.core.playback.state.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_pause_on(self): - self.core.current_playlist.append([Track(uri='dummy:a')]) + self.core.tracklist.append([Track(uri='dummy:a')]) - self.sendRequest(u'play "0"') - self.sendRequest(u'pause "1"') + self.sendRequest('play "0"') + self.sendRequest('pause "1"') self.assertEqual(PAUSED, self.core.playback.state.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_pause_toggle(self): - self.core.current_playlist.append([Track(uri='dummy:a')]) + self.core.tracklist.append([Track(uri='dummy:a')]) - self.sendRequest(u'play "0"') + self.sendRequest('play "0"') self.assertEqual(PLAYING, self.core.playback.state.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') - self.sendRequest(u'pause') + self.sendRequest('pause') self.assertEqual(PAUSED, self.core.playback.state.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') - self.sendRequest(u'pause') + self.sendRequest('pause') self.assertEqual(PLAYING, self.core.playback.state.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_play_without_pos(self): - self.core.current_playlist.append([Track(uri='dummy:a')]) + self.core.tracklist.append([Track(uri='dummy:a')]) - self.sendRequest(u'play') + self.sendRequest('play') self.assertEqual(PLAYING, self.core.playback.state.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_play_with_pos(self): - self.core.current_playlist.append([Track(uri='dummy:a')]) + self.core.tracklist.append([Track(uri='dummy:a')]) - self.sendRequest(u'play "0"') + self.sendRequest('play "0"') self.assertEqual(PLAYING, self.core.playback.state.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_play_with_pos_without_quotes(self): - self.core.current_playlist.append([Track(uri='dummy:a')]) + self.core.tracklist.append([Track(uri='dummy:a')]) - self.sendRequest(u'play 0') + self.sendRequest('play 0') self.assertEqual(PLAYING, self.core.playback.state.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_play_with_pos_out_of_bounds(self): - self.core.current_playlist.append([]) + self.core.tracklist.append([]) - self.sendRequest(u'play "0"') + self.sendRequest('play "0"') self.assertEqual(STOPPED, self.core.playback.state.get()) - self.assertInResponse(u'ACK [2@0] {play} Bad song index') + self.assertInResponse('ACK [2@0] {play} Bad song index') def test_play_minus_one_plays_first_in_playlist_if_no_current_track(self): self.assertEqual(self.core.playback.current_track.get(), None) - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b'), ]) - self.sendRequest(u'play "-1"') + self.sendRequest('play "-1"') self.assertEqual(PLAYING, self.core.playback.state.get()) self.assertEqual('dummy:a', self.core.playback.current_track.get().uri) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_play_minus_one_plays_current_track_if_current_track_is_set(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b'), ]) @@ -249,36 +251,36 @@ class PlaybackControlHandlerTest(protocol.BaseTestCase): self.core.playback.stop() self.assertNotEqual(self.core.playback.current_track.get(), None) - self.sendRequest(u'play "-1"') + self.sendRequest('play "-1"') self.assertEqual(PLAYING, self.core.playback.state.get()) self.assertEqual('dummy:b', self.core.playback.current_track.get().uri) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_play_minus_one_on_empty_playlist_does_not_ack(self): - self.core.current_playlist.clear() + self.core.tracklist.clear() - self.sendRequest(u'play "-1"') + self.sendRequest('play "-1"') self.assertEqual(STOPPED, self.core.playback.state.get()) self.assertEqual(None, self.core.playback.current_track.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_play_minus_is_ignored_if_playing(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a', length=40000)]) self.core.playback.seek(30000) self.assertGreaterEqual( self.core.playback.time_position.get(), 30000) self.assertEquals(PLAYING, self.core.playback.state.get()) - self.sendRequest(u'play "-1"') + self.sendRequest('play "-1"') self.assertEqual(PLAYING, self.core.playback.state.get()) self.assertGreaterEqual( self.core.playback.time_position.get(), 30000) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_play_minus_one_resumes_if_paused(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a', length=40000)]) self.core.playback.seek(30000) self.assertGreaterEqual( @@ -287,41 +289,41 @@ class PlaybackControlHandlerTest(protocol.BaseTestCase): self.core.playback.pause() self.assertEquals(PAUSED, self.core.playback.state.get()) - self.sendRequest(u'play "-1"') + self.sendRequest('play "-1"') self.assertEqual(PLAYING, self.core.playback.state.get()) self.assertGreaterEqual( self.core.playback.time_position.get(), 30000) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_playid(self): - self.core.current_playlist.append([Track(uri='dummy:a')]) + self.core.tracklist.append([Track(uri='dummy:a')]) - self.sendRequest(u'playid "0"') + self.sendRequest('playid "0"') self.assertEqual(PLAYING, self.core.playback.state.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_playid_without_quotes(self): - self.core.current_playlist.append([Track(uri='dummy:a')]) + self.core.tracklist.append([Track(uri='dummy:a')]) - self.sendRequest(u'playid 0') + self.sendRequest('playid 0') self.assertEqual(PLAYING, self.core.playback.state.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_playid_minus_1_plays_first_in_playlist_if_no_current_track(self): self.assertEqual(self.core.playback.current_track.get(), None) - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b'), ]) - self.sendRequest(u'playid "-1"') + self.sendRequest('playid "-1"') self.assertEqual(PLAYING, self.core.playback.state.get()) self.assertEqual('dummy:a', self.core.playback.current_track.get().uri) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_playid_minus_1_plays_current_track_if_current_track_is_set(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b'), ]) @@ -331,35 +333,35 @@ class PlaybackControlHandlerTest(protocol.BaseTestCase): self.core.playback.stop() self.assertNotEqual(None, self.core.playback.current_track.get()) - self.sendRequest(u'playid "-1"') + self.sendRequest('playid "-1"') self.assertEqual(PLAYING, self.core.playback.state.get()) self.assertEqual('dummy:b', self.core.playback.current_track.get().uri) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_playid_minus_one_on_empty_playlist_does_not_ack(self): - self.core.current_playlist.clear() + self.core.tracklist.clear() - self.sendRequest(u'playid "-1"') + self.sendRequest('playid "-1"') self.assertEqual(STOPPED, self.core.playback.state.get()) self.assertEqual(None, self.core.playback.current_track.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_playid_minus_is_ignored_if_playing(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=40000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=40000)]) self.core.playback.seek(30000) self.assertGreaterEqual( self.core.playback.time_position.get(), 30000) self.assertEquals(PLAYING, self.core.playback.state.get()) - self.sendRequest(u'playid "-1"') + self.sendRequest('playid "-1"') self.assertEqual(PLAYING, self.core.playback.state.get()) self.assertGreaterEqual( self.core.playback.time_position.get(), 30000) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_playid_minus_one_resumes_if_paused(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=40000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=40000)]) self.core.playback.seek(30000) self.assertGreaterEqual( self.core.playback.time_position.get(), 30000) @@ -367,66 +369,66 @@ class PlaybackControlHandlerTest(protocol.BaseTestCase): self.core.playback.pause() self.assertEquals(PAUSED, self.core.playback.state.get()) - self.sendRequest(u'playid "-1"') + self.sendRequest('playid "-1"') self.assertEqual(PLAYING, self.core.playback.state.get()) self.assertGreaterEqual( self.core.playback.time_position.get(), 30000) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_playid_which_does_not_exist(self): - self.core.current_playlist.append([Track(uri='dummy:a')]) + self.core.tracklist.append([Track(uri='dummy:a')]) - self.sendRequest(u'playid "12345"') - self.assertInResponse(u'ACK [50@0] {playid} No such song') + self.sendRequest('playid "12345"') + self.assertInResponse('ACK [50@0] {playid} No such song') def test_previous(self): - self.sendRequest(u'previous') - self.assertInResponse(u'OK') + self.sendRequest('previous') + self.assertInResponse('OK') def test_seek(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=40000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=40000)]) - self.sendRequest(u'seek "0"') - self.sendRequest(u'seek "0" "30"') + self.sendRequest('seek "0"') + self.sendRequest('seek "0" "30"') self.assertGreaterEqual(self.core.playback.time_position, 30000) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_seek_with_songpos(self): seek_track = Track(uri='dummy:b', length=40000) - self.core.current_playlist.append( + self.core.tracklist.append( [Track(uri='dummy:a', length=40000), seek_track]) - self.sendRequest(u'seek "1" "30"') + self.sendRequest('seek "1" "30"') self.assertEqual(self.core.playback.current_track.get(), seek_track) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_seek_without_quotes(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=40000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=40000)]) - self.sendRequest(u'seek 0') - self.sendRequest(u'seek 0 30') + self.sendRequest('seek 0') + self.sendRequest('seek 0 30') self.assertGreaterEqual( self.core.playback.time_position.get(), 30000) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_seekid(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=40000)]) - self.sendRequest(u'seekid "0" "30"') + self.core.tracklist.append([Track(uri='dummy:a', length=40000)]) + self.sendRequest('seekid "0" "30"') self.assertGreaterEqual( self.core.playback.time_position.get(), 30000) - self.assertInResponse(u'OK') + self.assertInResponse('OK') - def test_seekid_with_cpid(self): + def test_seekid_with_tlid(self): seek_track = Track(uri='dummy:b', length=40000) - self.core.current_playlist.append( + self.core.tracklist.append( [Track(uri='dummy:a', length=40000), seek_track]) - self.sendRequest(u'seekid "1" "30"') - self.assertEqual(1, self.core.playback.current_cpid.get()) + self.sendRequest('seekid "1" "30"') + self.assertEqual(1, self.core.playback.current_tlid.get()) self.assertEqual(seek_track, self.core.playback.current_track.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_stop(self): - self.sendRequest(u'stop') + self.sendRequest('stop') self.assertEqual(STOPPED, self.core.playback.state.get()) - self.assertInResponse(u'OK') + self.assertInResponse('OK') diff --git a/tests/frontends/mpd/protocol/reflection_test.py b/tests/frontends/mpd/protocol/reflection_test.py index 8bd9b7e0..33032d73 100644 --- a/tests/frontends/mpd/protocol/reflection_test.py +++ b/tests/frontends/mpd/protocol/reflection_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy import settings from tests.frontends.mpd import protocol @@ -5,63 +7,63 @@ from tests.frontends.mpd import protocol class ReflectionHandlerTest(protocol.BaseTestCase): def test_commands_returns_list_of_all_commands(self): - self.sendRequest(u'commands') + self.sendRequest('commands') # Check if some random commands are included - self.assertInResponse(u'command: commands') - self.assertInResponse(u'command: play') - self.assertInResponse(u'command: status') + self.assertInResponse('command: commands') + self.assertInResponse('command: play') + self.assertInResponse('command: status') # Check if commands you do not have access to are not present - self.assertNotInResponse(u'command: kill') + self.assertNotInResponse('command: kill') # Check if the blacklisted commands are not present - self.assertNotInResponse(u'command: command_list_begin') - self.assertNotInResponse(u'command: command_list_ok_begin') - self.assertNotInResponse(u'command: command_list_end') - self.assertNotInResponse(u'command: idle') - self.assertNotInResponse(u'command: noidle') - self.assertNotInResponse(u'command: sticker') - self.assertInResponse(u'OK') + self.assertNotInResponse('command: command_list_begin') + self.assertNotInResponse('command: command_list_ok_begin') + self.assertNotInResponse('command: command_list_end') + self.assertNotInResponse('command: idle') + self.assertNotInResponse('command: noidle') + self.assertNotInResponse('command: sticker') + self.assertInResponse('OK') def test_commands_show_less_if_auth_required_and_not_authed(self): settings.MPD_SERVER_PASSWORD = u'secret' - self.sendRequest(u'commands') + self.sendRequest('commands') # Not requiring auth - self.assertInResponse(u'command: close') - self.assertInResponse(u'command: commands') - self.assertInResponse(u'command: notcommands') - self.assertInResponse(u'command: password') - self.assertInResponse(u'command: ping') + self.assertInResponse('command: close') + self.assertInResponse('command: commands') + self.assertInResponse('command: notcommands') + self.assertInResponse('command: password') + self.assertInResponse('command: ping') # Requiring auth - self.assertNotInResponse(u'command: play') - self.assertNotInResponse(u'command: status') + self.assertNotInResponse('command: play') + self.assertNotInResponse('command: status') def test_decoders(self): - self.sendRequest(u'decoders') - self.assertInResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('decoders') + self.assertInResponse('ACK [0@0] {} Not implemented') def test_notcommands_returns_only_kill_and_ok(self): - response = self.sendRequest(u'notcommands') + response = self.sendRequest('notcommands') self.assertEqual(2, len(response)) - self.assertInResponse(u'command: kill') - self.assertInResponse(u'OK') + self.assertInResponse('command: kill') + self.assertInResponse('OK') def test_notcommands_returns_more_if_auth_required_and_not_authed(self): settings.MPD_SERVER_PASSWORD = u'secret' - self.sendRequest(u'notcommands') + self.sendRequest('notcommands') # Not requiring auth - self.assertNotInResponse(u'command: close') - self.assertNotInResponse(u'command: commands') - self.assertNotInResponse(u'command: notcommands') - self.assertNotInResponse(u'command: password') - self.assertNotInResponse(u'command: ping') + self.assertNotInResponse('command: close') + self.assertNotInResponse('command: commands') + self.assertNotInResponse('command: notcommands') + self.assertNotInResponse('command: password') + self.assertNotInResponse('command: ping') # Requiring auth - self.assertInResponse(u'command: play') - self.assertInResponse(u'command: status') + self.assertInResponse('command: play') + self.assertInResponse('command: status') def test_tagtypes(self): - self.sendRequest(u'tagtypes') - self.assertInResponse(u'OK') + self.sendRequest('tagtypes') + self.assertInResponse('OK') def test_urlhandlers(self): - self.sendRequest(u'urlhandlers') - self.assertInResponse(u'OK') - self.assertInResponse(u'handler: dummy') + self.sendRequest('urlhandlers') + self.assertInResponse('OK') + self.assertInResponse('handler: dummy') diff --git a/tests/frontends/mpd/protocol/regression_test.py b/tests/frontends/mpd/protocol/regression_test.py index a90e37ab..68230c6a 100644 --- a/tests/frontends/mpd/protocol/regression_test.py +++ b/tests/frontends/mpd/protocol/regression_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import random from mopidy.models import Track @@ -16,7 +18,7 @@ class IssueGH17RegressionTest(protocol.BaseTestCase): - Press next until you get to the unplayable track """ def test(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b'), Track(uri='dummy:error'), @@ -26,21 +28,21 @@ class IssueGH17RegressionTest(protocol.BaseTestCase): ]) random.seed(1) # Playlist order: abcfde - self.sendRequest(u'play') + self.sendRequest('play') self.assertEquals('dummy:a', self.core.playback.current_track.get().uri) - self.sendRequest(u'random "1"') - self.sendRequest(u'next') + self.sendRequest('random "1"') + self.sendRequest('next') self.assertEquals('dummy:b', self.core.playback.current_track.get().uri) - self.sendRequest(u'next') + self.sendRequest('next') # Should now be at track 'c', but playback fails and it skips ahead self.assertEquals('dummy:f', self.core.playback.current_track.get().uri) - self.sendRequest(u'next') + self.sendRequest('next') self.assertEquals('dummy:d', self.core.playback.current_track.get().uri) - self.sendRequest(u'next') + self.sendRequest('next') self.assertEquals('dummy:e', self.core.playback.current_track.get().uri) @@ -57,26 +59,26 @@ class IssueGH18RegressionTest(protocol.BaseTestCase): """ def test(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b'), Track(uri='dummy:c'), Track(uri='dummy:d'), Track(uri='dummy:e'), Track(uri='dummy:f')]) random.seed(1) - self.sendRequest(u'play') - self.sendRequest(u'random "1"') - self.sendRequest(u'next') - self.sendRequest(u'random "0"') - self.sendRequest(u'next') + self.sendRequest('play') + self.sendRequest('random "1"') + self.sendRequest('next') + self.sendRequest('random "0"') + self.sendRequest('next') - self.sendRequest(u'next') - cp_track_1 = self.core.playback.current_cp_track.get() - self.sendRequest(u'next') - cp_track_2 = self.core.playback.current_cp_track.get() - self.sendRequest(u'next') - cp_track_3 = self.core.playback.current_cp_track.get() + self.sendRequest('next') + tl_track_1 = self.core.playback.current_tl_track.get() + self.sendRequest('next') + tl_track_2 = self.core.playback.current_tl_track.get() + self.sendRequest('next') + tl_track_3 = self.core.playback.current_tl_track.get() - self.assertNotEqual(cp_track_1, cp_track_2) - self.assertNotEqual(cp_track_2, cp_track_3) + self.assertNotEqual(tl_track_1, tl_track_2) + self.assertNotEqual(tl_track_2, tl_track_3) class IssueGH22RegressionTest(protocol.BaseTestCase): @@ -93,20 +95,20 @@ class IssueGH22RegressionTest(protocol.BaseTestCase): """ def test(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b'), Track(uri='dummy:c'), Track(uri='dummy:d'), Track(uri='dummy:e'), Track(uri='dummy:f')]) random.seed(1) - self.sendRequest(u'play') - self.sendRequest(u'random "1"') - self.sendRequest(u'deleteid "1"') - self.sendRequest(u'deleteid "2"') - self.sendRequest(u'deleteid "3"') - self.sendRequest(u'deleteid "4"') - self.sendRequest(u'deleteid "5"') - self.sendRequest(u'deleteid "6"') - self.sendRequest(u'status') + self.sendRequest('play') + self.sendRequest('random "1"') + self.sendRequest('deleteid "1"') + self.sendRequest('deleteid "2"') + self.sendRequest('deleteid "3"') + self.sendRequest('deleteid "4"') + self.sendRequest('deleteid "5"') + self.sendRequest('deleteid "6"') + self.sendRequest('status') class IssueGH69RegressionTest(protocol.BaseTestCase): @@ -121,15 +123,15 @@ class IssueGH69RegressionTest(protocol.BaseTestCase): """ def test(self): - self.core.stored_playlists.create('foo') - self.core.current_playlist.append([ + self.core.playlists.create('foo') + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b'), Track(uri='dummy:c'), Track(uri='dummy:d'), Track(uri='dummy:e'), Track(uri='dummy:f')]) - self.sendRequest(u'play') - self.sendRequest(u'stop') - self.sendRequest(u'clear') - self.sendRequest(u'load "foo"') + self.sendRequest('play') + self.sendRequest('stop') + self.sendRequest('clear') + self.sendRequest('load "foo"') self.assertNotInResponse('song: None') @@ -146,10 +148,10 @@ class IssueGH113RegressionTest(protocol.BaseTestCase): """ def test(self): - self.core.stored_playlists.create( + self.core.playlists.create( u'all lart spotify:track:\w\{22\} pastes') - self.sendRequest(u'lsinfo "/"') + self.sendRequest('lsinfo "/"') self.assertInResponse( u'playlist: all lart spotify:track:\w\{22\} pastes') diff --git a/tests/frontends/mpd/protocol/status_test.py b/tests/frontends/mpd/protocol/status_test.py index e2f0df9c..ef3cf7b2 100644 --- a/tests/frontends/mpd/protocol/status_test.py +++ b/tests/frontends/mpd/protocol/status_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy.models import Track from tests.frontends.mpd import protocol @@ -5,33 +7,33 @@ from tests.frontends.mpd import protocol class StatusHandlerTest(protocol.BaseTestCase): def test_clearerror(self): - self.sendRequest(u'clearerror') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('clearerror') + self.assertEqualResponse('ACK [0@0] {} Not implemented') def test_currentsong(self): track = Track() - self.core.current_playlist.append([track]) + self.core.tracklist.append([track]) self.core.playback.play() - self.sendRequest(u'currentsong') - self.assertInResponse(u'file: ') - self.assertInResponse(u'Time: 0') - self.assertInResponse(u'Artist: ') - self.assertInResponse(u'Title: ') - self.assertInResponse(u'Album: ') - self.assertInResponse(u'Track: 0') - self.assertInResponse(u'Date: ') - self.assertInResponse(u'Pos: 0') - self.assertInResponse(u'Id: 0') - self.assertInResponse(u'OK') + self.sendRequest('currentsong') + self.assertInResponse('file: ') + self.assertInResponse('Time: 0') + self.assertInResponse('Artist: ') + self.assertInResponse('Title: ') + self.assertInResponse('Album: ') + self.assertInResponse('Track: 0') + self.assertInResponse('Date: ') + self.assertInResponse('Pos: 0') + self.assertInResponse('Id: 0') + self.assertInResponse('OK') def test_currentsong_without_song(self): - self.sendRequest(u'currentsong') - self.assertInResponse(u'OK') + self.sendRequest('currentsong') + self.assertInResponse('OK') def test_stats_command(self): - self.sendRequest(u'stats') - self.assertInResponse(u'OK') + self.sendRequest('stats') + self.assertInResponse('OK') def test_status_command(self): - self.sendRequest(u'status') - self.assertInResponse(u'OK') + self.sendRequest('status') + self.assertInResponse('OK') diff --git a/tests/frontends/mpd/protocol/stickers_test.py b/tests/frontends/mpd/protocol/stickers_test.py index 3e8b687f..de610521 100644 --- a/tests/frontends/mpd/protocol/stickers_test.py +++ b/tests/frontends/mpd/protocol/stickers_test.py @@ -1,33 +1,35 @@ +from __future__ import unicode_literals + from tests.frontends.mpd import protocol class StickersHandlerTest(protocol.BaseTestCase): def test_sticker_get(self): self.sendRequest( - u'sticker get "song" "file:///dev/urandom" "a_name"') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + 'sticker get "song" "file:///dev/urandom" "a_name"') + self.assertEqualResponse('ACK [0@0] {} Not implemented') def test_sticker_set(self): self.sendRequest( - u'sticker set "song" "file:///dev/urandom" "a_name" "a_value"') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + 'sticker set "song" "file:///dev/urandom" "a_name" "a_value"') + self.assertEqualResponse('ACK [0@0] {} Not implemented') def test_sticker_delete_with_name(self): self.sendRequest( - u'sticker delete "song" "file:///dev/urandom" "a_name"') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + 'sticker delete "song" "file:///dev/urandom" "a_name"') + self.assertEqualResponse('ACK [0@0] {} Not implemented') def test_sticker_delete_without_name(self): self.sendRequest( - u'sticker delete "song" "file:///dev/urandom"') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + 'sticker delete "song" "file:///dev/urandom"') + self.assertEqualResponse('ACK [0@0] {} Not implemented') def test_sticker_list(self): self.sendRequest( - u'sticker list "song" "file:///dev/urandom"') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + 'sticker list "song" "file:///dev/urandom"') + self.assertEqualResponse('ACK [0@0] {} Not implemented') def test_sticker_find(self): self.sendRequest( - u'sticker find "song" "file:///dev/urandom" "a_name"') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + 'sticker find "song" "file:///dev/urandom" "a_name"') + self.assertEqualResponse('ACK [0@0] {} Not implemented') diff --git a/tests/frontends/mpd/protocol/stored_playlists_test.py b/tests/frontends/mpd/protocol/stored_playlists_test.py index c8db3f8f..6bac95e5 100644 --- a/tests/frontends/mpd/protocol/stored_playlists_test.py +++ b/tests/frontends/mpd/protocol/stored_playlists_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import datetime from mopidy.models import Track, Playlist @@ -5,109 +7,109 @@ from mopidy.models import Track, Playlist from tests.frontends.mpd import protocol -class StoredPlaylistsHandlerTest(protocol.BaseTestCase): +class PlaylistsHandlerTest(protocol.BaseTestCase): def test_listplaylist(self): - self.backend.stored_playlists.playlists = [ + self.backend.playlists.playlists = [ Playlist(name='name', tracks=[Track(uri='file:///dev/urandom')])] - self.sendRequest(u'listplaylist "name"') - self.assertInResponse(u'file: file:///dev/urandom') - self.assertInResponse(u'OK') + self.sendRequest('listplaylist "name"') + self.assertInResponse('file: file:///dev/urandom') + self.assertInResponse('OK') def test_listplaylist_without_quotes(self): - self.backend.stored_playlists.playlists = [ + self.backend.playlists.playlists = [ Playlist(name='name', tracks=[Track(uri='file:///dev/urandom')])] - self.sendRequest(u'listplaylist name') - self.assertInResponse(u'file: file:///dev/urandom') - self.assertInResponse(u'OK') + self.sendRequest('listplaylist name') + self.assertInResponse('file: file:///dev/urandom') + self.assertInResponse('OK') def test_listplaylist_fails_if_no_playlist_is_found(self): - self.sendRequest(u'listplaylist "name"') - self.assertEqualResponse(u'ACK [50@0] {listplaylist} No such playlist') + self.sendRequest('listplaylist "name"') + self.assertEqualResponse('ACK [50@0] {listplaylist} No such playlist') def test_listplaylistinfo(self): - self.backend.stored_playlists.playlists = [ + self.backend.playlists.playlists = [ Playlist(name='name', tracks=[Track(uri='file:///dev/urandom')])] - self.sendRequest(u'listplaylistinfo "name"') - self.assertInResponse(u'file: file:///dev/urandom') - self.assertInResponse(u'Track: 0') - self.assertNotInResponse(u'Pos: 0') - self.assertInResponse(u'OK') + self.sendRequest('listplaylistinfo "name"') + self.assertInResponse('file: file:///dev/urandom') + self.assertInResponse('Track: 0') + self.assertNotInResponse('Pos: 0') + self.assertInResponse('OK') def test_listplaylistinfo_without_quotes(self): - self.backend.stored_playlists.playlists = [ + self.backend.playlists.playlists = [ Playlist(name='name', tracks=[Track(uri='file:///dev/urandom')])] - self.sendRequest(u'listplaylistinfo name') - self.assertInResponse(u'file: file:///dev/urandom') - self.assertInResponse(u'Track: 0') - self.assertNotInResponse(u'Pos: 0') - self.assertInResponse(u'OK') + self.sendRequest('listplaylistinfo name') + self.assertInResponse('file: file:///dev/urandom') + self.assertInResponse('Track: 0') + self.assertNotInResponse('Pos: 0') + self.assertInResponse('OK') def test_listplaylistinfo_fails_if_no_playlist_is_found(self): - self.sendRequest(u'listplaylistinfo "name"') + self.sendRequest('listplaylistinfo "name"') self.assertEqualResponse( - u'ACK [50@0] {listplaylistinfo} No such playlist') + 'ACK [50@0] {listplaylistinfo} No such playlist') def test_listplaylists(self): last_modified = datetime.datetime(2001, 3, 17, 13, 41, 17, 12345) - self.backend.stored_playlists.playlists = [ + self.backend.playlists.playlists = [ Playlist(name='a', last_modified=last_modified)] - self.sendRequest(u'listplaylists') - self.assertInResponse(u'playlist: a') + self.sendRequest('listplaylists') + self.assertInResponse('playlist: a') # Date without microseconds and with time zone information - self.assertInResponse(u'Last-Modified: 2001-03-17T13:41:17Z') - self.assertInResponse(u'OK') + self.assertInResponse('Last-Modified: 2001-03-17T13:41:17Z') + self.assertInResponse('OK') - def test_load_known_playlist_appends_to_current_playlist(self): - self.core.current_playlist.append([Track(uri='a'), Track(uri='b')]) - self.assertEqual(len(self.core.current_playlist.tracks.get()), 2) - self.backend.stored_playlists.playlists = [ + def test_load_known_playlist_appends_to_tracklist(self): + self.core.tracklist.append([Track(uri='a'), Track(uri='b')]) + self.assertEqual(len(self.core.tracklist.tracks.get()), 2) + self.backend.playlists.playlists = [ Playlist(name='A-list', tracks=[ Track(uri='c'), Track(uri='d'), Track(uri='e')])] - self.sendRequest(u'load "A-list"') - tracks = self.core.current_playlist.tracks.get() + self.sendRequest('load "A-list"') + tracks = self.core.tracklist.tracks.get() self.assertEqual(5, len(tracks)) self.assertEqual('a', tracks[0].uri) self.assertEqual('b', tracks[1].uri) self.assertEqual('c', tracks[2].uri) self.assertEqual('d', tracks[3].uri) self.assertEqual('e', tracks[4].uri) - self.assertInResponse(u'OK') + self.assertInResponse('OK') def test_load_unknown_playlist_acks(self): - self.sendRequest(u'load "unknown playlist"') - self.assertEqual(0, len(self.core.current_playlist.tracks.get())) - self.assertEqualResponse(u'ACK [50@0] {load} No such playlist') + self.sendRequest('load "unknown playlist"') + self.assertEqual(0, len(self.core.tracklist.tracks.get())) + self.assertEqualResponse('ACK [50@0] {load} No such playlist') def test_playlistadd(self): - self.sendRequest(u'playlistadd "name" "file:///dev/urandom"') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('playlistadd "name" "file:///dev/urandom"') + self.assertEqualResponse('ACK [0@0] {} Not implemented') def test_playlistclear(self): - self.sendRequest(u'playlistclear "name"') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('playlistclear "name"') + self.assertEqualResponse('ACK [0@0] {} Not implemented') def test_playlistdelete(self): - self.sendRequest(u'playlistdelete "name" "5"') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('playlistdelete "name" "5"') + self.assertEqualResponse('ACK [0@0] {} Not implemented') def test_playlistmove(self): - self.sendRequest(u'playlistmove "name" "5" "10"') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('playlistmove "name" "5" "10"') + self.assertEqualResponse('ACK [0@0] {} Not implemented') def test_rename(self): - self.sendRequest(u'rename "old_name" "new_name"') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('rename "old_name" "new_name"') + self.assertEqualResponse('ACK [0@0] {} Not implemented') def test_rm(self): - self.sendRequest(u'rm "name"') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('rm "name"') + self.assertEqualResponse('ACK [0@0] {} Not implemented') def test_save(self): - self.sendRequest(u'save "name"') - self.assertEqualResponse(u'ACK [0@0] {} Not implemented') + self.sendRequest('save "name"') + self.assertEqualResponse('ACK [0@0] {} Not implemented') diff --git a/tests/frontends/mpd/serializer_test.py b/tests/frontends/mpd/serializer_test.py index 2d2a9f87..711a069e 100644 --- a/tests/frontends/mpd/serializer_test.py +++ b/tests/frontends/mpd/serializer_test.py @@ -1,21 +1,23 @@ +from __future__ import unicode_literals + import datetime import os from mopidy import settings from mopidy.utils.path import mtime, uri_to_path from mopidy.frontends.mpd import translator, protocol -from mopidy.models import Album, Artist, CpTrack, Playlist, Track +from mopidy.models import Album, Artist, TlTrack, Playlist, Track from tests import unittest class TrackMpdFormatTest(unittest.TestCase): track = Track( - uri=u'a uri', - artists=[Artist(name=u'an artist')], - name=u'a name', - album=Album(name=u'an album', num_tracks=13, - artists=[Artist(name=u'an other artist')]), + uri='a uri', + artists=[Artist(name='an artist')], + name='a name', + album=Album(name='an album', num_tracks=13, + artists=[Artist(name='an other artist')]), track_no=7, date=datetime.date(1977, 1, 1), length=137000, @@ -44,19 +46,19 @@ class TrackMpdFormatTest(unittest.TestCase): result = translator.track_to_mpd_format(Track(), position=1) self.assertNotIn(('Pos', 1), result) - def test_track_to_mpd_format_with_cpid(self): - result = translator.track_to_mpd_format(CpTrack(1, Track())) + def test_track_to_mpd_format_with_tlid(self): + result = translator.track_to_mpd_format(TlTrack(1, Track())) self.assertNotIn(('Id', 1), result) - def test_track_to_mpd_format_with_position_and_cpid(self): + def test_track_to_mpd_format_with_position_and_tlid(self): result = translator.track_to_mpd_format( - CpTrack(2, Track()), position=1) + TlTrack(2, Track()), position=1) self.assertIn(('Pos', 1), result) self.assertIn(('Id', 2), result) def test_track_to_mpd_format_for_nonempty_track(self): result = translator.track_to_mpd_format( - CpTrack(122, self.track), position=9) + TlTrack(122, self.track), position=9) self.assertIn(('file', 'a uri'), result) self.assertIn(('Time', 137), result) self.assertIn(('Artist', 'an artist'), result) @@ -94,14 +96,14 @@ class TrackMpdFormatTest(unittest.TestCase): self.assertIn(('MUSICBRAINZ_ARTISTID', 'foo'), result) def test_artists_to_mpd_format(self): - artists = [Artist(name=u'ABBA'), Artist(name=u'Beatles')] + artists = [Artist(name='ABBA'), Artist(name='Beatles')] translated = translator.artists_to_mpd_format(artists) - self.assertEqual(translated, u'ABBA, Beatles') + self.assertEqual(translated, 'ABBA, Beatles') def test_artists_to_mpd_format_artist_with_no_name(self): artists = [Artist(name=None)] translated = translator.artists_to_mpd_format(artists) - self.assertEqual(translated, u'') + self.assertEqual(translated, '') class PlaylistMpdFormatTest(unittest.TestCase): diff --git a/tests/frontends/mpd/status_test.py b/tests/frontends/mpd/status_test.py index 9f2395e5..6afa5541 100644 --- a/tests/frontends/mpd/status_test.py +++ b/tests/frontends/mpd/status_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import pykka from mopidy import core @@ -129,21 +131,21 @@ class StatusHandlerTest(unittest.TestCase): self.assertEqual(result['state'], 'pause') def test_status_method_when_playlist_loaded_contains_song(self): - self.core.current_playlist.append([Track(uri='dummy:a')]) + self.core.tracklist.append([Track(uri='dummy:a')]) self.core.playback.play() result = dict(status.status(self.context)) self.assertIn('song', result) self.assertGreaterEqual(int(result['song']), 0) - def test_status_method_when_playlist_loaded_contains_cpid_as_songid(self): - self.core.current_playlist.append([Track(uri='dummy:a')]) + def test_status_method_when_playlist_loaded_contains_tlid_as_songid(self): + self.core.tracklist.append([Track(uri='dummy:a')]) self.core.playback.play() result = dict(status.status(self.context)) self.assertIn('songid', result) self.assertEqual(int(result['songid']), 0) def test_status_method_when_playing_contains_time_with_no_length(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=None)]) + self.core.tracklist.append([Track(uri='dummy:a', length=None)]) self.core.playback.play() result = dict(status.status(self.context)) self.assertIn('time', result) @@ -153,7 +155,7 @@ class StatusHandlerTest(unittest.TestCase): self.assertLessEqual(position, total) def test_status_method_when_playing_contains_time_with_length(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=10000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=10000)]) self.core.playback.play() result = dict(status.status(self.context)) self.assertIn('time', result) @@ -163,7 +165,7 @@ class StatusHandlerTest(unittest.TestCase): self.assertLessEqual(position, total) def test_status_method_when_playing_contains_elapsed(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=60000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=60000)]) self.core.playback.play() self.core.playback.pause() self.core.playback.seek(59123) @@ -172,7 +174,7 @@ class StatusHandlerTest(unittest.TestCase): self.assertEqual(result['elapsed'], '59.123') def test_status_method_when_starting_playing_contains_elapsed_zero(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=10000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=10000)]) self.core.playback.play() self.core.playback.pause() result = dict(status.status(self.context)) @@ -180,7 +182,7 @@ class StatusHandlerTest(unittest.TestCase): self.assertEqual(result['elapsed'], '0.000') def test_status_method_when_playing_contains_bitrate(self): - self.core.current_playlist.append([Track(uri='dummy:a', bitrate=320)]) + self.core.tracklist.append([Track(uri='dummy:a', bitrate=320)]) self.core.playback.play() result = dict(status.status(self.context)) self.assertIn('bitrate', result) diff --git a/tests/frontends/mpris/__init__.py b/tests/frontends/mpris/__init__.py index e69de29b..baffc488 100644 --- a/tests/frontends/mpris/__init__.py +++ b/tests/frontends/mpris/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/tests/frontends/mpris/events_test.py b/tests/frontends/mpris/events_test.py index a4efe344..94f48115 100644 --- a/tests/frontends/mpris/events_test.py +++ b/tests/frontends/mpris/events_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import sys import mock diff --git a/tests/frontends/mpris/player_interface_test.py b/tests/frontends/mpris/player_interface_test.py index 620845e4..35fb0161 100644 --- a/tests/frontends/mpris/player_interface_test.py +++ b/tests/frontends/mpris/player_interface_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import sys import mock @@ -58,7 +60,7 @@ class PlayerInterfaceTest(unittest.TestCase): result = self.mpris.Get(objects.PLAYER_IFACE, 'LoopStatus') self.assertEqual('Track', result) - def test_get_loop_status_is_playlist_when_looping_current_playlist(self): + def test_get_loop_status_is_playlist_when_looping_tracklist(self): self.core.playback.repeat = True self.core.playback.single = False result = self.mpris.Get(objects.PLAYER_IFACE, 'LoopStatus') @@ -99,7 +101,7 @@ class PlayerInterfaceTest(unittest.TestCase): def test_set_rate_is_ignored_if_can_control_is_false(self): self.mpris.get_CanControl = lambda *_: False - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.assertEqual(self.core.playback.state.get(), PLAYING) @@ -107,7 +109,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(self.core.playback.state.get(), PLAYING) def test_set_rate_to_zero_pauses_playback(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.assertEqual(self.core.playback.state.get(), PLAYING) @@ -147,38 +149,38 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertIn('mpris:trackid', result.keys()) self.assertEqual(result['mpris:trackid'], '') - def test_get_metadata_has_trackid_based_on_cpid(self): - self.core.current_playlist.append([Track(uri='dummy:a')]) + def test_get_metadata_has_trackid_based_on_tlid(self): + self.core.tracklist.append([Track(uri='dummy:a')]) self.core.playback.play() - (cpid, track) = self.core.playback.current_cp_track.get() + (tlid, track) = self.core.playback.current_tl_track.get() result = self.mpris.Get(objects.PLAYER_IFACE, 'Metadata') self.assertIn('mpris:trackid', result.keys()) self.assertEqual( - result['mpris:trackid'], '/com/mopidy/track/%d' % cpid) + result['mpris:trackid'], '/com/mopidy/track/%d' % tlid) def test_get_metadata_has_track_length(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=40000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=40000)]) self.core.playback.play() result = self.mpris.Get(objects.PLAYER_IFACE, 'Metadata') self.assertIn('mpris:length', result.keys()) self.assertEqual(result['mpris:length'], 40000000) def test_get_metadata_has_track_uri(self): - self.core.current_playlist.append([Track(uri='dummy:a')]) + self.core.tracklist.append([Track(uri='dummy:a')]) self.core.playback.play() result = self.mpris.Get(objects.PLAYER_IFACE, 'Metadata') self.assertIn('xesam:url', result.keys()) self.assertEqual(result['xesam:url'], 'dummy:a') def test_get_metadata_has_track_title(self): - self.core.current_playlist.append([Track(name='a')]) + self.core.tracklist.append([Track(name='a')]) self.core.playback.play() result = self.mpris.Get(objects.PLAYER_IFACE, 'Metadata') self.assertIn('xesam:title', result.keys()) self.assertEqual(result['xesam:title'], 'a') def test_get_metadata_has_track_artists(self): - self.core.current_playlist.append([Track(artists=[ + self.core.tracklist.append([Track(artists=[ Artist(name='a'), Artist(name='b'), Artist(name=None)])]) self.core.playback.play() result = self.mpris.Get(objects.PLAYER_IFACE, 'Metadata') @@ -186,14 +188,14 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(result['xesam:artist'], ['a', 'b']) def test_get_metadata_has_track_album(self): - self.core.current_playlist.append([Track(album=Album(name='a'))]) + self.core.tracklist.append([Track(album=Album(name='a'))]) self.core.playback.play() result = self.mpris.Get(objects.PLAYER_IFACE, 'Metadata') self.assertIn('xesam:album', result.keys()) self.assertEqual(result['xesam:album'], 'a') def test_get_metadata_has_track_album_artists(self): - self.core.current_playlist.append([Track(album=Album(artists=[ + self.core.tracklist.append([Track(album=Album(artists=[ Artist(name='a'), Artist(name='b'), Artist(name=None)]))]) self.core.playback.play() result = self.mpris.Get(objects.PLAYER_IFACE, 'Metadata') @@ -201,7 +203,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(result['xesam:albumArtist'], ['a', 'b']) def test_get_metadata_has_track_number_in_album(self): - self.core.current_playlist.append([Track(track_no=7)]) + self.core.tracklist.append([Track(track_no=7)]) self.core.playback.play() result = self.mpris.Get(objects.PLAYER_IFACE, 'Metadata') self.assertIn('xesam:trackNumber', result.keys()) @@ -244,7 +246,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(self.core.playback.volume.get(), 10) def test_get_position_returns_time_position_in_microseconds(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=40000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=40000)]) self.core.playback.play() self.core.playback.seek(10000) result_in_microseconds = self.mpris.Get( @@ -268,7 +270,7 @@ class PlayerInterfaceTest(unittest.TestCase): def test_can_go_next_is_true_if_can_control_and_other_next_track(self): self.mpris.get_CanControl = lambda *_: True - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() result = self.mpris.Get(objects.PLAYER_IFACE, 'CanGoNext') @@ -276,7 +278,7 @@ class PlayerInterfaceTest(unittest.TestCase): def test_can_go_next_is_false_if_next_track_is_the_same(self): self.mpris.get_CanControl = lambda *_: True - self.core.current_playlist.append([Track(uri='dummy:a')]) + self.core.tracklist.append([Track(uri='dummy:a')]) self.core.playback.repeat = True self.core.playback.play() result = self.mpris.Get(objects.PLAYER_IFACE, 'CanGoNext') @@ -284,7 +286,7 @@ class PlayerInterfaceTest(unittest.TestCase): def test_can_go_next_is_false_if_can_control_is_false(self): self.mpris.get_CanControl = lambda *_: False - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() result = self.mpris.Get(objects.PLAYER_IFACE, 'CanGoNext') @@ -292,7 +294,7 @@ class PlayerInterfaceTest(unittest.TestCase): def test_can_go_previous_is_true_if_can_control_and_previous_track(self): self.mpris.get_CanControl = lambda *_: True - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.core.playback.next() @@ -301,7 +303,7 @@ class PlayerInterfaceTest(unittest.TestCase): def test_can_go_previous_is_false_if_previous_track_is_the_same(self): self.mpris.get_CanControl = lambda *_: True - self.core.current_playlist.append([Track(uri='dummy:a')]) + self.core.tracklist.append([Track(uri='dummy:a')]) self.core.playback.repeat = True self.core.playback.play() result = self.mpris.Get(objects.PLAYER_IFACE, 'CanGoPrevious') @@ -309,7 +311,7 @@ class PlayerInterfaceTest(unittest.TestCase): def test_can_go_previous_is_false_if_can_control_is_false(self): self.mpris.get_CanControl = lambda *_: False - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.core.playback.next() @@ -318,7 +320,7 @@ class PlayerInterfaceTest(unittest.TestCase): def test_can_play_is_true_if_can_control_and_current_track(self): self.mpris.get_CanControl = lambda *_: True - self.core.current_playlist.append([Track(uri='dummy:a')]) + self.core.tracklist.append([Track(uri='dummy:a')]) self.core.playback.play() self.assertTrue(self.core.playback.current_track.get()) result = self.mpris.Get(objects.PLAYER_IFACE, 'CanPlay') @@ -361,7 +363,7 @@ class PlayerInterfaceTest(unittest.TestCase): def test_next_is_ignored_if_can_go_next_is_false(self): self.mpris.get_CanGoNext = lambda *_: False - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.assertEqual(self.core.playback.current_track.get().uri, 'dummy:a') @@ -369,7 +371,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(self.core.playback.current_track.get().uri, 'dummy:a') def test_next_when_playing_skips_to_next_track_and_keep_playing(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.assertEqual(self.core.playback.current_track.get().uri, 'dummy:a') @@ -379,7 +381,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(self.core.playback.state.get(), PLAYING) def test_next_when_at_end_of_list_should_stop_playback(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.core.playback.next() @@ -389,7 +391,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(self.core.playback.state.get(), STOPPED) def test_next_when_paused_should_skip_to_next_track_and_stay_paused(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.core.playback.pause() @@ -400,7 +402,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(self.core.playback.state.get(), PAUSED) def test_next_when_stopped_skips_to_next_track_and_stay_stopped(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.core.playback.stop() @@ -412,7 +414,7 @@ class PlayerInterfaceTest(unittest.TestCase): def test_previous_is_ignored_if_can_go_previous_is_false(self): self.mpris.get_CanGoPrevious = lambda *_: False - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.core.playback.next() @@ -421,7 +423,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(self.core.playback.current_track.get().uri, 'dummy:b') def test_previous_when_playing_skips_to_prev_track_and_keep_playing(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.core.playback.next() @@ -432,7 +434,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(self.core.playback.state.get(), PLAYING) def test_previous_when_at_start_of_list_should_stop_playback(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.assertEqual(self.core.playback.current_track.get().uri, 'dummy:a') @@ -441,7 +443,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(self.core.playback.state.get(), STOPPED) def test_previous_when_paused_skips_to_previous_track_and_pause(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.core.playback.next() @@ -453,7 +455,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(self.core.playback.state.get(), PAUSED) def test_previous_when_stopped_skips_to_previous_track_and_stops(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.core.playback.next() @@ -466,7 +468,7 @@ class PlayerInterfaceTest(unittest.TestCase): def test_pause_is_ignored_if_can_pause_is_false(self): self.mpris.get_CanPause = lambda *_: False - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.assertEqual(self.core.playback.state.get(), PLAYING) @@ -474,7 +476,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(self.core.playback.state.get(), PLAYING) def test_pause_when_playing_should_pause_playback(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.assertEqual(self.core.playback.state.get(), PLAYING) @@ -482,7 +484,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(self.core.playback.state.get(), PAUSED) def test_pause_when_paused_has_no_effect(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.core.playback.pause() @@ -492,7 +494,7 @@ class PlayerInterfaceTest(unittest.TestCase): def test_playpause_is_ignored_if_can_pause_is_false(self): self.mpris.get_CanPause = lambda *_: False - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.assertEqual(self.core.playback.state.get(), PLAYING) @@ -500,7 +502,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(self.core.playback.state.get(), PLAYING) def test_playpause_when_playing_should_pause_playback(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.assertEqual(self.core.playback.state.get(), PLAYING) @@ -508,7 +510,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(self.core.playback.state.get(), PAUSED) def test_playpause_when_paused_should_resume_playback(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.core.playback.pause() @@ -524,7 +526,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertGreaterEqual(after_pause, at_pause) def test_playpause_when_stopped_should_start_playback(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.assertEqual(self.core.playback.state.get(), STOPPED) self.mpris.PlayPause() @@ -532,7 +534,7 @@ class PlayerInterfaceTest(unittest.TestCase): def test_stop_is_ignored_if_can_control_is_false(self): self.mpris.get_CanControl = lambda *_: False - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.assertEqual(self.core.playback.state.get(), PLAYING) @@ -540,7 +542,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(self.core.playback.state.get(), PLAYING) def test_stop_when_playing_should_stop_playback(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.assertEqual(self.core.playback.state.get(), PLAYING) @@ -548,7 +550,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(self.core.playback.state.get(), STOPPED) def test_stop_when_paused_should_stop_playback(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.core.playback.pause() @@ -558,21 +560,21 @@ class PlayerInterfaceTest(unittest.TestCase): def test_play_is_ignored_if_can_play_is_false(self): self.mpris.get_CanPlay = lambda *_: False - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.assertEqual(self.core.playback.state.get(), STOPPED) self.mpris.Play() self.assertEqual(self.core.playback.state.get(), STOPPED) def test_play_when_stopped_starts_playback(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.assertEqual(self.core.playback.state.get(), STOPPED) self.mpris.Play() self.assertEqual(self.core.playback.state.get(), PLAYING) def test_play_after_pause_resumes_from_same_position(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=40000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=40000)]) self.core.playback.play() before_pause = self.core.playback.time_position.get() @@ -589,14 +591,14 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertGreaterEqual(after_pause, at_pause) def test_play_when_there_is_no_track_has_no_effect(self): - self.core.current_playlist.clear() + self.core.tracklist.clear() self.assertEqual(self.core.playback.state.get(), STOPPED) self.mpris.Play() self.assertEqual(self.core.playback.state.get(), STOPPED) def test_seek_is_ignored_if_can_seek_is_false(self): self.mpris.get_CanSeek = lambda *_: False - self.core.current_playlist.append([Track(uri='dummy:a', length=40000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=40000)]) self.core.playback.play() before_seek = self.core.playback.time_position.get() @@ -612,7 +614,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertLess(after_seek, before_seek + milliseconds_to_seek) def test_seek_seeks_given_microseconds_forward_in_the_current_track(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=40000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=40000)]) self.core.playback.play() before_seek = self.core.playback.time_position.get() @@ -629,7 +631,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertGreaterEqual(after_seek, before_seek + milliseconds_to_seek) def test_seek_seeks_given_microseconds_backward_if_negative(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=40000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=40000)]) self.core.playback.play() self.core.playback.seek(20000) @@ -648,7 +650,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertLess(after_seek, before_seek) def test_seek_seeks_to_start_of_track_if_new_position_is_negative(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=40000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=40000)]) self.core.playback.play() self.core.playback.seek(20000) @@ -668,7 +670,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertGreaterEqual(after_seek, 0) def test_seek_skips_to_next_track_if_new_position_gt_track_length(self): - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a', length=40000), Track(uri='dummy:b')]) self.core.playback.play() @@ -693,7 +695,7 @@ class PlayerInterfaceTest(unittest.TestCase): def test_set_position_is_ignored_if_can_seek_is_false(self): self.mpris.get_CanSeek = lambda *_: False - self.core.current_playlist.append([Track(uri='dummy:a', length=40000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=40000)]) self.core.playback.play() before_set_position = self.core.playback.time_position.get() @@ -711,7 +713,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertLess(after_set_position, position_to_set_in_millisec) def test_set_position_sets_the_current_track_position_in_microsecs(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=40000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=40000)]) self.core.playback.play() before_set_position = self.core.playback.time_position.get() @@ -732,7 +734,7 @@ class PlayerInterfaceTest(unittest.TestCase): after_set_position, position_to_set_in_millisec) def test_set_position_does_nothing_if_the_position_is_negative(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=40000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=40000)]) self.core.playback.play() self.core.playback.seek(20000) @@ -755,7 +757,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(self.core.playback.current_track.get().uri, 'dummy:a') def test_set_position_does_nothing_if_position_is_gt_track_length(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=40000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=40000)]) self.core.playback.play() self.core.playback.seek(20000) @@ -778,7 +780,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.assertEqual(self.core.playback.current_track.get().uri, 'dummy:a') def test_set_position_is_noop_if_track_id_isnt_current_track(self): - self.core.current_playlist.append([Track(uri='dummy:a', length=40000)]) + self.core.tracklist.append([Track(uri='dummy:a', length=40000)]) self.core.playback.play() self.core.playback.seek(20000) @@ -805,7 +807,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.backend.library.dummy_library = [ Track(uri='dummy:/test/uri')] self.mpris.OpenUri('dummy:/test/uri') - self.assertEqual(len(self.core.current_playlist.tracks.get()), 0) + self.assertEqual(len(self.core.tracklist.tracks.get()), 0) def test_open_uri_ignores_uris_with_unknown_uri_scheme(self): self.assertListEqual(self.core.uri_schemes.get(), ['dummy']) @@ -813,21 +815,21 @@ class PlayerInterfaceTest(unittest.TestCase): self.backend.library.dummy_library = [ Track(uri='notdummy:/test/uri')] self.mpris.OpenUri('notdummy:/test/uri') - self.assertEqual(len(self.core.current_playlist.tracks.get()), 0) + self.assertEqual(len(self.core.tracklist.tracks.get()), 0) - def test_open_uri_adds_uri_to_current_playlist(self): + def test_open_uri_adds_uri_to_tracklist(self): self.mpris.get_CanPlay = lambda *_: True self.backend.library.dummy_library = [ Track(uri='dummy:/test/uri')] self.mpris.OpenUri('dummy:/test/uri') self.assertEqual( - self.core.current_playlist.tracks.get()[0].uri, 'dummy:/test/uri') + self.core.tracklist.tracks.get()[0].uri, 'dummy:/test/uri') def test_open_uri_starts_playback_of_new_track_if_stopped(self): self.mpris.get_CanPlay = lambda *_: True self.backend.library.dummy_library = [ Track(uri='dummy:/test/uri')] - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.assertEqual(self.core.playback.state.get(), STOPPED) @@ -841,7 +843,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.mpris.get_CanPlay = lambda *_: True self.backend.library.dummy_library = [ Track(uri='dummy:/test/uri')] - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.core.playback.pause() @@ -858,7 +860,7 @@ class PlayerInterfaceTest(unittest.TestCase): self.mpris.get_CanPlay = lambda *_: True self.backend.library.dummy_library = [ Track(uri='dummy:/test/uri')] - self.core.current_playlist.append([ + self.core.tracklist.append([ Track(uri='dummy:a'), Track(uri='dummy:b')]) self.core.playback.play() self.assertEqual(self.core.playback.state.get(), PLAYING) diff --git a/tests/frontends/mpris/root_interface_test.py b/tests/frontends/mpris/root_interface_test.py index 79a8b07f..9e16c6bb 100644 --- a/tests/frontends/mpris/root_interface_test.py +++ b/tests/frontends/mpris/root_interface_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import sys import mock diff --git a/tests/help_test.py b/tests/help_test.py index a2803b72..fdef0f52 100644 --- a/tests/help_test.py +++ b/tests/help_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import os import subprocess import sys diff --git a/tests/models_test.py b/tests/models_test.py index 004c0a28..4e3cdabf 100644 --- a/tests/models_test.py +++ b/tests/models_test.py @@ -1,6 +1,8 @@ +from __future__ import unicode_literals + import datetime -from mopidy.models import Artist, Album, CpTrack, Track, Playlist +from mopidy.models import Artist, Album, TlTrack, Track, Playlist from tests import unittest @@ -52,19 +54,19 @@ class GenericCopyTets(unittest.TestCase): class ArtistTest(unittest.TestCase): def test_uri(self): - uri = u'an_uri' + uri = 'an_uri' artist = Artist(uri=uri) self.assertEqual(artist.uri, uri) self.assertRaises(AttributeError, setattr, artist, 'uri', None) def test_name(self): - name = u'a name' + name = 'a name' artist = Artist(name=name) self.assertEqual(artist.name, name) self.assertRaises(AttributeError, setattr, artist, 'name', None) def test_musicbrainz_id(self): - mb_id = u'mb-id' + mb_id = 'mb-id' artist = Artist(musicbrainz_id=mb_id) self.assertEqual(artist.musicbrainz_id, mb_id) self.assertRaises( @@ -76,7 +78,7 @@ class ArtistTest(unittest.TestCase): def test_repr(self): self.assertEquals( - "Artist(name='name', uri='uri')", + "Artist(name=u'name', uri=u'uri')", repr(Artist(uri='uri', name='name'))) def test_serialize(self): @@ -85,26 +87,26 @@ class ArtistTest(unittest.TestCase): Artist(uri='uri', name='name').serialize()) def test_eq_name(self): - artist1 = Artist(name=u'name') - artist2 = Artist(name=u'name') + artist1 = Artist(name='name') + artist2 = Artist(name='name') self.assertEqual(artist1, artist2) self.assertEqual(hash(artist1), hash(artist2)) def test_eq_uri(self): - artist1 = Artist(uri=u'uri') - artist2 = Artist(uri=u'uri') + artist1 = Artist(uri='uri') + artist2 = Artist(uri='uri') self.assertEqual(artist1, artist2) self.assertEqual(hash(artist1), hash(artist2)) def test_eq_musibrainz_id(self): - artist1 = Artist(musicbrainz_id=u'id') - artist2 = Artist(musicbrainz_id=u'id') + artist1 = Artist(musicbrainz_id='id') + artist2 = Artist(musicbrainz_id='id') self.assertEqual(artist1, artist2) self.assertEqual(hash(artist1), hash(artist2)) def test_eq(self): - artist1 = Artist(uri=u'uri', name=u'name', musicbrainz_id='id') - artist2 = Artist(uri=u'uri', name=u'name', musicbrainz_id='id') + artist1 = Artist(uri='uri', name='name', musicbrainz_id='id') + artist2 = Artist(uri='uri', name='name', musicbrainz_id='id') self.assertEqual(artist1, artist2) self.assertEqual(hash(artist1), hash(artist2)) @@ -115,39 +117,39 @@ class ArtistTest(unittest.TestCase): self.assertNotEqual(Artist(), 'other') def test_ne_name(self): - artist1 = Artist(name=u'name1') - artist2 = Artist(name=u'name2') + artist1 = Artist(name='name1') + artist2 = Artist(name='name2') self.assertNotEqual(artist1, artist2) self.assertNotEqual(hash(artist1), hash(artist2)) def test_ne_uri(self): - artist1 = Artist(uri=u'uri1') - artist2 = Artist(uri=u'uri2') + artist1 = Artist(uri='uri1') + artist2 = Artist(uri='uri2') self.assertNotEqual(artist1, artist2) self.assertNotEqual(hash(artist1), hash(artist2)) def test_ne_musicbrainz_id(self): - artist1 = Artist(musicbrainz_id=u'id1') - artist2 = Artist(musicbrainz_id=u'id2') + artist1 = Artist(musicbrainz_id='id1') + artist2 = Artist(musicbrainz_id='id2') self.assertNotEqual(artist1, artist2) self.assertNotEqual(hash(artist1), hash(artist2)) def test_ne(self): - artist1 = Artist(uri=u'uri1', name=u'name1', musicbrainz_id='id1') - artist2 = Artist(uri=u'uri2', name=u'name2', musicbrainz_id='id2') + artist1 = Artist(uri='uri1', name='name1', musicbrainz_id='id1') + artist2 = Artist(uri='uri2', name='name2', musicbrainz_id='id2') self.assertNotEqual(artist1, artist2) self.assertNotEqual(hash(artist1), hash(artist2)) class AlbumTest(unittest.TestCase): def test_uri(self): - uri = u'an_uri' + uri = 'an_uri' album = Album(uri=uri) self.assertEqual(album.uri, uri) self.assertRaises(AttributeError, setattr, album, 'uri', None) def test_name(self): - name = u'a name' + name = 'a name' album = Album(name=name) self.assertEqual(album.name, name) self.assertRaises(AttributeError, setattr, album, 'name', None) @@ -171,7 +173,7 @@ class AlbumTest(unittest.TestCase): self.assertRaises(AttributeError, setattr, album, 'date', None) def test_musicbrainz_id(self): - mb_id = u'mb-id' + mb_id = 'mb-id' album = Album(musicbrainz_id=mb_id) self.assertEqual(album.musicbrainz_id, mb_id) self.assertRaises( @@ -183,12 +185,12 @@ class AlbumTest(unittest.TestCase): def test_repr_without_artists(self): self.assertEquals( - "Album(artists=[], name='name', uri='uri')", + "Album(artists=[], name=u'name', uri=u'uri')", repr(Album(uri='uri', name='name'))) def test_repr_with_artists(self): self.assertEquals( - "Album(artists=[Artist(name='foo')], name='name', uri='uri')", + "Album(artists=[Artist(name=u'foo')], name=u'name', uri=u'uri')", repr(Album(uri='uri', name='name', artists=[Artist(name='foo')]))) def test_serialize_without_artists(self): @@ -203,14 +205,14 @@ class AlbumTest(unittest.TestCase): Album(uri='uri', name='name', artists=[artist]).serialize()) def test_eq_name(self): - album1 = Album(name=u'name') - album2 = Album(name=u'name') + album1 = Album(name='name') + album2 = Album(name='name') self.assertEqual(album1, album2) self.assertEqual(hash(album1), hash(album2)) def test_eq_uri(self): - album1 = Album(uri=u'uri') - album2 = Album(uri=u'uri') + album1 = Album(uri='uri') + album2 = Album(uri='uri') self.assertEqual(album1, album2) self.assertEqual(hash(album1), hash(album2)) @@ -222,8 +224,8 @@ class AlbumTest(unittest.TestCase): self.assertEqual(hash(album1), hash(album2)) def test_eq_artists_order(self): - artist1 = Artist(name=u'name1') - artist2 = Artist(name=u'name2') + artist1 = Artist(name='name1') + artist2 = Artist(name='name2') album1 = Album(artists=[artist1, artist2]) album2 = Album(artists=[artist2, artist1]) self.assertEqual(album1, album2) @@ -243,18 +245,18 @@ class AlbumTest(unittest.TestCase): self.assertEqual(hash(album1), hash(album2)) def test_eq_musibrainz_id(self): - album1 = Album(musicbrainz_id=u'id') - album2 = Album(musicbrainz_id=u'id') + album1 = Album(musicbrainz_id='id') + album2 = Album(musicbrainz_id='id') self.assertEqual(album1, album2) self.assertEqual(hash(album1), hash(album2)) def test_eq(self): artists = [Artist()] album1 = Album( - name=u'name', uri=u'uri', artists=artists, num_tracks=2, + name='name', uri='uri', artists=artists, num_tracks=2, musicbrainz_id='id') album2 = Album( - name=u'name', uri=u'uri', artists=artists, num_tracks=2, + name='name', uri='uri', artists=artists, num_tracks=2, musicbrainz_id='id') self.assertEqual(album1, album2) self.assertEqual(hash(album1), hash(album2)) @@ -266,20 +268,20 @@ class AlbumTest(unittest.TestCase): self.assertNotEqual(Album(), 'other') def test_ne_name(self): - album1 = Album(name=u'name1') - album2 = Album(name=u'name2') + album1 = Album(name='name1') + album2 = Album(name='name2') self.assertNotEqual(album1, album2) self.assertNotEqual(hash(album1), hash(album2)) def test_ne_uri(self): - album1 = Album(uri=u'uri1') - album2 = Album(uri=u'uri2') + album1 = Album(uri='uri1') + album2 = Album(uri='uri2') self.assertNotEqual(album1, album2) self.assertNotEqual(hash(album1), hash(album2)) def test_ne_artists(self): - album1 = Album(artists=[Artist(name=u'name1')]) - album2 = Album(artists=[Artist(name=u'name2')]) + album1 = Album(artists=[Artist(name='name1')]) + album2 = Album(artists=[Artist(name='name2')]) self.assertNotEqual(album1, album2) self.assertNotEqual(hash(album1), hash(album2)) @@ -296,52 +298,52 @@ class AlbumTest(unittest.TestCase): self.assertNotEqual(hash(album1), hash(album2)) def test_ne_musicbrainz_id(self): - album1 = Album(musicbrainz_id=u'id1') - album2 = Album(musicbrainz_id=u'id2') + album1 = Album(musicbrainz_id='id1') + album2 = Album(musicbrainz_id='id2') self.assertNotEqual(album1, album2) self.assertNotEqual(hash(album1), hash(album2)) def test_ne(self): album1 = Album( - name=u'name1', uri=u'uri1', artists=[Artist(name=u'name1')], + name='name1', uri='uri1', artists=[Artist(name='name1')], num_tracks=1, musicbrainz_id='id1') album2 = Album( - name=u'name2', uri=u'uri2', artists=[Artist(name=u'name2')], + name='name2', uri='uri2', artists=[Artist(name='name2')], num_tracks=2, musicbrainz_id='id2') self.assertNotEqual(album1, album2) self.assertNotEqual(hash(album1), hash(album2)) -class CpTrackTest(unittest.TestCase): +class TlTrackTest(unittest.TestCase): def setUp(self): - self.cpid = 123 + self.tlid = 123 self.track = Track() - self.cp_track = CpTrack(self.cpid, self.track) + self.tl_track = TlTrack(self.tlid, self.track) - def test_cp_track_can_be_accessed_as_a_tuple(self): - self.assertEqual(self.cpid, self.cp_track[0]) - self.assertEqual(self.track, self.cp_track[1]) + def test_tl_track_can_be_accessed_as_a_tuple(self): + self.assertEqual(self.tlid, self.tl_track[0]) + self.assertEqual(self.track, self.tl_track[1]) - def test_cp_track_can_be_accessed_by_attribute_names(self): - self.assertEqual(self.cpid, self.cp_track.cpid) - self.assertEqual(self.track, self.cp_track.track) + def test_tl_track_can_be_accessed_by_attribute_names(self): + self.assertEqual(self.tlid, self.tl_track.tlid) + self.assertEqual(self.track, self.tl_track.track) class TrackTest(unittest.TestCase): def test_uri(self): - uri = u'an_uri' + uri = 'an_uri' track = Track(uri=uri) self.assertEqual(track.uri, uri) self.assertRaises(AttributeError, setattr, track, 'uri', None) def test_name(self): - name = u'a name' + name = 'a name' track = Track(name=name) self.assertEqual(track.name, name) self.assertRaises(AttributeError, setattr, track, 'name', None) def test_artists(self): - artists = [Artist(name=u'name1'), Artist(name=u'name2')] + artists = [Artist(name='name1'), Artist(name='name2')] track = Track(artists=artists) self.assertEqual(set(track.artists), set(artists)) self.assertRaises(AttributeError, setattr, track, 'artists', None) @@ -377,7 +379,7 @@ class TrackTest(unittest.TestCase): self.assertRaises(AttributeError, setattr, track, 'bitrate', None) def test_musicbrainz_id(self): - mb_id = u'mb-id' + mb_id = 'mb-id' track = Track(musicbrainz_id=mb_id) self.assertEqual(track.musicbrainz_id, mb_id) self.assertRaises( @@ -389,12 +391,12 @@ class TrackTest(unittest.TestCase): def test_repr_without_artists(self): self.assertEquals( - "Track(artists=[], name='name', uri='uri')", + "Track(artists=[], name=u'name', uri=u'uri')", repr(Track(uri='uri', name='name'))) def test_repr_with_artists(self): self.assertEquals( - "Track(artists=[Artist(name='foo')], name='name', uri='uri')", + "Track(artists=[Artist(name=u'foo')], name=u'name', uri=u'uri')", repr(Track(uri='uri', name='name', artists=[Artist(name='foo')]))) def test_serialize_without_artists(self): @@ -415,14 +417,14 @@ class TrackTest(unittest.TestCase): Track(uri='uri', name='name', album=album).serialize()) def test_eq_uri(self): - track1 = Track(uri=u'uri1') - track2 = Track(uri=u'uri1') + track1 = Track(uri='uri1') + track2 = Track(uri='uri1') self.assertEqual(track1, track2) self.assertEqual(hash(track1), hash(track2)) def test_eq_name(self): - track1 = Track(name=u'name1') - track2 = Track(name=u'name1') + track1 = Track(name='name1') + track2 = Track(name='name1') self.assertEqual(track1, track2) self.assertEqual(hash(track1), hash(track2)) @@ -434,8 +436,8 @@ class TrackTest(unittest.TestCase): self.assertEqual(hash(track1), hash(track2)) def test_eq_artists_order(self): - artist1 = Artist(name=u'name1') - artist2 = Artist(name=u'name2') + artist1 = Artist(name='name1') + artist2 = Artist(name='name2') track1 = Track(artists=[artist1, artist2]) track2 = Track(artists=[artist2, artist1]) self.assertEqual(track1, track2) @@ -474,8 +476,8 @@ class TrackTest(unittest.TestCase): self.assertEqual(hash(track1), hash(track2)) def test_eq_musibrainz_id(self): - track1 = Track(musicbrainz_id=u'id') - track2 = Track(musicbrainz_id=u'id') + track1 = Track(musicbrainz_id='id') + track2 = Track(musicbrainz_id='id') self.assertEqual(track1, track2) self.assertEqual(hash(track1), hash(track2)) @@ -484,10 +486,10 @@ class TrackTest(unittest.TestCase): artists = [Artist()] album = Album() track1 = Track( - uri=u'uri', name=u'name', artists=artists, album=album, track_no=1, + uri='uri', name='name', artists=artists, album=album, track_no=1, date=date, length=100, bitrate=100, musicbrainz_id='id') track2 = Track( - uri=u'uri', name=u'name', artists=artists, album=album, track_no=1, + uri='uri', name='name', artists=artists, album=album, track_no=1, date=date, length=100, bitrate=100, musicbrainz_id='id') self.assertEqual(track1, track2) self.assertEqual(hash(track1), hash(track2)) @@ -499,26 +501,26 @@ class TrackTest(unittest.TestCase): self.assertNotEqual(Track(), 'other') def test_ne_uri(self): - track1 = Track(uri=u'uri1') - track2 = Track(uri=u'uri2') + track1 = Track(uri='uri1') + track2 = Track(uri='uri2') self.assertNotEqual(track1, track2) self.assertNotEqual(hash(track1), hash(track2)) def test_ne_name(self): - track1 = Track(name=u'name1') - track2 = Track(name=u'name2') + track1 = Track(name='name1') + track2 = Track(name='name2') self.assertNotEqual(track1, track2) self.assertNotEqual(hash(track1), hash(track2)) def test_ne_artists(self): - track1 = Track(artists=[Artist(name=u'name1')]) - track2 = Track(artists=[Artist(name=u'name2')]) + track1 = Track(artists=[Artist(name='name1')]) + track2 = Track(artists=[Artist(name='name2')]) self.assertNotEqual(track1, track2) self.assertNotEqual(hash(track1), hash(track2)) def test_ne_album(self): - track1 = Track(album=Album(name=u'name1')) - track2 = Track(album=Album(name=u'name2')) + track1 = Track(album=Album(name='name1')) + track2 = Track(album=Album(name='name2')) self.assertNotEqual(track1, track2) self.assertNotEqual(hash(track1), hash(track2)) @@ -547,19 +549,19 @@ class TrackTest(unittest.TestCase): self.assertNotEqual(hash(track1), hash(track2)) def test_ne_musicbrainz_id(self): - track1 = Track(musicbrainz_id=u'id1') - track2 = Track(musicbrainz_id=u'id2') + track1 = Track(musicbrainz_id='id1') + track2 = Track(musicbrainz_id='id2') self.assertNotEqual(track1, track2) self.assertNotEqual(hash(track1), hash(track2)) def test_ne(self): track1 = Track( - uri=u'uri1', name=u'name1', artists=[Artist(name=u'name1')], - album=Album(name=u'name1'), track_no=1, date='1977-01-01', + uri='uri1', name='name1', artists=[Artist(name='name1')], + album=Album(name='name1'), track_no=1, date='1977-01-01', length=100, bitrate=100, musicbrainz_id='id1') track2 = Track( - uri=u'uri2', name=u'name2', artists=[Artist(name=u'name2')], - album=Album(name=u'name2'), track_no=2, date='1977-01-02', + uri='uri2', name='name2', artists=[Artist(name='name2')], + album=Album(name='name2'), track_no=2, date='1977-01-02', length=200, bitrate=200, musicbrainz_id='id2') self.assertNotEqual(track1, track2) self.assertNotEqual(hash(track1), hash(track2)) @@ -567,13 +569,13 @@ class TrackTest(unittest.TestCase): class PlaylistTest(unittest.TestCase): def test_uri(self): - uri = u'an_uri' + uri = 'an_uri' playlist = Playlist(uri=uri) self.assertEqual(playlist.uri, uri) self.assertRaises(AttributeError, setattr, playlist, 'uri', None) def test_name(self): - name = u'a name' + name = 'a name' playlist = Playlist(name=name) self.assertEqual(playlist.name, name) self.assertRaises(AttributeError, setattr, playlist, 'name', None) @@ -600,11 +602,11 @@ class PlaylistTest(unittest.TestCase): tracks = [Track()] last_modified = datetime.datetime.now() playlist = Playlist( - uri=u'an uri', name=u'a name', tracks=tracks, + uri='an uri', name='a name', tracks=tracks, last_modified=last_modified) - new_playlist = playlist.copy(uri=u'another uri') - self.assertEqual(new_playlist.uri, u'another uri') - self.assertEqual(new_playlist.name, u'a name') + new_playlist = playlist.copy(uri='another uri') + self.assertEqual(new_playlist.uri, 'another uri') + self.assertEqual(new_playlist.name, 'a name') self.assertEqual(list(new_playlist.tracks), tracks) self.assertEqual(new_playlist.last_modified, last_modified) @@ -612,11 +614,11 @@ class PlaylistTest(unittest.TestCase): tracks = [Track()] last_modified = datetime.datetime.now() playlist = Playlist( - uri=u'an uri', name=u'a name', tracks=tracks, + uri='an uri', name='a name', tracks=tracks, last_modified=last_modified) - new_playlist = playlist.copy(name=u'another name') - self.assertEqual(new_playlist.uri, u'an uri') - self.assertEqual(new_playlist.name, u'another name') + new_playlist = playlist.copy(name='another name') + self.assertEqual(new_playlist.uri, 'an uri') + self.assertEqual(new_playlist.name, 'another name') self.assertEqual(list(new_playlist.tracks), tracks) self.assertEqual(new_playlist.last_modified, last_modified) @@ -624,12 +626,12 @@ class PlaylistTest(unittest.TestCase): tracks = [Track()] last_modified = datetime.datetime.now() playlist = Playlist( - uri=u'an uri', name=u'a name', tracks=tracks, + uri='an uri', name='a name', tracks=tracks, last_modified=last_modified) new_tracks = [Track(), Track()] new_playlist = playlist.copy(tracks=new_tracks) - self.assertEqual(new_playlist.uri, u'an uri') - self.assertEqual(new_playlist.name, u'a name') + self.assertEqual(new_playlist.uri, 'an uri') + self.assertEqual(new_playlist.name, 'a name') self.assertEqual(list(new_playlist.tracks), new_tracks) self.assertEqual(new_playlist.last_modified, last_modified) @@ -638,11 +640,11 @@ class PlaylistTest(unittest.TestCase): last_modified = datetime.datetime.now() new_last_modified = last_modified + datetime.timedelta(1) playlist = Playlist( - uri=u'an uri', name=u'a name', tracks=tracks, + uri='an uri', name='a name', tracks=tracks, last_modified=last_modified) new_playlist = playlist.copy(last_modified=new_last_modified) - self.assertEqual(new_playlist.uri, u'an uri') - self.assertEqual(new_playlist.name, u'a name') + self.assertEqual(new_playlist.uri, 'an uri') + self.assertEqual(new_playlist.name, 'a name') self.assertEqual(list(new_playlist.tracks), tracks) self.assertEqual(new_playlist.last_modified, new_last_modified) @@ -652,13 +654,13 @@ class PlaylistTest(unittest.TestCase): def test_repr_without_tracks(self): self.assertEquals( - "Playlist(name='name', tracks=[], uri='uri')", + "Playlist(name=u'name', tracks=[], uri=u'uri')", repr(Playlist(uri='uri', name='name'))) def test_repr_with_tracks(self): self.assertEquals( - "Playlist(name='name', tracks=[Track(artists=[], name='foo')], " - "uri='uri')", + "Playlist(name=u'name', tracks=[Track(artists=[], name=u'foo')], " + "uri=u'uri')", repr(Playlist(uri='uri', name='name', tracks=[Track(name='foo')]))) def test_serialize_without_tracks(self): @@ -673,14 +675,14 @@ class PlaylistTest(unittest.TestCase): Playlist(uri='uri', name='name', tracks=[track]).serialize()) def test_eq_name(self): - playlist1 = Playlist(name=u'name') - playlist2 = Playlist(name=u'name') + playlist1 = Playlist(name='name') + playlist2 = Playlist(name='name') self.assertEqual(playlist1, playlist2) self.assertEqual(hash(playlist1), hash(playlist2)) def test_eq_uri(self): - playlist1 = Playlist(uri=u'uri') - playlist2 = Playlist(uri=u'uri') + playlist1 = Playlist(uri='uri') + playlist2 = Playlist(uri='uri') self.assertEqual(playlist1, playlist2) self.assertEqual(hash(playlist1), hash(playlist2)) @@ -700,9 +702,9 @@ class PlaylistTest(unittest.TestCase): def test_eq(self): tracks = [Track()] playlist1 = Playlist( - uri=u'uri', name=u'name', tracks=tracks, last_modified=1) + uri='uri', name='name', tracks=tracks, last_modified=1) playlist2 = Playlist( - uri=u'uri', name=u'name', tracks=tracks, last_modified=1) + uri='uri', name='name', tracks=tracks, last_modified=1) self.assertEqual(playlist1, playlist2) self.assertEqual(hash(playlist1), hash(playlist2)) @@ -713,20 +715,20 @@ class PlaylistTest(unittest.TestCase): self.assertNotEqual(Playlist(), 'other') def test_ne_name(self): - playlist1 = Playlist(name=u'name1') - playlist2 = Playlist(name=u'name2') + playlist1 = Playlist(name='name1') + playlist2 = Playlist(name='name2') self.assertNotEqual(playlist1, playlist2) self.assertNotEqual(hash(playlist1), hash(playlist2)) def test_ne_uri(self): - playlist1 = Playlist(uri=u'uri1') - playlist2 = Playlist(uri=u'uri2') + playlist1 = Playlist(uri='uri1') + playlist2 = Playlist(uri='uri2') self.assertNotEqual(playlist1, playlist2) self.assertNotEqual(hash(playlist1), hash(playlist2)) def test_ne_tracks(self): - playlist1 = Playlist(tracks=[Track(uri=u'uri1')]) - playlist2 = Playlist(tracks=[Track(uri=u'uri2')]) + playlist1 = Playlist(tracks=[Track(uri='uri1')]) + playlist2 = Playlist(tracks=[Track(uri='uri2')]) self.assertNotEqual(playlist1, playlist2) self.assertNotEqual(hash(playlist1), hash(playlist2)) @@ -738,10 +740,10 @@ class PlaylistTest(unittest.TestCase): def test_ne(self): playlist1 = Playlist( - uri=u'uri1', name=u'name2', tracks=[Track(uri=u'uri1')], + uri='uri1', name='name2', tracks=[Track(uri='uri1')], last_modified=1) playlist2 = Playlist( - uri=u'uri2', name=u'name2', tracks=[Track(uri=u'uri2')], + uri='uri2', name='name2', tracks=[Track(uri='uri2')], last_modified=2) self.assertNotEqual(playlist1, playlist2) self.assertNotEqual(hash(playlist1), hash(playlist2)) diff --git a/tests/outputs/__init__.py b/tests/outputs/__init__.py index e69de29b..baffc488 100644 --- a/tests/outputs/__init__.py +++ b/tests/outputs/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/tests/scanner_test.py b/tests/scanner_test.py index 6af48bb5..08784458 100644 --- a/tests/scanner_test.py +++ b/tests/scanner_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from datetime import date from mopidy.scanner import Scanner, translator @@ -17,14 +19,14 @@ class TranslatorTest(unittest.TestCase): def setUp(self): self.data = { 'uri': 'uri', - 'album': u'albumname', + 'album': 'albumname', 'track-number': 1, - 'artist': u'name', + 'artist': 'name', 'album-artist': 'albumartistname', - 'title': u'trackname', + 'title': 'trackname', 'track-count': 2, 'date': FakeGstDate(2006, 1, 1,), - 'container-format': u'ID3 tag', + 'container-format': 'ID3 tag', 'duration': 4531, 'musicbrainz-trackid': 'mbtrackid', 'musicbrainz-albumid': 'mbalbumid', diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py index e69de29b..baffc488 100644 --- a/tests/utils/__init__.py +++ b/tests/utils/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/tests/utils/deps_test.py b/tests/utils/deps_test.py index 42c8b299..168f98e5 100644 --- a/tests/utils/deps_test.py +++ b/tests/utils/deps_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import platform import pygst diff --git a/tests/utils/encoding_test.py b/tests/utils/encoding_test.py index da50d9be..1a4e56c5 100644 --- a/tests/utils/encoding_test.py +++ b/tests/utils/encoding_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import mock from mopidy.utils.encoding import locale_decode @@ -11,22 +13,22 @@ class LocaleDecodeTest(unittest.TestCase): mock.return_value = 'UTF-8' result = locale_decode( - '[Errno 98] Adresse d\xc3\xa9j\xc3\xa0 utilis\xc3\xa9e') + b'[Errno 98] Adresse d\xc3\xa9j\xc3\xa0 utilis\xc3\xa9e') - self.assertEquals(u'[Errno 98] Adresse d\xe9j\xe0 utilis\xe9e', result) + self.assertEquals('[Errno 98] Adresse d\xe9j\xe0 utilis\xe9e', result) def test_can_decode_an_ioerror_with_french_content(self, mock): mock.return_value = 'UTF-8' - error = IOError(98, 'Adresse d\xc3\xa9j\xc3\xa0 utilis\xc3\xa9e') + error = IOError(98, b'Adresse d\xc3\xa9j\xc3\xa0 utilis\xc3\xa9e') result = locale_decode(error) - self.assertEquals(u'[Errno 98] Adresse d\xe9j\xe0 utilis\xe9e', result) + self.assertEquals('[Errno 98] Adresse d\xe9j\xe0 utilis\xe9e', result) def test_does_not_use_locale_to_decode_unicode_strings(self, mock): mock.return_value = 'UTF-8' - locale_decode(u'abc') + locale_decode('abc') self.assertFalse(mock.called) diff --git a/tests/utils/importing_test.py b/tests/utils/importing_test.py index 271f9dbe..5be4078b 100644 --- a/tests/utils/importing_test.py +++ b/tests/utils/importing_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from mopidy.utils import importing from tests import unittest diff --git a/tests/utils/network/__init__.py b/tests/utils/network/__init__.py index e69de29b..baffc488 100644 --- a/tests/utils/network/__init__.py +++ b/tests/utils/network/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/tests/utils/network/connection_test.py b/tests/utils/network/connection_test.py index c9fe9a05..3e63cdfc 100644 --- a/tests/utils/network/connection_test.py +++ b/tests/utils/network/connection_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import errno import gobject import logging diff --git a/tests/utils/network/lineprotocol_test.py b/tests/utils/network/lineprotocol_test.py index 9a19e12e..530c708c 100644 --- a/tests/utils/network/lineprotocol_test.py +++ b/tests/utils/network/lineprotocol_test.py @@ -1,4 +1,6 @@ -#encoding: utf-8 +# encoding: utf-8 + +from __future__ import unicode_literals import re from mock import sentinel, Mock @@ -159,10 +161,10 @@ class LineProtocolTest(unittest.TestCase): def test_parse_lines_unicode(self): self.mock.delimiter = re.compile(r'\n') - self.mock.recv_buffer = u'æøå\n'.encode('utf-8') + self.mock.recv_buffer = 'æøå\n'.encode('utf-8') lines = network.LineProtocol.parse_lines(self.mock) - self.assertEqual(u'æøå'.encode('utf-8'), lines.next()) + self.assertEqual('æøå'.encode('utf-8'), lines.next()) self.assertRaises(StopIteration, lines.next) self.assertEqual('', self.mock.recv_buffer) @@ -208,10 +210,10 @@ class LineProtocolTest(unittest.TestCase): def test_send_line_encodes_joined_lines_with_final_terminator(self): self.mock.connection = Mock(spec=network.Connection) - self.mock.join_lines.return_value = u'lines\n' + self.mock.join_lines.return_value = 'lines\n' network.LineProtocol.send_lines(self.mock, sentinel.lines) - self.mock.encode.assert_called_once_with(u'lines\n') + self.mock.encode.assert_called_once_with('lines\n') def test_send_lines_sends_encoded_string(self): self.mock.connection = Mock(spec=network.Connection) @@ -222,11 +224,11 @@ class LineProtocolTest(unittest.TestCase): self.mock.connection.queue_send.assert_called_once_with(sentinel.data) def test_join_lines_returns_empty_string_for_no_lines(self): - self.assertEqual(u'', network.LineProtocol.join_lines(self.mock, [])) + self.assertEqual('', network.LineProtocol.join_lines(self.mock, [])) def test_join_lines_returns_joined_lines(self): - self.assertEqual(u'1\n2\n', network.LineProtocol.join_lines( - self.mock, [u'1', u'2'])) + self.assertEqual('1\n2\n', network.LineProtocol.join_lines( + self.mock, ['1', '2'])) def test_decode_calls_decode_on_string(self): string = Mock() @@ -236,13 +238,13 @@ class LineProtocolTest(unittest.TestCase): def test_decode_plain_ascii(self): result = network.LineProtocol.decode(self.mock, 'abc') - self.assertEqual(u'abc', result) + self.assertEqual('abc', result) self.assertEqual(unicode, type(result)) def test_decode_utf8(self): result = network.LineProtocol.decode( - self.mock, u'æøå'.encode('utf-8')) - self.assertEqual(u'æøå', result) + self.mock, 'æøå'.encode('utf-8')) + self.assertEqual('æøå', result) self.assertEqual(unicode, type(result)) def test_decode_invalid_data(self): @@ -259,13 +261,13 @@ class LineProtocolTest(unittest.TestCase): string.encode.assert_called_once_with(self.mock.encoding) def test_encode_plain_ascii(self): - result = network.LineProtocol.encode(self.mock, u'abc') + result = network.LineProtocol.encode(self.mock, 'abc') self.assertEqual('abc', result) self.assertEqual(str, type(result)) def test_encode_utf8(self): - result = network.LineProtocol.encode(self.mock, u'æøå') - self.assertEqual(u'æøå'.encode('utf-8'), result) + result = network.LineProtocol.encode(self.mock, 'æøå') + self.assertEqual('æøå'.encode('utf-8'), result) self.assertEqual(str, type(result)) def test_encode_invalid_data(self): diff --git a/tests/utils/network/server_test.py b/tests/utils/network/server_test.py index 6090077d..3f7da337 100644 --- a/tests/utils/network/server_test.py +++ b/tests/utils/network/server_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import errno import gobject import socket diff --git a/tests/utils/network/utils_test.py b/tests/utils/network/utils_test.py index f28aeb4b..ff8af9bd 100644 --- a/tests/utils/network/utils_test.py +++ b/tests/utils/network/utils_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import socket from mock import patch, Mock diff --git a/tests/utils/path_test.py b/tests/utils/path_test.py index 91951ac7..512a3ba1 100644 --- a/tests/utils/path_test.py +++ b/tests/utils/path_test.py @@ -1,5 +1,7 @@ # encoding: utf-8 +from __future__ import unicode_literals + import glib import os import shutil @@ -58,61 +60,61 @@ class GetOrCreateFolderTest(unittest.TestCase): class PathToFileURITest(unittest.TestCase): def test_simple_path(self): if sys.platform == 'win32': - result = path.path_to_uri(u'C:/WINDOWS/clock.avi') + result = path.path_to_uri('C:/WINDOWS/clock.avi') self.assertEqual(result, 'file:///C://WINDOWS/clock.avi') else: - result = path.path_to_uri(u'/etc/fstab') + result = path.path_to_uri('/etc/fstab') self.assertEqual(result, 'file:///etc/fstab') def test_folder_and_path(self): if sys.platform == 'win32': - result = path.path_to_uri(u'C:/WINDOWS/', u'clock.avi') + result = path.path_to_uri('C:/WINDOWS/', 'clock.avi') self.assertEqual(result, 'file:///C://WINDOWS/clock.avi') else: - result = path.path_to_uri(u'/etc', u'fstab') - self.assertEqual(result, u'file:///etc/fstab') + result = path.path_to_uri('/etc', 'fstab') + self.assertEqual(result, 'file:///etc/fstab') def test_space_in_path(self): if sys.platform == 'win32': - result = path.path_to_uri(u'C:/test this') + result = path.path_to_uri('C:/test this') self.assertEqual(result, 'file:///C://test%20this') else: - result = path.path_to_uri(u'/tmp/test this') - self.assertEqual(result, u'file:///tmp/test%20this') + result = path.path_to_uri('/tmp/test this') + self.assertEqual(result, 'file:///tmp/test%20this') def test_unicode_in_path(self): if sys.platform == 'win32': - result = path.path_to_uri(u'C:/æøå') + result = path.path_to_uri('C:/æøå') self.assertEqual(result, 'file:///C://%C3%A6%C3%B8%C3%A5') else: - result = path.path_to_uri(u'/tmp/æøå') - self.assertEqual(result, u'file:///tmp/%C3%A6%C3%B8%C3%A5') + result = path.path_to_uri('/tmp/æøå') + self.assertEqual(result, 'file:///tmp/%C3%A6%C3%B8%C3%A5') class UriToPathTest(unittest.TestCase): def test_simple_uri(self): if sys.platform == 'win32': result = path.uri_to_path('file:///C://WINDOWS/clock.avi') - self.assertEqual(result, u'C:/WINDOWS/clock.avi') + self.assertEqual(result, 'C:/WINDOWS/clock.avi') else: result = path.uri_to_path('file:///etc/fstab') - self.assertEqual(result, u'/etc/fstab') + self.assertEqual(result, '/etc/fstab') def test_space_in_uri(self): if sys.platform == 'win32': result = path.uri_to_path('file:///C://test%20this') - self.assertEqual(result, u'C:/test this') + self.assertEqual(result, 'C:/test this') else: - result = path.uri_to_path(u'file:///tmp/test%20this') - self.assertEqual(result, u'/tmp/test this') + result = path.uri_to_path('file:///tmp/test%20this') + self.assertEqual(result, '/tmp/test this') def test_unicode_in_uri(self): if sys.platform == 'win32': result = path.uri_to_path('file:///C://%C3%A6%C3%B8%C3%A5') - self.assertEqual(result, u'C:/æøå') + self.assertEqual(result, 'C:/æøå') else: - result = path.uri_to_path(u'file:///tmp/%C3%A6%C3%B8%C3%A5') - self.assertEqual(result, u'/tmp/æøå') + result = path.uri_to_path('file:///tmp/%C3%A6%C3%B8%C3%A5') + self.assertEqual(result, '/tmp/æøå') class SplitPathTest(unittest.TestCase): diff --git a/tests/utils/settings_test.py b/tests/utils/settings_test.py index c98527cd..0ecbb90f 100644 --- a/tests/utils/settings_test.py +++ b/tests/utils/settings_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import os from mopidy import exceptions, settings @@ -25,29 +27,34 @@ class ValidateSettingsTest(unittest.TestCase): self.defaults, {'MPD_SERVER_HOSTNMAE': '127.0.0.1'}) self.assertEqual( result['MPD_SERVER_HOSTNMAE'], - u'Unknown setting. Did you mean MPD_SERVER_HOSTNAME?') + 'Unknown setting. Did you mean MPD_SERVER_HOSTNAME?') + + def test_custom_settings_does_not_return_errors(self): + result = setting_utils.validate_settings( + self.defaults, {'CUSTOM_MYAPP_SETTING': 'foobar'}) + self.assertNotIn('CUSTOM_MYAPP_SETTING', result) def test_not_renamed_setting_returns_error(self): result = setting_utils.validate_settings( self.defaults, {'SERVER_HOSTNAME': '127.0.0.1'}) self.assertEqual( result['SERVER_HOSTNAME'], - u'Deprecated setting. Use MPD_SERVER_HOSTNAME.') + 'Deprecated setting. Use MPD_SERVER_HOSTNAME.') def test_unneeded_settings_returns_error(self): result = setting_utils.validate_settings( self.defaults, {'SPOTIFY_LIB_APPKEY': '/tmp/foo'}) self.assertEqual( result['SPOTIFY_LIB_APPKEY'], - u'Deprecated setting. It may be removed.') + 'Deprecated setting. It may be removed.') def test_unavailable_bitrate_setting_returns_error(self): result = setting_utils.validate_settings( self.defaults, {'SPOTIFY_BITRATE': 50}) self.assertEqual( result['SPOTIFY_BITRATE'], - u'Unavailable Spotify bitrate. ' - u'Available bitrates are 96, 160, and 320.') + 'Unavailable Spotify bitrate. ' + 'Available bitrates are 96, 160, and 320.') def test_two_errors_are_both_reported(self): result = setting_utils.validate_settings( @@ -56,7 +63,7 @@ class ValidateSettingsTest(unittest.TestCase): def test_masks_value_if_secret(self): secret = setting_utils.mask_value_if_secret('SPOTIFY_PASSWORD', 'bar') - self.assertEqual(u'********', secret) + self.assertEqual('********', secret) def test_does_not_mask_value_if_not_secret(self): not_secret = setting_utils.mask_value_if_secret( @@ -72,13 +79,13 @@ class ValidateSettingsTest(unittest.TestCase): result = setting_utils.validate_settings( self.defaults, {'FRONTENDS': []}) self.assertEqual( - result['FRONTENDS'], u'Must contain at least one value.') + result['FRONTENDS'], 'Must contain at least one value.') def test_empty_backends_list_returns_error(self): result = setting_utils.validate_settings( self.defaults, {'BACKENDS': []}) self.assertEqual( - result['BACKENDS'], u'Must contain at least one value.') + result['BACKENDS'], 'Must contain at least one value.') class SettingsProxyTest(unittest.TestCase): @@ -93,17 +100,17 @@ class SettingsProxyTest(unittest.TestCase): def test_getattr_raises_error_on_missing_setting(self): try: self.settings.TEST - self.fail(u'Should raise exception') + self.fail('Should raise exception') except exceptions.SettingsError as e: - self.assertEqual(u'Setting "TEST" is not set.', e.message) + self.assertEqual('Setting "TEST" is not set.', e.message) def test_getattr_raises_error_on_empty_setting(self): - self.settings.TEST = u'' + self.settings.TEST = '' try: self.settings.TEST - self.fail(u'Should raise exception') + self.fail('Should raise exception') except exceptions.SettingsError as e: - self.assertEqual(u'Setting "TEST" is empty.', e.message) + self.assertEqual('Setting "TEST" is empty.', e.message) def test_getattr_does_not_raise_error_if_setting_is_false(self): self.settings.TEST = False @@ -191,12 +198,12 @@ class FormatSettingListTest(unittest.TestCase): self.settings = setting_utils.SettingsProxy(settings) def test_contains_the_setting_name(self): - self.settings.TEST = u'test' + self.settings.TEST = 'test' result = setting_utils.format_settings_list(self.settings) self.assertIn('TEST:', result, result) def test_repr_of_a_string_value(self): - self.settings.TEST = u'test' + self.settings.TEST = 'test' result = setting_utils.format_settings_list(self.settings) self.assertIn("TEST: u'test'", result, result) @@ -206,18 +213,18 @@ class FormatSettingListTest(unittest.TestCase): self.assertIn("TEST: 123", result, result) def test_repr_of_a_tuple_value(self): - self.settings.TEST = (123, u'abc') + self.settings.TEST = (123, 'abc') result = setting_utils.format_settings_list(self.settings) self.assertIn("TEST: (123, u'abc')", result, result) def test_passwords_are_masked(self): - self.settings.TEST_PASSWORD = u'secret' + self.settings.TEST_PASSWORD = 'secret' result = setting_utils.format_settings_list(self.settings) self.assertNotIn("TEST_PASSWORD: u'secret'", result, result) self.assertIn("TEST_PASSWORD: u'********'", result, result) def test_short_values_are_not_pretty_printed(self): - self.settings.FRONTEND = (u'mopidy.frontends.mpd.MpdFrontend',) + self.settings.FRONTEND = ('mopidy.frontends.mpd.MpdFrontend',) result = setting_utils.format_settings_list(self.settings) self.assertIn( "FRONTEND: (u'mopidy.frontends.mpd.MpdFrontend',)", result) diff --git a/tests/version_test.py b/tests/version_test.py index 2689a716..978660b0 100644 --- a/tests/version_test.py +++ b/tests/version_test.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + from distutils.version import StrictVersion as SV from mopidy import __version__ diff --git a/tools/debug-proxy.py b/tools/debug-proxy.py index 4fb39b5b..938afa57 100755 --- a/tools/debug-proxy.py +++ b/tools/debug-proxy.py @@ -1,5 +1,7 @@ #! /usr/bin/env python +from __future__ import unicode_literals + import argparse import difflib import sys diff --git a/tools/idle.py b/tools/idle.py index fc9cb021..122e998d 100644 --- a/tools/idle.py +++ b/tools/idle.py @@ -3,6 +3,8 @@ # This script is helper to systematicly test the behaviour of MPD's idle # command. It is simply provided as a quick hack, expect nothing more. +from __future__ import unicode_literals + import logging import pprint import socket