----------------------------
- 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:
1. Don't rescan the list of classes unless the framework actually defines
new classes.
2. The metadata loader now implemented in C.
3. CF wrapper types (e.g. CGContextRef) no longer have methods
corresponding to global functions, the speed-hit for calculating
these is too large.
- It is now conveniently possible to create instance variables with
a specific type (e.g. without manually making up a encoded type
string):
.. sourcecode:: python
:linenos:
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):
.. sourcecode:: python
:linenos:
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:
1) 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.
2) 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``.
3) Due to a limitation in the implementation of python's ``super`` class [f1]_
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.
.. [f1] 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:
.. sourcecode:: python
:linenos:
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:
.. sourcecode:: sh
$ 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:
.. sourcecode:: python
:linenos:
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 separate 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:
.. sourcecode:: python
:linenos:
o = <Some Objective-C Object>
print o._.myKey
o._.myKey = 44
is equivalent to:
.. sourcecode:: python
:linenos:
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:
.. sourcecode:: python
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
mentioned 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:
.. sourcecode:: python
:linenos:
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:
.. sourcecode:: python
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 supply 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:
* ``None``: pass a non-NULL pointer to the objc function/method
* ``objc.NULL``: pass a NULL pointer to the objc method.
The already existing behaviour is the same as passing in ``None`` for all
output arguments.
This is most useful for suppressing 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 length, 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`` adds a list of methods to a class when that
class has the specified selector:
.. sourcecode:: python
addConvenienceForSelector('hash', [
('__hash__', lambda self: self.hash()),
])
* ``addConvenienceForClass`` adds a list of methods to the class with the
specified name:
.. sourcecode:: python
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).