Fixed typo.
[pdm.git] / pdm / cli.py
index 46276be..7cfa263 100644 (file)
@@ -19,16 +19,21 @@ def resolve(spec):
         return spec
     sk = None
     try:
         return spec
     sk = None
     try:
-        if "/" in spec:
+        if ":" in spec:
+            p = spec.rindex(":")
+            first, second = spec[:p], spec[p + 1:]
+            if "/" in second:
+                from . import sshsock
+                sk = sshsock.sshsocket(first, second)
+            else:
+                sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+                sk.connect((first, second))
+        elif "/" in spec:
             sk = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
             sk.connect(spec)
         elif spec.isdigit():
             sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
             sk.connect(("localhost", int(spec)))
             sk = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
             sk.connect(spec)
         elif spec.isdigit():
             sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
             sk.connect(("localhost", int(spec)))
-        elif ":" in spec:
-            sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-            p = spec.rindex(":")
-            sk.connect((spec[:p], int(spec[p + 1:])))
         else:
             raise Exception("Unknown target specification %r" % spec)
         rv = sk
         else:
             raise Exception("Unknown target specification %r" % spec)
         rv = sk
@@ -51,17 +56,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
         """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.sk = resolve(sk)
-        self.buf = ""
+        self.buf = b""
         line = self.readline()
         line = self.readline()
-        if line != "+PDM1":
+        if line != b"+PDM1":
             raise protoerr("Illegal protocol signature")
         if proto is not None:
             self.select(proto)
             raise protoerr("Illegal protocol signature")
         if proto is not None:
             self.select(proto)
@@ -77,23 +82,25 @@ class client(object):
     def readline(self):
         """Read a single NL-terminated line and return it."""
         while True:
     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 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"""
                 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)
             raise Exception("Illegal protocol specified: %r" % proto)
-        self.sk.send(proto + "\n")
+        self.sk.send(proto + b"\n")
         rep = self.readline()
         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):
             raise protoerr("Error reply when selecting protocol %s: %s" % (proto, rep[1:]))
 
     def __enter__(self):
@@ -106,17 +113,17 @@ class client(object):
 class replclient(client):
     """REPL protocol client
     
 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."""
     """
     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
 
     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")
         """
         while True:
             ncode = code.replace("\n\n", "\n")
@@ -124,16 +131,16 @@ class replclient(client):
             code = ncode
         while len(code) > 0 and code[-1] == "\n":
             code = code[:-1]
             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()
         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)
 
             else:
                 raise protoerr("Illegal reply: %s" % ln)
 
@@ -207,8 +214,8 @@ class perfproxy(object):
 class perfclient(client):
     """PERF protocol client
     
 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
 
     This client class implements functions for finding PERF objects on
     the server, and returns, for each server-side object looked up, a
@@ -218,12 +225,12 @@ class perfclient(client):
     they implement a close() method for that purpose, and can also be
     used in `with' statements.
 
     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."""
     """
     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.nextid = 0
         self.lock = threading.Lock()
         self.proxies = {}
@@ -235,10 +242,10 @@ class perfclient(client):
         self.sk.send(buf)
 
     def recvb(self, num):
         self.sk.send(buf)
 
     def recvb(self, num):
-        buf = ""
+        buf = b""
         while len(buf) < num:
             data = self.sk.recv(num - len(buf))
         while len(buf) < num:
             data = self.sk.recv(num - len(buf))
-            if data == "":
+            if data == b"":
                 raise EOFError()
             buf += data
         return buf
                 raise EOFError()
             buf += data
         return buf
@@ -317,7 +324,7 @@ class perfclient(client):
         used by the server process.
 
         The proxy objects returned by this function are cached and the
         used by the server process.
 
         The proxy objects returned by this function are cached and the
-        same object are returned the next time the same name is
+        same object is returned the next time the same name is
         requested, which means that they are kept live until the
         client connection is closed.
         """
         requested, which means that they are kept live until the
         client connection is closed.
         """