Throw more informative error classes from perf.
[pdm.git] / pdm / srv.py
index b2c131a..2ddb9e7 100644 (file)
@@ -10,6 +10,7 @@ which describes the functioning of the REPL and PERF protocols.
 import os, sys, socket, threading, grp, select
 import types, pprint, traceback
 import pickle, struct
 import os, sys, socket, threading, grp, select
 import types, pprint, traceback
 import pickle, struct
+from . import perf as mperf
 
 __all__ = ["repl", "perf", "listener", "unixlistener", "tcplistener", "listen"]
 
 
 __all__ = ["repl", "perf", "listener", "unixlistener", "tcplistener", "listen"]
 
@@ -40,35 +41,36 @@ class repl(object):
         self.mod = types.ModuleType("repl")
         self.mod.echo = self.echo
         self.printer = pprint.PrettyPrinter(indent = 4, depth = 6)
         self.mod = types.ModuleType("repl")
         self.mod.echo = self.echo
         self.printer = pprint.PrettyPrinter(indent = 4, depth = 6)
-        cl.send("+REPL\n")
+        cl.send(b"+REPL\n")
 
     def sendlines(self, text):
         for line in text.split("\n"):
 
     def sendlines(self, text):
         for line in text.split("\n"):
-            self.cl.send(" " + line + "\n")
+            self.cl.send(b" " + line.encode("utf-8") + b"\n")
 
     def echo(self, ob):
         self.sendlines(self.printer.pformat(ob))
 
     def command(self, cmd):
 
     def echo(self, ob):
         self.sendlines(self.printer.pformat(ob))
 
     def command(self, cmd):
+        cmd = cmd.decode("utf-8")
         try:
             try:
                 ccode = compile(cmd, "PDM Input", "eval")
             except SyntaxError:
                 ccode = compile(cmd, "PDM Input", "exec")
         try:
             try:
                 ccode = compile(cmd, "PDM Input", "eval")
             except SyntaxError:
                 ccode = compile(cmd, "PDM Input", "exec")
-                exec ccode in self.mod.__dict__
-                self.cl.send("+OK\n")
+                exec(ccode, self.mod.__dict__)
+                self.cl.send(b"+OK\n")
             else:
                 self.echo(eval(ccode, self.mod.__dict__))
             else:
                 self.echo(eval(ccode, self.mod.__dict__))
-                self.cl.send("+OK\n")
+                self.cl.send(b"+OK\n")
         except:
             lines = ("".join(traceback.format_exception(*sys.exc_info()))).split("\n")
             while len(lines) > 0 and lines[-1] == "": lines = lines[:-1]
             for line in lines:
         except:
             lines = ("".join(traceback.format_exception(*sys.exc_info()))).split("\n")
             while len(lines) > 0 and lines[-1] == "": lines = lines[:-1]
             for line in lines:
-                self.cl.send(" " + line + "\n")
-            self.cl.send("+EXC\n")
+                self.cl.send(b" " + line.encode("utf-8") + b"\n")
+            self.cl.send(b"+EXC\n")
 
     def handle(self, buf):
 
     def handle(self, buf):
-        p = buf.find("\n\n")
+        p = buf.find(b"\n\n")
         if p < 0:
             return buf
         cmd = buf[:p + 1]
         if p < 0:
             return buf
         cmd = buf[:p + 1]
@@ -171,13 +173,13 @@ class perf(object):
     def __init__(self, cl):
         self.cl = cl
         self.odtab = {}
     def __init__(self, cl):
         self.cl = cl
         self.odtab = {}
-        cl.send("+PERF1\n")
+        cl.send(b"+PERF1\n")
         self.buf = ""
         self.lock = threading.Lock()
         self.subscribed = {}
 
     def closed(self):
         self.buf = ""
         self.lock = threading.Lock()
         self.subscribed = {}
 
     def closed(self):
-        for id, recv in self.subscribed.iteritems():
+        for id, recv in self.subscribed.items():
             ob = self.odtab[id]
             if ob is None: continue
             ob, protos = ob
             ob = self.odtab[id]
             if ob is None: continue
             ob, protos = ob
@@ -196,10 +198,10 @@ class perf(object):
 
     def bindob(self, id, ob):
         if not hasattr(ob, "pdm_protocols"):
 
     def bindob(self, id, ob):
         if not hasattr(ob, "pdm_protocols"):
-            raise ValueError("Object does not support PDM introspection")
+            raise mperf.nosuchname("Object does not support PDM introspection")
         try:
             proto = ob.pdm_protocols()
         try:
             proto = ob.pdm_protocols()
-        except Exception, exc:
+        except Exception as exc:
             raise ValueError("PDM introspection failed", exc)
         self.odtab[id] = ob, proto
         return proto
             raise ValueError("PDM introspection failed", exc)
         self.odtab[id] = ob, proto
         return proto
@@ -207,16 +209,16 @@ class perf(object):
     def bind(self, id, module, obnm):
         resmod = sys.modules.get(module)
         if resmod is None:
     def bind(self, id, module, obnm):
         resmod = sys.modules.get(module)
         if resmod is None:
-            self.send("-", ImportError("No such module: %s" % module))
+            self.send("-", mperf.nosuchname("No such module: %s" % module))
             return
         try:
             ob = getattr(resmod, obnm)
         except AttributeError:
             return
         try:
             ob = getattr(resmod, obnm)
         except AttributeError:
-            self.send("-", AttributeError("No such object: %s" % obnm))
+            self.send("-", mperf.nosuchname("No such object: %s" % obnm))
             return
         try:
             proto = self.bindob(id, ob)
             return
         try:
             proto = self.bindob(id, ob)
-        except Exception, exc:
+        except Exception as exc:
             self.send("-", exc)
             return
         self.send("+", proto)
             self.send("-", exc)
             return
         self.send("+", proto)
@@ -228,7 +230,7 @@ class perf(object):
             return None
         ob, protos = ob
         if proto not in protos:
             return None
         ob, protos = ob
         if proto not in protos:
-            self.send("-", ValueError("Object does not support that protocol"))
+            self.send("-", mperf.nosuchproto("Object does not support that protocol: " + proto))
             return None
         return ob
 
             return None
         return ob
 
@@ -238,12 +240,12 @@ class perf(object):
             return
         try:
             ob = src.lookup(obnm)
             return
         try:
             ob = src.lookup(obnm)
-        except KeyError, exc:
-            self.send("-", exc)
+        except KeyError as exc:
+            self.send("-", mperf.nosuchname(obnm))
             return
         try:
             proto = self.bindob(tgtid, ob)
             return
         try:
             proto = self.bindob(tgtid, ob)
-        except Exception, exc:
+        except Exception as exc:
             self.send("-", exc)
             return
         self.send("+", proto)
             self.send("-", exc)
             return
         self.send("+", proto)
@@ -273,7 +275,7 @@ class perf(object):
             return
         try:
             ret = ob.readattr()
             return
         try:
             ret = ob.readattr()
-        except Exception, exc:
+        except Exception as exc:
             self.send("-", Exception("Could not read attribute"))
             return
         self.send("+", ret)
             self.send("-", Exception("Could not read attribute"))
             return
         self.send("+", ret)
@@ -290,7 +292,7 @@ class perf(object):
             return
         try:
             self.send("+", ob.invoke(method, *args, **kwargs))
             return
         try:
             self.send("+", ob.invoke(method, *args, **kwargs))
-        except Exception, exc:
+        except Exception as exc:
             self.send("-", exc)
 
     def event(self, id, ob, ev):
             self.send("-", exc)
 
     def event(self, id, ob, ev):
@@ -356,7 +358,7 @@ protocols["perf"] = perf
 
 class client(threading.Thread):
     def __init__(self, sk):
 
 class client(threading.Thread):
     def __init__(self, sk):
-        super(client, self).__init__(name = "Management client")
+        super().__init__(name = "Management client")
         self.setDaemon(True)
         self.sk = sk
         self.handler = self
         self.setDaemon(True)
         self.sk = sk
         self.handler = self
@@ -365,6 +367,10 @@ class client(threading.Thread):
         return self.sk.send(data)
 
     def choose(self, proto):
         return self.sk.send(data)
 
     def choose(self, proto):
+        try:
+            proto = proto.decode("ascii")
+        except UnicodeError:
+            proto = None
         if proto in protocols:
             self.handler = protocols[proto](self)
         else:
         if proto in protocols:
             self.handler = protocols[proto](self)
         else:
@@ -372,7 +378,7 @@ class client(threading.Thread):
             raise Exception()
 
     def handle(self, buf):
             raise Exception()
 
     def handle(self, buf):
-        p = buf.find("\n")
+        p = buf.find(b"\n")
         if p >= 0:
             proto = buf[:p]
             buf = buf[p + 1:]
         if p >= 0:
             proto = buf[:p]
             buf = buf[p + 1:]
@@ -381,24 +387,24 @@ class client(threading.Thread):
 
     def run(self):
         try:
 
     def run(self):
         try:
-            buf = ""
-            self.send("+PDM1\n")
+            buf = b""
+            self.send(b"+PDM1\n")
             while True:
                 ret = self.sk.recv(1024)
             while True:
                 ret = self.sk.recv(1024)
-                if ret == "":
+                if ret == b"":
                     return
                 buf += ret
                 while True:
                     try:
                         nbuf = self.handler.handle(buf)
                     except:
                     return
                 buf += ret
                 while True:
                     try:
                         nbuf = self.handler.handle(buf)
                     except:
+                        #for line in traceback.format_exception(*sys.exc_info()):
+                        #    print(line)
                         return
                     if nbuf == buf:
                         break
                     buf = nbuf
         finally:
                         return
                     if nbuf == buf:
                         break
                     buf = nbuf
         finally:
-            #for line in traceback.format_exception(*sys.exc_info()):
-            #    print line
             try:
                 self.sk.close()
             finally:
             try:
                 self.sk.close()
             finally:
@@ -415,7 +421,7 @@ class listener(threading.Thread):
     tcplistener.
     """
     def __init__(self):
     tcplistener.
     """
     def __init__(self):
-        super(listener, self).__init__(name = "Management listener")
+        super().__init__(name = "Management listener")
         self.setDaemon(True)
 
     def listen(self, sk):
         self.setDaemon(True)
 
     def listen(self, sk):
@@ -443,14 +449,14 @@ class listener(threading.Thread):
 
 class unixlistener(listener):
     """Unix socket listener"""
 
 class unixlistener(listener):
     """Unix socket listener"""
-    def __init__(self, name, mode = 0600, group = None):
+    def __init__(self, name, mode = 0o600, group = None):
         """Create a listener that will bind to the Unix socket named
         by `name'. The socket will not actually be bound until the
         listener is started. The socket will be chmodded to `mode',
         and if `group' is given, the named group will be set as the
         owner of the socket.
         """
         """Create a listener that will bind to the Unix socket named
         by `name'. The socket will not actually be bound until the
         listener is started. The socket will be chmodded to `mode',
         and if `group' is given, the named group will be set as the
         owner of the socket.
         """
-        super(unixlistener, self).__init__()
+        super().__init__()
         self.name = name
         self.mode = mode
         self.group = group
         self.name = name
         self.mode = mode
         self.group = group
@@ -480,7 +486,7 @@ class tcplistener(listener):
         the given local interface. The socket will not actually be
         bound until the listener is started.
         """
         the given local interface. The socket will not actually be
         bound until the listener is started.
         """
-        super(tcplistener, self).__init__()
+        super().__init__()
         self.port = port
         self.bindaddr = bindaddr
 
         self.port = port
         self.bindaddr = bindaddr
 
@@ -518,7 +524,7 @@ def listen(spec):
         last = spec
     if "/" in first:
         parts = spec.split(":")
         last = spec
     if "/" in first:
         parts = spec.split(":")
-        mode = 0600
+        mode = 0o600
         group = None
         if len(parts) > 1:
             mode = int(parts[1], 8)
         group = None
         if len(parts) > 1:
             mode = int(parts[1], 8)