First commit

master
unknown 2013-04-30 02:49:34 -03:00
commit 2909a53756
19 changed files with 448 additions and 0 deletions

8
.gitignore vendored 100644
View File

@ -0,0 +1,8 @@
*.class
*.pyc
*.pyo
.svn
__pycache__
_svn
/.project
/.pydevproject

18
.project 100644
View File

@ -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>

7
.pydevproject 100644
View File

@ -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
CHANGES.txt 100644
View File

0
LICENSE.txt 100644
View File

0
MANIFEST.in 100644
View File

43
README.txt 100644
View File

@ -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
orun/__init__.py 100644
View File

14
orun/app.py 100644
View File

@ -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

View File

@ -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()

View File

@ -0,0 +1,5 @@
from orun import js
from orun.js import client
from . import base as Ext
from .base import *

14
orun/extjs/app.html vendored 100644
View File

@ -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>

56
orun/extjs/base.py 100644
View File

@ -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)

23
orun/extjs/cp.py 100644
View File

@ -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()

187
orun/js.py 100644
View File

@ -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))

View File

27
orun/servers/cp.py 100644
View File

@ -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()

7
orun/session.py 100644
View File

@ -0,0 +1,7 @@
class Session(dict):
def add_object(self, obj):
self['js_' + id(obj)] = obj
def create_session():
return Session()

13
setup.py 100644
View File

@ -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(),
)