Merge branch 'RonaldZ-issue997' into develop
This commit is contained in:
commit
f74b1c4c97
@ -15,6 +15,10 @@ from mopidy.internal import path, versioning
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_core_schema = ConfigSchema('core')
|
||||
# MPD supports at most 10k tracks, some clients segfault when this is exceeded.
|
||||
_core_schema['max_tracklist_length'] = Integer(minimum=1, maximum=10000)
|
||||
|
||||
_logging_schema = ConfigSchema('logging')
|
||||
_logging_schema['color'] = Boolean()
|
||||
_logging_schema['console_format'] = String()
|
||||
|
||||
@ -2,7 +2,6 @@ from __future__ import absolute_import, unicode_literals
|
||||
|
||||
# flake8: noqa
|
||||
from .actor import Core
|
||||
from .ext import Extension
|
||||
from .history import HistoryController
|
||||
from .library import LibraryController
|
||||
from .listener import CoreListener
|
||||
|
||||
@ -1 +1,3 @@
|
||||
[core]
|
||||
enabled = true
|
||||
max_tracklist_length = 10000
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import os
|
||||
|
||||
import mopidy
|
||||
from mopidy import config, ext
|
||||
|
||||
|
||||
class Extension(ext.Extension):
|
||||
|
||||
dist_name = 'Mopidy-Core'
|
||||
ext_name = 'core'
|
||||
version = mopidy.__version__
|
||||
|
||||
def get_default_config(self):
|
||||
conf_file = os.path.join(os.path.dirname(__file__), 'ext.conf')
|
||||
return config.read(conf_file)
|
||||
|
||||
def get_config_schema(self):
|
||||
schema = super(Extension, self).get_config_schema()
|
||||
del schema['enabled'] # core cannot be disabled
|
||||
return schema
|
||||
|
||||
def setup(self, registry):
|
||||
pass # core has nothing to register
|
||||
@ -3,6 +3,7 @@ from __future__ import absolute_import, unicode_literals
|
||||
import logging
|
||||
import random
|
||||
|
||||
from mopidy import exceptions
|
||||
from mopidy.core import listener
|
||||
from mopidy.internal import deprecation, validation
|
||||
from mopidy.models import TlTrack, Track
|
||||
@ -431,8 +432,13 @@ class TracklistController(object):
|
||||
tracks.extend(track_map[uri])
|
||||
|
||||
tl_tracks = []
|
||||
max_length = self.core._config['core']['max_tracklist_length']
|
||||
|
||||
for track in tracks:
|
||||
if self.get_length() >= max_length:
|
||||
raise exceptions.TracklistFull(
|
||||
'Tracklist may contain at most %d tracks.' % max_length)
|
||||
|
||||
tl_track = TlTrack(self._next_tlid, track)
|
||||
self._next_tlid += 1
|
||||
if at_position is not None:
|
||||
|
||||
@ -21,6 +21,13 @@ class BackendError(MopidyException):
|
||||
pass
|
||||
|
||||
|
||||
class CoreError(MopidyException):
|
||||
|
||||
def __init__(self, message, errno=None):
|
||||
super(CoreError, self).__init__(message, errno)
|
||||
self.errno = errno
|
||||
|
||||
|
||||
class ExtensionError(MopidyException):
|
||||
pass
|
||||
|
||||
@ -44,6 +51,13 @@ class ScannerError(MopidyException):
|
||||
pass
|
||||
|
||||
|
||||
class TracklistFull(CoreError):
|
||||
|
||||
def __init__(self, message, errno=None):
|
||||
super(TracklistFull, self).__init__(message, errno)
|
||||
self.errno = errno
|
||||
|
||||
|
||||
class AudioException(MopidyException):
|
||||
pass
|
||||
|
||||
|
||||
1
setup.py
1
setup.py
@ -34,7 +34,6 @@ setup(
|
||||
'mopidy = mopidy.__main__:main',
|
||||
],
|
||||
'mopidy.ext': [
|
||||
'core = mopidy.core:Extension',
|
||||
'http = mopidy.http:Extension',
|
||||
'local = mopidy.local:Extension',
|
||||
'file = mopidy.file:Extension',
|
||||
|
||||
@ -17,12 +17,19 @@ from tests import dummy_backend
|
||||
class BackendEventsTest(unittest.TestCase):
|
||||
|
||||
def setUp(self): # noqa: N802
|
||||
config = {
|
||||
'core': {
|
||||
'max_tracklist_length': 10000,
|
||||
}
|
||||
}
|
||||
|
||||
self.backend = dummy_backend.create_proxy()
|
||||
self.backend.library.dummy_library = [
|
||||
Track(uri='dummy:a'), Track(uri='dummy:b')]
|
||||
|
||||
with deprecation.ignore():
|
||||
self.core = core.Core.start(backends=[self.backend]).proxy()
|
||||
self.core = core.Core.start(
|
||||
config, backends=[self.backend]).proxy()
|
||||
|
||||
def tearDown(self): # noqa: N802
|
||||
pykka.ActorRegistry.stop_all()
|
||||
|
||||
@ -18,6 +18,12 @@ from tests import dummy_audio as audio
|
||||
class CorePlaybackTest(unittest.TestCase):
|
||||
|
||||
def setUp(self): # noqa: N802
|
||||
config = {
|
||||
'core': {
|
||||
'max_tracklist_length': 10000,
|
||||
}
|
||||
}
|
||||
|
||||
self.backend1 = mock.Mock()
|
||||
self.backend1.uri_schemes.get.return_value = ['dummy1']
|
||||
self.playback1 = mock.Mock(spec=backend.PlaybackProvider)
|
||||
@ -46,7 +52,7 @@ class CorePlaybackTest(unittest.TestCase):
|
||||
self.uris = [
|
||||
'dummy1:a', 'dummy2:a', 'dummy3:a', 'dummy1:b', 'dummy1:c']
|
||||
|
||||
self.core = core.Core(mixer=None, backends=[
|
||||
self.core = core.Core(config, mixer=None, backends=[
|
||||
self.backend1, self.backend2, self.backend3])
|
||||
|
||||
def lookup(uris):
|
||||
@ -614,9 +620,16 @@ class TestBackend(pykka.ThreadingActor, backend.Backend):
|
||||
class TestStream(unittest.TestCase):
|
||||
|
||||
def setUp(self): # noqa: N802
|
||||
config = {
|
||||
'core': {
|
||||
'max_tracklist_length': 10000,
|
||||
}
|
||||
}
|
||||
|
||||
self.audio = audio.DummyAudio.start().proxy()
|
||||
self.backend = TestBackend.start(config={}, audio=self.audio).proxy()
|
||||
self.core = core.Core(audio=self.audio, backends=[self.backend])
|
||||
self.core = core.Core(
|
||||
config, audio=self.audio, backends=[self.backend])
|
||||
self.playback = self.core.playback
|
||||
|
||||
self.tracks = [Track(uri='dummy:a', length=1234),
|
||||
@ -698,6 +711,12 @@ class TestStream(unittest.TestCase):
|
||||
class CorePlaybackWithOldBackendTest(unittest.TestCase):
|
||||
|
||||
def test_type_error_from_old_backend_does_not_crash_core(self):
|
||||
config = {
|
||||
'core': {
|
||||
'max_tracklist_length': 10000,
|
||||
}
|
||||
}
|
||||
|
||||
b = mock.Mock()
|
||||
b.uri_schemes.get.return_value = ['dummy1']
|
||||
b.playback = mock.Mock(spec=backend.PlaybackProvider)
|
||||
@ -705,7 +724,7 @@ class CorePlaybackWithOldBackendTest(unittest.TestCase):
|
||||
b.library.lookup.return_value.get.return_value = [
|
||||
Track(uri='dummy1:a', length=40000)]
|
||||
|
||||
c = core.Core(mixer=None, backends=[b])
|
||||
c = core.Core(config, mixer=None, backends=[b])
|
||||
c.tracklist.add(uris=['dummy1:a'])
|
||||
c.playback.play() # No TypeError == test passed.
|
||||
b.playback.play.assert_called_once_with()
|
||||
@ -714,9 +733,15 @@ class CorePlaybackWithOldBackendTest(unittest.TestCase):
|
||||
class TestPlay(unittest.TestCase):
|
||||
|
||||
def setUp(self): # noqa: N802
|
||||
config = {
|
||||
'core': {
|
||||
'max_tracklist_length': 10000,
|
||||
}
|
||||
}
|
||||
|
||||
self.backend = mock.Mock()
|
||||
self.backend.uri_schemes.get.return_value = ['dummy']
|
||||
self.core = core.Core(backends=[self.backend])
|
||||
self.core = core.Core(config, backends=[self.backend])
|
||||
|
||||
self.tracks = [Track(uri='dummy:a', length=1234),
|
||||
Track(uri='dummy:b', length=1234)]
|
||||
@ -732,6 +757,12 @@ class TestPlay(unittest.TestCase):
|
||||
|
||||
class Bug1177RegressionTest(unittest.TestCase):
|
||||
def test(self):
|
||||
config = {
|
||||
'core': {
|
||||
'max_tracklist_length': 10000,
|
||||
}
|
||||
}
|
||||
|
||||
b = mock.Mock()
|
||||
b.uri_schemes.get.return_value = ['dummy']
|
||||
b.playback = mock.Mock(spec=backend.PlaybackProvider)
|
||||
@ -741,7 +772,7 @@ class Bug1177RegressionTest(unittest.TestCase):
|
||||
track1 = Track(uri='dummy:a', length=40000)
|
||||
track2 = Track(uri='dummy:b', length=40000)
|
||||
|
||||
c = core.Core(mixer=None, backends=[b])
|
||||
c = core.Core(config, mixer=None, backends=[b])
|
||||
c.tracklist.add([track1, track2])
|
||||
|
||||
c.playback.play()
|
||||
|
||||
@ -11,7 +11,13 @@ from mopidy.models import TlTrack, Track
|
||||
|
||||
class TracklistTest(unittest.TestCase):
|
||||
|
||||
def setUp(self): # noqa: N802
|
||||
def setUp(self): # noqa:
|
||||
config = {
|
||||
'core': {
|
||||
'max_tracklist_length': 10000,
|
||||
}
|
||||
}
|
||||
|
||||
self.tracks = [
|
||||
Track(uri='dummy1:a', name='foo'),
|
||||
Track(uri='dummy1:b', name='foo'),
|
||||
@ -29,7 +35,7 @@ class TracklistTest(unittest.TestCase):
|
||||
self.library.lookup.side_effect = lookup
|
||||
self.backend.library = self.library
|
||||
|
||||
self.core = core.Core(mixer=None, backends=[self.backend])
|
||||
self.core = core.Core(config, mixer=None, backends=[self.backend])
|
||||
self.tl_tracks = self.core.tracklist.add(uris=[
|
||||
t.uri for t in self.tracks])
|
||||
|
||||
@ -107,6 +113,12 @@ class TracklistTest(unittest.TestCase):
|
||||
class TracklistIndexTest(unittest.TestCase):
|
||||
|
||||
def setUp(self): # noqa: N802
|
||||
config = {
|
||||
'core': {
|
||||
'max_tracklist_length': 10000,
|
||||
}
|
||||
}
|
||||
|
||||
self.tracks = [
|
||||
Track(uri='dummy1:a', name='foo'),
|
||||
Track(uri='dummy1:b', name='foo'),
|
||||
@ -116,7 +128,7 @@ class TracklistIndexTest(unittest.TestCase):
|
||||
def lookup(uris):
|
||||
return {u: [t for t in self.tracks if t.uri == u] for u in uris}
|
||||
|
||||
self.core = core.Core(mixer=None, backends=[])
|
||||
self.core = core.Core(config, mixer=None, backends=[])
|
||||
self.core.library = mock.Mock(spec=core.LibraryController)
|
||||
self.core.library.lookup.side_effect = lookup
|
||||
|
||||
|
||||
@ -22,6 +22,9 @@ from tests.local import generate_song, populate_tracklist
|
||||
|
||||
class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
config = {
|
||||
'core': {
|
||||
'max_tracklist_length': 10000,
|
||||
},
|
||||
'local': {
|
||||
'media_dir': path_to_data_dir(''),
|
||||
'data_dir': path_to_data_dir(''),
|
||||
@ -51,7 +54,7 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
self.audio = dummy_audio.create_proxy()
|
||||
self.backend = actor.LocalBackend.start(
|
||||
config=self.config, audio=self.audio).proxy()
|
||||
self.core = core.Core(backends=[self.backend])
|
||||
self.core = core.Core(self.config, backends=[self.backend])
|
||||
self.playback = self.core.playback
|
||||
self.tracklist = self.core.tracklist
|
||||
|
||||
|
||||
@ -17,6 +17,9 @@ from tests.local import generate_song, populate_tracklist
|
||||
|
||||
class LocalTracklistProviderTest(unittest.TestCase):
|
||||
config = {
|
||||
'core': {
|
||||
'max_tracklist_length': 10000
|
||||
},
|
||||
'local': {
|
||||
'media_dir': path_to_data_dir(''),
|
||||
'data_dir': path_to_data_dir(''),
|
||||
@ -35,7 +38,7 @@ class LocalTracklistProviderTest(unittest.TestCase):
|
||||
self.audio = dummy_audio.create_proxy()
|
||||
self.backend = actor.LocalBackend.start(
|
||||
config=self.config, audio=self.audio).proxy()
|
||||
self.core = core.Core(mixer=None, backends=[self.backend])
|
||||
self.core = core.Core(self.config, mixer=None, backends=[self.backend])
|
||||
self.controller = self.core.tracklist
|
||||
self.playback = self.core.playback
|
||||
|
||||
|
||||
@ -31,6 +31,9 @@ class BaseTestCase(unittest.TestCase):
|
||||
|
||||
def get_config(self):
|
||||
return {
|
||||
'core': {
|
||||
'max_tracklist_length': 10000
|
||||
},
|
||||
'mpd': {
|
||||
'password': None,
|
||||
}
|
||||
@ -45,7 +48,9 @@ class BaseTestCase(unittest.TestCase):
|
||||
|
||||
with deprecation.ignore():
|
||||
self.core = core.Core.start(
|
||||
mixer=self.mixer, backends=[self.backend]).proxy()
|
||||
self.get_config(),
|
||||
mixer=self.mixer,
|
||||
backends=[self.backend]).proxy()
|
||||
|
||||
self.uri_map = uri_mapper.MpdUriMapper(self.core)
|
||||
self.connection = MockConnection()
|
||||
|
||||
@ -25,12 +25,20 @@ STOPPED = PlaybackState.STOPPED
|
||||
class StatusHandlerTest(unittest.TestCase):
|
||||
|
||||
def setUp(self): # noqa: N802
|
||||
config = {
|
||||
'core': {
|
||||
'max_tracklist_length': 10000,
|
||||
}
|
||||
}
|
||||
|
||||
self.mixer = dummy_mixer.create_proxy()
|
||||
self.backend = dummy_backend.create_proxy()
|
||||
|
||||
with deprecation.ignore():
|
||||
self.core = core.Core.start(
|
||||
mixer=self.mixer, backends=[self.backend]).proxy()
|
||||
config,
|
||||
mixer=self.mixer,
|
||||
backends=[self.backend]).proxy()
|
||||
|
||||
self.dispatcher = dispatcher.MpdDispatcher(core=self.core)
|
||||
self.context = self.dispatcher.context
|
||||
|
||||
Loading…
Reference in New Issue
Block a user