These aren’t just templates, though. See the README.txt.
As it implies, the project-tool.py script is used to effectively convert between Xcode templates and buildable projects. That is, you can create a project that builds/runs like a regular Xcode project, and then easily turn it into a template with the invocation of a simple command line like this:
Nothing remotely Python specific about it. And, as some have noticed, the PyObjC Cocoa templates leverage the new Interface Builder file format (xib) such that all kinds of substitutions happen in the templated interfaces, too. As in: No more MyDocument ever again.
Specifically, RubyCocoa and PyObjC both assume that nothing else might have loaded the dynamic libraries that are automatically generated by the gen_bridge_metadata script. So, either bridge will quite happily attempt to load /System/Library/Frameworks/Foundation.framework/Resources/BridgeSupport/Foundation.dylib and then barf mightily when the other bridge has already loaded the same dylib.
The example is rife with silliness related to catching the resulting exceptions and ignoring them. Worse, the fallout is such that from Foundation import * doesn’t actually cause the Objective-C classes to be defined within the importing module.
There is a back door — objc.lookUpClass() — but this is yet further evidence that, at this time, mixing these two languages in a single Cocoa application is not anything more than a silly hacque (as the SVN repository subdir indicates).
What does it do?
Not much, really.
Start with RubyCocoa Application Template (because I can deal with brokeness in Python, I wanted to start with something working in Ruby)
NSApp Delegate written in Obj-C
Finish loading hooks used to bootstrap PyObjC/Python (with gross exception ignoring goofiness related to the dylib)
Bind a table view to an array of dicts where each dict has the key “name” leading to a string value bound through array controller.
Array controller bound through app delegate method.
App delegate returns array of dictionaries by calling python based NSObject subclass.
Python based NSObject subclass composes an array of dictionaries (all python) from a combinatio of Python strings and Ruby strings by calling an instance of a Ruby based subclass of NSObject.
Very little code. Lots of moving parts. Some gears grinding. Maybe even a gear tooth or four missing. Enjoy.
The NEWS.txt file is extremely illuminating as there were tons and tons of changes and bug fixes in 2.0.
It cannot be emphasized enough; this is a huge release for PyObjC. As big as when PyObjC first gained subclassing (which wasn’t until about 7 years into its 14 year history). Go read the NEWS file; both major enties on PyObjC 2.0.
Note that libffi on Leopard is fully 64 bit and, thus, PyObjC should be mostly ready for 64 bit, though it was neither built for, nor tested with, 64 bit.
Yes, it fully leverages the metadata generated by the BridgeSupport project. Via BridgeSupport, PyObjC — and RubyCocoa, and anything else leveraging BridgeSupport — has enough metadata to bridge to just about any C or Objective-C API. The goal of BridgeSupport is to provide a machine readable description of system APIs with full fidelity; something that the Objective-C runtime metadata does not provide (including, for example, information about straight C functions).
Ronald: Thank you. 12 years is a long time for any open source project to remain active and the last year, largely through Ronald’s contributions, has proven to be one of the most vibrant years of development in the project’s history!
Apple has surpassed Dell in the market cap department. This happened earlier in the year and then Apple’s stock got nailed.
Hopefully, that won’t be the pattern this time around.
Ronald Oussoren — of PyObjC and Universal Python fame (amongst other things) — is in town and will be joining us for Korean food and Bowling this evening. Korean food starts at 7:30pm at Fusion Korea next to Homestead Lanes (though we don’t bowl there — long story).
Bob Ippolito and Ronald Oussoren have been working on a branch of Python 2.4 with the intention of creating a universal build of Python.
They have done that and more. A lot more. In the process, many other aspects of Python on Mac OS X have been fixed or optimized. Furthermore, the Python build now uses SDKs as a part of the build. This lays the framework for being able to do development on one version of the OS while targeting older versions with Python. Very nice.
This is one of the areas of the world of universal binaries that few people really understand.
Building a correct universal binary of most open source projects is exceedingly hard.
Simply passing CFLAGS=-arch i386 -arch ppc will generally not yield a correct binary. Worse, if the project uses autoconf, you can rest assured that the result of ./configure ; sudo make install will only yield a correct result for the architecture the build is created on. While autoconf can support cross-compilation, very few developers using autoconf will jump through the hoops necessary to do so.
And that is really what this boils down to. Cross compilation is hard to get right. Xcode makes building universal binaries easy because the entire high level Mac OS X development model and all of the predecessor technology has been focused on cross-compilation for well over a decade.
If you are planning on developing or maintaining a body of source targeted to Mac OS X that cannot use the Xcode native build system — and there are certainly many reasons to do so — I would highly recommend that you go have a close look at Ronald’s and Bob’s work.
While working with Twisted and Nevow, I ran into a situation where something terribly nasty was happening well below any code I had written. Basically, I was faced with the classic high level development problem of “something I did long ago broke something deep within several layers of large scale systems I did not write”.
In these situations, a debugger does little good because there is little clue as to where things went awry. What I really needed was a way to trace execution.
It turns out that Python has excellent hooks for doing exactly that.
Add the following to any random hunk o’ code:
def traceit(frame, event, arg):
if event == 'line':
lineno = frame.f_lineno
if '__file__' in frame.f_globals:
filename = frame.f_globals['__file__']
if (filename.endswith('.pyc') or
filename = filename[:-1]
name = frame.f_globals['__name__']
line = linecache.getline(filename, lineno)
name = '[unknown]'
src = inspect.getsourcelines(frame)
line = src[lineno]
line = 'Unknown code named [%s]. VM instruction #%d' % \
print '%s:%s: %s' % (name, lineno, line.rstrip())
Then, to turn it on, call sys.settrace(). You can easily toggle the trace functionality, thus reducing the tracing to a very limited portion of the overall execution. This prevents one from drowning in data.
Note that the function has a frame object as an argument. That frame object allows for extremely deep introspection of the execution state, including variable state and just about anything else you would like to find out about the underlying virtual machine.
The original code was cribbed from the dalke scientific site. That article has an awesome explanation of the details of tracing. I just added some error checking and fallback code in the case where the original file/source cannot be determined. This enables the tracing functionality to work seamlessly within the context of Twisted.
It has already saved me a ton of time and I’m about to throw this permanently into my local Python library.