#!/usr/bin/env python
'''Find python module version'''
__author__ = "Miki Tebeka <miki.tebeka@gmail.com>"
def valueof(v):
if callable(v):
try:
return v()
except Exception:
return None
return v
def load_module(module_name):
module = __import__(module_name)
# __import__("a.b") will give us a
if ("." in module_name):
names = module_name.split(".")[1:]
while names:
name = names.pop(0)
module = getattr(module, name)
return module
def find_module_version(module_name):
module = load_module(module_name)
attrs = set(dir(module))
for known in ("__version__", "version", "version_string"):
if known in attrs:
v = valueof(getattr(module, known))
if v:
return v
for attr in attrs:
if "version" in attr.lower():
v = getattr(module, attr)
if not v:
continue
v = valueof(v)
if v:
return v
def main(argv=None):
if argv is None:
import sys
argv = sys.argv
from optparse import OptionParser
parser = OptionParser("usage: %prog MODULE_NAME")
opts, args = parser.parse_args(argv[1:])
if len(args) != 1:
parser.error("wrong number of arguments") # Will exit
module_name = args[0]
try:
version = find_module_version(module_name)
except ImportError, e:
raise SystemExit("error: can't import %s (%s)" % (module_name, e))
if version:
print version
else:
raise SystemExit("error: can't find version for %s" % module_name)
if __name__ == "__main__":
main()
If it won't be simple, it simply won't be. [Hire me, source code] by Miki Tebeka, CEO, 353Solutions
Wednesday, January 28, 2009
Find Module Version
Quick script to check which version of Python module is installed.
Friday, January 16, 2009
Which build utility to run?
I have the following as a script called "mk" and set in my .vimrc
set makeprg=mk
#!/bin/bash
# Guess which make utility to use
# Miki Tebeka <miki.tebeka@gmail.com>
makecmd=""
if [ -f SConstruct ]; then
makecmd="scons -Q -D"
elif [ -f build.xml ]; then
makecmd="ant"
elif [ -f Makefile ]; then
makecmd="make"
elif [ -f makefile ]; then
makecmd="make"
elif [ "$OSTYPE" == "WINNT" ]; then
proj=`ls *.dsp 2>/dev/null`
if [ -f $proj ]; then
makecmd="msdev $proj /MAKE"
fi
fi
if [ -z "$makecmd" ]; then
echo "can't find project file"
exit 1
fi
$makecmd $@
Wednesday, January 07, 2009
Moved to bitbucket
All(?) the code from this blog is now at BitBucket
imapclean
#!/usr/bin/env python
'''Clean your IMAP inbox
Copy all message to "Archive" and delete them from Inbox
'''
__author__ = "Miki Tebeka <miki.tebeka@gmail.com>"
from imaplib import IMAP4
import logging as log
def move_messages(server, user, passwd, purge=0):
imap = IMAP4(server)
imap.login(user, passwd)
imap.select()
messages = imap.search(None, "ALL")[1][0].split()
for msg_id in messages:
flags = imap.fetch(msg_id, "(FLAGS)")[1][0]
if not flags.startswith(msg_id):
log.error("bad reply for %s flags - %s" % (msg_id, flags))
continue
if "Deleted" in flags:
log.info("skipping %s - already deleted" % msg_id)
continue
log.info("deleting %s" % msg_id)
imap.copy(msg_id, "Archive")
imap.store(msg_id, "+FLAGS", "\\Deleted")
if purge:
log.info("purging deleted messages")
imap.expunge()
log.info("logging out")
imap.close()
imap.logout()
def main(argv=None):
if argv is None:
import sys
argv = sys.argv
from optparse import OptionParser
from getpass import getpass, getuser
parser = OptionParser("usage: %prog")
parser.add_option("-p", "--purge", help="purge deleted messages",
action="store_true", default=0, dest="purge")
parser.add_option("-v", "--verbose", help="be verbose",
dest="verbose", action="store_true", default=0)
parser.add_option("--server", help="imap server",
default="localhost", dest="server")
parser.add_option("--user", help="IMAP user name",
dest="user", default="")
parser.add_option("--passwd", help="IMAP password",
dest="passwd", default="")
opts, args = parser.parse_args(argv[1:])
if args:
parser.error("wrong number of arguments") # Will exit
level = log.DEBUG if opts.verbose else log.ERROR
log.basicConfig(format="%(levelname)s: %(message)s",
level=level)
opts.user = opts.user or getuser()
opts.passwd = opts.passwd or getpass()
try:
move_messages(opts.server, opts.user, opts.passwd, opts.purge)
except Exception, e:
if opts.verbose:
log.exception(e)
else:
log.error(e)
raise SystemExit(1)
if __name__ == "__main__":
main()
Yeah, the pygments experiment worked.
Friday, December 12, 2008
crashlog
Get email notification whenever your program crashes.
Friday, November 14, 2008
The Code You Don't Write
Act without doing, work without effort.
Think of the small as large and the few as many.
Confront the difficult while it is still easy;
accomplish the great task by a series of small steps.
- Lao-Tze
Sometimes, the code you don't write is more important than the one you write.
Whenever I start on a new task, my first question is "how can I do this without coding?".
Here's a small (true) exmaple:
We had a problem that serving files on an NFS mounted volume was slow for the first request and them it was good. Probably the mount went "stale" after a while.
First option of learning the inner working of NFS mounts was dropped immediately - you can never know how much time this tinkering will take and if it'll work eventually.
So I decided to keep the NFS mount "warm" by periodically accessing it.
First Version:
from time import sleep
from os import listdir
while 1:
listdir("/path/to/nfs")
sleep(10 * 60 * 60)
and in crontab
@reboot /usr/bin/python /path/to/script.py
Then I thought - "cron", and second version came:
from os import listdir
listdir("/path/to/nfs")</code></pre>
and in crontab:
*/10 * * * * /usr/bin/python /path/to/script.py
And then last version (just crontab):
*/10 * * * * /bin/ls /path/to/nfs
So down from 6 LOC to 3 LOC to 1 LOC - that's what I call produtivity :)
Saturday, November 08, 2008
Where is Miki?

A little CGI script that show where I am (gets data from my google calendar).
Using Google Data Python API
#!/usr/bin/env python
'''Where where am I? (data from Google calendar)
Get gdata from http://code.google.com/p/gdata-python-client/
'''
__author__ = "Miki Tebeka <miki.tebeka@gmail.com>"
import gdata.calendar.service as cal_service
from time import localtime, strptime, strftime, mktime, timezone
DAY = 24 * 60 * 60
def caltime_to_local(caltime):
# 2008-11-07T23:30:00.000+02:00
t = mktime(strptime(caltime[:16], "%Y-%m-%dT%H:%M"))
tz_h, tz_m = map(int, caltime[-5:].split(":"))
cal_tz = (tz_h * 60 * 60) + (tz_m * 60)
if caltime[-6] == "-":
cal_tz = -cal_tz
# See timezone documentation, the sign is reversed
diff = -timezone - cal_tz
return localtime(t + diff)
def iter_meetings():
client = cal_service.CalendarService()
client.email = "your-google-user-name"
client.password = "your-google-password"
client.source = "Where-is-Miki"
client.ProgrammaticLogin()
query = cal_service.CalendarEventQuery("default", "private", "full")
query.start_min = strftime("%Y-%m-%d")
tomorrow = localtime(mktime(localtime()) + DAY)
query.start_max = strftime("%Y-%m-%d", tomorrow)
feed = client.CalendarQuery(query)
for event in feed.entry:
title = event.title.text
when = event.when[0]
start = caltime_to_local(when.start_time)
end = caltime_to_local(when.end_time)
yield title, start, end
def find_meeting(meetings, now):
for title, start, end in meetings:
print title, start, end
if start <= now <= end:
return title, end
return None, None
def meetings_html(meetings):
if not meetings:
return "No meetings today"
trs = []
tr = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>"
for title, start, end in meetings:
start = strftime("%H:%M", start)
end = strftime("%H:%M", end)
trs.append(tr % (title, start, end))
return "Today's meetings: <table border='1'>" + \
"<tr><th>Title</th><th>Start</th><th>End</th></tr>" + \
"\n".join(trs) + \
"</table>"
HTML = '''
<html>
<head>
<title>Where is Miki?</title>
<style>
body, td, th {
font-family: Monospace;
font-size: 22px;
}
</style>
</head>
<body>
<h1>Where is Miki?</h1>
<p>
Seems that he is <b>%s</b>.
</p>
<p>
%s
</p>
</body>
</html>
'''
if __name__ == "__main__":
import cgitb; cgitb.enable()
from operator import itemgetter
days = ["Mon","Tue","Wed", "Thu", "Fri", "Sat", "Sun"]
now = localtime()
day = days[now.tm_wday]
meetings = sorted(iter_meetings(), key=itemgetter(-1))
# Yeah, yeah - I get in early
if (now.tm_hour < 6) or (now.tm_hour > 17):
where = "at home"
elif day in ["Sat", "Sun"]:
where = "at home"
else:
title, end = find_meeting(now, meetings)
if end:
where = "meeting %s (until %s)" % (title, strftime("%H:%M", end))
else:
where = "at work"
print "Content-Type: text/html\n"
print HTML % (where, meetings_html(meetings))
Wednesday, November 05, 2008
Document With Examples
I've found out that a lot of times when I have a parsing code, it's best to document the methods with examples of the input.
A small example:
A small example:
#!/usr/bin/env python
'''Simple script showing how to document with examples'''
__author__ = "Miki Tebeka <miki.tebeka@gmail.com>"
import re
# HTTP/1.1 200 OK
# HTTP/1.1 301 Moved Permanently
def http_code(line):
return line.split()[1]
if __name__ == "__main__":
print http_code("HTTP/1.1 301 Moved Permanently")
Monday, October 13, 2008
JavaScript sound player
It's very easy to connect Adobe FLEX to JavaScript.
We'll create a simple sound player that exposes two functions: play and stop. It'll also call the JavaScript function on_play_complete when the current sound has finished playing.
Compile with mxmlc soundplayer.mxml
We'll create a simple sound player that exposes two functions: play and stop. It'll also call the JavaScript function on_play_complete when the current sound has finished playing.
soundplayer.mxml
Compile with mxmlc soundplayer.mxml
soundplayer.html
Tuesday, September 23, 2008
"Disabling" an image
Sometimes you want to mark a button image as "disabled". The usual method is to have two images and display the "disabled" state image when disabled.
However you can use the image opacity the mark is as disabled as well:
However you can use the image opacity the mark is as disabled as well:
<html>
<head>
<title>Dimmer</title>
<style>
.disabled {
filter: alpha(opacity=50);
-moz-opacity: 0.50;
opacity: 0.50;
}
</style>
</head>
<body>
<center>
<p>Show how to "dim" an image, marking it disabled</p>
<img src="image.png" id="image" /> <br />
<button onclick="disable();">Disable</button>
<button onclick="enable();">Enable</button>
</center>
</body>
<script src="jquery.js"></script>
<script>
function disable() {
$('#image').addClass('disabled');
}
function enable() {
$('#image').removeClass('disabled');
}
</script>
</html>
Thursday, September 18, 2008
Destktop Web Application

It's very easy have the browser window as your user interface, even on desktop applications.
Below is a small phone book demo.
General Design:
- Have a web server serve the main search page
- I'm using BaseHTTPServer but you can use any other framework
- Run an AJAX query and display the results
- I'm using jQuery
- fork the server so the program will return
webphone.py (AKA the web server)
index.html (AKA the GUI)
pymodver
Which version of module do I have?
#!/usr/bin/env python
'''Find python module version'''
__author__ = "Miki Tebeka <miki.tebeka@gmail.com>"
def valueof(v):
if callable(v):
try:
return v()
except Exception:
return None
return v
def load_module(module_name):
module = __import__(module_name)
# __import__("a.b") will give us a
if ("." in module_name):
names = module_name.split(".")[1:]
while names:
name = names.pop(0)
module = getattr(module, name)
return module
def find_module_version(module_name):
module = load_module(module_name)
attrs = set(dir(module))
for known in ("__version__", "version"):
if known in attrs:
v = valueof(getattr(module, known))
if v:
return v
for attr in attrs:
if "version" in attr.lower():
v = getattr(module, attr)
if not v:
continue
v = valueof(v)
if v:
return v
def main(argv=None):
if argv is None:
import sys
argv = sys.argv
from optparse import OptionParser
parser = OptionParser("usage: %prog MODULE_NAME")
opts, args = parser.parse_args(argv[1:])
if len(args) != 1:
parser.error("wrong number of arguments") # Will exit
module_name = args[0]
try:
version = find_module_version(module_name)
except ImportError, e:
raise SystemExit("error: can't import %s (%s)" % (module_name, e))
if version:
print version
else:
raise SystemExit("error: can't find version for %s" % module_name)
if __name__ == "__main__":
main()
Tuesday, September 16, 2008
Exit Gracefully
When your program is terminated by a signal, the atexit handlers are not called.
A short solution:
A short solution:
Sunday, September 07, 2008
"unpack" updated
Updated the code to unpack and added view functionality to it.
Thursday, September 04, 2008
putclip
A "cross platform" command line utility to place things in the clipboard.
(On linux uses xsel)
(On linux uses xsel)
#!/usr/bin/env python
'''Place stuff in clipboard - multi platform'''
__author__ = "Miki Tebeka <miki.tebeka@gmail.com>"
from os import popen
from sys import platform
COMMDANDS = { # platform -> command
"darwin" : "pbcopy",
"linux2" : "xsel -i",
"cygwin" : "/bin/putclip",
}
def putclip(text):
command = COMMDANDS[platform]
popen(command, "w").write(text)
def main(argv=None):
if argv is None:
import sys
argv = sys.argv
from optparse import OptionParser
from sys import stdin
parser = OptionParser("%prog [PATH]")
opts, args = parser.parse_args(argv[1:])
if len(args) not in (0, 1):
parser.error("wrong number of arguments") # Will exit
if platform not in COMMDANDS:
message = "error: don't know how to handle clipboard on %s" % platform
raise SystemExit(message)
if (not args) or (args[0] == "-"):
info = stdin
else:
try:
infile = args[0]
info = open(infile)
except IOError, e:
raise SystemExit("error: can't open %s - %s" % (infile, e))
try:
putclip(info.read())
except OSError, e:
raise SystemExit("error: %s" % e)
if __name__ == "__main__":
main()
Friday, August 15, 2008
flatten
#!/usr/bin/env python
__author__ = "Miki Tebeka <miki.tebeka@gmail.com>"
def flatten(items):
'''Flatten a nested list.
>>> a = [[1], 2, [[[3]], 4]]
>>> list(flatten(a))
[1, 2, 3, 4]
>>>
'''
for item in items:
if getattr(item, "__iter__", None):
for subitem in flatten(item):
yield subitem
else:
yield item
if __name__ == "__main__":
from doctest import testmod
testmod()
Thursday, August 07, 2008
printobj
'''Quick and dirty object "repr"'''
__author__ = "Miki Tebeka "
# FIXME: Find how to make doctest play with "regular" class definition
def printobj(obj):
'''
Quick and dirty object "repr"
>>> class Point: pass
>>> p = Point()
>>> p.x, p.y = 1, 2
>>> printobj(p)
('y', 2)
('x', 1)
>>>
'''
print "\n".join(map(str, obj.__dict__.items()))
if __name__ == "__main__":
from doctest import testmod
testmod()
Thursday, July 24, 2008
CGI trampoline for cross site AJAX
Most (all?) browsers won't let you do cross site AJAX calls.
One solution is JSONP (which is supported by jQuery). However not all servers support it.
The other solution is to create a "trampoline" in your site that returns the data from the remote site:
One solution is JSONP (which is supported by jQuery). However not all servers support it.
The other solution is to create a "trampoline" in your site that returns the data from the remote site:
Sunday, July 20, 2008
whichscm
#!/usr/bin/env python
'''Find under which SCM directory is'''
__author__ = "Miki Tebeka <miki.tebeka@gmail.com>"
from os import sep
from os.path import join, isdir, abspath
from itertools import ifilter, imap
def updirs(path):
parts = path.split(sep)
if not parts[0]:
parts[0] = sep # FIXME: Windows
while parts:
yield join(*parts)
parts.pop()
def scmdirs(path, scms):
for scmext in scms:
yield join(path, scmext)
def scm(dirname):
return dirname[-3:].lower()
def scms(path, scms):
return imap(scm, ifilter(isdir, scmdirs(path, scms)))
def whichscm(path):
path = abspath(path)
for scm in scms(path, (".svn", "CVS")):
return scm
scmdirs = (".bzr", ".hg", ".git")
for dirname in updirs(path):
for scm in scms(dirname, (".bzr", ".hg", ".git")):
return scm
def main(argv=None):
if argv is None:
import sys
argv = sys.argv
from optparse import OptionParser
parser = OptionParser("usage: %prog [DIRNAME]")
opts, args = parser.parse_args(argv[1:])
if len(args) not in (0, 1):
parser.error("wrong number of arguments") # Will exit
dirname = args[0] if args else "."
if not isdir(dirname):
raise SystemExit("error: %s is not a directory" % dirname)
scm = whichscm(dirname)
if not scm:
raise SystemExit("error: can't find scm for %s" % dirname)
print scm
if __name__ == "__main__":
main()
Subscribe to:
Posts (Atom)