def test_versions_can_be_strictly_ordered(self): self.assert_(SV('0.1.0a0') < SV('0.1.0a1')) self.assert_(SV('0.1.0a1') < SV('0.1.0a2')) self.assert_(SV('0.1.0a2') < SV('0.1.0a3')) self.assert_(SV('0.1.0a3') < SV('0.1.0')) self.assert_(SV('0.1.0') < SV('0.2.0')) self.assert_(SV('0.1.0') < SV('1.0.0')) self.assert_(SV('0.2.0') < SV('0.3.0')) self.assert_(SV('0.3.0') < SV(get_version())) self.assert_(SV(get_version()) < SV('0.3.2'))
def setup_logging(verbosity_level, save_debug_log): setup_root_logger() setup_console_logging(verbosity_level) if save_debug_log: setup_debug_logging_to_file() logger = logging.getLogger('mopidy.utils.log') logger.info(u'Starting Mopidy %s on %s %s', get_version(), get_platform(), get_python())
def parse_options(self): parser = optparse.OptionParser(version='Mopidy %s' % get_version()) parser.add_option('-q', '--quiet', action='store_const', const=0, dest='verbosity_level', help='less output (warning level)') parser.add_option('-v', '--verbose', action='store_const', const=2, dest='verbosity_level', help='more output (debug level)') parser.add_option('--save-debug-log', action='store_true', dest='save_debug_log', help='save debug log to "./mopidy.log"') parser.add_option('--list-settings', action='callback', callback=list_settings_optparse_callback, help='list current settings') return parser.parse_args()[0]
def parse_options(): parser = optparse.OptionParser(version=u'Mopidy %s' % get_version()) parser.add_option('--help-gst', action='store_true', dest='help_gst', help='show GStreamer help options') parser.add_option('-i', '--interactive', action='store_true', dest='interactive', help='ask interactively for required settings which is missing') parser.add_option('-q', '--quiet', action='store_const', const=0, dest='verbosity_level', help='less output (warning level)') parser.add_option('-v', '--verbose', action='store_const', const=2, dest='verbosity_level', help='more output (debug level)') parser.add_option('--save-debug-log', action='store_true', dest='save_debug_log', help='save debug log to "./mopidy.log"') parser.add_option('--list-settings', action='callback', callback=list_settings_optparse_callback, help='list current settings') return parser.parse_args(args=mopidy_args)[0]
def parse_options(): parser = optparse.OptionParser(version=u'Mopidy %s' % get_version()) parser.add_option('--help-gst', action='store_true', dest='help_gst', help='show GStreamer help options') parser.add_option('-i', '--interactive', action='store_true', dest='interactive', help='ask interactively for required settings which are missing') parser.add_option('-q', '--quiet', action='store_const', const=0, dest='verbosity_level', help='less output (warning level)') parser.add_option('-v', '--verbose', action='count', default=1, dest='verbosity_level', help='more output (debug level)') parser.add_option('--save-debug-log', action='store_true', dest='save_debug_log', help='save debug log to "./mopidy.log"') parser.add_option('--list-settings', action='callback', callback=list_settings_optparse_callback, help='list current settings') return parser.parse_args(args=mopidy_args)[0]
# The encoding of source files. #source_encoding = 'utf-8' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Mopidy' copyright = u'2010-2011, 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 # built documents. # # The full version, including alpha/beta/rc tags. release = mopidy.get_version() # The short X.Y version. version = '.'.join(release.split('.')[:2]) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build.
if dirname.startswith('.'): del dirnames[i] if '__init__.py' in filenames: packages.append('.'.join(fullsplit(dirpath))) elif filenames: data_files.append([dirpath, [os.path.join(dirpath, f) for f in filenames]]) if os.geteuid() == 0: # Only try to install this file if we are root data_files.append( ('/usr/local/share/applications', ['data/mopidy.desktop'])) setup( name='Mopidy', version=get_version(), author='Stein Magnus Jodal', author_email='*****@*****.**', packages=packages, package_data={'mopidy': ['backends/spotify/spotify_appkey.key']}, cmdclass=cmdclasses, data_files=data_files, scripts=['bin/mopidy', 'bin/mopidy-scan'], url='http://www.mopidy.com/', license='Apache License, Version 2.0', description='MPD server with Spotify support', long_description=open('README.rst').read(), classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: No Input/Output (Daemon)', 'Intended Audience :: End Users/Desktop',
# The encoding of source files. #source_encoding = 'utf-8' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Mopidy' copyright = u'2010-2011, 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 # built documents. # # The full version, including alpha/beta/rc tags. release = mopidy.get_version() # The short X.Y version. version = '.'.join(release.split('.')[:2]) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. #unused_docs = []
project_dir = 'mopidy' for dirpath, dirnames, filenames in os.walk(project_dir): # Ignore dirnames that start with '.' for i, dirname in enumerate(dirnames): if dirname.startswith('.'): del dirnames[i] if '__init__.py' in filenames: packages.append('.'.join(fullsplit(dirpath))) elif filenames: data_files.append( [dirpath, [os.path.join(dirpath, f) for f in filenames]]) setup( name='Mopidy', version=get_version(), author='Stein Magnus Jodal', author_email='*****@*****.**', packages=packages, package_data={'mopidy': ['backends/spotify/spotify_appkey.key']}, cmdclass=cmdclasses, data_files=data_files, scripts=['bin/mopidy', 'bin/mopidy-scan'], url='http://www.mopidy.com/', license='Apache License, Version 2.0', description='MPD server with Spotify support', long_description=open('README.rst').read(), classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: No Input/Output (Daemon)', 'Intended Audience :: End Users/Desktop',
class SpotifySessionManager(BaseThread, PyspotifySessionManager): cache_location = settings.SPOTIFY_CACHE_PATH or CACHE_PATH settings_location = settings.SPOTIFY_CACHE_PATH or CACHE_PATH appkey_file = os.path.join(os.path.dirname(__file__), 'spotify_appkey.key') user_agent = 'Mopidy %s' % get_version() def __init__(self, username, password): PyspotifySessionManager.__init__(self, username, password) BaseThread.__init__(self) self.name = 'SpotifyThread' self.gstreamer = None self.backend = None self.connected = threading.Event() self.session = None self.container_manager = None self.playlist_manager = None def run_inside_try(self): self.setup() self.connect() def setup(self): gstreamer_refs = ActorRegistry.get_by_class(GStreamer) assert len(gstreamer_refs) == 1, \ 'Expected exactly one running gstreamer.' self.gstreamer = gstreamer_refs[0].proxy() backend_refs = ActorRegistry.get_by_class(Backend) assert len(backend_refs) == 1, 'Expected exactly one running backend.' self.backend = backend_refs[0].proxy() def logged_in(self, session, error): """Callback used by pyspotify""" if error: logger.error(u'Spotify login error: %s', error) return logger.info(u'Connected to Spotify') self.session = session logger.debug(u'Preferred Spotify bitrate is %s kbps', settings.SPOTIFY_BITRATE) self.session.set_preferred_bitrate(BITRATES[settings.SPOTIFY_BITRATE]) self.container_manager = SpotifyContainerManager(self) self.playlist_manager = SpotifyPlaylistManager(self) self.container_manager.watch(self.session.playlist_container()) self.connected.set() def logged_out(self, session): """Callback used by pyspotify""" logger.info(u'Disconnected from Spotify') def metadata_updated(self, session): """Callback used by pyspotify""" logger.debug(u'Callback called: Metadata updated') def connection_error(self, session, error): """Callback used by pyspotify""" if error is None: logger.info(u'Spotify connection OK') else: logger.error(u'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()) def notify_main_thread(self, session): """Callback used by pyspotify""" logger.debug(u'notify_main_thread() called') 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' capabilites = """ audio/x-raw-int, endianness=(int)1234, channels=(int)%(channels)d, width=(int)16, depth=(int)16, signed=(boolean)true, rate=(int)%(sample_rate)d """ % { 'sample_rate': sample_rate, 'channels': channels, } self.gstreamer.emit_data(capabilites, bytes(frames)) return num_frames def play_token_lost(self, session): """Callback used by pyspotify""" logger.debug(u'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()) def end_of_track(self, session): """Callback used by pyspotify""" logger.debug(u'End of data stream reached') self.gstreamer.emit_end_of_stream() def refresh_stored_playlists(self): """Refresh the stored playlists in the backend with fresh meta data from Spotify""" playlists = map(SpotifyTranslator.to_mopidy_playlist, self.session.playlist_container()) playlists = filter(None, playlists) self.backend.stored_playlists.playlists = playlists logger.debug(u'Refreshed %d stored playlist(s)', len(playlists)) def search(self, query, queue): """Search method used by Mopidy backend""" def callback(results, userdata=None): # TODO Include results from results.albums(), etc. too # TODO Consider launching a second search if results.total_tracks() # is larger than len(results.tracks()) playlist = Playlist(tracks=[ SpotifyTranslator.to_mopidy_track(t) for t in results.tracks() ]) queue.put(playlist) self.connected.wait() self.session.search(query, callback, track_count=100, album_count=0, artist_count=0) def logout(self): """Log out from spotify""" logger.debug(u'Logging out from Spotify') if self.session: self.session.logout()
#source_encoding = 'utf-8' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Mopidy' copyright = u'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 # built documents. # # The full version, including alpha/beta/rc tags. from mopidy import get_version release = get_version() # The short X.Y version. version = '.'.join(release.split('.')[:2]) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. #unused_docs = []
#source_encoding = 'utf-8' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Mopidy' copyright = u'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 # built documents. # # The full version, including alpha/beta/rc tags. from mopidy import get_version release = get_version() # The short X.Y version. version = '.'.join(release.split('.')[:2]) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build.
def test_current_version_is_parsable_as_a_strict_version_number(self): SV(get_version())
class SpotifySessionManager(BaseThread, PyspotifySessionManager): cache_location = settings.SPOTIFY_CACHE_PATH settings_location = cache_location appkey_file = os.path.join(os.path.dirname(__file__), 'spotify_appkey.key') user_agent = 'Mopidy %s' % get_version() def __init__(self, username, password): PyspotifySessionManager.__init__(self, username, password) BaseThread.__init__(self) self.name = 'SpotifyThread' self.audio = None self.backend = None self.connected = threading.Event() self.session = None self.container_manager = None self.playlist_manager = None self._initial_data_receive_completed = False def run_inside_try(self): self.setup() self.connect() def setup(self): audio_refs = ActorRegistry.get_by_class(audio.Audio) assert len(audio_refs) == 1, \ 'Expected exactly one running Audio instance.' self.audio = audio_refs[0].proxy() backend_refs = ActorRegistry.get_by_class(Backend) assert len(backend_refs) == 1, 'Expected exactly one running backend.' self.backend = backend_refs[0].proxy() def logged_in(self, session, error): """Callback used by pyspotify""" if error: logger.error(u'Spotify login error: %s', error) return logger.info(u'Connected to Spotify') self.session = session logger.debug(u'Preferred Spotify bitrate is %s kbps', settings.SPOTIFY_BITRATE) self.session.set_preferred_bitrate(BITRATES[settings.SPOTIFY_BITRATE]) self.container_manager = SpotifyContainerManager(self) self.playlist_manager = SpotifyPlaylistManager(self) self.container_manager.watch(self.session.playlist_container()) self.connected.set() def logged_out(self, session): """Callback used by pyspotify""" logger.info(u'Disconnected from Spotify') def metadata_updated(self, session): """Callback used by pyspotify""" logger.debug(u'Callback called: Metadata updated') def connection_error(self, session, error): """Callback used by pyspotify""" if error is None: logger.info(u'Spotify connection OK') else: logger.error(u'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()) 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' capabilites = """ audio/x-raw-int, endianness=(int)1234, channels=(int)%(channels)d, width=(int)16, depth=(int)16, signed=(boolean)true, rate=(int)%(sample_rate)d """ % { 'sample_rate': sample_rate, 'channels': channels, } self.audio.emit_data(capabilites, bytes(frames)) return num_frames def play_token_lost(self, session): """Callback used by pyspotify""" logger.debug(u'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()) 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 # 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. self._initial_data_receive_completed = True self.refresh_stored_playlists() def end_of_track(self, session): """Callback used by pyspotify""" logger.debug(u'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""" if not self._initial_data_receive_completed: logger.debug(u'Still getting data; skipped refresh of playlists') return playlists = map(SpotifyTranslator.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)) def search(self, query, queue): """Search method used by Mopidy backend""" def callback(results, userdata=None): # TODO Include results from results.albums(), etc. too # TODO Consider launching a second search if results.total_tracks() # is larger than len(results.tracks()) playlist = Playlist(tracks=[ SpotifyTranslator.to_mopidy_track(t) for t in results.tracks() ]) queue.put(playlist) self.connected.wait() self.session.search(query, callback, track_count=100, album_count=0, artist_count=0) def logout(self): """Log out from spotify""" logger.debug(u'Logging out from Spotify') if self.session: self.session.logout()