Skip to content

neyer/webalchemy

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Alt Webalchemy

MIT licensed. Powered by Pythonium and Tornado. Some examples:

Contributions and feedback are welcome! Open a pull request, open an issue, mail me, or just post on the mailing list.

##Getting Started

###Installation

  • Make sure you use Python3
  • Copy the webalchemy directory to your project root directory (yeah, poorman's install, never fails!)
  • no external dependencies, all Pure Python, all included. Arriving to PIP soon :)

###Tutorial and Documentation

A Webalchemy application is a regular Python class (no need to inherit anything) that provides relevant methods used by the Webalchemy server. The only required method is initialize, which is called when the client side is ready for automation. Here we create a header and append it to the document body:

class HellowWorldApp:
    def initialize(self, **kwargs):
        kwargs['remote_document'].body.element(h1='Hello World!!!')

to serve through a websocket just feed it to the run function and set your browser to http://127.0.0.1:8080

from webalchemy import server
server.run(HellowWorldApp)

Try changing the header text and save the file, see how the client changes accordingly. Lets put some style:

class HellowWorldApp:
    def initialize(self, **kwargs):
        h1 = kwargs['remote_document'].body.element(h1='Hello World!!!')
        h1.style(
            color='#FF0000',
            marginLeft='75px',
            marginTop='75px',
            background='#00FF00'
        )

Want to use css rules to style all h1`s? no problem!

class HellowWorldApp:
    def initialize(self, **kwargs):
        self.rdoc = kwargs['remote_document']
        self.rdoc.body.element(h1='Hello World!!!')
        self.rdoc.body.element(h1='--------------')
        self.rdoc.stylesheet.rule('h1').style(
            color='#FF0000',
            marginLeft='75px',
            marginTop='75px',
            background='#00FF00'
        )

Lets add a click listener by using the events property of elements:

self.rdoc.body.element(h1='Hello World!!!').events.add(click=self.clicked, translate=True)

in the following simple event each click deletes the 1st letter of the heading. This is run client side, it is translated to JS behind the scenes:

def clicked(self):
    self.textContent = self.textContent[1:]

If we want to notify the server that the button was clicked we can use an RPC call from the client to the server. The function above should be added one line:

def clicked(self):
    self.textContent = self.textContent[1:]
    rpc(self.handle_click_on_backend, 'some message', 'just so you see how to pass paramaters')

In the server we can do something like this:

def handle_click_on_backend(self, sender_id, m1, m2):
    self.rdoc.body.element(h1=m1+m2)

Now the whole program looks like this:

class HellowWorldApp:
    def initialize(self, **kwargs):
        self.rdoc = kwargs['remote_document']
        self.rdoc.body.element(h1='Hello World!!!').events.add(click=self.clicked, translate=True)
        self.rdoc.body.element(h2='--------------')
        self.rdoc.stylesheet.rule('h1').style(
            color='#FF0000',
            marginLeft='75px',
            marginTop='75px',
            background='#00FF00'
        )

    def clicked(self):
        self.textContent = self.textContent[1:]
        rpc(self.handle_click_on_backend, 'some message', 'just so you see how to pass paramaters')

    def handle_click_on_backend(self, sender_id, m1, m2):
        self.rdoc.body.element(h1=m1+m2)

This how you push and pull data to and from the client. Now you may wonder if it's dangerous for the client to be able to call any function on the server. Well actually the client can only call registered functions. In our case handle_click_on_backend got registered when we assigned it to the rpc() call on the client.

####Including external scripts

no need to require :)

class ThreeDEarth:

    include = ['https://rawgithub.com/mrdoob/three.js/master/build/three.min.js']

    def initialize(self, **kwargs):
        # do something cool here!

####Further help

Join the mailing list.

webalchemy supports the MVC pattern, usage of existing HTML, and much more. All this missing documentation is WIP. Meanwhile take a look in the examples below. I also suggest you play a bit, try making a few containers - you can spread them across multiple Python files. It's not too complicated :)

See examples below, they demonstrate a lot more than the above. Further docs and tutorials are WIP

####Example 1: Realtime Meteor Colors:

We "translated" Meteor colors app to webalchemy. The app can be seen in action here and the Meteor original here. The source is in the examples directory (here), it can be executed like this:

from webalchemy import server
from webalchemy.examples.colors_meteor_example import ColorsMeteorApp
server.run(ColorsMeteorApp)

Note this example still contains a bit of JS, it will be translated to pure Python soon.

####Example 2: TodoMVC:

This is a client-only app. It can be served from a websocket like this:

from webalchemy import server
from webalchemy.examples.todomvc.todomvc import AppTodoMvc as app
server.run(app)

or it can be "frozen" to be served from a static folder (see live demo)like this:

from webalchemy import server
from webalchemy.examples.todomvc.todomvc import AppTodoMvc as app
server.generate_static(app, writefile='todomvc.html')

more on this app here

####Example 3: WebGL Earth:

from webalchemy import server
from webalchemy.examples.three_d_earth.three_d_earth import ThreeDEarth
server.run(ThreeDEarth)

see frozen app here and source here

##Philosophy

The main idea is to write all server-side code and automate the client using proxy objects. This works well for all kinds of apps. For e.g. if you want 100% client side, just tell the server to generate or serve the client code. If you want 99% server then don't use any client code except for passing events to the server, which will decide what to do. This is like the opposite of what Meteor does, but seems to have several advantages. The best advantage is that you get to enjoy all the Python ecosystem on the server. Want to do some number crunching, machine learning, natural language analysis, or cartography? No problem! Other advantages are server-side code and HTML generation, Python on client side, scaling with ZMQ, etc.

##What to expect:

  • Documentation :)
  • Major cleanup
  • asyncio and AutobahnPython to replace Tornado in Python3.4
  • pyzmq for some real scalability, like with IPython
  • Data binding for general usage, not just the DOM. Use it with pixi.js sprites, use it to bind server-side model with client side model, etc.

About

Modern web development with Python

Resources

License

Stars

Watchers

Forks

Packages

No packages published