A new macOS release means a new major release of PyObjC. I'm happy to announce 
that PyObjC 8 is available on PyPI with full support for macOS 12, including 
APIs introduced in that release.

I've also been working on performance and code quality of the core bridge. 
There are significant speedups of the core bridge in PyObjC 8.0, and I have 
more ideas to reduce the performance difference between regular Python methods 
and calling Objective-C APIs.

The release is a bit later than I would have liked, in part because I've been 
worrying about the covid-19 situation in Holland. Because of that I've spend 
some more time away from the computer.

A full change log is included below.

Backward incompatible changes
In PyObjC 7 and earlier it was possible to leave out "output" arguments when 
calling a method with a Python implementation:

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:

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.

GH-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.

 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 objc.python_method to mark this as a python-only function.

Upcoming incompatible changes
The module PyObjCTools.Signals is deprecated and will be removed in PyObjC 9.

objc.initFrameworkWrapper and 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 objc.function, objc.WeakRef, 
objc.selector, objc.IMP, objc.python_method.

This reduces the interpreter overhead for calling instances of these objects.

Implement Py_TPFLAGS_METHOD_DESCRIPTOR for objc.selector, 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, objc.IMP 
and objc.selector for simpler callables.

"Simpler" methods are those with a small number of plain arguments, although 
the definition of what's simple will evolve over time.

Generic Implementation Quality
GH-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.

GH-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.

GH-374: Use pyupgrade to modernize the code base

This is enforced by a pre-commit hook.

GH-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)
GH-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:

  def create_integers(count: int) -> NSArray[int]:
        return NSArray[int].arrayWithArray_([i for i in range(count)])
This requires typing stubs for framework bindings to be really useful, and 
those do not yet exist.

Other changes and bugfixes
GH-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.

GH-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.

GH-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.

GH-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.

GH-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 PyType_FromSpec.

The objc.FSRef.from_path and 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 objc.objc_object now raises TypeError instead of 
objc.InternalError. User code should always inherit from a Cocoa class.

GH-354: Add an option to install all framework bindings, including those not 
relevant for the current platform. To use this:

$ pip install 'pyobjc[allbindings]'


Ronald
—

Twitter / micro.blog: @ronaldoussoren
Blog: https://blog.ronaldoussoren.net/

_______________________________________________
Pythonmac-SIG maillist  -  Pythonmac-SIG@python.org
https://mail.python.org/mailman/listinfo/pythonmac-sig
unsubscribe: https://mail.python.org/mailman/options/Pythonmac-SIG

Reply via email to