3. Functions#
A lowercase pub fn in a from file. Arguments are positional or keyword, by the Zig parameter name; inspect.signature and the stub show the names and defaults. Below: Zig parameter type (what Python accepts): notes.
i32,u64,u8, ... (up to 64 bits) (int,__index__):OverflowError: `f(x)` = 300 is out of range 0..255?u32(int,None, omitted):None/ omitted givenull; stubint | None = Nonebool(anything): truthiness, likeif x:f64,f32(float,int)[]const u8,[:0]const u8(str): UTF-8, borrowed for the callpy.Bytes(bytes):.data, borrowedpy.Path(str,bytes,os.PathLike):.pathis[:0]const u8(os.fsencode); released after the callpy.Buffer/py.WritableBuffer(bytes-like / writable bytes-like):.data; locked for the call, then releasedpy.OwnedBuffer/py.OwnedWritableBuffer(the same): yours:defer data.deinit()or store itpy.Sequence(T)(any sequence (list,tuple,range, ...)):.items: []T, each converted like aT; released after*T,*const T,?*T(an instance ofsetu.Class(T)or a subclass):TypeErrorotherwise;XType.object(d)is the object*Object,?*Object(anything): raw, borrowed;Noneis passed through as a valuerest: py.Rest(*args): first (afterself);.items,try rest.tuple(); parameters before it: positional-only_: py.KwOnly(*): the parameters after it are keyword-onlyextra: py.Kwargs(**kwargs): last parameter;.dictisnullwhen none; functions and methods onlya: struct { x: i64 = 0, _: py.KwOnly = .{}, fd: i32 = AT_FDCWD }(named arguments): an argument struct, see below
An argument struct's field defaults are the Python defaults, shown as written (null -> None, a.b.NAME -> NAME, so the module must export NAME); a field without a default is required.
Return types: void (None), bool, ints, floats, ?T (null -> None), Error!T, []const u8 / a literal (str), py.Bytes (bytes), *Object (a new reference, taken), tuples .{ a, b } (tuple), other slices (list). py.toPython(value) does this conversion by hand (null with an exception set on failure); try py.new(value) the same as Error!*Object.
From here on the examples are Setu's test extension setu_class (test/): a Zig block is its code, the Python block after it a session with it, which test/guide_test.py runs on every interpreter. The sessions call the module pkg, standing for your package (from pkg import read).
/// Reads up to `n` bytes (default: all of `buf`) from `fd` into `buf` at `offset`; returns how many. /// /// Example /// >>> import os /// >>> fd = os.open('a.txt', os.O_RDWR | os.O_CREAT) /// >>> os.write(fd, b'hello world') /// 11 /// >>> b = bytearray(8) /// >>> read(fd, b, 4, offset=6) /// 4 /// >>> b /// bytearray(b'worl\x00\x00\x00\x00') /// >>> os.close(fd) pub fn read(fd: i32, buf: py.WritableBuffer, n: ?usize, _: py.KwOnly, offset: i64) Error!usize { const want = @min(n orelse buf.data.len, buf.data.len); const res: isize = @bitCast(std.os.linux.pread(fd, buf.data.ptr, want, offset)); // cast: a signed word return @intCast(try py.checkErrno(res)); // cast: `checkErrno` gave >= 0 }
Stub: def read(fd: int, buf: Buffer, n: int | None = None, *, offset: int) -> int:. In Python:
>>> import os >>> from pkg import read >>> fd = os.open('a.txt', os.O_RDWR | os.O_CREAT) >>> os.write(fd, b'hello world') 11 >>> b = bytearray(8) >>> read(fd, b, 4, offset=6) # n = 4 4 >>> b bytearray(b'worl\x00\x00\x00\x00') >>> read(fd, b, offset=0) # n omitted: all of b 8 >>> b bytearray(b'hello wo') >>> read(fd, b, 4, 0) # offset is keyword-only Traceback (most recent call last): ... TypeError: read() takes at most 3 positional arguments (4 given) >>> read(fd, b, -1, offset=0) # n is a usize Traceback (most recent call last): ... OverflowError: `read(n)` = -1 is out of range 0..18446744073709551615 >>> read(-1, b, offset=0) # py.checkErrno Traceback (most recent call last): ... OSError: [Errno 9] Bad file descriptor >>> os.close(fd)