lxml OSX compilation madness

September 29th, 2009

I don’t think that there has ever been a point in time where installing lxml on OSX was not a horrible pain in the ass. I think that at one point, it was enough just to install updated versions of libxml2 and libxslt, and lxml would compile nicely. But I must have done something bad, cause at some point recently, lxml just stopped compiling for me.

This would not do at all. I use virtualenv (and virtualenvwrapper) pretty religiously, and am loathe to install much of anything in the system-wide site-packages. I needed to get things to a point where a straight-up easy_install lxml would work. I didn’t wanna be messing around with custom install flags or whatever every time I cut a new env.

This is not a neat step-by-step guide for getting lxml working in OSX. This is just a record of some stuff that I saw, and some things that I did. Some combination thereof was sufficient to get things working.

For the record, I’m using lxml 2.2.2, libxml2 2.7.5, and libxslt 1.1.26.

One day, I fired up python, typed from lxml import etree and got an error much like the following:

>>> from lxml import etree
Traceback (most recent call last):
  File "", line 1, in 
ImportError: dlopen(/Users/nwilliams/.virtualenvs/lxml1/lib/python2.6/site-packages/lxml-2.2.2-py2.6-macosx-10.5-universal.egg/lxml/etree.so, 2): Symbol not found: _xmlFree
  Referenced from: /Users/nwilliams/.virtualenvs/lxml1/lib/python2.6/site-packages/lxml-2.2.2-py2.6-macosx-10.5-universal.egg/lxml/etree.so
  Expected in: dynamic lookup

>>>

Needless to say, I was less than pleased.

Looking though the source, I gathered that _xmlFree was a symbol exported by libxml2. My first thought was that lxml was somehow compiling against the old system version of libxml2, or for some other reason couldn’t find the new version.

I noticed a few funny things about the output when installing lxml. First, there were two lines right before all the heavy compilation work:

Using build configuration of libxslt 1.1.26
Building against libxml2/libxslt in the following directory: /usr/local/lib

The second line suggested that lxml was, in fact, seeing the version of libxml2 that I wanted it to. The first was a problem though, because normally, it looks like this:

Using build configuration of libxml2 2.7.5 and libxslt 1.1.26

For some reason, lxml wasn’t finding xml2-config. Doing export XML2_CONFIG=/usr/local/bin/xml2-config seemed to fix things.

The other issue was probably the important one. While compiling lxml, I would see a bunch of warnings that looked like this:

ld: warning in /usr/local/lib/libxml2.dylib, file is not of required architecture
ld: warning in /usr/local/lib/libxslt.dylib, file is not of required architecture

Also for another file or two, and all repeated a few times.

Checking file /usr/local/lib/libxml2.dylib told me that the files in question were only compiled as i386 binaries. I eventually found this page, which showed me how to compile libxml2 and libxslt as universal binaries. I did modify things somewhat, though, most notably adding 64-bit architectures.
The configure command I used for libxml2 was:

env CFLAGS="-arch i386 -arch ppc -arch x86_64 -arch ppc64" ./configure --enable-static=no --without-python --disable-dependency-tracking

And for libxslt:

env CFLAGS="-arch i386 -arch ppc -arch x86_64 -arch ppc64" ./configure --disable-dependency-tracking

The CFLAGS bit is necessary, that’s what’s making things work. I don’t actually know exactly what the point of --enable-static=no is. I’m sure it’ll come back to bite me in the ass at some point. --without-python sounds scary, but since lxml is actually an alternative to the gross “real” bindings, we don’t care about them. I also have no idea what --disable-dependency-tracking does, but make will fail without it.

Once I had these universal libraries built and installed, easy_install lxml worked like a charm.

completions breaking on zsh upgrade

December 4th, 2008

If you upgrade zsh and suddenly find that certain completion functions are breaking and throwing up all over your terminal, remember to delete ~/.zcompdump.

For instance, when I upgraded one of my systems from 4.3.4 to 4.3.9, I would get the following error whenever I tried to complete a command name:

alternative:69: command not found: _path_commands

This gets me every time.

examining a dynamically loaded iframe in Selenium

December 2nd, 2008

Nothing too exciting here, just something I was chewing on for a while and wanted to write down. I’m testing a page that uses GreyBox to display modal windows. GreyBox puts the content in an iframe, so you have to do a little finagling to get at it. Most of the selenium rc methods that handle frames seem to require me to actually know something about the frame I’m looking at, like an id or a name or something. I dunno any of that crap, just use that damn iframe there.

Anyway, select_frame (I’m using the python bindings here) lets you use the “index” locator, so you can jump right in to the first frame. Then to get back out, there is the “relative” locator that lets you just move up one level. You end up with something like this:

# do stuff in the main window here
sel.click("the link you're clickin")
sel.select_frame('index=0')
# do stuff to the iframe here
sel.select_frame('relative=up')
# you're back in the main window

I don’t have all that solid a grasp on what’s going on around here, so I’m sure this only works in whatever bizarre edge case I have set up. Whatever, hopefully google will direct some poor soul here and I will end up making his day just that much brighter.

helvetireader list view css update

December 2nd, 2008

Here is an update to the CSS I posted the other day for tweaking Helvetireader.

#selectors-box, #add-box { display: none; }
.entry { -webkit-border-radius: 0 !important; -moz-border-radius: 0 ! important; }
.entry .collapsed { padding: 2px 0 2px 0 ! important; }
.entry .collapsed .entry-secondary { margin-top: 1px !important; }
.entry .collapsed .entry-original { margin-top: 2px !important; }
.entry .collapsed .entry-icons { top: -4px !important; }
.entry .collapsed .entry-date { margin: 0 30px 0 0 !important; padding: 1px 0 1px 0 !important; }
.entry-actions { height: 1.2em !important; padding-top: 0px !important; }
.entry-actions:hover { padding-left: 25px !important; }

I forgot to even mention in my last post, but the real reason for needing most of this is that I’m using Reader in list view, instead of expanded view as is intended. I think the only real difference you might see using this css in expanded view is that you won’t get the nice rounded corners around each entry. Unless there’s a CSS selector for matching the parent of a certain element, I don’t know a practical way to preserve the corners. I also never use expanded view, so I don’t care.

Helvetireader

November 29th, 2008

I use Google Reader a lot, and lately I’d been feeling somewhat frustrated with its use of space. It is the means through which I consume the majority of my online information, and I wanted it to be a little more efficient about presenting that info.

So, I was very happy to discover Helvetireader, a Greasemonkey script for applying a much more minimalist style to Reader. It removes many of the UI elements, forcing much wider use of keyboard shortcuts. I was already a big fan of Reader’s keyboard shortcuts, and Helvetireader prompted me to get familiar with a few others that I hadn’t even thought to look for.

At the moment, the script just adds two elements inside the page’s head tag — one link tag to change the favicon, and another linking to the stylesheet. I have been tweaking the script a little to get things a little more how I like them. What I did is just add a style element, define its InnerHTML, and append it as a child to the head tag. I put my tweaks inside a new userscript, but you could just as easily edit the Helvetireader script. Just make sure that your adjustments come after Helvetireader’s CSS.

So, the javascript I have for adding the style tag looks something like the following:

var newStyle = document.createElement('style');
newStyle.type = 'text/css';
newStyle.innerHTML = "CSS GOES HERE";
document.getElementsByTagName("head")[0].appendChild(newStyle);

The biggest thing that I wanted to change was removing the links above the feed tree. It takes up like half the height of the page and I never use any of them. Even with the browser window maximised, I could only see a tiny subset of my feeds. You might say that I was mad as hell and not going to take it anymore. Luckily, fixing this was a simple matter:

#selectors-box, #add-box { display: none; }

In list view, the little star icon was kind of off center, and the date overlapped with the icon on the right. The star icon being low also made the whole bar taller than it should have been and the top of some of the text underneath was being exposed. The following fixed that:

#entries.list .collapsed .entry-icons { top: -5px ! important; padding-bottom: 5px; }
.collapsed .entry-date { margin: .2em 30px 0 0 ! important; }

When an article is expanded, the options at the bottom only show up when you hover over them. They also overlapped with the little gear icon. I think they might have been pushed down a bit or something as well. As is typical with CSS that I write, I’m never quite sure what is actually necessary. I tend to just get stuff working, maybe pare down a few really obvious things, and then not mess with it. So don’t take any of this as authoritative, it’s just stuff that seems to work for me.

.entry-actions { height: 1.2em ! important; padding-top: -0px ! important; }
.entry-actions:hover { padding-left: 25px ! important; }

Unfortunately, Javascript doesn’t have nice multi-line strings or heredocs, and I didn’t really feel like putting all of my CSS on one line. So, I cheated a little like so:

newStyle.innerHTML = "\
#selectors-box, #add-box { display: none; }\n\
#entries.list .collapsed .entry-icons { top: -5px ! important; padding-bottom: 5px; }\n\
.collapsed .entry-date { margin: .2em 30px 0 0 ! important; }\n\
.entry-actions { height: 1.2em ! important; padding-top: -0px ! important; }\n\
.entry-actions:hover { padding-left: 25px ! important; }\n\
";

Not ideal perhaps, but not too terrible, I’d say. And that’s usually good enough.

I’ve only been using this for a day or so, but I’m really liking it so far. I suspect that I would probably feel the same even if I didn’t have a huge fetish for Helvetica.

EDIT: updated css

links for 2008-10-17

October 17th, 2008

forget that

August 18th, 2008

That twitter digest plugin was a nice idea and all, but it kind of loses its effectiveness when you never post for real. Also, it didn’t seem to understand how dates work.

twitters for 2008-08-17

August 17th, 2008
  • Ikea is a fun place, moreso than I remembered #

twitters for 2008-08-16

August 16th, 2008
  • I want a nice processor and amplifier, but expensive things cost money :( #

Twitter Updates for 2008-08-14

August 14th, 2008
  • @catechism yeah, but we’re the ones looking at it all day in reply to catechism #
  • got a first look at the new apartment – small rooms, loud trains, in-unit washer/dryer :) #