Release v0.16.1
This commit is contained in:
commit
578eed99ce
2
.mailmap
2
.mailmap
@ -8,5 +8,5 @@ John Bäckstrand <sopues@gmail.com> <sandos@XBMCLive.(none)>
|
||||
Alli Witheford <alzeih@gmail.com>
|
||||
Alexandre Petitjean <alpetitjean@gmail.com>
|
||||
Alexandre Petitjean <alpetitjean@gmail.com> <alexandre.petitjean@lne.fr>
|
||||
Javier Domingo Cansino <javier.domingo@fon.com> <javierdo1@gmail.com>
|
||||
Javier Domingo Cansino <javierdo1@gmail.com> <javier.domingo@fon.com>
|
||||
Lasse Bigum <lasse@bigum.org> <l.bigum@samsung.com>
|
||||
|
||||
@ -4,7 +4,7 @@ install:
|
||||
- "wget -O - http://apt.mopidy.com/mopidy.gpg | sudo apt-key add -"
|
||||
- "sudo wget -O /etc/apt/sources.list.d/mopidy.list http://apt.mopidy.com/mopidy.list"
|
||||
- "sudo apt-get update || true"
|
||||
- "sudo apt-get install $(apt-cache depends mopidy | awk '$2 !~ /mopidy/ {print $2}')"
|
||||
- "sudo apt-get install $(apt-cache depends mopidy | awk '$2 !~ /mopidy|python:any/ {print $2}')"
|
||||
- "pip install coveralls flake8"
|
||||
|
||||
before_script:
|
||||
|
||||
3
AUTHORS
3
AUTHORS
@ -24,6 +24,7 @@
|
||||
- Alli Witheford <alzeih@gmail.com>
|
||||
- Alexandre Petitjean <alpetitjean@gmail.com>
|
||||
- Terje Larsen <terlar@gmail.com>
|
||||
- Javier Domingo Cansino <javier.domingo@fon.com>
|
||||
- Javier Domingo Cansino <javierdo1@gmail.com>
|
||||
- Pavol Babincak <scroolik@gmail.com>
|
||||
- Javier Domingo <javierdo1@gmail.com>
|
||||
- Lasse Bigum <lasse@bigum.org>
|
||||
|
||||
@ -4,7 +4,13 @@
|
||||
Authors
|
||||
*******
|
||||
|
||||
Contributors to Mopidy in the order of appearance:
|
||||
Mopidy is copyright 2009-2013 Stein Magnus Jodal and contributors. Mopidy is
|
||||
licensed under the `Apache License, Version 2.0
|
||||
<http://www.apache.org/licenses/LICENSE-2.0>`_.
|
||||
|
||||
The following persons have contributed to Mopidy. The list is in the order of
|
||||
first contribution. For details on who have contributed what, please refer to
|
||||
our Git repository.
|
||||
|
||||
.. include:: ../AUTHORS
|
||||
|
||||
|
||||
@ -4,6 +4,30 @@ Changelog
|
||||
|
||||
This changelog is used to track all major changes to Mopidy.
|
||||
|
||||
|
||||
v0.16.1 (2013-11-02)
|
||||
====================
|
||||
|
||||
This is very small release to get Mopidy's Debian package ready for inclusion
|
||||
in Debian.
|
||||
|
||||
**Commands**
|
||||
|
||||
- Fix removal of last dir level in paths to dependencies in
|
||||
``mopidy --show-deps`` output.
|
||||
|
||||
- Add manpages for all commands.
|
||||
|
||||
**Local backend**
|
||||
|
||||
- Fix search filtering by track number that was added in 0.16.0.
|
||||
|
||||
**MPD frontend**
|
||||
|
||||
- Add support for ``list "albumartist" ...`` which was missed when ``find`` and
|
||||
``search`` learned to handle ``albumartist`` in 0.16.0.
|
||||
|
||||
|
||||
v0.16.0 (2013-10-27)
|
||||
====================
|
||||
|
||||
|
||||
13
docs/commands/index.rst
Normal file
13
docs/commands/index.rst
Normal file
@ -0,0 +1,13 @@
|
||||
.. _commands:
|
||||
|
||||
********
|
||||
Commands
|
||||
********
|
||||
|
||||
Mopidy comes with the following commands:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:glob:
|
||||
|
||||
**
|
||||
98
docs/commands/mopidy-convert-config.rst
Normal file
98
docs/commands/mopidy-convert-config.rst
Normal file
@ -0,0 +1,98 @@
|
||||
.. _mopidy-convert-config:
|
||||
|
||||
*****************************
|
||||
mopidy-convert-config command
|
||||
*****************************
|
||||
|
||||
Synopsis
|
||||
========
|
||||
|
||||
mopidy-convert-config
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Mopidy is a music server which can play music both from multiple sources, like
|
||||
your local hard drive, radio streams, and from Spotify and SoundCloud. Searches
|
||||
combines results from all music sources, and you can mix tracks from all
|
||||
sources in your play queue. Your playlists from Spotify or SoundCloud are also
|
||||
available for use.
|
||||
|
||||
The ``mopidy-convert-config`` command is used to convert ``settings.py``
|
||||
configuration files used by ``mopidy`` < 0.14 to the ``mopidy.conf`` config
|
||||
file used by ``mopidy`` >= 0.14.
|
||||
|
||||
|
||||
Options
|
||||
=======
|
||||
|
||||
.. program:: mopidy-convert-config
|
||||
|
||||
This program does not take any options. It looks for the pre-0.14 settings file
|
||||
at ``$XDG_CONFIG_DIR/mopidy/settings.py``, and if it exists it converts it and
|
||||
ouputs a Mopidy 0.14 compatible ini-format configuration. If you don't already
|
||||
have a config file at ``$XDG_CONFIG_DIR/mopidy/mopidy.conf``, you're asked if
|
||||
you want to save the converted config to that file.
|
||||
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
Given the following contents in ``~/.config/mopidy/settings.py``:
|
||||
|
||||
::
|
||||
|
||||
LOCAL_MUSIC_PATH = u'~/music'
|
||||
MPD_SERVER_HOSTNAME = u'::'
|
||||
SPOTIFY_PASSWORD = u'secret'
|
||||
SPOTIFY_USERNAME = u'alice'
|
||||
|
||||
Running ``mopidy-convert-config`` will convert the config and create a new
|
||||
``mopidy.conf`` config file:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
$ mopidy-convert-config
|
||||
Checking /home/alice/.config/mopidy/settings.py
|
||||
Converted config:
|
||||
|
||||
[spotify]
|
||||
username = alice
|
||||
password = ********
|
||||
|
||||
[mpd]
|
||||
hostname = ::
|
||||
|
||||
[local]
|
||||
media_dir = ~/music
|
||||
|
||||
Write new config to /home/alice/.config/mopidy/mopidy.conf? [yN] y
|
||||
Done.
|
||||
|
||||
Contents of ``~/.config/mopidy/mopidy.conf`` after the conversion:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[spotify]
|
||||
username = alice
|
||||
password = secret
|
||||
|
||||
[mpd]
|
||||
hostname = ::
|
||||
|
||||
[local]
|
||||
media_dir = ~/music
|
||||
|
||||
|
||||
See also
|
||||
========
|
||||
|
||||
:ref:`mopidy(1) <mopidy-cmd>`
|
||||
|
||||
|
||||
Reporting bugs
|
||||
==============
|
||||
|
||||
Report bugs to Mopidy's issue tracker at
|
||||
<https://github.com/mopidy/mopidy/issues>
|
||||
59
docs/commands/mopidy-scan.rst
Normal file
59
docs/commands/mopidy-scan.rst
Normal file
@ -0,0 +1,59 @@
|
||||
.. _mopidy-scan-cmd:
|
||||
|
||||
*******************
|
||||
mopidy-scan command
|
||||
*******************
|
||||
|
||||
Synopsis
|
||||
========
|
||||
|
||||
mopidy-scan
|
||||
[-h] [--version] [-q] [-v]
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Mopidy is a music server which can play music both from multiple sources, like
|
||||
your local hard drive, radio streams, and from Spotify and SoundCloud. Searches
|
||||
combines results from all music sources, and you can mix tracks from all
|
||||
sources in your play queue. Your playlists from Spotify or SoundCloud are also
|
||||
available for use.
|
||||
|
||||
The ``mopidy-scan`` command is used to index a music library to make it
|
||||
available for playback with ``mopidy``.
|
||||
|
||||
|
||||
Options
|
||||
=======
|
||||
|
||||
.. program:: mopidy-scan
|
||||
|
||||
.. cmdoption:: --version
|
||||
|
||||
Show Mopidy's version number and exit.
|
||||
|
||||
.. cmdoption:: -h, --help
|
||||
|
||||
Show help message and exit.
|
||||
|
||||
.. cmdoption:: -q, --quiet
|
||||
|
||||
Show less output: warning level and higher.
|
||||
|
||||
.. cmdoption:: -v, --verbose
|
||||
|
||||
Show more output: debug level and higher.
|
||||
|
||||
|
||||
See also
|
||||
========
|
||||
|
||||
:ref:`mopidy(1) <mopidy-cmd>`
|
||||
|
||||
|
||||
Reporting bugs
|
||||
==============
|
||||
|
||||
Report bugs to Mopidy's issue tracker at
|
||||
<https://github.com/mopidy/mopidy/issues>
|
||||
124
docs/commands/mopidy.rst
Normal file
124
docs/commands/mopidy.rst
Normal file
@ -0,0 +1,124 @@
|
||||
.. _mopidy-cmd:
|
||||
|
||||
**************
|
||||
mopidy command
|
||||
**************
|
||||
|
||||
Synopsis
|
||||
========
|
||||
|
||||
mopidy
|
||||
[-h] [--version] [-q] [-v] [--save-debug-log] [--show-config]
|
||||
[--show-deps] [--config CONFIG_FILES] [-o CONFIG_OVERRIDES]
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Mopidy is a music server which can play music both from multiple sources, like
|
||||
your local hard drive, radio streams, and from Spotify and SoundCloud. Searches
|
||||
combines results from all music sources, and you can mix tracks from all
|
||||
sources in your play queue. Your playlists from Spotify or SoundCloud are also
|
||||
available for use.
|
||||
|
||||
The ``mopidy`` command is used to start the server.
|
||||
|
||||
|
||||
Options
|
||||
=======
|
||||
|
||||
.. program:: mopidy
|
||||
|
||||
.. cmdoption:: -h, --help
|
||||
|
||||
Show help message and exit.
|
||||
|
||||
.. cmdoption:: --version
|
||||
|
||||
Show Mopidy's version number and exit.
|
||||
|
||||
.. cmdoption:: -q, --quiet
|
||||
|
||||
Show less output: warning level and higher.
|
||||
|
||||
.. cmdoption:: -v, --verbose
|
||||
|
||||
Show more output: debug level and higher.
|
||||
|
||||
.. cmdoption:: --save-debug-log
|
||||
|
||||
Save debug log to the file specified in the :confval:`logging/debug_file`
|
||||
config value, typically ``./mopidy.log``.
|
||||
|
||||
.. cmdoption:: --show-config
|
||||
|
||||
Show the current effective config. All configuration sources are merged
|
||||
together to show the effective document. Secret values like passwords are
|
||||
masked out. Config for disabled extensions are not included.
|
||||
|
||||
.. cmdoption:: --show-deps
|
||||
|
||||
Show dependencies, their versions and installation location.
|
||||
|
||||
.. cmdoption:: --config <file>
|
||||
|
||||
Specify config file to use. To use multiple config files, separate them
|
||||
with colon. The later files override the earlier ones if there's a
|
||||
conflict.
|
||||
|
||||
.. cmdoption:: -o <option>, --option <option>
|
||||
|
||||
Specify additional config values in the ``section/key=value`` format. Can
|
||||
be provided multiple times.
|
||||
|
||||
|
||||
Files
|
||||
=====
|
||||
|
||||
/etc/mopidy/mopidy.conf
|
||||
System wide Mopidy configuration file.
|
||||
|
||||
~/.config/mopidy/mopidy.conf
|
||||
Your personal Mopidy configuration file. Overrides any configs from the
|
||||
system wide configuration file.
|
||||
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
To start the music server, run::
|
||||
|
||||
mopidy
|
||||
|
||||
To start the server with an additional config file than can override configs
|
||||
set in the default config files, run::
|
||||
|
||||
mopidy --config ./my-config.conf
|
||||
|
||||
To start the server and change a config value directly on the command line,
|
||||
run::
|
||||
|
||||
mopidy --option mpd/enabled=false
|
||||
|
||||
The :option:`--option` flag may be repeated multiple times to change multiple
|
||||
configs::
|
||||
|
||||
mopidy -o mpd/enabled=false -o spotify/bitrate=320
|
||||
|
||||
The :option:`--show-config` output shows the effect of the :option:`--option`
|
||||
flags::
|
||||
|
||||
mopidy -o mpd/enabled=false -o spotify/bitrate=320 --show-config
|
||||
|
||||
|
||||
See also
|
||||
========
|
||||
|
||||
:ref:`mopidy-scan(1) <mopidy-scan-cmd>`, :ref:`mopidy-convert-config(1)
|
||||
<mopidy-convert-config>`
|
||||
|
||||
Reporting bugs
|
||||
==============
|
||||
|
||||
Report bugs to Mopidy's issue tracker at
|
||||
<https://github.com/mopidy/mopidy/issues>
|
||||
323
docs/conf.py
323
docs/conf.py
@ -1,16 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Mopidy documentation build configuration file, created by
|
||||
# sphinx-quickstart on Fri Feb 5 22:19:08 2010.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing
|
||||
# dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
# encoding: utf-8
|
||||
|
||||
"""Mopidy documentation build configuration file"""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
@ -18,6 +8,17 @@ import os
|
||||
import sys
|
||||
|
||||
|
||||
# -- Read The Docs configuration ----------------------------------------------
|
||||
|
||||
RTD_NEW_THEME = True
|
||||
|
||||
|
||||
# -- Workarounds to have autodoc generate API docs ----------------------------
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
|
||||
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__) + '/../'))
|
||||
|
||||
|
||||
class Mock(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
@ -43,7 +44,6 @@ class Mock(object):
|
||||
else:
|
||||
return Mock()
|
||||
|
||||
|
||||
MOCK_MODULES = [
|
||||
'cherrypy',
|
||||
'dbus',
|
||||
@ -68,213 +68,8 @@ MOCK_MODULES = [
|
||||
for mod_name in MOCK_MODULES:
|
||||
sys.modules[mod_name] = Mock()
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
|
||||
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__) + '/../'))
|
||||
|
||||
# When RTD builds the project, it sets the READTHEDOCS environment variable to
|
||||
# the string True.
|
||||
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
||||
|
||||
# Enable Read the Docs' new theme
|
||||
RTD_NEW_THEME = True
|
||||
|
||||
# -- General configuration ----------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.extlinks',
|
||||
'sphinx.ext.graphviz',
|
||||
'sphinx.ext.viewcode',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = 'Mopidy'
|
||||
copyright = '2009-2013, Stein Magnus Jodal and contributors'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
from mopidy.utils.versioning 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 = []
|
||||
|
||||
# List of directories, relative to source directory, that shouldn't be searched
|
||||
# for source files.
|
||||
exclude_trees = ['_build']
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
modindex_common_prefix = ['mopidy.']
|
||||
|
||||
|
||||
# -- Options for HTML output --------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. Major themes that come with
|
||||
# Sphinx are currently 'default' and 'sphinxdoc'.
|
||||
html_theme = 'default'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
html_theme_path = ['_themes']
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
if on_rtd:
|
||||
html_logo = '_static/mopidy.png'
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_use_modindex = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = ''
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'Mopidydoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output -------------------------------------------------
|
||||
|
||||
# The paper size ('letter' or 'a4').
|
||||
#latex_paper_size = 'letter'
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#latex_font_size = '10pt'
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples (source start
|
||||
# file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
(
|
||||
'index',
|
||||
'Mopidy.tex',
|
||||
'Mopidy Documentation',
|
||||
'Stein Magnus Jodal',
|
||||
'manual'
|
||||
),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#latex_preamble = ''
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_use_modindex = True
|
||||
|
||||
|
||||
needs_sphinx = '1.0'
|
||||
|
||||
extlinks = {'issue': ('https://github.com/mopidy/mopidy/issues/%s', '#')}
|
||||
|
||||
# -- Custom Sphinx object types -----------------------------------------------
|
||||
|
||||
def setup(app):
|
||||
from sphinx.ext.autodoc import cut_lines
|
||||
@ -283,3 +78,91 @@ def setup(app):
|
||||
b'confval', 'confval',
|
||||
objname='configuration value',
|
||||
indextemplate='pair: %s; configuration value')
|
||||
|
||||
|
||||
# -- General configuration ----------------------------------------------------
|
||||
|
||||
needs_sphinx = '1.0'
|
||||
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.extlinks',
|
||||
'sphinx.ext.graphviz',
|
||||
'sphinx.ext.viewcode',
|
||||
]
|
||||
|
||||
templates_path = ['_templates']
|
||||
source_suffix = '.rst'
|
||||
master_doc = 'index'
|
||||
|
||||
project = 'Mopidy'
|
||||
copyright = '2009-2013, Stein Magnus Jodal and contributors'
|
||||
|
||||
from mopidy.utils.versioning import get_version
|
||||
release = get_version()
|
||||
version = '.'.join(release.split('.')[:2])
|
||||
|
||||
exclude_trees = ['_build']
|
||||
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
modindex_common_prefix = ['mopidy.']
|
||||
|
||||
|
||||
# -- Options for HTML output --------------------------------------------------
|
||||
|
||||
html_theme = 'default'
|
||||
html_theme_path = ['_themes']
|
||||
html_static_path = ['_static']
|
||||
|
||||
html_use_modindex = True
|
||||
html_use_index = True
|
||||
html_split_index = False
|
||||
html_show_sourcelink = True
|
||||
|
||||
htmlhelp_basename = 'Mopidy'
|
||||
|
||||
|
||||
# -- Options for LaTeX output -------------------------------------------------
|
||||
|
||||
latex_documents = [
|
||||
(
|
||||
'index',
|
||||
'Mopidy.tex',
|
||||
'Mopidy Documentation',
|
||||
'Stein Magnus Jodal and contributors',
|
||||
'manual'
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for manpages output ----------------------------------------------
|
||||
|
||||
man_pages = [
|
||||
(
|
||||
'commands/mopidy',
|
||||
'mopidy',
|
||||
'music server',
|
||||
'',
|
||||
'1'
|
||||
),
|
||||
(
|
||||
'commands/mopidy-scan',
|
||||
'mopidy-scan',
|
||||
'index music for playback with mopidy',
|
||||
'',
|
||||
'1'
|
||||
),
|
||||
(
|
||||
'commands/mopidy-convert-config',
|
||||
'mopidy-convert-config',
|
||||
'migrate config files from mopidy pre-0.14',
|
||||
'',
|
||||
'1'
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for extlink extension --------------------------------------------
|
||||
|
||||
extlinks = {'issue': ('https://github.com/mopidy/mopidy/issues/%s', '#')}
|
||||
|
||||
@ -98,24 +98,118 @@ Creating releases
|
||||
|
||||
#. Update changelog and commit it.
|
||||
|
||||
#. Bump the version number in ``mopidy/__init__.py``. Remember to update the
|
||||
test case in ``tests/version_test.py``.
|
||||
|
||||
#. Merge the release branch (``develop`` in the example) into master::
|
||||
|
||||
git checkout master
|
||||
git merge --no-ff -m "Release v0.2.0" develop
|
||||
git merge --no-ff -m "Release v0.16.0" develop
|
||||
|
||||
#. Build package and test it manually in a new virtualenv. The following
|
||||
assumes the use of virtualenvwrapper::
|
||||
|
||||
python setup.py sdist
|
||||
mktmpenv
|
||||
pip install path/to/dist/Mopidy-0.16.0.tar.gz
|
||||
toggleglobalsitepackages
|
||||
|
||||
Then test Mopidy manually to confirm that the package is working correctly.
|
||||
|
||||
#. Tag the release::
|
||||
|
||||
git tag -a -m "Release v0.2.0" v0.2.0
|
||||
git tag -a -m "Release v0.16.0" v0.16.0
|
||||
|
||||
#. Push to GitHub::
|
||||
|
||||
git push
|
||||
git push --tags
|
||||
|
||||
#. Build package and upload to PyPI::
|
||||
#. Build source package and upload to PyPI::
|
||||
|
||||
python setup.py sdist upload
|
||||
|
||||
#. Build wheel package and upload to PyPI::
|
||||
|
||||
pip install -U wheel
|
||||
python setup.py bdist_wheel upload
|
||||
|
||||
#. Merge ``master`` back into ``develop`` and push the branch to GitHub.
|
||||
|
||||
#. Make sure the new tag is built by Read the Docs, and that the ``latest``
|
||||
version shows the newly released version.
|
||||
|
||||
#. Spread the word through the topic on #mopidy on IRC, @mopidy on Twitter, and
|
||||
on the mailing list.
|
||||
|
||||
#. Update the Debian package.
|
||||
|
||||
#. Spread the word.
|
||||
|
||||
Updating Debian packages
|
||||
========================
|
||||
|
||||
This howto is not intended to learn you all the details, just to give someone
|
||||
already familiar with Debian packaging an overview of how Mopidy's Debian
|
||||
packages is maintained.
|
||||
|
||||
#. Install the basic packaging tools::
|
||||
|
||||
sudo apt-get install build-essential git-buildpackage
|
||||
|
||||
#. Check out the ``debian`` branch of the repo::
|
||||
|
||||
git checkout -t origin/debian
|
||||
git pull
|
||||
|
||||
#. Merge the latest release tag into the ``debian`` branch::
|
||||
|
||||
git merge v0.16.0
|
||||
|
||||
#. Update the ``debian/changelog`` with a "New upstream release" entry::
|
||||
|
||||
dch -v 0.16.0-0mopidy1
|
||||
git add debian/changelog
|
||||
git commit -m "debian: New upstream release"
|
||||
|
||||
#. Check if any dependencies in ``debian/control`` or similar needs updating.
|
||||
|
||||
#. Install any Build-Deps listed in ``debian/control``.
|
||||
|
||||
#. Build the package and fix any issues repeatedly until the build succeeds and
|
||||
the Lintian check at the end of the build is satisfactory::
|
||||
|
||||
git buildpackage -uc -us
|
||||
|
||||
#. Install and test newly built package::
|
||||
|
||||
sudo debi
|
||||
|
||||
#. If everything is OK, build the package a final time to tag the package
|
||||
version::
|
||||
|
||||
git buildpackage -uc -us --git-tag
|
||||
|
||||
#. Push the changes you've done to the ``debian`` branch and the new tag::
|
||||
|
||||
git push
|
||||
git push --tags
|
||||
|
||||
#. If you're building for multiple architectures, checkout the ``debian``
|
||||
branch on the other builders and run::
|
||||
|
||||
git buildpackage -uc -us
|
||||
|
||||
#. Copy files to the APT server. Make sure to select the correct part of the
|
||||
repo, e.g. main, contrib, or non-free::
|
||||
|
||||
scp ../mopidy*_0.16* bonobo.mopidy.com:/srv/apt.mopidy.com/app/incoming/stable/main
|
||||
|
||||
#. Update the APT repo::
|
||||
|
||||
ssh bonobo.mopidy.com
|
||||
/srv/apt.mopidy.com/app/update.sh
|
||||
|
||||
#. Test installation from apt.mopidy.com::
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get dist-upgrade
|
||||
|
||||
@ -48,7 +48,6 @@ About
|
||||
:maxdepth: 1
|
||||
|
||||
authors
|
||||
license
|
||||
changelog
|
||||
versioning
|
||||
|
||||
@ -72,6 +71,7 @@ Reference
|
||||
:maxdepth: 2
|
||||
|
||||
glossary
|
||||
commands/index
|
||||
api/index
|
||||
modules/index
|
||||
|
||||
|
||||
@ -71,25 +71,22 @@ it out.
|
||||
Arch Linux: Install from AUR
|
||||
============================
|
||||
|
||||
If you are running Arch Linux, you can install the latest release of Mopidy
|
||||
using the `mopidy-git <https://aur.archlinux.org/packages/mopidy-git/>`_
|
||||
package found in AUR. The package installs from the ``master`` branch of the
|
||||
Mopidy Git repo, which always corresponds to the latest release.
|
||||
If you are running Arch Linux, you can install Mopidy
|
||||
using the `mopidy <https://aur.archlinux.org/packages/mopidy/>`_
|
||||
package found in AUR.
|
||||
|
||||
#. To install Mopidy with GStreamer, libspotify and pyspotify, you can use
|
||||
``packer``, ``yaourt``, or do it by hand like this::
|
||||
#. To install Mopidy with all dependencies, you can use
|
||||
for example `yaourt <https://wiki.archlinux.org/index.php/yaourt>`_::
|
||||
|
||||
wget http://aur.archlinux.org/packages/mopidy-git/mopidy-git.tar.gz
|
||||
tar xf mopidy-git.tar.gz
|
||||
cd mopidy-git/
|
||||
makepkg -si
|
||||
yaourt -S mopidy
|
||||
|
||||
To upgrade Mopidy to future releases, just rerun ``makepkg``.
|
||||
To upgrade Mopidy to future releases, just upgrade your system using::
|
||||
|
||||
#. Optional: If you want to scrobble your played tracks to Last.fm, you need to
|
||||
install `python2-pylast`::
|
||||
yaourt -Syu
|
||||
|
||||
sudo pacman -S python2-pylast
|
||||
#. Optional: If you want to use any Mopidy extensions, like Spotify support or
|
||||
Last.fm scrobbling, AUR also got `packages for several Mopidy extensions
|
||||
<https://aur.archlinux.org/packages/?K=mopidy>`_.
|
||||
|
||||
#. Finally, you need to set a couple of :doc:`config values </config>`, and
|
||||
then you're ready to :doc:`run Mopidy </running>`.
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
*******
|
||||
License
|
||||
*******
|
||||
|
||||
Mopidy is copyright 2009-2013 Stein Magnus Jodal and contributors. For a list
|
||||
of contributors, see :doc:`authors`. For details on who have contributed what,
|
||||
please refer to our git repository.
|
||||
|
||||
Mopidy is licensed under the `Apache License, Version 2.0
|
||||
<http://www.apache.org/licenses/LICENSE-2.0>`_.
|
||||
128
docs/running.rst
128
docs/running.rst
@ -6,10 +6,17 @@ To start Mopidy, simply open a terminal and run::
|
||||
|
||||
mopidy
|
||||
|
||||
For a complete reference to the Mopidy commands and their command line options,
|
||||
see :ref:`mopidy-cmd` and :ref:`mopidy-scan-cmd`.
|
||||
|
||||
When Mopidy says ``MPD server running at [127.0.0.1]:6600`` it's ready to
|
||||
accept connections by any MPD client. Check out our non-exhaustive
|
||||
:doc:`/clients/mpd` list to find recommended clients.
|
||||
|
||||
|
||||
Stopping Mopidy
|
||||
===============
|
||||
|
||||
To stop Mopidy, press ``CTRL+C`` in the terminal where you started Mopidy.
|
||||
|
||||
Mopidy will also shut down properly if you send it the TERM signal, e.g. by
|
||||
@ -18,124 +25,3 @@ using ``kill``::
|
||||
kill `ps ax | grep mopidy | grep -v grep | cut -d' ' -f1`
|
||||
|
||||
This can be useful e.g. if you create init script for managing Mopidy.
|
||||
|
||||
|
||||
mopidy command
|
||||
==============
|
||||
|
||||
.. program:: mopidy
|
||||
|
||||
.. cmdoption:: --version
|
||||
|
||||
Show Mopidy's version number and exit.
|
||||
|
||||
.. cmdoption:: -h, --help
|
||||
|
||||
Show help message and exit.
|
||||
|
||||
.. cmdoption:: -q, --quiet
|
||||
|
||||
Show less output: warning level and higher.
|
||||
|
||||
.. cmdoption:: -v, --verbose
|
||||
|
||||
Show more output: debug level and higher.
|
||||
|
||||
.. cmdoption:: --save-debug-log
|
||||
|
||||
Save debug log to the file specified in the :confval:`logging/debug_file`
|
||||
config value, typically ``./mopidy.conf``.
|
||||
|
||||
.. cmdoption:: --show-config
|
||||
|
||||
Show the current effective config. All configuration sources are merged
|
||||
together to show the effective document. Secret values like passwords are
|
||||
masked out. Config for disabled extensions are not included.
|
||||
|
||||
.. cmdoption:: --show-deps
|
||||
|
||||
Show dependencies, their versions and installation location.
|
||||
|
||||
.. cmdoption:: --config <file>
|
||||
|
||||
Specify config file to use. To use multiple config files, separate them
|
||||
with colon. The later files override the earlier ones if there's a
|
||||
conflict.
|
||||
|
||||
.. cmdoption:: -o <option>, --option <option>
|
||||
|
||||
Specify additional config values in the ``section/key=value`` format. Can
|
||||
be provided multiple times.
|
||||
|
||||
|
||||
|
||||
mopidy-scan command
|
||||
===================
|
||||
|
||||
.. program:: mopidy-scan
|
||||
|
||||
.. cmdoption:: --version
|
||||
|
||||
Show Mopidy's version number and exit.
|
||||
|
||||
.. cmdoption:: -h, --help
|
||||
|
||||
Show help message and exit.
|
||||
|
||||
.. cmdoption:: -q, --quiet
|
||||
|
||||
Show less output: warning level and higher.
|
||||
|
||||
.. cmdoption:: -v, --verbose
|
||||
|
||||
Show more output: debug level and higher.
|
||||
|
||||
|
||||
.. _mopidy-convert-config:
|
||||
|
||||
mopidy-convert-config command
|
||||
=============================
|
||||
|
||||
.. program:: mopidy-convert-config
|
||||
|
||||
This program does not take any options. It looks for the pre-0.14 settings file
|
||||
at ``$XDG_CONFIG_DIR/mopidy/settings.py``, and if it exists it converts it and
|
||||
ouputs a Mopidy 0.14 compatible ini-format configuration. If you don't already
|
||||
have a config file at ``$XDG_CONFIG_DIR/mopidy/mopidy.conf``, you're asked if
|
||||
you want to save the converted config to that file.
|
||||
|
||||
Example usage::
|
||||
|
||||
$ cat ~/.config/mopidy/settings.py
|
||||
LOCAL_MUSIC_PATH = u'~/music'
|
||||
MPD_SERVER_HOSTNAME = u'::'
|
||||
SPOTIFY_PASSWORD = u'secret'
|
||||
SPOTIFY_USERNAME = u'alice'
|
||||
|
||||
$ mopidy-convert-config
|
||||
Checking /home/alice/.config/mopidy/settings.py
|
||||
Converted config:
|
||||
|
||||
[spotify]
|
||||
username = alice
|
||||
password = ********
|
||||
|
||||
[mpd]
|
||||
hostname = ::
|
||||
|
||||
[local]
|
||||
media_dir = ~/music
|
||||
|
||||
Write new config to /home/alice/.config/mopidy/mopidy.conf? [yN] y
|
||||
Done.
|
||||
|
||||
$ cat ~/.config/mopidy/mopidy.conf
|
||||
[spotify]
|
||||
username = alice
|
||||
password = secret
|
||||
|
||||
[mpd]
|
||||
hostname = ::
|
||||
|
||||
[local]
|
||||
media_dir = ~/music
|
||||
|
||||
@ -21,4 +21,4 @@ if (isinstance(pykka.__version__, basestring)
|
||||
warnings.filterwarnings('ignore', 'could not open display')
|
||||
|
||||
|
||||
__version__ = '0.16.0'
|
||||
__version__ = '0.16.1'
|
||||
|
||||
@ -21,6 +21,12 @@ class LocalLibraryProvider(base.BaseLibraryProvider):
|
||||
self._tag_cache_file = self.backend.config['local']['tag_cache_file']
|
||||
self.refresh()
|
||||
|
||||
def _convert_to_int(self, string):
|
||||
try:
|
||||
return int(string)
|
||||
except ValueError:
|
||||
return object()
|
||||
|
||||
def refresh(self, uri=None):
|
||||
logger.debug(
|
||||
'Loading local tracks from %s using %s',
|
||||
@ -61,7 +67,7 @@ class LocalLibraryProvider(base.BaseLibraryProvider):
|
||||
# FIXME this is bound to be slow for large libraries
|
||||
for value in values:
|
||||
if field == 'track_no':
|
||||
q = value
|
||||
q = self._convert_to_int(value)
|
||||
else:
|
||||
q = value.strip()
|
||||
|
||||
@ -81,7 +87,6 @@ class LocalLibraryProvider(base.BaseLibraryProvider):
|
||||
album_filter(t) or
|
||||
artist_filter(t) or
|
||||
albumartist_filter(t) or
|
||||
track_no_filter(t) or
|
||||
date_filter(t))
|
||||
|
||||
if field == 'uri':
|
||||
@ -119,7 +124,7 @@ class LocalLibraryProvider(base.BaseLibraryProvider):
|
||||
# FIXME this is bound to be slow for large libraries
|
||||
for value in values:
|
||||
if field == 'track_no':
|
||||
q = value
|
||||
q = self._convert_to_int(value)
|
||||
else:
|
||||
q = value.strip().lower()
|
||||
|
||||
@ -140,7 +145,6 @@ class LocalLibraryProvider(base.BaseLibraryProvider):
|
||||
album_filter(t) or
|
||||
artist_filter(t) or
|
||||
albumartist_filter(t) or
|
||||
track_no_filter(t) or
|
||||
date_filter(t))
|
||||
|
||||
if field == 'uri':
|
||||
|
||||
@ -163,7 +163,7 @@ def validate_extension(extension):
|
||||
def register_gstreamer_elements(enabled_extensions):
|
||||
"""Registers custom GStreamer elements from extensions.
|
||||
|
||||
:params enabled_extensions: list of enabled extensions
|
||||
:param enabled_extensions: list of enabled extensions
|
||||
"""
|
||||
|
||||
for extension in enabled_extensions:
|
||||
|
||||
@ -127,8 +127,8 @@ def findadd(context, mpd_query):
|
||||
|
||||
|
||||
@handle_request(
|
||||
r'^list "?(?P<field>([Aa]rtist|[Aa]lbum|[Dd]ate|[Gg]enre))"?'
|
||||
r'( (?P<mpd_query>.*))?$')
|
||||
r'^list "?(?P<field>([Aa]rtist|[Aa]lbumartist|[Aa]lbum|[Dd]ate|'
|
||||
r'[Gg]enre))"?( (?P<mpd_query>.*))?$')
|
||||
def list_(context, field, mpd_query=None):
|
||||
"""
|
||||
*musicpd.org, music database section:*
|
||||
@ -136,7 +136,7 @@ def list_(context, field, mpd_query=None):
|
||||
``list {TYPE} [ARTIST]``
|
||||
|
||||
Lists all tags of the specified type. ``TYPE`` should be ``album``,
|
||||
``artist``, ``date``, or ``genre``.
|
||||
``artist``, ``albumartist``, ``date``, or ``genre``.
|
||||
|
||||
``ARTIST`` is an optional parameter when type is ``album``,
|
||||
``date``, or ``genre``. This filters the result list by an artist.
|
||||
@ -218,6 +218,8 @@ def list_(context, field, mpd_query=None):
|
||||
return
|
||||
if field == 'artist':
|
||||
return _list_artist(context, query)
|
||||
if field == 'albumartist':
|
||||
return _list_albumartist(context, query)
|
||||
elif field == 'album':
|
||||
return _list_album(context, query)
|
||||
elif field == 'date':
|
||||
@ -236,6 +238,17 @@ def _list_artist(context, query):
|
||||
return artists
|
||||
|
||||
|
||||
def _list_albumartist(context, query):
|
||||
albumartists = set()
|
||||
results = context.core.library.find_exact(**query).get()
|
||||
for track in _get_tracks(results):
|
||||
if track.album:
|
||||
for artist in track.album.artists:
|
||||
if artist.name:
|
||||
albumartists.add(('AlbumArtist', artist.name))
|
||||
return albumartists
|
||||
|
||||
|
||||
def _list_album(context, query):
|
||||
albums = set()
|
||||
results = context.core.library.find_exact(**query).get()
|
||||
|
||||
@ -41,7 +41,7 @@ def _format_dependency(dep_info):
|
||||
lines.append('%s: not found' % dep_info['name'])
|
||||
else:
|
||||
if 'path' in dep_info:
|
||||
source = ' from %s' % os.path.dirname(dep_info['path'])
|
||||
source = ' from %s' % dep_info['path']
|
||||
else:
|
||||
source = ''
|
||||
lines.append('%s: %s%s' % (
|
||||
@ -75,7 +75,7 @@ def python_info():
|
||||
'name': 'Python',
|
||||
'version': '%s %s' % (
|
||||
platform.python_implementation(), platform.python_version()),
|
||||
'path': platform.__file__,
|
||||
'path': os.path.dirname(platform.__file__),
|
||||
}
|
||||
|
||||
|
||||
@ -127,7 +127,7 @@ def gstreamer_info():
|
||||
return {
|
||||
'name': 'GStreamer',
|
||||
'version': '.'.join(map(str, gst.get_gst_version())),
|
||||
'path': gst.__file__,
|
||||
'path': os.path.dirname(gst.__file__),
|
||||
'other': '\n'.join(other),
|
||||
}
|
||||
|
||||
|
||||
@ -108,13 +108,19 @@ class LocalLibraryProviderTest(unittest.TestCase):
|
||||
result = self.library.find_exact(artist=['unknown artist'])
|
||||
self.assertEqual(list(result[0].tracks), [])
|
||||
|
||||
result = self.library.find_exact(albumartist=['unknown albumartist'])
|
||||
self.assertEqual(list(result[0].tracks), [])
|
||||
|
||||
result = self.library.find_exact(album=['unknown artist'])
|
||||
self.assertEqual(list(result[0].tracks), [])
|
||||
|
||||
result = self.library.find_exact(date=['1990'])
|
||||
self.assertEqual(list(result[0].tracks), [])
|
||||
|
||||
result = self.library.find_exact(track_no=[9])
|
||||
result = self.library.find_exact(track_no=['9'])
|
||||
self.assertEqual(list(result[0].tracks), [])
|
||||
|
||||
result = self.library.find_exact(track_no=['no_match'])
|
||||
self.assertEqual(list(result[0].tracks), [])
|
||||
|
||||
result = self.library.find_exact(uri=['fake uri'])
|
||||
@ -167,10 +173,10 @@ class LocalLibraryProviderTest(unittest.TestCase):
|
||||
self.assertEqual(list(result[0].tracks), [self.tracks[2]])
|
||||
|
||||
def test_find_exact_track_no(self):
|
||||
result = self.library.find_exact(track_no=[1])
|
||||
result = self.library.find_exact(track_no=['1'])
|
||||
self.assertEqual(list(result[0].tracks), self.tracks[:1])
|
||||
|
||||
result = self.library.find_exact(track_no=[2])
|
||||
result = self.library.find_exact(track_no=['2'])
|
||||
self.assertEqual(list(result[0].tracks), self.tracks[1:2])
|
||||
|
||||
def test_find_exact_date(self):
|
||||
@ -222,13 +228,16 @@ class LocalLibraryProviderTest(unittest.TestCase):
|
||||
test = lambda: self.library.find_exact(artist=[''])
|
||||
self.assertRaises(LookupError, test)
|
||||
|
||||
test = lambda: self.library.find_exact(albumartist=[''])
|
||||
self.assertRaises(LookupError, test)
|
||||
|
||||
test = lambda: self.library.find_exact(track=[''])
|
||||
self.assertRaises(LookupError, test)
|
||||
|
||||
test = lambda: self.library.find_exact(album=[''])
|
||||
self.assertRaises(LookupError, test)
|
||||
|
||||
test = lambda: self.library.find_exact(track_no=[])
|
||||
test = lambda: self.library.find_exact(track_no=[''])
|
||||
self.assertRaises(LookupError, test)
|
||||
|
||||
test = lambda: self.library.find_exact(date=[''])
|
||||
@ -244,10 +253,16 @@ class LocalLibraryProviderTest(unittest.TestCase):
|
||||
result = self.library.search(artist=['unknown artist'])
|
||||
self.assertEqual(list(result[0].tracks), [])
|
||||
|
||||
result = self.library.search(albumartist=['unknown albumartist'])
|
||||
self.assertEqual(list(result[0].tracks), [])
|
||||
|
||||
result = self.library.search(album=['unknown artist'])
|
||||
self.assertEqual(list(result[0].tracks), [])
|
||||
|
||||
result = self.library.search(track_no=[9])
|
||||
result = self.library.search(track_no=['9'])
|
||||
self.assertEqual(list(result[0].tracks), [])
|
||||
|
||||
result = self.library.search(track_no=['no_match'])
|
||||
self.assertEqual(list(result[0].tracks), [])
|
||||
|
||||
result = self.library.search(date=['unknown date'])
|
||||
@ -314,10 +329,10 @@ class LocalLibraryProviderTest(unittest.TestCase):
|
||||
self.assertEqual(list(result[0].tracks), self.tracks[1:2])
|
||||
|
||||
def test_search_track_no(self):
|
||||
result = self.library.search(track_no=[1])
|
||||
result = self.library.search(track_no=['1'])
|
||||
self.assertEqual(list(result[0].tracks), self.tracks[:1])
|
||||
|
||||
result = self.library.search(track_no=[2])
|
||||
result = self.library.search(track_no=['2'])
|
||||
self.assertEqual(list(result[0].tracks), self.tracks[1:2])
|
||||
|
||||
def test_search_any(self):
|
||||
@ -352,6 +367,9 @@ class LocalLibraryProviderTest(unittest.TestCase):
|
||||
test = lambda: self.library.search(artist=[''])
|
||||
self.assertRaises(LookupError, test)
|
||||
|
||||
test = lambda: self.library.search(albumartist=[''])
|
||||
self.assertRaises(LookupError, test)
|
||||
|
||||
test = lambda: self.library.search(track=[''])
|
||||
self.assertRaises(LookupError, test)
|
||||
|
||||
|
||||
@ -398,6 +398,66 @@ class MusicDatabaseListTest(protocol.BaseTestCase):
|
||||
self.assertNotInResponse('Artist: ')
|
||||
self.assertInResponse('OK')
|
||||
|
||||
### Albumartist
|
||||
|
||||
def test_list_albumartist_with_quotes(self):
|
||||
self.sendRequest('list "albumartist"')
|
||||
self.assertInResponse('OK')
|
||||
|
||||
def test_list_albumartist_without_quotes(self):
|
||||
self.sendRequest('list albumartist')
|
||||
self.assertInResponse('OK')
|
||||
|
||||
def test_list_albumartist_without_quotes_and_capitalized(self):
|
||||
self.sendRequest('list Albumartist')
|
||||
self.assertInResponse('OK')
|
||||
|
||||
def test_list_albumartist_with_query_of_one_token(self):
|
||||
self.sendRequest('list "albumartist" "anartist"')
|
||||
self.assertEqualResponse(
|
||||
'ACK [2@0] {list} should be "Album" for 3 arguments')
|
||||
|
||||
def test_list_albumartist_with_unknown_field_in_query_returns_ack(self):
|
||||
self.sendRequest('list "albumartist" "foo" "bar"')
|
||||
self.assertEqualResponse('ACK [2@0] {list} not able to parse args')
|
||||
|
||||
def test_list_albumartist_by_artist(self):
|
||||
self.sendRequest('list "albumartist" "artist" "anartist"')
|
||||
self.assertInResponse('OK')
|
||||
|
||||
def test_list_albumartist_by_album(self):
|
||||
self.sendRequest('list "albumartist" "album" "analbum"')
|
||||
self.assertInResponse('OK')
|
||||
|
||||
def test_list_albumartist_by_full_date(self):
|
||||
self.sendRequest('list "albumartist" "date" "2001-01-01"')
|
||||
self.assertInResponse('OK')
|
||||
|
||||
def test_list_albumartist_by_year(self):
|
||||
self.sendRequest('list "albumartist" "date" "2001"')
|
||||
self.assertInResponse('OK')
|
||||
|
||||
def test_list_albumartist_by_genre(self):
|
||||
self.sendRequest('list "albumartist" "genre" "agenre"')
|
||||
self.assertInResponse('OK')
|
||||
|
||||
def test_list_albumartist_by_artist_and_album(self):
|
||||
self.sendRequest(
|
||||
'list "albumartist" "artist" "anartist" "album" "analbum"')
|
||||
self.assertInResponse('OK')
|
||||
|
||||
def test_list_albumartist_without_filter_value(self):
|
||||
self.sendRequest('list "albumartist" "artist" ""')
|
||||
self.assertInResponse('OK')
|
||||
|
||||
def test_list_albumartist_should_not_return_artists_without_names(self):
|
||||
self.backend.library.dummy_find_exact_result = SearchResult(
|
||||
tracks=[Track(album=Album(artists=[Artist(name='')]))])
|
||||
|
||||
self.sendRequest('list "albumartist"')
|
||||
self.assertNotInResponse('Artist: ')
|
||||
self.assertInResponse('OK')
|
||||
|
||||
### Album
|
||||
|
||||
def test_list_album_with_quotes(self):
|
||||
|
||||
@ -20,7 +20,7 @@ class DepsTest(unittest.TestCase):
|
||||
lambda: dict(name='Platform', version='Loonix 4.0.1'),
|
||||
lambda: dict(
|
||||
name='Pykka', version='1.1',
|
||||
path='/foo/bar/baz.py', other='Quux'),
|
||||
path='/foo/bar', other='Quux'),
|
||||
lambda: dict(name='Foo'),
|
||||
lambda: dict(name='Mopidy', version='0.13', dependencies=[
|
||||
dict(name='pylast', version='0.5', dependencies=[
|
||||
@ -58,6 +58,7 @@ class DepsTest(unittest.TestCase):
|
||||
self.assertIn(platform.python_implementation(), result['version'])
|
||||
self.assertIn(platform.python_version(), result['version'])
|
||||
self.assertIn('python', result['path'])
|
||||
self.assertNotIn('platform.py', result['path'])
|
||||
|
||||
def test_gstreamer_info(self):
|
||||
result = deps.gstreamer_info()
|
||||
@ -66,6 +67,7 @@ class DepsTest(unittest.TestCase):
|
||||
self.assertEquals(
|
||||
'.'.join(map(str, gst.get_gst_version())), result['version'])
|
||||
self.assertIn('gst', result['path'])
|
||||
self.assertNotIn('__init__.py', result['path'])
|
||||
self.assertIn('Python wrapper: gst-python', result['other'])
|
||||
self.assertIn(
|
||||
'.'.join(map(str, gst.get_pygst_version())), result['other'])
|
||||
|
||||
@ -40,5 +40,6 @@ class VersionTest(unittest.TestCase):
|
||||
self.assertLess(SV('0.14.0'), SV('0.14.1'))
|
||||
self.assertLess(SV('0.14.1'), SV('0.14.2'))
|
||||
self.assertLess(SV('0.14.2'), SV('0.15.0'))
|
||||
self.assertLess(SV('0.15.0'), SV(__version__))
|
||||
self.assertLess(SV(__version__), SV('0.16.1'))
|
||||
self.assertLess(SV('0.15.0'), SV('0.16.0'))
|
||||
self.assertLess(SV('0.16.0'), SV(__version__))
|
||||
self.assertLess(SV(__version__), SV('0.17.1'))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user