1 """This class works in concert with bin/pylab_server.py
2 to allow you to display simple pylab/matplotlib graphics
3 on another machine. It's most useful if you need to do
4 plots from a machine where pylab isn't or cannot be installed.
5 """
6
7 import os as _os
8
9
10
14
18
22
23
25 import socket as _s
26 import codecs as _c
27 import random as _r
28 import cPickle as _p
29 import md5 as _m
30
31 ID = 'pylab_server'
32 KEY = 'alfaljflajljljslfajsljalsfjalsqowrq nfnqn qkfqle'
33 PP = 0
34
38
39
41 if self.out:
42
43 self.sock.sendall( ''.join(self.out) )
44 self.out = []
45
46
47 - def send(self, prefix, s):
48 self.out.append( '%s %s\n' % (prefix, self.tohex(s)[0]) )
49
50 self.thash.update(s)
51 if len(s) > 1000:
52 self.flush()
53
54
56 self.fromhex = self._c.getdecoder('hex_codec')
57 self.tohex = self._c.getencoder('hex_codec')
58 self.thash = self._m.new()
59 self.rhash = self._m.new()
60 self.thash.update(self.KEY + '1')
61 self.rhash.update(self.KEY + '2')
62 self.out = []
63 self.rqno = None
64 self.rfile = None
65 self.open(host, port)
66
67
68 - def call(self, fnname, args, argdict):
69 self.xmit_call(fnname, args, argdict)
70 return self.recv()
71
72
74 self.send('I', self.ID)
75 self.rqno = self._r.getrandbits(31)
76 self.send('R', '%d' % self.rqno)
77 self.send('O', 'call')
78 self.send('F', fnname)
79 self.send('A', self._p.dumps(args, self.PP) )
80 self.send('B', self._p.dumps(argdict, self.PP) )
81 self.send('H', self.thash.hexdigest() )
82 self.send('E', 'END')
83 self.flush()
84
85
87 self.xmit_special(op)
88 return self.recv()
89
90
92 self.send('I', self.ID)
93 self.rqno = self._r.getrandbits(31)
94 self.send('R', '%d' % self.rqno)
95 self.send('O', op)
96 self.send('H', self.thash.hexdigest() )
97 self.send('E', 'END')
98 self.flush()
99
100
101 - def get(self, prefix):
102 tmp = self.rfile.readline()
103 if tmp == '':
104 raise _SocketClosed
105 x = self.fromhex(tmp[1:].strip())[0]
106 if tmp[0] == 'Z':
107 raise _ProtocolError, 'Remote: %s' % x
108 if tmp[0] != prefix:
109 raise _BadPrefixError, 'Expected %s, got %s' % (prefix, tmp[0])
110 self.rhash.update(x)
111 return x
112
113
115 if self.get('i') != self.ID:
116 raise _ProtocolError, 'ID mismatch'
117 if int(self.get('r')) != self.rqno:
118 raise _ProtocolError, 'Bad rqno.'
119 code = self.get('c')
120 v = self.get('v')
121 localhash = self.rhash.hexdigest()
122 if localhash != self.get('h'):
123 raise _ProtocolError, 'Bad authentication'
124 if self.get('e') != 'END':
125 raise _ProtocolError, 'No end'
126
127 rv = self._p.loads( v )
128
129 if code == 'Exception':
130 function, argt, argd, x = rv
131 raise Exception(x, function, argt, argd)
132 elif code == 'AttributeError':
133 raise AttributeError, rv
134 return rv
135
136
137 - def open(self, host, port):
138 """Connect to a host.
139 Don't try to reopen an already connected instance.
140 """
141 self.eof = 0
142 self.host = host
143 self.port = port
144 msg = "getaddrinfo returns an empty list"
145 for res in self._s.getaddrinfo(host, port, 0, self._s.SOCK_STREAM):
146 af, socktype, proto, canonname, sa = res
147 try:
148 self.sock = self._s.socket(af, socktype, proto)
149 self.sock.connect(sa)
150 except self._s.error, msg:
151 if self.sock:
152 self.sock.close()
153 self.sock = None
154 continue
155 break
156 if not self.sock:
157 raise self._s.error, '%s on (%s,%s,%s,%s,%s)' % (msg,
158 af, socktype, proto, canonname, sa)
159 self.rfile = self.sock.makefile('rb', -1)
160
161
163 if self.sock:
164
165 self.sock.close()
166 self.sock = None
167
168
171
173 c = _pylab_client(_Host, _Port)
174 print c.special('list')[:10]
175 print c.call('plot', ([1,2,3,4], [1,2,4,1]), {})
176 print c.call('show', (), {})
177 c.close()
178
179
180
181 if 'PYLABDISP' in _os.environ:
182 Host, Port = _os.environ.get('PYLABDISP', 'localhost:8125').split(':')
183 _client = _pylab_client(Host, Port)
184 _list = _client.special('list')
185 for (_nm, _c) in _list:
186 if _c:
187 exec("def %s(*a, **b): _client.call('%s', a, b)" % (_nm, _nm))
188 else:
189 from pylab import *
190
191 if __name__ == '__main__':
192 plot([1,2,3,4], [1,2,4,1])
193 show()
194