]> kaliko git repositories - mpd-sima.git/commitdiff
Add abstract unix socket support for MPD connection
authorkaliko <kaliko@azylum.org>
Wed, 5 May 2021 16:30:45 +0000 (18:30 +0200)
committerkaliko <kaliko@azylum.org>
Fri, 7 May 2021 16:27:31 +0000 (18:27 +0200)
Add unittests for env var parsing

doc/Changelog
sima/utils/config.py
sima/utils/utils.py
tests/test_config.py

index c487b0ef66422f091ce90abcccc5bdabefd7b1c7..0e390f1297a603c6ea3a9149294a3ff0c9a6b5b8 100644 (file)
@@ -2,6 +2,7 @@ MPD_sima v0.18.0.dev0
 
  * Removed obsolete --create-db and --generate-config options
  * Fixed crash when setting XDG_CONFIG_HOME (closes #50)
 
  * Removed obsolete --create-db and --generate-config options
  * Fixed crash when setting XDG_CONFIG_HOME (closes #50)
+ * Add abstract unix socket support for MPD connection
 
  -- kaliko <kaliko@azylum.org>  Wed, 28 Apr 2021 17:21:39 +0200
 
 
  -- kaliko <kaliko@azylum.org>  Wed, 28 Apr 2021 17:21:39 +0200
 
index 854d6df9cb36adc8213354b1e3b0386a4d45fc80..a46c0c66493e3519ab1af41cefe7d88e8087ddbf 100644 (file)
@@ -139,7 +139,7 @@ class ConfMan:  # CONFIG MANAGER CLASS
         self.use_envar()
         self.startopt = options
 
         self.use_envar()
         self.startopt = options
 
-        ## INIT CALLS
+        # INIT CALLS
         self.init_config()
         self.supersedes_config_with_cmd_line_options()
         # set dbfile
         self.init_config()
         self.supersedes_config_with_cmd_line_options()
         # set dbfile
@@ -204,9 +204,11 @@ class ConfMan:  # CONFIG MANAGER CLASS
         # honor MPD_HOST format as in mpc(1)  for command line option --host
         if self.startopt.get('host'):
             if '@' in self.startopt.get('host'):
         # 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"""
 
     def use_envar(self):
         """Use MPD en.var. to set defaults"""
index 8e07e7ae965e5f7342b5425a3094a46f61730bc3..b9dc980c37f5a109b207e133b660df4bb26517df 100644 (file)
@@ -30,7 +30,7 @@ from argparse import ArgumentError, Action
 from base64 import b64decode as push
 from codecs import getencoder
 from datetime import datetime
 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
 
 from os.path import dirname, isabs, join, normpath, exists, isdir, isfile
 from time import sleep
 
@@ -45,22 +45,33 @@ def getws(dic):
     aka = getencoder('rot-13')(str((aka), 'utf-8'))[0]
     dic.update({'apikey': aka})
 
     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
 
 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):
 
 
 def normalize_path(path):
index 36ba2accf0bf9d5da101acfd1cb6b40f439720fe..eee93bd8a06c58f3e14bab31009ac6b2e0d5b110 100644 (file)
@@ -12,6 +12,11 @@ from sima.lib.logger import set_logger
 
 
 class TestConfMan(unittest.TestCase):
 
 
 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')
 
     @patch('sima.utils.config.makedirs')
     @patch('sima.utils.config.chmod')
@@ -46,5 +51,63 @@ class TestConfMan(unittest.TestCase):
         expected_config = os.path.join(home, '.config', DIRNAME, CONF_FILE)
         self.assertEqual(constructed_config_location, expected_config)
 
         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
 # VIM MODLINE
 # vim: ai ts=4 sw=4 sts=4 expandtab fileencoding=utf8