Freitag, 26. November 2010

OpenId login with web.py fast easy simple example

#!/usr/bin/env python
import web
from web import webopenid
urls = (
'/', 'index',
'/openid', 'webopenid.host',
)

app = web.application(urls,globals())

def form(openid_loc):
  oid = status()
  if oid:
    return '''
<form action="%s" method="post">

<img alt="OpenID" src="http://openid.net/login-bg.gif"
/>
<b>%s</b>
<input name="action" type="hidden" value="logout" />
<input name="return_to" type="hidden" value="%s" />
<button type="submit">log out</button></form>
''' % (openid_loc, oid, web.ctx.fullpath)
  else:
    return '''
<form action="%s" method="post">
<input name="openid" style="background:
url("http://openid.net/login-bg.gif")
no-repeat scroll 0% 0% transparent;
padding-left: 18px;" type="text" value="" />
<input name="return_to" type="hidden" value="%s"
/>
<button type="submit">log in</button></form>
''' % (openid_loc, web.ctx.fullpath)

class index:
  def GET(self):
    oid = webopenid.status()
    if not oid:
      return 'please log in: ' + \
        webopenid.form('/openid')
    else:
      return 'you are logged in as:' + \
              webopenid.form('/openid')

if __name__ == '__main__':
  app.run()

Samstag, 6. Februar 2010

Some thoughts on startiing hacking on the AVR Butterfly

Connecting the Butterfly
Without knowing much about the Butterfly, it was difficult to get things working at first. The Butterfly comes with pre-installed firmware which shows off the features. There are options like entering and displaying your name on the LED screen (the Butterfly actually comes with a  safety pin so you can use it as a name label on your shirt), displaying temperature (I think) and changing and displaying the date.

I figured it would be best to make an initial back up copy of the original Butterfly firmware. This wasn't particularly easy. I used a Fritzl ASP initially (modified by jw to handle shifting the TTL +5v +0v to a quasi RS232 +12v -12v). With avrdude I was able to retrieve and save the original firmware. The command and options were:

avrdude -p atmega169 -b 19200 -c butterfly -P /dev/ttyUSB0 -U flash:r:flash.hex:i

But in order to be able to actually talk to the Butterfly, you need to get it into a state where the bootloader is active (i.e. that the Butterfly doesn't just jump into the firmware's main()). The trick here is to reset the Butterfly (short the two contacts on the extreme bottom right of the Butterfly as you look at it from the front) and then immediately press the joystick down (take care not to waggle it here - otherwise it won't work) and within a couple of seconds enter the avrdude command above in the console. avrdude should tell you that it connected successfully to the programmer and was able to save the flash.hex file (you may need to touch the flash.hex file beforehand).

Things to watch out for
When connecting using a serial cable over the Butterfly UART pins, I followed the diagram in the Butterfly User's Manual. You need to remember that the serial connector shown in that diagram is the 'male' connector - the one with the pins. If you (like me) have the other connector - the 'female' side, then you are going to have to 'mirror' the diagram. You would therefore have the GND at the extreme left of the upper row (where the upper row has 5 holes) and you would have to find out accordingly where the RX and TX holes are.

Another thing to look out for when connecting the serial connector to the UART pins is that some serial cables are 'crossover' cables, designed to connect PC to PC. If this is the case, you will have to swap RX and TX when connecting to UART. If nothing is working, try changing the connections around. That's how I got it working (after about two hours wondering why nothing was happening).


A quick first firmware for the Butterfly

1  #define F_CPU 1000000UL // how fast is CPU?
2  #include
3  #include
4  int main()
5  {    DDRB |=(1<
6  for(;;)
7    {
8      PORTB &= ~(1<
9      _delay_ms(200.0);
10      PORTB |= (1<
11     _delay_ms(200.0);
12    }
13    return 0;
14 }

Dienstag, 26. Januar 2010

TurboGears 2.1b1 released and updated on the openSUSE build service

One-Click Install TurboGears 2.1?

You can now One-Click Install TurboGears 2.1 Beta 1 directly from the openSUSE build service. Just click here!

2.1b1: (**January, 25 2009**)

  • Deprecated default in favor of _default
  • Fixed handling of Unicode parameters
  • Added disable_request_extensions flag to configuration to allow users to ignore the request extension dispatch bits of object dispatch.
  • Increased length of Permission.permission_name to 63 chars.
  • Fixed GET requests on nested RestControllers?.
  • Fixed case-sensitive incorrectness in quickstart when using mako template option.
  • Fixed numerous URL routing bugs, consilidating the RC and TGC controller base.
  • Fixed eroneous tg.url call inside the quickstart template.
  • Added use_dotted_templatenames support for Genshi.
  • Added ignore_parameters setting in the config
  • Added ability to have sa_auth.cookie_secret in .ini file
  • Added cookie_secret to quickstart template
  • Added tgext template
  • Added backwards compat for TurboJson?

Samstag, 16. Januar 2010

File uploads using with ajax using jquery.form and TurboGears 2.1

While trying to follow the ajax file upload example from http://jquery.malsup.com/form/#file-upload I was running into trouble with the server response. I was expecting the server to return json, which I wanted to parse in a callback function. What happened was that the server did its job perfectly and returned content-type application/json. However, the browser (in this case Firefox 3.5) prompted me to download the response, rather than to parse it in the callback function. This is obviously useless.

The answer was to return content-type text/plain instead of application/json. To do this in TurboGears 2.1, I followed an example from Pylons. My controller now looks like this:
   @expose()
    def uploadFile(self,**kwargs):
        """ Simple controller to handle uploaded files
        """
        # do stuff such as handle file upload...
        response.headers['Content-type'] = "text/plain"
        return dict(info={'filesize':50000,'filename':'whatever')
Note the response.headers['Content-type'] = "text/plain" - and that I left out the expose('json') which you would normally use in TurboGears to return json...

Mittwoch, 6. Januar 2010

TurboGears2 application using Apache and mod_wsgi

Here are the steps I went through to get a TurboGears2 application running using Apache and mod_wsgi. It assumes that apache2 and mod_wsgi are configured and properly set up (don't forget to a2enmod wsgi in order to load the wsgi module). There is a good example documented at http://www.turbogears.org/2.0/docs/main/Deployment/modwsgi+virtualenv.html

Install the required packages:

zypper in apache2
zypper in apache2-mod_wsgi
zypper in python-wsgideploy

Create a new turbogears application using paster. This one is called labum
paster quickstart labum

Go into the newly created application root folder
cd labum

Create an apache wsgi setup for the application
paster modwsgi_deploy

Go into the newly created folder 'apache'
cd apache

Edit the labum.wsgi file to suit your environment. I quickstarted the labum application in the
folder /home/cfarrell/Dokumente/labum, so I need to remove the default references to /usr/local/turbogears. I do this in vi using
:%s/\/usr\/local\/turbogears7\/home\/cfarrell\/Dokumente

Copy the the file 'labum' in the 'apache' directory to the apache2 configuration directory. On openSUSE this worked (all *.conf files in /etc/apache2/vhosts.d/ are auto loaded by apache):
cp /home/cfarrell/Dokumente/labum/apache/labum /etc/apache2/vhosts.d/labum.conf

Go back into your turbogears application directory:
cd /home/cfarrell/Dokumente/labum

Copy your development.ini file to production.ini and remove the debugging by setting
debug = False in the first couple of lines

Reload apache and go to http://localhost/labum. If everything worked, you should now be able to see your TurboGears application. If it didn't, you should see what happened by looking at
/var/log/apache2/errors.log

Freitag, 11. Dezember 2009

Creating a history table using SQL triggers

Just for the record and for posterity, this is how to insert a row into table B after a row has been inserted in table a (e.g. something like a foreign key) using a sqlite3 trigger (the trigger would probably work on other databases as well). Add this to a file - call the file "trigger.txt" or something like that:

CREATE TRIGGER mytrigger AFTER INSERT ON table_a
    BEGIN
        INSERT INTO table_b VALUES(NULL,new.primary_id)
END;

Easy, non? Now you have to import the trigger into the sqlite database. Assuming you have already got a database called mydb.db, use this command:
sqlite3 mydb.db < trigger.txt



Now, when you enter a row into table a, a row should automagically be appended to table b.

Montag, 7. Dezember 2009

python-perlmodule in the openSUSE build service

If you've ever wanted to embed perl code directly in python code, or execute perl code or functions directly from python, then python-perlmodule may be exactly what you are looking for. This package basically compiles and embeds the perl interpreter inside python. Once installed, it is possible to directly access perl by doing (e.g.):

import perl
x = perl.eval('3+3')
print x
6
print type(x)
'int'

Neat, eh? Theoretically, you could paste any long string of perl code into the perl.eval() function and have it executed as perl. The return value is a perl object, with python attributes. Sounds strange, huh? Well, consider this code:

import perl
x = perl.eval('[12,23,34,45,{ foo=>999,bar=>666},56,67]')
print x

for i in x: print i
...
12
23
34
45

56
67
>>> print x[4]['foo']
999


Quite handy, non? You can also access perl modules using syntax such as:
import perl
perl.require('Digest::MD5')

You can download the rpm directly from my openSUSE build service repository.