X-Git-Url: http://dolda2000.com/gitweb/?a=blobdiff_plain;f=pdm%2Fsrv.py;h=b2c131aef72874965ab81c16169e2b56399a9f7f;hb=9e3c83b113c519d0073457ae0cfe80291bcda7e9;hp=3ddc6823e1ce33ad3d54a78f7d721cac9e59aaf5;hpb=144c745cd600fc7c050f5426fe438430885ef5b8;p=pdm.git diff --git a/pdm/srv.py b/pdm/srv.py index 3ddc682..b2c131a 100644 --- a/pdm/srv.py +++ b/pdm/srv.py @@ -19,9 +19,9 @@ class repl(object): """REPL protocol handler Provides a read-eval-print loop. The primary client-side interface - is the pdm.cli.replclient class. Clients can send arbitrary code, - which is compiled and run on its own thread in the server process, - and output responses that are echoed back to the client. + is the L{pdm.cli.replclient} class. Clients can send arbitrary + code, which is compiled and run on its own thread in the server + process, and output responses that are echoed back to the client. Each client is provided with its own module, in which the code runs. The module is prepared with a function named `echo', which @@ -40,34 +40,35 @@ class repl(object): self.mod = types.ModuleType("repl") self.mod.echo = self.echo self.printer = pprint.PrettyPrinter(indent = 4, depth = 6) - cl.send(b"+REPL\n") + cl.send("+REPL\n") def sendlines(self, text): for line in text.split("\n"): - self.cl.send(b" " + line.encode("utf-8") + b"\n") + self.cl.send(" " + line + "\n") 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") - exec(ccode, self.mod.__dict__) - self.cl.send(b"+OK\n") + exec ccode in self.mod.__dict__ + self.cl.send("+OK\n") else: self.echo(eval(ccode, self.mod.__dict__)) - self.cl.send(b"+OK\n") + self.cl.send("+OK\n") except: - for line in traceback.format_exception(*sys.exc_info()): - self.cl.send(b" " + line.encode("utf-8")) - self.cl.send(b"+EXC\n") + 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") def handle(self, buf): - p = buf.find(b"\n\n") + p = buf.find("\n\n") if p < 0: return buf cmd = buf[:p + 1] @@ -98,12 +99,12 @@ class perf(object): already be imported. PDM will not import new modules for clients; rather, the daemon process needs to import all modules that clients should be able to interact with. PDM itself always imports - the pdm.perf module, which contains a few basic PERF objects. See - its documentation for details. + the L{pdm.perf} module, which contains a few basic PERF + objects. See its documentation for details. The following interfaces are currently known to PERF. - * attr: + - attr: An object that implements the `attr' interface models an attribute that can be read by clients. The attribute can be anything, as long as its representation can be @@ -117,9 +118,9 @@ class perf(object): description of the attribute. Both should be idempotent. `readattr' can return any pickleable object, and `attrinfo' should return either None to indicate that it has no - description, or an instance of the pdm.perf.attrinfo class. + description, or an instance of the L{pdm.perf.attrinfo} class. - * dir: + - dir: The `dir' interface models a directory of other PERF objects. An object implementing it must implement methods called `lookup' and `listdir'. `lookup' is called with a single @@ -130,7 +131,7 @@ class perf(object): used as argument to `lookup', but the list is not required to be exhaustive and may also be empty. - * invoke: + - invoke: The `invoke' interface allows a more arbitrary form of method calls to objects implementing it. Such objects must implement a method called `invoke', which is called with one positional @@ -141,7 +142,7 @@ class perf(object): the client. In case the method name is not recognized, `invoke' should raise an AttributeError. - * event: + - event: The `event' interface allows PERF objects to notify clients of events asynchronously. Objects implementing it must implement methods called `subscribe' and `unsubscribe'. `subscribe' will @@ -151,7 +152,7 @@ class perf(object): `event' object should then call all such registered callables with a single argument describing the event. The argument could be any object that can be pickled, but should be an instance of - a subclass of the pdm.perf.event class. If `subscribe' is + a subclass of the L{pdm.perf.event} class. If `subscribe' is called with a callback object that it has already registered, it should raise a ValueError. `unsubscribe' is called with a single argument, which is a previously registered callback @@ -160,23 +161,23 @@ class perf(object): object is not, in fact, registered, a ValueError should be raised. - The pdm.perf module contains a few convenience classes which + The L{pdm.perf} module contains a few convenience classes which implements the interfaces, but PERF objects are not required to be instances of them. Any object can implement a PERF interface, as long as it does so as described above. - The pdm.cli.perfclient class is the client-side implementation. + The L{pdm.cli.perfclient} class is the client-side implementation. """ def __init__(self, cl): self.cl = cl self.odtab = {} - cl.send(b"+PERF1\n") + cl.send("+PERF1\n") self.buf = "" self.lock = threading.Lock() self.subscribed = {} def closed(self): - for id, recv in self.subscribed.items(): + for id, recv in self.subscribed.iteritems(): ob = self.odtab[id] if ob is None: continue ob, protos = ob @@ -198,7 +199,7 @@ class perf(object): raise ValueError("Object does not support PDM introspection") try: proto = ob.pdm_protocols() - except Exception as exc: + except Exception, exc: raise ValueError("PDM introspection failed", exc) self.odtab[id] = ob, proto return proto @@ -215,7 +216,7 @@ class perf(object): return try: proto = self.bindob(id, ob) - except Exception as exc: + except Exception, exc: self.send("-", exc) return self.send("+", proto) @@ -237,12 +238,12 @@ class perf(object): return try: ob = src.lookup(obnm) - except KeyError as exc: + except KeyError, exc: self.send("-", exc) return try: proto = self.bindob(tgtid, ob) - except Exception as exc: + except Exception, exc: self.send("-", exc) return self.send("+", proto) @@ -272,7 +273,7 @@ class perf(object): return try: ret = ob.readattr() - except Exception as exc: + except Exception, exc: self.send("-", Exception("Could not read attribute")) return self.send("+", ret) @@ -289,7 +290,7 @@ class perf(object): return try: self.send("+", ob.invoke(method, *args, **kwargs)) - except Exception as exc: + except Exception, exc: self.send("-", exc) def event(self, id, ob, ev): @@ -355,7 +356,7 @@ protocols["perf"] = perf class client(threading.Thread): def __init__(self, sk): - super().__init__(name = "Management client") + super(client, self).__init__(name = "Management client") self.setDaemon(True) self.sk = sk self.handler = self @@ -364,10 +365,6 @@ class client(threading.Thread): 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: @@ -375,7 +372,7 @@ class client(threading.Thread): raise Exception() def handle(self, buf): - p = buf.find(b"\n") + p = buf.find("\n") if p >= 0: proto = buf[:p] buf = buf[p + 1:] @@ -384,24 +381,24 @@ class client(threading.Thread): def run(self): try: - buf = b"" - self.send(b"+PDM1\n") + buf = "" + self.send("+PDM1\n") while True: ret = self.sk.recv(1024) - if ret == b"": + if ret == "": 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: + #for line in traceback.format_exception(*sys.exc_info()): + # print line try: self.sk.close() finally: @@ -418,7 +415,7 @@ class listener(threading.Thread): tcplistener. """ def __init__(self): - super().__init__(name = "Management listener") + super(listener, self).__init__(name = "Management listener") self.setDaemon(True) def listen(self, sk): @@ -446,14 +443,14 @@ class listener(threading.Thread): class unixlistener(listener): """Unix socket listener""" - def __init__(self, name, mode = 0o600, group = None): + def __init__(self, name, mode = 0600, 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. """ - super().__init__() + super(unixlistener, self).__init__() self.name = name self.mode = mode self.group = group @@ -483,7 +480,7 @@ class tcplistener(listener): the given local interface. The socket will not actually be bound until the listener is started. """ - super().__init__() + super(tcplistener, self).__init__() self.port = port self.bindaddr = bindaddr @@ -521,7 +518,7 @@ def listen(spec): last = spec if "/" in first: parts = spec.split(":") - mode = 0o600 + mode = 0600 group = None if len(parts) > 1: mode = int(parts[1], 8)