[hackers] [wmii] Add ridiculously overwrought asynchronous 9P client. || Kris Maglione

From: <hg_AT_suckless.org>
Date: Thu, 21 May 2009 18:38:41 +0000 (UTC)

changeset: 2460:b63a6adce614
tag: tip
user: Kris Maglione <jg_AT_suckless.org>
date: Thu May 21 14:38:38 2009 -0400
files: alternative_wmiircs/python/pygmi/__init__.py alternative_wmiircs/python/pygmi/fs.py alternative_wmiircs/python/pyxp/asyncclient.py alternative_wmiircs/python/pyxp/client.py alternative_wmiircs/python/pyxp/fcall.py alternative_wmiircs/python/pyxp/fields.py alternative_wmiircs/python/pyxp/mux.py alternative_wmiircs/python/wmiirc
description:
Add ridiculously overwrought asynchronous 9P client.

diff -r f529bf0b3cce -r b63a6adce614 alternative_wmiircs/python/pygmi/__init__.py
--- a/alternative_wmiircs/python/pygmi/__init__.py Thu May 21 14:22:58 2009 -0400
+++ b/alternative_wmiircs/python/pygmi/__init__.py Thu May 21 14:38:38 2009 -0400
@@ -1,7 +1,7 @@
 import os
 import sys
 
-from pyxp import Client
+from pyxp.asyncclient import Client
 
 if 'WMII_ADDRESS' in os.environ:
     client = Client(os.environ['WMII_ADDRESS'])
diff -r f529bf0b3cce -r b63a6adce614 alternative_wmiircs/python/pygmi/fs.py
--- a/alternative_wmiircs/python/pygmi/fs.py Thu May 21 14:22:58 2009 -0400
+++ b/alternative_wmiircs/python/pygmi/fs.py Thu May 21 14:38:38 2009 -0400
@@ -16,7 +16,7 @@
         pass
 
     def ctl(self, msg):
- client.write(self.ctl_path, msg)
+ client.awrite(self.ctl_path, msg)
 
     def __getitem__(self, key):
         for line in self.ctl_lines():
@@ -58,7 +58,7 @@
         lines = tuple(client.readlines(self.ctl_path))
         if self.ctl_hasid:
             lines = lines[1:]
- return lines[:-1]
+ return lines
 
     _id = None
     @property
@@ -111,7 +111,7 @@
         def __set__(self, dir, val):
             if not self.writable:
                 raise NotImplementedError('File %s is not writable' % self.name)
- return client.write('%s/%s' % (dir.path, self.name), val)
+ return client.awrite('%s/%s' % (dir.path, self.name), val)
 
     @property
     def ctl_path(self):
@@ -341,13 +341,9 @@
 
     def create(self, colors=None, label=None):
         with client.create(self.path, OWRITE) as f:
- if colors or label:
- f.write(self.getval(colors, label))
+ f.write(self.getval(colors, label))
     def remove(self):
- try:
- client.remove(self.path)
- except Exception:
- pass
+ client.aremove(self.path)
 
     def getval(self, colors=None, label=None):
         if colors is None:
@@ -358,7 +354,7 @@
 
     colors = property(
         lambda self: tuple(map(Color, client.read(self.path).split(' ')[:3])),
- lambda self, val: client.write(self.path, self.getval(colors=val)))
+ lambda self, val: client.awrite(self.path, self.getval(colors=val)))
 
     label = property(
         lambda self: client.read(self.path).split(' ', 3)[3],
@@ -480,7 +476,7 @@
             assert '/' not in k and '\n' not in v
             lines.append('/%s/ -> %s' % (k, v))
         lines.append('')
- client.write(self.path, '\n'.join(lines))
+ client.awrite(self.path, '\n'.join(lines))
 
     def iteritems(self):
         for line in client.readlines(self.path):
@@ -520,7 +516,7 @@
             self.add(t.id)
         for b in wmii.lbuttons:
             if b.name not in self.tags:
- b.remove()
+ b.aremove()
         self.focus(Tag('sel').id)
 
         self.mru = [self.sel.id]
diff -r f529bf0b3cce -r b63a6adce614 alternative_wmiircs/python/pyxp/asyncclient.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/alternative_wmiircs/python/pyxp/asyncclient.py Thu May 21 14:38:38 2009 -0400
@@ -0,0 +1,206 @@
+from pyxp import client, fcall
+from pyxp.client import *
+
+def awithfile(*oargs, **okwargs):
+ def wrapper(fn):
+ def next(self, path, *args, **kwargs):
+ def next(file, exc, tb):
+ fn(self, (file, exc, tb), *args, **kwargs)
+ self.aopen(path, next, *oargs, **okwargs)
+ return next
+ return wrapper
+def wrap_callback(fn, file):
+ file.called = 0
+ def callback(data, exc, tb):
+ file.called += 1
+ file.close()
+ if callable(fn):
+ fn(data, exc, tb)
+ return callback
+
+class Client(client.Client):
+ ROOT_FID = 0
+
+ def awalk(self, path, async, fail=None):
+ ctxt = dict(path=path, fid=self.getfid(), ofid=ROOT_FID)
+ def next(resp=None, exc=None, tb=None):
+ if exc and ctxt['ofid'] != ROOT_FID:
+ self.aclunk(ctxt['fid'])
+ if not ctxt['path'] and resp or exc:
+ if exc and fail:
+ return self.respond(fail, None, exc, tb)
+ return self.respond(async, ctxt['fid'], exc, tb)
+ wname = ctxt['path'][:fcall.MAX_WELEM]
+ ofid = ctxt['ofid']
+ ctxt['path'] = ctxt['path'][fcall.MAX_WELEM:]
+ if resp:
+ ctxt['ofid'] = ctxt['fid']
+ self.dorpc(fcall.Twalk(fid=ofid,
+ newfid=ctxt['fid'],
+ wname=wname),
+ next)
+ next()
+
+ def _open(self, path, mode, open):
+ resp = None
+
+ with self.walk(path) as nfid:
+ fid = nfid
+ resp = self.dorpc(open(fid))
+
+ def cleanup():
+ self.aclunk(fid)
+ file = File(self, '/'.join(path), resp, fid, mode, cleanup)
+ self.files[fid] = file
+
+ return file
+
+ def _aopen(self, path, mode, open, callback):
+ resp = None
+ def next(fid, exc, tb):
+ def next(resp, exc, tb):
+ def cleanup():
+ self.clunk(fid)
+ file = File(self, '/'.join(path), resp, fid, mode, cleanup)
+ self.files[fid] = file
+ self.respond(callback, file)
+ self.dorpc(open(fid), next, callback)
+ self.awalk(path, next, callback)
+
+ def aopen(self, path, callback=True, mode=OREAD):
+ assert callable(callback)
+ path = self.splitpath(path)
+ def open(fid):
+ return fcall.Topen(fid=fid, mode=mode)
+ return self._aopen(path, mode, open, callback)
+
+ def acreate(self, path, callback=True, mode=OREAD, perm=0):
+ path = self.splitpath(path)
+ name = path.pop()
+ def open(fid):
+ return fcall.Tcreate(fid=fid, mode=mode, name=name, perm=perm)
+ if not callable(callback):
+ def callback(resp, exc, tb):
+ if resp:
+ resp.close()
+ return self._aopen(path, mode, open, async)
+
+ def aremove(self, path, callback=True):
+ path = self.splitpath(path)
+ def next(fid, exc, tb):
+ self.dorpc(fcall.Tremove(fid=fid), callback)
+ self.awalk(path, next, callback)
+
+ def astat(self, path, callback):
+ path = self.splitpath(path)
+ def next(fid, exc, tb):
+ def next(resp, exc, tb):
+ callback(resp.stat, exc, tb)
+ self.dorpc(fcall.Tstat(fid=fid), next, callback)
+
+ @awithfile()
+ def aread(self, (file, exc, tb), callback, *args, **kwargs):
+ if exc:
+ callback(file, exc, tb)
+ else:
+ file.aread(wrap_callback(callback, file), *args, **kwargs)
+ @awithfile(mode=OWRITE)
+ def awrite(self, (file, exc, tb), data, callback=True, *args, **kwargs):
+ if exc:
+ self.respond(callback, file, exc, tb)
+ else:
+ file.awrite(data, wrap_callback(callback, file), *args, **kwargs)
+ @awithfile()
+ def areadlines(self, (file, exc, tb), fn):
+ def callback(resp):
+ if resp is None:
+ file.close()
+ if fn(resp) is False:
+ file.close()
+ return False
+ if exc:
+ callback(None)
+ else:
+ file.sreadlines(callback)
+
+class File(client.File):
+ @staticmethod
+ def respond(callback, data, exc=None, tb=None):
+ if callable(callback):
+ callback(data, exc, tb)
+
+ def stat(self, callback):
+ def next(resp, exc, tb):
+ callback(resp.stat, exc, tb)
+ resp = self.dorpc(fcall.Tstat(), next, callback)
+
+ def aread(self, callback, count=None, offset=None, buf=''):
+ ctxt = dict(res=[], count=self.iounit, offset=self.offset)
+ if count is not None:
+ ctxt['count'] = count
+ if offset is not None:
+ ctxt['offset'] = offset
+ def next(resp=None, exc=None, tb=None):
+ if resp and resp.data:
+ ctxt['res'].append(resp.data)
+ ctxt['offset'] += len(resp.data)
+ if ctxt['count'] == 0:
+ if offset is None:
+ self.offset = ctxt['offset']
+ return callback(''.join(ctxt['res']), exc, tb)
+
+ n = min(ctxt['count'], self.iounit)
+ ctxt['count'] -= n
+
+ self.dorpc(fcall.Tread(offset=ctxt['offset'], count=n),
+ next, callback)
+ next()
+
+ def areadlines(self, callback):
+ ctxt = dict(last=None)
+ def next(data, exc, tb):
+ res = True
+ if data:
+ lines = data.split('\n')
+ if ctxt['last']:
+ lines[0] = ctxt['last'] + lines[0]
+ for i in range(0, len(lines) - 1):
+ res = callback(lines[i])
+ if res is False:
+ break
+ ctxt['last'] = lines[-1]
+ if res is not False:
+ self.aread(next)
+ else:
+ if ctxt['last']:
+ callback(ctxt['last'])
+ callback(None)
+ self.aread(next)
+
+ def awrite(self, data, callback, offset=None):
+ ctxt = dict(offset=self.offset, off=0)
+ if offset is not None:
+ ctxt['offset'] = offset
+ def next(resp=None, exc=None, tb=None):
+ if resp:
+ ctxt['off'] += resp.count
+ ctxt['offset'] += resp.count
+ if ctxt['off'] < len(data):
+ n = min(len(data), self.iounit)
+
+ self.dorpc(fcall.Twrite(offset=ctxt['offset'],
+ data=data[ctxt['off']:ctxt['off']+n]),
+ next, callback)
+ else:
+ if offset is None:
+ self.offset = ctxt['offset']
+ self.respond(callback, ctxt['off'], exc, tb)
+ next()
+
+ def aremove(self, callback=True):
+ def next(resp, exc, tb):
+ self.close()
+ self.respond(resp and True, exc, tb)
+ self.dorpc(fcall.Tremove(), next)
+
+# vim:se sts=4 sw=4 et:
diff -r f529bf0b3cce -r b63a6adce614 alternative_wmiircs/python/pyxp/client.py
--- a/alternative_wmiircs/python/pyxp/client.py Thu May 21 14:22:58 2009 -0400
+++ b/alternative_wmiircs/python/pyxp/client.py Thu May 21 14:38:38 2009 -0400
@@ -1,5 +1,4 @@
-# Copyright (C) 2007 Kris Maglione
-# See PERMISSIONS
+# Copyright (C) 2009 Kris Maglione
 
 import operator
 import os
@@ -43,6 +42,12 @@
 
 class Client(object):
     ROOT_FID = 0
+
+ @staticmethod
+ def respond(callback, data, exc=None, tb=None):
+ if callable(callback):
+ callback(data, exc, tb)
+
 
     def __enter__(self):
         return self
@@ -89,30 +94,49 @@
             self.mux.fd.close()
             self.mux = None
 
- def dorpc(self, req):
- resp = self.mux.rpc(req)
- if isinstance(resp, fcall.Rerror):
- raise RPCError, "RPC returned error (%s): %s" % (
- req.__class__.__name__, resp.ename)
- if req.type != resp.type ^ 1:
- raise ProtocolException, "Missmatched RPC message types: %s => %s" % (
- req.__class__.__name__, resp.__class__.__name__)
- return resp
+ def dorpc(self, req, callback=None, error=None):
+ def doresp(resp):
+ if isinstance(resp, fcall.Rerror):
+ raise RPCError, "%s[%d] RPC returned error: %s" % (
+ req.__class__.__name__, resp.tag, resp.ename)
+ if req.type != resp.type ^ 1:
+ raise ProtocolException, "Missmatched RPC message types: %s => %s" % (
+ req.__class__.__name__, resp.__class__.__name__)
+ return resp
+ def next(mux, resp):
+ try:
+ res = doresp(resp)
+ except Exception, e:
+ if error:
+ self.respond(error, None, e, None)
+ else:
+ self.respond(callback, None, e, None)
+ else:
+ self.respond(callback, res)
+ if not callback:
+ return doresp(self.mux.rpc(req))
+ self.mux.rpc(req, next)
 
     def splitpath(self, path):
         return [v for v in path.split('/') if v != '']
 
     def getfid(self):
         with self.lock:
- if len(self.fids):
+ if self.fids:
                 return self.fids.pop()
- else:
- self.lastfid += 1
- return self.lastfid
+ self.lastfid += 1
+ return self.lastfid
     def putfid(self, fid):
         with self.lock:
             self.files.pop(fid)
             self.fids.append(fid)
+
+ def aclunk(self, fid, callback=None):
+ def next(resp, exc, tb):
+ if resp:
+ self.putfid(fid)
+ self.respond(callback, resp, exc, tb)
+ self.dorpc(fcall.Tclunk(fid=fid), next)
 
     def clunk(self, fid):
         try:
@@ -133,9 +157,9 @@
 
         @apply
         class Res:
- def __enter__(self):
+ def __enter__(res):
                 return fid
- def __exit__(self, exc_type, exc_value, traceback):
+ def __exit__(res, exc_type, exc_value, traceback):
                 if exc_type:
                     self.clunk(fid)
         return Res
@@ -148,20 +172,20 @@
             resp = self.dorpc(open(fid))
 
         def cleanup():
- self.clunk(fid)
- file = File(self, resp, fid, mode, cleanup)
+ self.aclunk(fid)
+ file = File(self, '/'.join(path), resp, fid, mode, cleanup)
         self.files[fid] = file
 
         return file
 
- def open(self, path, mode = OREAD):
+ def open(self, path, mode=OREAD):
         path = self.splitpath(path)
 
         def open(fid):
             return fcall.Topen(fid=fid, mode=mode)
         return self._open(path, mode, open)
 
- def create(self, path, mode = OREAD, perm = 0):
+ def create(self, path, mode=OREAD, perm=0):
         path = self.splitpath(path)
         name = path.pop()
 
@@ -209,22 +233,23 @@
     def __exit__(self, *args):
         self.close()
 
- def __init__(self, client, fcall, fid, mode, cleanup):
+ def __init__(self, client, path, fcall, fid, mode, cleanup):
         self.lock = RLock()
         self.client = client
+ self.path = path
         self.fid = fid
         self.cleanup = cleanup
         self.mode = mode
         self.iounit = fcall.iounit
         self.qid = fcall.qid
+ self.closed = False
 
         self.offset = 0
- self.fd = None
 
- def dorpc(self, fcall):
+ def dorpc(self, fcall, async=None, error=None):
         if hasattr(fcall, 'fid'):
             fcall.fid = self.fid
- return self.client.dorpc(fcall)
+ return self.client.dorpc(fcall, async, error)
 
     def stat(self):
         resp = self.dorpc(fcall.Tstat())
@@ -262,6 +287,9 @@
             if not data:
                 break
             lines = data.split('\n')
+ if last:
+ lines[0] = last + lines[0]
+ last = None
             for i in range(0, len(lines) - 1):
                 yield lines[i]
             last = lines[-1]
@@ -300,15 +328,13 @@
                 yield s
 
     def close(self):
- try:
- if self.fd:
- self.fd_close()
- finally:
- self.cleanup()
- self.tg = None
- self.fid = None
- self.client = None
- self.qid = None
+ assert not self.closed
+ self.closed = True
+ self.cleanup()
+ self.tg = None
+ self.fid = None
+ self.client = None
+ self.qid = None
 
     def remove(self):
         try:
@@ -319,10 +345,4 @@
             except Exception:
                 pass
 
- def fd_close(self):
- try:
- self.fd.close()
- finally:
- self.fd = None
-
 # vim:se sts=4 sw=4 et:
diff -r f529bf0b3cce -r b63a6adce614 alternative_wmiircs/python/pyxp/fcall.py
--- a/alternative_wmiircs/python/pyxp/fcall.py Thu May 21 14:22:58 2009 -0400
+++ b/alternative_wmiircs/python/pyxp/fcall.py Thu May 21 14:38:38 2009 -0400
@@ -61,7 +61,7 @@
 
 class Terror(Fcall):
     def __init__(self):
- raise Error("Illegal 9P tag 'Terror' encountered")
+ raise Exception("Illegal 9P tag 'Terror' encountered")
 class Rerror(Fcall):
     ename = String()
 
diff -r f529bf0b3cce -r b63a6adce614 alternative_wmiircs/python/pyxp/fields.py
--- a/alternative_wmiircs/python/pyxp/fields.py Thu May 21 14:22:58 2009 -0400
+++ b/alternative_wmiircs/python/pyxp/fields.py Thu May 21 14:38:38 2009 -0400
@@ -74,13 +74,9 @@
     def marshall(self, val):
         return self.encode(int(val.strftime('%s')))
 
-# To do: use unicode strings, ensure UTF-8.
-# Not a problem in Python 3K, but there the other
-# data blobs are.
-class String(Int):
+class Data(Int):
     def __init__(self, size=2):
- super(String, self).__init__(size)
-
+ super(Data, self).__init__(size)
     def unmarshall(self, data, offset):
         n = self.decode(data, offset)
         offset += self.size
@@ -89,8 +85,18 @@
     def marshall(self, val):
         return [self.encode(len(val)), val]
 
-class Data(String):
- pass
+# Note: Py3K strings are Unicode by default. They can't store binary
+# data.
+class String(Data):
+ def unmarshall(self, data, offset):
+ off, val = super(String, self).unmarshall(data, offset)
+ return off, val.decode('UTF-8')
+ def marshall(self, val):
+ if isinstance(val, str):
+ str.decode('UTF-8')
+ else:
+ val = val.encode('UTF-8')
+ return super(String, self).marshall(val)
 
 class Array(Int):
     def __init__(self, size, spec):
diff -r f529bf0b3cce -r b63a6adce614 alternative_wmiircs/python/pyxp/mux.py
--- a/alternative_wmiircs/python/pyxp/mux.py Thu May 21 14:22:58 2009 -0400
+++ b/alternative_wmiircs/python/pyxp/mux.py Thu May 21 14:38:38 2009 -0400
@@ -14,6 +14,9 @@
 # The above copyright notice and this permission notice shall be
 # included in all copies or substantial portions of the Software.
 
+import sys
+import traceback
+
 from pyxp import fields
 from pyxp.dial import dial
 from threading import *
@@ -22,13 +25,14 @@
 __all__ = 'Mux',
 
 class Mux(object):
- def __init__(self, con, process, mintag=0, maxtag=1<<16 - 1):
+ def __init__(self, con, process, flush=None, mintag=0, maxtag=1<<16 - 1):
         self.queue = set()
         self.lock = RLock()
         self.rendez = Condition(self.lock)
         self.outlock = RLock()
         self.inlock = RLock()
         self.process = process
+ self.flush = flush
         self.wait = {}
         self.free = set(range(mintag, maxtag))
         self.mintag = mintag
@@ -42,60 +46,78 @@
         if self.fd is None:
             raise Exception("No connection")
 
- def rpc(self, dat):
- r = self.newrpc(dat)
+ def mux(self, rpc):
+ try:
+ rpc.waiting = True
+ self.lock.acquire()
+ while self.muxer and self.muxer != rpc and rpc.data is None:
+ rpc.wait()
 
- try:
- self.lock.acquire()
- while self.muxer and self.muxer != r and r.data is None:
- r.wait()
-
- if r.data is None:
- if self.muxer and self.muxer != r:
- self.fail()
- self.muxer = r
+ if rpc.data is None:
+ assert not self.muxer or self.muxer is rpc
+ self.muxer = rpc
                 self.lock.release()
                 try:
- while r.data is None:
+ while rpc.data is None:
                         data = self.recv()
                         if data is None:
                             self.lock.acquire()
- self.queue.remove(r)
+ self.queue.remove(rpc)
                             raise Exception("unexpected eof")
                         self.dispatch(data)
+ finally:
                     self.lock.acquire()
- finally:
                     self.electmuxer()
- self.puttag(r)
         except Exception, e:
- import sys
- import traceback
             traceback.print_exc(sys.stdout)
- print e
+ if self.flush:
+ self.flush(self, rpc.data)
+ raise e
         finally:
             if self.lock._is_owned():
                 self.lock.release()
- return r.data
+
+ if rpc.async:
+ if callable(rpc.async):
+ rpc.async(self, rpc.data)
+ else:
+ return rpc.data
+
+ def rpc(self, dat, async=None):
+ rpc = self.newrpc(dat, async)
+ if async:
+ with self.lock:
+ if self.muxer is None:
+ self.electmuxer()
+ else:
+ return self.mux(rpc)
 
     def electmuxer(self):
+ async = None
         for rpc in self.queue:
- if self.muxer != rpc and rpc.async == False:
- self.muxer = rpc
- rpc.notify()
- return
+ if self.muxer != rpc:
+ if rpc.async:
+ async = rpc
+ else:
+ self.muxer = rpc
+ rpc.notify()
+ return
         self.muxer = None
+ if async:
+ self.muxer = async
+ Thread(target=self.mux, args=(async,)).start()
 
     def dispatch(self, dat):
- tag = dat.tag - self.mintag
- r = None
+ tag = dat.tag
+ rpc = None
         with self.lock:
- r = self.wait.get(tag, None)
- if r is None or r not in self.queue:
- print "bad rpc tag: %u (no one waiting on it)" % dat.tag
+ rpc = self.wait.get(tag, None)
+ if rpc is None or rpc not in self.queue:
+ #print "bad rpc tag: %u (no one waiting on it)" % dat.tag
                 return
- self.queue.remove(r)
- r.data = dat
- r.notify()
+ self.puttag(rpc)
+ self.queue.remove(rpc)
+ rpc.dispatch(dat)
 
     def gettag(self, r):
         tag = 0
@@ -111,16 +133,13 @@
         self.wait[tag] = r
 
         r.tag = tag
- r.data.tag = r.tag
- r.data = None
+ r.orig.tag = r.tag
         return r.tag
 
- def puttag(self, r):
- t = r.tag
- if self.wait.get(t, None) != r:
- self.fail()
- del self.wait[t]
- self.free.add(t)
+ def puttag(self, rpc):
+ if rpc.tag in self.wait:
+ del self.wait[rpc.tag]
+ self.free.add(rpc.tag)
         self.rendez.notify()
 
     def send(self, dat):
@@ -128,17 +147,20 @@
         n = self.fd.send(data)
         return n == len(data)
     def recv(self):
- data = self.fd.recv(4)
- if data:
- len = fields.Int.decoders[4](data, 0)
- data += self.fd.recv(len - 4)
- return self.process(data)
+ try:
+ with self.inlock:
+ data = self.fd.recv(4)
+ if data:
+ len = fields.Int.decoders[4](data, 0)
+ data += self.fd.recv(len - 4)
+ return self.process(data)
+ except Exception, e:
+ traceback.print_exc(sys.stdout)
+ print repr(data)
+ return None
 
- def fail():
- raise Exception()
-
- def newrpc(self, dat):
- rpc = Rpc(self, dat)
+ def newrpc(self, dat, async=None):
+ rpc = Rpc(self, dat, async)
         tag = None
 
         with self.lock:
@@ -153,11 +175,19 @@
             self.puttag(rpc)
 
 class Rpc(Condition):
- def __init__(self, mux, data):
+ def __init__(self, mux, data, async=None):
         super(Rpc, self).__init__(mux.lock)
         self.mux = mux
+ self.orig = data
+ self.data = None
+ self.waiting = False
+ self.async = async
+
+ def dispatch(self, data=None):
         self.data = data
- self.waiting = True
- self.async = False
+ if not self.async or self.waiting:
+ self.notify()
+ elif callable(self.async):
+ Thread(target=self.async, args=(self.mux, data)).start()
 
 # vim:se sts=4 sw=4 et:
diff -r f529bf0b3cce -r b63a6adce614 alternative_wmiircs/python/wmiirc
--- a/alternative_wmiircs/python/wmiirc Thu May 21 14:22:58 2009 -0400
+++ b/alternative_wmiircs/python/wmiirc Thu May 21 14:38:38 2009 -0400
@@ -65,7 +65,7 @@
 
 # End Configuration
 
-client.write('/event', 'Start wmiirc')
+client.awrite('/event', 'Start wmiirc')
 
 tags = Tags()
 bind_events({
@@ -105,7 +105,7 @@
     def exec_(self, args=''):
         wmii['exec'] = args
     def exit(self, args=''):
- client.write('/event', 'Quit')
+ client.awrite('/event', 'Quit')
 
 program_menu = Menu(histfile='%s/history.prog' % confpath[0], nhist=5000,
                     action=curry(call, 'wmiir', 'setsid',
@@ -140,7 +140,7 @@
         self.label = ''
 
     def write(self, notice):
- client.write('/event', 'Notice %s' % notice.replace('\n', ' '))
+ client.awrite('/event', 'Notice %s' % notice.replace('\n', ' '))
 
     def show(self, notice):
         if self.timer:
Received on Thu May 21 2009 - 18:38:41 UTC

This archive was generated by hypermail 2.2.0 : Thu May 21 2009 - 18:48:04 UTC