chiark / gitweb /
ensure tests avoid user config!
[disorder] / python / disorder.py.in
index eb5850700fbd45a4889889836db4de64e4fbe9e8..95854383f6768912530fa5280f50d3992973994c 100644 (file)
@@ -53,6 +53,7 @@ import locale
 
 _configfile = "pkgconfdir/config"
 _dbhome = "pkgstatedir"
+_userconf = True
 
 # various regexps we'll use
 _ws = re.compile(r"^[ \t\n\r]+")
@@ -104,15 +105,20 @@ class operationError(Error):
   Indicates that an operation failed (e.g. an attempt to play a
   nonexistent track).  The connection should still be usable.
   """
-  def __init__(self, res, details):
+  def __init__(self, res, details, cmd=None):
     self.res_ = int(res)
+    self.cmd_ = cmd
     self.details_ = details
   def __str__(self):
-    """Return the complete response string from the server.
+    """Return the complete response string from the server, with the command
+    if available.
 
     Excludes the final newline.
     """
-    return "%d %s" % (self.res_, self.details_)
+    if self.cmd_ is None:
+      return "%d %s" % (self.res_, self.details_)
+    else:
+      return "%d %s [%s]" % (self.res_, self.details_, self.cmd_)
   def response(self):
     """Return the response code from the server."""
     return self.res_
@@ -225,7 +231,7 @@ def _list2dict(l):
     while True:
       k = i.next()
       v = i.next()
-      d[k] = v
+      d[str(k)] = v
   except StopIteration:
     pass
   return d
@@ -288,10 +294,11 @@ class client:
       home = pw.pw_dir
     privconf = _configfile + "." + pw.pw_name
     passfile = home + os.sep + ".disorder" + os.sep + "passwd"
-    self._readfile(_configfile)
+    if os.path.exists(_configfile):
+      self._readfile(_configfile)
     if os.path.exists(privconf):
       self._readfile(privconf)
-    if os.path.exists(passfile):
+    if os.path.exists(passfile) and _userconf:
       self._readfile(passfile)
     self.state = 'disconnected'
 
@@ -579,7 +586,10 @@ class client:
     The return value is the preference 
     """
     ret, details = self._simple("get", track, key)
-    return details
+    if ret == 555:
+      return None
+    else:
+      return details
 
   def prefs(self, track):
     """Get all the preferences for a track.
@@ -647,7 +657,15 @@ class client:
     all of the required words (in their path name, trackname
     preferences, etc.)
     """
-    self._simple("search", *words)
+    self._simple("search", _quote(words))
+    return self._body()
+
+  def tags(self):
+    """List all tags
+
+    The return value is a list of all tags which apply to at least one
+    track."""
+    self._simple("tags")
     return self._body()
 
   def stats(self):
@@ -749,6 +767,37 @@ class client:
     ret, details = self._simple("part", track, context, part)
     return details
 
+  def setglobal(self, key, value):
+    """Set a global preference value.
+
+    Arguments:
+    key -- the preference name
+    value -- the new preference value
+    """
+    self._simple("set-global", key, value)
+
+  def unsetglobal(self, key):
+    """Unset a global preference value.
+
+    Arguments:
+    key -- the preference to remove
+    """
+    self._simple("set-global", key, value)
+
+  def getglobal(self, key):
+    """Get a global preference value.
+
+    Arguments:
+    key -- the preference to look up
+
+    The return value is the preference 
+    """
+    ret, details = self._simple("get-global", key)
+    if ret == 555:
+      return None
+    else:
+      return details
+
   ########################################################################
   # I/O infrastructure
 
@@ -779,6 +828,9 @@ class client:
       raise protocolError(self.who, "invalid response %s")
 
   def _send(self, *command):
+    # Quote and send a command
+    #
+    # Returns the encoded command.
     quoted = _quote(command)
     self._debug(client.debug_proto, "==> %s" % quoted)
     encoded = quoted.encode("UTF-8")
@@ -786,6 +838,7 @@ class client:
       self.w.write(encoded)
       self.w.write("\n")
       self.w.flush()
+      return encoded
     except IOError, e:
       # e.g. EPIPE
       self._disconnect()
@@ -799,17 +852,19 @@ class client:
     #
     # If an I/O error occurs, disconnect from the server.
     #
-    # On success returns response as a (code, details) tuple
+    # On success or 'normal' errors returns response as a (code, details) tuple
     #
     # On error raise operationError
     if self.state == 'disconnected':
       self.connect()
     if command:
-      self._send(*command)
+      cmd = self._send(*command)
+    else:
+      cmd = None
     res, details = self._response()
-    if res / 100 == 2:
+    if res / 100 == 2 or res == 555:
       return res, details
-    raise operationError(res, details)
+    raise operationError(res, details, cmd)
 
   def _body(self):
     # Fetch a dot-stuffed body