Merge branch 'master' into python3
authorFredrik Tolf <fredrik@dolda2000.com>
Fri, 23 Dec 2011 06:14:45 +0000 (07:14 +0100)
committerFredrik Tolf <fredrik@dolda2000.com>
Fri, 23 Dec 2011 06:14:45 +0000 (07:14 +0100)
1  2 
pdm/cli.py
pdm/perf.py
pdm/srv.py

diff --combined pdm/cli.py
@@@ -51,17 -51,17 +51,17 @@@ class client(object)
          """Create a client object connected to the specified
          server. `sk' can either be a socket object, which is used as
          it is, or a string specification very similar to the
-         specification for pdm.srv.listen, so see its documentation for
-         details. The differences are only that this function does not
-         take arguments specific to socket creation, like the mode and
-         group arguments for Unix sockets. If `proto' is given, that
-         subprotocol will negotiated with the server (by calling the
-         select() method).
+         specification for L{pdm.srv.listen}, so see its documentation
+         for details. The differences are only that this function does
+         not take arguments specific to socket creation, like the mode
+         and group arguments for Unix sockets. If `proto' is given,
+         that subprotocol will negotiated with the server (by calling
+         the select() method).
          """
          self.sk = resolve(sk)
 -        self.buf = ""
 +        self.buf = b""
          line = self.readline()
 -        if line != "+PDM1":
 +        if line != b"+PDM1":
              raise protoerr("Illegal protocol signature")
          if proto is not None:
              self.select(proto)
      def readline(self):
          """Read a single NL-terminated line and return it."""
          while True:
 -            p = self.buf.find("\n")
 +            p = self.buf.find(b"\n")
              if p >= 0:
                  ret = self.buf[:p]
                  self.buf = self.buf[p + 1:]
                  return ret
              ret = self.sk.recv(1024)
 -            if ret == "":
 +            if ret == b"":
                  return None
              self.buf += ret
  
      def select(self, proto):
          """Negotiate the given subprotocol with the server"""
 -        if "\n" in proto:
 +        if isinstance(proto, str):
 +            proto = proto.encode("ascii")
 +        if b"\n" in proto:
              raise Exception("Illegal protocol specified: %r" % proto)
 -        self.sk.send(proto + "\n")
 +        self.sk.send(proto + b"\n")
          rep = self.readline()
 -        if len(rep) < 1 or rep[0] != "+":
 +        if len(rep) < 1 or rep[0] != b"+"[0]:
              raise protoerr("Error reply when selecting protocol %s: %s" % (proto, rep[1:]))
  
      def __enter__(self):
  class replclient(client):
      """REPL protocol client
      
-     Implements the client side of the REPL protocol; see pdm.srv.repl
-     for details on the protocol and its functionality.
+     Implements the client side of the REPL protocol; see
+     L{pdm.srv.repl} for details on the protocol and its functionality.
      """
      def __init__(self, sk):
          """Create a connected client as documented in the `client' class."""
 -        super(replclient, self).__init__(sk, "repl")
 +        super().__init__(sk, "repl")
  
      def run(self, code):
          """Run a single block of Python code on the server. Returns
-         the output of the command (as documented in pdm.srv.repl) as a
-         string.
+         the output of the command (as documented in L{pdm.srv.repl})
+         as a string.
          """
          while True:
              ncode = code.replace("\n\n", "\n")
              code = ncode
          while len(code) > 0 and code[-1] == "\n":
              code = code[:-1]
 -        self.sk.send(code + "\n\n")
 -        buf = ""
 +        self.sk.send((code + "\n\n").encode("utf-8"))
 +        buf = b""
          while True:
              ln = self.readline()
 -            if ln[0] == " ":
 -                buf += ln[1:] + "\n"
 -            elif ln[0] == "+":
 -                return buf
 -            elif ln[0] == "-":
 -                raise protoerr("Error reply: %s" % ln[1:])
 +            if ln[0] == b" "[0]:
 +                buf += ln[1:] + b"\n"
 +            elif ln[0] == b"+"[0]:
 +                return buf.decode("utf-8")
 +            elif ln[0] == b"-"[0]:
 +                raise protoerr("Error reply: %s" % ln[1:].decode("utf-8"))
              else:
                  raise protoerr("Illegal reply: %s" % ln)
  
@@@ -209,8 -207,8 +209,8 @@@ class perfproxy(object)
  class perfclient(client):
      """PERF protocol client
      
-     Implements the client side of the PERF protocol; see pdm.srv.perf
-     for details on the protocol and its functionality.
+     Implements the client side of the PERF protocol; see
+     L{pdm.srv.perf} for details on the protocol and its functionality.
  
      This client class implements functions for finding PERF objects on
      the server, and returns, for each server-side object looked up, a
      they implement a close() method for that purpose, and can also be
      used in `with' statements.
  
-     See pdm.srv.perf for details on the various PERF interfaces that
-     the proxy objects might implement.
+     See L{pdm.srv.perf} for details on the various PERF interfaces
+     that the proxy objects might implement.
      """
      def __init__(self, sk):
          """Create a connected client as documented in the `client' class."""
 -        super(perfclient, self).__init__(sk, "perf")
 +        super().__init__(sk, "perf")
          self.nextid = 0
          self.lock = threading.Lock()
          self.proxies = {}
          self.sk.send(buf)
  
      def recvb(self, num):
 -        buf = ""
 +        buf = b""
          while len(buf) < num:
              data = self.sk.recv(num - len(buf))
 -            if data == "":
 +            if data == b"":
                  raise EOFError()
              buf += data
          return buf
diff --combined pdm/perf.py
@@@ -5,35 -5,44 +5,44 @@@ for implementing PERF interfaces in com
  classes to implement some standard PERF objects that can be used by
  PERF clients connecting to any PERF server.
  
- See the documentation for pdm.srv.perf for a description of the
+ See the documentation for L{pdm.srv.perf} for a description of the
  various PERF interfaces.
  
  It contains two named PERF objects:
  
-  * sysres -- A directory containing the following objects pertaining
-              to the resource usage of the server process:
-    * realtime -- An attribute returning the amount of real time
-                  since the PDM module was imported (which likely
-                  coincides with the amount of time the server process
-                  has been running).
-    * cputime  -- An attribute returning the amount of CPU time
-                  consumed by the server process (in both user and
-                  kernel mode).
-    * utime    -- An attribute returning the amount of CPU time the
-                  server process has spent in user mode.
-    * stime    -- An attribute returning the amount of CPU time the
-                  server process has spent in kernel mode.
-    * maxrss   -- An attribute returning the largest resident set size
-                  the server process has used during its lifetime.
-    * rusage   -- An attribute returning the current rusage of the
-                  server process.
- * sysinfo -- A directory containing the following objects pertaining
-              to the environment of the server process:
-    * pid      -- An attribute returning the PID of the server process.
-    * uname    -- An attribute returning the uname information of the
-                  system.
-    * hostname -- An attribute returning the hostname of the system.
-    * platform -- An attribute returning the Python build platform.
+  - sysres -- A directory containing the following objects pertaining
+    to the resource usage of the server process:
+     - realtime -- An attribute returning the amount of real time since
+       the PDM module was imported (which likely coincides with the
+       amount of time the server process has been running).
+     - cputime -- An attribute returning the amount of CPU time
+       consumed by the server process (in both user and kernel mode).
+     - utime -- An attribute returning the amount of CPU time the
+       server process has spent in user mode.
+     - stime -- An attribute returning the amount of CPU time the
+       server process has spent in kernel mode.
+     - maxrss -- An attribute returning the largest resident set size
+       the server process has used during its lifetime.
+     - rusage -- An attribute returning the current rusage of the
+       server process.
+  - sysinfo -- A directory containing the following objects pertaining
+    to the environment of the server process:
+     - pid -- An attribute returning the PID of the server process.
+     - uname -- An attribute returning the uname information of the
+       system.
+     - hostname -- An attribute returning the hostname of the system.
+     - platform -- An attribute returning the Python build platform.
  """
  
  import os, sys, resource, time, socket, threading
@@@ -44,7 -53,7 +53,7 @@@ __all__ = ["attrinfo", "simpleattr", "v
  
  class attrinfo(object):
      """The return value of the `attrinfo' method on `attr' objects as
-     described in pdm.srv.perf.
+     described in L{pdm.srv.perf}.
  
      Currently contains a single data field, `desc', which should have
      a human-readable description of the purpose of the attribute.
@@@ -54,7 -63,7 +63,7 @@@
  
  class perfobj(object):
      def __init__(self, *args, **kwargs):
 -        super(perfobj, self).__init__()
 +        super().__init__()
      
      def pdm_protocols(self):
          return []
@@@ -65,7 -74,7 +74,7 @@@ class simpleattr(perfobj)
      read.
      """
      def __init__(self, func, info = None, *args, **kwargs):
 -        super(simpleattr, self).__init__(*args, **kwargs)
 +        super().__init__(*args, **kwargs)
          self.func = func
          if info is None:
              info = attrinfo()
@@@ -78,7 -87,7 +87,7 @@@
          return self.info
  
      def pdm_protocols(self):
 -        return super(simpleattr, self).pdm_protocols() + ["attr"]
 +        return super().pdm_protocols() + ["attr"]
  
  class valueattr(perfobj):
      """An implementation of the `attr' interface, which is initialized
@@@ -86,7 -95,7 +95,7 @@@
      updates to the value are reflected in subsequent reads.
      """
      def __init__(self, init, info = None, *args, **kwargs):
 -        super(valueattr, self).__init__(*args, **kwargs)
 +        super().__init__(*args, **kwargs)
          self.value = init
          if info is None:
              info = attrinfo()
          return self.info
  
      def pdm_protocols(self):
 -        return super(valueattr, self).pdm_protocols() + ["attr"]
 +        return super().pdm_protocols() + ["attr"]
  
  class eventobj(perfobj):
      """An implementation of the `event' interface. It keeps track of
      subscribers when submitted with the `notify' method.
      """
      def __init__(self, *args, **kwargs):
 -        super(eventobj, self).__init__(*args, **kwargs)
 +        super().__init__(*args, **kwargs)
          self.subscribers = set()
  
      def subscribe(self, cb):
              except: pass
  
      def pdm_protocols(self):
 -        return super(eventobj, self).pdm_protocols() + ["event"]
 +        return super().pdm_protocols() + ["event"]
  
  class staticdir(perfobj):
      """An implementation of the `dir' interface. Put other PERF
      return them to requesting clients.
      """
      def __init__(self, *args, **kwargs):
 -        super(staticdir, self).__init__(*args, **kwargs)
 +        super().__init__(*args, **kwargs)
          self.map = {}
  
      def __setitem__(self, name, ob):
          return self.map.get(name, default)
  
      def listdir(self):
 -        return self.map.keys()
 +        return list(self.map.keys())
  
      def lookup(self, name):
          return self.map[name]
  
      def pdm_protocols(self):
 -        return super(staticdir, self).pdm_protocols() + ["dir"]
 +        return super().pdm_protocols() + ["dir"]
  
  class event(object):
      """This class should be subclassed by all event objects sent via
@@@ -200,7 -209,7 +209,7 @@@ class procevent(event)
      `finishevent' emitted when the connection is closed.
      """
      def __init__(self, id):
 -        super(procevent, self).__init__()
 +        super().__init__()
          if isinstance(id, procevent):
              self.id = id.id
          else:
  class startevent(procevent):
      """A subclass of `procevent'. See its documentation for details."""
      def __init__(self):
 -        super(startevent, self).__init__(getprocid())
 +        super().__init__(getprocid())
  
  class finishevent(procevent):
      """A subclass of `procevent'. Intended to be emitted when a
      distinction is meaningful. The `start' parameter should be the
      `startevent' instance used when the process was initiated."""
      def __init__(self, start, aborted = False):
 -        super(finishevent, self).__init__(start)
 +        super().__init__(start)
          self.aborted = aborted
  
  sysres = staticdir()
diff --combined pdm/srv.py
@@@ -19,9 -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
          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"):
 -            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):
 +        cmd = cmd.decode("utf-8")
          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__))
 -                self.cl.send("+OK\n")
 +                self.cl.send(b"+OK\n")
          except:
              for line in traceback.format_exception(*sys.exc_info()):
 -                self.cl.send(" " + line)
 -            self.cl.send("+EXC\n")
 +                self.cl.send(b" " + line.encode("utf-8"))
 +            self.cl.send(b"+EXC\n")
  
      def handle(self, buf):
 -        p = buf.find("\n\n")
 +        p = buf.find(b"\n\n")
          if p < 0:
              return buf
          cmd = buf[:p + 1]
@@@ -98,12 -97,12 +98,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
         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
         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
         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
         `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
         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("+PERF1\n")
 +        cl.send(b"+PERF1\n")
          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
              raise ValueError("Object does not support PDM introspection")
          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
              return
          try:
              proto = self.bindob(id, ob)
 -        except Exception, exc:
 +        except Exception as exc:
              self.send("-", exc)
              return
          self.send("+", proto)
              return
          try:
              ob = src.lookup(obnm)
 -        except KeyError, exc:
 +        except KeyError as exc:
              self.send("-", exc)
              return
          try:
              proto = self.bindob(tgtid, ob)
 -        except Exception, exc:
 +        except Exception as exc:
              self.send("-", exc)
              return
          self.send("+", proto)
              return
          try:
              ret = ob.readattr()
 -        except Exception, exc:
 +        except Exception as exc:
              self.send("-", Exception("Could not read attribute"))
              return
          self.send("+", ret)
              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):
@@@ -355,7 -354,7 +355,7 @@@ protocols["perf"] = per
  
  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
          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:
              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:]
  
      def run(self):
          try:
 -            buf = ""
 -            self.send("+PDM1\n")
 +            buf = b""
 +            self.send(b"+PDM1\n")
              while True:
                  ret = self.sk.recv(1024)
 -                if ret == "":
 +                if ret == b"":
                      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 -413,7 +418,7 @@@ class listener(threading.Thread)
      tcplistener.
      """
      def __init__(self):
 -        super(listener, self).__init__(name = "Management listener")
 +        super().__init__(name = "Management listener")
          self.setDaemon(True)
  
      def listen(self, sk):
  
  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.
          """
 -        super(unixlistener, self).__init__()
 +        super().__init__()
          self.name = name
          self.mode = mode
          self.group = group
@@@ -483,7 -478,7 +483,7 @@@ class tcplistener(listener)
          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
  
@@@ -521,7 -516,7 +521,7 @@@ def listen(spec)
          last = spec
      if "/" in first:
          parts = spec.split(":")
 -        mode = 0600
 +        mode = 0o600
          group = None
          if len(parts) > 1:
              mode = int(parts[1], 8)