Testing Django – part 2 – lettuce

The first part of this series was an introduction to Django testing with nose. In this part we will shed light on lettuce to practice Behaviour Driven Development (BDD). You can find all the other parts here:

The frame work lettuce is heavily inspired by cucumber – a BDD framework for Ruby. The key idea is to make specifications a communication tool between the different stake holders of a project (e.g. owner and the developer) and testable as well. To accomplish that the feature descriptions are written in a business-readable domain-specific language. A second layer (the so called step definition) is used to translate these specifications into testable code.

Starting with the dummy project from the first part we first need to install lettuce:

$ sudo pip install lettuce

And we have to configure the app to make use of lettuce (in the settings.py file):

    'fruitsalad.fruits', # From the first part
    'django_nose', # From the first part
    'lettuce.django' # Add now

By doing so manage.py gets a new command called harvest. Running this command will give the following output:

$ ./manage.py harvest
Django's builtin server is running at
could not find features at ./fruits/features

0 feature (0 passed)
0 scenario (0 passed)
0 step (0 passed)

This means we have to add features. So we setup a dedicated folder

$ mkdir fruits/features

and create a file called fruits/features/fruits_basics.feature. The precise name is not important as long as it ends with .feature. Let’s add the a feature definition to this file:

Feature: Fruits should be yummy.

    Scenario: Having a cherry
        Given I access the url "/fruits/cherry"
        Then I see the content of the cherry page

Lettuce digests this feature and looks for the step definition of it. As there is none so far it offers us some snippets that we can use:

$ ./manage.py harvest
Django's builtin server is running at

Feature: Fruits should be yummy.              # fruits/features/fruits_basics.feature:1

  Scenario: Having a cherry                   # fruits/features/fruits_basics.feature:3
    Given I access the url "/fruits/cherry"   # fruits/features/fruits_basics.feature:4
    Then I see the content of the cherry page # fruits/features/fruits_basics.feature:5

1 feature (0 passed)
1 scenario (0 passed)
2 steps (2 undefined, 0 passed)

You can implement step definitions for undefined steps with these snippets:

# -*- coding: utf-8 -*-
from lettuce import step

@step(u'Given I access the url "(.*)"')
def given_i_access_the_url_group1(step, group1):
@step(u'Then I see the content of the cherry page')
def then_i_see_the_content_of_the_cherry_page(step):

0 feature (0 passed)
0 scenario (0 passed)
0 step (0 passed)

We copy the given code into a the step file fruits/features/fruits_basics.py and run lettuce again:

$ ./manage.py harvest
Django's builtin server is running at

Feature: Fruits should be yummy.              # fruits/features/fruits_basics.feature:1

  Scenario: Having a cherry                   # fruits/features/fruits_basics.feature:3
    Given I access the url "/fruits/cherry"   # fruits/features/fruits_basics.py:5
    Then I see the content of the cherry page # fruits/features/fruits_basics.py:9

1 feature (1 passed)
1 scenario (1 passed)
2 steps (2 passed)

The test passes now but only as we did not assert anything so far. Let change this. We use Django‘s testing client which we covered shortly in the first part to test the existence of a page:

from lettuce import step
from lettuce.django import django_url
from lettuce import world
from django.test.client import Client

@step(u'Given I access the url "(.*)"')
def given_i_access_the_url_group1(step, url):
    world.client = Client()
    world.response = world.client.get(django_url(url))

@step(u'Then I see the content of the cherry page')
def then_i_see_the_content_of_the_cherry_page(step):
    assert world.response.content == "Show the cherry page"

world is a little helper construction that is explained here. Let’s run lettuce again with these real specs:

/manage.py harvest
Django's builtin server is running at

Feature: Fruits should be yummy.              # fruits/features/fruits_basics.feature:1

  Scenario: Having a cherry                   # fruits/features/fruits_basics.feature:3
    Given I access the url "/fruits/cherry"   # fruits/features/fruits_basics.py:8
    Then I see the content of the cherry page # fruits/features/fruits_basics.py:13

1 feature (1 passed)
1 scenario (1 passed)
2 steps (2 passed)

The test passes and we are happy. We only applied Python‘s assert function in these examples but as described here nose’s assertion (e.g. assert_equal, assert_true) functions that we met in the first part of the series can be used here, too.

Testing Django – part 1 – nose

The following series is meant to be a hands-on introduction to selected tools that can be used for automated Django testing. You can find all the parts here:


If you want to bring the good practice of automated testing or even Test Driven Development (TDD) to your Django project you have many different testing framework to choose from. In the first part of this series I want to introduce nose, in the second part we will have a look at Behavior Driven Development (BDD) with lettuce.

It is important to keep in mind that there are different levels of testing. The most important once are:

  1. unit testing
  2. integration testing
  3. system testing

Python‘s standard libraries and Django offer the unittest and doctest libs but I personally prefer the nose testing framework as it is powerful and has an easy syntax. Actually you can also use tests written for unittest or doctest and use nose a the test runner. You can even mix different types of testing styles. This is what I would call flexible.

Starting a project

Let’s start a little dummy project with one app. I am one of these folks who like to work with fruity examples:

$ django-admin.py startproject fruitsalad
$ cd fruitsalad/
$ django-admin.py startapp fruits

This should generate something that looks like this:

$ find 

Set up the basic database information in the settings.py:

    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'fruit.db',

Make manage.py executable

$ chmod u+x manage.py

and fire up the server:

$ ./manage.py runserver 
Validating models...
0 errors found

Django version 1.2.1, using settings 'fruitsalad.settings'
Development server is running at
Quit the server with CONTROL-C.

If you open in your browser you should get a welcome page.

Install nose and django-nose:

$ sudo pip install nose
$ sudo pip install django-nose

In the settings.py we need to tell the Django project to load our app and django-nose:

    'fruitsalad.fruits', # Add this
    'django_nose',  #  Add this                                                            

Additionally we have to specify nose as our test runner:

TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'

Testing models

Test drive development means to write first the test and then the functionality to fulfill the expectations. So let’s write the first unit tests with nose. For nose is does not matter where in project folder you put the tests. It will find them (if you name the classes and functions correctly – i.e. starting with “Test” or “test”, respectively) but when creating the fruits app the file fruits/tests.py was created. I think it’s a good location for our tests so I will use it. django-admin.py put a unittest and a docstring based test example into this file already but we want to use nose syntax for our tests. We copy the following text into the file:

from fruitsalad.fruits.models import Fruit
import nose.tools as nt

class TestFruit(object):

    def setup(self):
	self.fruit = Fruit()

    def test_color(self):
        nt.assert_equal(self.fruit.name, "Papaya")
	nt.assert_equal(self.fruit.color, "orange")

    def test_yumminess(self):

    def test_color_change(self):
        nt.assert_equal(self.fruit.color, "brown")

    def teardown(self):

Here we have one test class that contains three test functions. nose offers different possibilities to compare the expectations with real results. In the example we use assert_equal (the two given argument have to be equal) and assert_true (the given argument has to be True) but there are many others. Check pydoc nose.tools or this page for further references. We also use the setup and the teardown method to prepare our testing environment before the tests and to clean it after the tests.

We can now run nose and see if it test fails. As we configured nose as test runner we can do this in the following way:

$ ./manage.py test

Now we have our tests which define our expected behaviour of the model. We continue by creating a model that satisfies these tests. We add the following to fruits/model.py:

from django.db import models

class Fruit(models.Model):

    name = models.CharField(max_length=50)
    color = models.CharField(max_length=50)

    def set_name(self, name):
        self.name = name

    def set_color(self, color):
        self.color = color

    def is_yummy(self):

    def become_brown(self):
        self.color = "brown"

    def disappear(self):
        self.color = "transparent"

Now it should be possible to run the tests successfully:

$ ./manage.py test
Creating test database 'default'...
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_user_permissions
Creating table auth_user_groups
Creating table auth_user
Creating table auth_message
Creating table django_content_type
Creating table django_session
Creating table django_site
Creating table fruits_fruit
Installing index for auth.Permission model
Installing index for auth.Group_permissions model
Installing index for auth.User_user_permissions model
Installing index for auth.User_groups model
Installing index for auth.Message model
No fixtures found.
nosetests --verbosity 1
Ran 3 tests in 0.002s

Destroying test database 'default'...

If a test fails you get a message like this:

  File "/home/myuser/fruitsalad/../fruitsalad/fruits/tests.py", line 12, in test_color
    nt.assert_equal(self.fruit.name, "Kiwi")
AssertionError: 'Papaya' != 'Kiwi'

Ran 6 tests in 0.012s

FAILED (failures=1)
Destroying test database 'default'...

Testing views

In the next step we are going to test the views of our app (if you are not a Djangonout so far: the expression “view” is used differently as in other web frameworks). This could be already see as integration testing as interaction between model and views could be tested here. But to keep it simple for this introduction we don’t use our models here but only let the views do the work. To access the views we use Django‘s Client class. We add the following test to our fruits/test.py file:

from django.test import Client

class TestFruitView(object):

    def setup(self):
        self.client = Client()

    def test_product_index(self):
        response = self.client.get("/fruits/")
        nt.assert_equal(response.content, "The index")

    def test_product_show(self):
        response = self.client.get("/fruits/papaya")
        nt.assert_equal(response.content, "Show the papaya page")

    def test_product_add(self):
        response = self.client.get("/fruits/add")
        nt.assert_equal(response.content, "Add a fruit")

A test run might return this now:

TemplateDoesNotExist: 404.html

Ran 6 tests in 0.019s

FAILED (errors=3)
Destroying test database 'default'...

The first step to solve this is to specify our url pattern in the file url.py:

urlpatterns = patterns(
    (r'^fruits/add', 'fruits.views.add'),
    (r'^fruits/(\w+)', 'fruitsalad.fruits.views.show'),
    (r'^fruits/', 'fruitsalad.fruits.views.index')

Now our app knows which view should be accessed depending on the requested url. Still we get errors:

TemplateDoesNotExist: 404.html

Ran 6 tests in 0.020s

FAILED (errors=3)
Destroying test database 'default'...

This is due to the fact that the views don’t exits so far – what we will change now. We adapt the fruits/views.py to look like this:

from django.http import HttpResponse

def index(request):
    return HttpResponse("The index")

def show(request, fruit):
    return HttpResponse("Show the %s page" % fruit)

def add(request):
    return HttpResponse("Add a fruit")

Now the new tests run successfully.

Destroying test database 'default'...
kuf@yersinia $ ./manage.py test
Creating test database 'default'...
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_user_permissions
Creating table auth_user_groups
Creating table auth_user
Creating table auth_message
Creating table django_content_type
Creating table django_session
Creating table django_site
Creating table fruits_fruit
Installing index for auth.Permission model
Installing index for auth.Group_permissions model
Installing index for auth.User_user_permissions model
Installing index for auth.User_groups model
Installing index for auth.Message model
No fixtures found.
nosetests --verbosity 1
Ran 6 tests in 0.013s

Destroying test database 'default'...

I hope you got a basic understanding how to test your Django app with nose. In the second part we will dive into the testing of our project with lettuce.

JavaScript interaction between an embedded SVG image and its hosting HTML file

I needed to modify a HTML document depending on the cursor position in an embedded SVG file. Why would somebody need that? An example could be that you have a SVG based map in a HTML file and the name of the country on which the cursor is located should be highlighted in the HTML document. Actually this is pretty simple to do:

The hosting HTML file looks like this:

<html xmlns="http://www.w3.org/1999/xhtml">
    <title>SVG + HTML </title>
      var htmlDocument = document;
  <body id="body">

    Name of the color:
    <span id="colorNameField">Move the cursor over the colored squares.</span>

      <object data='image.svg' height='500' type='image/svg+xml' width='500'></object>


(test/download file)

The SVG file with the creative name “image.svg” has the following content:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" height="70" width="190">

<rect height="50" width="50" x="10" y="10" fill="red" stroke="black" id="red"

<rect height="50" width="50" x="70" y="10" fill="green" stroke="black" id="green"

<rect height="50" width="50" x="130" y="10" fill="blue" stroke="black" id="blue"

<script type='application/ecmascript'>
    function writeColorName(evt){
      var colorName = evt.target.id;
       var textToReplace = top.htmlDocument.getElementById("colorNameField");
       textToReplace.innerHTML = colorName;


(download file)

In this example the color of the square is show above the image if you put the cursor on a square.


The magic happens in the following way. In the <script> part of the HTML file the variable htmlDocument is defined and gets the document content assigned as value. In the script part of the SVG file we can access this variable via top.htmlDocument. Now we have the full HTML document representation at hand and can modify it as we like.

Dump Emacs org-mode agendas and todo lists to the command line

Emacsorg-mode is just a mind blowing tool for organizing everything – there is a full Google Tech Talk only about this extension. Among other things I use it for my scheduling and todo lists. Sometimes (e.g. when I start my computer in the morning) I just want a quick glance at my today’s appointments and top todo items without opening Emacs and starting the agenda view. Due to this I created a simple setup that dumps this information into the command line.

To do so you first must have a org-mode formated file. If you need basic information about how to use the org-modes read its excellent documentation. Here is a sample file that I named “projectes.org”. It has the following made-up content:

* Project Boing
** TODO [#A] Make a the plan
** TODO [#A] Write the specs
** TODO [#A] Write the code
   DEADLINE: <2010-08-27 Fri>
* Project Blub
** Meet the others
   SCHEDULED: <2010-08-25 Wed>
** TODO [#B] Dream up something
** TODO [#C] Slacking

You need to add this file to the list of agenda files in your Emacs configuration file (~/.emacs) so that the org-mode will include it in the agenda display:

(custom-set-variables '(org-agenda-files (quote ("~/projects.org"))))

If you have Emacs running, the org-mode installed and activated “M-X org-angenda a” will give you an overview of the dates and “M-X org-angenda t” will present your todo list.

To call this function from the command line instead of inside of Emacs use the editors batch mode:

$ emacs -batch -l ~/.emacs -eval '(org-batch-agenda "a")' 2> /dev/null

The “2> /dev/null” takes care of some extra and for us not useful information. The output should look like this:

Week-agenda (W34):
Monday     23 August 2010 W34
Tuesday    24 August 2010
Wednesday  25 August 2010
  projects:   In   2 d.:  TODO [#A] Write the code
  projects:   Scheduled:  Meet the others
Thursday   26 August 2010
Friday     27 August 2010
  projects:   Deadline:   TODO [#A] Write the code
Saturday   28 August 2010
Sunday     29 August 2010

If you run this on a different date the output will look different. Today – the 25th of August – it is 2 days to the deadline that ends at the 27th. Again – to fully understand everything I can just refer you to the org-mode documentation. In order to get the todo list written to the command line we have to adapt the call just slidely – replace the “a” by a “t”.

$ emacs -batch -l ~/.emacs -eval '(org-batch-agenda "t")' 2> /dev/null

The output should look similar to this:

Global list of TODO items of type: ALL
Available with `N r': (0)ALL
  projects:   TODO [#A] Make a the plan
  projects:   TODO [#A] Write the specs
  projects:   TODO [#A] Write the code
  projects:   TODO [#B] Dream up something
  projects:   TODO [#C] Slacking

Finally make some handy aliases in your ~/.profile file:

alias todo="emacs -batch -l ~/.emacs -eval '(org-batch-agenda \"t\")' 2> /dev/null "
alias today="emacs -batch -l ~/.emacs -eval '(org-batch-agenda \"a\")' 2> /dev/null "

Now you can get the wished output by typing “todo” or “agenda” in the command line.

Installing LeoCAD – a CAD program for toy bricks

LEGO™ rocks, sharing knowlege rocks. Sharing Lego models kicks ass. To do so you can either send you LEGO™ constructions by mail or (better) use a CAD program to model your ideas digitally and upload it. I had a look around for open source tools specialized on modeling plastic toy bricks and found LeoCAD.


To be perfectly honest – this tool has still its weaknesses and is not very stable but it’s enough to get the job done. I first tried to install a compiled version on Ubuntu 10.4 but ended up compiling it myself. There is a very helpful guide for this. Unfortunately not all versions run without problems so currently I can recommend to use version 0.75.1 – other versions e.g. were not able to load saved files (quite a painful experience when you spent some time in creating a model). As mentioned in the compiling guide you should check if you have everything needed (e.g. OpenGL and GTK) installed before compiling:

$ sudo apt-get install libgtk2.0-dev libgl1-mesa-dev

After that you can download the source using subversion and compile it:

$ mkdir /tmp/leo_tmp
$ cd /tmp/leo_tmp
$ svn co http://svn.gerf.org/leocad/tags/leocad-0.75.1 leocad
$ cd leocad/
$ mkdir /opt/leocad-0.75.1
$ mv bin/ /opt/leocad-0.75.1/

LeoCAD needs libraries of pieces (e.g. the bricks). Download and unzip the recommended library the following way:

$ cd /opt/leocad-0.75.1
$ mkdir pieces
$ cd pieces/
$ wget http://leocad.googlecode.com/files/pieces-3506.zip
$ unzip pieces-3506.zip
$ ls -1 

Now we are ready to launch LeoCAD. You have to tell it where the pieces libraries are.

$ export LEOCAD_LIB=/opt/leocad-0.75.1/pieces/ ; /opt/leocad-0.75.1/bin/leocad

(If you use it more often you might want to create and alias for this.) LeoCAD should be now up and running – waiting for you input. I recommend to have a look at the basic tutorial to get a feeling how to work with it.

Set up an Eclipse-free environment for Android application development

If you want to start to develop applications for Android you need to install the Android SDK. The installation instructions advise you to install Eclipse and to add the Android Development Tools (ADT) plugin. Not everybody is a fan of this dinosaur-like IDE and luckily it is not really needed. The plugin is just a wrapper for some tools that you can use in the command line, too. Here I will give you a description about how to setup an Eclipse-free, lightweight and transparent developing environment in Ubuntu GNU/Linux and how to use some to the SDK tools.

At first check if you have JDK and ant installed.

$ dpkg -l | egrep "jdk|ant1" | cut -c -30
ii  ant1.8
ii  ant1.8-optional
ii  default-jdk               
ii  openjdk-6-jdk             
ii  openjdk-6-jre             
ii  openjdk-6-jre-headless    
ii  openjdk-6-jre-lib

If anything is missing fill the gap. Then choose a suitable version of the Android SDK and download it:

$ wget http://dl.google.com/android/android-sdk_r06-linux_86.tgz

Unpack the downloaded file and move the resulting folder to location that you prefer for this purpose:

$ tar xfz android-sdk_r06-linux_86.tgz
$ mv android-sdk-linux_86 /opt/

Let’s have a quick look into our new tool box.

$ ls /opt/android-sdk-linux_86/tools/
adb         dmtracedump  hierarchyviewer  mksdcard           traceview
android     draw9patch   hprof-conv       NOTICE.txt         zipalign
apkbuilder  emulator     layoutopt        source.properties
ddms        etc1tool     lib              sqlite3

To make these tool available without their full path we add their folders path to the PATH environment variable in our .bashrc, .profilerc or a similar file:

if [ -d "/opt/android-sdk-linux_86/tools/" ] ; then

The first program will use it the AVD Manager that we launch via the SDK. We need it to install further components e.g. the Android platform 2.1 files.

$ android
Starting Android SDK and AVD Manager
No command line parameters provided, launching UI.
See 'android --help' for operations from the command line.

… starts a gui:


… and there we can choose the component to install. We add the package 7 with Android 2.1.


After this we have even more tools:

$ /opt/android-sdk-linux_86/platforms/android-7/tools/
aapt  aidl  dexdump  dx  lib  NOTICE.txt

Having all our tools at hand we now create our first project

$ android create project \
     --name ARockingApp \
     --target 1 \
     --path ./a_rocking_app \
     --package com.android.arockingapp \
     --activity ARockingApp

What does this command create?

$ find a_rocking_app/

This is the basic scaffold of an Android app and without any changes we can build the app using ant (actually you don’t have to use ant but run dx & Co. manually). Use the option debug to sign the app (and maybe read some background about signing apps).

$ ant debug
Buildfile: /home/kuf/jo/a_rocking_app/build.xml
Total time: 6 seconds

This should give us the following application files:

$ find . -name "*apk"

To run the app we create a new virtual device by using the SDK. Call android and click on “New” under “Virtual devices”. Give the device a name and select a target platform. Click on the newly created device and then on “Start”. Depending on your hosting system it might take a while until the emulator shows a proper home screen.


To get a list of running device use adb (Android Debug Bridge) with the option devices.

$ adb devices
List of devices attached 
emulator-5554	device

Now we know to which device we can install our new app to. As we have only one the option “-s” is not really needed but I add it here to show its usage:

$ adb -s emulator-5554 install bin/ARockingApp-debug.apk
205 KB/s (13207 bytes in 0.062s)
	pkg: /data/local/tmp/ARockingApp-debug.apk

The emulator shows an icon of the app.


If you click on this icon the app starts. As we haven’t changed anything in the source code after creating the app project we should see the default welcoming text.


Now you can fire up your favorite text editor and hack your first proper application!

Take a screenshot of an Android device using the SDK

Assuming you have installed the Android SDK you can use the Dalvik Debug Monitor Server (DDMS) to take screenshot of your Android phone or emulated devices. You have to activate USB debugging on the device (Settings > Applications > Development > USB debugging) and connect it to your computer. Then fire up the DDMS:

$ ddms

There simply select the device. After that you should find the option “Screen Capture” in the “Device” tab.


After clicking it you get a screenshot of your device which you can modify and save.

Create a launch short cut for an Android Scripting Environment script

Once you have written a useful ASE script you might want to have an icon on your home screen to launch the script instead of opening ASE first and selecting the script there. For this you can add a shortcut to your home screen. Go to your home screen, click the menu button and select “Add to Home”.


In the menu that appears choose “Shortcut”.


From that list select “ASE”.


Now select the script you want to run …


and decide if you want to run it in the shell or in the background.


Now you can find an icon on your screen that launches your script.


First steps with the Android Scripting Environment

The Android Scripting Environment (ASE) offers an easy way to generate (small) programs for Android phones. The quickest way to install ASE is via the barcode reader application and the bar code given on the ASE homepage that links to the installation package. After the installation of ASE you need to add an interpreter for the programming language which you like to use. Currently Python, JRuby, Perl, Lua, Tcl, BeanShell, Shell (installed per default) and JavaScript are available. For installing an interpreter press the menu button, select “View”, select “Interpreters”, press the menu button, select “Add” and select a language.

The following examples will show how to write some small programs using Python (currently version 2.6.2). The ASE Python interpreter comes with many “batteries included” (= standard libs) and some handy extras like BeautifulSoup (HTML/XML parser) and xmpppy (guess :)).

In general you can generate scripts on your phone directly in ASE. Alternatively use your preferred editor on you PC/Mac, mount the phone and copy the file to /<PATH_TO_THE_DEVICE>/ase/scripts/. In the latter case you need to unmount the device before you run the scripts.

Let’s start with a classic: To create a program that prints the Zen of Python open ASE, click the menu button, select “Add” and select “Python 2.6.2”. Now there is a display with two text fields – one for the filename, the other one for the script content.


Name the file “zen.py” (or whatever you like) and change the content to this:

import this


Now press the menu button and select “Save & Run”. The file is executed in the shell and you should see output like this:


Congratulations! You run your first Python script on an Android device. So far we have not used any of the Android specific features. To see the options have a look at the API referefence (push the menu button and select “API Browser”)


The following example makes use of the vibration functionality of the phone. Open a new file, give it a name and change the text to this and run it as done before.

import android
import time

droid = android.Android()
droid.vibrate() # vibrate - default time = 300 ms
time.sleep(2) # wait 2 second
droid.vibrate(500) # vibrate again - this time 500 ms

To use Adroid specific functions you need to import the “android” library and create an object of the Android class which offers the methods described in the API reference. As you can see you can import standard libraries like “time”, too.

One very cool feature is the option to use the camera of the phone as a barcode scanner. Create a new file with the following content, execute it and put any product with an barcode in front of the camera.

import android

droid = android.Android()
gtin = droid.scanBarcode().result["extras"]["SCAN_RESULT"]
print gtin

The GTIN of the product is printed to the shell. I make use of such a script to generate data for my project ProductTransparency. To send the output of a barcode scanning process to a server you can use urllib:

import android
import urllib

server_url = "http://add-your-server-url-here.net"
droid = android.Android()
gtin = droid.scanBarcode().result["extras"]["SCAN_RESULT"]
f = urllib.urlopen(dblink, gtin)
print f.read()