You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+15Lines changed: 15 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,6 +5,21 @@ All notable changes to PyOZ will be documented in this file.
5
5
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
8
+
## [0.11.4] - 2026-02-19
9
+
10
+
### Added
11
+
-**`pyoz.Signature(T, "python_type")` -- stub return type override** - New comptime wrapper type that overrides the Python type annotation in generated `.pyi` stubs without affecting runtime behavior. Use this when the Zig return type doesn't map cleanly to the desired Python type, most commonly when `?T` is used for CPython exception signaling (returning `null` + `PyErr_SetString`) rather than representing Python `None`. For example, `fn probe() pyoz.Signature(?Dict, "dict[str, bool]")` generates `def probe() -> dict[str, bool]` instead of the incorrect `def probe() -> dict[str, bool] | None`. Also supports `pyoz.Signature(?void, "Never")` for functions that only raise. Works uniformly on module-level functions, class instance/static/class methods, `__call__`, `__new__`, and `allowThreads`/`allowThreadsTry`.
12
+
-**`PyMemoryView_Check`** - Added type check function for `memoryview` objects, following the same `isTypeOrSubtype` pattern as other type checks. Uses `PyMemoryView_Type` which is part of the stable ABI since Python 3.2, so works across 3.8–3.13 in both normal and ABI3 modes.
13
+
14
+
### Fixed
15
+
-**Comptime branch quota exceeded with large modules** - Modules with many functions would fail to compile with `evaluation exceeded 1000 backwards branches` in `anyFuncUsesDateTime`/`anyFuncUsesDecimal`. Fixed by setting `@setEvalBranchQuota(std.math.maxInt(u32))` in both functions.
16
+
17
+
### Refactored
18
+
-**Type check functions** - `PySet_Check`, `PyFrozenSet_Check`, `PyBytes_Check`, `PyByteArray_Check`, and `PyObject_TypeCheck` now use the shared `isTypeOrSubtype` helper for consistency.
19
+
20
+
### Removed
21
+
-**`method__returns__` class method stub override** - The `pub const method_name__returns__: []const u8 = "..."` convention for overriding class method return type stubs has been removed in favor of the unified `pyoz.Signature(T, "python_type")` approach, which works identically for both module-level functions and class methods.
Copy file name to clipboardExpand all lines: docs/guide/classes.md
+19-4Lines changed: 19 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -654,23 +654,38 @@ class Node:
654
654
...
655
655
```
656
656
657
-
### Return Type Override (`__returns__`)
657
+
### Return Type Override (`Signature`)
658
658
659
-
When a method returns `?*pyoz.PyObject`, the stub shows `Any | None`. Override it with the concrete Python type:
659
+
When a method returns `?T` only to signal errors (not to return `None`), or returns `?*pyoz.PyObject` for a complex type, the inferred stub annotation won't match the actual Python API. Use `pyoz.Signature(T, "stub_string")` as the return type to override it:
`Signature` works the same way for instance methods, static methods, and class methods. See [Return Type Override](stubs.md#return-type-override-signature) for full details.
688
+
674
689
### Parameter Names (`__params__`)
675
690
676
691
Zig's `@typeInfo` does not expose function parameter names, so stubs default to `arg0, arg1, ...`. Override with actual names:
When a function returns `?T` only to signal errors (not to return `None` to Python), the generated stub shows `T | None` — which is misleading. Use `pyoz.Signature(T, "stub_string")` to override the stub annotation:
124
+
125
+
```zig
126
+
fn validate(n: i64) pyoz.Signature(?i64, "int") {
127
+
if (n < 0) return pyoz.raiseValueError("must be non-negative");
128
+
return .{ .value = n };
129
+
}
130
+
```
131
+
132
+
The stub shows `-> int` instead of `-> int | None`. At runtime, `Signature` is transparent — PyOZ unwraps the `.value` field automatically. See [Type Stubs: Return Type Override](stubs.md#return-type-override-signature) for more details.
133
+
120
134
## Docstrings
121
135
122
136
The third argument to function registrations becomes the Python docstring:
Sometimes the automatically inferred stub type doesn't match the intended Python-level API. The most common case: a function returns `?T` (optional) only to signal errors via `null`, but the Python caller never sees `None` — they see a raised exception instead. The stub would show `T | None` when it should just show `T`.
117
+
118
+
Use `pyoz.Signature(T, "stub_string")` as the return type to override the stub annotation while preserving runtime behavior:
Without `Signature`, the stub would show `-> int | None`.
136
+
137
+
### How It Works
138
+
139
+
`Signature` is a comptime wrapper type. At runtime it's a struct with a single `.value` field — PyOZ unwraps it automatically, so Python never sees the wrapper. The second parameter (the string) is used verbatim as the return type annotation in the generated `.pyi` file.
140
+
141
+
### Works Everywhere
142
+
143
+
`Signature` works identically for module-level functions and class methods (instance, static, and class methods):
Supports `!Owned(T)` (error union) and `?Owned(T)` (optional) return types.
278
278
279
+
## Stub Return Type Override
280
+
281
+
### `pyoz.Signature(T, "stub_string")`
282
+
283
+
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.
284
+
285
+
```zig
286
+
fn validate(n: i64) pyoz.Signature(?i64, "int") {
287
+
if (n < 0) return pyoz.raiseValueError("must be non-negative");
288
+
return .{ .value = n };
289
+
}
290
+
```
291
+
292
+
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).
0 commit comments