Blog-o! Notes from latte.ca

Fri, 08 Sep 2006

Okay, y'all know by now that we've got a new Mac. And in the grand tradition of new computers, I'm trying to burn up all the hard drive space with fun or useful utilities. Since this is pretty much my first exposure to OSX, anything goes, since I probably haven't heard of it.

Having said that, here's what I have found:

  • QuickSilver
  • I installed Growl, but I don't think anything is using it, other than Transmission.
  • TextWrangler (Freeware, from the people who make BBEdit) is surprisingly my editor of choice. (Well, except for this post.) I was sure I'ld stick with vim, being old-skool like that, but I find I want to save my Terminal window for running things, and edit my source in an editor.

Oh, and the two neat new tricks I've learned so far are:

  • Command-Shift-4, then the spacebar to take a screenshot of just one window, and
  • sudo defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText -string "My Funny Message!!!"
    to print a message on the login window.

[Posted at 20:39 by Blake Winton] link
Wed, 30 Aug 2006

Cc:-ed to the MacPython list, because they might know.

Hello,

I'm trying to get Subversion bindings for my installed version of MacPython (/Library/Frameworks/Python.framework/Versions/2.4/) This seems to mean that I want to install Subversion, and if so, I would like to get it hooked up to Apache so that I can connect to http://svn.latte.ca/ (or whatever) on my work computer and access my home repository.

Now, I can install the subversion python bindings using DarwinPorts, but that won't hook into the Framework version of Python, so I've downloaded the Subversion 1.3.2 sources, and I can build them, but they complain about my version of Apache. Specifically, about apxs being too old.

Do I really need to upgrade apache to Apache 2 to get this all working?

Is there a good way of replacing the default Apache with Apache 2, or is that a really bad idea because the Software Update will get horribly confused?

Is there another place I should be asking these questions?

Thanks,
Blake.

[Posted at 12:47 by Blake Winton] link
Thu, 24 Aug 2006

As I mentioned before, we got a Mac Mini. It's been a bit of a pain getting it all set up, but I think we're finally done. The web server is moved over, along with all the websites. The mail server is moved over, and I took the opportunity to delete my mother's account. (That's not as bad as it sounds. She had it redirecting to GMail anyways, and the error message says as much. Of course, since I haven't told her about it yet, this will probably come as a bit of a surprise.) Uh, and that turned out to be all the servers I was running. Well, I was running CherryPy, and some other stuff, but it wasn't particularly important, and I've found better ways of doing it, for the most part.

But that's not really why I'm posting here. I'm posting here because I got some cool Python stuff working under the Mac, and I wanted to share it. Specifically, I (or rather, my wife and I) wanted to have a window showing on the login screen, displaying the weather. After several bits of trial and error, and liberal "borrowing" from Dethe Elza's Pastels project I finally got something which would do what I wanted. First, the code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
from AppKit import NSObject, NSApplication, NSTimer, NSApp, NSURL
from AppKit import NSURLRequest, NSWindow, NSTitledWindowMask
from AppKit import NSClosableWindowMask, NSMiniaturizableWindowMask
from AppKit import NSResizableWindowMask, NSBackingStoreBuffered
from BeautifulSoup import BeautifulSoup
from PyObjCTools import AppHelper
from WebKit import WebView, WebDataSource

import os
import stat
import time
import urllib

width, height = 620, 540

def Window(title, width, height, view=None):
    window = NSWindow.alloc().initWithContentRect_styleMask_backing_defer_(
        ((0,0),(width,height)),
        NSTitledWindowMask |
        NSClosableWindowMask | 
        NSMiniaturizableWindowMask |
        NSResizableWindowMask,
        NSBackingStoreBuffered,
        False)
    window.setTitle_(title)
    if view:
        window.setContentView_(view)
    window.orderFront_(window)
    return window

class MyAppDelegate(NSObject):
    def update( self, timer ):
        y = urllib.urlopen( str(self.wUrl) ).read()
        b = BeautifulSoup( y )
        self.view.mainFrame().loadHTMLString_baseURL_(
            """<html><head><title>test<title>%s<head>
            <body>%s<body><html>""" %
            ("".join( [str(x) for x in b.head.findAll( 'style' )]), b.body.div.div.div.div.div),
            self.wUrl )

    def applicationDidFinishLaunching_(self, notification):
        rect = ((0,0),(width, height))
        self.view = WebView.alloc().initWithFrame_(rect)
        self.window = Window('Pastels Test', width, height, self.view)
        self.window_delegate = MyWindowDelegate.alloc().init()
        self.window.setDelegate_(self.window_delegate)
        self.wUrl = NSURL.alloc().initWithString_(
            "http://weatheroffice.ec.gc.ca/city/pages/on-143_metric_e.html")
        self.update( None )
        timer = NSTimer.scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(
            1800, self, 'update', None, True )

class MyWindowDelegate(NSObject):
    def windowWillClose_(self, notification):
        NSApp().terminate_(self)

def main():
    app_delegate = MyAppDelegate.alloc().init()
    NSApplication.sharedApplication().setDelegate_(app_delegate)   
    AppHelper.runEventLoop(installInterrupt=True)

if __name__ == "__main__":
    while True:
        if os.stat( "/dev/console" )[stat.ST_UID] == 0:
            # If the console is owned by root, start the app.
            main()
        else:
            # Otherwise, sleep until it is.
            time.sleep( 10 )


And next, the launchd plist file that keeps it running:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
"http://www.apple.
com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>  
    <key>Label</key>
    <string>ca.latte.update.login.weather</string>
    <key>ProgramArguments</key>
    <array> 
        <string>/path/to/test.py</string>
    </array>
    <key>ServiceDescription</key>
    <string>A program to pop up the weather in a box</string>
    <key>LowPriorityIO</key>
    <true/>
    <key>RunAtLoad</key>
    <true/>
    <key>OnDemand</key>
    <false/>
    <key>Nice</key>
    <integer>1</integer>
    <key>StandardOutPath</key>
    <string>/path/to/loginWeather.out</string>
    <key>StandardErrorPath</key>
    <string>/path/to/loginWeather.err</string>
</dict>
</plist>

And there you have it. Way cooler than my previous attempt, which tried to write using sudo defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText -string "parsed weather info here".

If any of you have any questions, I'ld love to answer them as best I can. Just comment, and I'll see what I can dig up. By which I mean email Dethe, and ask him. ;)

[Posted at 22:23 by Blake Winton] link