API Reference¶
Quick reference for PyOZ's public API.
Module Definition¶
pyoz.module(config)¶
Define a Python module.
pub const MyModule = pyoz.module(.{
.name = "mymodule", // Required: module name
.doc = "Description", // Optional: docstring
.from = &.{ ... }, // Optional: auto-scan namespaces
.funcs = &.{ ... }, // Optional: functions
.classes = &.{ ... }, // Optional: classes
.enums = &.{ ... }, // Optional: enums
.consts = &.{ ... }, // Optional: constants
.exceptions = &.{ ... }, // Optional: custom exceptions
.error_mappings = &.{ ... }, // Optional: error->exception mappings
});
Auto-Scan (.from)¶
.from Field¶
Auto-scan Zig namespaces to register all Python-compatible public declarations.
const math = @import("math.zig");
pub const MyModule = pyoz.module(.{
.name = "mymodule",
.from = &.{ math },
});
See Auto-Scan Guide for full details.
pyoz.source(namespace, options)¶
Filter which declarations to export from a namespace.
pyoz.source(math, .{ .only = &.{ "add", "PI" } })
pyoz.source(math, .{ .exclude = &.{ "internal_helper" } })
.only and .exclude are mutually exclusive.
pyoz.withSource(namespace, source)¶
Attach source text to a namespace for automatic /// doc comment and parameter name extraction.
Enables: real parameter names in help() / inspect.signature() / .pyi stubs, /// doc comments as Python docstrings, //! module-level doc comments, and /// above structs as class docstrings. Composes with source() and sub(). Source text is NOT embedded in the final binary.
pyoz.sub(name, namespace)¶
Create a submodule from a namespace.
pyoz.sub("strings", string_utils)
pyoz.sub("io", pyoz.source(io_utils, .{ .exclude = &.{ "debug" } }))
pyoz.Exception(base, doc)¶
Marker type for defining exceptions inside .from namespaces.
pyoz.ErrorMap(mappings)¶
Marker type for defining error-to-exception mappings inside .from namespaces.
pub const __errors__ = pyoz.ErrorMap(.{
.{ "InvalidInput", .ValueError },
.{ "TooBig", .ValueError, "Value exceeds limit" },
});
Docstring Convention¶
With withSource, /// doc comments are automatically extracted as docstrings and //! comments become the module docstring. Without withSource, use explicit constants:
pub fn add(a: i64, b: i64) i64 { return a + b; }
pub const add__doc__ = "Add two integers"; // docstring for add
pub const __doc__ = "Module docstring fallback"; // namespace-level docstring
Explicit {name}__doc__ constants take priority over /// comments.
Functions¶
pyoz.func(name, fn, doc)¶
Define a basic function.
pyoz.kwfunc(name, fn, doc)¶
Define a function with named keyword arguments using Args(T).
const GreetArgs = struct {
name: []const u8,
greeting: []const u8 = "Hello",
};
fn greet(args: pyoz.Args(GreetArgs)) []const u8 { ... }
pyoz.kwfunc("greet", greet, "Greet someone")
Classes¶
pyoz.class(name, T)¶
Define a class from a Zig struct.
pyoz.base(Parent)¶
Declare inheritance from another PyOZ class. The child struct must embed the parent as its first field named _parent.
const Animal = struct {
name: []const u8,
age: i64,
pub fn speak(self: *const Animal) []const u8 {
return "...";
}
};
const Dog = struct {
pub const __base__ = pyoz.base(Animal);
_parent: Animal, // Must be first field, must match parent type
breed: []const u8,
pub fn fetch(self: *const Dog) []const u8 {
return "fetching!";
}
};
Python constructor accepts flattened fields (parent fields first, then child fields):
d = Dog("Rex", 3, "Labrador") # name, age from Animal; breed from Dog
d.speak() # inherited method
d.fetch() # own method
isinstance(d, Animal) # True
Rules:
- Parent class must be listed before child in the classes array
- Child's first field must be _parent: ParentType
- Parent methods and properties are inherited via Python's MRO
- isinstance() and type checks work correctly for subtypes
Properties¶
pyoz.property(config)¶
Define a property with custom getter/setter.
pub const celsius = pyoz.property(.{
.get = struct {
fn get(self: *const Self) f64 { return self._celsius; }
}.get,
.set = struct {
fn set(self: *Self, v: f64) void { self._celsius = v; }
}.set,
.doc = "Temperature in Celsius",
});
Enums¶
pyoz.enumDef(name, E)¶
Define an enum (auto-detects IntEnum vs StrEnum).
pyoz.enumDef("Color", Color) // enum(i32) -> IntEnum
pyoz.enumDef("Status", Status) // enum -> StrEnum
Constants¶
pyoz.constant(name, value)¶
Define a module-level constant.
Exceptions¶
pyoz.exception(name, opts)¶
Define a custom exception.
// Full syntax
pyoz.exception("MyError", .{ .doc = "...", .base = .ValueError })
// Shorthand
pyoz.exception("MyError", .ValueError)
Exception Bases¶
.Exception, .ValueError, .TypeError, .RuntimeError, .IndexError, .KeyError, .AttributeError, .StopIteration
Raising Exceptions¶
// One-liner (in functions returning ?T):
if (bad) return pyoz.raiseValueError("message");
// Two-line (discard return, then return null):
_ = pyoz.raiseValueError("message");
return null;
All raise functions: raiseValueError, raiseTypeError, raiseRuntimeError, raiseKeyError, raiseIndexError, raiseAttributeError, raiseMemoryError, raiseOSError, and many more.
pyoz.fmt(comptime format, args)¶
Inline string formatter using Zig's std.fmt syntax. Returns [*:0]const u8.
// Use with raise functions for dynamic error messages:
return pyoz.raiseValueError(pyoz.fmt("value {d} exceeds limit {d}", .{ val, limit }));
// General formatting:
const msg = pyoz.fmt("hello {s}", .{"world"});
Catching Exceptions¶
if (pyoz.catchException()) |*exc| {
defer @constCast(exc).deinit();
if (exc.isValueError()) { ... }
else exc.reraise();
}
Error Mapping¶
pyoz.mapError(name, exc)¶
Map Zig error to Python exception.
pyoz.mapErrorMsg(name, exc, msg)¶
Map with custom message.
Types¶
Input Types¶
| Type | Python |
|---|---|
pyoz.ListView(T) |
list |
pyoz.DictView(K, V) |
dict |
pyoz.SetView(T) |
set |
pyoz.IteratorView(T) |
Any iterable |
pyoz.BufferView(T) |
NumPy array (read) |
pyoz.BufferViewMut(T) |
NumPy array (write) |
Output Types¶
| Type | Python |
|---|---|
pyoz.Dict(K, V) |
dict |
pyoz.Set(T) |
set |
pyoz.FrozenSet(T) |
frozenset |
Special Types¶
| Type | Python |
|---|---|
pyoz.Complex |
complex |
pyoz.Date |
datetime.date |
pyoz.Time |
datetime.time |
pyoz.DateTime |
datetime.datetime |
pyoz.TimeDelta |
datetime.timedelta |
pyoz.Bytes |
bytes |
pyoz.Path |
str or pathlib.Path |
pyoz.Decimal |
decimal.Decimal |
Allocator-Backed Returns¶
pyoz.Owned(T)¶
Wrapper for returning heap-allocated values. PyOZ converts the inner value to a Python object, then frees the backing memory.
fn make_report(count: i64) !pyoz.Owned([]const u8) {
const allocator = std.heap.page_allocator;
const result = try std.fmt.allocPrint(allocator, "Report: {d} items", .{count});
return pyoz.owned(allocator, result);
}
pyoz.owned(allocator, value)¶
Create an Owned wrapper. Auto-coerces []u8 → []const u8.
const data = try allocator.alloc(u8, 1024);
return pyoz.owned(allocator, data); // returns Owned([]const u8)
Supports !Owned(T) (error union) and ?Owned(T) (optional) return types.
Stub Return Type Override¶
pyoz.Signature(T, "stub_string")¶
Override the .pyi stub return type annotation while preserving runtime behavior. T is the actual Zig return type; "stub_string" is written verbatim into the generated stub.
fn validate(n: i64) pyoz.Signature(?i64, "int") {
if (n < 0) return pyoz.raiseValueError("must be non-negative");
return .{ .value = n };
}
At runtime, Signature is a struct with a .value field — PyOZ unwraps it automatically. Works for module-level functions and class methods (instance, static, class).
| Usage | Stub Output |
|---|---|
pyoz.Signature(?i64, "int") |
-> int |
pyoz.Signature(?*PyObject, "list[Node]") |
-> list[Node] |
pyoz.Signature(?Node, "Node") |
-> Node |
Strong References¶
pyoz.Ref(T)¶
Strong reference to a Python-managed object of type T. Prevents use-after-free via automatic refcounting.
| Method | Description |
|---|---|
ref.set(py_obj) |
Store reference (INCREFs new, DECREFs old) |
ref.get(class_infos) |
Get ?*const T to referenced data |
ref.getMut(class_infos) |
Get ?*T to referenced data |
ref.object() |
Get raw ?*PyObject (borrowed) |
ref.clear() |
Release reference (DECREF + set null) |
Ref fields are automatically excluded from Python properties, __init__, and stubs.
Module.selfObject(T, ptr)¶
Recover the wrapping *PyObject from a *const T data pointer. Used to obtain the PyObject needed for Ref(T).set().
fn make_child(owner: *const Owner, tag: i64) Child {
var child = Child{ .tag = tag, ._owner = .{} };
child._owner.set(MyModule.selfObject(Owner, owner));
return child;
}
GIL Control¶
pyoz.releaseGIL()¶
Release the GIL for CPU-intensive work.
pyoz.acquireGIL()¶
Acquire GIL from non-Python thread.
Submodules¶
mod.createSubmodule(name, doc, methods)¶
Create a submodule.
var methods = [_]pyoz.PyMethodDef{
pyoz.methodDef("func", &pyoz.wrapFunc(fn), "doc"),
pyoz.methodDefSentinel(),
};
const mod = pyoz.Module{ .ptr = module };
_ = mod.createSubmodule("sub", "Submodule doc", &methods);
Class Features¶
Magic Methods¶
Arithmetic: __add__, __sub__, __mul__, __truediv__, __floordiv__, __mod__, __pow__, __neg__, __pos__, __abs__
Comparison: __eq__, __ne__, __lt__, __le__, __gt__, __ge__
Bitwise: __and__, __or__, __xor__, __invert__, __lshift__, __rshift__
Sequence: __len__, __getitem__, __setitem__, __delitem__, __contains__
Iterator: __iter__, __next__, __reversed__
Other: __repr__, __str__, __hash__, __bool__, __call__, __enter__, __exit__
Class Options¶
const MyClass = struct {
pub const __doc__: [*:0]const u8 = "Class docstring";
pub const __frozen__: bool = true; // Immutable
pub const __features__ = .{ .dict = true, .weakref = true };
pub const __base__ = pyoz.bases.list; // Inherit from builtin
pub const __base__ = pyoz.base(Parent); // Inherit from PyOZ class
};