Thursday, November 30, 2006

Pycon 2007: it's Crunch time

Yesterday I got some good news from the Pycon organizers: my proposed talk entitled Easy creation of interactive tutorials has been accepted. In this talk, I'll demonstrate how Crunchy can be used to create interactive Python tutorials. I've been thinking about how to organize my talk for about two months now but have not written a line yet. One thing I can say for sure at this time: this is not going to be your typical PowerPoint-type presentation. My current plan is to use Firefox for the presentation: one tab will display a fake html-based Python tutorial, the second tab will make use of codetch so that I can edit the same tutorial "live", and the third tab will display the resulting interactive tutorial as processed by Crunchy.

Monday, November 13, 2006

Rur-ple: double the number of languages

While I haven't had time to do programming in the past few months, some Rur-ple users have been busy and submitted new material. The upcoming 1.0 release of Rur-ple will include 3 new languages [Turkish (including a translation of most lessons), German and Welsh] as well as previously included languages [English (with all lessons), French and Spanish].

Inspired by the user contributions, I spent a few hours today re-writing the localization code. To add a new language now only requires the following:
  1. Adding one line in a Python file (translation.py), that specify the language and language code, as well as the name of the .po file.
  2. Creating a .po file containing the string translations.
  3. Creating an html file (rur.htm) used as a Welcome Page in that language.
The new version will also save the last language selected and will use it upon re-starting Rur-ple.

Monday, August 21, 2006

Securing Crunchy

Following my last post, some alert readers pointed out that Crunchy could be a security risk for its users. Crunchy acts as a web server, fetching html-based Python tutorials and displaying them in your browser with controls allowing to execute the Python code. This is meant as a good thing... but it might not be if the code is allowed to run automatically when the page is loaded. In fact, this might have occurred with previous (<0.7) Johannes and I changed the way that Crunchy works so as to remove any security worries - at least, we hope so. Anyone interested can obviously look at the code; for others, here's what we do:
  • Each time Crunchy starts, it generates a random session number (10 digit long).
  • The javascript code used to communicate between Crunchy and the browser is fetched from a static file and modified to include the unique session number as part of each command; a new javascript file, with a filename that incorporates the session number is generated.
  • When Crunchy fetches an html page, it processes it to remove unwanted code. This means removing all (java-)scripts and only allowing html tags that are on a "whitelist". This whitelist excludes any of the usual "onload", "oninit", etc., automatic execution.
  • Next, Crunchy interactive elements (Python interpreter, code editor, button for Python code execution, etc.) are inserted with the javascript calls, each call given a unique identifier for that session.
  • Finally, the processed page is displayed in the browser, with the server waiting for user-generated interactions.
  • This procedure is repeated for any page that is loaded during that session.
  • At the end of a session, when Crunchy is terminated, the javascript file that was generated and used in that session is deleted.
The latest version (0.7) includes this security features and many new additions [a complete list of the changes from version 0.6 is appended at the end of this message]. Currently, Johannes is working on adapting How to think like a computer scientist to use with Crunchy, as well adding new interactive features. For my part, I have been working on internationalisation issues (adding a French interface) and other configuration choices. Due to end-of-summer holidays, work on Crunchy will likely slow down for a few weeks at least but we should be able to reach version 1.0 early in the Fall.

After that, I will be ready to start implementing rur-ple inside the Crunchy environment; if there is enough interest, I might implement a turtle graphics module as well.

===== Changes from 0.6 to 0.7 ================
0. Name change
To prevent confusion with an existing program named CrunchyFrog, "Crunchy Frog" has been renamed as "Crunchy", short for "Crunchy, the Interactive Python Tutorial Maker".

1. *Security fix*
The previous versions of Crunchy allowed tutorials containing arbitrary (and hidden) javascript code to be loaded within a browser window. The new version removes any existing javascript code prior to processing for display within a browser.

Feel free to try and break this - and please report any findings back to us.

2. New functionality.
  • It is possible to run external programs from within the browser; sample demos include GUI programs with 1. Tkinter, 2. pyGtk, 3. wxPython, 4. Pygame
  • Automatic syntax colouring of (static) Python code, including (as an option) line numbering.
  • New plotting canvas with simple to use api to draw mathematical functions
  • Drawing & plotting canvas can be set to arbitrary size.
  • Multiple canvas can now appear on same page.
  • New addition and simplification to the sound api.
  • Simplification of error message (tracebacks) more suitable for beginners.
  • New plotting canvas with simple to use api to draw mathematical functions
  • Drawing & plotting canvas can be set to arbitrary size.
  • Multiple canvas can now appear on same page.
  • New addition and simplification to the sound api.
  • Simplification of error message (tracebacks) more suitable for beginners.
3. New visual design:
  • Integrated menu which can be styled through custom css
  • Three sample css styles now included (selectable via the browser menu)

4. New content:
  • First draft sound tutorial exploring concepts of frequency, beats, harmonics (Fourier series), etc.
  • New addition to the basic "Crunchy user" tutorial
  • Additions to all reference documentation (sound & graphics api, vlam options, etc.)

Friday, August 04, 2006

Exciting Crunchy News

While I knew all along it could be done, I've had a lot of fun during the last two days playing with the newest, and possibly most exciting feature of "The application formerly known as Crunchy Frog", or simply "Crunchy". It is now possible, from within a Firefox windows, to click a button and launch an external Python script. (I should mention that the bulk of this latest feature was implemented by Johannes Woolard - I just had to make a few minor changes to get it working on Windows.)

I'll provide more details later, but here's the short story. You write an html document in which you insert the Python script you want to execute inside a <pre> element with some minor markup (<pre title="external copycode">); actually, you can have as many scripts you want on any given page. Crunchy processes the page, displays the Python scripts in colour (!) and makes a copy of each available for further editing inside a <textarea>. You can then just click on a button and the script is launched.

This means that Crunchy can really transform *any* Python tutorial into an interactive experience. Crunchy can load html pages from the web (not only local ones) and perform its magic ;-)

So far, I've launched Tkinter windows, wxPython apps, Pygame programs, a terminal with a Python interpreter and, the latest, a gnuplot window that ran the gnuplot demo. You can actually have a number of independent external apps going at the same time, allowing for some interesting experiments (edit the code in the <textarea> and launch the new version).

Stay tuned for more news soon, and the announcement of the next release.

Saturday, July 22, 2006

Crunchy news

It's now been a month since my last blog post and a lot has happened in the meantime. We (Johannes and I) have just released a new version of Crunchy Frog. We were planning to do a release (version 0.5) a bit earlier but we kept "fixing this", "adding that little bit", "changing this", etc., until I felt it was well beyond what had been planned for the next release. So, after discussing briefly about it (at Johannes's request), we set up a roadmap for Crunchy Frog as a whole (as oppposed to just for Johannes' project) with a date set for the 1.0 release that would coincide with the end of this Summer of Code project for Johannes.

The new public release (0.6) looks very different from the previous public one (0.4). Crunchy now has its own site. Previously, Johannes had set up an svn repository which has come extremely handy. This summer of code project is supposed to be a learning experience from the student (Johannes) under the direction of a more experienced mentor (that would be me). However, I can say that it has been a huge learning experience for me. So far, I had only worked on my own project, and only very recently had learned to use an svn repository on my own computer. Working as part of a team (supposedly as the team leader [I have the final say, if need be]; in reality, it's pretty much a team of equals, each of us having different strengths) has been an experience in itself.

While we have settled on a roadmap, I can already see some additional features, not mentioned so far, that I would like to implement before the end of the summer. For those interesed in Crunchy Frog: stay tuned, there could be some very nice new stuff added soon.

The 0.6 release got some attention outside of "regular channels" and I just found out that there exists another Python project named CrunchyFrog (no space between the two words). This, I think, is most unfortunate and I am in a bit of a quandry as to what to do about the name. Note that the developper behind CrunchyFrog, who brought its existence to my attention, not only has not complained about me choosing this name, but has actually set up a link to Crunchy Frog on his own website. [This is something we'll definitely have to reciprocate; Johannes is responsible for the website and is taking a well deserved break after the last minute rush to get everything organised for the 0.6 release.] Nonetheless, the possibility of changing the name of the project has to be considered ... even though Johannes has designed a nice graphical interface based on a Frog theme.

With all this attention devoted to Crunchy Frog, Rur-ple's development has been suspended. However, just a few days ago, Michel Weinachter sent me
  • a "patch" so that the user-chosen language can be remembered from one session to the next;
  • an exe version, produced by py2exe, so that Windows users don't need to install Python nor wxPython to use Rur-ple;
  • some simple code to make use of a clipboard within rur-ple; I have not had time to see how to make this work though;
  • just today, a link to a Firefox extension useful to users of Crunchy Frog. This extension enables the "normal" use of a tab key within an html <textarea>, which comes in handy when typing Python code.
Merci Michel!

So, all in all, a busy month with lots of long nights of coding after work. I have a great job, which does not and never will require me to do any programming [sometimes, much to my chagrin.] However, as a hobby, programming in Python has really been a fantastic one. It is my hope that the programs I create will be found useful by others.

Thursday, June 22, 2006

Almost there: version 0.9.9 of RUR-PLE has been released

The title of this post pretty much says it all. I just need to write a few more lessons, read over once more all the existing lessons, do once more all the suggested exercises ... and, barring any surprises, I will be ready to release version 1.0 of RUR-PLE. Thus will end an adventure that started a little less than 2 years ago, as I decided to start a new hobby and learned about Python.

Sunday, June 18, 2006

Chasing an unseen bug

A few days ago I was contacted by M.H., a professor in the U.S. who teaches Introduction to Computer Programming every year and was thinking of using RUR-PLE. [Great, I thought, more user feedback to be expected.] Unfortunately, M.H. had tried the latest version and found that the code highlighting feature [described in this post] did not work.

How could I possibly find a bug that I can not reproduce? I thought... Thus began an exchange of emails that led me to find a way to reproduce the bug and, eventually, to solve it. The final solution was somewhat typical of my experience with Python: try the obvious!

These last three words are probably the best words of advice I could give to anyone who writes computer programs using Python. If you are reading this blog as a potential source of useful tips [you fool!], you should probably stop now as nothing else I will write is likely to come even close to being as useful to you.

However, if you want to get a good laugh at my expense, you are invited to continue reading.

I first started by asking M.H. what everyone always asks me when I claim to find a bug or when I don't understand the behaviour of some module and post some question on various lists.

What OS and what version of wxPython are you using?

I expected that M.H. was using Mac OS or Linux, in which case I was getting ready to diplomatically tell him that he was likely out of luck as I'm [shame on me], a Windows user. However, M.H. told me that he was using Win XP (same here), Python 2.4.3 (I'm using 2.4.2) and wxPython 2.6 (same here).

Ok. I was more stumped then ever. This was bugging me... These days, I'm working on Crunchy Frog which will, eventually, include and supersede RUR-PLE. As it is, I have a lot more ideas than time at my disposal to work on Crunchy Frog, and this "distraction" was not welcome. However, I could not ignore it.

Since I couldn't reproduce the bug, I asked M.H. if he could do me a favour and insert a print statement in the method where the line number was set for the purpose of highlighting. As I wrote the email, I had a "clever" thought. M.H. is in the U.S. He's probably using the ansi version of wxPython whereas I'm using the unicode version. I bet you something's wrong with that version... Sure enough, my first hunch was right: M.H. was using the ansi version. And the print statement was outputting the same result on his computer as it was on mine. So, if one hunch was right... I asked M.H. to install the wxPython unicode version, which he kindly agreed to.

Same result... Of course, you are no doubt thinking. However, you are not trying to quash a bug you can't even reproduce. [That's my excuse, anyway.]

At that time I was visiting my partner who, unfortunately, lives 300 km (200 mi) from where I live. Fortunately, she is extremely patient and puts up with me when I am distracted by a programming problem. I decided to install wxPython and the latest version of RUR-PLE on her computer to investigate some more.

Ooops... wxPython is now at version 2.6.3.2. I am sure the version installed on my computer is 2.6.1.0. I read over the "changes" document to see if I can find anything that I can use. There does not appear to be anything relevant. I install the new version ... sure enough, I can "see" the bug (or, should I say, I can't see anything as no highlighting is taking place).

I read the "changes" document a second (and third) time, just to be sure. No luck.

Time to dig in my code. [... Where is this object initialised?... This could have been written so much better... What was I thinking then (about a year ago)... ] After staring at the code for a while, being convinced that the highlighting information is properly set (it was working before, after all) I am convinced it is a wxPython bug that was introduced. I file a bug report and expect to leave it at that.

However, my conscience is nagging me. I decide to look at the code again, staring at the method where the highlighting updates should take place. Here it is, with a few added notes.
def update_refresh(self, robot, name):
if 'robot' in self.robot_dict: # (1)
arg = self.parent.status_bar.beeper_field, self.robot_dict['robot']._beeper_bag
event_manager.SendCustomEvent(self.parent, arg)
time.sleep(robot.delay) # (2)
wx.Yield() # (3)
self.world.DoDrawing() #(4)
self.WorldDisplay.drawImage() #(5)
if name:
self.WorldDisplay.scrollWorld(name) # (6)
self.WorldDisplay.Refresh() # (7)
wx.Yield()
  1. The information in the status bar (number of beepers carried by robot, etc.) is updated.
  2. The animation is paused at each step.
  3. Making sure other controls of the application are responsive so that the program can be paused or stopped altogether by pressing the appropriate button, etc.
  4. Update the (in-memory) image based on the latest robot action.
  5. Update the screen image.
  6. Prevent the robot from going off the screen.
  7. Refresh the screen [Refresh() is a wxPython method.]
That's it. Not much there. I refresh the screen so as to ensure that the robot world, right next to the code "window", gets updated on the screen when a new line of code is executed, and should be highlighted in the code window.

Can you see the bug?

I didn't refresh the code window. It worked before though.

How do I do this... the robot world is a ScrolledWindow whereas the code window is a StyledTextControl... Where do I find the relevant documentation...

That's when I thought of the three important words I mentioned before: try the obvious. I typed in

self.ProgramEditor.Refresh()
and launched RUR-PLE. Problem solved. I guess it was just dumb luck that this refresh statement was not required before. All I have to do now is fix the bug and update the version on sourceforge ... before I go back and rewrite the parts of the code that I didn't find easy to read just a few days ago.

Monday, June 05, 2006

Praise for Python

Sometimes, I come accross something which I really wish I could have written. Usually, I just smile, try to commit it to memory, and move on. This time, I have to quote what Jim Roskind wrote on Guido's blog:
I was initially a bit put off by the Python indentation approach (I was a grammar guy… and got used to parsing braces and parens, and didn’t like the idea of white space having so much meaning), but I soon came to love it. Eventually I came to apply one of my favorite computer science sayings to Python as an endorsement to their indentation blocking approach: “The fundamental evil in computer science is the replication of code or data.” In almost all languages I had previously worked, the indentation of code had always been a critical PART of program nesting structure (at least for the reader). As I read and wrote more Python, its use of indentation as the ONLY way to specify blocks began to look better and better. All the silly bugs related to indentation errors (misleading the human reader) were gone in Python. The redundant use in other languages of braces AS WELL AS indentation (the former to help the parser, and the latter to help the human reader) was an effective duplication of the author’s intent. That duplication in other languages, a fundamental original sin, was missing in Python. It was cool! ;-)
Yes, indeed. Python is cool. :-)

Sunday, June 04, 2006

RUR-PLE video

The kind folks from ShowMeDo had contacted me and suggested I make a demonstration video for RUR-PLE. I'm happy to announce that this has been done, and that the video now appears on the ShowMeDo website. The link to this demonstration video can be found on the right hand side side-bar for this blog. The sound quality is not all that good, but the video should give a good idea of what RUR-PLE is all about. (I will definitely need to get a better microphone for future videos, and possibly for remaking this one.)

Thursday, May 25, 2006

rur-ple bug fix for Mac and Linux users

Brad Miller uncovered a bug (hard coded windows specific path separators) in version 0.9.8.2 of rur-ple. Version 0.9.8.3 has been uploaded with required changes. Apologies to Linux and Mac users.

Summer of Code 2006

For a second year in a row, Google is paying hundreds of students to spend their summer contributing to open source projects. This is known as Summer of Code 2006. The Python Software Foundation is a mentoring organisation that is the beneficiary of 25 Summer of Code projects. Continuing on my streak of luck with Python, I am mentoring Johannes Woolard, a promising student whose project was accepted in this Summer of Code competition. Johannes has a blog, and has already started working on his project. Within the span of a day or two, he has already removed the CherryPy dependency of Crunchy Frog, which was one of my longer-term objective - but something I didn't know how to do. Kudos to Johannes!

Tuesday, May 23, 2006

Rur-ple 0.9.8.2 released

I implemented in rur-ple the "auto-indent" feature that was added to Lightning Compiler. This should be more user-friendly for beginners. I also fixed a bug that was introduced when I improved the highlighting method - it was no longer possible to run programs where robots were introduced by an instruction [e.g. Reeborg = UsedRobot()] in an otherwise empty world.

Lightning 2.1

Thanks to Milan Melena, who left a code sample on this blog, Lightning 2.1 has been released, with added auto-indent and quick fold/unfold. Next, I'll have to consider added auto-indent to rur-ple.

Monday, May 22, 2006

Rur-ple: getting closer to 1.0

Rur-ple is getting ever closer to version 1.0. I have to finish about 10 new lessons to get to version 0.9.9 after which I will do a final cleanup of the code for the 1.0 release candidate. The current version (released today) is 0.9.8.1.

Since the last release, I made two changes that should be helpful for students. The first one has been to use a scintilla feature to indicate white spaces with tiny dots as indicated in the picture below.



This should help locate problems related to blank lines with a number of spaces that does not match the indentation level; this had apparently been a problem for some students.

The second change is more significant. When I started working on rur-ple, I wanted to be able to step through the code and highlight the line of code being executed. I managed to do this only partially through a kludge.

The first step was to take the user code and add some line number information using the Python module tokenize and some complicated processing. For example, the code shown above might be re-written as follows:
def follow_right_wall():
....linenumber = 20
....if right_is_clear():
........linenumber = 21
........turn_right()
........linenumber = 22
........move()
........linenumber = 23
....elif front_is_clear():
........linenumber = 24
........move()
........linenumber = 25
....else:
........linenumber = 26
........turn_left()
........linenumber = 27

I would then call exec to execute the processed code, leaving the unprocessed one displayed in the editor window. Each time a basic instruction (like move, turn_left, pick_beeper, put_beeper) was executed, the graphical display would be updated and the corresponding line of code in the editor was highlighted. When I came up with this solution, I had only been programming with Python for a few months and thought it was rather clever.

Unfortunately it was not possible, using this method, to highlight every line being executed: only those with one of the four basic robot instructions.


The new version makes use of the Python method sys.trace to follow the execution. It is much simpler than the old version (5 lines of code instead of 33) and works much better, as can be seen on the picture on the left. It has not yet been field tested but Andy Judkis's students should do just that in the coming week.

Monday, May 15, 2006

New version of RUR-PLE (0.9.8)

After receiving some suggestions from Andy Judkis, a high school teacher who uses Rur-ple in his classes, I made the following changes to rur-ple.
  • I added an "output pane" in the robot world window. Users can now put "print" statements in their programs, and the result will appear in the output pane. This should be useful in "tracing" the program flow.
  • I added two new instructions that can be used in robot programs: input_int("optional text") and input_string("optional text: e.g. Enter your name.") This is an undocumented feature for now.
  • I fixed an obscure "bug" discovered by Andy. When the "World file" is visible, the display was not updated when giving some beepers to the robot. This did not affect in any way the program execution; furthermore, most of the time, the world file viewer was probably hidden. Still, it should now be fixed.
  • Finally, I had removed the requirement to save a program before running it. However, I had made it such that a dialog would pop up if a user was trying to quit without saving a program. Apparently, it would sometimes cause the program to hang. I could not reproduce the bug ...

Optional typechecking: fun with "with"

A while ago, prompted by various entries [1, 2, 3, 4] on Guido's blog about Adding Optional Static Typing to Python, I mused about different ways of doing this [5, 6, 7], keeping the syntax as Pythonic as possible, but at the cost of introducing a new keyword ("where"). Today's entry is written in the same spirit (i.e. just for fun), but with a different syntax, and makes use of the new "with" keyword. By itself, this blog entry is probably too brief to make much sense.

Let me start by introducing some static typing information that could be extracted from an IDE, or used by pychecker or pylint.

01 def gcd(a, b):
02 '''Returns the Greatest Common Divisor,
03 implementing Euclid's algorithm.
04 with __typecheck__:
05 assert isinstance(a, int), 'First argument must be an integer.'
06 assert isinstance(b, int), 'Second argument must be an integer.'
07 #Some doctests for good measure
08 >>> print gcd(6, 3)
09 3
07 '''
08 while a:
09 a, b = b%a, a
10 return b
The above is totally valid Python. Just like doctests can be extracted by the doctest module, the "typecheck" assertions could be extracted and used by other programs. However, as they stand, they are "totally optional".

Now, if we wanted to use the typechecking information in some module where gcd() is actually used, we would have to instruct the interpreter to do so ... here's a way we might want to write this:
1    with __typecheck__:
2 gcd()
3 some_other_useful_function()
4 # the rest of the code follows...


Granted, this is not currently valid in Python ... but its intent should be understandable!

Wednesday, May 10, 2006

Crunchy Frog 0.3

Version 0.3 of "Crunchy Frog" has been released. It can be found at
https://sourceforge.net/project/showfiles.php?group_id=125834

Crunchy Frog transforms a "traditional" Python tutorial into an interactive session within your favourite web browser. Four modes of interaction are currently possible:
1. One-liner, similar to the typical instruction at the Python interpreter.
2. Embedded Python shell, within an html page.
3. Multi-line Python code, as entered in a traditional editor, and executed by Python.
4. Solutions to doctests, as described by Jeff Elkner in a post on edu-sig.

Even though it is an early release, Crunchy Frog could probably already be useful in a classroom situation. To use it, you will also need to have installed Elementtree and CherryPy.

Suggestion: read the 6 page long "tutorial" included, using your favourite browser. Then, start Crunchy Frog, and go through the tutorial again. The whole thing should be doable in approximately 15 minutes ... if you don't spend too much time playing with the interpreter. :-)

Thursday, May 04, 2006

My first CherryPy app.

Using CherryPy, I've just created version 0.1 of "Crunchy Frog". It can be found at
https://sourceforge.net/project/showfiles.php?group_id=125834

Crunchy Frog is just a temporary name for this app. (Read the tutorial for more details.) What it does is to transform a "traditional" Python tutorial into an interactive session within your favourite web browser. Three modes of interaction are currently possible:
1. one-liner, similar to the typical instruction at the Python interpreter.
2. multi-line Python code, as entered in a traditional editor, and executed by Python.
3. Solutions to doctests, as described by Jeff Elkner in a post on edu-sig.

Crunchy Frog is more of a proof-of-concept than a serious application at this point. The code is rather messy, showing my total lack of experience with this type of program (web app). I will very likely rewrite it from scratch for the next release. To use it you will also need to have installed Elementtree (included with Python 2.5?) and CherryPy.

To try it: read the 5 (short) pages long "tutorial" included, using your favourite browser. Then, start Crunchy Frog, and go through the tutorial again. The whole thing should be doable in less than 10 minutes.

Saturday, April 29, 2006

Rur-ple 0.9.7a: bug fix

Once again, rur-ple was broken on Linux (and Mac OS); however, this time the bug was reported (only the second ever reported bug through sourceforge since Stas Z guided me to make it work on Linux for the first time!). It is now fixed :-)

There must be some other bugs, somewhere... After all, I did not use any kind of "unit tests" for most of the code. Anyone that tries to use rur-ple and find problems should feel free to report them!

As soon as I can get about a week's worth of time (and inspiration!) to write the last lessons, I will be able to finally release version 1.0. After that, watch for a new version that will use a web browser (instead of wxPython) as its graphical environment. Now, what I need is a new name for that future version...

CherryPy is great!

Inspired by Ian Bicking's HTConsole, I wanted to see if I could get a simple "Python compiler", similar to Lightning Compiler but using a browser window instead of basing it on wxPython. Having no experience with any web programming, and looking at Ian's code, I thought it would take me forever to get this going. Also, I didn't really want to have to learn about all the packages used by Ian to produce HTConsole.

After a few simple attempts with Python's webbrowser module, a fruitless query on comp.lang.python, and some wandering on the web, I came accross CherryPy. To be honest, I had heard of CherryPy before, but had never looked at it as I thought it was something I would never need.

Lo and behold, simply after reading the basic tutorials included with CherryPy, I was able to write a very small program which does pretty much the same thing that earlier versions of Lightning Compiler could do. The complete code is included below:

import cherrypy
import os
from tempfile import gettempdir
TMP_DIR = gettempdir()

class PythonRunner(object):
title = 'Play with Python'

def header(self):
return '''
<html>
<head>
<title>%s</title>
</head>
<body>
<h2>%s</h2>
''' % (self.title, self.title)

def footer(self):
return '''
</body>
</html>
'''

def index(self, code=None):
cherrypy.session['code'] = code
output = ''
if code is None:
cherrypy.session['output'] = ''
else:
tmp_filename = os.path.join(TMP_DIR, 'my_file.dat')
f = open(tmp_filename, 'w')
f.write(code)
f.close()
f_in, f_out = os.popen4("python %s"%tmp_filename)
output = "The result of"
output += "<pre><font color='blue'>%s</font></pre>is: "%code
output += "<pre><font color='green'>"
for line in f_out.readlines():
output += line
output += "</font></pre>"
cherrypy.session['output'] = output
return self.header()+'''
Type in your Python code.
<form action="index" method="GET">
<textarea name="code" rows=5 cols=80></textarea><br/>
<input type="submit" value="Run Python"/>
</form>
<br/>
%s
''' % output + self.footer()
index.exposed = True

cherrypy.root = PythonRunner()
cherrypy.config.update({'session_filter.on': True})

if __name__ == '__main__':
cherrypy.config.update(file = 'tutorial.conf')
cherrypy.server.start()
And here's what it looks like (html code simply pasted below; it doesn't work here!)

Play with Python



Type in your Python code.





The result of
def hello():
print 'Hello from CherryPy!'
hello()
a = 3
print a*3
is:
Hello from CherryPy!
9


Thank you CherryPy developpers!