return to OCLUG Web Site
A Django site.
November 19, 2012

Michael P. Soulier
msoulier
But I Digress
» Joysticks? We don't need no stinking joysticks...

So, after unpackaging my brand-spanking new Mac Mini, I grabbed a copy of the X-Plane demo, dropped in an old usb joystick and fired it up. Oddly, X-Plane itself asked me if I wanted to calibrate the joystick, which struck me as odd, that hasn't happened in years, not since my days with plain old DOS. DOS didn't have a controller subsystem so there was no way to calibrate a joystick once, for all apps, but Microsoft fixed that long, long ago. Even Linux has jscal to allow the same thing. It's command-line, but it works.

So of course I assumed that on a Mac, with it's reputation for dead simple plug and play, everything just works, dead simple and easy, it would have the same right? Umm, no. No command-line tool, no graphical tool, no voice activated tool, no swiping on my LCD, nothing. It's left up to the application, kinda like DOS. Way to go Apple.

Now, why do I care, since X-Plane has such a utility? Well, in X-Plane, I don't. But after downloading and installing Flightgear, I do. They leave the joystick calibration up to the OS, and rightly so. So, I can't use the joystick in Flightgear, not that I'd want to use it on this machine anyway, as I've already found out that the OpenGL rendering performance on the Mac Mini is horrid. Wow, another strike over my cheap Linux box sitting next to me that was made out of spare parts from a friend's basement. That is truly, utterly, sad.

Seriously Apple, is that the best you can do? If you think I'm interested in tilting an ipad to fly a plane in any realistic simulation, you guys have been smoking way too much of what you usually smoke. I want realism, and last time I flew, the pilot didn't have to lean to bank the plane. At least, I hope not, the door was closed and locked, post-9/11 and all, but I digress.

Bottom line Apple, for what I paid for this thing, you could have done much, much better in this regard. X-Plane rocks, but Intel graphics in the mini? Pleease, put a smoking Nvidia chipset in there and give me a decent framerate for games!

Are you listening?

November 17, 2012

Michael P. Soulier
msoulier
But I Digress
» Umm, done unzipping yet?

So, the first thing I did after after wrapping my head around the cocoa interface was to start installing software like a madman. I wanted Firefox, VLC, Kobo, Gimp, Vim, etc, etc, etc. So, I had to learn how to install apps on OS X.

Apps in OS X seem to come in at least two different forms: .app files, which are self-contained application packages that you simply drop into /Applications on the system (totally awesome), and .pkg files, which are more windows-like installers.

The latter seems to be required with more complex installs, like plug-ins that need to put files in privileged places all over the system, requiring root access to install. As an admin user, I can already put .app files into /Applications without root access, the implications of which are that a virus could infect the apps in /Applications too, so that's a strike, security-wise, for OS X over Linux. Still better than Windows though, where a Power User can change anything under Program Files or Windows without escalating privileges.

The .app files or .pkg files can come in many forms, the most common of which is a .dmg file, which is a disk image that OS X will casually mount on a loopback. I've noticed that the Finder can mount .dmg and .iso files with a simple click. With an .app file, you just drag it to /Applications, and you're done, and uninstalling is just a simple. Far superior to any OS that I've used in the past. It's also common to download .zip files, which clicking on in the Finder fires-up the Archive Utility.

So there I was, clicking along and installing, and then a progress bar indicating that the .zip file was opening just kept going, and going, and going. I looked online, and found that I am not alone in having this problem. Apparently, the appleeventsd daemon requires killing under those circumstances, something that the nice guy at Apple support did not know. Looks like the issue is in OS X 10.8.2, which I am running.

Hmm. Bad timing in jumping on the Apple bandwagon? I wonder how long they'll take to fix the issue. Good test for what it will be like to live as part of Apple's ecosystem.

October 29, 2012

Michael P. Soulier
msoulier
But I Digress
» Need a new desktop

So my desktop is getting a tad clunky, even running Linux. I was thinking of replacing it, and just the tower, as I have all of the peripherals I need. I was thinking of dual-booting Windows and Linux maybe, to play the occasional commercial game, but nothing really heavy. Decent graphics card with good OpenGL support for Flightgear, and good Linux compatability.

For just the computer I wouldn’t plan on paying more than about $400.00 CDN, recommendations welcome. You’d think that PC prices would drop now that everyone and his brother seems to want a tablet, but it doesn’t seem to be happening, at least not that I notice.


May 10, 2012

Michael P. Soulier
msoulier
But I Digress
» Post-transaction events in Django

So, at work I’m using Django quite a bit, and I ran into a problem where I need the database transaction to be committed, and then I need to trigger additional server-side code that will act on that data.

Putting all of this into the view function with a manually managed transaction sucks, far too much code. There’s transaction middleware, but by then your view function has returned. What to do?

Simple. I added my own middleware, and I return a new property that I tag into the HttpResponse object. Python is flexible enough to allow this hack.

MIDDLEWARE_CLASSES = (
    'teleworker.lib.middleware.MslEventMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.middleware.transaction.TransactionMiddleware',

So in my MslEventMiddleware, I look for a new property in the response, and if it’s present, I execute the requested command, which will happen after the TransactionMiddleware has called commit.

    def process_response(self, request, response):
        if hasattr(response, 'mslevent'):
           msl.event(response.mslevent)

Simple enough. Although a real post-processing API in Django would be helpful.


May 4, 2012

Michael P. Soulier
msoulier
But I Digress
» Blogging in the mobile age

What a strange world where I am writing a blog post on my phone. Kinda slow going, even using this cool Swype app to speed things up. Mind you, I suck at it…

Perhaps a Bluetooth keyboard will be needed.

Anyone else phone-blogging?


May 3, 2012

Michael P. Soulier
msoulier
But I Digress
» Eclipse, you could be nicer to me

So I’m playing in Eclipse going through Android development HOWTOs. Yes, I know. Java. Thankfully there’s a scripting layer for Android, but I want to learn it all before I choose a toolset for a particular problem. Besides, Java ain’t all bad, just mostly.

Anywho, I fired up the HelloWorld tutorial, made my project, and very quickly found that Eclipse’s wonderful generated code that was going to save me all this work of typing Java didn’t compile. I got, “main cannot be resolved or is not a field”. Huh? The main it’s referring to is my main.xml file (can’t have too much XML eh Java?) describing the Android UI layout, under res/layouts/main.xml. Invoked through the ubiguitous Android R object. What do you mean it’s not there, you stupid machine??

So I do what any modern programmer does, after swearing at my screen repeatedly, I look up the error in google, and voila, I’m not alone. This post was particularly helpful. Apparently, it’s an Android SDK issue, which Eclipse invokes to create the project. Yo, Google! Get off your butts and fix it! Seems to me that you have time…


February 16, 2012

Michael P. Soulier
msoulier
But I Digress
» Bash, sometimes you suck

So, I’m trying to pass a ! character to a shell command. Should be simple right?

Not so much.

twit --post 'OMG...I'm out of coffee...work stoppage!'
bash: !': event not found

Huh? Oh yeah, in the fine tradition of crappy shells like csh, bash uses ! to re-run commands from the command history. But you’d think that in a single-quoted string it wouldn’t interpret that, it would just pass it into the command I’m running. Nope.

Can I escape it with a backslash? You bet.

$ echo "foobar\!"
foobar\!

K, still not what I wanted.

Simple solution, don’t use bash.

sh twit --post 'OMG...I'm out of coffee...work stoppage!'

Works fine in a POSIX mode.

Am I missing something? Is there a simpler way to get what I want? This blows the 80/20 rule totally.


January 7, 2011

Michael P. Soulier
msoulier
But I Digress
» Fixing my EeePC

So, close to a year ago I bought a new netbook for myself, a carefully researched EeePC from ASUS, mainly for the reputation of quality and Linux compatibility.

Last night I foolishly left it on but unplugged it, so by the morning the battery was dead. I didn’t realize this until I turned it on, unplugged, and found that it wasn’t working. The battery indicator clearly showed that the battery was too depleted, but oddly the box didn’t even attempt to boot. I plugged it in and it didn’t help. Nothing on the screen, not even a bios screen.

Calling ASUS tech support was no help, they finally concluded that I needed to send it to them. Meanwhile I was doing research online and found this extremely helpful thread that suggested a corrupt CMOS and a simple short-circuit technique to clear it.

So, before sending it to ASUS I pulled out my multimeter probes and shorted the CMOS terminals as described. Lo and behold, it booted. I’ve powered it down and back up repeatedly to confirm, and it’s good now.

So, ASUS tech support, 0. Eeeuser community 1.

Thanks guys!


July 23, 2010

Michael P. Soulier
msoulier
But I Digress
» I really love *nix

So I’ve recently been playing with Ditz, a ruby-based distributed issue tracker, to go along with my distributed workflow in Git. It’s a good start, but not quite polished yet. I added the issue-claiming plugin, played with it for a while, and then realized that I don’t need it since I’m the only developer on the projects that I want to use it for.

Then I removed the plugin, but it left behind sections in the ditz yaml files that caused it to now spew warnings.

msoulier@egor:...ier/work/mbg-bugs$ ditz todo
warning: unknown field "claimer" in YAML for
tag:ditz.rubyforge.org,2008-03-06:issue; ignoring
warning: unknown field "claimer" in YAML for
tag:ditz.rubyforge.org,2008-03-06:issue; ignoring
warning: unknown field "claimer" in YAML for
tag:ditz.rubyforge.org,2008-03-06:issue; ignoring
warning: unknown field "claimer" in YAML for
tag:ditz.rubyforge.org,2008-03-06:issue; ignoring

Well that’s unacceptable. So now I need to remove this claimer line from each file. Well, this is *nix so I’m not doing it by hand. I could use a perl one-liner but I’m a tad more familiar with ex commands, editing in Vim all day as I do.

So, I make an exscript file containing this:

%g/^claimer:/d
wq

And then run it on the files like so

for file in $(find bugs -name "issue*.yaml")
do
   ex - $file < exscript
done

Presto. Fixed. So happy.


June 11, 2010

Michael P. Soulier
msoulier
But I Digress
» Twisted Python and Chunked Encoding

When I was first writing a little web service in Twisted Python that would return JSON encoded data, and I was having some issues with loading it up using Javascript, I used Wireshark to trace the whole thing and was surprised at how the response looked.

There were delimiters around the data, and the response headers included a reference to “Chunked Transfer-Encoding”. I had to look it up to find out what it was, and I had no idea how to turn it off so I posted on the Twisted Python mailing list, and got a prompt reply.

Chunked encoding has nothing to do with the content type. It is used if
you do not set a content-length header.

So, figure out your response’s length (in bytes), and set the
content-length header to that.

Aha! So this in my http.Request handler fixed it.


log.info("sending response")
# Set the content length so that we don't respond with chunked
# encoding.
size = len(content)
log.debug("content length is %d bytes" % size)
self.setHeader('Content-Length', size)
self.write(content)
self.finish()
log.info("done")

Well, not a fix really as there was no bug, but I wanted to rule out the chunked encoding as the source of a problem that I was seeing.


» Humour in manpages

I just discovered surfraw in the results of an apt-cache search (love that command) and I had to laugh at the manpage:

DESCRIPTION
       Surfraw provides a fast unix command line interface to a variety
       of popular WWW search engines and other artifacts
       of power.  It reclaims google, altavista, dejanews, freshmeat,
       research index, slashdot and many others  from  the
       false‐prophet,  pox‐infested  heathen  lands  of html‐forms, placing
       these wonders where they belong, deep in unix
       heartland, as god loving extensions to the shell.

I know, I’m a geek, but to me it’s funny.


June 9, 2010

Michael P. Soulier
msoulier
But I Digress
» Dual-screen hack with x2vnc

I have two LCDs at work from having both a Windows and Linux PC on my desk. I need both right now due to some inane dependence on Windows-based process tools that were not of my choosing, but lets not go there.

To keep myself as productive as possible, I really just want to shove the two LCDs together and use one keyboard and mouse with a dual-screen setup. With one being Linux and the other Windows I won’t be able to move windows between the two displays but that’s ok. In the future I could put both LCDs on a single OS and access the other remotely but right now this is sufficient.

To make this work I’m leaning on x2vnc for a lovely dual-screen hack. Unfortunately it didn’t work initially, as the latest x2vnc speaks VNC 3.3 and TightVNC speaks 3.8 with no option that I could find to be backwards compatible. So, I looked around and I found RealVNC. The free, GPL version does have a backwards compatability mode of (use protocol 3.3 only) which I enabled, and now it’s working.

The VNC window on my Linux box is a thin, single pixel border on the east side of my monitor, and when I cross it I end up on the Windows box due to Microsoft’s ludicrous idea of a multi-user platform. So, thanks to the x2vnc developers, the RealVNC developers, and hey thanks Microsoft for being so lazy. It works great.


June 5, 2010

Michael P. Soulier
msoulier
But I Digress
» Cross-Origin Requests in Twisted

I’ve just been learning about Cross-Origin Resource Sharing, to permit javascript downloaded from one domain to make Ajax requests out to another domain. I started learning this because I was writing a Google Maps client to test some back-end code and it wasn’t working for some reason. Thanks to the help of someone on the Prototype mailing list, and a packet trace, the problem was quickly found.

When I loaded my static page off of the disk, the browser assigns it an origin of null. I was then accessing a service running on my desktop, so its origin was localhost. As the origins differ, when I tried to make an Ajax request to it my browser automagickally makes an OPTIONS request to the server, requesting permission.

Let me show an example, captured via tcpdump:

sudo tcpdump -i lo -nn -s0 -w out.pcap tcp port 8000

When I load up this pcap file in wireshark and follow TCP stream, I see:

OPTIONS /route/?start=sta-9998&end=sta-9999&starttime=1274469161 HTTP/1.1
Host: localhost:8000
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.4) Gecko/20091206 Gentoo Firefox/3.5.4
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Origin: null
Access-Control-Request-Method: GET
Access-Control-Request-Headers: x-prototype-version,x-requested-with

This is the OPTIONS request to the server, asking if it is permitted for this client to make a cross-origin request to that server. Specifically, it is asking permission to make a GET request from an Origin of “null”. If the server doesn’t respond with the right access-control headers, the browser will not permit the GET request to take place.

I had to modify my server, written in Twisted Python, to respond with:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Allow-Headers: x-prototype-version,x-requested-with
Content-Length: 0
Access-Control-Max-Age: 2520

So here I’m saying, yes, it is permitted from any origin (hence the *) to make a GET request, and the client can cache this permission for 2520 seconds (42 minutes). This won’t be my response when I deploy, I will tightly control the domains that this service permits, and lower the max-age to more like 10 minutes.

Now, this initial response is not enough, be aware. These headers must be supplied in every response, not just the response to the OPTIONS request. So when the GET finally takes place it looks like:

GET /route/?start=sta-9998&end=sta-9999&starttime=1274469161 HTTP/1.1
Host: localhost:8000
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.4) Gecko/20091206 Gentoo Firefox/3.5.4
Accept: application/json
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
X-Requested-With: XMLHttpRequest
X-Prototype-Version: 1.6.1
Origin: null

And the server now responds with:

HTTP/1.1 200 OK
Content-Length: 76
Access-Control-Allow-Headers: x-prototype-version,x-requested-with
Access-Control-Max-Age: 2520
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Content-Type: application/json

{
    "reason": "No workers ready, try again soon",
    "status": "defer"
}

This is just an example while the server is loading a rather large data set, and cannot respond yet. Note the Access-Control headers in the response, just like the initial OPTIONS response.

Doing this in Twisted is simple enough. Inside of a http.Request handler, you can set response headers with self.setHeader(header_name, header_value), like so:

            self.setHeader('Access-Control-Allow-Origin', '*')
            self.setHeader('Access-Control-Allow-Methods', 'GET')
            self.setHeader('Access-Control-Allow-Headers',
                           'x-prototype-version,x-requested-with')
            self.setHeader('Access-Control-Max-Age', 2520)
            self.setHeader('Content-type', 'application/json')

My next steps are to tighten this granting of access, probably via configuration file, but I’m sure you get the idea.


April 9, 2010

Michael P. Soulier
msoulier
But I Digress
» Hydro Ottawa (aka. Need a longer lasting UPS)

Lately living in Stittsville is feeling more and more like being in a third-world country, given the frequency of power outages lately.

Two days ago the power was out in the morning for over an hour, and I look at the outage report and it says this:

2010-04-07  	Goulbourn  	7:42 am  	9:17 am  	95 minutes  	3325
    • cause unknown, line was patrolled and no cause was found

And this morning it went down again. The website doesn’t show this one yet (they seem to update the site as an afterthought) and when I called into their irritating phone queues the human being that I finally reached had no information.

Reliable power? Not here.


December 12, 2009

Michael P. Soulier
msoulier
But I Digress
» Ruby silliness

Ok, this is just dumb.

msoulier@kanga:~$ gem list torrent --remote

*** REMOTE GEMS ***

Well that’s wrong, I know there’s a RubyTorrent gem.

msoulier@kanga:~$ gem list tftp --remote

*** REMOTE GEMS ***

tftpplus (0.4)

It finds my tftp library just fine with a substring.

msoulier@kanga:~$ gem list RubyTorrent --remote

*** REMOTE GEMS ***

rubytorrent (0.3)

So why do I have to be so specific?

I shouldn’t need a web interface to find code in a repository people! Learn from apt-cache.


November 20, 2009

Michael P. Soulier
msoulier
But I Digress
» Java time capsule

I’ve been involved in some discussions regarding Java recently, and I’ve repeated said that I mostly find it a solution that is still looking for a problem.

Looking back at this post by Paul Graham on “Java’s Cover” I find it interesting how many of his points still ring true, 8 years later.

My favorite quote:

It could be that in Java’s case I’m mistaken. It could be that a language promoted by one big company to undermine another, designed by a committee for a “mainstream” audience, hyped to the skies, and beloved of the DoD, happens nonetheless to be a clean, beautiful, powerful language that I would love programming in. It could be, but it seems very unlikely.

My problem with it is simple, and it’s why I dislike ClearCase, and many other technologies; it makes easy things hard. I’m busy. I’d use it if forced to, and then I’d try desperately to like it. Until then, I have better things to do.


November 18, 2009

Michael P. Soulier
msoulier
But I Digress
» Java sucks

Well yes, we know this already from the way that it makes easy things hard, and hard things nearly impossible, but it’s rarely been captured with the eloquence that I find in these wonderful quotes on the topic.

And yet, as cockroaches are to humans this technology/language/marketing campaign continues unabated until having java on one’s resume is a requirement to find a job through some ignorant HR department that has no idea what is is. Like the job posting I saw a few years ago for a java programmer with 10-years experience when java was only 7 years old. Luck with that.

My favourite quote:

If Java had true garbage collection, most programs would delete themselves upon execution. — Robert Sewell

My boss asks me occasionally why I don’t use Java, and I tell him that I have many tools in my toolbox, some good and some bad that I bought on impulse due to good marketing or simply because they were new. Java is like my trendy flip-grip pliers from Crappy Tire that try to be both clippers and needle-nose pliers, but suck at both jobs. I don’t hate the tool, but I certainly don’t reach for it often, and I’m thinking of throwing it out.


August 18, 2009

Michael P. Soulier
msoulier
But I Digress
» Call Select does the right thing

I just got a few calls, two of them from Call Select. The first one asked me to call back and the second said that the matter was cleared-up and we would not have to pay anything, meaning that they can’t find any proof that we ever agreed to their service in the first place.

Why they didn’t just immediately absorb the buck-and-a-half of fees incurred is beyond me, was it really worth the hassle? The person I talked to claims that they most-likely made a mistake. Possible, so I shouldn’t overreact here. The fact is that I don’t know, regardless of what my cynical side wants to suspect, so I’ll just let it lie. I’m more interested now in why this kind of thing is possible in Canada.

Anyway, I also got a call from a reporter a the Ottawa Citizen, as I did email him about the issue, and he said he’d been looking into it. I’m not a big believer in coincidences, personally, so I think I’ll go buy the Citizen for at least the next few days. I suddenly like them even more than usual.

If the Citizen wants to follow-up on weak laws around telecom in Canada, more power to them. Maybe it will help the next guy.


August 10, 2009

Michael P. Soulier
msoulier
But I Digress
» Mike Z., you’ll be missed


…not. Thanks for nothing. I guess six-sigma doesn’t really fix everything, huh?

August 2, 2009

Michael P. Soulier
msoulier
But I Digress
» Still No Long-Distance


So, thanks to our long-distance service being taken over by Call Select without our permission, every time I try to make a long-distance call now, I am asked for an access code.

I was told by a Bell rep that it would be fixed by now, but it’s not and they’re off until Tuesday (long weekend), so no long-distance calls for us.

Thanks again Call Select. And thank you CRTC for working so hard to prevent this kind of thing.