Our Voting System Is STILL Broken!

Please take a moment to look at these two maps, especially if you voted in the recent General Election (#GE2017).

Just as I did for the UK General Election two years ago in 2015, I’ve taken it upon myself to analyse the results and highlight the differences (and imbalance) between the First Past the Post and Proportional Representation (D’Hondt) systems.

Again, after looking at the results of the General Election in some detail it is still apparent  that our voting system in this country is very, very broken! Just to remind everyone, we don’t actually vote for parties (and therefore governments), we simply vote for our local representative. The total number of votes a party receives is not taken into consideration at all, which seems a little strange, particularly when you consider that all through the election campaigns we hear ‘Vote Conservative’ or ‘Vote SNP’, not ‘Vote Bob Smith, your local MP’.

So, as I am still a tremendous geek, I got my hands on all the numbers, created a database and generated some maps!

The first image is the results as you will have seen them using the First Past the Post method. I merely created this one for reference.

First Pas the Post 2017

The second image is the same numbers, this time evaluated using the D’Hondt method for calculating Proportional Representation. This method quite literally calculates the number of seats a party should get based on their proportion of the overall votes cast. I then assigned constituencies to each party (largest first) based on the constituencies in which they received the most votes, thus insuring that (for the most part and where possible) the local representative reflects the local preference.

Interestingly, the constituency of the Na h-Eileanan an Iar (Western Isles) in Scotland ended up with an MP from the Ulster Unionist Party… who only stand in Northern Ireland! This shows two things:

  1. It is not appropriate for local issues parties to stand in a country wide election (IMHO).
  2. My method for seat distribution under D’Hondt PR may be somewhat simplistic!

D'Hondt Proportional Representation 2017

As can be seen, the difference is astounding! The Liberal Democrats would have 48MPs not 12, UKIP would have 12MPs not 0, the Green Party would have 10MPs not 1, the SNP would have 20MPs not 35! Most importantly, The Conservative Party would have had a much harder time finding an ally to form a minority as they would have had 38 less seats and only 16 more than second party Labour.

Seeing these results, I still really don’t understand how anyone can argue against the fact that, using PR, we would have a balanced, fairer and more representative government.

Please like and share this if you agree. Lets make ourselves heard.

Also, consider getting involved by liking or joining the Electoral Reform Society (Scotland) and by lobbying your local representatives at Council, Local Assembly and Governmental level. Check out TheyWorkForYou to find out who they are!

NB. these images were made for demonstration purposes only, assumptions are made and errors happen, so if something is wrong its not intentional! These image were made my me (Rob Kent) using the Python programming language, PostgreSQL, NumPy and matplotlib with data from BBC News, the Office for National Statistics and the Ordnance Survey and OpenDataNI.

Maths is pretty!

The below image is a collage of 48 individual images of the same Mandelbrot set drawn six different ways with eight different colour palettes.

Mandelbrot Collage

A collage of Mandelbrot set images using different colour palettes and drawing techniques.

I hope you’ll agree that some of them are truly beautiful. In fact I’m gonna create some much larger versions of a few of them because the detail and patterns are gorgeous. Just need to find a wall to hang them on…

Anywho, they were generated by me using a custom Python algorithm. I may well package this up with a GUI at some point so other people can play with the parameters and create there own pretty and unique images, but until then you’ll have to enjoy these.

Like and share 🙂

Our Voting System Is Broken!

Please take a moment to look at these two maps, especially if you voted in the recent General Election (‪#‎GE2015‬).

After looking at the results of the General Election in some detail over the past few days it has become more apparent than ever to me that our voting system in this country is very, very broken! We don’t actually vote for parties (and therefore governments), we simply vote for our local representative. The total number of votes a party receives is not taken into consideration at all, which seems a little strange, particularly when you consider that all through the election campaigns we hear ‘Vote Conservative’ or ‘Vote SNP’, not ‘Vote Bob Smith, your local MP’.

So, being a tremendous geek, I got my hands on all the numbers, created a database and generated the following two images.

The first image is the results as you will have seen them using the First Past the Post method. I merely created this one for reference.

First Past the Post

The second image is the same numbers, this time evaluated using the D’Hondt method for calculating Proportional Representation. This method quite literally calculates the number of seats a party should get based on there proportion of the overall votes cast. I then assigned constituencies to each party (largest first) based on the constituencies in which they received the most votes, thus insuring that (for the most part and where possible) the local representative reflects the local preference.

D'Hondt Proportional Representation

As can be seen, the difference is astounding! UKIP would have 83MPs not 1, the Green Party would have 25MPs not 1, the SNP would have 31MPs not 56!

Seeing these results, I really don’t understand how anyone can argue against the fact that, using PR, we would have a balanced, fairer and more representative government.

Please like and share this if you agree. Lets make ourselves heard.

Also, consider getting involved by liking or joining the Electoral Reform Society (Scotland) and by lobbying your local representatives at Council, Local Assembly and Governmental level. Check out TheyWorkForYou to find out who they are!

NB. these images were made for demonstration purposes only, assumptions are made and errors happen, so if something is wrong its not intentional! These image were made my me (Rob Kent) using the Python programming language, SQLite, NumPy and matplotlib with data from BBC News, the Office for National Statistics and the Ordnance Survey.

QtWebKit and Favicons

I’m currently working on developing a stripped down tabbed browser for a project and therefore wanted to get the favicon for the page that is being displayed in each tab. However, there seems to be a bug with Qt4/WebKit when it comes to using the QWebSettings.iconForUrl() method in that it doesn’t seem to (consistently at least) return anything… so I wrote my own solution as follows:

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebKit import *
from PyQt5.QtNetwork import *
 
from html.parser import HTMLParser
 
class QtFavicon(QObject):
    NAIVE = 0
    PAGE  = 1
    ICON  = 2
 
    class _Threaded(QObject):
        finished=pyqtSignal()
 
        def __init__(self, url, parent=None, **kwargs):
            QObject.__init__(self, parent, **kwargs)
 
            self._nam=None
            self._url=QUrl(url)
            self.data=QByteArray()
 
        def request(self, url, reason=0):
            self._reason=reason
            request=QNetworkRequest(url)
            request.setRawHeader("User-Agent", "PyQt4.QtNetwork.QNetworkAccessManager")
            request.setRawHeader("Connection", "close")
 
            if not self._nam: self._nam=QNetworkAccessManager()
            self._reply=self._nam.get(request)
            self._reply.finished.connect(self._finished)
 
        @pyqtSlot()
        def start(self): self.request(self._url.resolved(QUrl("favicon.ico")))
 
        @pyqtSlot()
        def _finished(self):
            try:
                if self._reply.error()==QNetworkReply.NoError:
                    if self._reason in (QtFavicon.NAIVE, QtFavicon.ICON) and \
                            self._reply.bytesAvailable()>0:
                        self.data=self._reply.readAll()
 
                    elif self._reason in (QtFavicon.PAGE,) and self._reply.bytesAvailable()>0:
                        page=self._reply.readAll()
                        p=QtFavicon._Parser()
                        p.feed(page.data())
                        self.request(QUrl(p.faviconHref), QtFavicon.ICON)
                        return
 
                elif self._reply.error()==QNetworkReply.ContentNotFoundError:
                    if self._reason in (QtFavicon.NAIVE,):
                        return self.request(self._url, QtFavicon.PAGE)
            except: pass
            self.finished.emit()
 
    class _Parser(HTMLParser):
        def __init__(self, *args, **kwargs):
            HTMLParser.__init__(self, *args, **kwargs)
 
            self.faviconHref=None
 
        def handle_starttag(self, tag, attrs):
            attrs=dict(attrs)
            if tag.lower()!="link" or \
                    'rel' not in attrs or \
                    attrs['rel'] not in ("icon", "shortcut icon"): return
            self.faviconHref=attrs['href']
 
    @staticmethod
    def iconForUrl(url, timeout=10000):
        thread=QThread()
        threaded=QtFavicon._Threaded(url, finished=thread.quit)
        thread.started.connect(threaded.start)
        threaded.moveToThread(thread)
 
        _timeout=QTime.currentTime().addMSecs(timeout)
        thread.start()
        while not thread.isFinished():
            qApp.processEvents()
            if QTime.currentTime()<_timeout: continue
            thread.terminate()
            thread.wait(timeout)
            break
             
        p=QPixmap()
        data=threaded.data
        if data.length()>0: p.loadFromData(threaded.data)
        return QIcon(p)
 
if __name__=="__main__":
    from sys import argv, exit
 
    class Widget(QWidget):
        def __init__(self, parent=None, **kwargs):
            QWidget.__init__(self, parent, **kwargs)
 
            l=QVBoxLayout(self)
            self._href=QLineEdit(self)
            l.addWidget(self._href)
            l.addWidget(QPushButton("Get Favicon", self, clicked=self.iconForUrl))
 
        @pyqtSlot()
        def iconForUrl(self):
            href=self._href.text()
            self.setWindowTitle(href)
            self.setWindowIcon(QtFavicon.iconForUrl(href))
 
    a=QApplication(argv)
    w=Widget()
    w.show()
    w.raise_()
    exit(a.exec_())

I hope somebody else finds this useful.

Mapping a Network Drive with Python

Recently I found it necessary for an application I’m creating to automatically map a network drive when the program starts if the operating system (Windows 7) has not all ready done so. This may seem like a relatively simple think to want to do, particularly when you consider how simple it is for the user to do it manually from an Explorer window, however a little Googling reveals that is actually quite a task and almost impossible from Python without the use of a 3rd party library, e.g. pywin32. As I would like my application to be lightweight, portable and easily built with py2exe I am therefore trying to keep the dependency count low so I thought I would instead go about implementing my own method with a single simple DLL written in C++ (my second favourite language) which would take advantage of the Windows API directly.

So, step one was to fire up Visual C++ 2008 Express and start a new DLL solution imaginatively called ‘MapDrive’. This is done by selecting ‘File > New > Project…’ and selecting ‘Win32 Console Application’ from the ‘Templates’ section of the resulting dialog. Pressing the ‘Ok’ button in this dialog results in a new one titled ‘Win32 Application Wizard’, the second page of which allows you to set the ‘Application Type’ to ‘DLL’. I also checked the ‘Precompiled header’ option under the ‘Additional options’ section. Clicking the ‘Finish’ button in this dialog will result in a project containing a number of header and source files with example DLL function implementations in them. For this project we need the following six files:

  • MapDrive.h
  • stdafx.h
  • targetver.h
  • dllmain.cpp
  • MapDrive.cpp
  • stdafx.cpp

targetver.h is auto-generated and needs no modification or explanation. The same can be said for dllmain.cpp except that an extra include line is required for our MappDrive.h implementation as follows:

// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include "MapDrive.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

stdafx.cpp is a simple one-liner to include its header file:

#include "stdafx.h"

stdafx.h itself includes most of the Windows headers and libraries required for the project as follows:

#pragma once
#include "targetver.h"

#define WIN32_LEAN_AND_MEAN

#ifndef UNICODE
#define UNICODE
#endif
#pragma comment(lib, "mpr.lib")

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <Winnetwk.h>

Finally, we get to the implementation of our functionality. MapDrive.h defines the only function we actually wish to expose and the MAPDRIVE_API macro which will expose our function to the outside world in the C language style (i.e. without C++ name mangling):

#ifdef MAPDRIVE_EXPORTS
#define MAPDRIVE_API extern "C" __declspec(dllexport)
#else
#define MAPDRIVE_API __declspec(dllimport)
#endif

MAPDRIVE_API int mapDrive(LPWSTR, LPWSTR, LPWSTR, LPWSTR, LPWSTR);

MapDrive.cpp contains the implementation of our mapDrive() function as well as a convenience function that nicely formats error messages from the Windows API for us as follows:

#include "stdafx.h"
#include "MapDrive.h"
#include <strsafe.h>

#define ASCII 20127

void formatError(DWORD error, LPWSTR errorStr){
	LPVOID msg, display;

	FormatMessage(
		FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
		error,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		(LPTSTR) &msg,
		0,
		NULL
	);
	
	int sizeNeeded=lstrlen((LPCTSTR)msg);
	display=(LPVOID)LocalAlloc(LMEM_ZEROINIT, sizeNeeded*sizeof(TCHAR)); 
    StringCchPrintf((LPTSTR)display, LocalSize(display)/sizeof(TCHAR), TEXT("%s"), msg); 
	StringCbPrintf(errorStr, 80, L"%s", display);
 
	LocalFree(msg);
    LocalFree(display);
}

MAPDRIVE_API int mapDrive(LPWSTR name, LPWSTR path, LPWSTR username, LPWSTR password, LPWSTR message){
	NETRESOURCE nr;
	memset(&nr, 0, sizeof(NETRESOURCE));
	nr.dwType=RESOURCETYPE_ANY;
	nr.lpLocalName=name;
	nr.lpRemoteName=path;
	nr.lpProvider=NULL;

	DWORD flags=CONNECT_UPDATE_PROFILE;

	DWORD retVal=WNetAddConnection2(&nr, password, username, flags);
	if(retVal==NO_ERROR) return 0;

	formatError(retVal, message);
	return retVal;
}

The mapDrive() function simply constructs a NETRESOURCE struct and populates it with desired drive letter and the UNC path to be mapped and passes it to the WNetAddConntection2() Windows API function along with the user credentials to be used and a flag which tells the operating system to automatically remap this drive if possible when booting in the future. If this function returns 0 (success) then it returns, otherwise the formatError() function is called to get an error string for the returned error code (which is written to the pointer passed as an argument).

Thats all the C++ required and compiling this solution in Release mode results in a nice little DLL only 8KB in size. All we need do now is create a Python interface to the DLL. I actually implemented this is in two ways, the first being my usual approach using just ctypes and the second using Qt (via PyQt, because I’m a big fan and the application I’m writing depends on it), mostly as an experiment. The code is as follows:

import ctypes
from ctypes.wintypes import LPWSTR
from PyQt4.QtCore import QLibrary

class MapDrive(object):
	_handle=ctypes.cdll.LoadLibrary("MapDrive.dll")

	@classmethod
	def mapDrive(cls, name, path, username, password):
		m=LPWSTR(" "*80)
		ok=cls._handle.mapDrive(
		    LPWSTR(name),
		    LPWSTR(path),
		    LPWSTR(username),
		    LPWSTR(password),
		    m
		)
		return ok, m.value

class MapDrive2(object):
	_handle=QLibrary("MapDrive.dll")
	assert _handle.load()
	assert _handle.isLoaded()
	_mapDrive=ctypes.CFUNCTYPE(
		ctypes.c_int,
		LPWSTR,
		LPWSTR,
		LPWSTR,
		LPWSTR,
		LPWSTR
	)(int(_handle.resolve("mapDrive")))

	@classmethod
	def mapDrive(cls, name, path, username, password):
		m=LPWSTR(" "*80)
		ok=cls._mapDrive(
		    LPWSTR(name),
		    LPWSTR(path),
		    LPWSTR(username),
		    LPWSTR(password),
		    m
		)
		return ok, m.value

if __name__=="__main__":
	print "MapDrive 1:", MapDrive.mapDrive(
		"Y:", 
		"\\\\path\\to\\be\\mapped",
		"username",
		"password"
	)

	print "MapDrive 2:", MapDrive2.mapDrive(
		"Y:", 
		"\\\\path\\to\\be\\mapped",
		"username",
		"password"
	)

To be honest, the pure ctypes method is cleaner, neater and shorter and is the one I will be using as, unlike the QLibrary method, it automatically detects the C++ function signature which somehow seems more safe and secure. I only include the QLibrary example as I have used this from C++ in the past and it certainly simplifies the process in that language and I was simply wondering if it were possible to use this method from Python too (which it is, as proved).

I hope this post and the example it contains is useful to someone, somewhere and if you have any questions or comments I will happily respond. I will also try and either upload a zip of the all the C++ and Python code or place it in my Google code repository at some point.

Python & C#: Making Them Talk Nicely

Over the years I have had to write a number of interfaces and wrappers between different programming languages (C/C++ and Python, Ada and C, Java and Python to name a few). Some of these are easy to achieve, other less so. A new challenge came along today with a need to access a C# class from Python. After a number of false starts I came up with the following solution which is to package the C# code as a COM object, register it with the OS (Windows) and access this from Python. There are surprisingly few full, correct and complete examples of this out there so I though I would provide one.

The first thing to do is to create a C# COM object. I used Visual Studio 2013 and created a new Visual C# Class Library solution. It is necessary to go in to the “Build” tab of the projects properties dialog and check the “Register for COM interop” option. The following is all the necessary code:

using System;
using System.Runtime.InteropServices;

namespace TestCOM
{
    [ComVisible(true)]
    [Guid("EAA4976A-45C3-4BC5-BC0B-E474F4C3C83F")]
    public interface ComClass1Interface {
        void helloWorld();
    }

    [ComVisible(true)]
    [Guid("0D53A3E8-E51A-49C7-944E-E72A2064F938"),
            ClassInterface(ClassInterfaceType.None)]
    public class ComClass1 : ComClass1Interface {
        public void helloWorld() { Console.WriteLine("Hello World"); }
    }
}

Building this solution will generate a type library file (TLB) and as well as a DLL which will be registered with the OS (you may need to run Visual Studio “As Administrator” for this to happen).

Now that we have successfully created and registered our COM object we can get on with accessing it from Python. To do this we use the comtypes package (easy_install comtypes) as follows:

from comtypes.client import GetModule, CreateObject
GetModule("TestCOM.tlb")

from comtypes.gen.TestCOM import ComClass1

o=CreateObject(ComClass1)
o.helloWorld()

NB You will need to change the path passed to GetModule() if the TLB file is not in the same directory as the Python script.

When you run this script, assuming everything has gone to plan, you will see something akin to the following in the console:

> python comtest.py
# Generating comtypes.gen._4146E699_C65F_479C_961A_BA3D8EFFC700_0_1_0
# Generating comtypes.gen._BED7F4EA_1A96_11D2_8F08_00A0C9A6186D_0_2_4
# Generating comtypes.gen.TestCOM
Hello World

The “# Generating…” lines will only occur when the content of the TLB/DLL files are changed and comtypes has to update the auto-generated Python module. The “Hello World” line is our C# code printing to the console, success!

Waiting for a Signal

Occasionally it becomes necessary to block and wait for a signal to be emitted. This may seem a little oxymoronic when using an event driven framework like Qt where the whole point is not to block, but, I promise you, sometimes it is necessary. The issue is that although you may want to block the execution of some function or method until a signal is emitted, you don’t want to block the event loop because the GUI will become unresponsive, not good. Therefore, we need sprinkle a little fairy dust over the problem and block one loop whilst executing another. However, we don’t want to wait indefinitely, we need to have a fallback that will release the block after some suitable period if the signal isn’t emitted in a timely fashion (if at all). I’ve tried, with varying levels of success, a few different methods of achieving this and the following is the latest, which is a well honed melange:

import sip
sip.setapi('QString',2)
sip.setapi('QVariant',2)

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

def waitForSignal(sender, senderSignal, timeoutMs, expectedSignalParams=None):
    timer=QTimer(singleShot=True)
    loop=QEventLoop()

    senderSignalArgsWrong=[]

    @pyqtSlot()
    def senderSignalSlot(*args):
        senderSignalArgsWrong.append((expectedSignalParams is not None) and 
                (expectedSignalParams!=args))
        loop.quit()

    senderSignal.connect(senderSignalSlot)
    timer.timeout.connect(loop.quit)

    QTimer.singleShot(0, sender)
    timer.start(timeoutMs)

    ex=[]
    def exceptHook(type_, value, traceback):
        ex.append(value)
        oeh(type_, value, traceback)

    oeh=sys.excepthook
    sys.excepthook=exceptHook

    loop.exec_()
    if ex: raise ex[0]

    ret=timer.isActive()
    timer.stop()
    senderSignal.disconnect(senderSignalSlot)
    timer.timeout.disconnect(loop.quit)

    sys.excepthook=oeh

    return ret and senderSignalArgsWrong and (not senderSignalArgsWrong[0])

if __name__=="__main__":
    from sys import argv, exit

    class Widget(QWidget):
        def __init__(self, parent=None, **kwargs):
            QWidget.__init__(self, parent, **kwargs)

            l=QVBoxLayout(self)
            l.addWidget(QPushButton("Start", self, clicked=self.start))
            self._stopButton=QPushButton("Stop", self)
            l.addWidget(self._stopButton)

        @pyqtSlot()
        def start(self):
            print "Start"
            ret=waitForSignal(self.work, self._stopButton.clicked, 5000)
            print "Finished:", ret

        @pyqtSlot()
        def work(self): print "Work"

    a=QApplication(argv)
    w=Widget()
    w.show()
    w.raise_()
    exit(a.exec_())

The basic principle is to block the execution of the main event loop and create a second loop to handle events in the mean time. A timer is used to release the block in the event of a failure. A timer is also used to execute the worker function to make sure it is executed in the correct event loop and the desired signal is caught. A certain amount of inspiration for this particular implemenation was gathered from the test suite for the Enki text editor.

(Py)Qt4 Font on MacOSX Mavericks

In preparing my project for its next release I have found the default font on MacOSX 10.9 Mavericks has changed to be retina optimised which seems to upset (Py)Qt4. The symptom is that text tends to be vertically misaligned on widgets such as QPushButton and QComboBox. This can be easily rectified however as follows:

import platform
if platform.system()=='Darwin':
    _release,_versioninfo,_machine=platform.mac_ver()
    if float(_release[:4])>=10.9: QFont.insertSubstitution(".Lucida Grande UI", "Lucida Grande")

If you prefer to your thing with Qt in C++, then the following is for you:

#ifdef Q_OS_MACX
  if (QSysInfo::MacintoshVersion>QSysInfo::MV_10_8)
    QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande");
#endif

Pretty Math Formulae with PyQt4 and MathTran

This is the second post on the subject of producing pretty math formulae that can be used with PyQt4 GUI’s. In the first I used matplotlib’s MathText functionality to plot a TeX formatted string and then manipulated that plot to appear as a QLabel. David Boddie kindly commented on that post and suggested that I take a look at an article he produced for Qt Quarterly (Using a Simple Web Service with Qt) in which he describes using the MathTran web service to produce the same result. I won’t repeat all of the detail here, but essentially its a simple case of performing a get request into which is encoded the TeX string you want rendered and a PNG image is returned (assuming your TeX is sane). As this article was written a while ago and was, therefore, using the now obsolete QHttp API, I thought I would update the example David gave to use the current network API and present it as follows:

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtNetwork import *

class Window(QWidget):
    def __init__(self, parent=None, **kwargs):
        QWidget.__init__(self, parent, **kwargs)

        self.setWindowTitle("MathTran Equation Viewer V2")

        self._nam=QNetworkAccessManager(self, finished=self.updateForm)

        l=QVBoxLayout(self, spacing=4, margin=4)

        self._outputLabel=QLabel(self, frameShape=QFrame.StyledPanel)
        l.addWidget(self._outputLabel, stretch=1)

        self._equationEditor=QTextEdit(self)
        l.addWidget(self._equationEditor)

        self._clearButton=QPushButton("&Clear", self, clicked=self.clearForm)
        self._updateButton=QPushButton("&Update", self, clicked=self.fetchImage)

        bb=QDialogButtonBox(self)
        bb.addButton(self._clearButton, QDialogButtonBox.ResetRole)
        bb.addButton(self._updateButton, QDialogButtonBox.ApplyRole)
        l.addWidget(bb)

    @pyqtSlot()
    def clearForm(self):
        self._outputLabel.setPixmap(QPixmap())
        self._equationEditor.clear()

    @pyqtSlot()
    def fetchImage(self):
        self._clearButton.setEnabled(False)
        self._updateButton.setEnabled(False)
        self._equationEditor.setReadOnly(True)

        url=QUrl()
        url.setHost('mathtran.org')
        url.setScheme('http')
        url.setPath('/cgi-bin/mathtran')
        url.setQueryDelimiters('=', ';')
        url.addQueryItem('D','3')
        url.addQueryItem('tex', self._equationEditor.toPlainText())
        self._nam.get(QNetworkRequest(url))

    @pyqtSlot(QNetworkReply)
    def updateForm(self, reply):
        self._clearButton.setEnabled(True)
        self._updateButton.setEnabled(True)
        self._equationEditor.setReadOnly(False)

        if reply.error()!=QNetworkReply.NoError: return

        image=QImage.fromData(reply.readAll())
        if image.isNull(): return

        self._outputLabel.setPixmap(QPixmap.fromImage(image))

if __name__=="__main__":
    from sys import argv, exit

    a=QApplication(argv)
    w=Window()
    w.show()
    w.raise_()
    exit(a.exec_())

The following is a screen shot using the same TeX representation of the DFT as in previous example:

MathTran Equation Viewer V2

The DFT as rendered by MathTran

Thanks go to David Boddie for his suggestions and for his permission to update and repost this solution.

py2app and PyEnchant

If there is one thing that is guaranteed to give me a headache and cause teddy to leave the pram at the speed of sound it is the task of packaging Python applications for distribution. This should statement should not be seen as a criticism of the available tools or the lovely people who produce them: its an incredibly difficult task and projects like py2exe and py2app do definitely make the task significantly easier than it may otherwise be, but it can still be a pain the proverbial!

So, todays challenge: setup a Mac OSX 10.6 Snow Leopard machine to build an application that includes PyQt4, matplotlib, numpy, a plethora of other packages and PyEnchant. For those not in the know, PyEnchant provides a Python wrapper to the excellent Enchant spell checking library. I’m not going to write an exhaustive tutorial on py2app here, you can find much better examples elsewhere (although I can if anyone is interested), I’m just going to explain how to install Enchant/PyEnchant in such a way that they can be packaged and the options that need to be passed to py2app’s setup method to ensure they will work when packaged.

The first thing is: don’t install Enchant with Homebrew as many places suggest! In fact, you don’t need to install Enchant (or Homebrew for that matter) at all. Just go to PyPi and download the PyEnchant egg (here) for your version of Python. In my case this was “pyenchant-1.6.5-py2.7-macosx-10.4-universal.egg”. Don’t be confused by the ‘macosx-10.4’ bit, I have this package working perfectly with Snow Leopard, Lion and Mountain Lion (10.6, 10.7 and 10.8 respectively). Install the egg as normal (i.e. easy_install pyenchant-1.6.5-py2.7-macosx-10.4-universal.egg). Now for the magic! If you have a look in your site-packages directory, the path to which (if you don’t know it) can be found by executing the following at the command line:

python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"

You’ll see there are actually two PyEnchant eggs… which is where the fun begins! One contains PyEnchant without the associated (and imperative) dylib file for Enchant. The other does contain the dylib. However, the one that is listed in the easy_install.pth file (which governs Python’s discovery of packages installed from eggs) is not the one we want! So, you should have two folder named something like:

  • pyenchant-1.6.5-py27.egg
  • pyenchant-1.6.5-py27-macosx-10.4-universal.egg

Delete the first of these. No really, go on delete it! Now open easy_install.pth with an editor (and the appropriate permissions, i.e. sudo). Somewhere in the list of paths (after “import sys; sys.__plen = len(sys.path)”) you should find the path to the first of the PyEnchant eggs listed above (the one you just deleted). Change this path to that of the other egg, save and exit. That’s the scary bit done, just run your Python interpreter and make sure you can import and use the PyEnchant package. The little demo from the PyEnchant website below should work beautifully:

>>> import enchant
>>> d = enchant.Dict("en_US")
>>> d.check("Hello")
True
>>> d.check("Helo")
False
>>> d.suggest("Helo")
['He lo', 'He-lo', 'Hello', 'Helot', 'Help', 'Halo', 'Hell', 'Held', 'Helm', 'Hero', "He'll"]

Ok, now for the py2app side of things! In your setup.py script you wil (or at least should!) have a call to the “setup” method. The options that are passed to this method generally take the form of a dictionary. You will need the following options included in that dictionary, I’ve added the basic ones for reference within the structure:

{
    'app':'your_script.py',
    'setup_requires':['py2app','pyenchant'],
    'options':{
        'py2app':{
            'packages':['enchant'],
            'argv_emulation':True,
        }
    }
}

Setting the options this way ensures that the Enchant dylib is included in the ‘Frameworks’ folder of the app bundle uncompressed rather than zipped into site-packages as part of ‘Resources’, which would be bad.

So thats it. I have now successfully built my app on several versions of Mac OSX using these deceptively simple methods (which took me ages to work out!). I hope this helps somebody else faced with the same task. Please ask any questions or offer suggestions by commenting on this post.