Friday, September 25, 2009

Importing your Thunderbird contacts to GMail.

I found myself needing to import my Thunderbird contacts to GMail. After asking the internets Thunderbird provides an option to export contacts as a CSV file and GMail provides an option to import contacts from a CSV file. Cool I thought and proceeded to something that should take me a couple of minutes to complete.
Of course surprise, surprise the CSV format outputted from Thunderbird does not produce the expected results when imported to GMail. So I quickly hacked up the following Python script to generate a GMail friendly csv file from a csv file exported from Thunderbird. Note that in order to use it you must have Python installed in your PC.
import sys
import csv

def transform(filename_in, filename_out):
  output_list = []
  try:
      file_input = open(filename_in)

      csv_input = csv.reader(file_input)
    
      for row in csv_input:
          entry_list = []
          entry_list.append(row[0])
          entry_list.append(row[1])
          if(output_list):
              entry_list.append(row[4])
          else:
              entry_list.append('Email Address')
            
          output_list.append(entry_list)

      file_input.close()
        
  except IOError:
      print 'Could not open file %s. '\
            'Make sure that the file exists.' % filename_in
      sys.exit(1)
        
  try:  
      file_output  = open(filename_out, "wb")
      csv_output = csv.writer(file_output)

      for row in output_list:
          csv_output.writerow(row)
        
      file_output.close()

  except IOError:
      print 'Could not open file %s. '\
            'Make sure that the file can be written.' % filename_out  
      sys.exit(1)
        

if __name__ == '__main__':
  if len(sys.argv) != 3:
      print "Usage: %s [input csv file] [output csv file]" % sys.argv[0]
      sys.exit(1)

  transform(sys.argv[1],sys.argv[2])
So to actually import your contacts from your Thunderbird email client to GMail:
  • In Thunderbird select Address Book -> Tools -> Export
  • In the export dialog select "Comma separated values" as the output type and save it somewhere (i.e. /home/foo/export.csv)
  • Grab the script above and save it somewhere with a name of your choice (i.e. converter.py)
  • Run the script with arguments the name of the file exported from Thunderbird and the name of the output file (i.e. python converter.py /home/foo/export.csv /home/foo/gmail_import.csv)
  • Open up GMail contacts and select "Import"
  • Choose the file outputted by the script (i.e. /home/foo/gmail_import.csv) and proceed to importing.
  • Enjoy

Monday, June 1, 2009

Starting a Django project in Eclipse with PyDev

Assuming python and Django installed plus eclipse with PyDev. The django project we ‘ll create is called mysite and the respective eclipse project will be named mysite-project.

  • In eclipse New –> PyDev Project
  • Project name: mysite-project
  • Deselect “Create default “src” folder and add it to the pythonpath” and press OK
  • Navigate to the Workspace folder of eclipse.
  • Navigate to the folder mysite-project from the command line.
  • Execute django-admin.py startproject mysite
  • Press F5 on the project
  • Right click on the project name in the Pydev Package Explorer from Eclipse and select "Properties".
  • Select PyDev - PYTHONPATH
  • In the "Source Folders" tab press "Add source folder" and select the folder "mysite" created from django-admin.
Now you are ready to start coding. The approach of creating the top level django project folder as a sub directory of the eclipse project's top level folder allows us to have correct auto completion from PyDev by using it's supported folder structure (a source folder inside the eclipse project). I will continue posting on my eclipse setup for django projects but this should get you started.

Sunday, May 17, 2009

Researching techniques on unit testing Qt GUI applications

I have been struggling for a while on how to make desktop applications I am working on with Qt unit testable. In general there are many techniques presented that achieve the goal of making the UI part of an application so thin that it doesn’t need to be be unit tested while the business logic behind the UI is separated and can be easily unit tested. Most of these techniques work beautifully in implementations that use languages with a big arsenal of tools targeted to unit testing and dependency injection like Python and Java that I have experience with.

In Qt and C++ the whole process of making an UI testable has it’s quirks (Qt views need to have a parent – child relation, there is no garbage collection etc.). I have found that the approach of “Humble Dialog” is the one that gives me most benefits:

  • The view is the front-man (what is exported from a model – view – presenter (controller) triad is the view) so it plays well with Qt that also has this approach and is more comprehensible from an audience that is not exposed to the pattern.
  • All the wiring of  the triad happens in the view, so all parts that are not supposed to be unit tested are in the same place and I can in most places avoid setting up factories for wiring up and instantiating the triads.
  • The messages between triads are easily delivered since the whole setup resembles a lot the typical mixed UI/business logic that seems to be the convenient way of creating applications with a UI and is the one that most GUI toolkits support.

An example implementation of something as simple as a messagebox presenting some text could be (from a question I posted on Stack Overflow):

class IView {
public:
    IView(){}
    virtual ~IView(){}

    virtual void showResult(const QString &text)=0;
};

class Presenter {
public:
    Presenter(IView *view){
        m_View = view;
    }
    ~Presenter(){}

    void buttonPressed(){
        QString text;
        // Evaluate text
        m_View->showResult(text);        
    }

private:
    IView *m_View;
}

class MyView : public IView , public QDialog {
public:
    MyView(){
        m_Presenter = new Presenter(this);
        m_Button = new QPushbutton(this);
        m_Label = new QLabel(this);

        // Ui event handled inside view but then directly
        // propagated to the Presenter
        connect(m_Button,SIGNAL(clicked()),this,SLOT(buttonPressed()));
    }
    ~MyView(){
        delete m_Presenter;
        // Qt will automatically delete m_Button and m_Label;
    }

    void showResult(const QString &text){
        m_Label->setText(text);
    }

protected slots:
    void buttonPressed(){
        m_Presenter->buttonPressed();
    }

private:
    Presenter *m_Presenter;
    QPushbutton *m_Button;
    QLabel *m_Label;
}

class TestView : public IView {
public:
    TestView(){}
    ~TestView(){}

    void showResult(const QString &text){
        m_LabelText = text;
    }
    QString getResult(){
        return m_LabelText;
    }

private:
    QString m_LabelText;
}

// Test code
TestView view;
Presenter presenter(&view);
presenter.buttonPressed();
EXPECT_EQ(view.getResult(),"Expected Result");

// Production code
MyView view;
view.show();

The main advantage I see from following this approach is that if I wanted to i.e. instantiate an new model – view – presenter triad after some user action I could perform it inside the view instantiating it easily without the need for a factory and secondly from the “outside” the triad seems to be just a view and not a full blown MVP triad that makes it play well with Qt.

I ‘d like others to share their thoughts on this, since for me settling with this approach has come after a lot of trial and error.

Monday, April 6, 2009

Twitter client for fun

I was checking the twitter APIs now that I 'm also using it and they are all quite clean (most probably because the underlying API is also clean and complete). I thought I 'd give it a try and got python-twitter http://code.google.com/p/python-twitter/
A client that just receives my latest tweets using PyQt4 was quite easy to build:
import sys
import twitter
from PyQt4.QtGui import QApplication, QMainWindow, QTabWidget, QListView
from PyQt4.QtCore import QAbstractListModel, Qt, QVariant

class TweetsModel(QAbstractListModel):
    def __init__(self, tweets = set()):
        QAbstractListModel.__init__(self)
        self.tweets = tweets

    def rowCount(self, parent):
        return len(self.tweets)

    def data(self, index, role):
        ret = QVariant()
        if ( index.isValid() and index.row() < len(self.tweets)
            and role == Qt.DisplayRole ):
            ret = QVariant(self.tweets[index.row()])
        return ret

class TweetsListView(QListView):
    def __init__(self, parent):
        QListView.__init__(self, parent)

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        
        api = twitter.Api()
        statuses = api.GetUserTimeline("pagles")
        tweets = [s.text for s in statuses]

        self.tabs = QTabWidget(self)
        self.tweetsModel = TweetsModel(tweets)
        self.tweetsList = TweetsListView(self)
        self.tweetsList.setModel(self.tweetsModel)
        self.tabs.addTab(self.tweetsList,self.tr("Tweets"))

        self.setCentralWidget(self.tabs)

class QweetApplication(QApplication):
    def __init__(self):
        QApplication.__init__(self, sys.argv)

if __name__ == "__main__":
    app = QweetApplication()
    mainwindow = MainWindow()
    mainwindow.show()
    exit(app.exec_())
Yes, my username in twitter is pagles in case you followed the code closely :-)

Wednesday, February 11, 2009

Get the version of gcc with python.

I needed to get the version of gcc in a python script (Ubuntu Linux). And here it is:
commands.getoutput("gcc -v").split(' ')[-4:-3][0]
Python is fun...