From c5bc2a4a86211c114529ce357935a26dbaba6297 Mon Sep 17 00:00:00 2001 From: Nicholas Gates Date: Wed, 18 Oct 2023 21:55:44 +0100 Subject: [PATCH 1/3] Deprecate __new__ in favour of __init__ --- .vscode/launch.json | 11 ++++ docs/guide/classes.md | 22 ++++++-- docs/guide/modules.md | 2 +- example/buffers.zig | 7 +-- example/classes.zig | 29 +++++------ example/iterators.zig | 4 +- example/modules.zig | 4 +- example/operators.zig | 20 ++++---- pydust/src/builtins.zig | 13 +++-- pydust/src/modules.zig | 21 ++++---- pydust/src/pydust.zig | 3 ++ pydust/src/pytypes.zig | 100 ++++++++++++------------------------ pydust/src/types/module.zig | 4 +- 13 files changed, 117 insertions(+), 123 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 8539ac55..4b0d3519 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -19,5 +19,16 @@ ], "program": "zig-out/bin/debug.bin", }, + { + "type": "lldb", + "request": "launch", + "name": "LLDB Python", + "program": "${command:python.interpreterPath}", + "args": [ + "-m", + "pytest", + ], + "cwd": "${workspaceFolder}" + }, ] } \ No newline at end of file diff --git a/docs/guide/classes.md b/docs/guide/classes.md index 86577f55..982de63c 100644 --- a/docs/guide/classes.md +++ b/docs/guide/classes.md @@ -20,13 +20,24 @@ corresponding Python object around it. For example, the class above can be correctly constructed using the `py.init` function: ```zig -const some_class = try py.init(SomeClass, .{ .count = 1 }); +const some_instance = try py.init(SomeClass, .{ .count = 1 }); +``` + +Alternatively, a class can be allocated without instantiation. This can be useful when some +fields of the class refer by pointer to other fields. + +```zig +var some_instance = try py.alloc(SomeClass); +some_instance.* = .{ + .foo = 124, + .bar = &some_instance.foo, +}; ``` ### From Python -To enable instantiation from Python, you must define a `__new__` function -that takes a CallArgs struct and returns a new instance of `Self`. +Declaring a `__init__` function signifies to Pydust to make your class instantiable +from Python. This function may take zero arguments as a pure marker to allow instantiation. === "Zig" @@ -50,7 +61,7 @@ Inheritance allows you to define a subclass of another Zig Pydust class. Subclasses are defined by including the parent class struct as a field of the subclass struct. They can then be instantiated from Zig using `py.init`, or from Python -if a `__new__` function is defined. +if a `__init__` function is defined. === "Zig" @@ -162,7 +173,8 @@ const binaryfunc = fn(*Self, object) !object; | Method | Signature | | :--------- | :--------------------------------------- | -| `__new__` | `#!zig fn(CallArgs) !Self` | +| `__init__` | `#!zig fn() void` | +| `__init__` | `#!zig fn(*Self) !void` | | `__init__` | `#!zig fn(*Self, CallArgs) !void` | | `__del__` | `#!zig fn(*Self) void` | | `__repr__` | `#!zig fn(*Self) !py.PyString` | diff --git a/docs/guide/modules.md b/docs/guide/modules.md index ddbd741b..1c2a5e8e 100644 --- a/docs/guide/modules.md +++ b/docs/guide/modules.md @@ -31,7 +31,7 @@ Please refer to the annotations in this example module for an explanation of the 2. Unlike regular Python modules, native Python modules are able to carry private internal state. 3. Any fields that cannot be defaulted at comptime (i.e. if they require calling into Python) - must be initialized in the module's `__new__` function. + must be initialized in the module's `__init__` function. 4. Module functions taking a `*Self` or `*const Self` argument are passed a pointer to their internal state. diff --git a/example/buffers.zig b/example/buffers.zig index 5302c281..d8eef59f 100644 --- a/example/buffers.zig +++ b/example/buffers.zig @@ -22,17 +22,14 @@ pub const ConstantBuffer = py.class(struct { shape: []const isize, // isize to be compatible with Python API format: [:0]const u8 = "l", // i64 - pub fn __new__(args: struct { elem: i64, length: u32 }) !Self { + pub fn __init__(self: *Self, args: struct { elem: i64, length: u32 }) !void { const values = try py.allocator.alloc(i64, args.length); @memset(values, args.elem); const shape = try py.allocator.alloc(isize, 1); shape[0] = @intCast(args.length); - return Self{ - .values = values, - .shape = shape, - }; + self.* = .{ .values = values, .shape = shape }; } pub fn __del__(self: *Self) void { diff --git a/example/classes.zig b/example/classes.zig index 3c9c71c3..7da9ef9b 100644 --- a/example/classes.zig +++ b/example/classes.zig @@ -25,8 +25,8 @@ pub const SomeClass = py.class(struct { pub const ConstructableClass = py.class(struct { count: u32 = 0, - pub fn __new__(args: struct { count: u32 }) @This() { - return .{ .count = args.count }; + pub fn __init__(self: *@This(), args: struct { count: u32 }) void { + self.count = args.count; } }); // --8<-- [end:constructor] @@ -48,9 +48,9 @@ pub const Dog = py.class(struct { animal: Animal, breed: py.PyString, - pub fn __new__(args: struct { breed: py.PyString }) !Self { + pub fn __init__(self: *Self, args: struct { breed: py.PyString }) !void { args.breed.incref(); - return .{ + self.* = .{ .animal = .{ .species = try py.PyString.create("dog") }, .breed = args.breed, }; @@ -67,9 +67,9 @@ pub const Dog = py.class(struct { pub const User = py.class(struct { const Self = @This(); - pub fn __new__(args: struct { name: py.PyString }) Self { + pub fn __init__(self: *Self, args: struct { name: py.PyString }) void { args.name.incref(); - return .{ .name = args.name, .email = .{} }; + self.* = .{ .name = args.name, .email = .{} }; } name: py.PyString, @@ -105,9 +105,8 @@ pub const Counter = py.class(struct { count: py.attribute(usize) = .{ .value = 0 }, - pub fn __new__(args: struct {}) Self { - _ = args; - return .{}; + pub fn __init__(self: *Self) void { + _ = self; } pub fn increment(self: *Self) void { @@ -129,8 +128,8 @@ pub const ZigOnlyMethod = py.class(struct { const Self = @This(); number: i32, - pub fn __new__(args: struct { x: i32 }) Self { - return .{ .number = args.x }; + pub fn __init__(self: *Self, args: struct { x: i32 }) void { + self.number = args.x; } pub usingnamespace py.zig(struct { @@ -149,8 +148,8 @@ pub const Hash = py.class(struct { const Self = @This(); number: u32, - pub fn __new__(args: struct { x: u32 }) Self { - return .{ .number = args.x }; + pub fn __init__(self: *Self, args: struct { x: u32 }) void { + self.number = args.x; } pub fn __hash__(self: *const Self) usize { @@ -163,8 +162,8 @@ pub const Hash = py.class(struct { pub const Callable = py.class(struct { const Self = @This(); - pub fn __new__() Self { - return .{}; + pub fn __init__(self: *Self) void { + _ = self; } pub fn __call__(self: *const Self, args: struct { i: u32 }) u32 { diff --git a/example/iterators.zig b/example/iterators.zig index b3186e95..38516fe0 100644 --- a/example/iterators.zig +++ b/example/iterators.zig @@ -22,8 +22,8 @@ pub const Range = py.class(struct { upper: i64, step: i64, - pub fn __new__(args: struct { lower: i64, upper: i64, step: i64 }) Self { - return .{ .lower = args.lower, .upper = args.upper, .step = args.step }; + pub fn __init__(self: *Self, args: struct { lower: i64, upper: i64, step: i64 }) void { + self.* = .{ .lower = args.lower, .upper = args.upper, .step = args.step }; } pub fn __iter__(self: *const Self) !*RangeIterator { diff --git a/example/modules.zig b/example/modules.zig index 4c82d857..800ebb41 100644 --- a/example/modules.zig +++ b/example/modules.zig @@ -27,8 +27,8 @@ const Self = @This(); // (1)! count: u32 = 0, // (2)! name: py.PyString, -pub fn __new__() !Self { // (3)! - return .{ .name = try py.PyString.create("Ziggy") }; +pub fn __init__(self: *Self) !void { // (3)! + self.* = .{ .name = try py.PyString.create("Ziggy") }; } pub fn __del__(self: Self) void { diff --git a/example/operators.zig b/example/operators.zig index 6a558476..4d3d4648 100644 --- a/example/operators.zig +++ b/example/operators.zig @@ -19,8 +19,8 @@ pub const Ops = py.class(struct { num: u64, - pub fn __new__(args: struct { num: u64 }) Self { - return .{ .num = args.num }; + pub fn __init__(self: *Self, args: struct { num: u64 }) !void { + self.num = args.num; } pub fn num(self: *const Self) u64 { @@ -171,8 +171,8 @@ pub const Operator = py.class(struct { num: u64, - pub fn __new__(args: struct { num: u64 }) Self { - return .{ .num = args.num }; + pub fn __init__(self: *Self, args: struct { num: u64 }) void { + self.num = args.num; } pub fn num(self: *const Self) u64 { @@ -204,8 +204,8 @@ pub const Comparator = py.class(struct { num: u64, - pub fn __new__(args: struct { num: u64 }) Self { - return .{ .num = args.num }; + pub fn __init__(self: *Self, args: struct { num: u64 }) void { + self.num = args.num; } pub fn __richcompare__(self: *const Self, other: *const Self, op: py.CompareOp) bool { @@ -227,8 +227,8 @@ pub const Equals = py.class(struct { num: u64, - pub fn __new__(args: struct { num: u64 }) Self { - return .{ .num = args.num }; + pub fn __init__(self: *Self, args: struct { num: u64 }) void { + self.num = args.num; } pub fn __eq__(self: *const Self, other: *const Self) bool { @@ -243,9 +243,9 @@ pub const LessThan = py.class(struct { name: py.PyString, - pub fn __new__(args: struct { name: py.PyString }) Self { + pub fn __init__(self: *Self, args: struct { name: py.PyString }) void { args.name.incref(); - return .{ .name = args.name }; + self.name = args.name; } pub fn __lt__(self: *const Self, other: *const Self) !bool { diff --git a/pydust/src/builtins.zig b/pydust/src/builtins.zig index cfba4b2e..24dbdafa 100644 --- a/pydust/src/builtins.zig +++ b/pydust/src/builtins.zig @@ -172,8 +172,8 @@ pub fn import(module_name: [:0]const u8) !py.PyObject { return (try py.PyModule.import(module_name)).obj; } -/// Instantiate a class defined in Pydust. -pub inline fn init(comptime Cls: type, args: Cls) PyError!*Cls { +/// Allocate a Pydust class, but does not initialize the memory. +pub fn alloc(comptime Cls: type) PyError!*Cls { const pytype = try self(Cls); defer pytype.decref(); @@ -181,11 +181,16 @@ pub inline fn init(comptime Cls: type, args: Cls) PyError!*Cls { // NOTE(ngates): we currently don't allow users to override tp_alloc, therefore we can shortcut // using ffi.PyType_GetSlot(tp_alloc) since we know it will always return ffi.PyType_GenericAlloc const pyobj: *pytypes.PyTypeStruct(Cls) = @alignCast(@ptrCast(ffi.PyType_GenericAlloc(@ptrCast(pytype.obj.py), 0) orelse return PyError.PyRaised)); - pyobj.state = args; - return &pyobj.state; } +/// Allocate and instantiate a class defined in Pydust. +pub inline fn init(comptime Cls: type, state: Cls) PyError!*Cls { + const cls: *Cls = try alloc(Cls); + cls.* = state; + return cls; +} + /// Check if object is an instance of cls. pub fn isinstance(object: anytype, cls: anytype) !bool { const pyobj = py.object(object); diff --git a/pydust/src/modules.zig b/pydust/src/modules.zig index ee67f911..f02aeecc 100644 --- a/pydust/src/modules.zig +++ b/pydust/src/modules.zig @@ -85,6 +85,7 @@ fn Slots(comptime definition: type) type { pub const slots: [:empty]const ffi.PyModuleDef_Slot = blk: { var slots_: [:empty]const ffi.PyModuleDef_Slot = &.{}; + slots_ = slots_ ++ .{ffi.PyModuleDef_Slot{ .slot = ffi.Py_mod_exec, .value = @ptrCast(@constCast(&Self.mod_exec)), @@ -115,6 +116,17 @@ fn Slots(comptime definition: type) type { } inline fn mod_exec_internal(module: py.PyModule) !void { + // First, initialize the module state using an __init__ function + if (@typeInfo(definition).Struct.fields.len > 0) { + if (!@hasDecl(definition, "__init__")) { + @compileError( + "Non-empty module '" ++ State.getIdentifier(definition).qualifiedName ++ "' must define `fn __init__(*Self) !void` method to initialize its state", + ); + } + const state = try module.getState(definition); + try state.__init__(); + } + // Add attributes (including class definitions) to the module inline for (attrs.attributes) |attr| { const obj = try attr.ctor(module); @@ -147,15 +159,6 @@ fn Slots(comptime definition: type) type { try module.addObjectRef(name, submod); } - - // Finally, i Initialize the state struct to default values - const state = try module.getState(definition); - if (@hasDecl(definition, "__new__")) { - const newFunc = @field(definition, "__new__"); - state.* = try newFunc(); - } else { - state.* = definition{}; - } } }; } diff --git a/pydust/src/pydust.zig b/pydust/src/pydust.zig index db9ce7ef..c74f17a4 100644 --- a/pydust/src/pydust.zig +++ b/pydust/src/pydust.zig @@ -108,6 +108,9 @@ pub const Args = []types.PyObject; /// Zig type representing variadic keyword arguments to a Python function. pub const Kwargs = std.StringHashMap(types.PyObject); +/// Zig type representing `(*args, **kwargs)` +pub const CallArgs = struct { args: Args, kwargs: Kwargs }; + /// Force the evaluation of Pydust registration methods. /// Using this enables us to breadth-first traverse the object graph, ensuring /// objects are registered before they're referenced elsewhere. diff --git a/pydust/src/pytypes.zig b/pydust/src/pytypes.zig index cf1be6cf..77e3ad50 100644 --- a/pydust/src/pytypes.zig +++ b/pydust/src/pytypes.zig @@ -118,16 +118,7 @@ fn Slots(comptime definition: type, comptime name: [:0]const u8) type { } if (@hasDecl(definition, "__new__")) { - slots_ = slots_ ++ .{ffi.PyType_Slot{ - .slot = ffi.Py_tp_new, - .pfunc = @ptrCast(@constCast(&tp_new)), - }}; - } else { - // Otherwise, we set tp_new to a default that throws a type error. - slots_ = slots_ ++ .{ffi.PyType_Slot{ - .slot = ffi.Py_tp_new, - .pfunc = @ptrCast(@constCast(&tp_new_default)), - }}; + @compileLog("The behaviour of __new__ is replaced by __init__(*Self). See ", State.getIdentifier(definition).qualifiedName); } if (@hasDecl(definition, "__init__")) { @@ -135,6 +126,13 @@ fn Slots(comptime definition: type, comptime name: [:0]const u8) type { .slot = ffi.Py_tp_init, .pfunc = @ptrCast(@constCast(&tp_init)), }}; + } else { + // Otherwise, we set tp_init to a default that throws to ensure the class + // cannot be constructed from Python + slots_ = slots_ ++ .{ffi.PyType_Slot{ + .slot = ffi.Py_tp_init, + .pfunc = @ptrCast(@constCast(&tp_init_default)), + }}; } if (@hasDecl(definition, "__del__")) { @@ -244,69 +242,39 @@ fn Slots(comptime definition: type, comptime name: [:0]const u8) type { break :blk slots_; }; - fn tp_new(subtype: *ffi.PyTypeObject, pyargs: [*c]ffi.PyObject, pykwargs: [*c]ffi.PyObject) callconv(.C) ?*ffi.PyObject { - const pyself: *ffi.PyObject = ffi.PyType_GenericAlloc(subtype, 0) orelse return null; - // Cast it into a supertype instance. Note: we check at comptime that subclasses of this class - // include our own state object as the first field in their struct. - const self: *PyTypeStruct(definition) = @ptrCast(pyself); + fn tp_init(pyself: *ffi.PyObject, pyargs: [*c]ffi.PyObject, pykwargs: [*c]ffi.PyObject) callconv(.C) c_int { + const sig = funcs.parseSignature("__init__", @typeInfo(@TypeOf(definition.__init__)).Fn, &.{ *definition, *const definition, py.PyObject }); - // Allow the definition to initialize the state field. - self.state = tp_new_internal( - .{ .py = @alignCast(@ptrCast(subtype)) }, - if (pyargs) |pa| py.PyTuple.unchecked(.{ .py = pa }) else null, - if (pykwargs) |pk| py.PyDict.unchecked(.{ .py = pk }) else null, - ) catch return null; + if (sig.selfParam == null and @typeInfo(definition).fields.len > 0) { + @compileError("__init__ must take both a self argument"); + } + const self = tramp.Trampoline(sig.selfParam.?).unwrap(py.PyObject{ .py = pyself }) catch return -1; - return pyself; - } + if (sig.argsParam) |Args| { + const args = if (pyargs) |pa| py.PyTuple.unchecked(.{ .py = pa }) else null; + const kwargs = if (pykwargs) |pk| py.PyDict.unchecked(.{ .py = pk }) else null; - fn tp_new_internal(subtype: py.PyObject, pyargs: ?py.PyTuple, pykwargs: ?py.PyDict) PyError!definition { - const sig = funcs.parseSignature("__new__", @typeInfo(@TypeOf(definition.__new__)).Fn, &.{ py.PyObject, py.PyType }); - - if (sig.selfParam) |Self| { - const pycls = try tramp.Trampoline(Self).unwrap(subtype); - if (sig.argsParam) |Args| { - const args = try tramp.Trampoline(Args).unwrapCallArgs(pyargs, pykwargs); - defer funcs.deinitArgs(Args, args); - return try tramp.coerceError(definition.__new__(pycls, args)); - } else { - return try tramp.coerceError(definition.__new__(pycls)); - } - } else if (sig.argsParam) |Args| { - const args = try tramp.Trampoline(Args).unwrapCallArgs(pyargs, pykwargs); - defer funcs.deinitArgs(Args, args); - return try tramp.coerceError(definition.__new__(args)); + const init_args = tramp.Trampoline(Args).unwrapCallArgs(args, kwargs) catch return -1; + defer funcs.deinitArgs(Args, init_args); + + tramp.coerceError(definition.__init__(self, init_args)) catch return -1; + } else if (sig.selfParam) |_| { + tramp.coerceError(definition.__init__(self)) catch return -1; } else { - return try tramp.coerceError(definition.__new__()); + // The function is just a marker to say that the type can be instantiated from Python } + + return 0; } - fn tp_new_default(subtype: *ffi.PyTypeObject, pyargs: [*c]ffi.PyObject, pykwargs: [*c]ffi.PyObject) callconv(.C) ?*ffi.PyObject { + fn tp_init_default(pyself: *ffi.PyObject, pyargs: [*c]ffi.PyObject, pykwargs: [*c]ffi.PyObject) callconv(.C) ?*ffi.PyObject { + _ = pyself; _ = pykwargs; _ = pyargs; - _ = subtype; py.TypeError.raise("Native type cannot be instantiated from Python") catch return null; return null; } - fn tp_init(pyself: *ffi.PyObject, pyargs: [*c]ffi.PyObject, pykwargs: [*c]ffi.PyObject) callconv(.C) c_int { - const sig = funcs.parseSignature("__init__", @typeInfo(@TypeOf(definition.__init__)).Fn, &.{ *definition, *const definition, py.PyObject }); - - if (sig.selfParam == null or sig.argsParam == null) { - @compileError("__init__ must take both a self argument and an args struct"); - } - - const args = if (pyargs) |pa| py.PyTuple.unchecked(.{ .py = pa }) else null; - const kwargs = if (pykwargs) |pk| py.PyDict.unchecked(.{ .py = pk }) else null; - - const self = tramp.Trampoline(sig.selfParam.?).unwrap(py.PyObject{ .py = pyself }) catch return -1; - const init_args = tramp.Trampoline(sig.argsParam.?).unwrapCallArgs(args, kwargs) catch return -1; - defer funcs.deinitArgs(sig.argsParam.?, init_args); - - tramp.coerceError(definition.__init__(self, init_args)) catch return -1; - return 0; - } - /// Wrapper for the user's __del__ function. /// Note: tp_del is deprecated in favour of tp_finalize. /// @@ -400,10 +368,8 @@ fn Doc(comptime definition: type, comptime name: [:0]const u8) type { const docLen = blk: { var size: usize = 0; var maybeSig: ?funcs.Signature = null; - if (@hasDecl(definition, "__new__")) { - maybeSig = funcs.parseSignature("__new__", @typeInfo(@TypeOf(definition.__new__)).Fn, &.{py.PyObject}); - } else if (@hasDecl(definition, "__init__")) { - maybeSig = funcs.parseSignature("__init__", @typeInfo(@TypeOf(definition._init__)).Fn, &.{ py.PyObject, *definition, *const definition }); + if (@hasDecl(definition, "__init__")) { + maybeSig = funcs.parseSignature("__init__", @typeInfo(@TypeOf(definition.__init__)).Fn, &.{ py.PyObject, *definition, *const definition }); } if (maybeSig) |sig| { @@ -428,10 +394,8 @@ fn Doc(comptime definition: type, comptime name: [:0]const u8) type { var userDoc: [docLen:0]u8 = undefined; var docOffset = 0; var maybeSig: ?funcs.Signature = null; - if (@hasDecl(definition, "__new__")) { - maybeSig = funcs.parseSignature("__new__", @typeInfo(@TypeOf(definition.__new__)).Fn, &.{py.PyObject}); - } else if (@hasDecl(definition, "__init__")) { - maybeSig = funcs.parseSignature("__init__", @typeInfo(@TypeOf(definition.__new__)).Fn, &.{ py.PyObject, *definition, *const definition }); + if (@hasDecl(definition, "__init__")) { + maybeSig = funcs.parseSignature("__init__", @typeInfo(@TypeOf(definition.__init__)).Fn, &.{ py.PyObject, *definition, *const definition }); } if (maybeSig) |sig| { diff --git a/pydust/src/types/module.zig b/pydust/src/types/module.zig index e8bd9b69..97a2639f 100644 --- a/pydust/src/types/module.zig +++ b/pydust/src/types/module.zig @@ -55,8 +55,8 @@ pub const PyModule = extern struct { @compileError("Can only init class objects"); } - if (@hasDecl(Cls, "__new__")) { - @compileError("PyTypes with a __new__ method should be instantiated with ptype.call(...)"); + if (@hasDecl(Cls, "__init__")) { + @compileError("PyTypes with a __init__ method should be instantiated via Python with ptype.call(...)"); } // Alloc the class From a1e1393fc4eb16266d7a21e2e067c581d9b8c0da Mon Sep 17 00:00:00 2001 From: Nicholas Gates Date: Wed, 18 Oct 2023 22:10:46 +0100 Subject: [PATCH 2/3] Fixes --- pydust/src/modules.zig | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pydust/src/modules.zig b/pydust/src/modules.zig index f02aeecc..d86a8ae0 100644 --- a/pydust/src/modules.zig +++ b/pydust/src/modules.zig @@ -119,12 +119,14 @@ fn Slots(comptime definition: type) type { // First, initialize the module state using an __init__ function if (@typeInfo(definition).Struct.fields.len > 0) { if (!@hasDecl(definition, "__init__")) { - @compileError( - "Non-empty module '" ++ State.getIdentifier(definition).qualifiedName ++ "' must define `fn __init__(*Self) !void` method to initialize its state", - ); + @compileError("Non-empty module must define `fn __init__(*Self) !void` method to initialize its state: " ++ @typeName(definition)); } const state = try module.getState(definition); - try state.__init__(); + if (@typeInfo(@typeInfo(@TypeOf(definition.__init__)).Fn.return_type.?) == .ErrorUnion) { + try state.__init__(); + } else { + state.__init__(); + } } // Add attributes (including class definitions) to the module From b8b95544337f59fa0f77bc93556ffae1fdda1fe4 Mon Sep 17 00:00:00 2001 From: Nicholas Gates Date: Wed, 18 Oct 2023 22:12:15 +0100 Subject: [PATCH 3/3] Fixes --- example/buffers.pyi | 2 +- example/classes.pyi | 14 +++++++------- example/iterators.pyi | 2 +- example/operators.pyi | 10 +++++----- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/example/buffers.pyi b/example/buffers.pyi index 11484d46..384fda2d 100644 --- a/example/buffers.pyi +++ b/example/buffers.pyi @@ -7,5 +7,5 @@ class ConstantBuffer: A class implementing a buffer protocol """ - def __init__(elem, length, /): + def __init__(self, elem, length, /): pass diff --git a/example/classes.pyi b/example/classes.pyi index 59f63425..59eb051a 100644 --- a/example/classes.pyi +++ b/example/classes.pyi @@ -4,7 +4,7 @@ class Animal: def species(self, /): ... class Callable: - def __init__(): + def __init__(self, /): pass def __call__(self, /, *args, **kwargs): """ @@ -13,18 +13,18 @@ class Callable: ... class ConstructableClass: - def __init__(count, /): + def __init__(self, count, /): pass class Counter: - def __init__(): + def __init__(self, /): pass def increment(self, /): ... count: ... class Hash: - def __init__(x, /): + def __init__(self, x, /): pass def __hash__(self, /): """ @@ -41,7 +41,7 @@ class SomeClass: """ class User: - def __init__(name, /): + def __init__(self, name, /): pass @property def email(self): ... @@ -49,11 +49,11 @@ class User: def greeting(self): ... class ZigOnlyMethod: - def __init__(x, /): + def __init__(self, x, /): pass def reexposed(self, /): ... class Dog(Animal): - def __init__(breed, /): + def __init__(self, breed, /): pass def breed(self, /): ... diff --git a/example/iterators.pyi b/example/iterators.pyi index 7289c3e0..f59ad081 100644 --- a/example/iterators.pyi +++ b/example/iterators.pyi @@ -5,7 +5,7 @@ class Range: An example of iterable class """ - def __init__(lower, upper, step, /): + def __init__(self, lower, upper, step, /): pass def __iter__(self, /): """ diff --git a/example/operators.pyi b/example/operators.pyi index 99e09955..cf1c5fe6 100644 --- a/example/operators.pyi +++ b/example/operators.pyi @@ -1,7 +1,7 @@ from __future__ import annotations class Comparator: - def __init__(num, /): + def __init__(self, num, /): pass def __lt__(self, value, /): """ @@ -35,7 +35,7 @@ class Comparator: ... class Equals: - def __init__(num, /): + def __init__(self, num, /): pass def __lt__(self, value, /): """ @@ -69,7 +69,7 @@ class Equals: ... class LessThan: - def __init__(name, /): + def __init__(self, name, /): pass def __lt__(self, value, /): """ @@ -103,7 +103,7 @@ class LessThan: ... class Operator: - def __init__(num, /): + def __init__(self, num, /): pass def __truediv__(self, value, /): """ @@ -118,7 +118,7 @@ class Operator: def num(self, /): ... class Ops: - def __init__(num, /): + def __init__(self, num, /): pass def __add__(self, value, /): """