August 31, 2009

Kay で pyjamas を使う

日本語の情報もできたのでちょっと変わり種をやります。

Python 版 GWT である pyjamas を Kay と組み合わせてみました.. と言っても jsonrpc の簡単なサンプルを動かしただけですが。

Pyjamas をインストールした場所を ${PYJAMAS_HOME} と、プロジェクトのディレクトリを ${PROJECT_DIR} として進めましょう。

${PYJAMAS_HOME}/examples/jsonrpc をいじって使います。public 以下は JSONRPCExample.html だけ必要みたい。


$ tree kay-pyjamas-sample
kay-pyjamas-sample
|-- JSONRPCExample.py
`-- public
`-- JSONRPCExample.html

1 directory, 2 files


JSONRPCExample.py を下記のように少しいじります。

import pyjd # dummy in pyjs

from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.TextArea import TextArea
from pyjamas.ui.Label import Label
from pyjamas.ui.Button import Button
from pyjamas.ui.HTML import HTML
from pyjamas.ui.VerticalPanel import VerticalPanel
from pyjamas.ui.HorizontalPanel import HorizontalPanel
from pyjamas.ui.ListBox import ListBox
from pyjamas.JSONService import JSONProxy

class JSONRPCExample:
def onModuleLoad(self):
self.TEXT_WAITING = "Waiting for response..."
self.TEXT_ERROR = "Server Error"
self.METHOD_ECHO = "Echo"
self.METHOD_REVERSE = "Reverse"
self.METHOD_UPPERCASE = "UPPERCASE"
self.METHOD_LOWERCASE = "lowercase"
self.methods = [self.METHOD_ECHO, self.METHOD_REVERSE, self.METHOD_UPPERCASE, self.METHOD_LOWERCASE]

self.remote_py = EchoServicePython()

self.status=Label()
self.text_area = TextArea()
self.text_area.setText("""{'Test'} [\"String\"]
\tTest Tab
Test Newline\n
after newline
""" + r"""Literal String:
{'Test'} [\"String\"]
""")
self.text_area.setCharacterWidth(80)
self.text_area.setVisibleLines(8)

self.method_list = ListBox()
self.method_list.setName("hello")
self.method_list.setVisibleItemCount(1)
for method in self.methods:
self.method_list.addItem(method)
self.method_list.setSelectedIndex(0)

method_panel = HorizontalPanel()
method_panel.add(HTML("Remote string method to call: "))
method_panel.add(self.method_list)
method_panel.setSpacing(8)

self.button_py = Button("Send to Python Service", self)

buttons = HorizontalPanel()
buttons.add(self.button_py)
buttons.setSpacing(8)

info = """

JSON-RPC Example


This example demonstrates the calling of server services with
JSON-RPC.


Enter some text below, and press a button to send the text
to an Echo service on your server. An echo service simply sends the exact same text back that it receives.

"""

panel = VerticalPanel()
panel.add(HTML(info))
panel.add(self.text_area)
panel.add(method_panel)
panel.add(buttons)
panel.add(self.status)

RootPanel().add(panel)

def onClick(self, sender):
self.status.setText(self.TEXT_WAITING)
method = self.methods[self.method_list.getSelectedIndex()]
text = self.text_area.getText()
id = -1
if method == self.METHOD_ECHO:
id = self.remote_py.echo(text, self)
elif method == self.METHOD_REVERSE:
id = self.remote_py.reverse(text, self)
elif method == self.METHOD_UPPERCASE:
id = self.remote_py.uppercase(text, self)
elif method == self.METHOD_LOWERCASE:
id = self.remote_py.lowercase(text, self)
if id<0:
self.status.setText(self.TEXT_ERROR)

def onRemoteResponse(self, response, request_info):
self.status.setText(response)

def onRemoteError(self, code, message, request_info):
self.status.setText("Server Error or Invalid Response: ERROR %d - %s" %
(code, message))


class EchoServicePython(JSONProxy):
def __init__(self):
JSONProxy.__init__(self, "/json", ["echo", "reverse", "uppercase", "lowercase"])

if __name__ == '__main__':
# for pyjd, set up a web server and load the HTML from there:
# this convinces the browser engine that the AJAX will be loaded
# from the same URI base as the URL, it's all a bit messy...
pyjd.setup("http://127.0.0.1/examples/jsonrpc/public/JSONRPCExample.html")
app = JSONRPCExample()
app.onModuleLoad()
pyjd.run()


そしたらそのディレクトリに入ってコンパイルします。今回はターゲットを直
接 ${PROJECT_DIR}/media にしてしまいます。


$ cd kay-pyjamas-sample
$ ${PYJAMAS_HOME}/bin/pyjsbuild -o ${PROJECT_DIR}/media JSONRPCExample.py


成功すると ${PROJECT_DIR}/media/JSONRPCExample.html が出来ます。
http://localhost:8080/media/JSONRPCExample.html で画面が出ていればまあ成功です。

サーバーサイドは下記の通りにします。myapp はアプリケーション名に読み換
えてくださいね。

${PROJECT_DIR}/myapp/urls.py

# -*- coding: utf-8 -*-
# myapp.urls


from werkzeug.routing import (
Map, Rule, Submount,
EndpointPrefix, RuleTemplate,
)
import myapp.views

def make_rules():
return [
EndpointPrefix('myapp/', [
Rule('/', endpoint='index'),
Rule('/json', endpoint='json_rpc'),
]),
]

all_views = {
'myapp/index': myapp.views.index,
'myapp/json_rpc': myapp.views.json_rpc,
}


最後に view です。

${PROJECT_DIR}/myapp/views.py

# -*- coding: utf-8 -*-
# myapp.views
# ... 省略

import simplejson

# ... 省略

def json_uppercase(args):
return [args[0].upper()]

def json_echo(args):
return [args[0]]

def json_reverse(args):
return [args[0][::-1]]

def json_lowercase(args):
return [args[0].lower()]

def json_rpc(request):
if request.method:
args = simplejson.loads(request.data)
method_name = 'json_%s' % args[u"method"]
json_func = globals().get(method_name)
json_params = args[u"params"]
json_method_id = args[u"id"]
result = json_func(json_params)
args.pop(u"method")
args["result"] = result[0]
args["error"] = None
return Response(simplejson.dumps(args), content_type="application/json")
else:
return Response('Error')



適当な作りですが、まあこれで動きます。興味があれば色々工夫してみてくだ
さい。

今日はここでおしまいです。

No comments: