Skip to content
This repository was archived by the owner on Apr 3, 2026. It is now read-only.

Commit ccc4450

Browse files
committed
Add keyError and make Int.as throw ValueError if cast is invalid
1 parent cedf0bf commit ccc4450

1 file changed

Lines changed: 22 additions & 8 deletions

File tree

py.zig

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,16 @@ pub inline fn attributeErrorObject(comptime value: anytype, msg: [:0]const u8, a
144144
return value;
145145
}
146146

147+
// Helper that is the equivalent to `KeyError(msg)`
148+
pub inline fn keyError(msg: [:0]const u8, args: anytype) !void {
149+
return errorFormat(@ptrCast(c.PyExc_KeyError), msg, args);
150+
}
151+
152+
pub inline fn keyErrorObject(comptime value: anytype, msg: [:0]const u8, args: anytype) @TypeOf(value) {
153+
keyError(msg, args) catch {};
154+
return value;
155+
}
156+
147157
pub inline fn memoryError() !void {
148158
_ = c.PyErr_NoMemory();
149159
return error.PyError;
@@ -1030,19 +1040,20 @@ pub const Int = extern struct {
10301040
return c.PyIndex_Check(@as([*c]c.PyObject, @constCast(@ptrCast(obj)))) != 0;
10311041
}
10321042

1033-
// Convert to the given zig type
1043+
// Convert to the given zig type. If it cannot be safely casted it
1044+
// will raise a ValueError("int out of range for T")
10341045
pub inline fn as(self: *Int, comptime T: type) !T {
10351046
comptime var error_value = -1;
10361047
const n = @bitSizeOf(c_long);
1037-
const r: T = switch (@typeInfo(T)) {
1048+
const r: ?T = switch (@typeInfo(T)) {
10381049
.Int => |info| switch (info.bits) {
1039-
0...n => @intCast(if (info.signedness == .signed)
1050+
0...n => std.math.cast(T, if (info.signedness == .signed)
10401051
c.PyLong_AsLong(@ptrCast(self))
10411052
else blk: {
10421053
error_value = std.math.maxInt(c_ulong); // Update error value
10431054
break :blk c.PyLong_AsUnsignedLong(@ptrCast(self));
10441055
}),
1045-
else => @intCast(if (info.signedness == .signed)
1056+
else => std.math.cast(T, if (info.signedness == .signed)
10461057
c.PyLong_AsLongLong(@ptrCast(self))
10471058
else blk: {
10481059
error_value = std.math.maxInt(c_ulonglong); // Update error value
@@ -1052,11 +1063,14 @@ pub const Int = extern struct {
10521063
.Float => @floatCast(c.PyLong_AsDouble(@ptrCast(self))),
10531064
else => @compileError("Cannot convert python in to " ++ @typeName(T)),
10541065
};
1055-
1056-
if (r == error_value and errorOccurred() != null) {
1057-
return error.PyError;
1066+
if (r) |value| {
1067+
if (value == error_value and errorOccurred() != null) {
1068+
return error.PyError;
1069+
}
1070+
return value;
10581071
}
1059-
return r;
1072+
try valueError("int out of range for {s}", .{@typeName(T)});
1073+
unreachable;
10601074
}
10611075

10621076
// Create a pyton Int from any zig integer or float type. This will

0 commit comments

Comments
 (0)