From 6c2e06ed20cdea1a67629554d8aa1d5fcda030f9 Mon Sep 17 00:00:00 2001 From: Nathan Reiner Date: Wed, 2 Sep 2026 08:17:42 +0200 Subject: Implement sequences and tuples --- src/Watcher.zig | 62 --------------------- src/dict.zig | 143 ----------------------------------------------- src/dict/Watcher.zig | 62 +++++++++++++++++++++ src/dict/root.zig | 145 ++++++++++++++++++++++++++++++++++++++++++++++++ src/main.zig | 14 +++++ src/root.zig | 6 +- src/sequence/fast.zig | 20 +++++++ src/sequence/root.zig | 113 +++++++++++++++++++++++++++++++++++++ src/str.zig | 2 +- src/struct-sequence.zig | 25 +++++++++ src/tuple.zig | 19 ++++++- src/type/Watcher.zig | 43 ++++++++++++++ src/type/root.zig | 58 +++++++++++++++++++ 13 files changed, 501 insertions(+), 211 deletions(-) delete mode 100644 src/Watcher.zig delete mode 100644 src/dict.zig create mode 100644 src/dict/Watcher.zig create mode 100644 src/dict/root.zig create mode 100644 src/sequence/fast.zig create mode 100644 src/sequence/root.zig create mode 100644 src/struct-sequence.zig create mode 100644 src/type/Watcher.zig create mode 100644 src/type/root.zig diff --git a/src/Watcher.zig b/src/Watcher.zig deleted file mode 100644 index 4a0a7c3..0000000 --- a/src/Watcher.zig +++ /dev/null @@ -1,62 +0,0 @@ -const std = @import("std"); -const c = @import("c"); -const zpy = @import("root.zig"); - -const Self = @This(); - -id: c_int, - -pub const Event = enum(u32) { - added = c.PyDict_EVENT_ADDED, - modified = c.PyDict_EVENT_MODIFIED, - deleted = c.PyDict_EVENT_DELETED, - cloned = c.PyDict_EVENT_CLONED, - cleared = c.PyDict_EVENT_CLEARED, - deallocated = c.PyDict_EVENT_DEALLOCATED, -}; - -pub const Callback = fn (Event, *zpy.Dict, *zpy.Object, *zpy.Object) error{Exception}!void; - -pub fn add(callback: Callback) !Self { - const wrapper = struct { - pub fn wrapper( - event: c_uint, - dict: [*c]c.PyObject, - key: [*c]c.PyObject, - value: [*c]c.PyObject, - ) callconv(.c) c_int { - return if (std.meta.isError(callback( - @enumFromInt(event), - @ptrCast(dict), - @ptrCast(key), - @ptrCast(value), - ))) -1 else 0; - } - }.wrapper; - - const result = c.PyDict_AddWatcher(&wrapper); - - if (result == -1) { - return error.Exception; - } - - return .{ .id = result }; -} - -pub fn clear(self: Self) !void { - if (c.PyDict_Clear(self.id) == -1) { - return error.Exception; - } -} - -pub fn watch(self: Self, dict: *zpy.Dict) !void { - if (c.PyDict_Watch(self.id, @ptrCast(dict)) == -1) { - return error.Exception; - } -} - -pub fn unwatch(self: Self, dict: *zpy.Dict) !void { - if (c.PyDict_Unwatch(self.id, @ptrCast(dict)) == -1) { - return error.Exception; - } -} diff --git a/src/dict.zig b/src/dict.zig deleted file mode 100644 index a38d18d..0000000 --- a/src/dict.zig +++ /dev/null @@ -1,143 +0,0 @@ -const std = @import("std"); -const c = @import("c"); - -const zpy = @import("root.zig"); - -pub const Dict = extern struct { - const Self = @This(); - - data: c.PyObject, - - pub const Key = union(enum) { - string: [*c]const u8, - object: *zpy.Object, - }; - - pub fn new() !*Self { - return @ptrCast(c.PyDict_New() orelse return error.Exception); - } - - pub fn clear(self: *Self) void { - c.PyDict_Clear(self.object.ptr); - } - - pub fn contains(self: *const Self, key: Key) bool { - return switch (key) { - .string => |str| c.PyDict_ContainsString(@ptrCast(self), str), - .object => |obj| c.PyDict_Contains(@ptrCast(self), @ptrCast(obj)), - } == 1; - } - - pub fn copy(self: *const Self) *Self { - return @ptrCast(c.PyDict_Copy(@ptrCast(self))); - } - - pub fn set(self: *Self, key: Key, value: zpy.Object) !void { - const ret = switch (key) { - .string => |str| c.PyDict_SetItemString(self.object.ptr, str, value.ptr), - .object => |obj| c.PyDict_SetItem(self.object.ptr, obj.ptr, value.ptr), - }; - - if (ret == -1) return error.Exception; - } - - pub fn get(self: *const Self, key: Key) ?*zpy.Object { - return @ptrCast(switch (key) { - .string => |str| c.PyDict_GetItemString(@ptrCast(@constCast(self)), str), - .object => |obj| c.PyDict_GetItem(@ptrCast(@constCast(self)), @ptrCast(obj)), - }); - } - - pub fn delete(self: *Self, key: Key) !void { - const ret = switch (key) { - .string => |str| c.PyDict_DelItemString(@ptrCast(self), str), - .object => |obj| c.PyDict_DelItem(@ptrCast(self), @ptrCast(obj)), - }; - - if (ret == -1) return error.Exception; - } - - pub fn setDefault(self: *Self, key: *zpy.Object, default: *zpy.Object) *zpy.Object { - return @ptrCast(c.PyDict_SetDefault( - @ptrCast(self), - @ptrCast(key), - @ptrCast(default), - )); - } - - pub fn pop(self: *Self, key: Key) ?zpy.Object { - var result: ?*c.PyObject = undefined; - - switch (key) { - .string => |str| c.PyDict_PopString(@ptrCast(self), str, &result), - .object => |obj| c.PyDict_Pop(@ptrCast(self), @ptrCast(obj), &result), - } - - return result; - } - - pub fn items(self: *const Self) zpy.List { - return @ptrCast(c.PyDict_Items(@ptrCast(@constCast(self)))); - } - - pub fn keys(self: *const Self) zpy.List { - return @ptrCast(c.PyDict_Keys(@ptrCast(@constCast(self)))); - } - - pub fn values(self: *const Self) zpy.List { - return @ptrCast(c.PyDict_Values(@ptrCast(@constCast(self)))); - } - - pub fn size(self: *const Self) usize { - return @intCast(c.PyDict_Size(@ptrCast(@constCast(self)))); - } - - pub const Iterator = struct { - dict: *Dict, - position: c.Py_ssize_t = 0, - - pub const Pair = struct { - key: *zpy.Object, - value: *zpy.Object, - }; - - pub fn next(self: *@This()) ?Pair { - var pair: Pair = undefined; - - if (c.PyDict_Next( - @ptrCast(self.dict), - &self.position, - @ptrCast(&pair.key), - @ptrCast(&pair.value), - ) == 1) { - return pair; - } - - return null; - } - }; - - pub fn iterator(self: *Self) Iterator { - return .{ .dict = self }; - } - - pub fn merge(self: *Self, other: *Self) !void { - if (c.PyDict_Merge( - @ptrCast(self), - @ptrCast(other), - 0, - ) == -1) { - return error.Exception; - } - } - - pub fn update(self: *Self, other: *Self) !void { - if (c.PyDict_Merge( - @ptrCast(self), - @ptrCast(other), - 1, - ) == -1) { - return error.Exception; - } - } -}; diff --git a/src/dict/Watcher.zig b/src/dict/Watcher.zig new file mode 100644 index 0000000..317a269 --- /dev/null +++ b/src/dict/Watcher.zig @@ -0,0 +1,62 @@ +const std = @import("std"); +const c = @import("c"); +const zpy = @import("../root.zig"); + +const Self = @This(); + +id: c_int, + +pub const Event = enum(u32) { + added = c.PyDict_EVENT_ADDED, + modified = c.PyDict_EVENT_MODIFIED, + deleted = c.PyDict_EVENT_DELETED, + cloned = c.PyDict_EVENT_CLONED, + cleared = c.PyDict_EVENT_CLEARED, + deallocated = c.PyDict_EVENT_DEALLOCATED, +}; + +pub const Callback = fn (Event, *zpy.Dict, *zpy.Object, *zpy.Object) error{Exception}!void; + +pub fn add(callback: Callback) !Self { + const wrapper = struct { + pub fn wrapper( + event: c_uint, + dict: [*c]c.PyObject, + key: [*c]c.PyObject, + value: [*c]c.PyObject, + ) callconv(.c) c_int { + return if (std.meta.isError(callback( + @enumFromInt(event), + @ptrCast(dict), + @ptrCast(key), + @ptrCast(value), + ))) -1 else 0; + } + }.wrapper; + + const result = c.PyDict_AddWatcher(&wrapper); + + if (result == -1) { + return error.Exception; + } + + return .{ .id = result }; +} + +pub fn clear(self: Self) !void { + if (c.PyDict_Clear(self.id) == -1) { + return error.Exception; + } +} + +pub fn watch(self: Self, dict: *zpy.Dict) !void { + if (c.PyDict_Watch(self.id, @ptrCast(dict)) == -1) { + return error.Exception; + } +} + +pub fn unwatch(self: Self, dict: *zpy.Dict) !void { + if (c.PyDict_Unwatch(self.id, @ptrCast(dict)) == -1) { + return error.Exception; + } +} diff --git a/src/dict/root.zig b/src/dict/root.zig new file mode 100644 index 0000000..169add1 --- /dev/null +++ b/src/dict/root.zig @@ -0,0 +1,145 @@ +const std = @import("std"); +const c = @import("c"); + +const zpy = @import("../root.zig"); + +pub const Dict = extern struct { + const Self = @This(); + + data: c.PyObject, + + pub const Watcher = @import("Watcher.zig"); + + pub const Key = union(enum) { + string: [*c]const u8, + object: *zpy.Object, + }; + + pub fn new() !*Self { + return @ptrCast(c.PyDict_New() orelse return error.Exception); + } + + pub fn clear(self: *Self) void { + c.PyDict_Clear(self.object.ptr); + } + + pub fn contains(self: *const Self, key: Key) bool { + return switch (key) { + .string => |str| c.PyDict_ContainsString(@ptrCast(self), str), + .object => |obj| c.PyDict_Contains(@ptrCast(self), @ptrCast(obj)), + } == 1; + } + + pub fn copy(self: *const Self) *Self { + return @ptrCast(c.PyDict_Copy(@ptrCast(self))); + } + + pub fn set(self: *Self, key: Key, value: zpy.Object) !void { + const ret = switch (key) { + .string => |str| c.PyDict_SetItemString(self.object.ptr, str, value.ptr), + .object => |obj| c.PyDict_SetItem(self.object.ptr, obj.ptr, value.ptr), + }; + + if (ret == -1) return error.Exception; + } + + pub fn get(self: *const Self, key: Key) ?*zpy.Object { + return @ptrCast(switch (key) { + .string => |str| c.PyDict_GetItemString(@ptrCast(@constCast(self)), str), + .object => |obj| c.PyDict_GetItem(@ptrCast(@constCast(self)), @ptrCast(obj)), + }); + } + + pub fn delete(self: *Self, key: Key) !void { + const ret = switch (key) { + .string => |str| c.PyDict_DelItemString(@ptrCast(self), str), + .object => |obj| c.PyDict_DelItem(@ptrCast(self), @ptrCast(obj)), + }; + + if (ret == -1) return error.Exception; + } + + pub fn setDefault(self: *Self, key: *zpy.Object, default: *zpy.Object) *zpy.Object { + return @ptrCast(c.PyDict_SetDefault( + @ptrCast(self), + @ptrCast(key), + @ptrCast(default), + )); + } + + pub fn pop(self: *Self, key: Key) ?zpy.Object { + var result: ?*c.PyObject = undefined; + + switch (key) { + .string => |str| c.PyDict_PopString(@ptrCast(self), str, &result), + .object => |obj| c.PyDict_Pop(@ptrCast(self), @ptrCast(obj), &result), + } + + return result; + } + + pub fn items(self: *const Self) zpy.List { + return @ptrCast(c.PyDict_Items(@ptrCast(@constCast(self)))); + } + + pub fn keys(self: *const Self) zpy.List { + return @ptrCast(c.PyDict_Keys(@ptrCast(@constCast(self)))); + } + + pub fn values(self: *const Self) zpy.List { + return @ptrCast(c.PyDict_Values(@ptrCast(@constCast(self)))); + } + + pub fn size(self: *const Self) usize { + return @intCast(c.PyDict_Size(@ptrCast(@constCast(self)))); + } + + pub const Iterator = struct { + dict: *Dict, + position: c.Py_ssize_t = 0, + + pub const Pair = struct { + key: *zpy.Object, + value: *zpy.Object, + }; + + pub fn next(self: *@This()) ?Pair { + var pair: Pair = undefined; + + if (c.PyDict_Next( + @ptrCast(self.dict), + &self.position, + @ptrCast(&pair.key), + @ptrCast(&pair.value), + ) == 1) { + return pair; + } + + return null; + } + }; + + pub fn iterator(self: *Self) Iterator { + return .{ .dict = self }; + } + + pub fn merge(self: *Self, other: *Self) !void { + if (c.PyDict_Merge( + @ptrCast(self), + @ptrCast(other), + 0, + ) == -1) { + return error.Exception; + } + } + + pub fn update(self: *Self, other: *Self) !void { + if (c.PyDict_Merge( + @ptrCast(self), + @ptrCast(other), + 1, + ) == -1) { + return error.Exception; + } + } +}; diff --git a/src/main.zig b/src/main.zig index fa6fe82..c87075e 100644 --- a/src/main.zig +++ b/src/main.zig @@ -31,4 +31,18 @@ pub fn main() !void { while (global_iterator.next()) |pair| { std.debug.print("{f}\n", .{pair.key}); } + + const structtype: *zpy.Type = try .new( + .{ .name = "MyStruct" }, + &.{ + .{ .name = "first" }, + .{ .name = "second" }, + } + ); + + var struct_seq: *zpy.StructSequence = try .new(structtype); + struct_seq.set(0, (try zpy.Int.from(42)).asObject()); + struct_seq.set(1, (zpy.Str.from("hello")).asObject()); + + std.debug.print("struct = {f}\n", .{struct_seq.asObject()}); } diff --git a/src/root.zig b/src/root.zig index c45470f..0f4d9a2 100644 --- a/src/root.zig +++ b/src/root.zig @@ -4,13 +4,15 @@ const err = @import("error.zig"); pub const Exception = err.Exception; pub const Object = @import("object.zig").Object; -pub const Dict = @import("dict.zig").Dict; -pub const Watcher = @import("Watcher.zig"); +pub const Type = @import("type/root.zig").Type; +pub const Dict = @import("dict/root.zig").Dict; pub const Str = @import("str.zig").Str; pub const Tuple = @import("tuple.zig").Tuple; pub const Int = @import("int.zig").Int; pub const Float = @import("float.zig").Float; pub const List = @import("list.zig").List; +pub const Sequence = @import("sequence/root.zig").Sequence; +pub const StructSequence = @import("struct-sequence.zig").StructSequence; pub const Interpreter = @import("Interpreter.zig"); diff --git a/src/sequence/fast.zig b/src/sequence/fast.zig new file mode 100644 index 0000000..07f5de6 --- /dev/null +++ b/src/sequence/fast.zig @@ -0,0 +1,20 @@ +const c = @import("c"); +const zpy = @import("../root.zig"); + +pub const Fast = extern struct { + const Self = @This(); + + data: c.PyObject, + + pub fn size(self: *Self) !usize { + return @intCast(c.PySequence_Fast_GET_SIZE(@ptrCast(self))); + } + + pub fn get(self: *Self, index: usize) *zpy.Object { + return @ptrCast(c.PySequence_Fast_GET_ITEM(@ptrCast(self), @intCast(index)) orelse return error.Exception); + } + + pub fn items(self: *Self) [*:null][*c]zpy.Object { + return @ptrCast(c.PySequence_Fast_ITEMS(@ptrCast(self))); + } +}; diff --git a/src/sequence/root.zig b/src/sequence/root.zig new file mode 100644 index 0000000..107233b --- /dev/null +++ b/src/sequence/root.zig @@ -0,0 +1,113 @@ +const c = @import("c"); +const zpy = @import("../root.zig"); + +pub const Sequence = extern struct { + const Self = @This(); + pub const Fast = @import("fast.zig").Fast; + + data: c.PyObject, + + pub fn size(self: *Self) usize { + return @intCast(c.PySequence_Size(@ptrCast(self))); + } + + pub fn concat(self: *Self, tail: *Self) !*Self { + return @ptrCast(c.PySequence_Concat( + @ptrCast(self), + @ptrCast(tail), + ) orelse return error.Exception); + } + + pub fn repeat(self: *Self, n: usize) !*Self { + return @ptrCast(c.PySequence_Repeat( + @ptrCast(self), + @intCast(n), + ) orelse return error.Exception); + } + + pub fn inPlaceConcat(self: *Self, tail: *Self) !*Self { + return @ptrCast(c.PySequence_InPlaceConcat( + @ptrCast(self), + @ptrCast(tail), + ) orelse return error.Exception); + } + + pub fn inPlaceRepeat(self: *Self, n: usize) !*Self { + return @ptrCast(c.PySequence_InPlaceRepeat( + @ptrCast(self), + @intCast(n), + ) orelse return error.Exception); + } + + pub fn get(self: *Self, index: usize) ?*zpy.Object { + return @ptrCast(c.PySequence_GetItem(@ptrCast(self), @intCast(index))); + } + + pub fn getSlice(self: *Self, from: usize, to: usize) ?*Self { + return @ptrCast(c.PySequence_GetSlice(@ptrCast(self), @intCast(from), @intCast(to))); + } + + pub fn set(self: *Self, index: usize, value: *zpy.Object) !void { + if (c.PySequence_SetItem(@ptrCast(self), @intCast(index), @ptrCast(value)) == -1) { + return error.Exception; + } + } + + pub fn delete(self: *Self, index: usize) !void { + if (c.PySequence_DelItem(@ptrCast(self), @intCast(index)) == -1) { + return error.Exception; + } + } + + pub fn deleteSlice(self: *Self, from: usize, to: usize) !void { + if (c.PySequence_DelSlice(@ptrCast(self), @intCast(from), @intCast(to)) == -1) { + return error.Exception; + } + } + + pub fn count(self: *const Self, value: *zpy.Object) !usize { + const result = c.PySequence_Count(@ptrCast(@constCast(self)), @ptrCast(value)); + + if (result == -1) { + return error.Exception; + } + + return result; + } + + pub fn contains(self: *const Self, value: *zpy.Object) !bool { + const result = c.PySequence_Contains(@ptrCast(@constCast(self)), @ptrCast(value)); + + if (result == -1) { + return error.Exception; + } + + return result != 0; + } + + pub fn indexOf(self: *const Self, value: *zpy.Object) !usize { + const index = c.PySequence_Index(@ptrCast(@constCast(self)), @ptrCast(value)); + + if (index == -1) { + return error.Exception; + } + + return index; + } + + pub fn toList(self: *Self) !*zpy.List { + return @ptrCast(c.PySequence_List(@ptrCast(self)) orelse return error.Exception); + } + + pub fn toTuple(self: *Self) !*zpy.Tuple { + return @ptrCast(c.PySequence_Tuple(@ptrCast(self)) orelse return error.Exception); + } + + pub fn asFast(self: *Self) !*Fast { + return @ptrCast(c.PySequence_Fast(@ptrCast(self), null) orelse return error.Exception); + } + + pub fn asObject(self: *Self) *zpy.Object { + return @ptrCast(self); + } +}; diff --git a/src/str.zig b/src/str.zig index 7dde4f9..c66bd7e 100644 --- a/src/str.zig +++ b/src/str.zig @@ -7,7 +7,7 @@ pub const Str = extern struct { data: c.PyObject, - pub fn fromString(buffer: []const u8) *Self { + pub fn from(buffer: []const u8) *Self { return @ptrCast(c.PyUnicode_FromStringAndSize(@ptrCast(buffer), @intCast(buffer.len))); } diff --git a/src/struct-sequence.zig b/src/struct-sequence.zig new file mode 100644 index 0000000..bc1b8e7 --- /dev/null +++ b/src/struct-sequence.zig @@ -0,0 +1,25 @@ +const c = @import("c"); + +const zpy = @import("root.zig"); + +pub const StructSequence = extern struct { + const Self = @This(); + + data: c.PyObject, + + pub fn new(t: *zpy.Type) !*Self { + return @ptrCast(c.PyStructSequence_New(@ptrCast(@constCast(t))) orelse return error.Exception); + } + + pub fn get(self: *Self, index: usize) *Self { + return @ptrCast(c.PyStructSequence_GetItem(@ptrCast(self), @intCast(index))); + } + + pub fn set(self: *Self, index: usize, value: *zpy.Object) void { + c.PyStructSequence_SetItem(@ptrCast(self), @intCast(index), @ptrCast(value)); + } + + pub fn asObject(self: *Self) *zpy.Object { + return @ptrCast(self); + } +}; diff --git a/src/tuple.zig b/src/tuple.zig index ba82003..4e53d3f 100644 --- a/src/tuple.zig +++ b/src/tuple.zig @@ -22,24 +22,37 @@ pub const Tuple = extern struct { } pub fn size(self: *const Self) usize { - return c.PyTuple_GET_SIZE(self.object.ptr); + return c.PyTuple_GET_SIZE(@ptrCast(self)); } - pub fn get(self: *Self, index: usize) !*zpy.Object { + pub fn get(self: *const Self, index: usize) !*zpy.Object { return @ptrCast( c.PyTuple_GetItem( - self.object.ptr, + @ptrCast(self), @intCast(index), ) orelse return error.Exception, ); } + pub fn getUnchecked(self: *Self, index: usize) *zpy.Object { + return @ptrCast(c.PyTuple.GET_ITEM( + @ptrCast(self), + @intCast(index), + )); + } + pub fn set(self: *Self, index: usize, value: *zpy.Object) !void { if (c.PyTuple_SetItem(@ptrCast(self), @intCast(index), @ptrCast(value)) == -1) { return error.Exception; } } + pub fn resize(self: *Self, newlen: usize) !void { + if (c._PyTuple_Resize(@ptrCast(&self), @intCast(newlen)) == -1) { + return error.Exception; + } + } + pub fn asObject(self: *Self) *zpy.Object { return @ptrCast(self); } diff --git a/src/type/Watcher.zig b/src/type/Watcher.zig new file mode 100644 index 0000000..6369df5 --- /dev/null +++ b/src/type/Watcher.zig @@ -0,0 +1,43 @@ +const std = @import("std"); +const c = @import("c"); +const zpy = @import("../root.zig"); + +const Self = @This(); + +id: c_int, + +pub const Callback = fn (*zpy.Type) error{Exception}!void; + +pub fn add(callback: Callback) !Self { + const wrapper = struct { + pub fn wrapper(t: [*c]c.PyObject) callconv(.c) c_int { + return if (std.meta.isError(callback(@ptrCast(t)))) -1 else 0; + } + }; + + const result = c.PyType_AddWatcher(&wrapper); + + if (result == -1) { + return error.Exception; + } + + return .{ .id = result }; +} + +pub fn clear(self: Self) !void { + if (c.PyType_Clear(self.id) == -1) { + return error.Exception; + } +} + +pub fn watch(self: Self, t: *zpy.Dict) !void { + if (c.PyType_Watch(self.id, t) == -1) { + return error.Exception; + } +} + +pub fn unwatch(self: Self, t: *zpy.Dict) !void { + if (c.PyType_Unwatch(self.id, t) == -1) { + return error.Exception; + } +} diff --git a/src/type/root.zig b/src/type/root.zig new file mode 100644 index 0000000..128f3d9 --- /dev/null +++ b/src/type/root.zig @@ -0,0 +1,58 @@ +const std = @import("std"); +const c = @import("c"); + +const zpy = @import("../root.zig"); + +pub const Type = extern struct { + const Self = @This(); + + data: c.PyObject, + + pub const Watcher = @import("Watcher.zig"); + + pub const Description = extern struct { + name: [*:0]const u8, + doc: ?[*:0]const u8 = null, + }; + + pub fn new(description: Description, comptime fields: []const Description) !*Self { + var c_desc: c.PyStructSequence_Desc = .{ + .name = @ptrCast(description.name), + .doc = @ptrCast(description.doc), + .fields = @ptrCast(@constCast(fields)), + .n_in_sequence = @intCast(fields.len), + }; + + return @ptrCast(c.PyStructSequence_NewType(@ptrCast(&c_desc)) orelse return error.Exception); + } + + pub fn getDict(self: *Self) *zpy.Dict { + return @ptrCast(c.PyType_GetDict(@ptrCast(self))); + } + + pub fn modified(self: *Self) void { + c.PyType_Modified(@ptrCast(self)); + } + + pub fn isGc(self: *Self) bool { + return c.PyType_IS_GC(@ptrCast(self)) != 0; + } + + pub fn isSubtype(self: *Self, target: *Self) bool { + return c.PyType_IsSubtype(@ptrCast(self), @ptrCast(target)) != 0; + } + + pub fn ready(self: *Self) !void { + if (c.PyType_Ready(@ptrCast(self)) == -1) { + return error.Exception; + } + } + + pub fn getName(self: *Self) *zpy.Str { + return @ptrCast(c.Pytype_GetName(@ptrCast(self))); + } + + pub fn asObject(self: *Self) *zpy.Object { + return @ptrCast(self); + } +}; -- cgit v1.2.3-70-g09d2