An overview of the relevant changes in new, and older, releases.
Note
This is version currently in development and has not been released yet
PyObjC could crash when calling a method that is dynamicly generated (that is, the selector is not present in the class according to the Objective-C runtime but the instance responds to it anyway).
The cases that used to crash now raise objc.error instead.
Note
It is highly unlikely that real code would run into this, found while working on PyObjC 3.x.
When writing a python unicode object to an NSArchiver or NSKeyedArchiver the object is now stored exactly the same as a normal NSString, and will be read back as such.
This increases interoperability with code that expects to read back a non-keyed archive in a different proces. An example of this is the use of Growl (see issue #31)
Instances of subclasses of unicode are not affected by this change, and can only be read back by other PyObjC programs.
Issue #43: It was no longer possible to create instances of LaunchServices.LSLaunchURLSpec due to incomplete metadata.
Issue #41: the ‘install.py’ script in the root of pyobjc repository failed to perform an install when running in a clean checkout of the tree.
Issue #44: the various Cocoa frameworks only export @protocol defintions when they happen to be used by code in the framework. Added extensions to the various framework wrappers to ensure that all protocols are available to python code.
Opaque pointer types now can be constructed with a “c_void_p” keyword argument that contains a ctypes.c_void_p value for the pointer.
This is the reverse of the __c_void_p__() method that was added earlier.
Issue #46: It was not possible to use the Quartz.CoreGraphics module on OSX 10.5 when the binary was build on 10.8 (and using a 10.5 deployment target).
Simular issues may be present in some of the other framework wrappers, there will be a more generic fix for this issue in a future release.
Add conversion to/from ctypes.c_void_p to proxies for Cocoa objects.
To use:
anObject = NSArray.array()
void_p = anObject.__c_void_p__()
# use void_p with ctypes
otherObject = NSObject(c_void_p=voip_p)
assert anObject is otherObject
Note that it is save to contruct the python proxy from NSObject, the class will return an instance of the correct proxy type (in this example an instance of NSArray)
Fixed problem where the result of anObject.__cobject__() could not be converted back to a PyObjC object again.
A number of framework wrappers have a “protocols” submodule containing protocol objects (for example the module ‘Foundation.protocol’). Use of these modules is deprecated, they will be removed in PyObjC 3.0.
Use objc.protocolNamed() to access protocols instead.
Instances of objc.ivar now have slots for introspection:
Added implementation of ‘==’ and ‘!=’ for selectors defined in Python that is slightly smarter than the default (identity based) implementation in Python.
This is mostly done for the PyObjC unittests and shouldn’t affect user code.
Issue #30: Explicitly check if the compiler works, and try to fall back to clang if it doesn’t. This uses a simular algoritm as the fix for <http://bugs.python.org/issue13590> in Python’s tracker.
Issue #22: Reimplement support for bridgesupport files
This reintroduces objc.parseBridgeSupport and objc.initFrameworkWrapper, both are reimplemented in Python (previous version used C code)
Note
The implementation is currently barely tested and therefore likely contains bugs.
Struct types created by the framework wrappers once again create class methods on objc.ivar to generate instance variables of that type:
myLocation = objc.ivar.NSPoint()
This has the same result as:
myLocation = objc.ivar(typer=NSPoint.__typestr__)
objc.IBAction() now raises TypeError when the argument is None.
objc.instancemethod() is now actually exported by the objc package.
objc.accessor() and objc.typedAccessor() were not 64-bit safe.
objc.accessor() and objc.typedAccessor() didn’t support the entire set of KVC accessors.
Add methods “_asdict” and “_replace” and field “_fields” to the struct wrapper types. These new attributes mirror the collections.namedtuple interface.
Note
In the long run I’d like to make struct wrappers immutable to allow using them as dictionary keys. This is a first step in that direction and makes it possible to verify that immutable struct wrappers are useable.
Added objc.createStructAlias(), and deprecated objc.registerStructAlias(). The new function has a “name” argument and can register types with the objc.ivar type (see previous item)
Add explicit deprecation warnings to objc.CFToObject and objc.ObjectToCF. Both functions barely function at all and will be removed with PyObjC 3.0.
objc.CFToObject and objc.ObjectToCF are no longer available when using Python 3.x, the APIs are used for MacPython support and that part of the standard library is not available with Python 3.x.
objc.splitStruct is renamed to objc.splitStructSignature and now actually works. The old name is temporarily available as an alias.
Fix refcounting leak in objc.splitSignature.
objc._loadFunctionList is renamed to objc.loadFunctionList and is fully documented. The old name is temporarily available as an alias.
Move (deprected) decorator “signature” from objc._functions to objc._descriptors, and remove the former module.
Note
The names op submodules of objc are implementation details, don’t import them directly.
The optional argument for the decorator objc.selectorFor() was broken
The PyObjCTools.KeyValueCoding.kvc wrapper __setattr__ wrapper incorrectly set attributes on itself as well as on the wrapped object (the latter using Key-Value Coding)
Renamed (private) function injectSuffixes to inject_suffixes to match the other code in objc._dyld.
Slight restructuring of objc._pythonify to reduce code duplication between the python 2.x and python 3.x cases.
Removed deprecated methods from PyObjCTools.TestSupport
collections.Sequence objects are now automaticly proxied as NSArray instances
collections.Mapping objects are now automaticly proxies as NSDictionary instances
Removed some objects and functions from objc._bridges that weren’t public and weren’t used by PyObjC itself:
_bridgePythonTypes was called unconditionally, but never did anything because the data structures were empty and no code adds anything to them.
Improved documentation
For Objective-C blocks: try to extract the block signature from the (Objective-)C runtime when there is no metadata for the block. The block signature is available only when the code that creates the block is compiled using a recent enough compiler (although “recent enough” is fairly old by now)
Fixes some issues with objc.object_property which were found by improved unittests. In particular:
Fixed some issues with objc.array_property and objc.set_property that were found by much improved unittests.
Fixed issues with PyObjCTools.KeyValueCoding that were found by improved unittests:
getKey didn’t work propertly on dictionaries (dictionaries were treated as sequences)
getKeyPath didn’t raise the correct exception for empty key paths
@unionOfObjects and @distinctUnionOfObjects operators for Python sequences didn’t raise an exception when the selected keypath didn’t exist on an item of the sequence.
@unionOfArrays and @distinctUnionOfArrays operators for Python sequences didn’t raise an exception when the selected keypath didn’t exist on an item of the sequence.
the keypath pointed to objects that weren’t hashable.
@distinctUnionOfSets operator was not present at all.
‘PyObjCTools.KeyValueCoding.setKey’ now sets keys in dictionaries, that is:
>>> a = {}
>>> setKey(a, 'foo', 42)
>>> a
{'foo': 42 }
‘PyObjCTools.KeyValueCoding.setKey(object, ‘key’, value)’ now sets attribute ‘key’ when the object already has that attribute, before looking at ‘_key’. This avoids that setKey changes the underlying storage for a common Python property pattern:
class Record (object):
@property
def prop(self):
return self._prop
@prop.setter
def prop(self, value):
self._prop = calculate_using(value)
Until PyObjC 2.5 the property setter for ‘prop’ would not be called when using KeyValueCoding.
Removed Mac OS X 10.2 (!) compatibility from PyObjCTools.KeyValueCoding.
PyObjCTools.KeyValueCoding has undocumented attributes ‘ArrayOperators’ and ‘arrayOperators’, both will be removed in a future release.
Using NSArchiver or NSKeyedArchiver to encode and then decode a python list or tuple could result in an unexpected value. In particular, if any element of the sequence was None before archiving it would by NSNull.null() when read back.
Using NSArchiver or NSKeyedArchiver to encode and decode (pure) python objects didn’t always work correctly. Found by improved unittests.
Using NSArchiver or NSKeyedArchiver to encode and decode bytes objects in Python 3 would result in an instance of NSData instead of bytes.
The implementation of cmp() for NSSet instances now matches the behavior of regular python sets, that is calling cmp(anNSSet, aValue) will raise a TypeError exception unless both arguments are the same object (anNSSet is aValue).
Issue #36: explictly document that PyObjC does not support the Objective-C Garbage Collection system (introduced in OSX 10.5, deprecated in OSX 10.8), and also mention this in the documentation for the screen saver framework because the screen saver engine uses GC on OSX 10.6 and 10.7.
Issue #37: Fix runtime link error with EPD (Enthought Python Distribution), which doesn’t include the pymactoolbox functionality.
Various improvements to the documentation
Note
2.41 was never released, all bugfixes are in the 2.4 branch as well as the 2.5 release.
Cocoa wrappers: fix metadata for copy, mutableCopy, copyWithZone: and mutableCopyWithZone:
Fix for issue 3585235 on SourceForge: the threading helper category on NSObject didn’t work due to a typo (defined in the Cocoa bindings)
Fix is based on a patch by “Kentzo” with further updates and tests by Ronald.
Rename ReadMe.txt to README.txt to work around misfeature in the sdist command in distutils.
Issue #28: Avoid crash when using CGEventTabProxy values.
Issue #33: “easy_install pyobjc” no longer tries to install the InterfaceBuilderKit bindings on OSX 10.7 or later.
Note
Sadly enough this changelog is incomplete.
Fix crash when unarchiving a Python object.
Add missing calls to [super init] in the implementation of OC_PythonUnicode and OC_PythonString (the ObjC proxies for python’s unicode and str types)
objc.addConvenienceForSelector is deprecated, primarily to make it possible to restructure the pyobjc internals.
Workaround for bug in pip that resulted in pyobjc-core not being pip installable. Patch by Marc Abramowitz.
Creating new formal protocols now uses the new runtime API that was introduced in OSX 10.7. Because of this it is now possible to create new formal protocols in 64-bit code (when running on OSX 10.7 or later)
Codebase should work again when Python using --enable-unicode=ucs4.
BUG: Avoid crashes in calculating with NSDecimal values in Python 3
Implement ‘//’ operator for NSDecimal and NSDecimalNumber.
Implement support for the round builtin in NSDecimal and NSDecimalNumber
There is now limited support for packed struct definitions. This requires that the struct is wrapped using objc.createStructType.
Struct packing is not described in the encoding string for a structure, which is why special support is needed.
objc.registerStructAlias now returns the alias type instead of None
In Python 3.x there is a new way to explicitly specify which (informal) protocols a class conforms to:
class MyClass (NSObject, protocols=[Protocol1, Protocol2]):
pass
Python 2.x does not support this syntax, you can still use the following code there:
class MyClass (NSObject, Protocol1, Protocol2):
pass
Note: The Python 2.x style works upto Python 3.2. In Python 3.3 and later the Python 2.x style declaration no longer works due to changes in the language.
It is also possible to specify the protocols that a class conforms to using a “__pyobjc_protocols__” attribute in the class body. This has the same interface as the “protocols” keyword argument in Python 3.x.
This is primarily meant to be used by code that needs to work in Python 2 as well as Python 3.
Updated Python support. With this release PyObjC supports Python 2.6 and later, including Python 3.3 (which has a completely new representation for unicode strings)
NOTE: Support for 3.3 is very much work in progress right now, there have been changes for the new unicode representation, but more changes are required.
Known issues:
Futhermore there are two refcounting test failures in both 3.2 and 3.3
Add objc.setObjCPointerIsError and objc.getObjCPointerIsError.
By default PyObjC will create a PyObjCPointer object when it tries to convert a pointer it doesn’t know about to Python. These values are fairly useless and obvious an indication that an API is wrapped improperly.
With objc.setObjCPointerIsError(True) you can tell the bridge to raise an exception instead of creating these values.
-[OC_PythonNumber compare:] calls super when the other value is an NSNumber and the Python value can be represented using a basic C type.
This could slightly affect the results of comparing Python and Cocoa numbers, and avoids unbounded recursion when comparing Python numbers with NSDecimalNumbers on OSX 10.7 or later.
Add implementations for methods from the NSComparisonMethods informal protocol to OC_PythonNumber
Add ‘__cmp__’ method when the Objective-C class implements the ‘compare:’ selector.
Introduced a way to compile bridgesupport data and lazily load wrappers.
Avoid using “from Cocoa import *” to get the most benefits from this, use either “import Cocoa” or “from Cocoa import NSObject”.
objc.initFrameworkWrapper is now deprecated, switch to the new compiled metadata code instead.
objc.allocateBuffer now returns a bytearray on python >= 2.6, it used to return a buffer object in Python 2.
a TypeError.
objc.getAssociatedObject, objc.setAssociatedObject and objc.removeAssociatedObjects are wrappers for the corresponding functions in the Objective-C runtime API. These functions are only available when PyObjC was build on a system running OSX 10.6 or later, and the script is also running on such as system.
The policy argument for objc.setAssociatedObject is optional and defaults to objc.OBJC_ASSOCIATION_RETAIN.
Add some experimental code that slightly reduces the amount of memory used when loading bridgesupport files.
Futher work is needed to investigate what causes the memory usage to increase as much as it does, sadly enough Instruments doesn’t play nice with --with-pymalloc and for some reason ‘import Foundation’ crashes with --without-pymalloc.
“<struct>” definitions in the bridgesupport files can now have an alias attribute containing the name of Python type that should be used to proxy values of this type.
This is used in the Quartz bindings to ensure that CGRect and NSRect (from the Foundation framework) map onto the same Python type.
Added objc.registerStructAlias, a helper function to add a type encoding that should map on an already existing struct type.
Use this to ensure that NSRect and CGRect are the same (in the Foundation and Quartz bindings).
This version requires Python 2.6 or later, and also supports Python 3.1 or later.
BUGFIX: The generic proxy for Python objects now implements -(CFTypeID)_cfTypeID, which should result in less hard to understand Objective-C exceptions.
BUGFIX: The metadata file support now checks if the metadata is compatible with information gathered from the Objective-C runtime.
This ensures that when a native method signature is incompatible with the signature in a metadata file the brige won’t garble the correct information (and that in turn avoids hard crashes).
PyObjC’s support for NSCoding now also works with plain NSArchiver instances, not just with NSKeyedArchiver.
(This item is currenlty only true for python3, need tests for python 2.x)
NSDictionary now fully implements the dict API, except for the differences not below:
NSDictionary doesn’t have the __missing__ hook.
semantics from Python.
NSDictionary.copy always returns an immutable dictionary, use NSDictionary.mutableCopy to get a mutable dictionary.
Instances of NSDictionary cannot be pickled
NSDictionary implements one important feature that native Python dictionaries don’t: full support for Key-Value Observations. Sadly enough it is not possible to support Key-Value Observation of native Python dictionaries without patching the interpreter.
NSSet and NSMutableSet implement the same interface as frozenset and set, except for the differences listed below:
object, use the mutableCopy method to create a mutable copy.
Instances of NSSet cannot be pickled
In-place operators are not implemented, which means that aSet |= value will assign a new object to aSet (as if you wrote aSet = aSet | value.
This is needed because the bridge cannot know if if aSet is mutable, let alone if aSet is a value that you are allowed to mutate by API contracts.
It is not possible to subclass NSSet and NSMutableSet in the same way as Python’s set and frozenset classes because the Cocoa classes are class clusters (which means that all instances of NSSet are actually instances of, non-necessarily public, subclasses.
Sadly enough set([1,2,3]) == NSSet([1, 2, 3]) evaluates to False, even though the values are equavalent. Reversing the order of the test (NSSet([1, 2, 3]) == set([1,2,3])) results in the expected result.
This is caused by the way equality tests for sets are implemented in CPython and is not something that can be fixed in PyObjC.
BUGFIX: accessing methods through anObject.pyobjc_instancMethods is now safer, before this release this could cause unlimited recursion (although I’m not sure if it was possible to trigger this without other changes in this release).
The PyObjC egg now includes the header files that should be used to compile to compile the extensions in the framework wrappers, which makes it a lot easier to access those headers.
BUGFIX: The definition for Py_ARG_SIZE_T was incorrect, which causes problems in 64-bit code.
Initial port to Python 3.x
C-style ‘char’ characters and ‘char*’ strings are translated to/from byte strings (‘str’ in Python 2.x, ‘bytes’ in Python 3.x). There is no automatic translation from Unicode strings.
Objective-C selector names and encoded type strings are byte strings as well.
NOTE: Python 3 support is pre-alpha at this time: the code compiles but does not pass tests yet. The code also needs to be reviewed to check for python3<->objc integration (dict.keys now returns a view, NSDictionary.keys still returns a basic iterator, ...)
TODO:
The Python 3.x port does not support transparent proxies for ‘FILE*’ “objects” because the file type in Python3 is not implemented on top of the C library stdio.
The Python 2.x port has been enhanced to accept Unicode strings in more locations.
Implement support for PEP-3118, for both Python 2.x and Python 3.x.
This means that proxying arrays of basic C types to ObjC can now make use of the extended type information provided by the PEP-3118 API.
Furthermore it is possible to use memoryview objects with NSData instances, with the limitation that the memoryview must be cleaned up before the currently active autorelease pool is cleared, or the data instance is resized. That’s a result of API restrictions in Apple’s frameworks.
The PyObjCTest testsuite now supports version-specific tests: for Python 2.x it will load modules whose name starts with ‘test2_’ and for Python 3.x those starting with ‘test3_’. For both versions it will load test modules whose name starts with ‘test_’ as well.
Renamed the assertion functions in PyObjCTools.TestSupport, added assertFoo methods and deprecated the failIfFoo and failUnlessFoo methods (simularly to what’s happening in the stdlib).
Added objc.propertiesForClass. This function returns information about properties for a class from the Objective-C runtime. The information does not include information about properties in superclasses.
Added objc.object_property. This is class behaves simularly to property, but integrates better with Objective-C code and APIs like Key-Value Observation.
Added objc.array_property. This is simular to objc.object_property, but models a list-like object and implements the right Objective-C interfaces for Key-Value Coding/Observations.
Added objc.set_property. This is simular to objc.object_property, but models a set-like object and implements the right Objective-C interfaces for Key-Value Coding/Observations.
Added objc.dict_property. This is simular to objc.object_property, but models a dict-like object and implements the right Objective-C interfaces for Key-Value Coding/Observations.
NOTE: The interfaces of array_property, set_property and dict_property are minimal w.r.t. options for tweaking their behaviour. That will change in future versions of PyObjC.
Please let us know which hooks would be usefull.
The documentation is now written using Sphinx.
NOTE: This is an operation in progress, the documentation needs work to be truly usefull.
The (undocument) module PyObjCTools.DistUtilsSupport is no longer present.
Converting a negative value to an unsigned integer now causes a deprecation warning, this will be a hard error once I update all framework wrapper metadata.
BUGFIX: Ensure PyObjC compiles cleanly with Python 2.6.4.
BUGFIX: It is now possible to explicitly define __getitem__ (and other special methods) if your class implements objectForKey::
class MyObject (NSObject):
def objectForKey_(self, k):
pass
def __getitem__(self, k):
pass
In previous version of PyObjC the implementation of __getitem__ would silently be replaced by a generic one.
The default value for the __useKVO__ attribute in class definitions can now be controlled by objc.setUseKVOForSetattr(b). The default is True.
Note: in previous versions the default was False.
Note2: the __useKVO__ attribute is an implementation detail and should not be used in normal code.
This change fixes an issue where KVO failed to detect some changes when those changes were done in Python using attribute access syntax.
Wrappers for objc_sync_wait, objc_sync_notify and objc_sync_notifyAll have been removed. These have never been part of the public API and this should therefore not affect existing code.
BUGFIX: There was a refcount leak in the code that proxies native code to Python. This causes refcount leaks in user code when a Python class is instantiated from native code, when that class has an initializer written in Python.
Thanks to Dirk Stoop of Made by Sofa for providing the bugreport that helped fix this issue.
objc.recycleAutoreleasePool is now a no-op when a python bundle is loaded in an Objective-C program and the PyObjC’s global release pool gets drained by an outer release pool. This should not affect user programs.
BUGFIX: Storing pure python objects in a NSKeyedArchiver archive didn’t full work for all tuples, especially self-recursive tuples.
The current support for archiving Python objects passes all pickle unittests in Python 2.7.
BUGFIX: +new is supposed to return an already retained object (that is, the caller owns a reference). Until now PyObjC has assumed that the return value of +new is an autoreleased value. The same is true for all class methods whose name starts with new.
There is initial support for Objective-C blocks, based on the implementation description in the clang repository. Blocks are represented in Python as callable objects. This means you can pass an arbitrary callable when an Objective-C argument is a block, and that when your method accepts a block it will get passed a callable object.
There are some limitations on the usage of blocks due to lack of introspection in the current implementation of blocks. This has two side-effects:
objc.inject is no longer support. This was code that had no real relation to the rest of PyObjC and was only working in 32-bit mode with little reason to expect that it would ever be ported to 64-bit mode.
Move the testsuite from objc.test to PyObjCTest and no longer install the tests.
The tests are no longer installed because they aren’t needed for day-to-day usage of PyObjC. Furthermore this change will make it possible to copy all of the pyobjc-core “egg” into an application bundle without adding unnecessary files to that bundle.
BUGFIX: Storing pure python objects in a NSKeydArchiver archive didn’t work 100% reliably for Python floats. I’ve changed the implementation on for encoding floats a little and now floats do get rounddtripped properly.
The side effect of this is that archives written by PyObjC 2.2b2 or later cannot always be read by earlier versions (but PyObjC 2.2b2 can read archives created with earlier versions).
BUGFIX: Enable building from source with the Python.org binary distribution.
BUGFIX: Fix crash when using the animotor proxy feature of CoreAnimation. That is, the following code now works:
1 2 3 4 | app = NSApplication.sharedApplication()
window = NSWindow.alloc().init()
anim = window.animator()
anim.setAlphaValue_(1.0)
|
Improve handling of non-methods in objc.Category:
The docstring of a category is now ignored
You’ll get an explict error exception when trying to add and ivar to a class
It’s now possible to add class attributes in a category:
1 2 3 4 5 6 | class NSObject (objc.Category(NSObject)):
aClassDefault = [ 1, 2, 3 ]
@classmethod
def getDefault(cls):
return cls.aClassDefault
|
Fixed support for FSRef and FSSpec structures.
Added more magic signature heuristics: the delegate selector for sheets is now automaticly recognized, removing the need for the decorator AppHelper.didEndSelector (which will stay present for backward compatibility).
FIXME: Do the same thing for objc.accessor. Both are a frequent source for errors.
Added PyObjC.TestSupport. This is an unsupported module containing useful functionality for testing PyObjC itself.
Added free_result attribute to the retval element in metadata files. When this attribute has value 'true' the return value of the C function (or ObjC-method) will be free-ed using the function free(), otherwise the bridge assumes other code is reponsible to free the result.
This is to be used for low-level C API’s that return a pointer to a dynamicly allocated array that is to be free-ed by the caller. One example is the function DHCPClientPreferencesCopyApplicationOptions in the SystemConfiguration framework.
Added objc.context, which is helpfull for dealing with “context” arguments as used by several Cocoa APIs. The context argument must be a number in Python, while you’d prefer to pass in an arbitrary object instead. The objc.context registry allows you to get a context integer for an arbitrary Python object, and retrieve that later on.
To get the context integer for a Python object:
ctx = objc.context.register(myValue)
To unregister the object when you no longer need the context integer:
objc.context.unregister(myValue)
To retrieve the Python object given a context integer:
myValue = objc.context.get(ctx)
NOTE: This API is particularly handy when using Key-Value Observing, where the context number should be a unique value to make ensure that KVO usage by the superclass doesn’t get confused with your own usage of KVO.
PyObjC can now run in 64-bit mode.
NOTE: 64-bit support is beta quality, that is: all unittests pass, but I haven’t tried running real programs yet and hence there might be issues lurking below the surface.
NOTE: 64-bit support does not yet work on PPC due to a bug in libffi which prefents catching Objective-C exceptions.
This requires Leopard (OSX 10.5), earlier version of the OS don’t have a 64-bit Objective-C runtime at all. This currently also requires a copy of python that was build with MACOSX_DEPLOYMENT_TARGET=10.5.
Note that class posing (the poseAsClass_ class method) is not supported in 64-bit mode. It is also not possible to create new protocols in 64-bit code. Neither are supported by the 64-bit runtime APIs (that is, it is a restriction in Apple’s Objective-C 2.0 runtime).
There now is a custom proxy class for instances of datetime.date and datetime.datetime, which takes away the need to manually convert these instances before using them from Objective-C (such as using an NSDateFormatter)
Objective-C classes that support the NSCopying protocol can now be copied using copy.copy as well.
OC_PythonArray and OC_PythonDictionary now explicitly implement copyWithZone: and mutableCopyWithZone:, copies will now be Python objects instead of regular NSDictionary instances.
Pure Python objects now support the NSCopying protocol.
A new decorator: objc.namedselector for overriding the Objective-C selector. Usage:
1 2 3 4 5 | class MyObject (NSObject):
@objc.namedselector("foo:bar:")
def foobar(self, foo, bar):
pass
|
A number of new type signature values were added. These are not present in the Objective-C runtime, but are used to more precisely describe the type of some arguments.
The new values are:
PyObjC will automaticly translate these values into the correct Objective-C type encoding when communicating with the Objective-C runtime, making this change transparent to anyone but Python users.
NOTE: _C_CHR is of course still supported, with the same semi-schizofrenic behaviour as always.
NOTE2: The non-standard metadata extensions we used before to indicate that a C short is used as a unicode string are no longer supported.
Output arguments are no longer optional. They must be specified both in method implementations and method calls. In PyObjC 2.0 they were optional, but raised a deprecation warning, for backward compatiblity with PyObjC 1.x.
The backward compatibility code was removed because it made code more complicated and actually caused some bugs.
In PyObjC 1.x you could redefine an Objective-C class, as long as you redefined it in the same module (such as by reloading a module). That functionality didn’t work in PyObjC 2.0 and is now completely removed because the functionality isn’t supported by the Objective-C 2.0 runtime.
Adds custom wrappers for some more Python types:
OC_PythonNumber: wraps python numeric types
This is used instead of NSNumber because we might loose information otherwise (such as when using custom subclasses of int).
OC_PythonSet: wraps a python set and is a subclass of NSMutableSet
BUGFIX: OC_PythonEnumerator now actually works.
BUGFIX: using the @throw syntax one can raise arbitrary objects as exceptions (not just instances of NSException) in Objective-C. All instances of NSObject are now converted to Python exceptions, throwing some other object (such as a C++ exception) will still case a fatal error due to an uncaught exception.
(SF Bug: 1741095)
BUGFIX: repr(CoreFoundation.kCFAllocatorUseContext) now works
(SF Bug: 1827746)
BUGFIX: The wrappers for CoreFoundation types no longer create a new type in the Objective-C runtime, that type wasn’t used anywhere and was an unwanted side-effect of how CoreFoundation types are wrapped.
BUGFIX: The docstring for newly defined methods is no longer hidden by PyObjC. That is, given this code:
1 2 3 4 | class MyObject (NSObject):
def doit(self):
"do something"
return 1 + 2
|
MyObject.doit.__doc__ now evaluates to "do something", in previous versions of PyObjC the docstring was None.
BUGFIX: Fixed calling and implementation methods where one or more of the arguments are defined as arrays, like this:
-(void)fooCallback:(NSRect[4])rects;
There were various issues that caused these to not work correctly in all earlier versions of PyObjC (which wasn’t noticed earlier because Apple’s frameworks don’t use this construction).
BUGFIX: correctly select the native implementation of the compatiblity routines for the ObjC 2.0 runtime API when running on 10.5 (when compiled for OSX 10.3 or later).
BUGFIX: fix a number of compatibility routines (ObjC 2.0 runtime API on OSX 10.4 or earlier).
BUGFIX: objc.inject works on Leopard (at least on Intel Macs, haven’t tested on PPC).
BUGFIX: don’t crash when printing CF objects that are magic cookies.
BUGFIX: It is now possible to override respondsToSelector: in Python.
Add support for interacting with '@synchronized‘ blocks in Objective-C.
The function object_lock(object) is a contextmanager that acquires and releases the '@synchronized‘ mutex for an object, and can also be used manually.
That is (as context manager):
1 2 3 4 5 6 7 | from __future__ import with_statement
obj = NSObject.new()
with objc.object_lock(obj):
# Perform work while owning the @synchronize lock
pass
|
or (manually):
1 2 3 4 5 6 7 8 | obj = NSObject.new()
mutex = objc.object_lock(obj)
mutex.lock()
try:
# Perform work while owning the @synchronized lock
pass
finally:
mutex.unlock()
|
Note that the first version is slightly saver (see the documentation for with-statements for the details).
The basic infrastructure for playing nice in a GC host was added.
This doesn’t mean that PyObjC now actually plays nice with the ObjC garbage collector, some more development and much more testing is needed for that.
Even so, the end result is about as good as we have without GC, programs won’t make optimal use of GC because that would require surgery on the Python interpreter itself.
The metadata returned by the __metadata__ method is slightly changed to make it more compatible with the XML files.
Some of the older metadata attributes, such as isAlloc and doesDonateRef were dropped. isAlloc isn’t needed for anything but a number of now hardcoded methods (+alloc and +allocWithZone:), doesDonateRef is available through the new metadata mechanism.
Fix a memory leak in the code that creates the python representation for method lists.
Speed up framework loading due to three changes:
It is now conveniently possible to create instance variables with a specific type (e.g. without manually making up a encoded type string):
1 2 3 | class MyObject (NSObject):
bounds = objc.ivar.NSRect()
done = objc.ivar.bool()
|
Objective-C metaclasses are modelled as Python metaclasses. This brings a major improvement: class methods “just work”(TM):
1 2 3 4 | o = NSObject.alloc().init()
o.description()
NSObject.description()
|
In earlier versions of PyObjC the second call would fail because NSObject.description referred to an unbound instance-method instead of to the class method.
This change should require little or change to existing code. There’s only two types of code where the new behaviour is incompatible:
Code that introspects the class dictionary to see what methods are available. These will no longer see class methods, but will have to look at the metaclass as well. This affects pydoc(1) as well.
Code that uses unbound instance methods will no pick up class methods in some occasions. Use MyClass.instanceMethodForSelector_ instead of unbound methods, or alternatively access instance methods through MyClass.pyobjc_instanceMethods.
Due to a limitation in the implementation of python’s super class[1] it is not possible to use the super machinery to resolve class methods.
However, from Foundation import * will replace the builtin super by a subclass that does work correctly for PyObjC programs, therefore this doesn’t affect most PyObjC-using programs.
| [1] | It is not possible to override the way super looks for the “next” method to call. The class objc.super is a subclass of the builtin superclass with a __getattr__ implementation that does the right thing for supercalls for Objective-C class methods. |
It is now easily possible to tell PyObjC that a Python type should be treated like a builtin sequence type:
1 2 3 4 5 6 | import UserList, objc
class MyClass (UserList.UserList):
pass
objc.registerListType(MyClass)
|
And likewise for mapping types using objc.registerMappingType.
objc.enableThreading() is gone. It was introduced in ancient times to enable threading in the Python runtime but has been a no-op for ages because the PyObjC enables threading by default now.
The unittests can now use the leaks(1) command to check for memory leaks. This slows testing down significantly and is therefore off by default. Enable by setting PYOBJC_WITH_LEAKS to a value in the shell environment before running the tests:
$ PYOBJC_WITH_LEAKS=1 python setup.py test
NOTE: the actual value is ignored, as long as there is a value.
(BUGFIX): PyObjC was leaking memory when doing scans of the Objective-C method tables
(BUGFIX): The code below now raises an error, as it should have done in previous versions but never did:
1 2 3 | class MyObject (object):
def updateDescription(self):
self.description = 42
|
PyObjC has been split into several smaller packages: pyobjc-core contains the core bridge and frameworks are wrapped as seperate setuptools packages.
Objective-C objects now have an implicit attribute named _ which can be used a shortcut for Key-Value-Coding.
The code fragment below:
1 2 3 | o = <Some Objective-C Object>
print o._.myKey
o._.myKey = 44
|
is equivalent to:
1 2 | print o.valueForKey_('myKey')
o.setValue_forKey_(44, 'myKey')
|
The former is much nicer to use.
Struct wrappers now have a copy method. This method tries to do the right thing when subfields are other struct wrappers (that is, deep-copy them).
The metadata system has been revamped and mostly removes the need to write C-code when wrapping frameworks (that includes most of the AppKit and Foundation wrappers as well). The metadata is loaded at runtime from an XML file, whose format is shared between PyObjC and RubyCocoa.
objc.initFrameworkWrapper can be used to load a framework using these XML metadata files.
Note: because we now use an XML metadata file the scripts in Scripts/CodeGenerators have been removed: they are no longer needed. Have a look at the project pyobjc-metadata if you want to generate your own metadata.
Note2: the metadata format is shared with RubyCocoa, although there are currently some slight differences (that is, the PyObjC metadata is slightly richer).
PyObjC now has builtin support for CoreFoundation-based types, which is used by the new metadata file support. Note that doesn’t mean we support all of CoreFoundation and other CF-based frameworks, just that the machinery that’s needed for that is present and working.
This is a backward incompatible change: CF-based types will now be proxied using PyObjC-owned types instead of the ones in MacPython. However, PyObjC will still convert MacPython CF-wrappers to the right native type.
Another backward compatible change: registerCFSignature has a different signature:
registerCFSignature(name, encoding, typeId [, tollfreeName]) -> type
This is needed to capture all information about CF types.
This version introduces generic support for callback functions. The metadata metioned before contains information about the signature for callback functions, the decorator callbackFor converts a plain function to one that can be used as a callback:
1 2 3 4 5 6 7 8 | @objc.callbackFor(NSArray.sortedArrayUsingFunction_andContext_)
def compare(left, right, context):
if left.key < right.key:
return NSOrderedAscending
elif left.key > right.key:
return NSOrderedDescending
else:
return NSOrderedSame
|
The makeCallbackFor callback should be used for callbacks where the callable is stored by the called function and is optional otherwise (such as the example above).
The decorator selectorFor can be used to ensure that a method has the right signature to be used as the callback method for a specific method.
Usage:
@objc.selectorFor(NSApplication.beginSheet_modalForWindow_modalDelegate_didEndSelector_contextInfo_)
def sheetDidEnd_returnCode_contextInfo_(self, sheet, returnCode, info):
pass
PyObjC compiled on Leopard uses the Objective-C 2.0 runtime.
The compiler on 10.5 still gives warning about usage of deprecated APIs unless compiling for 10.5 or later because of a compatibility layer.
GNUstep support has been removed because this has never worked properly, nobody seems interested in fixing that and the internal APIs of PyObjC have changed greatly.
Output arguments are treated slightly different. In previous versions you were not allowed to pass values for output arguments.
This is now deprecated behaviour, you should choose to suply values for all arguments including output arguments (mixing these two styles is not allowed, if you have two output argument you must either supply a value for both of them or neither).
There are only two acceptable values for output argument:
The already existing behaviour is the same as passing in None for all output arguments.
This is most useful for supressing an NSError value for methods that have an NSError** argument (when you don’t want to look at that value), because generating that object might be expensive.
objc.setSignature is deprecated, use the new metadata machinery instead.
Opaque types (such as NSZonePointer) are now mutable, which is mostly present to allow framework wrappers to provide a nice OO interface to those types instead of forcing users to use the procedural API.
None of the current framework wrappers use this feature.
Several new methods were added to improve integration with a future version of MacPython: opaque pointer types and NSObject now have a method named __cobject__ that returns a PyCObject which represents the proxied value. Furthermore both opaque pointer types and subclasses of NSObject are now callable and will create the proper proxy object when passed a PyCObject. Note however than the caller is responsible to ensure that the PyCObject value represents a value of the right type.
Archiving pure python objects using NSArchiver was already unsupported, we now explicitly raise an exception when users try to do this anyway. It is supported to archive and retrieve simple values: instances of int, long, float, str and unicode.
A __del__ or dealloc method can revive objects, which isn’t really supported by Objective-C. We’ll now warn about this, hopefully before the program crashes. The warning is objc.RevivedObjectiveCObjectWarning.
Some functions and methods return an instance of objc.varlist. These objects behave a little like tuples, but don’t have a defined lenght, you are responsible to not peak beyond the end of the actual array.
The best way to deal with these objects is to convert them to real tuples as soon as possbible (using the as_tuple method). The number of elements in that tuple should be known to you and depends on the API.
These objects are used in places where objects return an array but the size of that array cannot be described using the bridge metadata. These are mostly arrays whose size depends on the state of an object, or whose size is a function of one or more arguments of the method.
There now is a public API for adding new “convenience methods”, that is methods that emulate standard Python methods using Objective-C methods.
There are two functions for adding new convenience methods:
addConvenienceForSelector('hash', [
('__hash__', lambda self: self.hash()),
])
specified name:
addConvenienceForSelector('NSObject', [
('dummy', lambda self: 42 ),
])
In both cases the addition is done lazily, the class that will be changed need not be loaded at the time of the call.
Fix a long-standing race condition where one could end up with a reference to an already deallocated Objective-C object when the last ObjC reference goes away on one thread and is just “recreated” on a second thread.
The ‘name’ and ‘reason’ of an Objective-C exception are now represented as Unicode objects in the Python representation of the exception, instead of as a UTF-8 encoded string.
The standard Python exception message is still a UTF-8 encoded string, that’s needed to ensure that we can always print the value of the exception message (such as in tracebacks).
PyObjC now uses setuptools. Setuptools support is fairly minimal at the moment, we expect to move more of the build infrastructure to setuptools and to split PyObjC into smaller eggs.
Fix an issue that made is possible to create weakref’s to subclasses of subclasses of Objective-C classes. This was unintentional behaviour, the weakref is to the proxy (see the news for 1.0b1 for more details).
Add RoundTransparentWindow and DragItemAround examples in Examples/AppKit.
Both are ports of Objective-C examples at ADC and were provided by ytrewq1.
Fix issue where programs would crash with an badly aligned C-stack on some problems. This issue only affected Intel systems.
Remove OC_PythonObject.pythonifyStructTable. This method of wrapping structs was untested and not used in the core distribution. Use objc.createStructType instead.
Binaries build on 10.4 also work on 10.3. This means it is no longer necessary to build PyObjC on the lowest version of the OS that you want to run your binaries on. Doing this with python is somewhat of a black art, please test your applications on the lowest version of the OS that you want to support to make sure that this actually works.
Classes whose name starts with and underscore are no longer imported when using objc.loadBundle. They are still available using objc.lookUpClass.
Methods whose name starts with an underscore are no longer visible when introspecting using dir(), but can still be called.
These changes were done to make introspection slightly more user-friendly: anything that is now hidden from introspection is most likely not part of a public API.
Most of the libffi testsuite is now run using a module that emulates dejagnu.
Introduction of a GUI tool to manage custom method signatures (Tools/Signatures). This replaces the find-raw-pointers.py script.
Fixed memory leak in OC_PythonObject, this was due to bad reference counting.
NSMutableArray.sort now has the same API as list.sort. Due to implementation constraints the key argument results in slower sorting than you’d see with list.sort.
Selectors now have a read-only property ‘native_signature’ that contains the untampered signature for the method. This is for use by tools.
‘void*’ arguments are treated like unsigned integers, they are almost always opaque cookies.
FILE* arguments are recognized and mostly work correctly. We can’t reliably detect if the file was opened in append mode though.
Make it possible to override the KVO methods, like setValue:forKey: and valueForKey: in Python for all levels in the inheritance hierarchie.
Fix issues with reference counts for __slots__.
Experimental: use -autorelease instead of -release to release values in destructors. This seems to solve at least one memory managment issue.
A slight complication in the naming rule:
These changes fix some minor annoyances with the older scheme. Note that the translation from Objective-C to Python is unmodified and is entirely consistent with the modified rules for translating from Python to Objective-C.
Fix for a memory leak in __pyobjc_object__ handling.
Added wrappers for embedded DiscRecording frameworks ([ 1224188 ] Fix for DiscRecording framework)
Probably working Xcode 2.1 support (for converted Xcode 2.0 projects)
Hide List, Object, and Protocol classes from objc.loadBundle to prevent confusion with Python code. They can still be looked up with objc.lookUpClass.
Fixed a regression where type signatures for pointers weren’t normalized (fixes uses of NSModalSession, etc.)
Fixed a bug with -[NSObject hash] to __hash__, there was a mismatch between integer types.
Removed traces of the old Project Builder and Xcode templates in the examples and Foundation initialization code (PYOBJCFRAMEWORKS).
Fixed a problem with reference counting in initializers.
New TinyURLService example in AppKit that demonstrates how to write a service that transforms URLs into their tinyurl.com equivalents.
Ported to Mac OS X on Intel. This is an initial, experimental port. The Intel ABI has not been finalised yet. It is also possible to build fat binaries, that option should not be used in production builds.
Support a number of new frameworks:
SenTestingKit
TODO: this framework uses lots of macros (such as STAssertEquals), these have not yet been wrapped/converted.
SecurityFoundation
Importing objc now ensures that Foundation is multi-threaded, previously it only ensured that Python was.
New objc.RegisterCFSignature used to register CFTypeRef-like signatures with the runtime.
PyObjCTools.Conversion functions now support all property list types with the following conversions:
New toPythonDecimal, fromPythonDecimal functions which convert between NSDecimalNumber and decimal.Decimal using an intermediate string.
New serializePropertyList and deserializePropertyList functions which serialize (Objective-C) property lists to and from NSData.
OC_PythonObject, the proxy for Python objects that do not have an Objective-C superclass and are not otherwise special-cased, now act slightly more like typical Objective-C objects (supporting -isEqual:, -hash, and -compare:). This allows them to work with Key-Value Coding if they are contained by an Objective-C object, among other things.
New objc.signature decorator that allows easier specification of objc.selector wrappers for functions when using Python 2.4:
@objc.signature('i@:if')
def methodWithX_andY_(self, x, y):
return 0
PyObjCTools.KeyValueCoding.getKeyPath now supports all of the Array Operators supported by Mac OS X 10.4.
Key-Value Coding of Python objects (whether or not using an Objective-C base class) should act like Objective-C now. In previous versions there were inconsistencies with the use of capitalization, the underscore postfix in setters, and Key-Value Observing.
The formal protocol list is now complete. A new internal function, objc.protocolsForProcess() enumerates over all mach headers and returns all of the protocols defined in the expected place. This fixes the scenario where an application uses a protocol but does not define any classes that conform to that protocol (i.e. to check plugin conformity). Previously it was not possible to reach these protocols simply by walking over all of the classes.
A special value, objc.NULL, may now be passed in the place of ‘in’ and ‘inout’ arguments. This tells the bridge to pass a NULL pointer to the Objective-C method, instead of a pointer to the value. The return value will still be a tuple of the expected size.
Some of the new Tiger frameworks now have wrappers:
Documentation and tests not yet written.
New OutlineEditor example in Examples/CoreData, it is a Python version of the identically named Apple example.
The last argument of selectors that end with ‘:error:’ is now assumed to be ‘out’ if its type is an object pointer.
More conveniences for list-like and dict-like objects: __reversed__, reverse, pop, remove, fromkeys.
OC_PythonDictionary and OC_PythonArray now return NSNull to Objective-C callers as appropriate.
New WebKitInterpreter example in Examples/Plugins. Uses the new WebKit Cocoa plugin API available in Safari 1.3 and later to embed a PyInterpreter in the browser.
Fixed a CFBundleRef reference counting bug in Foundation._Foundation. The symptom of this is usually a crashing application after having loaded a PyObjC-based plugin into an otherwise Objective-C app.
New PyObjCTools.AppHelper functions: callAfter and callLater, conveniences for calling Python functions on the main thread as soon as possible, or after a delay.
Twisted examples changed to use threadedselectreactor instead of cfreactor. cfreactor is deprecated. Needs Twisted newer than 2.0 (svn r13575 or later).
objc.inject now injects on main thread by default, and takes an optional third useMainThread argument to change this behavior. This is a complete rewrite which should be correct, stable, Tiger compatible, and synchronized with mach_* 1.1.
Removed an NSAutoreleasePool category hack that has been deprecated for quite some time.
New objc.removeAutoreleasePool function that will remove PyObjC’s global NSAutoreleasePool, which may be useful for plugins.
Fixed bug in the NSBundle hack that caused a NULL pointer dereference if looking up a non-existent class using NSBundle API.
Added OC_PythonUnicode and OC_PythonString classes that preserve the identity of str and unicode objects across the bridge. The 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.
New Xcode project template “PyObjC Mixed Application” that is a py2app based Python application that loads an Objective-C plug-in built as a separate target.
New py2app based Xcode templates “PyObjC Application” and “PyObjC Document-based Application”, these replace the older “Cocoa-Python Application” and “Cocoa-Python Document-based Application” respectively.
New InjectBrowser example in Examples/Inject that demonstrates injection of the ClassBrowser example into another application using objc.inject.
NSData and NSMutableData instances now support the Python buffer protocol.
NSData instances now support a convenience API that allow them to act like a buffer instance for str() and slicing.
Objects that support the Python buffer protocol, such as buffer and array.array (but not str or unicode) are now bridged as NSData subclasses.
New objc.pyobjc_id function that returns a the id of the underlying NSObject as an integer. (Python wrapper objects are often made on the fly, meaning id(obj) is not constant during the lifetime of the object.)
The bridge now maintains object identity across the bridge in both directions. Previous versions of the bridge only did this when bridging from Objective-C to Python.
Exceptions: NSString and NSNumber do not have unique proxies. These types are converted to subclasses of Python types as appropriate, so they can not have unique proxies. The identity of the original Objective-C object is maintained by these subclasses, but there may be many Python “value proxies” for a single Objective-C object.
Any Python object that is proxied using the __pyobjc_object__ interface will only get a unique proxy if the __pyobjc_object__ method implements that feature.
New objc.protocolsForClass function that returns a list of protocols that the class directly claims to conform to.
PyObjC classes can now declare that they implement formal protocols, for example:
class MyLockingClass(NSObject, objc.protocolNamed('NSLocking')):
# implementation
pass
It is also possible to define new protocols:
MyProtocol = objc.formal_protocol("MyProtocol", None, [
selector(None, selector='mymethod', signature='v@:'),
])
All formal protocols are instances of objc.formal_protocol.
PyObjCTools.KeyValueCoding has a new kvc class that allows Pythonic Key-Value Coding.
The kvc class uses __pyobjc_object__, so it may cross the bridge as the wrapped object.
NSNumber instances are bridged to a float, long, or int subclass that uses __pyobjc_object__. NSDecimal is converted to NSDecimalNumber when used as an object, NSDecimalNumber is not bridged to NSDecimal because the latter is a mutable type.
The Python to Objective-C bridge now looks for a __pyobjc_object__ attribute to get a PyObjC object from a Python object.
New IDNSnitch example in Inject that demonstrates how to write an monitor for the launch of another application, use objc.inject to load code into a target process, and override the implementation of an existing method but still call back into the original implementation (method swizzling).
objc.IMP should do the right thing now. This type is returned by +[NSObject methodForSelector:] and +[NSObject instanceMethodForSelector:]
New ToDos example in CocoaBindings that demonstrates how to use two array controllers for the same data, and how to use value transformers to alter the color of text. Originally from “Cocoa Bindings Examples and Hints”, converted to PyObjC by u.fiedler.
New Bookmarks example in CocoaBindings that demonstrates how to subclass NSArrayController to implement the NSTableView delegate drag and drop protocol, including copying of objects between documents and accepting URL drops from other applications. Also demonstrates re-ordering of the content array. Originally from “Cocoa Bindings Examples and Hints”, converted to PyObjC by u.fiedler.
New FilteringController example in CocoaBindings that demonstrates how to subclass NSArrayController to implement filtering of a NSTableView. Also demonstrates the use of indexed accessors. Originally from “Cocoa Bindings Examples and Hints”, converted to PyObjC by u.fiedler.
New ControlledPreferences example in CocoaBindings that demonstrates how to use Cocoa Bindings to simplify storing and retrieving user preferences. Originally from “Cocoa Bindings Examples and Hints”, converted to PyObjC by u.fiedler.
New TemperatureTransformer example in CocoaBindings that demonstrates how to use NSValueTransfomers with PyObjC. Based on Apple’s “Cocoa: Value Transformers” documentation, converted to PyObjC by u.fiedler.
New CurrencyConvBindings example in CocoaBindings that demonstrates a Cocoa Bindings enabled version of the CurrencyConverter example. Converted to PyObjC by u.fiedler from the example in Apple’s “Introduction to Developing Cocoa Applications Using Bindings”.
New ManualBindings example in CocoaBindings that demonstrates how to develop programmatic bindings from a PyObjC application. Converted to PyObjC by u.fiedler from the “Cocoa Bindings and Hints” example of the same name.
New HotKeyPython example in AppKit that demonstrates how to use Carbon global hot keys from a PyObjC application. Also demonstrates how to use a NSApplication subclass.
Key-Value Observing support is now automatic in Python classes that descend from NSObject, unless they implement a custom willChangeValueForKey:, didChangeValueForKey:, or __useKVO__ is not True. This allows self.foo = 1 to automatically trigger notifications. This works in all cases, whether foo is a property, ivar, or just in the __dict__.
New Inject folder in Examples, with an InjectInterpreter example that will inject a GUI Python interpreter into any process.
New objc.inject() function for Mac OS X 10.3 and later, allows an arbitrary bundle to be loaded into another process using mach_inject.
objc.classAddMethods now recognizes and supports classmethods.
GC is now correctly implemented for struct wrappers.
The NSNumber bridge has been removed, now you will get NSNumber instances across the bridge instead of a Python representation.
PyObjCTools.AppHelper.runEventLoop() will now bring your application to the front at startup when using pdb mode for convenience.
objc.loadBundle() no longer filters the class list. This solves a few potential issues and shaves off about 1/3rd of the overhead of python -c "import AppKit".
PyObjCTools.AppHelper.runEventLoop() no longer breaks on pure Objective-C exceptions. Most exceptions of this variety are more like warnings, and there is nothing that can be done them anyway.
PyObjCTools.AppHelper.runEventLoop() now installs the interrupt handler and verbose exception logging when using pdb, either explicitly or by the USE_PDB environment variable.
There is now a fast path for the NSString/unicode bridge when Py_UNICODE_SIZE is 2. This is the default setting for Python.
The default selector signature will have a void return value unless a “return” statement with an argument is used in the bytecode. In that case, it will default to an object return value.
__bundle_hack__ is no longer necessary, py2app now sets a different environment variable to the current plugin during execution, and a hack is installed to NSBundle so that classes may respond to requests for their bundle with the +bundleForClass method. The class builder adds a default implementation of this to Python classes if this environment variable is set.
Added objc.currentBundle(), which is equivalent to NSBundle.mainBundle() except after loading a plug-in. Makes it easier to load nib files.
PyObjCTools.NibClassBuilder.extractClasses() now uses objc.currentBundle() instead of NSBundle.mainBundle(). This makes plugins less of a hassle to develop and allows identical code to be used for application or plugin development.
objc.registerPlugin() and objc.pluginBundle() are now deprecated as they are no longer useful.
It is now possible to subclass a class that implements copyWithZone: without setting __slots__ to ().
It is now possible to override dealloc. It is still possible to define __del__.
As an experimental feature it is also possible to override retain and release. Note it almost never a good idea to do this (even when you’re programming in Objective-C and much more so in Python).
poseAsClass: can be used, although it is not very useful in python, use categories instead.
A major issue with poseAsClass: is that existing references to the old version of the class won’t be changed to point to the new class.
It is now possible to access all instance variables of a class using the functions objc.listInstanceVariables(aClassOrInstance), objc.getInstanceVariable(obj, name) and objc.setInstanceVariable(obj, name, value [, updateRefCount]).
The last argument of setInstanceVariable is required when the instance variable is an object. If it is true the bridge will update reference counts, otherwise it won’t.
All wrappers for opaque pointers (such as NSZone*) now have the same interface and share a single implementation. This decreases code-size and makes it easier to add new wrappers. A new feature is a __typestr__ attribute on the type object, this contains the encoded Objective-C type of the pointer.
A function for creating new wrappers is exposed to python, as objc.createOpaquePointerType(name, typestr, doc). The same function is also exposed in the C-API.
Wrappers for C-structs how have a __typestr__ attribute on their type. This attribute contains the encoded Objective-C type of the struct.
The default __init__ for struct-wrappers now initializes fields with an appropriate default value, instead of None.
New wrappers can now be created from Python using the function objc.createStructType(name, typestr, fieldnames, doc). The same function is also exposed in the C API (and has been for a while).
PyObjCTools.AppHelper.stopEventLoop will attempt to stop the current NSRunLoop (if started by runConsoleEventLoop) or terminate the current NSApplication (which may or may not have been started by runEventLoop).
This version no longer support Python 2.2. Python 2.3 or later is required.
It is now possible to use reload on modules containing Objective-C classes.
objc.loadBundle now returns bundle we just loaded.
Added objc.loadBundleVariables and objc.loadBundleFunctions, two functions for reading global variables and functions from a bundle.
objc.runtime will now raise AttributeError instead of objc.nosuchclass_error when a class is not found.
objc.Category can be used to define categories on existing classes:
class NSObject (objc.Category(NSObject)):
def myMethod(self):
pass
This adds method myMethod to class NSObject.
py2app is now used for all Example scripts and is the recommended method for creating PyObjC applications.
Proxies of dict, list, and tuple now respect the invariant that you should get an identical instance if you ask for the same thing twice and the collection has not been mutated. This fixes some problems with binary plist serialization, and potentially some edge cases elsewhere.
There is now a __bundle_hack__ class attribute that will cause the PyObjC class builder to use a statically allocated class wrapper if one is available via certain environment variables. This functionality is used to enable +[NSBundle bundleForClass:] to work for exactly one class from a py2app-created plugin bundle.
We now have a working Interface Builder palette example due to __bundle__hack__.
bool(NSNull.null()) is now false.
setup.py supports several new commands:
build_libffi:
builds libffi (used by build_ext)
- build_html:
builds html documentation from ReST source
- bdist_dmg:
creates a disk image with the binary installer
- bdist_mpkg:
creates a binary installer
- test:
runs unit test suite (replaces Scripts/runPyObjCTests and Scripts/runalltests)
PyObjCStrBridgeWarning can now be generated when Python str objects cross the bridge by calling objc.setStrBridgeEnabled(False). It is HIGHLY recommended that your application never send str objects over the bridge, as it is likely to cause problems due to the required coercion to unicode.
The coercion bridge from Python to Objective-C instances can now be augmented from Python as it is exposed by OC_PythonObject. See objc._bridges. This is how the str -> unicode -> NSString bridge with optional warnings is implemented.
The coercion bridge between Python objects and Objective-C structures can now be augmented from Python as it is exposed by OC_PythonObject. See objc._bridges. This is how the Carbon.File.FSRef <-> '{FSRef=[80c]}' structure bridge is implemented.
Extension modules such as _objc, _AppKit, etc. are now inside packages as objc._objc, AppKit._AppKit, etc. They should never be used directly, so this should not break user code.
More fine-grained multi-threading support
Xcode templates use a smarter embedded main program
Add support for WebObjects 4.5 (a one-line patch!)
Add a PackageManager clone to the Examples directory
Add better support for NSProxy
This makes it possible to use at Distributed Objects, although this feature has not received much testing
Function ‘objc.protocolNamed’ is the Python equivalent of the @protocol expression in Objective-C.
Add several new examples
Fixes some regressions in 1.1 w.r.t. 1.0
Add Xcode templates for python files
You can now select a new python file in the ‘add file...’ dialog in Xcode
Fix installer for Panther: the 1.1a0 version didn’t behave correctly
There is now an easier way to define methods that conform to the expectations of Cocoa bindings:
class MyClass (NSObject):
@objc.accessor
def setSomething_(self, value):
pass
@objc.accessor
def something(self):
return "something!"
It is not necessary to use objc.accessor when overriding an existing accessor method.
Objective-C structs can now be wrapped using struct-like types. This has been used to implement wrapper types for NSPoint, NSSize, NSRange and NSRect in Foundation and NSAffineTransformStruct in AppKit.
This means you can now access the x-coordinate of a point as aPoint.x, accessing aPoint[0] is still supported for compatibility with older versions of PyObjC.
It is still allowed to use tuples, or other sequences, to represent Objective-C structs.
NOTE: This has two side-effects that may require changes in your programs: the values of the types mentioned above are no longer immutable and cannot be used as keys in dicts or elements in sets. Another side-effect is that a pickle containing these values created using this version of PyObjC cannot be unpickled on older versions of PyObjC.
This version adds support for NSDecimal. This is a fixed-point type defined in Cocoa.
NSDecimalNumbers are no longer converted to floats, that would loose information.
If an Objective-C method name is a Python keyword you can now access it by appending two underscores to its name, e.g. someObject.class__().
The same is true for defining methods, if you define a method raise__ in a subclass of NSObject it will registered with the runtime as raise.
NOTE: Currently only class and raise are treated like this, because those are the only Python keywords that are actually used as Objective-C method names.
Experimental support for instanceMethodForSelector: and methodForSelector:. This support is not 100% stable, and might change in the future.
Backward incompatible change: class methods are no longer callable through the instances.
Integrates full support for MacOS X 10.3 (aka Panther)
Adds a convenience/wrapper module for SecurityInterface
It is now safe to call from Objective-C to Python in arbitrary threads, but only when using Python 2.3 or later.
Fixes some issues with passing structs between Python and Objective-C.
Uses the Panther version of NSKeyValueCoding, the Jaguar version is still supported.
method updateNSString of objc.pyobjc_unicode is deprecated, use create a new unicode object using unicode(mutableStringInstance) instead.
NSAppleEventDescriptor bridged to Carbon.AE
LibFFI is used more aggressivly, this should have no user-visible effects other than fixing a bug related to key-value observing.
Adds a number of new Examples:
OpenGLDemo
Shows how to use OpenGL with PyObjC
SillyBallsSaver
Shows how to write a screensaver in Python. Requires a framework install of Python (that is, MacOS X 10.3 or MacPython 2.3 on MacOS X 10.2).
Twisted/WebServicesTool
Shows how to integrate Twisted (1.1 or later) with Cocoa, it is a refactor of the WebServicesTool example that is made much simpler by using Twisted.
Twisted/WebServicesTool-ControllerLayer
Shows how to integrate Twisted (1.1 or later) with Cocoa, it is a refactor of the WebServicesTool example that is made much simpler by using Twisted as it does not need threads. This one also uses NSController and therefore requires MacOS X 10.3.
Better support for the NSKeyValueCoding protocol. The module PyObjCTools.KeyValueCoding provides a python interface that makes it possible to use key-value coding with python objects as well as Objective-C objects. Key-Value Coding also works as one would expect with Python objects when accessing them from Objective-C (both for plain Python objects and Python/Objective-C hybrid objects).
objc.pyobjc_unicode objects are now pickled as unicode objects, previously the couldn’t be pickled or were pickled as incomplete objects (protocol version 2).
Pickling of ObjC objects never worked, we now explicitly throw an exception if you try to pickle one: pickle protocol version 2 silently wrote the incomplete state of objects to the pickle.
The default repr() of ObjC objects is now the result of a call to the description method. This method is not called for unitialized objects, because that might crash the interpreter; we use a default implementation in that case.
A minor change to the conversion rule for methods with output arguments (pointers to values in ObjC, where the method will write through the pointer). If the method has ‘void’ as its return type, we used to return a tuple where the first value is always None. This first element is no longer included, furthermore if the method has only 1 output argument we no longer return a tuple but return the output value directly (again only if the method has ‘void’ as its return type).
This is a backward incompatible change, but there are not many of such methods.
Another backward incompatible change is a minor cleanup of the names in the objc module. The most significant of these is the change from recycle_autorelease_pool to recycleAutoreleasePool. The other changed names are internal to the bridge and should not be used in other code.
The interface of Foundation.NSFillRects changed, it now has an interface that is consistent with the rest of the bridge.
More tutorials
Two new tutorials were added: ‘Adding Python code to an existing ObjC application’ and ‘Understanding existing PyObjC examples’. The former explains how you can use Python to add new functionality to an already existing Objective-C application, the latter explains how to understand PyObjC programs written by other people.
More examples
Three examples were added: DotView, ClassBrowser and PythonBrowser, respectively showing the use of a custom NSView, NSBrowser and NSOutlineView. PythonBrowser is reusable, making it trivial to add an object browser to your application.
Support for MacOS X 10.1
It is now possible to build PyObjC on MacOS X 10.1, with full access to the Cocoa API’s on that platform.
Note: The port to MacOS X 10.1 is not as well supported as the 10.2 port. The developers do not have full-time access to a MacOS X 10.1 system.
Support for the WebKit framework, included with Safari 1.0.
If you build PyObjC from source you will have to build on a system that has the WebKit SDK installed to make use of this. Note that the additional functionality will only be usuable on systems that have Safari 1.0 installed, however as long as you don’t use the additional functionality it is safe to run a ‘WebKit-enabled’ PyObjC on systems without Safari 1.0.
It is no longer necessary to specify which protocols are implemented by
a class, this information is automaticly deduced from the list of implemented methods. You’ll still a runtime error if you implement some methods of a protocol and one of the unimplemented methods is required.
Support for “toll-free bridging” of Carbon.CF types to Objective-C objects.
It is now possible to use instances of Carbon.CF types in places where Objective-C objects are expected. And to explicitly convert between the two.
Note: this requires Python 2.3.
Better integration with MacPython 2.3:
It is now possible to write plugin bundles, such as preference panes for use in System Preferences, in Python. See Examples/PrefPanes for an example of this feature.
The methods pyobjcPopPool and pyobjcPushPool of NSAutoreleasePool are deprecated. These were introduced when PyObjC did not yet support the usual method for creating autorelease pools and are no longer necessary.
Improved unittests, greatly increasing the confidence in the correctness of the bridge.
All suppport for non-FFI builds has been removed.
Object state is completely stored in the Objective-C object. This has no user-visible effects, but makes the implementation a lot easier to comprehend and maintain.
As part of the previous item we also fixed a bug that allowed addition of attributes to Objective-C objects. This was never the intention and had very odd semantics. Pure Objective-C objects not longer have a __dict__.
Weakrefs are no longer used in the implementation of the bridge. Because the weakrefs to proxy objects isn’t very useful the entire feature has been removed: It is no longer possible to create weakrefs to Objective-C objects.
NOTE: You could create weakrefs in previous versions, but those would expire as soon as the last reference from Python died, not when the Objective-C object died, therefore code that uses weakrefs to Objective-C objects is almost certainly incorrect.
Added support for custom conversion for pointer types. The end result is that we support more Cocoa APIs without special mappings.
The generator scripts are automaticly called when building PyObjC. This should make it easier to support multiple versions of MacOS X.
This version includes numerous bugfixes and improvements.
The module AppKit.NibClassBuilder has been moved to the package PyObjCTools.
Usage of libFFI (http://sourceware.org/libffi/) is now mandatory. The setup.py gives the impression that it isn’t, but we do not support non-FFI builds.
We actually have some documentation, more will be added in future releases.
There are more Project Builder templates (see ‘Project Templates’).
The InterfaceBuilder, PreferencePanes and ScreenSaver frameworks have been wrapped.
Management of reference counts is now completely automatic, it is no longer necessary to manually compensate for the higher reference count of objects returned by the alloc, copy and copyWithZone: class methods.
Various function and keyword arguments have been renamed for a better integration with Cocoa. A partial list is of the changed names is:
objc.lookup_class -> objc.lookUpClass
objc.selector arguments/attributes:
is_initializer -> isInitializer
is_allocator -> isAlloc
donates_ref -> doesDonateReference
is_required -> isRequired
class_method -> isClassMethod
defining_class -> definingClass
returns_self -> returnsSelf
argument_types -> argumentTypes
return_type -> returnType
objc.get_class_list -> objc.getClassList
On Python 2.2, objc.YES and objc.NO are instances of a private boolean type, on Python 2.3 these are instances of the builtin type bool.
Because we now use libFFI a large amount of code could be disabled. The binaries are therefore much smaller, while we can now forward messages with arbitrary signatures (not limited to those we thought of while generating the static proxies that were used in 0.8)
Better support for APIs that use byte arrays are arguments or return values. Specifically, the developer can now manipulate bitmaps directly via the NSBitmapImageRep class, work with binary data through the NSData class, and very quickly draw points and rects via NSRectFillList()
We added a subclass of unicode that is used to proxy NSString values. This makes it easily possible to use NSString values with Python APIs, while at the same time allowing access to the full power of NSString.
Here again, supporting GNU_RUNTIME and GNUstep Base! On my new Linux box I can finally test the module against them: I installed the latest snapshot of gstep-core, that contains the base library too. Given a sane GNUstep env (GNUSTEP_XXX env vars), you should be able to build a static ObjC-ized interpreter by:
o Adjusting Setup, commenting out NeXT definition and enabling GNU
ones;
o make -f Makefile.pre.in boot
o make static
Accepts a struct.pack() string for pointer arguments, but...
... New methods on ObjCMethod: .pack_argument and .unpack_argument: these should be used whenever an ObjC method expects a passed-by-reference argument; for example, on NeXTSTEP [View getFrame:] expects a pointer to an NXRect structure, that it will fill with the current frame of the view: in this case you should use something similar to:
framep = aView.getFrame__.pack_argument (0)
aView.getFrame__ (framep)
frame = aView.getFrame__.unpack_argument (0, framep)
Correctly handle pointer arguments.
New syntax to get a class: ObjC.runtime.NameOfClass
New syntax aliasing .new(): SomeClass()
New Demo: LittleButtonedWindow, that tests points above.
What follow is the recipe to get PyObjC dynamically loadable on NeXTSTEP:
apply the patch in Misc/INSTALL.PyObjC to Python/importdl.c
modify Python/Makefile adding the switch -ObjC to the importdl.o build rule:
importdl.o: importdl.c
$(CC) -ObjC -c $(CFLAGS) -I$(DLINCLDIR) $(srcdir)/importdl.c
modify Modules/Setup moving the PyObjC entry suggested above AFTER *shared*, and remove -u libNeXT_s -lNeXT_s from it.
run make: this will update various files, in particular Modules/Makefile.
modify Modules/Makefile adding -u libNeXT_s -lNeXT_s to SYSLIBS:
SYSLIBS= $(LIBM) $(LIBC) -u libNeXT_s -lNeXT_s
run make again