summaryrefslogtreecommitdiffstats
path: root/Demo/pdist/client.py
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1995-04-10 11:40:52 (GMT)
committerGuido van Rossum <guido@python.org>1995-04-10 11:40:52 (GMT)
commit07a272d9dec67f8eb4f2bf1396a2f13671fdaba2 (patch)
tree5222965ba7973a2dd6848ea4d4a4cf5594e406db /Demo/pdist/client.py
parent21bc15b73da1e3e5ab60ff9b93a95bfd390fea3f (diff)
downloadcpython-07a272d9dec67f8eb4f2bf1396a2f13671fdaba2.zip
cpython-07a272d9dec67f8eb4f2bf1396a2f13671fdaba2.tar.gz
cpython-07a272d9dec67f8eb4f2bf1396a2f13671fdaba2.tar.bz2
commit -- why not
Diffstat (limited to 'Demo/pdist/client.py')
-rwxr-xr-xDemo/pdist/client.py133
1 files changed, 133 insertions, 0 deletions
diff --git a/Demo/pdist/client.py b/Demo/pdist/client.py
new file mode 100755
index 0000000..4b5cfc5
--- /dev/null
+++ b/Demo/pdist/client.py
@@ -0,0 +1,133 @@
+"""RPC Client module."""
+
+import sys
+import socket
+import pickle
+import __builtin__
+import os
+
+
+# Default verbosity (0 = silent, 1 = print connections, 2 = print requests too)
+VERBOSE = 1
+
+
+class Client:
+
+ """RPC Client class. No need to derive a class -- it's fully generic."""
+
+ def __init__(self, address, verbose = VERBOSE):
+ if type(address) == type(0):
+ address = ('', address)
+ self._address = address
+ self._verbose = verbose
+ if self._verbose: print "Connecting to %s ..." % repr(address)
+ self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self._socket.connect(address)
+ if self._verbose: print "Connected."
+ self._lastid = 0 # Last id for which a reply has been received
+ self._nextid = 1 # Id of next request
+ self._replies = {} # Unprocessed replies
+ self._rf = self._socket.makefile('r')
+ self._wf = self._socket.makefile('w')
+ self._methods = self._call('.methods')
+
+ def __del__(self):
+ self._close()
+
+ def _close(self):
+ if self._rf: self._rf.close()
+ self._rf = None
+ if self._wf: self._wf.close()
+ self._wf = None
+ if self._socket: self._socket.close()
+ self._socket = None
+
+ def __getattr__(self, name):
+ if name in self._methods:
+ method = _stub(self, name)
+ setattr(self, name, method) # XXX circular reference
+ return method
+ raise AttributeError, name
+
+ def _setverbose(self, verbose):
+ self._verbose = verbose
+
+ def _call(self, name, *args):
+ return self._vcall(name, args)
+
+ def _vcall(self, name, args):
+ return self._recv(self._vsend(name, args))
+
+ def _send(self, name, *args):
+ return self._vsend(name, args)
+
+ def _send_noreply(self, name, *args):
+ return self._vsend(name, args, 0)
+
+ def _vsend_noreply(self, name, args):
+ return self._vsend(name, args, 0)
+
+ def _vsend(self, name, args, wantreply = 1):
+ id = self._nextid
+ self._nextid = id+1
+ if not wantreply: id = -id
+ request = (name, args, id)
+ if self._verbose > 1: print "sending request: %s" % repr(request)
+ wp = pickle.Pickler(self._wf)
+ wp.dump(request)
+ return id
+
+ def _recv(self, id):
+ exception, value, rid = self._vrecv(id)
+ if rid != id:
+ raise RuntimeError, "request/reply id mismatch: %d/%d" % (id, rid)
+ if exception is None:
+ return value
+ x = exception
+ if hasattr(__builtin__, exception):
+ x = getattr(__builtin__, exception)
+ elif exception in ('posix.error', 'mac.error'):
+ x = os.error
+ if x == exception:
+ exception = x
+ raise exception, value
+
+ def _vrecv(self, id):
+ self._flush()
+ if self._replies.has_key(id):
+ if self._verbose > 1: print "retrieving previous reply, id = %d" % id
+ reply = self._replies[id]
+ del self._replies[id]
+ return reply
+ aid = abs(id)
+ while 1:
+ if self._verbose > 1: print "waiting for reply, id = %d" % id
+ rp = pickle.Unpickler(self._rf)
+ reply = rp.load()
+ del rp
+ if self._verbose > 1: print "got reply: %s" % repr(reply)
+ rid = reply[2]
+ arid = abs(rid)
+ if arid == aid:
+ if self._verbose > 1: print "got it"
+ return reply
+ self._replies[rid] = reply
+ if arid > aid:
+ if self._verbose > 1: print "got higher id, assume all ok"
+ return (None, None, id)
+
+ def _flush(self):
+ self._wf.flush()
+
+
+class _stub:
+
+ """Helper class for Client -- each instance serves as a method of the client."""
+
+ def __init__(self, client, name):
+ self._client = client
+ self._name = name
+
+ def __call__(self, *args):
+ return self._client._vcall(self._name, args)
+