Showing posts with label python. Show all posts
Showing posts with label python. Show all posts

Tuesday, 5 April 2011

Android first tips.

I've had the new android phone for a few days now, and thought I'd share some tips.

Transferring Contacts


One of the first things I found read that there was no easy way to copy my contacts from my old phone to the new one. I managed to send all of my contacts to the phone as vcards, via bluetooth. However, there seems to be no easy way of importing them into the contacts lusty.

The method I settled on was to combine all of the cards into one via a simple python script (using sl4a) and then uploading them into my gmail account. The contacts list syncs with gmail, and so job done.

Sl4a is the Scripting Languages for Android by Google, and gives you a programming interface tothe phone, without the need to develop on a PC - you can actually write and run scripts on the phone itself. The python script itself is:

import os, sys 

base = "/sdcard/bluetooth"

with open (os.path.join (base,"contacts.vcf"), "w") as fh:

for f in os.listdir(base):
if not f.endswith ("vcf") or f == "contacts.vcf":
continue

print >> fh, ""
with open (os.path.join (base, f)) as fhx:
print >> fh, fhx.read ()


Transferring files from Kubuntu



The next puzzle was how to transfer music and other files to the phone from my Kubuntu laptop. Now the phone I have is the Motorola Defy, and it seems to restrict access to through it's propriety software. The only drive that shows up when I plug in the USB cable is a small volume containing some Windows drivers. The simplest solution to this that I could find, which satisfied the criteria that the drive should show up in the File Manger as if it were a mounted drive, was to install SwiFTP, an ftp server, on the phone, expose the sdcard directory as the root dir, and then I can browse the phone, upload and download files through Dolphin as I'd wanted, without going through some clunky third party application...

Angry Birds


Don't do it - it is a massive, massive time waster. Time to finish the post now though - I have level 2 to complete.
Published with Blogger-droid v1.6.8

Tuesday, 17 April 2007

Swing Testing with Jython and Jemmy Part 1 - Setting up the system

Introduction

Testing is an important part of the software development process, and various types of testing need to be combined in order to make sure a product is sufficiently tested. A full set of unit tests goes a long way toward making a stable product, and brings with it a safety net to catch errors made when refactoring the code base. Unit tests a far from the whole story however; they are by nature highly localised, and so can't test the overall behaviour of a system. Functional tests go a step further in this regard than unit tests, wiring together various different components and checking that they work together correctly. At a higher level still are system tests, which should test the system as a whole, and that you can use the software to achieve what it is designed to do. Orthogonal to system tests, but at the same sort of level are acceptance tests, tests designed to see whether the product is suitable for the customers to use. Acceptance tests need to check the more superficial (but nevertheless important) aspects of the product. Does the product meet usability targets? Can the user cause crash the system by doing things wrong?

This post is intended to address the latter two types of testing: automating system and acceptance tests on the Java GUI. The basics of the technique requires two open source libraries: Jemmy, a GUI automation tool from the Netbeans team, and Jython, an implementation of Python written in Java.

Setting up the System

  1. Create a system-test folder, with tests and lib subdirectories. The lib subdirectory should further have java and python child directories. The java directory is where the jemmy and jython jars will reside, lib/python is where the python standard library will live.
  2. Download Jemmy and Jython. If Jython hasn't reached 2.2 final yet, 2.2a1 is very stable.
  3. Install Jython, and then copy jython.jar to lib/java and the contents of the Lib directory from within the installation directory to lib/python.
  4. Copy jemmy.jar into lib/java

You will now need to create a script to run your tests. Typically there will already be a script that is used to run the application that you want to test, and a copy of this script can be adapted to the job. In the case that the application is run by running the jar directly, you will need to examine the manifest in order to extract the classpath and main class for the script. The script will look something like the following:

#!/bin/bash
# file: run.sh
APP_DIR=/my/app
TEST_DIR=$APP_DIR/system-test

APP_LIB=$APP_DIR/lib
JAVA_LIB=$TEST_DIR/lib/java
PYTHON_LIB=$TEST_DIR/lib/python

CLASSPATH=$CLASSPATH\;$APP_LIB/anImportantLib.jar
CLASSPATH=$CLASSPATH\;$APP_LIB/anotherLib.jar

CLASSPATH=$CLASSPATH\;$JAVA_LIB/jemmy.jar
CLASSPATH=$CLASSPATH\;$JAVA_LIB/jython.jar

PYTHON_PATH=-Dpython.path="$PYTHON_LIB;./scripts;$TEST_DIR/tests;"

$JAVA_HOME/bin/java -cp $CLASSPATH $PYTHON_PATH org.python.util.jython $@

Note that this script will do nothing unless provided with a script name as an argument, and any arguments the script requires. As we will see later, the application itself is started within the test script. On windows, this can be converted to a batch script, or else run using Cygwin.

Writing the first script

The first script will simply start the application. Nothing more. It will go in the system-test/tests directory. Note that we start the app in a separate thread so that the running app doesn't block our tests from running!

# file: test.py
from co.uk.mycompany.myapp import MainApp
import sys

def run():
    MainApp.main(sys.argv[1:])

def main():
    startup = Thread(target=run)
    startup.start()

if __name__ == "__main__":
    main()

So, after that bit of work, we are back where we started, except that now we have to do something like the following to start the app:

./run.sh tests/test.py more args here

The next article will go into more detail about using jython and jemmy to do some actual work.

Tuesday, 3 April 2007

Python Coroutines

The latest release of Python (version 2.5) has a new feature called coroutines. This post looks at what coroutines are and how to use them. Firstly a brief recap on generator functions. The following function is a generator, since it's definition contains the keyword 'yield':

def rota(people):
    _people = list(people)
    current = 0
    while len(_people):
        yield _people[current]
        current = (current + 1) % len(_people)

if __name__ == "__main__":
    people = ["Ant", "Bernard", "Carly", "Deb", "Englebert"]
    r = rota(people)
    for i in range(10):
        print "It's %s's turn." % r.next()

The generator function returns an iterable object, which returns the value given by the yield statement whenever next() is called on it. In the above example, the iterator is never exhausted - it acts like a circular linked list. Note that we create a new list of people - this allows us to pass in an arbitrary sequence or iterator as the initial argument and isolates the generator from other parts of the program changing the list. So what are coroutines? Coroutines are essentially generators which allow you to pass data back into the generator function. For example, lets say we a almost happy with our rota generator, but we would like a way of updating the internal list of people on the rota. This is where coroutines and the 'send()' function come in:

def rota(people):
    _people = list(people)
    current = 0
    while len(_people):
        command = yield _people[current]
        current = (current + 1) % len(_people)
        if command:
            comm, name = command
            if comm == "add":
                _people.append(name)
            elif comm == "remove" and name in _people:
                _people.remove(name)

def printname(name): print "It's %s's turn." % name if __name__ == "__main__": people = ["Ant", "Bernard", "Carly", "Deb", "Englebert"] r = rota(people) for i in range(6): printname(r.next()) printname(r.send(("add", "Fred"))) for i in range(7): printname(r.next()) printname(r.send(("remove","Deb"))) for i in range(6): printname(r.next())

You can see from this example that we can use send() instead of next() to get the next value, but first the argument provided to send is given to the 'command' variable in the coroutine. In this case it expects a pair of things, a command string and a name (note that in a real world example you'd make the coroutine more robust by adding some tests on the return value from the yield). If the command is "add" the name is added to the internal list, if the command is "remove", then the name is removed from the list if it is there.

Refactoring Function Names in Python

I read an interesting article yesterday about how automating name refactoring in dynamically written languages can be done: http://dogbiscuit.org/mdub/weblog/Tech/Programming/Ruby/RubyMethodRenamed The idea is that you rename your function, and then create a method with the original name that will redirect to the new function and in addition track down the file it was called from, and rename the function call in that file. Thought I'd give it a go in Python, and so created a decorator for the job. Here it is in a basic form sans exception handling and logging.
import inspect, os, re, os.path

class renameto(object): 
 def __init__(self, new_function):
     self.new_function = new_function

 def __call__(self, function):
     self.function = function
     return self.decorator
  
 def decorator(self, *args, **kw):
     f = inspect.currentframe().f_back
     fn = f.f_code.co_filename
     lineno = f.f_lineno
  
     in_f = file(fn)
     out_l = []
  
     for i, line in enumerate(in_f):
         if i == (lineno - 1):
             line = re.sub(r"\b%s\b" % self.function.__name__,
                                         self.new_function.__name__, line)
         out_l.append(line)
  
     in_f.close()
  
     temp = fn + "~"
  
     if os.path.exists(temp):
         os.remove(temp)
      
     os.rename(fn, temp)
  
     out_f = file(fn, "w")
  
     for line in out_l:
         out_f.write(line)
     out_f.close()
  
     return self.new_function(*args, **kw)


def newf(arg):
 print "New trace Function: " + arg

@renameto(newf)
def bob(arg):
 pass
Note that what needs to be done to refactor the name is to copy the old method to the new method name, and then decorate the old method with the @renameto(newname) decorator. Optionally the body of the old method can be removed (or an exception thrown - it should never actually get called). Now run all of your tests - the refactoring should be automatically done (save for perhaps a handful of cases). This of course won't work in it's current form with functions that are assigned to a different variable. For example:
disguised_name = bob
disguised_name("Bet this one can't be changed!")
So some more work is required here to handle odd cases like this. Interesting idea though...

Shadowing and Overriding in Java and Python Inheritance.

This morning I was trying to do something in Java which would tidy up the code in some custom JSP tags I was writing. The idea was to have an abstract superclass for the tags which declared a method "getLog()". This method was to return the LOG object defined in the concrete subclass (I wanted to do some logging to the subclasses 'personal' log from a method within the superclass).

Something was nagging at me that this wasn't going to work, as I recalled that there was something different about overriding methods and variables in subclasses. I did a bit of research, and in fact you can't override variables, only methods. Variables are merely "shadowed".

What this means in practice is that subclasses may call superclass variables as if they were their own, unless they have shadowed them with their own copy of the variable (in which case you have to do "super.variable" to get the superclass version).

In Python on the other hand, you can override superclass variables in subclasses. In my opinion this behaviour is more intuitive and consistent than the Java behaviour. Here are some examples illustrating the difference between the languages:

Java example

// In file A.java
public class A {
  String x = "In class A";

String getX(){ return x; }

public static void main(String[] args){ B b = new B(); System.out.println(b.getX()); } }

class B extends A { String x = "In class B"; }

Compiling and running this example will print "In class A" to the console.

Python example

# In A.py
class A(object):
  def __init__(self):
      self.x = "In class A"
  def getX(self):
      return self.x

class B(A): def __init__(self): self.x = "In class B"

b = B() print b.getX()

Running this example will print "In class B".

It's not a huge deal, more of an irritation. If I want to do the sort of dependency inversion that I wanted, then I will just have to make all subclasses override a getLog() method in the superclass rather than using the LOG variable.

Partial Functions in Python

Recently I have found many uses for the "function that returns a function" python idiom. The basic idea is something like this:

def get_is_small(limit):

    def is_small(i):
        return i < limit
    
    return is_small

The net result is that you have a function reusable in many different situations, without having to keep track of the limit value:

>> is_quite_small = get_is_small(15)
>> is_very_small = get_is_small(3)
>> is_quite_small(6)
True
>> is_very_small(6)
False

This should all become much easier to do once python 2.5 is released, as there is a general purpose function to provide the outer function for you. I believe it will look something like:

import functional
def is_small(limit, i):
    return i < limit

is_quite_small = partial(is_small, 15)
is_very_small  = partial(is_small,3)

Update: Now that 2.5 has been released, I can confirm that it does have a partial function in the standard library - but in the module functools.