self.use_envar()
self.startopt = options
- ## INIT CALLS
+ # INIT CALLS
self.init_config()
self.supersedes_config_with_cmd_line_options()
# set dbfile
# honor MPD_HOST format as in mpc(1) for command line option --host
if self.startopt.get('host'):
if '@' in self.startopt.get('host'):
- passwd, host = self.startopt.get('host').split('@')
- self.config.set('MPD', 'password', passwd)
- self.config.set('MPD', 'host', host)
+ host, passwd = utils.parse_mpd_host(self.startopt.get('host'))
+ if passwd:
+ self.config.set('MPD', 'password', passwd)
+ if host:
+ self.config.set('MPD', 'host', host)
def use_envar(self):
"""Use MPD en.var. to set defaults"""
from base64 import b64decode as push
from codecs import getencoder
from datetime import datetime
-from os import environ, access, getcwd, W_OK, R_OK
+from os import getenv, access, getcwd, W_OK, R_OK
from os.path import dirname, isabs, join, normpath, exists, isdir, isfile
from time import sleep
aka = getencoder('rot-13')(str((aka), 'utf-8'))[0]
dic.update({'apikey': aka})
+def parse_mpd_host(value):
+ passwd = host = None
+ # If password is set: MPD_HOST=pass@host
+ if '@' in value:
+ mpd_host_env = value.split('@', 1)
+ if mpd_host_env[0]:
+ # A password is actually set
+ passwd = mpd_host_env[0]
+ if mpd_host_env[1]:
+ host = mpd_host_env[1]
+ elif mpd_host_env[1]:
+ # No password set but leading @ is an abstract socket
+ host = '@'+mpd_host_env[1]
+ else:
+ # MPD_HOST is a plain host
+ host = value
+ return host, passwd
+
def get_mpd_environ():
"""
Retrieve MPD env. var.
"""
passwd = host = None
- mpd_host_env = environ.get('MPD_HOST')
- if mpd_host_env:
- # If password is set:
- # mpd_host_env = ['pass', 'host'] because MPD_HOST=pass@host
- mpd_host_env = mpd_host_env.split('@')
- mpd_host_env.reverse()
- host = mpd_host_env[0]
- if len(mpd_host_env) > 1 and mpd_host_env[1]:
- passwd = mpd_host_env[1]
- return (host, environ.get('MPD_PORT', None), passwd)
+ if getenv('MPD_HOST'):
+ host, passwd = parse_mpd_host(getenv('MPD_HOST'))
+ return (host, getenv('MPD_PORT', None), passwd)
def normalize_path(path):
class TestConfMan(unittest.TestCase):
+ """For some tests we don't care about file access check, then to ensure
+ checks are properly mocked run test forcing non existent locations:
+
+ XDG_DATA_HOME=/non/existent/ XDG_HOME_CONFIG=/non/existent/ python3 -m unittest -vf tests/test_config.py
+ """
@patch('sima.utils.config.makedirs')
@patch('sima.utils.config.chmod')
expected_config = os.path.join(home, '.config', DIRNAME, CONF_FILE)
self.assertEqual(constructed_config_location, expected_config)
+ @patch('sima.utils.config.makedirs')
+ @patch('sima.utils.config.chmod')
+ @patch('sima.utils.config.ConfMan.control_facc')
+ def test_MPD_env_var(self, *args):
+ host = 'example.org'
+ passwd = 's2cr34!'
+ port = '6601'
+ os.environ.pop('MPD_HOST', None)
+ os.environ.pop('MPD_PORT', None)
+ # Test defaults
+ conf = ConfMan({})
+ self.assertEqual(dict(conf.config['MPD']),
+ {'host': 'localhost', 'port': '6600'})
+ # Test provided env. var.
+ os.environ['MPD_HOST'] = host
+ conf = ConfMan({})
+ self.assertEqual(dict(conf.config['MPD']),
+ {'host': host, 'port': '6600'})
+ os.environ['MPD_HOST'] = f'{passwd}@{host}'
+ conf = ConfMan({})
+ self.assertEqual(dict(conf.config['MPD']),
+ {'host': host,
+ 'password': passwd,
+ 'port': '6600'})
+ # Test abstract unix socket support with password
+ os.environ['MPD_HOST'] = f'{passwd}@@/{host}'
+ conf = ConfMan({})
+ self.assertEqual(dict(conf.config['MPD']),
+ {'host': f'@/{host}',
+ 'password': passwd,
+ 'port': '6600'})
+ # Test abstract unix socket support only
+ os.environ['MPD_HOST'] = f'@/{host}'
+ conf = ConfMan({})
+ self.assertEqual(dict(conf.config['MPD']),
+ {'host': f'@/{host}',
+ 'port': '6600'})
+ # Test port
+ os.environ['MPD_PORT'] = f'{port}'
+ conf = ConfMan({})
+ self.assertEqual(conf.config['MPD']['port'], port)
+
+ @patch('sima.utils.config.makedirs')
+ @patch('sima.utils.config.chmod')
+ @patch('sima.utils.config.ConfMan.control_facc')
+ def test_config_origin_priority(self, *args):
+ # cli provided host overrides env. var.
+ os.environ['MPD_HOST'] = 'baz.foo'
+ conf = ConfMan({'host': 'cli.host'})
+ self.assertEqual(conf.config['MPD']['host'], 'cli.host')
+ # cli provided abstract socket overrides env. var.
+ conf = ConfMan({'host': '@/abstract'})
+ self.assertEqual(conf.config['MPD']['host'], '@/abstract')
+ # cli provided passord and abstract socket overrides env. var.
+ conf = ConfMan({'host': 'pass!@@/abstract'})
+ self.assertEqual(conf.config['MPD']['host'], '@/abstract')
+ self.assertEqual(conf.config['MPD']['password'], 'pass!')
+
# VIM MODLINE
# vim: ai ts=4 sw=4 sts=4 expandtab fileencoding=utf8