Wednesday, August 12, 2009

Convert html files to pdf

#html2pdf.py
#
#Convert an html file into pdf. This script uses WebKit 
#and runs on OS X 1.5
#
#Usage: 
# python html2pdf.py <inputfile> <outputfile>
#
#Written using code from
#http://cocoadevcentral.com/articles/000074.php
#http://www.paulhammond.org/webkit2png

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

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

    def printFrame(self, frame):
        frameview = frame.frameView()
        sharedInfo = NSPrintInfo.sharedPrintInfo()
        sharedDict = sharedInfo.dictionary()
        printInfoDict = NSMutableDictionary.dictionaryWithDictionary_(
            sharedDict)
        printInfoDict.setObject_forKey_(NSPrintSaveJob,
                                        NSPrintJobDisposition);
        printInfoDict.setObject_forKey_(self.pdffile, 
                                       NSPrintSavePath)
        
        printInfo = NSPrintInfo.alloc().initWithDictionary_(printInfoDict)
        printInfo.setHorizontalPagination_(NSAutoPagination);
        printInfo.setVerticalPagination_(NSAutoPagination);
        printInfo.setVerticallyCentered_(False);
        

        printOp = frameview.printOperationWithPrintInfo_(printInfo)
        printOp.setShowPanels_(False)
        printOp.runOperation()
        NSApplication.sharedApplication().terminate_(None)


def main(args):

    htmlfile=args[1]
    pdffile=args[2]
    rect = ((00),(400400))
    
    app = NSApplication.sharedApplication()
    
    win = NSWindow.alloc()
    win.initWithContentRect_styleMask_backing_defer_ (rect, 
            NSBorderlessWindowMask, 20)

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

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

    mainFrame = webview.mainFrame()
    mainFrame.loadRequest_(request)

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

    win.setContentView_(webview)

    app.run()

if __name__ == "__main__":
    import sys
    main(sys.argv)

Monday, May 04, 2009

Create a popup bookmarklet

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

import sys
import urllib
import optparse

usage = "python buildbookmarklet.py [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",
                  default='Bookmarklet',
                  help="The title of the bookmarklet.")
(options, args) = parser.parse_args()


s = ('my_window= window.open ("","win","status=1,width=%i,height=%i");'
    'my_window.document.write(%s);'
     (options.width, options.height, repr(sys.stdin.read())))


print """
<html>
<a href="
javascript:%s">%s</a>
</html>
"
"" % (urllib.quote(s), options.title)

Friday, January 02, 2009

Create a mercurial mirror of an svn branch

#hgsvnsync.py
#
#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.
#
#Usage:
#To create a new mirror
# python hgsvnsync.py init svn_url mirror_location
#
#To update the mirror
# python hgsvnsync.py update mirror_location
#
# Changes
# 23-Jan-2009 Updated to working version.

import commands
import re
import os

hgignore= """syntax: regexp
[.]svn/
[.]hgignore
[.]commitmessage"""


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')
    f.write(content)
    f.close()

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) =  re.search(
        '------------------------------------------------------------------------\n'+
        'r(\d+) [|] (\w+) [|] ([^(]+)[^|]+[|] (\d+) line[s]?\n', log).groups()
    message = "%s\n\nSvn Revision %s" % ( 
                "\n".join(log.split('\n')[3:(3+int(lines))]),rev)
    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__':
    main()
    

Saturday, March 08, 2008

Creating a patch as a zip

#diffdiff.py
# Create a zip file containing the difference between two directories.
# Usage: python dirdiff.py 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 diff.zip 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)):
                write(f)
        for f in set(new_files).difference(old_files):
            write(join(new_base,f))
        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))
    zf.close()

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

Thursday, February 28, 2008

Lisp in a single expression

#lisp.py
#
#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:]])
                    (len(env)-env[::-1].index("(")-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)]], 
                        [])[0]))

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):
        total+=n&1
        n>>=1

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

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

cleancvs.py

#cleancvs.py
#
#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.
#
#usage:
#python cleancvs.py [path to clean]


import sys
import shutil

dir = sys.argv[1]

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