PyOZ v0.9.0
What's New in v0.9.0
Added
module-nameconfig option - New[tool.pyoz]field that decouples the native.soname from the pip package name. Setmodule-name = "_mypackage"to produce_mypackage.so, allowing a Python wrapper package with the same base name (e.g.,mypackage/) to coexist. This enables the standard Python pattern used by_sqlite3/sqlite3,_json/json, etc.include-extconfig option - New[tool.pyoz]field to control which file extensions are included frompy-packagesdirectories. Defaults to["py"]for backwards compatibility. Set["*"]to include all files, or list specific extensions like["py", "zig", "json"]. Useful for packaging template files, data files, or other non-Python assets alongside your Python code.Module.toPy()/Module.fromPy()- Module types now expose class-aware converters. UseModule.toPy(MyClass, instance)to convert registered class instances to Python objects when building raw Python containers (lists, dicts) manually. Unlikepyoz.Conversions(which has no class knowledge), the module converter knows about all registered classes and can wrap them into proper Python wrapper objects. Also exposesModule.ClassConverterfor direct access to the full converter type.- Stub
method__returns__convention - Declarepub const children__returns__: []const u8 = "list[Node]"on a class struct to override the return type annotation in generated.pyistubs. Useful for methods returning?*pyoz.PyObjectwhere the concrete Python type is known to the developer. - Stub
method__params__convention - Declarepub const find__params__: []const u8 = "rule_name"on a class struct to override parameter names in generated.pyistubs. Accepts comma-separated names (excludingself). Falls back toarg0, arg1, ...when not declared. Needed because Zig's@typeInfodoes not expose function parameter names.
Fixed
- Stub generator: duplicate class for exception+class - When a type was registered as both a class and an exception (e.g.,
ParseError), the stub generator emitted two separateclassdefinitions. Now they are merged into a singleclass ParseError(Exception):definition with all methods, properties, and the class docstring. - Stub generator: dunder return types were
Any- Magic methods like__iter__,__next__,__getitem__,__call__,__enter__used hardcodedAnyreturn types. Now they introspect the actual Zig function signatures:__iter__returnsIterator[Element],__next__unwraps the optional to the element type,__getitem__shows the actual key and value types,__enter__resolves to the class name when returning*Self, and__call__introspects its full signature. - Stub generator: class
__doc__was placeholder - Class docstrings declared viapub const __doc__were detected but emitted as"""..."""instead of the actual content. Now the full docstring text is propagated to the.pyifile. - Stub generator: method docstrings were ignored - Method docstrings declared via
pub const method__doc__(e.g.,magnitude__doc__) were explicitly skipped during stub generation. Now they are emitted as Python docstrings in the generated.pyifile. get_*property scanner treated non-functions as getters - The computed property system (properties.zig) and stub generator (stubs.zig) scanned forget_*declarations but didn't verify they were functions. Declarations likeget_error__doc__(a[*:0]const u8docstring for aget_errormethod) were misinterpreted as computed property getters, causing "type '[*:0]const u8' not a function" errors. Both scanners now skip non-functionget_*declarations.__repr__/__str__use-after-free - Fixed a memory safety bug where returning[]const u8from a stack-localbufPrintbuffer in__repr__or__str__caused undefined behavior. The callee's stack frame was destroyed before PyOZ could copy the data into a Python string. Both methods now support a buffered signaturefn __repr__(self: *const T, buf: []u8) []const u8where PyOZ provides a 4096-byte buffer that stays alive through thetoPycall. The legacy 1-parameter signature still works for string literals.raiseValueErrorand friends requiredcomptimeorinline- Removed unnecessarycomptimequalifier from the message parameter on all raise functions (raiseValueError,raiseTypeError,raiseException, customraise, etc.). Thecomptimerestriction prevented calling these from non-inline contexts and added no value sincePyErr_SetStringis a runtime C call. String literals still work as before; runtime strings are now also accepted.- Slot-handled dunders double-registered as methods - The method table generator (
methods.zig) was registering protocol dunders like__repr__,__str__,__hash__,__add__, etc. as regular Python methods in addition to their protocol slots. This caused compilation errors when the dunder's signature didn't match the regular method wrapper expectations (e.g., the new buffered__repr__with[]u8parameter). Now only slot-handled dunders are excluded; other dunders like__enter__,__exit__, and__missing__still pass through to the method table as intended. pyoz initremote fingerprint generation - Previously,pyoz init(without--local) generated a random fingerprint forbuild.zig.zonthat Zig would reject on first build, requiring manual fix-ups. Now both local and remote paths use the same strategy: write without fingerprint, runzig build, and patch with the suggested value. Extracted sharedpatchFingerprinthelper used by both code paths.
Documentation
- Raw
*pyoz.PyObjectas return type - Documented that*pyoz.PyObjectworks as both parameter and return type in class methods. Added examples for building and returning raw Python objects from Zig methods. - One-liner raise pattern - Documented that
raiseValueError()and friends returnNull, enablingreturn pyoz.raiseValueError("msg")as a one-liner in any function returning an optional type. - GC
__traverse__/__clear__example - Added a complete code example showing correct signatures (c_intreturn, by-valueGCVisitor), visitor return value checking, andPy_DecRefcleanup in__clear__.
Installation
Download the binary for your platform and add it to your PATH:
| Platform | Binary |
|---|---|
| Linux x86_64 | pyoz-x86_64-linux |
| Linux ARM64 | pyoz-aarch64-linux |
| macOS x86_64 | pyoz-x86_64-macos |
| macOS ARM64 (Apple Silicon) | pyoz-aarch64-macos |
| Windows x86_64 | pyoz-x86_64-windows.exe |
| Windows ARM64 | pyoz-aarch64-windows.exe |
Source
Download PyOZ-0.9.0.tar.gz for the source code.
Quick Start
pyoz init mymodule
cd mymodule
pyoz build
pip install dist/*.whl