Wednesday, August 12, 2009

Convert html files to pdf
#Convert an html file into pdf. This script uses WebKit 
#and runs on OS X 1.5
# python <inputfile> <outputfile>
#Written using code from

import WebKit
from Foundation import NSObject, NSMutableDictionary, NSURL, NSURLRequest
from AppKit import (NSPrintInfo, NSPrintSaveJob, NSPrintJobDisposition, 
                    NSPrintJobDisposition, NSPrintSavePath, NSPrintInfo, 
                    NSAutoPagination, NSApplication, NSWindow, 

class WebkitLoad (NSObject, WebKit.protocols.WebFrameLoadDelegate):
    def webView_didFinishLoadForFrame_(self,webview,frame):
        if (frame == webview.mainFrame()):

    def printFrame(self, frame):
        frameview = frame.frameView()
        sharedInfo = NSPrintInfo.sharedPrintInfo()
        sharedDict = sharedInfo.dictionary()
        printInfoDict = NSMutableDictionary.dictionaryWithDictionary_(
        printInfo = NSPrintInfo.alloc().initWithDictionary_(printInfoDict)

        printOp = frameview.printOperationWithPrintInfo_(printInfo)

def main(args):

    rect = ((00),(400400))
    app = NSApplication.sharedApplication()
    win = NSWindow.alloc()
    win.initWithContentRect_styleMask_backing_defer_ (rect, 
            NSBorderlessWindowMask, 20)

    webview = WebKit.WebView.alloc().init()

    url = NSURL.alloc().initFileURLWithPath_(htmlfile)
    request = NSURLRequest.alloc().initWithURL_(url)

    mainFrame = webview.mainFrame()

    loaddelegate = WebkitLoad.alloc().init()
    loaddelegate.pdffile = pdffile


if __name__ == "__main__":
    import sys

Monday, May 04, 2009

Create a popup bookmarklet
#Create a popup bookmarklet from some html content.
#echo "<h1>Hello World</h1>" | python > out.html

import sys
import urllib
import optparse

usage = "python [options]"
parser = optparse.OptionParser(usage=usage)

parser.add_option("-l""--length", type="int", dest="height",
                  default=150, help="The height of the popup window.")
parser.add_option("-w""--width", type="int", dest="width",
                  default=350, help="The width of the popup window.")
parser.add_option("-t""--title", type="string", dest="title",
                  help="The title of the bookmarklet.")
(options, args) = parser.parse_args()

s = ('my_window= ("","win","status=1,width=%i,height=%i");'
     (options.width, options.height, repr(

print """
<a href="
"" % (urllib.quote(s), options.title)

Friday, January 02, 2009

Create a mercurial mirror of an svn branch
#Create a mercurial mirror of a branch in an svn repository
#This scripts requires that the commands svn and hg be present
#in the path.
#To create a new mirror
# python init svn_url mirror_location
#To update the mirror
# python update mirror_location
# Changes
# 23-Jan-2009 Updated to working version.

import commands
import re
import os

hgignore= """syntax: regexp

def getRevisions(svn_url, frm=1):
    s = commands.getoutput('svn -r%s:HEAD log %s' % (frm, svn_url))
    return re.findall('------------------------------------------------------------------------\n'+
            'r(\d+) [|] \w+ [|] ', s)

def createFile(filename, content):
    f = file(filename, 'w')

def init(svn_url, dest):
    commands.getoutput('svn co -r1 %s %s' % (svn_url, dest))
    commands.getoutput('hg init %s' % dest)
    createFile(os.path.join(dest, '.hgignore'), hgignore)

def parseLog(log):
    (rev, commiter, date, lines) =
        'r(\d+) [|] (\w+) [|] ([^(]+)[^|]+[|] (\d+) line[s]?\n', log).groups()
    message = "%s\n\nSvn Revision %s" % ( 
    return (rev, commiter, date, message)
def parseInfo(info):
    return dict(re.findall("(\w+): (.*)", info))

def commitRevs(svn_url, dest, frm):
    revs = getRevisions(svn_url, frm)[1:]
    for rev in revs:
        print "Commiting revision %s" % rev
        commands.getoutput('svn update -r%s %s' % (rev, dest))
        logMsg = commands.getoutput('svn log -rCOMMITTED %s' % dest)
        (rev, commiter, date, message) = parseLog(logMsg)
        commitmessagepath = os.path.join(dest, '.commitmessage')
        createFile(commitmessagepath, message)
        commands.getoutput("hg commit -A -l %s -d '%s' -u %s %s" % 
                            (commitmessagepath, date, commiter, dest))

def main():
    import sys
    if sys.argv[1]=='init':
        svn_url = sys.argv[2]
        dest = sys.argv[3]
        init(svn_url, dest)
        commitRevs(svn_url, dest, 1)
    elif sys.argv[1]=='update':
        dest = sys.argv[2]
        info = parseInfo(commands.getoutput('svn info %s' % dest))
        rev = info['Revision']
        svn_url = info['URL']
        commitRevs(svn_url, dest, rev)

if __name__ == '__main__':

Saturday, March 08, 2008

Creating a patch as a zip
# Create a zip file containing the difference between two directories.
# Usage: python newdir olddir [outputfile]
# Files files in newdir that are different in olddir or are not present
# will be zipped. If the outputfile parameter is not  provided the a 
# file will be created.

from os import walk, stat
from os.path import join, sep, split
from sys import argv
from itertools import izip
from zipfile import ZipFile, ZIP_DEFLATED

def chop(base, path):
    if not base.endswith(sep):
        base = base + sep
    return path[len(base):]

def listfiles(path):
    for base, dirs, files in walk(path):
        for f in files:
            yield join(base, f)

def dirdiff(new_path, old_path, diff_file):
    zf = ZipFile(diff_file, "w")
    def write(file_path):
        zf.write(file_path, chop(new_path, file_path), ZIP_DEFLATED)
    for old, new in izip(walk(old_path), walk(new_path)):
        (old_base, old_dirs, old_files) = old
        (new_base, new_dirs, new_files) = new
        for d in set(new_dirs).difference(old_dirs):
            for f in listfiles(join(new_base, d)):
        for f in set(new_files).difference(old_files):
        fs = set(old_files) & set(new_files)
        ds = set(old_dirs) & set(new_dirs)
        old_dirs[:] = ds
        new_dirs[:] = ds
        for f in fs:
            file_old = join(old_base, f)
            file_new = join(new_base, f)
            if (stat(file_old).st_mtime != stat(file_new).st_mtime 
                and file(file_old).read()!=file(file_new).read()):
                write(join(new_base, f))

if __name__ == "__main__":
    new = argv[1]
    old = argv[2]
    if len(argv) == 4:
    dirdiff(new, old, out)

Thursday, February 28, 2008

Lisp in a single expression
#An interpreter for a simple scheme like lexically 
#scoped language implemented as single python expression.
#The interpreter is limited to the lambda special form and a
#sum function. The data types supported are positive integers
#and symbols.

import re
from itertools import *
iterpreter = (lambda s: (
    (lambda g: lambda env, exp: g(g)(env, exp))
    (lambda g: (lambda interpret:(
        lambda env, exp:{
            list:lambda exp:(
                (exp[:1]==["lambda"]) and 
                    (lambda env: lambda params: 
                        (lambda nenv: [interpret(nenv, e) 
                                for e in exp[2:]][-1])
                            (lambda x: dict(zip(exp[1], params)).get(x, False) 
                                or env(x)))(env) 
                or (lambda pexp: pexp[0](pexp[1:]))([interpret(env, e) 
                    for e in exp])),
            str:lambda exp: env(exp), int:lambda exp: exp
        }[type(exp)](exp)))(lambda env, exp:g(g)(env, exp))))
        (lambda x:{"sum":(lambda params: sum(params))}.get(x, False), 
        reduce(lambda env, v:
            (v==")" and
                (lambda:((lambda i:env[:i]+[env[i+1:]])
            or (lambda:env+[v]))(),
                [(i==2 and int(e[i]) or e[i]) for e, i in 
                    [(e,sum([c*(i is not ""for i, c in zip(e, count())])) 
                        for e in re.findall(r"(\()|(\))|(\d+)|(\w+)",s)]], 

s = "((lambda (a b) (sum a (b))) 1 (lambda () 8))"
v = iterpreter(s)
print v

Tuesday, September 04, 2007

Count the number of on bits in a 32 bit integer

#Count the number of on bits in in a 32bit integer

def bin2int(s):
    return sum(int(n)*2**i for i, n in zip(range(len(s)), s[::-1]))

def bitcount1(n):
    total = 0
    for i in range(32):

masks = [(1,  '01010101010101010101010101010101'),
         (2,  '00110011001100110011001100110011'),
         (4,  '00001111000011110000111100001111'),
         (8,  '00000000111111110000000011111111'),

masks = [(shift, bin2int(mask)) for shift, mask in masks] 

def bitcount2(n):
    for shift, mask in masks:
        n = (n & mask) + (n>>shift & mask)
    return n

def bitcount3(n):
    mask = bin2int('00010001000100010001000100010001')
    total = 0
    for i in range(4):
        total+=(((n>>i&mask)*mask) >> 28)& 0xf
    return total

Sunday, July 08, 2007
#Remove directories or files with the name CVS
#Doesn't check whether the file it is deleting is a cvs directory. 
#And expects unix path seperators.
#python [path to clean]

import sys
import shutil

dir = sys.argv[1]

for basePath, files, directories in os.walk(dir):
    if basePath.endswith("/CVS"):