Example #1
0
    def set_consume(self, value):
        """Set consume mode.

        :class:`True`
            Tracks are removed from the tracklist when they have been played.
        :class:`False`
            Tracks are not removed from the tracklist.
        """
        validation.check_boolean(value)
        if self.get_consume() != value:
            self._trigger_options_changed()
        return setattr(self, '_consume', value)
Example #2
0
    def set_consume(self, value):
        """Set consume mode.

        :class:`True`
            Tracks are removed from the tracklist when they have been played.
        :class:`False`
            Tracks are not removed from the tracklist.
        """
        validation.check_boolean(value)
        if self.get_consume() != value:
            self._trigger_options_changed()
        self._consume = value
Example #3
0
    def set_single(self, value):
        """
        Set single mode.

        :class:`True`
            Playback is stopped after current song, unless in ``repeat`` mode.
        :class:`False`
            Playback continues after current song.
        """
        validation.check_boolean(value)
        if self.get_single() != value:
            self._trigger_options_changed()
        self._single = value
Example #4
0
    def set_single(self, value):
        """
        Set single mode.

        :class:`True`
            Playback is stopped after current song, unless in ``repeat`` mode.
        :class:`False`
            Playback continues after current song.
        """
        validation.check_boolean(value)
        if self.get_single() != value:
            self._trigger_options_changed()
        return setattr(self, '_single', value)
Example #5
0
    def set_random(self, value):
        """Set random mode.

        :class:`True`
            Tracks are selected at random from the tracklist.
        :class:`False`
            Tracks are played in the order of the tracklist.
        """
        validation.check_boolean(value)
        if self.get_random() != value:
            self._trigger_options_changed()
        if value:
            self._shuffled = self.get_tl_tracks()
            random.shuffle(self._shuffled)
        self._random = value
Example #6
0
    def set_repeat(self, value):
        """
        Set repeat mode.

        To repeat a single track, set both ``repeat`` and ``single``.

        :class:`True`
            The tracklist is played repeatedly.
        :class:`False`
            The tracklist is played once.
        """
        validation.check_boolean(value)
        if self.get_repeat() != value:
            self._trigger_options_changed()
        self._repeat = value
Example #7
0
    def set_repeat(self, value):
        """
        Set repeat mode.

        To repeat a single track, set both ``repeat`` and ``single``.

        :class:`True`
            The tracklist is played repeatedly.
        :class:`False`
            The tracklist is played once.
        """
        validation.check_boolean(value)
        if self.get_repeat() != value:
            self._trigger_options_changed()
        return setattr(self, '_repeat', value)
Example #8
0
    def set_random(self, value):
        """Set random mode.

        :class:`True`
            Tracks are selected at random from the tracklist.
        :class:`False`
            Tracks are played in the order of the tracklist.
        """
        validation.check_boolean(value)
        if self.get_random() != value:
            self._trigger_options_changed()
        if value:
            self._shuffled = self.get_tl_tracks()
            random.shuffle(self._shuffled)
        return setattr(self, '_random', value)
Example #9
0
    def set_mute(self, mute):
        """Set mute state.

        :class:`True` to mute, :class:`False` to unmute.

        Returns :class:`True` if call is successful, otherwise :class:`False`.
        """
        validation.check_boolean(mute)
        if self._mixer is None:
            return False  # TODO: 2.0 return None

        with _mixer_error_handling(self._mixer):
            result = self._mixer.set_mute(bool(mute)).get()
            validation.check_instance(result, bool)
            return result

        return False
Example #10
0
def test_check_boolean_error_message():
    with raises(exceptions.ValidationError) as excinfo:
        validation.check_boolean(1234)
    assert 'Expected a boolean, not 1234' == str(excinfo.value)
Example #11
0
    def search(self, query=None, uris=None, exact=False, **kwargs):
        """
        Search the library for tracks where ``field`` contains ``values``.

        If ``uris`` is given, the search is limited to results from within the
        URI roots. For example passing ``uris=['file:']`` will limit the search
        to the local backend.

        Examples::

            # Returns results matching 'a' in any backend
            search({'any': ['a']})

            # Returns results matching artist 'xyz' in any backend
            search({'artist': ['xyz']})

            # Returns results matching 'a' and 'b' and artist 'xyz' in any
            # backend
            search({'any': ['a', 'b'], 'artist': ['xyz']})

            # Returns results matching 'a' if within the given URI roots
            # "file:///media/music" and "spotify:"
            search({'any': ['a']}, uris=['file:///media/music', 'spotify:'])

            # Returns results matching artist 'xyz' and 'abc' in any backend
            search({'artist': ['xyz', 'abc']})

        :param query: one or more queries to search for
        :type query: dict
        :param uris: zero or more URI roots to limit the search to
        :type uris: list of string or :class:`None`
        :param exact: if the search should use exact matching
        :type exact: :class:`bool`
        :rtype: list of :class:`mopidy.models.SearchResult`

        .. versionadded:: 1.0
            The ``exact`` keyword argument, which replaces :meth:`find_exact`.

        .. deprecated:: 1.0
            Previously, if the query was empty, and the backend could support
            it, all available tracks were returned. This has not changed, but
            it is strongly discouraged. No new code should rely on this
            behavior.

        .. deprecated:: 1.1
            Providing the search query via ``kwargs`` is no longer supported.
        """
        query = _normalize_query(query or kwargs)

        uris is None or validation.check_uris(uris)
        query is None or validation.check_query(query)
        validation.check_boolean(exact)

        if kwargs:
            deprecation.warn("core.library.search:kwargs_query")

        if not query:
            deprecation.warn("core.library.search:empty_query")

        futures = {}
        for backend, backend_uris in self._get_backends_to_uris(uris).items():
            futures[backend] = backend.library.search(query=query, uris=backend_uris, exact=exact)

        # Some of our tests check for LookupError to catch bad queries. This is
        # silly and should be replaced with query validation before passing it
        # to the backends.
        reraise = (TypeError, LookupError)

        results = []
        for backend, future in futures.items():
            try:
                with _backend_error_handling(backend, reraise=reraise):
                    result = future.get()
                    if result is not None:
                        validation.check_instance(result, models.SearchResult)
                        results.append(result)
            except TypeError:
                backend_name = backend.actor_ref.actor_class.__name__
                logger.warning(
                    '%s does not implement library.search() with "exact" ' "support. Please upgrade it.", backend_name
                )

        return results
Example #12
0
    def search(self, query=None, uris=None, exact=False, **kwargs):
        """
        Search the library for tracks where ``field`` contains ``values``.

        If ``uris`` is given, the search is limited to results from within the
        URI roots. For example passing ``uris=['file:']`` will limit the search
        to the local backend.

        Examples::

            # Returns results matching 'a' in any backend
            search({'any': ['a']})

            # Returns results matching artist 'xyz' in any backend
            search({'artist': ['xyz']})

            # Returns results matching 'a' and 'b' and artist 'xyz' in any
            # backend
            search({'any': ['a', 'b'], 'artist': ['xyz']})

            # Returns results matching 'a' if within the given URI roots
            # "file:///media/music" and "spotify:"
            search({'any': ['a']}, uris=['file:///media/music', 'spotify:'])

            # Returns results matching artist 'xyz' and 'abc' in any backend
            search({'artist': ['xyz', 'abc']})

        :param query: one or more queries to search for
        :type query: dict
        :param uris: zero or more URI roots to limit the search to
        :type uris: list of string or :class:`None`
        :param exact: if the search should use exact matching
        :type exact: :class:`bool`
        :rtype: list of :class:`mopidy.models.SearchResult`

        .. versionadded:: 1.0
            The ``exact`` keyword argument, which replaces :meth:`find_exact`.

        .. deprecated:: 1.0
            Previously, if the query was empty, and the backend could support
            it, all available tracks were returned. This has not changed, but
            it is strongly discouraged. No new code should rely on this
            behavior.

        .. deprecated:: 1.1
            Providing the search query via ``kwargs`` is no longer supported.
        """
        query = _normalize_query(query or kwargs)

        uris is None or validation.check_uris(uris)
        query is None or validation.check_query(query)
        validation.check_boolean(exact)

        if kwargs:
            deprecation.warn('core.library.search:kwargs_query')

        if not query:
            deprecation.warn('core.library.search:empty_query')

        futures = {}
        for backend, backend_uris in self._get_backends_to_uris(uris).items():
            futures[backend] = backend.library.search(query=query,
                                                      uris=backend_uris,
                                                      exact=exact)

        # Some of our tests check for LookupError to catch bad queries. This is
        # silly and should be replaced with query validation before passing it
        # to the backends.
        reraise = (TypeError, LookupError)

        results = []
        for backend, future in futures.items():
            try:
                with _backend_error_handling(backend, reraise=reraise):
                    result = future.get()
                    if result is not None:
                        validation.check_instance(result, models.SearchResult)
                        results.append(result)
            except TypeError:
                backend_name = backend.actor_ref.actor_class.__name__
                logger.warning(
                    '%s does not implement library.search() with "exact" '
                    'support. Please upgrade it.', backend_name)

        return results
Example #13
0
def test_check_boolean_with_valid_values():
    for value in (True, False):
        validation.check_boolean(value)
Example #14
0
def test_check_boolean_error_message():
    with raises(exceptions.ValidationError) as excinfo:
        validation.check_boolean(1234)
    assert 'Expected a boolean, not 1234' == str(excinfo.value)
Example #15
0
def test_check_boolean_with_other_values():
    for value in 1, 0, None, '', list(), tuple():
        with raises(exceptions.ValidationError):
            validation.check_boolean(value)
Example #16
0
def test_check_boolean_with_valid_values():
    for value in (True, False):
        validation.check_boolean(value)
Example #17
0
    def search(self, query, uris=None, exact=False):
        """
        Search the library for tracks where ``field`` contains ``values``.

        ``field`` can be one of ``uri``, ``track_name``, ``album``, ``artist``,
        ``albumartist``, ``composer``, ``performer``, ``track_no``, ``genre``,
        ``date``, ``comment``, or ``any``.

        If ``uris`` is given, the search is limited to results from within the
        URI roots. For example passing ``uris=['file:']`` will limit the search
        to the local backend.

        Examples::

            # Returns results matching 'a' in any backend
            search({'any': ['a']})

            # Returns results matching artist 'xyz' in any backend
            search({'artist': ['xyz']})

            # Returns results matching 'a' and 'b' and artist 'xyz' in any
            # backend
            search({'any': ['a', 'b'], 'artist': ['xyz']})

            # Returns results matching 'a' if within the given URI roots
            # "file:///media/music" and "spotify:"
            search({'any': ['a']}, uris=['file:///media/music', 'spotify:'])

            # Returns results matching artist 'xyz' and 'abc' in any backend
            search({'artist': ['xyz', 'abc']})

        :param query: one or more queries to search for
        :type query: dict
        :param uris: zero or more URI roots to limit the search to
        :type uris: list of string or :class:`None`
        :param exact: if the search should use exact matching
        :type exact: :class:`bool`
        :rtype: list of :class:`mopidy.models.SearchResult`

        .. versionadded:: 1.0
            The ``exact`` keyword argument.
        """
        query = _normalize_query(query)

        uris is None or validation.check_uris(uris)
        validation.check_query(query)
        validation.check_boolean(exact)

        if not query:
            return []

        futures = {}
        for backend, backend_uris in self._get_backends_to_uris(uris).items():
            futures[backend] = backend.library.search(query=query,
                                                      uris=backend_uris,
                                                      exact=exact)

        # Some of our tests check for LookupError to catch bad queries. This is
        # silly and should be replaced with query validation before passing it
        # to the backends.
        reraise = (TypeError, LookupError)

        results = []
        for backend, future in futures.items():
            try:
                with _backend_error_handling(backend, reraise=reraise):
                    result = future.get()
                    if result is not None:
                        validation.check_instance(result, models.SearchResult)
                        results.append(result)
            except TypeError:
                backend_name = backend.actor_ref.actor_class.__name__
                logger.warning(
                    '%s does not implement library.search() with "exact" '
                    "support. Please upgrade it.",
                    backend_name,
                )

        return results
Example #18
0
def test_check_boolean_with_other_values():
    for value in 1, 0, None, '', list(), tuple():
        with raises(exceptions.ValidationError):
            validation.check_boolean(value)