First commit
commit
2909a53756
|
@ -0,0 +1,8 @@
|
||||||
|
*.class
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
.svn
|
||||||
|
__pycache__
|
||||||
|
_svn
|
||||||
|
/.project
|
||||||
|
/.pydevproject
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>orun</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.python.pydev.PyDevBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>com.aptana.projects.webnature</nature>
|
||||||
|
<nature>org.python.pydev.pythonNature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<?eclipse-pydev version="1.0"?>
|
||||||
|
|
||||||
|
<pydev_project>
|
||||||
|
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
|
||||||
|
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
|
||||||
|
</pydev_project>
|
|
@ -0,0 +1,43 @@
|
||||||
|
====
|
||||||
|
Orun
|
||||||
|
====
|
||||||
|
|
||||||
|
Orun (Object RUNtime) is a small/lightweight library that provides a fast
|
||||||
|
and full way to build Python RIA, the client communicates with the server
|
||||||
|
through ajax. Typical usage often looks like this::
|
||||||
|
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# Cherrypy + ExtJS example
|
||||||
|
|
||||||
|
from orun.extjs import *
|
||||||
|
from orun.extjs import cp
|
||||||
|
|
||||||
|
def ok_click(id, *args, **kwargs):
|
||||||
|
cli << Ext.getCmp(id).setText('Clicked')
|
||||||
|
cli << js.client.alert('Server side message')
|
||||||
|
|
||||||
|
def button_click(id, *args, **kwargs):
|
||||||
|
js.write("""
|
||||||
|
Ext.getCmp("%s").setText('Clicked');
|
||||||
|
alert('Server side callback message');
|
||||||
|
""" % id)
|
||||||
|
|
||||||
|
class MyApplication(cp.ExtApplication):
|
||||||
|
def main(self, *args, **kwargs):
|
||||||
|
wnd = Ext.create('widget.window', {'title': 'My Window', 'width': 300, 'height': 250,
|
||||||
|
'items': [{'xtype': 'button', 'text': 'Click Here', 'handler': button_click}],
|
||||||
|
'buttons': [
|
||||||
|
{'text': 'OK', 'handler': ok_click},
|
||||||
|
{'text': 'Close', 'handler': js.function('this.up("window").close();')}]})
|
||||||
|
wnd.show()
|
||||||
|
wnd.setHeight(200)
|
||||||
|
|
||||||
|
app = MyApplication('Orun (ExtJS Application)')
|
||||||
|
app.run()
|
||||||
|
|
||||||
|
The example above, runs cherrypy application on 8080 http port, and exposes
|
||||||
|
extjs method.
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
from orun import js
|
||||||
|
|
||||||
|
class Application(object):
|
||||||
|
AJAX_URL = '/ajax_callback'
|
||||||
|
|
||||||
|
def __init__(self, title=''):
|
||||||
|
self.title = title
|
||||||
|
|
||||||
|
def main(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
js.AJAX_URL = self.AJAX_URL
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
from orun.extjs import *
|
||||||
|
from orun.extjs import cp
|
||||||
|
|
||||||
|
def ok_click(id, *args, **kwargs):
|
||||||
|
cli << Ext.getCmp(id).setText('Clicked')
|
||||||
|
cli << js.client.alert('Server side message')
|
||||||
|
|
||||||
|
def button_click(id, *args, **kwargs):
|
||||||
|
js.write("""
|
||||||
|
Ext.getCmp("%s").setText('Clicked');
|
||||||
|
alert('Server side callback message');
|
||||||
|
""" % id)
|
||||||
|
|
||||||
|
class MyApplication(cp.ExtApplication):
|
||||||
|
def main(self, *args, **kwargs):
|
||||||
|
wnd = Ext.create('widget.window', {'title': 'My Window', 'width': 300, 'height': 250,
|
||||||
|
'items': [{'xtype': 'button', 'text': 'Click Here', 'handler': button_click}],
|
||||||
|
'buttons': [
|
||||||
|
{'text': 'OK', 'handler': ok_click},
|
||||||
|
{'text': 'Close', 'handler': js.function('this.up("window").close();')}]})
|
||||||
|
wnd.show()
|
||||||
|
wnd.setHeight(200)
|
||||||
|
|
||||||
|
app = MyApplication('Orun (ExtJS Application)')
|
||||||
|
app.run()
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
from orun import js
|
||||||
|
from orun.js import client
|
||||||
|
from . import base as Ext
|
||||||
|
from .base import *
|
|
@ -0,0 +1,14 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<title>%s</title>
|
||||||
|
<script src="http://cdn.sencha.com/ext/gpl/4.2.0/ext-all.js"></script>
|
||||||
|
<link rel="stylesheet" href="http://cdn.sencha.com/ext/gpl/4.2.0/resources/ext-theme-classic/ext-theme-classic-all.css">
|
||||||
|
<script>
|
||||||
|
Ext.onReady(function () {
|
||||||
|
%s
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
|
@ -0,0 +1,56 @@
|
||||||
|
|
||||||
|
import json
|
||||||
|
from . import js
|
||||||
|
|
||||||
|
__all__ = ['create', 'createByAlias', 'Component']
|
||||||
|
|
||||||
|
def js_ajax(fn):
|
||||||
|
i = id(fn)
|
||||||
|
js.live_methods[i] = fn
|
||||||
|
return js.client.Ext.Ajax.request({'url': js.AJAX_URL, 'method': 'GET', 'params': {'fn': i, 'id': js.client.this.id}, 'success': js.function('eval(arguments[0].responseText);')})
|
||||||
|
|
||||||
|
js.js_ajax = js_ajax
|
||||||
|
|
||||||
|
def _create(meth, name, args):
|
||||||
|
#args['pyLive'] = True : TODO
|
||||||
|
obj = Component(**args)
|
||||||
|
js.write('var %s = Ext.create("%s", %s);' % (obj._id, name, str(obj)))
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def create(name, args={}):
|
||||||
|
return _create('create', name, args)
|
||||||
|
|
||||||
|
def createByAlias(alias, args={}):
|
||||||
|
return _create('createByAlias', alias, args)
|
||||||
|
|
||||||
|
def get(id):
|
||||||
|
return js.JsNode('Ext.get("%s")' % id)
|
||||||
|
|
||||||
|
def getCmp(id):
|
||||||
|
return js.JsNode('Ext.getCmp("%s")' % id)
|
||||||
|
|
||||||
|
class Component(js.JsObject):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(Component, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def _update(self, config):
|
||||||
|
def get_obj(value):
|
||||||
|
if isinstance(value, dict):
|
||||||
|
return Component(**v)
|
||||||
|
elif isinstance(value, (list, tuple)):
|
||||||
|
return [get_obj(v) for v in value]
|
||||||
|
else:
|
||||||
|
return value
|
||||||
|
cfg = {}
|
||||||
|
for k, v in config.items():
|
||||||
|
cfg[k] = get_obj(v)
|
||||||
|
super(Component, self).update(cfg)
|
||||||
|
|
||||||
|
def down(self, item):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def up(self, item):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return json.dumps(self._js, default=js._encoder)
|
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
import os
|
||||||
|
from orun.extjs import *
|
||||||
|
from orun.servers import cp
|
||||||
|
|
||||||
|
class ExtApplication(cp.Application):
|
||||||
|
def index(self, *args, **kwargs):
|
||||||
|
f = open(os.path.join(os.path.dirname(__file__), 'app.html')).read()
|
||||||
|
self.main()
|
||||||
|
return f % (self.title, str(js.js_manager))
|
||||||
|
index.exposed = True
|
||||||
|
|
||||||
|
def ajax_callback(self, *args, **kwargs):
|
||||||
|
fn = kwargs.pop('fn')
|
||||||
|
if fn:
|
||||||
|
fn = js.live_methods[int(fn)]
|
||||||
|
fn(*args, **kwargs)
|
||||||
|
return str(js.js_manager)
|
||||||
|
ajax_callback.exposed = True
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app = ExtApplication('Orun (ExtJS Application)')
|
||||||
|
app.run()
|
|
@ -0,0 +1,187 @@
|
||||||
|
|
||||||
|
import types
|
||||||
|
import json
|
||||||
|
|
||||||
|
AJAX_URL = '/ajax_callback'
|
||||||
|
js_manager = None
|
||||||
|
js_ajax = None
|
||||||
|
|
||||||
|
live_methods = {}
|
||||||
|
|
||||||
|
def _encoder(o):
|
||||||
|
if isinstance(o, JsObject):
|
||||||
|
return o._js
|
||||||
|
elif isinstance(o, JsNode):
|
||||||
|
return block(str(o))
|
||||||
|
elif isinstance(o, types.FunctionType) and js_ajax:
|
||||||
|
return function(js_ajax(o))
|
||||||
|
|
||||||
|
def encode(o):
|
||||||
|
if isinstance(o, JsNode):
|
||||||
|
return str(o)
|
||||||
|
elif isinstance(o, (list, tuple)):
|
||||||
|
return '[%s]' % ','.join([encode(i) for i in o])
|
||||||
|
else:
|
||||||
|
return json.dumps(o, default=_encoder)
|
||||||
|
|
||||||
|
# trick json serialize javascript block
|
||||||
|
class JsBlock(int):
|
||||||
|
def __new__(cls, *args, **kwargs):
|
||||||
|
obj = super(JsBlock, cls).__new__(cls, 0)
|
||||||
|
obj.code = args[0]
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def __str__(cls):
|
||||||
|
return cls.code
|
||||||
|
|
||||||
|
class JsFunction(JsBlock):
|
||||||
|
def __str__(cls):
|
||||||
|
return 'function () { %s }' % cls.code
|
||||||
|
|
||||||
|
block = JsBlock
|
||||||
|
func = function = JsFunction
|
||||||
|
|
||||||
|
def write(code):
|
||||||
|
if js_manager:
|
||||||
|
js_manager.write(str(code))
|
||||||
|
|
||||||
|
def __lshift__(self, value):
|
||||||
|
print('test')
|
||||||
|
|
||||||
|
class JsManager(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.output = []
|
||||||
|
|
||||||
|
def write(self, data):
|
||||||
|
self.output.append(data)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
s = '\n'.join(output)
|
||||||
|
output = self.output[:]
|
||||||
|
return s
|
||||||
|
|
||||||
|
class JsNode(object):
|
||||||
|
def __init__(self, name='', parent=None):
|
||||||
|
if parent and parent.name:
|
||||||
|
self.name = parent.name + '.' + name
|
||||||
|
else:
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
return JsNode(attr, self)
|
||||||
|
|
||||||
|
def __setattr__(self, attr, value):
|
||||||
|
if attr == 'name':
|
||||||
|
super(JsNode, self).__setattr__(attr, value)
|
||||||
|
else:
|
||||||
|
value = encode(value)
|
||||||
|
if self is client.var:
|
||||||
|
s = 'var %s = %s' % (attr, value)
|
||||||
|
else:
|
||||||
|
name = self.name + '.' if self.name else ''
|
||||||
|
s = '%s%s = %s' % (name, attr, value)
|
||||||
|
write(s)
|
||||||
|
|
||||||
|
def __add__(self, other):
|
||||||
|
return JsNode('%s + %s' % (encode(self), encode(other)))
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
return JsNode('%s - %s' % (encode(self), encode(other)))
|
||||||
|
|
||||||
|
def __mul__(self, other):
|
||||||
|
return JsNode('%s * %s' % (encode(self), encode(other)))
|
||||||
|
|
||||||
|
def __truediv__(self, other):
|
||||||
|
return JsNode('%s / %s' % (encode(self), encode(other)))
|
||||||
|
|
||||||
|
def __call__(self, *args, **kwargs):
|
||||||
|
l = []
|
||||||
|
d = []
|
||||||
|
for arg in args:
|
||||||
|
l.append(encode(arg))
|
||||||
|
for k, v in kwargs.items():
|
||||||
|
d.append('%s=%s' % (k, encode(v)))
|
||||||
|
_args = []
|
||||||
|
if l:
|
||||||
|
_args.extend(l)
|
||||||
|
if d:
|
||||||
|
_args.extend(d)
|
||||||
|
s = '%s(%s)' % (self.name, ','.join(_args))
|
||||||
|
self.name = s
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
class JsClient(JsNode):
|
||||||
|
def __init__(self, name='', parent=None):
|
||||||
|
if parent and parent.name:
|
||||||
|
self.name = parent.name + '.' + name
|
||||||
|
else:
|
||||||
|
self.name = name
|
||||||
|
self.__dict__['var'] = JsNode('var')
|
||||||
|
|
||||||
|
def __lshift__(self, other):
|
||||||
|
write(other)
|
||||||
|
|
||||||
|
class JsObjectNode(JsNode):
|
||||||
|
def __call__(self, *args, **kwargs):
|
||||||
|
super(JsObjectNode, self).__call__(*args, **kwargs)
|
||||||
|
write(str(self))
|
||||||
|
|
||||||
|
class JsObject(object):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self._loading = True
|
||||||
|
self._id = 'js_%s' % id(self)
|
||||||
|
self._create()
|
||||||
|
self._js = kwargs
|
||||||
|
self._loading = False
|
||||||
|
|
||||||
|
def _create(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _update(self, config):
|
||||||
|
self._js.update(config)
|
||||||
|
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
if not self.__dict__.get('_loading', True):
|
||||||
|
if attr in self._js:
|
||||||
|
return self._js.get(attr)
|
||||||
|
else:
|
||||||
|
return JsObjectNode(attr, JsNode(self._id))
|
||||||
|
|
||||||
|
def __setattr__(self, attr, value):
|
||||||
|
if '_js' in self.__dict__ and not attr in self.__dict__:
|
||||||
|
self[attr] = value
|
||||||
|
else:
|
||||||
|
super(JsObject, self).__setattr__(attr, value)
|
||||||
|
|
||||||
|
def __setitem__(self, attr, value):
|
||||||
|
if not self._loading:
|
||||||
|
write('%s.%s = %s' % (self._id, attr, json.dumps(value)))
|
||||||
|
self._js[attr] = value
|
||||||
|
|
||||||
|
def load(filename, klass=JsObject):
|
||||||
|
return klass(**json.load(open(filename)))
|
||||||
|
|
||||||
|
cli = client = JsClient()
|
||||||
|
|
||||||
|
def call(self, *args):
|
||||||
|
print('call')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
class MyManager(JsManager):
|
||||||
|
def write(self, code):
|
||||||
|
print(code)
|
||||||
|
js_manager = MyManager()
|
||||||
|
write(client.console.log('test'))
|
||||||
|
n = JsNode('console')
|
||||||
|
write(n.print(n.log({'id': 'item id'})))
|
||||||
|
client.var.x = 1
|
||||||
|
client.x.y = client.window.open('http://www.google.com')
|
||||||
|
client << client.x.y()([client.x])
|
||||||
|
client << client.Ext.create('window', {'left': 10})
|
||||||
|
client << client.x
|
||||||
|
|
||||||
|
# test block
|
||||||
|
print(json.dumps({'click': call}, default=_encoder))
|
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
import cherrypy
|
||||||
|
from orun import js
|
||||||
|
from orun import app
|
||||||
|
|
||||||
|
class Application(app.Application):
|
||||||
|
def index(self):
|
||||||
|
return 'Orun application server is running'
|
||||||
|
index.exposed = True
|
||||||
|
|
||||||
|
def run(self, port=8080, config=None):
|
||||||
|
super(Application, self).run()
|
||||||
|
cherrypy.quickstart(self, '/', config)
|
||||||
|
|
||||||
|
class JsManager(object):
|
||||||
|
def write(self, data):
|
||||||
|
cherrypy.response.body.append(data)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return ';\n'.join(cherrypy.response.body) + ';'
|
||||||
|
|
||||||
|
# Auto start cherrypy javascript manager
|
||||||
|
js.js_manager = JsManager()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app = Application()
|
||||||
|
app.run()
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
class Session(dict):
|
||||||
|
def add_object(self, obj):
|
||||||
|
self['js_' + id(obj)] = obj
|
||||||
|
|
||||||
|
def create_session():
|
||||||
|
return Session()
|
|
@ -0,0 +1,13 @@
|
||||||
|
from distutils.core import setup
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='Orun',
|
||||||
|
version='0.1.0',
|
||||||
|
author='Alexandre L. Dias',
|
||||||
|
author_email='alexandre@katrid.com',
|
||||||
|
packages=['orun', 'orun.test'],
|
||||||
|
url='http://pypi.python.org/pypi/Orun/',
|
||||||
|
license='LICENSE.txt',
|
||||||
|
description='Orun (Object RUNtime) Python JavaScript RIA framework.',
|
||||||
|
long_description=open('README.txt').read(),
|
||||||
|
)
|
Loading…
Reference in New Issue