Backward incompatible changes
* In PyObjC 7 and earlier it was possible to leave out "output" arguments when
calling a method with a Python implementation:
.. sourcecode:: python
class MyClass(NSObject):
objc.typedSelector(b":o^")
def methodWithOutput_(self, a):
return 1, 2
o = MyClass.alloc().init()
print(o.methodWithOutput_())
This no longer works, it is always necessary to pass in all arguments, which
was already true for methods implemented in Objective-C. That is:
.. sourcecode:: python
print(o.methodWithOutput_(None))
This change both simplifies the PyObjC code base and was required to cleanly
implement vectorcall support (see the section on performance below).
* Removed bindings for ``InterfaceBuilderKit``. This was a way to integrate
with InterfaceBuilder in old versions of Xcode, but support for that was
dropped before the release of Mac OS X 10.8.
* Bindings for the Objective-C runtime API related to "associated objects" is
now enabled unconditionally. This will cause problems when running or building
on macOS 10.6 or earlier.
* It is no longer possible to deploy to macOS 10.7 or earlier when you attempt to
create a formal protocol. Protocol creation already failed on those platform
due to lack of the required runtime API, and that will now result in a crash
because PyObjC no longer checks for availability of that runtime API.
* 371: Remove manual bindings for a number of old CoreGraphics APIs
The following functions are no longer available:
* ``CGDataProviderCreate``
* ``CGDataProviderCreateDirectAccess``
These functions were removed as a public API in macOS 10.8, but were still
available through PyObjC through old backward compatibility code. That code has
now been removed.
* For compatibility with Python's socket APIs functions that return a
"struct sockaddr" (either by reference or as a function result) will now
encode the IP address as a string and not a bytes object.
* The (undocumented) API in pyobjc-api.h (used in some framework bindings to
integratie with pyobjc-core) has changed in an incompatible way, in particular
the API for "caller" functions now mostly mirrors the vectorcall convention.
* Adding a method with a double underscore name will now raise an exception at
class definition time instead of silently not creating the Objective-C method.
.. sourcecode::
class AClass (NSObject):
...
def __foo_bar__(self, a, b, c):
pass
MethodNamesClass.__foo_bar__ = __foo_bar__
Before PyObjC 8 this would add a ``__foo_bar__`` selector to the Python
representation of the class without adding a selector to the Objective-C class.
Use :func:`objc.python_method` to mark this as a python-only function.
Upcoming incompatible changes
* The module :mod:`PyObjCTools.Signals` is deprecated and will be removed
in PyObjC 9.
* :func:`objc.initFrameworkWrapper` and :func:`objc.parseBridgeSupport`
are deprecated and will be removed in PyObjC 9.
These functions implement support for ".bridgesupport" XML files,
something that PyObjC hasn't used itself in a number of releases (in
part because system versions of those files are at best incomplete).
Performance
Most performance changes use features introduced in Python 3.9, performance
in older Python versions is unchanged except for the effects of general cleanup.
* Implement the "vectorcall" protocol for :class:`objc.function`, :class:`objc.WeakRef`,
:class:`objc.selector`, :class:`objc.IMP`, :class:`objc.python_method`.
This reduces the interpreter overhead for calling instances of these objects.
* Implement Py_TPFLAGS_METHOD_DESCRIPTOR for :class:`objc.selector`,
:class:`objc.python_method`.
* Use vectorcall in the method stub that forwards Objective-C calls to Python.
* Convert internal calls into Python to the vectorcall protocol (pyobjc-core)
* Add more optimized vectorcall implementation to :class:`objc.function`,
:class:`objc.IMP` and :class:`objc.selector` for simpler callables.
In the current version "simpole enough" callables have a 8 or fewer
arguments, and none of those arguments are pass by reference. This will
change over time.
Generic Implementation Quality
* 391: Fix some spelling errors found by the
`codespell <https://pypi.org/project/codespell/>`_ tool.
The codespell tool is also run as part of pre-commit hooks.
* 296: use clang-format for Objective-C code
The Objective-C code for the various extensions has been reformatted
using clang-format, and this enforced by a pre-commit hook.
* 374: Use pyupgrade to modernize the code base
This is enforced by a pre-commit hook.
* 388: Added "nullability" attributes to Objectice-C sources for pyobjc-core.
This gives the compiler and clang static analyzer more information
that can be used to pinpoint possible bugs in the implementation. As a
side effect of this a number of internal checks were strengthened, although
most of them were for error conditions that should never happen.
That said, this change also found a number of places where Python reference
counts weren't updated properly, which may have led to refcount overflows
in long running programs.
* Add more error checking to pyobjc-core to catch (very) unlikely error conditions.
This is a side effect of the previous item.
New features
* Updated framework bindings for macOS 12
* New framework bindings for the following frameworks:
- AudioVideoBridging (introduced in macOS 10.8)
- DataDetection (introduced in macOS 12.0)
- IntentsUI (introduced in macOS 12.0)
- LocalAuthenticationEmbeddedUI (introduced in macOS 12.0)
- MailKit (introduced in macOS 12.0)
- MetricKit (introduced in macOS 12.0)
- ShazamKit (introduced in macOS 12.0)
* 318: Implement support for ``__class_getitem__`` for Objective-C classes
The result of this is that effectively all Objective-C classes can be used
as generic classes, without runtime type checking. This is meant to be used
with optional type checking (for example MyPy)
Usage:
.. sourcecode:: python
def create_integers(count: int) -> NSArray[int]:
return NSArray[int].arrayWithArray_([i for i in range(count)])
.. note::
This requires typing stubs for framework bindings to be really useful,
and those do not yet exist.
* 354: Add an option to install all framework bindings, including those not
relevant for the current platform. To use this:
.. sourcecode:: sh
$ pip install 'pyobjc[allbindings]'
Other changes and bugfixes
* 390: pyobjc-core is no longer linked with the Carbon framework.
Due to implicit dependencies this also required a change to the Metal
bindings: those now import AppKit instead of Foundation.
* PyObjC only ships "Universal 2" wheels for Python 3.8 and later. Those work
with single-architecture builds of Python as well.
* PyObjC 8 only ships with source archives and "univeral2" binary
wheels (Python 3.? and later). There are no longer "x86_64" binary wheels.
* The *AVFoundation* bindings (in ``pyobjc-framework-AVFoundation``) now have
an install dependency on the *CoreAudio* bindings (``pyobjc-framework-CoreAudio``).
This is needed for a new API introduced in macOS 12.
* 371: Link extensions in the Quartz bindings to the Quartz frameworks
A number of C extensions in the Quartz bindings package were not
linked to a framework. Those now link to the Quartz framework.
* 378: Fix raising ``ImportError`` when doing ``from ApplicationServices import *``
The root cause for this were private classes in system frameworks that contain
a dot in their name (for example ``Swift.DispatchQueueShim``. Those names are
both private and invalid attribute names.
* Creating protocols that contain methods that have a method signature containing
PyObjC custom type encodings now works (those encodings are translated to
the corresponding Objective-C encoding.
* Fix bindings for ``SKIndexCopyDocumentRefsForDocumentIDs``, that binding
didn't work due to a typo in the metadata.
* 365: The ``PyObjCTools`` namespace package no longer has an ``__init__.py``
file in the source tree (that is, the tree switches to implicit namespace
packages instead of the older setuptools style for namespace packages).
This primarily affects testing with recent versions of pip/setuptools (which
seem to no longer install the ``__init__.py`` file for namespace packages).
* ``development-support/run-testsuite`` now uses ``venv`` instead of
``virtualenv``. This removes a development dependency.
* PR 367: Tweak the code that calculates ``PyObjC_BUILD_RELEASE`` in
the various setup.py files to deal with versions with more than two
labels (can happen when building using Xcode 13 beta)
PR by Eric Lin (Tzu Hsiang Lin), github user eric100lin.
* ``PyObjCTest.TestSupport`` now never uses "10.16" as the
OS release but always uses the actual platform version, even
when Python was compiled using an old SDK.
* Adjusted PyObjC testcases to check for 11.0 instead of 10.16
now that testsupport uses the real platform version.
* 385: Fix race condition the lazy importer
When two threads simultaneously try to get an attribute from a framework
binding one of them might fail with an attribute error because information
for resolving the name was removed before actually resolving the name.
* Fix various issues with invalid indices in :class:`objc.varlist`
* Fix support for ``AF_UNIX`` in the support code for ``struct sockaddr``.
* The implementation for opaque pointer types (such as the proxy for
'NSZone*') has switched to :c:func:`PyType_FromSpec`.
* The :meth:`objc.FSRef.from_path` and :meth:`objc.FSRef.as_pathname`,
methods now use the filesystem encoding instead of the default encoding.
C string. This shouldn't affect any code, both encoding default to UTF-8 on macOS.
* Inheriting directly from :class:`objc.objc_object` now raises :class:`TypeError`
instead of :class:`objc.InternalError`. User code should always inherit from
a Cocoa class.