Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

fastcocoa

Cocoa that reads like Swift: properties, kwarg selectors, and value bridging on top of pyobjc

pyobjc has twenty years of irreplaceable metadata (C function signatures, (value, error) out-param tupling, block signatures), but Cocoa code written with it reads as ceremony: f.setDateFormat_('yyyy'), str(e.title()), saveEvent_span_error_. Swift's niceness over the same APIs is a finite list of mechanical transforms, and fastcocoa applies them to pyobjc classes in place, so this:

from fastcocoa.eventkit import EKEvent, EKEventStore
s = EKEventStore()
ev = EKEvent(eventStore=s, title=title, startDate=start)
s.save(ev, span='thisEvent')

is real pyobjc underneath: the same objects, delegates, and framework coverage. Methods answer to their curated Swift names as well as the ObjC spellings, read from Apple's Swift symbol graphs along with the SDK's header docs, so the whole surface is searchable and self-documenting from Python (doc(s.save), sdksearch('remove.*reminder'), full_docs(sdkgroups('EventKit'))). This is the same move fastspec makes for HTTP APIs: take an API's machine-readable spec (there an OpenAPI or Google Discovery document, here Apple's own importer output) and turn it into a runtime surface with the documented names, rather than hand-writing bindings that drift.

Usage is documented in the module docstring: doc(fastcocoa) in a kernel session, or python -c 'import fastcocoa; print(fastcocoa.__doc__)'.

Installation

pip install fastcocoa

Extracting the Swift-name tables needs the Xcode Command Line Tools; without a toolchain, the ObjC spellings still work.

Where it fits

fastcocoa builds on two projects. pyobjc is the foundation: the features beyond attribute access (auto-raised error: out-params, block callbacks, framework constants) work because pyobjc ships twenty years of curated metadata that no runtime query can reconstruct. rubicon-objc is the inspiration. BeeWare's pure-ctypes bridge showed how pleasant ObjC from Python can feel, with properties as attributes and keyword arguments as selector parts, but it has none of pyobjc's metadata, so NSError** handling is manual and the C-level APIs are out of reach.

Reach for it when you write macOS application or automation code in Python: scripts, agents, and tools that read and write Cocoa objects all day. Over hundreds of such lines, ev.title = t reads better than ev.setTitle_(t), and converted values save a str(...) wrapper at every read.

Skip it when:

  • You make a handful of Cocoa calls in an otherwise ordinary program. Raw pyobjc is fine at that scale, and its full ObjC selector names grep directly against the runtime and headers, where fastcocoa's spellings resolve at call time (though the Swift names are exactly what Apple's current documentation shows).
  • Your code is a library loaded into someone else's process. pythonify patches classes in place, process-wide, and swept classes convert values on every property read. An application can own that decision. A guest library should not make it for its host, whose other pyobjc code would see the changed classes too.
  • You need the Cocoa objects themselves rather than converted values, for identity-sensitive APIs or to avoid conversion cost in a hot loop. The escape hatch is pyobjc's own o.pyobjc_instanceMethods.title(), which bypasses every fastcocoa descriptor.
  • You are not on macOS with a compiled pyobjc available. rubicon-objc is pure Python and also runs on iOS.

Development

pip install -e .[dev]

About

Cocoa that reads like Swift: properties, kwarg selectors, and value bridging on top of pyobjc

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages