Merge pull request #1115 from jodal/feature/no-global-sitepackages
Enable testing of backends with global site-packages disabled
This commit is contained in:
commit
0598a4e943
@ -25,6 +25,12 @@ Internal changes
|
||||
- Tests have been cleaned up to stop using deprecated APIs where feasible.
|
||||
(Partial fix: :issue:`1083`, PR: :issue:`1090`)
|
||||
|
||||
- It is now possible to import :mod:`mopidy.backends` without having GObject or
|
||||
GStreamer installed. In other words, a lot of backend extensions should now
|
||||
be able to run tests in a virtualenv with global site-packages disabled. This
|
||||
removes a lot of potential error sources. (Fixes: :issue:`1068`, PR:
|
||||
:issue:`1115`)
|
||||
|
||||
|
||||
v1.0.1 (UNRELEASED)
|
||||
===================
|
||||
|
||||
@ -2,7 +2,6 @@ from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
import platform
|
||||
import sys
|
||||
import textwrap
|
||||
import warnings
|
||||
|
||||
|
||||
@ -11,21 +10,6 @@ if not (2, 7) <= sys.version_info < (3,):
|
||||
'ERROR: Mopidy requires Python 2.7, but found %s.' %
|
||||
platform.python_version())
|
||||
|
||||
try:
|
||||
import gobject # noqa
|
||||
except ImportError:
|
||||
print(textwrap.dedent("""
|
||||
ERROR: The gobject Python package was not found.
|
||||
|
||||
Mopidy requires GStreamer (and GObject) to work. These are C libraries
|
||||
with a number of dependencies themselves, and cannot be installed with
|
||||
the regular Python tools like pip.
|
||||
|
||||
Please see http://docs.mopidy.com/en/latest/installation/ for
|
||||
instructions on how to install the required dependencies.
|
||||
"""))
|
||||
raise
|
||||
|
||||
|
||||
warnings.filterwarnings('ignore', 'could not open display')
|
||||
|
||||
|
||||
@ -4,8 +4,23 @@ import logging
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
import textwrap
|
||||
|
||||
try:
|
||||
import gobject # noqa
|
||||
except ImportError:
|
||||
print(textwrap.dedent("""
|
||||
ERROR: The gobject Python package was not found.
|
||||
|
||||
Mopidy requires GStreamer (and GObject) to work. These are C libraries
|
||||
with a number of dependencies themselves, and cannot be installed with
|
||||
the regular Python tools like pip.
|
||||
|
||||
Please see http://docs.mopidy.com/en/latest/installation/ for
|
||||
instructions on how to install the required dependencies.
|
||||
"""))
|
||||
raise
|
||||
|
||||
import gobject
|
||||
gobject.threads_init()
|
||||
|
||||
try:
|
||||
|
||||
@ -2,14 +2,18 @@ from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import logging
|
||||
|
||||
import gobject
|
||||
|
||||
import pykka
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def send_async(cls, event, **kwargs):
|
||||
# This file is imported by mopidy.backends, which again is imported by all
|
||||
# backend extensions. By importing modules that are not easily installable
|
||||
# close to their use, we make some extensions able to run their tests in a
|
||||
# virtualenv with global site-packages disabled.
|
||||
import gobject
|
||||
|
||||
gobject.idle_add(lambda: send(cls, event, **kwargs))
|
||||
|
||||
|
||||
|
||||
@ -8,25 +8,15 @@ import threading
|
||||
import urllib
|
||||
import urlparse
|
||||
|
||||
import glib
|
||||
|
||||
from mopidy import compat, exceptions
|
||||
from mopidy.compat import queue
|
||||
from mopidy.utils import encoding
|
||||
from mopidy.utils import encoding, xdg
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
XDG_DIRS = {
|
||||
'XDG_CACHE_DIR': glib.get_user_cache_dir(),
|
||||
'XDG_CONFIG_DIR': glib.get_user_config_dir(),
|
||||
'XDG_DATA_DIR': glib.get_user_data_dir(),
|
||||
'XDG_MUSIC_DIR': glib.get_user_special_dir(glib.USER_DIRECTORY_MUSIC),
|
||||
}
|
||||
|
||||
# XDG_MUSIC_DIR can be none, so filter out any bad data.
|
||||
XDG_DIRS = dict((k, v) for k, v in XDG_DIRS.items() if v is not None)
|
||||
XDG_DIRS = xdg.get_dirs()
|
||||
|
||||
|
||||
def get_or_create_dir(dir_path):
|
||||
|
||||
66
mopidy/utils/xdg.py
Normal file
66
mopidy/utils/xdg.py
Normal file
@ -0,0 +1,66 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import ConfigParser as configparser
|
||||
import io
|
||||
import os
|
||||
|
||||
|
||||
def get_dirs():
|
||||
"""Returns a dict of all the known XDG Base Directories for the current user.
|
||||
|
||||
The keys ``XDG_CACHE_DIR``, ``XDG_CONFIG_DIR``, and ``XDG_DATA_DIR`` is
|
||||
always available.
|
||||
|
||||
Additional keys, like ``XDG_MUSIC_DIR``, may be available if the
|
||||
``$XDG_CONFIG_DIR/user-dirs.dirs`` file exists and is parseable.
|
||||
|
||||
See http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
for the XDG Base Directory specification.
|
||||
"""
|
||||
|
||||
dirs = {
|
||||
'XDG_CACHE_DIR': (
|
||||
os.environ.get('XDG_CACHE_HOME') or
|
||||
os.path.expanduser(b'~/.cache')),
|
||||
'XDG_CONFIG_DIR': (
|
||||
os.environ.get('XDG_CONFIG_HOME') or
|
||||
os.path.expanduser(b'~/.config')),
|
||||
'XDG_DATA_DIR': (
|
||||
os.environ.get('XDG_DATA_HOME') or
|
||||
os.path.expanduser(b'~/.local/share')),
|
||||
}
|
||||
|
||||
dirs.update(_get_user_dirs(dirs['XDG_CONFIG_DIR']))
|
||||
|
||||
return dirs
|
||||
|
||||
|
||||
def _get_user_dirs(xdg_config_dir):
|
||||
"""Returns a dict of XDG dirs read from
|
||||
``$XDG_CONFIG_HOME/user-dirs.dirs``.
|
||||
|
||||
This is used at import time for most users of :mod:`mopidy`. By rolling our
|
||||
own implementation instead of using :meth:`glib.get_user_special_dir` we
|
||||
make it possible for many extensions to run their test suites, which are
|
||||
importing parts of :mod:`mopidy`, in a virtualenv with global site-packages
|
||||
disabled, and thus no :mod:`glib` available.
|
||||
"""
|
||||
|
||||
dirs_file = os.path.join(xdg_config_dir, 'user-dirs.dirs')
|
||||
|
||||
if not os.path.exists(dirs_file):
|
||||
return {}
|
||||
|
||||
with open(dirs_file, 'rb') as fh:
|
||||
data = fh.read()
|
||||
|
||||
data = b'[XDG_USER_DIRS]\n' + data
|
||||
data = data.replace(b'$HOME', os.path.expanduser(b'~'))
|
||||
data = data.replace(b'"', b'')
|
||||
|
||||
config = configparser.RawConfigParser()
|
||||
config.readfp(io.BytesIO(data))
|
||||
|
||||
return {
|
||||
k.decode('utf-8').upper(): os.path.abspath(v)
|
||||
for k, v in config.items('XDG_USER_DIRS') if v is not None}
|
||||
69
tests/utils/test_xdg.py
Normal file
69
tests/utils/test_xdg.py
Normal file
@ -0,0 +1,69 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import os
|
||||
|
||||
import mock
|
||||
|
||||
import pytest
|
||||
|
||||
from mopidy.utils import xdg
|
||||
|
||||
|
||||
@pytest.yield_fixture
|
||||
def environ():
|
||||
patcher = mock.patch.dict(os.environ, clear=True)
|
||||
yield patcher.start()
|
||||
patcher.stop()
|
||||
|
||||
|
||||
def test_cache_dir_default(environ):
|
||||
assert xdg.get_dirs()['XDG_CACHE_DIR'] == os.path.expanduser(b'~/.cache')
|
||||
|
||||
|
||||
def test_cache_dir_from_env(environ):
|
||||
os.environ['XDG_CACHE_HOME'] = '/foo/bar'
|
||||
|
||||
assert xdg.get_dirs()['XDG_CACHE_DIR'] == '/foo/bar'
|
||||
|
||||
|
||||
def test_config_dir_default(environ):
|
||||
assert xdg.get_dirs()['XDG_CONFIG_DIR'] == os.path.expanduser(b'~/.config')
|
||||
|
||||
|
||||
def test_config_dir_from_env(environ):
|
||||
os.environ['XDG_CONFIG_HOME'] = '/foo/bar'
|
||||
|
||||
assert xdg.get_dirs()['XDG_CONFIG_DIR'] == '/foo/bar'
|
||||
|
||||
|
||||
def test_data_dir_default(environ):
|
||||
assert xdg.get_dirs()['XDG_DATA_DIR'] == os.path.expanduser(
|
||||
b'~/.local/share')
|
||||
|
||||
|
||||
def test_data_dir_from_env(environ):
|
||||
os.environ['XDG_DATA_HOME'] = '/foo/bar'
|
||||
|
||||
assert xdg.get_dirs()['XDG_DATA_DIR'] == '/foo/bar'
|
||||
|
||||
|
||||
def test_user_dirs(environ, tmpdir):
|
||||
os.environ['XDG_CONFIG_HOME'] = str(tmpdir)
|
||||
|
||||
with open(os.path.join(str(tmpdir), 'user-dirs.dirs'), 'wb') as fh:
|
||||
fh.write('# Some comments\n')
|
||||
fh.write('XDG_MUSIC_DIR="$HOME/Music2"\n')
|
||||
|
||||
result = xdg.get_dirs()
|
||||
|
||||
assert result['XDG_MUSIC_DIR'] == os.path.expanduser(b'~/Music2')
|
||||
assert 'XDG_DOWNLOAD_DIR' not in result
|
||||
|
||||
|
||||
def test_user_dirs_when_no_dirs_file(environ, tmpdir):
|
||||
os.environ['XDG_CONFIG_HOME'] = str(tmpdir)
|
||||
|
||||
result = xdg.get_dirs()
|
||||
|
||||
assert 'XDG_MUSIC_DIR' not in result
|
||||
assert 'XDG_DOWNLOAD_DIR' not in result
|
||||
Loading…
Reference in New Issue
Block a user