Posts Tagged 'python'

Adding a Pidgin Trayicon to DWM

I am using dwm as a window manager for a long time. I hacked a few things into it which I felt were missing back then when I started to use dwm and got used to it so much that I hesitate to switch to awesome or even a newer version of dwm.

Tiled window managing is really a great idea but conflicts with programs which are design to be used in a more “traditional” desktop environment. One of those application is my instant messenger. I gave up using ncurses based messengers due to their lack of drag’n’drop capabilities, so I started using pidgin.

What I always wanted to have is some kind of tray icon which informs me about new incoming messages. The cool thing about pidgin and the whole underlying purple library is their great support for dbus. So instead of ripping off code from awesome to get full freedesktop compliant tray icons I wrote a small python script to add an icon to my dwm status bar.

The dwm status bar reads a string from stdin (passed to it by xinit) and displays it in the upper right corner of the screen. To do that it uses a loop in .xinitrc like this:

while true
do
	date=`date +'%d.%m.%Y %H:%M'`
	echo $date `pidginProbe.py`
	sleep 3
done | dwm

OK, so I need a script named pidginProbe.py which is just looking for an incoming message on the libpurple dbus interface, prints out a small notification and then terminates.

Here is how I connect to the purple dbus:

bus = dbus.SessionBus()
purple_service = bus.get_object("im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject")
purple = dbus.Interface(purple_service, "im.pidgin.purple.PurpleInterface")

Asking for an incoming message is not possible without installing a callback to a ReceivingChatMessage signal. But there is the option to ask for all active conversations which includes open chat windows and newly received messages.

def incomingMessageExists(purple):
    convs = purple.PurpleGetConversations()
    return len(convs) > 0

This function can be used to print [ ] to the screen when no message was received or [M] otherwise.

Of course much more is possible, nearly all important features can be used via dbus. See the developer documentation to find out about the other calls and signals.
I also added a notification which informs me about specific people going online (like my girlfriend ^^), here is the code example (that’s the simple version without error handling):

purple = dbus.Interface...
myid = # my ICQ/Jabber/... account id
contactid = # contact's ICQ/Jabber/... account id
myaccount = purple.PurpleAccountsFind(myid, '')
buddy = purple.PurpleFindBuddies(myaccount, contactid):
if purple.PurpleBuddyIsOnline(buddy[0]) == 1:
    print contactid, "is online"

Creating HTML Documents from Files with Wiki Syntax

I want to create some simple HTML documents with some basic layouting like heading, images and links. Writing pure HTML can be a slow and painful procedure. Usually I’m working with a lot of wikis, so I want to have a file were I can write my document using a common wiki syntax and generate HTML code from this wiki file afterwards.

There some good Perl wiki-to-html converters out there, but since I don’t want to install Perl on my Windows machine at my laboratory, I rather want to have something written in Python.

I found a nice parser and html converter for the Creole Wiki Syntax, it works well with Linux and Windows.

Unfortunately Creole is not the most powerful wiki syntax, I didn’t found out how to create a table of content yet and there are some other drawbacks. If someone knows a good wiki2html tool which doesn’t have tons of dependencies and runs fine under Windows, feel free to leave me a message.

Create New Classes With Python At Runtime

For a testing framework I want to create new classes in Python at runtime:

def mixIn(classname, parentclasses):
	if len(parentclasses) > 0:
		parents = map(lambda p:p.__name__, parentclasses)
		createclass = "class %s (%s):\n\tpass" % (classname, ",".join(parents))
	else:
		createclass = "class %s:\n\tpass" % classname
	exec createclass
	globals()[classname] = eval(classname)

This function creates a new class in the global namespace with the name classname inheriting from all classes in parentclasses, which is a list of strings.

Use the function like this:

class Foobar:
	def __init__(self, a):
		self.a = a
	def foo(self):
		return "foo" + str(self.a)

class Barfoo:
	def __init__(self, b, a):
		self.b = b
		self.a = a
	def bar(self):
		return "bar" + str(self.b) + str(self.a)

mixIn("Test", ["Foobar", "Barfoo"])
t = Test("23")
print t.foo() # this will print "foo23"
print t.bar() # this will throw an exception, because self.b is not defined

In most cases it’s not possible to generate a meaningful __init__ function automatically. The Python interpreter just takes the constructor of the first parent, but it’s possible to add another constructor afterwards.

def myinit(self, a, b):
	Foobar.__init__(self, a)
	Barfoo.__init__(self, b, a)
Test.__init__ = myinit
t = Test("23", "42")
print t.foo() # prints foo23
print t.bar() # prints bar4223

Iterating over Attributes of a Python Object

Today I needed to extract all attributes and their current value from a Python object. This is usually very handy for overriding __str__ or implementing a to_xml method. This should do the trick:

# functional style
def my_fancy_attribute_getter(self):
    attr_and_values = ((attr, getattr(self, attr)) for attr in dir(self) if not attr.startswith("__"))
    return [(attr, value) for attr, value in attr_and_values if not callable(value)]

# imperative style
def my_fancy_attribute_getter(self):
    result = []
    for attr in dir(self):
        if not attr.startswith("__"):
            value = getattr(self, attr)
            if not callable(value):
                result.append((attr, value))
    return result

Of course the line 4 can be changed to get method names too. All attributes beginning with “__” are considered to be private and should not be returned.

Edit:
There is another shorter way to do this. Every Python object has a __dict__ attribute which returns all attributes, methods and their values as dictionary:

def my_even_fancier_attribute_getter(self):
    return [(attr, value) for attr, value in self.__dict__.items() if not callable(value)]

Resizing Image Files with Python

Yesterday I came back from my holidays in Korea with a whole bunch of pictures which I now want to upload to my website to share them with my friends. Usually I take high resolution pictures with a size of 3056×1334 pixel. That’s of course to big for publishing them in the internet, so I wrote a small python script to convert them to 800×600 automatically by using the Unix convert command:

#!/usr/bin/env python
  1. -*- coding: utf-8 -*-
import sys import commands def convert(file, resize="800x600", prefix="small"): try: cmd = "convert -resize " + resize + " " + file + " " + prefix + "_" + file commands.getstatusoutput(cmd) except e: print e def usage(prog): print "Usage:", prog, "-r RESIZE -p PREFIX FILES..." if __name__ == "__main__": argv = sys.argv[1:] if len(argv) <= 1: usage(sys.argv[0]) sys.exit(-1) resize = "800x600" prefix = "small" for i in range(len(argv)): arg = argv[i] if arg == "-r" and i+1 < len(argv): resize = argv[i+1] elif arg == "-p" and i+1 < len(argv): prefix = argv[i+1] elif argv[i-1] != "-r" or argv[i-1] != "-p": convert(arg, resize, prefix)

Run the script with convert.py *.jpg and it will convert all jpg file into 800×600 pixel images while preserving the original file and creating new ones named “small_ORIGINALFILENAME”. Use the parameters “-r” and “-p” to define the resize rate or to change the prefix, see man convert for more details.

Converting flv to avi

I wrote a small python script to convert flv files to avi format using divx or xvid encoding. The trick is to use MPlayer’s “mencoder” tool to convert video streams. I copied the idea from a bash script I found on the internet, but needed a python module to integrate the flvtoavi() function into a greater project.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import os
import commands

BITRATE  = 1000

def flvtoavi(flvfile, options):
	try:
		cmd = " ".join(["mencoder",  flvfile, options, "-vf pp=lb -oac mp3lame"])
		cmd += " -lameopts fast:preset=standard -o "
		cmd += get_filename_without_suffix(flvfile)+".avi"
		commands.getstatusoutput(cmd)
	except Exception as e:
		print e

def get_filename_without_suffix(file):
	return ".".join(os.path.basename(file).split(".")[:-1])

def get_divx_options():
	return "-ovc lavc -lavcopts vcodec=mpeg4:vbitrate=%i:mbd=2:v4mv:autoaspect" % BITRATE

def get_xvid_options():
	return "-ovc xvid -xvidencopts bitrate=%i:autoaspect" % BITRATE


def usage(prog):
	print "Usage:", prog, "-divx|-xvid FLVFILES..."

if __name__ == "__main__":
	argv = sys.argv[1:]
	if len(argv) <= 1:
		usage(sys.argv[0])
		sys.exit(-1)
	format = argv[0]
	if format not in ["-divx", "-xvid"]:
		usage(sys.argv[0])
		sys.exit(-1)
	
	for file in argv[1:]:
		if format == "-divx":
			flvtoavi(file, get_divx_options())
		elif format == "-xvid":
			flvtoavi(file, get_xvid_options())