MacPython Logo from __future__ import *

buy music albums Silver Apples buy mp3 albums Tarrus Riley buy tracks mp3 Kravits buy Reaper albums mp3 buy Kravits albums music buy music Evita CD online albums mp3 Silver Apples download Madonna CD music buy tracks music Kravits download music albums Silver Apples

2005-04-19

Safari 1.3+ Canvas

Filed under: macosx — bob @ 12:00 am

[canvas0000.html]

2005-04-18

Safari 1.3 supports Objective-C Plugins

Filed under: PyObjC, macosx — bob @ 8:35 am

[SafariScreenSnapz002.mov]

2005-04-17

Twisted and foreign event loops

Filed under: PyObjC, pygame, python, wxPython — bob @ 8:24 am

There's a new reactor in Twisted svn: threadedselectreactor. This reactor blocks on select() in a worker thread, so that it is easy to integrate with a foreign event loop without having to completely separate your Twisted code into its own thread. This is awesome, and mostly eliminates the need to have specific reactors for each useful foreign event loop (cfreactor, wxreactor, etc.). Especially when the existing integration reactor sucks -- wxreactor is more or less a worst-possible implementation, and the others aren't a whole lot better.

In order to integrate with foreign event loops, threadedselectreactor sports an extension to the reactor interface: interleave(waker). waker is a callable that takes a callable as an argument. Its job is to call this callable from the thread of the main event loop. So, whatever you're integrating with needs to be able to send messages from an arbitrary thread to the main thread. All of the event loops worth the fairy dust their bits are encoded on are designed to do this easily.

Other than that, the only other thing that needs to be considered is shutdown (if it matters to shut down cleanly). To do that, you can simply replace your "quit" function with an implementation that:

  • Sets up an "after shutdown" reactor system event that will call "quitRightNow" when the reactor is dead
  • Calls reactor.stop() to commence the self destruct sequence

wxPython already has wxCallAfter that works perfectly well as the waker argument for interleave, so you can Twistify a wxPython application in about six lines. Here's a full demo: doc/examples/core/threadedselect/wxdemo.py.

PyObjC has a PyObjCTools.AppHelper.callAfter that also serves as a too-trivial-to-be-true waker (coincidence? no -- I just added it). You can check out the demo from: doc/examples/core/threadedselect/Cocoa/SimpleWebClient/. The examples in PyObjC's Examples/Twisted/ have also been refactored to use this (instead of cfreactor, which should be considered dead weight).

pygame is more low-level and doesn't provide any conveniences beyond getting and posting events. So your waker should be some function that posts a USEREVENT to pygame, which you need to pick up and do something with. A minimal example of this is here: doc/examples/core/threadedselect/pygamedemo.py.

This reactor should trivially integrate with just about any event loop, including PyQt, GTK, etc. However, the margins of my blog aren't big enough to fit them all.

2005-04-16

Unicode and vulgar fractions

Filed under: python — bob @ 10:56 pm

This little snippet will scan a block of text and replace fractions with the unicode vulgar fraction equivalent when possible, removing spaces if the fraction is immediately after another number. For example "1 1/2" will be replaced by "1½".

import re
FRACRE = re.compile(ur'(\d\ +)?(\d+/\d+)\b')

FRACTIONS = {
    u'1/2' : u'\u00BD',
    u'1/4' : u'\u00BC',
    u'3/4' : u'\u00BE',
    u'1/3' : u'\u2153',
    u'2/3' : u'\u2154',
    u'1/5' : u'\u2155',
    u'2/5' : u'\u2156',
    u'3/5' : u'\u2157',
    u'4/5' : u'\u2158',
    u'1/6' : u'\u2159',
    u'5/6' : u'\u215A',
    u'1/8' : u'\u215B',
    u'3/8' : u'\u215C',
    u'5/8' : u'\u215D',
    u'7/8' : u'\u215E',
}

def fractions(s):
    def subfrac(m):
        pre, post = m.groups()
        frac = FRACTIONS.get(post)
        if frac is None:
            start, end = m.span()
            return m.string[start:end]
        if pre is not None:
            frac = pre[0] + frac
        return frac
    return FRACRE.sub(subfrac, s)

2005-04-04

PyObjC and unicode

Filed under: PyObjC, macosx, python — bob @ 8:53 pm

There's a constant battle in PyObjC about what to do about regular str instances, since Foundation doesn't have a data type that's unencoded bytes (NSData) and text (NSString) at the same time. Up to now, str instances were be converted to NSString using Python's default encoding (sys.getdefaultencoding()), which is basically always ascii and will raise an exception, which is really never what you want. I committed a change this week that will hopefully be a least worst of both worlds solution:

  • Added OC_PythonUnicode and OC_PythonString classes that preserve the identity of str and unicode objects across the bridge. Additionally, bridge for str now uses the default encoding of NSString, rather than sys.getdefaultencoding() from Python. For Mac OS X, this is typically MacRoman. The reason for this is that not all Python str instances could cross the bridge at all previously. objc.setStrBridgeEnabled(False) will still trigger warnings, if you are attempting to track down an encoding bug. However, the symptoms of the bug will be incorrectly encoded text, not an exception.

This lets NSString decide what encoding to use (generally, MacRoman), so you still get garbage in garbage out, but:

  • It's lossless (garbage in, same garbage out)
  • 7-bit ASCII safe (usually when str is used for text, it is just ascii)
  • Doesn't raise exceptions in strange places
  • If it was data (not text) and you were just putting it in a container or something, it will still be data when you get it back

NeXT/Apple definitely did strings in a very nice way. Rather than deciding there should be one and only one way to do them, they made NSString a class cluster where you can have any concrete implementation you want. The only methods your concrete classes have to implement are:

-(unsigned)length:
Return the number of characters in the string
-(unichar)characterAtIndex:(unsigned)index:
Return the character at that index (or raise an exception)

There are, of course, additional methods that a concrete subclass of NSString can implement for efficiency.

Doing strings in this way has some nice advantages:

  • If they wanted to trade up unichar to 32 bits, it would require minimal changes to the source code
  • You can use whatever backing store you need to use, with whatever properties it needs to have (i.e. mmap backed store, a constant in the code that never gets freed, a length-prefixed string, whatever!)
  • You can use whatever encoding you want to use, and conversion doesn't take place until you do something with it

In Python's case, OC_PythonUnicode is actually a zero-copy concrete subclass of NSString (if Python's unicode characters are the same size as unichar, anyway). Python can't do ANYTHING like this:

  • The backing store of a Python unicode object must be controlled by Python (i.e. you can't point to a constant string, you can't point to a slice of another unicode object, etc.). This throws zero-copy strategies out the window.
  • The encoding of a Python unicode object must be UCS-2 (or UCS-4, depending on configure time options)

So, that sucks... but at least Python does have good unicode support, unlike some other languages with similar heritage.

Powered by WordPress