Posts

Showing posts with the label website

Why Firefox 13 'load tabs on demand' is bad UX.

With the new firefox 13, on start-up it does not reload all of the tabs at once. Theoretically this means firefox loads faster.  Since it only needs to load one website when you restore, not all of them. This is a great example of a UX/UI app experience that seems good for users, but is in fact bad.  This comes up quite often when optimizing applications, and I have even done this style of optimization in the past.  So I'm using this as a case study in why doing this is not good from a UX perspective. The Scenario. I have 8 tabs, and I'm using most of them. Old firefox behaviour. Firefox loads, I go away whilst it loads itself, then loads all 8 tabs. I wait .  It takes a while to load - but some stuff can be loaded at the same time, in parallel.  If they are fast pages it is pretty much instant, and I can get to work. If they are slow pages, then I have to wait once until they are all loaded.  I can go off and do something el...

The secret to my web development productivity...

Image
Can you see the secret to my web development productivity in this photo? No it's not the red cup of coffee. It's not the pieces of sticky tape on my laptop. Follow the cable from my laptop... and have a look under the desk. ... ... I'll wait whilst you have a look before telling you the answer. ... That's right!!! ... it's a joypad. Using python and pygame, I've made a little app which listens for joystick events, and then deploys the website I'm working on. With a mash, kick or prod of my foot, up goes my website. Deployed. Deploy is just a fancy word for 'upload my website, do database migrations, restart app servers, run tests, rollback if there are failures... etc'. For 5 british pounds, $7.8 USD, or 5.74 euros, you can get one of these joypads delivered to most places these days. It's giving me too much pleasure pressing it every time I want to upload a new version of the website. Most live updates EVER today - and I have the joypad to tha...

Using a html form as the model.

Image
I've mentioned this technique before, but I think it is worth repeating more clearly. Without any other code clouding the main message: ' All you need is love html . A HTML form can describe a model of your data quite well. This lets you go from HTML form design to a working Create Read Update Delete (CRUD) system. A CRUD can be thought of as a nice admin interface to edit your data (or a CMS if you prefer that acronym). For example: <form action='savepage' method='post'> title:<input type='text' name='title'> <br>textarea: <textarea name='content'></textarea> <input type='submit' name='submit'></form> That's all you need to create a CRUD. Things like validation can be defined in the html easily enough then implemented in your code to be checked server side, and client side. Parse the form to get the model, and go from there. The benefits are simplicity, and that designer...

Multiple file uploads with html 5, cherrypy 3.2 and firefox 3.6beta5.

Image
Here's an example for uploading multiple files with HTML 5 and newer browsers, like the firefox 3.6 beta5. You can shift/ctrl select multiple files, and even drag and drop them in. Makes for a much nicer user experience uploading files - rather than having to select one at a time, or having to load some java/flash thing. It uses the unreleased cherrypy 3.2, with it's new request entity parsing tool hooks. See http://www.cherrypy.org/wiki/RequestBodies for details about the new control allowed over the whole process. It's a lot easier to make custom request entity parsing behaviour now, and in a much less hacky way than before. http://rene.f0o.com/~rene/stuff/cherry_multi_fileupload.tar.gz With the tool in there, files come in as a list of files instead.

python3.2(svn) python2.7(svn) and the new GIL, cherrypy as a test.

Image
I've done some quick benchmarks for the unreleased python3.2 on the unreleased cherrypy webserver for python 3. Also with the unreleased python2.7. Here are the results... python3.1 Client Thread Report (1000 requests, 14 byte response body, 10 server threads): threads | Completed | Failed | req/sec | msec/req | KB/sec | 25 | 1000.0 | 0.0 | 533.32 | 1.875 | 93.75 | 50 | 1000.0 | 0.0 | 525.86 | 1.902 | 92.69 | 100 | 1000.0 | 0.0 | 522.96 | 1.912 | 92.1 | 200 | 1000.0 | 0.0 | 523.83 | 1.909 | 92.25 | 400 | 1000.0 | 0.0 | 506.92 | 1.973 | 89.27 | Average | 1000.0 | 0.0 | 522.578 | 1.9142 | 92.012 | python3.2 Client Thread Report (1000 requests, 14 byte response body, 10 server threads): threads | Completed | Failed | req/sec | msec/req | KB/sec | 25 | 1000.0 | 0.0 | 555.72 | 1.799 | 97.78 | 50 | 1000.0 | 0.0 | 558.86 | 1.789 | 98.52 | 100 | 1000.0 | 0.0 | 552.87 | 1.809...

structuring modules/packages and the cdb database for websites and python packages

Image
Integrated modules are nice, but so are modular packages. How can we have both? That is, keep all things for a module(or sub package) in one directory, but also have a nice integrated system built on top of that? Often for one package I will have a file layout like so: /setup.py /[package_name] /[package_name]/[package_module].py /[package_name]/tests/[package_module]_test.py /[package_name]/examples/[package_module].py /[package_name]/docs/[package_module].py Then each module has its tests, docs, and examples all mixed in the one directory. This is nice if you want to have all of the tests together, and all of the docs, and examples together. However then all of the modules are mixed in together. Meaning it is harder to separate them, and keep one module in its own directory. Having everything for one thing together is nicer for developers I think. Using namespace packages through setuptools distribute is one way. There is a draft pep around to put namespace packages into python...

Writing for the latest python is FUN.

Image
Writing for the latest python version is just simply... fun. Even the name 'python 3000' or py3k is amusing. It's been a joy over the last week plugging away at a few personal website and game projects using the latest python version. Over the last year I've been involved in upgrading existing code to the latest versions of python... but not really in writing it JUST for the latest versions. No need to consider backwards compatibility problems... older pythons be damned when programming for fun! I'm able to take advantage of the latest python features in deep architectural ways. To fiddle around with the new deep magic python internals. But the new deep magic parts aren't the best bits though... it's all the elegant little improvements that make a difference. It is of great delight finding python 3 compatible modules. It turns out that the modules available for python 3 are often of quite good quality - and well maintained. There's not all that ...

pywebsite.sqlitepickle. sqlite VS pickle

Image
The sqlite and pickle modules that come with python are quite useful. So lets mix them together and see what comes out. SQLITE Vs PICKLE pywebsite.sqlitepickle is a little module I just made which combines sqlite and pickle for persistence. Useful since it works with python3, and both pickle and sqlite are included with pythons (including pypy). Import the module. >>> from pywebsite import sqlitepickle An in memory db. >>> db = sqlitepickle.SQLPickle() >>> db.save('key', 'value') >>> db.get('key') 'value' Can also save to a file. So we first get a temp file name. >>> import tempfile >>> f = tempfile.NamedTemporaryFile() >>> fname = f.name >>> db = sqlitepickle.SQLPickle(fname) >>> db.save('key', 'value') >>> db.get('key') 'value' >>> db.close() The issues with this are that sqlite does not like sharing conn...

pygame, pywebsite -- a website with joystick controls???!??!

Here's a song program written with a pygame style api: import pygame pygame.init() counts = {} going = True while going: events = pygame.event.get() for e in events: if e.type == HTTP: if e.path.startswith('/song/'): song_id = e.path[6:] if e.method == "POST": counts[song_id] = counts.get(song_id, 0) + 1 e.write(counts[song_id]) elif e.path == "/": if e.method == "GET": data = ','.join(['%s=%s' % (k, v) for k, v in counts.iteritems()]) e.write(data) elif e.method == "DELETE": counts.clear() elif e.type in [QUIT, KEYDOWN, JOYBUTTON, MOUSEDOWN]: going = False Note this is not in pygame yet, but is just the possible API. So it can't be benchmarked since it doesn't really exist. It's Vapour-wa...