Create native Python extensions in Swift.
ApplePy lets you build pip install-able Python packages written entirely in Swift — with direct access to Apple frameworks like CoreML, Metal, NaturalLanguage, Security, and more. Powered by Swift macros for zero-boilerplate interop. Think PyO3 for Swift.
pip install applepy-cli # install the build tool
applepy new myproject # scaffold a project
cd myproject && applepy develop # build & installVersion 1.0.0 — BSD-3-Clause
import ApplePy
@PyFunction
func greet(name: String, greeting: String = "Hello") -> String {
"\(greeting), \(name)! 🍎"
}
@PyClass
struct Counter {
@PyProperty var count: Int = 0
@PyMethod
mutating func increment() { count += 1 }
@PyMethod
func value() -> Int { count }
}
@PyEnum
enum Color: Int {
case red = 0
case green = 1
case blue = 2
}
@PyModule("mylib", types: [Counter.self], functions: [greet])
func mylib() {}>>> import mylib
>>> mylib.greet("World")
'Hello, World! 🍎'
>>> mylib.greet("World", "Hi")
'Hi, World! 🍎'
>>> c = mylib.Counter(10)
>>> c.increment()
>>> c.value()
11
>>> mylib.Color.red
<Color.red: 0>| Macro | Purpose |
|---|---|
@PyFunction |
Expose top-level functions (with default argument support) |
@PyClass |
Expose structs/classes as Python types |
@PyMethod |
Mark instance methods for Python |
@PyStaticMethod |
Mark static methods for Python |
@PyProperty |
Expose stored properties with getters/setters |
@PyEnum |
Swift enum → Python IntEnum or class hierarchy (with associated values) |
@PyModule |
Generate PyInit_ module entry point |
| Swift | Python | Direction |
|---|---|---|
Int, Double, Float, Bool |
int, float, bool |
↔ |
String |
str |
↔ |
[T] |
list |
↔ |
[K: V] |
dict |
↔ |
Set<T> |
set |
↔ |
Optional<T> |
None / value |
↔ |
PyTuple2<A,B>, PyTuple3<A,B,C> |
tuple |
↔ |
[UInt8] / Data |
bytes |
→ (copy) |
| Feature | Details |
|---|---|
GILGuard: ~Copyable |
Compile-time GIL scope enforcement — can't escape withGIL |
PythonHandle |
Lightweight GIL token for protocol compatibility |
@PythonActor |
Global actor for Swift concurrency integration |
PyBridged / PyBridge |
ARC ↔ refcount memory bridge with debug assertions |
PythonException |
Captures Python error state as Swift Error |
PyExceptionType |
Create custom Python exception types at runtime |
PyExceptionMapping |
Protocol to route Swift errors to specific Python exceptions |
| Tool | Purpose |
|---|---|
| SPM Build Plugin | Auto-detects Python via pkg-config |
| SPM Bundle Plugin | Renames .dylib to CPython-compatible .so |
applepy-pack.py |
PEP 427 wheel packaging |
applepy-stubs.py |
Type stub (.pyi) generation |
| Dimension | PyO3 (Rust) | ApplePy (Swift) |
|---|---|---|
| Macros | #[pyfunction], #[pyclass], #[pymethods] |
@PyFunction, @PyClass, @PyMethod, @PyEnum |
| Memory safety | 'py lifetimes (compile-time) |
GILGuard: ~Copyable (compile-time) |
| Type conversions | 15+ crate integrations | Primitives, collections, tuples, sets |
| Async | pyo3-async-runtimes |
v1.1 (planned) |
| Build tool | maturin |
SPM plugins + manual scripts |
| Enums | Class-based | IntEnum + class hierarchy |
The fastest way to start a new ApplePy project is with the CLI:
# Install the CLI (pick one)
pip install applepy-cli
uv pip install applepy-cliThen create your project:
applepy new myproject
cd myproject
applepy develop
python myproject/examples/demo.py
# → Hello, World! 🍎The CLI handles everything: project scaffolding, Swift compilation, and packaging. See applepy-cli on PyPI for all options.
If you prefer to set things up manually, add ApplePy as a Swift package dependency:
dependencies: [
.package(url: "https://github.com/jagtesh/ApplePy.git", from: "1.0.0"),
]| Doc | Description |
|---|---|
| Getting Started | 5-minute quickstart |
| Macros Reference | @PyFunction, @PyClass, @PyMethod, @PyModule |
| Type Conversion | Swift ↔ Python type mapping |
| Memory Management | ARC ↔ refcount bridge |
| Building & Packaging | SPM, plugins, wheels |
| Feature | Target |
|---|---|
| Async/Await ↔ Asyncio bridge | v1.1 |
| Exception chaining / traceback | v1.1 |
| Free-threaded Python 3.14t | v1.2 |
| Ecosystem type bridges (Foundation.Date, Codable) | Future |
Taking inspiration from PyO3, ApplePy's macro system has been adapted to Swift 6.0 — including the @PyModule peer-macro pattern, compile-time GIL safety via ~Copyable, and the names: prefixed(_applepy_) approach for global-scope macro hygiene.
BSD-3-Clause © Jagtesh Chadha — see LICENSE.