The Occasional Occurence
Customizing the Python Import System
July 31, 2008 at 10:39 PM | categories: Python, Software, work, computing, GeneralSo I've been programming with Python since 2001 and I've never had the need to do anything that the standard import system didn't provide - until this week. We are planning on a little code reorganization for a project at work in preparation for collaboration from more developers. I wrote a simple custom importer/loader that let's a developer write
from application.widgets import foobar
instead of the longer
from application.widgets.foobar.widget import foobar
and the class foobar winds up in globals().
It's not groundbreaking functionality but it actually does add a little clarity in our situation. The whole task it was made quite simple by the features introduced in PEP 302 (that document is a great reference). Now, before anyone suggests that we could have just pulled the classes in via a __init__.py in the application/components directory, note that some components might depend on others which have not been imported and thus their imports would fail.
Anyhow, like I said, it isn't groundbreaking, but the very fact that you can customize Python's import system is neat. I got to thinking about what other ways I could hack the import system, and came up with a little web importer. I'll post the code below, only because I think it is a clever trick, not that it is something to use in development of a Real Application.
""" Stupid Python Trick - import modules over the web. Author: Christian Wyglendowski License: MIT (http://dowski.com/mit.txt) """ import httplib import imp import sys def register_domain(name): WebImporter.registered_domains.add(name) parts = reversed(name.split('.')) whole = [] for part in parts: whole.append(part) WebImporter.domain_modules.add(".".join(whole)) class WebImporter(object): domain_modules = set() registered_domains = set() def find_module(self, fullname, path=None): if fullname in self.domain_modules: return self if fullname.rsplit('.')[0] not in self.domain_modules: return None try: r = self._do_request(fullname, method="HEAD") except ValueError: return None else: r.close() if r.status == 200: return self return None def load_module(self, fullname): if fullname in sys.modules: return sys.modules[fullname] mod = imp.new_module(fullname) mod.__loader__ = self sys.modules[fullname] = mod if fullname not in self.domain_modules: url = "http://%s%s" % self._get_host_and_path(fullname) mod.__file__ = url r = self._do_request(fullname) code = r.read() assert r.status == 200 exec code in mod.__dict__ else: mod.__file__ = "[fake module %r]" % fullname mod.__path__ = [] return mod def _do_request(self, fullname, method="GET"): host, path = self._get_host_and_path(fullname) c = httplib.HTTPConnection(host) c.request(method, path) return c.getresponse() def _get_host_and_path(self, fullname): tld, domain, rest = fullname.split('.', 2) path = "/%s.py" % rest.replace('.', '/') return ".".join([domain, tld]), path sys.meta_path = [WebImporter()]
You can use it like so:
import webimport webimport.register_domain('dowski.com') from com.dowski import test
That would fetch and import http://dowski.com/test.py.
There may be other Python libraries out there that do this better - I couldn't find any with a quick Google search. I can think of a number of features would be needed for a serious implementation of something like this (caching, HTTP-AUTH, signatures, remote package support, etc). For now though I'm just throwing this out there because I think it is neat.
Anyone else doing neat tricks with the import hooks that Python exposes?
cw
Converting docx Files
April 16, 2008 at 01:34 PM | categories: Python, Software, work, computing, GeneralI'm working on an OOXML implementation in Python and found this handy utility for converting docx files to rtf.
It seems to open docx files that Word complains about, but at least it let's me know that I am on the right track. Also, it runs under Wine on Linux, so there is no need for a virtual or non-virtual machine running Windows.
cw
Code Farming
February 13, 2008 at 02:31 AM | categories: Python, Software, computing, GeneralI read a good article that gave an Organic Metaphor for software development. Here is a quote:
As I look at what I actually do in my cramped little cubicle, I realize that my work is more akin to farming than construction. I spend my days cultivating information, and growing a program. I can see the evolution of my work as it needs to scale through different platforms.
I really resonate with that description - writing software is very fluid and organic. Code is malleable and frequently changing. During development, there aren't necessarily rigid beams and permanent fasteners like in construction.
Perhaps lending credence to both the architectural and organic software development metaphors, the article closes with this thought:
The term "System Architecture" is a more fitting in the world of packaged software than it is for the IT department or Internet development. With packaged software, a group of programmers create one major release that they will distribute to hundreds of thousands of users. Since there is no method for evolution, this type of software has much more rigid. Of course, with the Internet explosion, packaged software will take a backseat to organic programming.
Yeah. The engineering/architectural and the organic metaphors probably both have their places. Packaged, physically distributed software probably requires more engineering. The organic metaphor better describes the survival of the fittest (or survival of the first-to-market) and rapid evolution that is possible (and required) in the internet ecosystem.
cw
Safari Gotchas
August 16, 2007 at 09:56 PM | categories: work, Software, computing, GeneralIn the spirit of sharing knowledge that will save someone from the sort of tedious pain I went through the past couple days, here are a few Safari (2.0.4) bugs that I had to work around:
1. No Global Javascript eval() That's right. You can't eval() in the global (window) context. Safari doesn't allow it. A lot of places mention the fact that you can do a window.setTimeout, but that runs asynchronously (which I did not want). Thankfully, there is one place on the web that gives the secret sauce on how to implement something that will accomplish basically the same thing as eval() in any other browser. Wrap that up in a nice little function of your own, and you are good to go.
2. CSS: background-position and Container Size If you want to control the position of a background-image in a DIV, make sure that the DIV is at least one pixel larger than the background-image. Otherwise, your attempts to position it might drive you to the brink of insanity. Not that I would know.
3. Calling click() on a Checkbox If you think you can just grab a checkbox type INPUT element from the DOM and call click() on it, you are sorely mistaken! You must explicitly check that bad boy by doing something like checkElem.checked = true.
4. Reinitializing jQuery Interface Plugin Sortables This is probably the most esoteric gotcha of the bunch, as it involves a third-party library (jQuery). All of the other major browsers (Firefox 2, IE6/7, Opera 9) simply let you reinitialize as many Sortables as you want. You just call .Sortable(config) on any element each time you want to make it sortable. This does not work in Safari. Before you reinitialize the Sortable, you need to call .SortableDestroy() on it.
In the application I am working on, this is important because we load each new state via an XMLHTTPRequest. Now, when a Sortable is initialized, a callback is registered to handle the .SortableDestroy() before a new state is initialized.
That's That Hopefully this info will save some of you a little trouble.
cw
Ion
July 21, 2007 at 11:51 PM | categories: work, Software, computing, GeneralSo an article about user interfaces on Coding Horror prompted me to say a short piece about Ion*.
When doing serious work on the computer, I always find myself tiling my windows. Overlapping windows are so annoying. And tiling them in an organized manner is even more annoying.
From the article:
Manipulating windows is pure excise-- extra work that stands between the user and completing their task. The more windows you have to deal with, the less work you get done, and the more time you spend sizing them, moving them, bringing them to the top, and dragging them around so they aren't overlapping.
Enter Ion.
It tiles them for you. And lets you move around from window-to-window using the keyboard.
Sure, it doesn't have wobbly windows or pretty wallpaper. But if you need some more visual or tactile feedback while computing, I suggest getting up and taking a short walk - not shaking a window around on your screen or gazing at your hipster wallpaper.
cw
* Sorry, Linux only. Try Ubuntu.