Python Programming, news on the Voidspace Python Projects and all things techie.

More Computer Death and PyCon UK Schedule

emoticon:podcast Well, after spending several hours reinstalling our full Resolver development environment, my computer decides that it really does have issues and shuts down altogether. Looks like the hard drive has gone. sign Now I have to go through the whole thing when the new drive arrives. Time to make a ghost I think...

On the flipside it has been fun doing Windows development on a Mac for the last two days. Laughing

The PyCon UK Talk Schedule has gone live. I'm talking at 9.30am on Saturday morning. Surprised

It means I can't get drunk on Friday evening, but at least I will get my talk out of the way and can enjoy the rest of the weekend. Smile

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2007-08-23 21:13:02 | |

Categories: , ,


Everyone's First Vi Session

emoticon:car I've just discovered Bash.org. There is some hilarious stuff there.

This one was made all the funnier due to recent enforced encounters with vim, by interns who refuse to use a proper IDE...

everyone's first vi session. ^C^C^X^X^X^XquitqQ!qdammit[esc]qwertyuiopasdfghjkl;:xwhat

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2007-08-19 20:29:42 | |

Categories: ,


Saving Files with Javascript and a Python CGI

emoticon:dove Silverlight doesn't have a save file dialog. This may change before Silverlight 1.1 comes out of alpha. In the meantime, it is very easy to provide the same functionality with a hidden form, a bit of Javascript and a Python CGI.

The first step is creating a Python CGI that can receive a filename and data posted to it, and will respond with the correct headers to trigger a save file dialog in the browser.

A save / open dialog from the browser.

The following code should do the trick!

#!/usr/local/bin/python2.4 -u

import sys
import cgitb
cgitb.enable()

import cgi
from urllib import unquote


errorhtml = '<html><head><title>Oops, invalid data...</title></head><p>Oops, invalid data...</p></html>'
serverline = "Content-Type: text/html\r\n\r\n"

responseline = '''Content-Type: application/octet-stream
Content-Disposition: attachment; filename= "%s"
Content-Length: %s

'''
. replace('\n', '\r\n')

def exit():
   sys.stdout.write(serverline)
   sys.stdout.write(errorhtml)
   sys.exit()

form = cgi.FieldStorage()

data = {}
for field in form.keys():
   if not isinstance(form[field], list):
      data[field] = form[field].value

if not 'filename' in data or not 'data' in data:
   exit()

filename = unquote(data['filename'])
file_data = unquote(data['data'])

sys.stdout.write(responseline % (filename, len(file_data)))
sys.stdout.write(file_data)

The important part in triggering the save file dialog from the browser is the headers sent in responseline. This CGI needs to be sent a 'filename' and a 'data' parameter to work.

So how do we trigger this from our code? We can use a hidden form and trigger a submission from Javascript.

Here is the html for the form:

<form name="saveform" action="/cgi-bin/savefile.py" method="POST">
    <input type="hidden" name="data" />
    <input type="hidden" name="filename" value="code.py" />
</form>

To submit this from Javascript we do the following:

document.saveform.data.value = editAreaLoader.getValue('code');
document.saveform.submit();

The call to editAreaLoader.getValue('code') is how we get the Python code out of the EditArea code editor - but you can set the hidden input field member value to whatever you want...

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2007-08-19 19:51:24 | |

Categories: , ,


Opening Files with Silverlight and the OpenFileDialog

emoticon:men One of the current limitations of Silverlight is that it comes with almost no controls. You can get round this by creating your own controls or by using Javascript controls for the view layer.

The controls it does have are in the System.Windows.Controls namespace. One of these is the OpenFileDialog.

We can use this from IronPython very easily. The API is similar to the Windows Forms OpenFileDialog.

The code to present a dialog, and read the file if the user selects one, is as follows:

from System.Windows.Controls import OpenFileDialog, DialogResult

dialog = OpenFileDialog()
dialog.Title = "Load Python File"
dialog.Filter = "Python files (*.py)|*.py|All files (*.*)|*.*"
if dialog.ShowDialog() == DialogResult.OK:
    data = dialog.SelectedFile.OpenText().ReadToEnd()

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2007-08-19 19:50:52 | |

Categories: , ,


Silverlight Web IDE 0.2.0

emoticon:fish What good is an IDE that can't save and load files? Exactly!

I've updated my example Silverlight Web IDE to allow you to load and save Python files.

Silverlight IronPython IDE with Load and Save

The project download includes a Python CGI file which is needed for saving the file. I'll explain how the loading and saving is done in the next two entries...

Warning! When you click save in IE for the first time, it will block the download. When you allow the download it will reload the page and you will lose your code! Either click save once before you start editing or make sure you save you code on the clipboard... Smile

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2007-08-19 19:49:51 | |

Categories: , ,


IsolatedStorageFile in Silverlight

emoticon:film Silverlight includes a local file store system. This can store up to 1MB per application.

The two core classes are IsolatedStorageFile and IsolatedStorageFileStream, which can be found in the System.IO.IsolatedStorage namespace.

A 'user store' can be treated like a small filesystem. You can store binary or text data in files, and create a directory structure.

The following IronPython code loads and saves text files in the IsolatedStorageFile:

from System.IO.IsolatedStorage import (
    IsolatedStorageFile, IsolatedStorageFileStream
)

from System.IO import (
    FileMode, StreamReader, StreamWriter
)


def SaveFile(name, data):
    store = IsolatedStorageFile.GetUserStoreForApplication()
    isolatedStream = IsolatedStorageFileStream(name, FileMode.OpenOrCreate, store)

    writer = StreamWriter(isolatedStream)
    writer.Write(data)

    writer.Close()
    isolatedStream.Close()
    store.Close()


def LoadFile(name):
    store = IsolatedStorageFile.GetUserStoreForApplication()
    isolatedStream = IsolatedStorageFileStream(name, FileMode.Open, store)

    reader = StreamReader(isolatedStream)
    data = reader.ReadToEnd()

    reader.Close()
    isolatedStream.Close()
    store.Close()

    return data


data = 'a long string of text'

SaveFile('test.txt', data)

print LoadFile('test.txt')

Again, this code is suitable for using in the IronPython Web IDE.

System.IO.IsolatedStorage also holds the IsolatedStorageException class.

Other useful methods and properties on IsolatedStorageFile instances include:

print store.GetFileNames('.')
store.CreateDirectory('directory_name')

print store.GetDirectoryNames('.')

print store.CurrentSize
print store.MaximumSize

You can store files in directories in the store, by passing a full path to SaveFile (you must create the directory before saving into it). LoadFile then works fine, but for some reason I've found that these files aren't listed by store.GetFileNames('directory_name'). Question

It looks like currently there is no way to delete a file, but you can save a file of length 0 over the top of them!

IsolatedStorageFile is not limited to Silverlight but is part of .NET. You can see the documentation here.

If you are interested in Silverlight, there is a Silverlight UK Blog that has posted some interesting code. Smile

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2007-08-19 15:19:11 | |

Categories: , ,


Using System.Windows.Browser.Net.BrowserHttpWebRequest

emoticon:mobile If you want more control over your requests than Downloader can offer, an alternative is to use BrowserHttpWebRequest instead.

This gives you access to the headers and allows you to make POST requests as well.

See the Silverlight Web Service QuickStart and Mike Ormond's Accessing ASP.NET Application Services for some example code.

Here is a translation of the previous example to make a synchronous 'GET' request with Silverlight. (It has the same limitation of not being able to make cross-domain calls.)

from System import Uri
from System.Windows.Browser.Net import BrowserHttpWebRequest
from System.IO import StreamReader

#help(BrowserHttpWebRequest)

uri = Uri('http://www.voidspace.org.uk')
request = BrowserHttpWebRequest(uri)

request.Method = 'GET'

response = request.GetResponse()
stream = StreamReader(response.GetResponseStream())
print stream.ReadToEnd()
stream.Close()

for item in response.Headers.Headers:
    print item, ':', response.Headers[item]

This IronPython code prints the headers from the HTTP response (and can also be tried from the IronPython Web IDE).

You can also use BrowserHttpWebRequest asynchronously, which will have to be the subject of a future example as it is now 2.22am...

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2007-08-19 02:17:37 | |

Categories: , ,


Using System.Windows.Downloader with Silverlight

emoticon:men I've been experimenting with the Downloader class and Silverlight. You can use it to fetch server resources from the browser.

You can try this code using the IronPython Web IDE.

from System import Uri
from System.Windows import Downloader

uri = Uri('http://www.voidspace.org.uk/')
dl = Downloader()

#help(Downloader)

def failed(s, e):
    print s.Status
    print s.StatusText
    print 'Failed'

def completed(s, e):
    print s.Status
    print s.StatusText
    print s.ResponseText
    print 'Completed'

def changed(s, e):
    print 'Progress changed', s.DownloadProgress

dl.DownloadFailed += failed
dl.Completed += completed
dl.DownloadProgressChanged += changed

dl.Open('GET', uri)
dl.Send()

Uncomment out the #help(Downloader) line to get an idea of the properties and methods available on Downloader.

You can't use this to make cross domain calls, but you can either implement a proxy on the server or use traditional Javascript to interact with Silverlight...

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2007-08-19 01:46:08 | |

Categories: , ,


Windows Mega-Death Badness

emoticon:music This happened last Thursday at work, but it traumatised me so badly that only now can I talk about it.

On Wednesday evening the latest round of Windows updates came in. According to the list they were just a bunch of security patches, so I applied the updates and rebooted. Windows refused to reboot. I tried again. Same result.

I tried to boot into safe mode, but Windows informed me that some essential file was corrupted or missing and it couldn't boot - I should try repair mode from the Windows CD instead.

So I trooped downstairs (we have two offices now) and fetched the Windows XP CD and tried to boot into repair mode. The bitter irony is that Windows reported the same error, and suggested I tried repair mode instead. aargh Mad

I've had to reinstall Windows, followed by reinstalling all my applications and our full development environment.

One curious thing is that the only data I needed to preserve before reinstalling Windows was my Thunderbird mail profile. I had had a couple of new emails that day that I downloaded (I don't like IMAP for some of the same reasons that I don't like gmail).

I booted from a Ubuntu live CD and copied the Thunderbird data onto a USB key. My inbox had precisely three emails in it at the time. The Thunderbird 'Inbox' file was 457 megabytes and appeared to contain every single email that has ever gone through my work inbox !?!?! What on earth is the need for that? Very odd...

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2007-08-18 22:09:49 | |

Categories:


Error 404: Road not Found

Error 404: Road not found

Via: Terminally Incoherent. Laughing

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2007-08-18 22:05:46 | |

Categories:


urllib2 Tutorial in Python Docs

emoticon:podcast As you have probably heard, the Python documentation has shifted to a new system based on ReStructured Text.

The development version of the docs for Python 2.6 are already up: Python Documentation.

This should make it easier for contributors to help with the documentation.

Simon Willison like them:

The Python docs have been redesigned for 2.6. They’re beautiful. The docs for a module are on a single page now (rather than splitting over multiple pages), they've added unobtrusive permalinks to individual sections and the whole thing is built on ReST rather than LaTeX.

One consequence that I hadn't anticipated, was that now the Python documentation is ReST based, my urllib2 HOWTO can at last be integrated into the Python docs:

Great, but it is one of the busiest pages on Voidspace. I hope this doesn't cost me traffic. Wink

Whilst on the subject of self-aggrandisement, my speaker profile has gone up on the Mix UK Speakers Page. Christian and I have also picked out the cover page for "IronPython in Action". The first part of the book should be available via Manning's early access program soon...

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2007-08-18 21:24:10 | |

Categories: , ,


Hosted by Webfaction

Counter...