bottle

Your own web Python IDE

A few years back I was wondering about editing Python in the cloud when I first got a Chromebook. At the time web based IDEs were only just starting to go mainstream; they have flourished since. How much better would it be if you could set up your own server? Writing a code editor in JavaScript is a huge undertaking but there are tools out there to do this and once you have the code the rest should be straight forward.

I wanted to try out Ace code editor for a few reasons; it is mature, supports Python (along with every other language I’m bothered about), is customizable, extensible, is licensed under a BSD licence, has an API and seemed easy to set up. So I set about creating a test rig so I could investigate the code editor with. Just getting the code editor to display without an absolute window position proved tricky (it’s always the little things that take the time) but eventually I discovered the div tag needed a height property to work the way I wanted it to.

With the editor now displaying, I really wanted to get my rig to run the code and display the result so I knew everything was working. This prompted the executing code post a couple of days ago (now you know the project I was hinting at). With a working execute function that returned the output as a string I just needed to get the text out of Ace using the method provided and back to the server.

I originally tried to do this without using any other JavaScript libraries but soon realised this was adding a lot of unnecessary and distracting script to the web page so went back to using the ever useful jQuery library to deal with the post and the updating of the results div. Surprisingly it worked on the first go.

The code (in BitBucket due to the length) uses all of the executing arbitrary code lines from the previous post but with the test now replaced with a bottle web server and a 35 line single page web app. I mixed CSS and JavaScript in with the HTML to simplify the server side code not because I recommend this or would do this in reality.

Running the code should give you an editor similar to the one below.

pyedit

Micro web frameworks

If you have ever tried writing a basic web application using the wsgi & cgi modules you’ll know that you still need to do quite a bit of standard code to achieve anything useful. And as is often the case, if you are finding yourself writing standard code time and time again the chances are other people are and have already written a library, or in this case a micro web framework. The aim of a micro web framework is to allow you to do all the common jobs with a minimum of code but not to provide you will bells and whistles, like ORM, that you would find in the bigger web frameworks.

There are quite a few micro web, or non full-stack, frameworks for Python probably because the libraries that come with Python make it easier. The main ones are Bottle, CherryPy, Flask (Python 3 support requires a few dependancy updates), itty (Python 3 has a completely different port) and Fresco. If you want a slightly out-of-date slideshow type review of these see this slideshow battle.

Probably the best one to get started with is Bottle. Installation is simply pip install bottle. This is just a single file so can be easily copied if your destination system lacks Internet access. It uses function decorators to apply the routing logic which you may not have seen before but is an elegant solution and makes the code very readable.

There is a decent tutorial page on the Bottle homepage but rather than disjointed snippets I have tried to come up a minimal example that actual does something, in this there are two pages, the default page that displays a form asking for a name and the hello page that says hello.

import bottle
boilerplate = '<html><head><title>Welcome to Bottle</title></head><body>{0}</body></html>'

@bottle.route('/')
def mainpage():
    return boilerplate.format('''<form action="hello" method="POST"> Hello friend, what is your name?
                              <input type="text" name="name"></form>''')

@bottle.post('/hello')
def greet():
    name = bottle.request.forms.get("name")
    return boilerplate.format('<p>Welcome '+name+'</p>')

bottle.run(host='localhost', port=8082,debug=True)