import os, sys, socket, threading, grp, select
import types, pprint, traceback
import pickle, struct
+from . import perf as mperf
__all__ = ["repl", "perf", "listener", "unixlistener", "tcplistener", "listen"]
"""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.echo(eval(ccode, self.mod.__dict__))
self.cl.send(b"+OK\n")
except:
- for line in traceback.format_exception(*sys.exc_info()):
- self.cl.send(b" " + line.encode("utf-8"))
+ lines = ("".join(traceback.format_exception(*sys.exc_info()))).split("\n")
+ while len(lines) > 0 and lines[-1] == "": lines = lines[:-1]
+ for line in lines:
+ self.cl.send(b" " + line.encode("utf-8") + b"\n")
self.cl.send(b"+EXC\n")
def handle(self, buf):
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
def bindob(self, id, ob):
if not hasattr(ob, "pdm_protocols"):
- raise ValueError("Object does not support PDM introspection")
+ raise mperf.nosuchname("Object does not support PDM introspection")
try:
proto = ob.pdm_protocols()
except Exception as exc:
def bind(self, id, module, obnm):
resmod = sys.modules.get(module)
if resmod is None:
- self.send("-", ImportError("No such module: %s" % module))
+ self.send("-", mperf.nosuchname("No such module: %s" % module))
return
try:
ob = getattr(resmod, obnm)
except AttributeError:
- self.send("-", AttributeError("No such object: %s" % obnm))
+ self.send("-", mperf.nosuchname("No such object: %s" % obnm))
return
try:
proto = self.bindob(id, ob)
return None
ob, protos = ob
if proto not in protos:
- self.send("-", ValueError("Object does not support that protocol"))
+ self.send("-", mperf.nosuchproto("Object does not support that protocol: " + proto))
return None
return ob
try:
ob = src.lookup(obnm)
except KeyError as exc:
- self.send("-", exc)
+ self.send("-", mperf.nosuchname(obnm))
return
try:
proto = self.bindob(tgtid, ob)