-
Notifications
You must be signed in to change notification settings - Fork 211
pyjamaswithcherrypyjsonrpc2
Tested with:
- CherryPy Version 3.2.2
- Pyjamas Version 0.8 (2012-2-12)
- Arch Linux
Pyjamas server-side stuff used for JSON-RPC is located here:
- [path to pyjamas]pyjs/jsonrpc
The CherryPy related implementation is done with two files:
- [path to pyjamas]pyjs/jsonrpc/__init__.py (base class JSONRPCService)
- [path to pyjamas]pyjs/jsonrpc/cherrypy/jsonrpc (cherrypy class JSONRPCService)
You have to impelement a service class which is derived from cherrypy.jsonrpc.JSONRPCService.
Doing like this your code may look as follows:
JsonRpcServer.py:
import os
from pyjs.jsonrpc.cherrypy.jsonrpc import JSONRPCService
class JsonApplicationService(JSONRPCService):
def __init__(self, defaultPage, loglevel=0, cherrylog=False):
JSONRPCService.__init__(self, defaultPage)
self.loglevel = loglevel
self.cherrylog = cherrylog
self.add_method(self.remotecall.__name__, self.remotecall)
def _log(self, s, level=-999):
if self.loglevel >= level:
nl = os.linesep if self.cherrylog else ""
print nl + ">>>", s
def remotecall(self, param):
self._log("remotecall called with %s" % param, level=1)
ret = param # echo
return retOnce your service is ready you can apply it to CherryPy.
Here's a possibility how you can do that.
JsonRpcServer.py:
import cherrypy
import os
from optparse import OptionParser
# Import your Service class (if it is in its own file)
# from serviceclassfile import JsonApplicationService
if __name__ == "__main__":
host = "127.0.0.1"
port = 8080
parser = OptionParser()
parser.add_option("--cherrylog", action="store_true", dest="cherrylog",
help="enable cherry server logging, default=disabled", default=False)
parser.add_option("--verbose", action="store", type="int", dest="verbose", metavar="LEVEL",
help="verbose level (0=silent), default=0", default=0)
(options, args) = parser.parse_args()
for x in args[0:2]:
try:
try: port = int(x)
except: host = x
except:
pass
defaultPage = "index.html"
service = JsonApplicationService(defaultPage,
options.verbose,
options.cherrylog)
configs = {"server.socket_host":host,
"server.socket_port":int(port),
"log.screen":options.cherrylog,
"tools.encode.on":True,
"tools.encode.encoding":"utf-8",
"tools.staticdir.on":True,
"tools.staticdir.dir":os.path.abspath(os.curdir),
}
cherrypy.quickstart(service, "/", {"global":configs})Please see the CherryPy website for the configs used above.
You may put the codelines above in a file (maybe JsonRpcServer.py) and start your CherryPy server as follows:
python2 services/JsonRpcServer.py --verbose=3 --cherrylog 50111 [15/Feb/2012:07:39:52] ENGINE Listening for SIGHUP. [15/Feb/2012:07:39:52] ENGINE Listening for SIGTERM. [15/Feb/2012:07:39:52] ENGINE Listening for SIGUSR1. [15/Feb/2012:07:39:52] ENGINE Bus STARTING [15/Feb/2012:07:39:52] ENGINE Started monitor thread 'Autoreloader'. [15/Feb/2012:07:39:52] ENGINE Started monitor thread '_TimeoutMonitor'. [15/Feb/2012:07:39:52] ENGINE Serving on 127.0.0.1:50111 [15/Feb/2012:07:39:52] ENGINE Bus STARTED
You have the server running on localhost port 50111.
On the client side you have to do your pyjamas user interface as well as the JSON-RPC proxy service.
JsonRpcClient.py:
from pyjamas.JSONService import JSONProxy
from pyjamas.ui.Button import Button
from pyjamas.ui.HTML import HTML
from pyjamas.ui.HorizontalPanel import HorizontalPanel
from pyjamas.ui.Label import Label
from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.TextBox import TextBox
from pyjamas.ui.VerticalPanel import VerticalPanel
# If your server uses pyjs.jsonrpc.cherrypy.jsonrpc
# your proxy url MUST be like that
PROXYURL = "services"
class JsonRpcClient:
def onModuleLoad(self):
remotemethods = ["remotecall"]
self.remote = RemoteService(PROXYURL, remotemethods)
self.status = Label(Text="Ready, waiting for input...")
self.textbox = TextBox(Width=400)
self.buttonClear = Button("Clear", self)
self.buttonRemotecall = Button("Send to CherryPy JSON-RSP Server", self)
panel = VerticalPanel(Spacing=20)
panel.add(HTML("<h2>CherryPy JSON-RPC Client</h2>"))
panel.add(self.status)
panel.add(self.textbox)
hp = HorizontalPanel()
hp.add(self.buttonRemotecall)
hp.add(self.buttonClear)
panel.add(hp)
RootPanel().add(panel)
def onClick(self, sender):
if sender == self.buttonClear:
self.status.setText("Ready, waiting for input...")
self.textbox.setText("")
elif sender == self.buttonRemotecall:
self.status.setText("Waiting remote response...")
text = self.textbox.getText()
id = self.remote.remotecall(text, self)
def onRemoteResponse(self, response, request_info):
self.status.setText("Remote response: %s" % response)
def onRemoteError(self, code, errobj, request_info):
# onRemoteError gets the HTTP error code or 0 and
# errobj is an jsonrpc 2.0 error dict:
# {
# 'code': jsonrpc-error-code (integer) ,
# 'message': jsonrpc-error-message (string) ,
# 'data' : extra-error-data
# }
message = errobj['message']
if code != 0:
self.status.setText("HTTP error %d: %s" % (code, message))
else:
code = errobj['code']
self.status.setText("JSONRPC Error %s: %s" % (code, message))
class RemoteService(JSONProxy):
def __init__(self, url, methods):
JSONProxy.__init__(self, url, methods)The follwoing code was tested with the python-webkit-engine. Note, that the cherrypy server must be up and running.
Desktop.py:
import pyjd
from JsonRpcClient import JsonRpcClient
if __name__ == '__main__':
HOST = "http://127.0.0.1"
SERVERPORT = 50111
pyjd.setup("%s:%d/Desktop.html" % (HOST, SERVERPORT))
app = JsonRpcClient()
app.onModuleLoad()
pyjd.run()Desktop.html:
<html>
<head>
<title>CherryPY JSON-RPC Client</title>
</head>
<body bgcolor="white">
<script src="bootstrap.js" type="text/javascript"></script>
</body>
</html>Build the following code and start a browser at localhost:50111
Main.py:
import pyjd
from JsonRpcClient import JsonRpcClient
if __name__ == "__main__":
app = JsonRpcClient()
app.onModuleLoad()
pyjd.run()index.html:
<!DOCTYPE HTML>
<html>
<head>
<meta name="pygwt:module" content="Main">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>CherryPY JSON-RPC Client</title>
</head>
<body>
<script src="bootstrap.js" type="text/javascript"></script>
<iframe id='__pygwt_historyFrame'
style='width:0;height:0;border:0;display:none;'></iframe>
</body>
</html>YOURDIR/JsonRpcCLient.py YOURDIR/Desktop.py YOURDIR/Main.py YOURDIR/public/index.html YOURDIR/public/Desktop.html YOURDIR/public/services/JsonRpcServer.py
In YOURDIR do
PATH_TO_PYJAMAS/bin/pyjsbuild --cache-buster --no-compile-inplace Main
In YOURDIR do
cd output; python2 services/JsonRpcServer.py --verbose=3 50111
In YOURDIR do
PATH_TO_PYJAMAS/bin/pyjd Desktop.py
Open a browser at localhost:50111