@@ -100,7 +100,7 @@ pub inline fn errorSetObject(exc: *Object, value: *Object) void {
100100// String formatting is done using zig's std.fmt.
101101// Does not steal a reference to exc.
102102// This uses the global python allocator to allocate the message
103- pub inline fn errorFormat (exc : * Object , format : []const u8 , args : anytype ) Error ! void {
103+ pub inline fn errorFormat (exc : * Object , comptime format : []const u8 , args : anytype ) Error ! void {
104104 if (comptime args .len == 0 ) {
105105 c .PyErr_SetString (@ptrCast (exc ), @ptrCast (format ));
106106 return error .PyError ;
@@ -112,51 +112,51 @@ pub inline fn errorFormat(exc: *Object, format: []const u8, args: anytype) Error
112112}
113113
114114// Helper that is the equivalent to `TypeError(msg)`
115- pub inline fn typeError (msg : [:0 ]const u8 , args : anytype ) ! void {
115+ pub inline fn typeError (comptime msg : [:0 ]const u8 , args : anytype ) ! void {
116116 return errorFormat (@ptrCast (c .PyExc_TypeError ), msg , args );
117117}
118118
119- pub inline fn typeErrorObject (comptime value : anytype , msg : [:0 ]const u8 , args : anytype ) @TypeOf (value ) {
119+ pub inline fn typeErrorObject (comptime value : anytype , comptime msg : [:0 ]const u8 , args : anytype ) @TypeOf (value ) {
120120 typeError (msg , args ) catch {};
121121 return value ;
122122}
123123
124124// Helper that is the equivalent to `SystemError(msg)`
125- pub inline fn systemError (msg : [:0 ]const u8 , args : anytype ) ! void {
125+ pub inline fn systemError (comptime msg : [:0 ]const u8 , args : anytype ) ! void {
126126 return errorFormat (@ptrCast (c .PyExc_SystemError ), msg , args );
127127}
128128
129- pub inline fn systemErrorObject (comptime value : anytype , msg : [:0 ]const u8 , args : anytype ) @TypeOf (value ) {
129+ pub inline fn systemErrorObject (comptime value : anytype , comptime msg : [:0 ]const u8 , args : anytype ) @TypeOf (value ) {
130130 systemError (msg , args ) catch {};
131131 return value ;
132132}
133133
134134// Helper that is the equivalent to `ValueError(msg)`
135- pub inline fn valueError (msg : [:0 ]const u8 , args : anytype ) ! void {
135+ pub inline fn valueError (comptime msg : [:0 ]const u8 , args : anytype ) ! void {
136136 return errorFormat (@ptrCast (c .PyExc_ValueError ), msg , args );
137137}
138138
139- pub inline fn valueErrorObject (comptime value : anytype , msg : [:0 ]const u8 , args : anytype ) @TypeOf (value ) {
139+ pub inline fn valueErrorObject (comptime value : anytype , comptime msg : [:0 ]const u8 , args : anytype ) @TypeOf (value ) {
140140 valueError (msg , args ) catch {};
141141 return value ;
142142}
143143
144144// Helper that is the equivalent to `AttributeError(msg)`
145- pub inline fn attributeError (msg : [:0 ]const u8 , args : anytype ) ! void {
145+ pub inline fn attributeError (comptime msg : [:0 ]const u8 , args : anytype ) ! void {
146146 return errorFormat (@ptrCast (c .PyExc_AttributeError ), msg , args );
147147}
148148
149- pub inline fn attributeErrorObject (comptime value : anytype , msg : [:0 ]const u8 , args : anytype ) @TypeOf (value ) {
149+ pub inline fn attributeErrorObject (comptime value : anytype , comptime msg : [:0 ]const u8 , args : anytype ) @TypeOf (value ) {
150150 attributeError (msg , args ) catch {};
151151 return value ;
152152}
153153
154154// Helper that is the equivalent to `KeyError(msg)`
155- pub inline fn keyError (msg : [:0 ]const u8 , args : anytype ) ! void {
155+ pub inline fn keyError (comptime msg : [:0 ]const u8 , args : anytype ) ! void {
156156 return errorFormat (@ptrCast (c .PyExc_KeyError ), msg , args );
157157}
158158
159- pub inline fn keyErrorObject (comptime value : anytype , msg : [:0 ]const u8 , args : anytype ) @TypeOf (value ) {
159+ pub inline fn keyErrorObject (comptime value : anytype , comptime msg : [:0 ]const u8 , args : anytype ) @TypeOf (value ) {
160160 keyError (msg , args ) catch {};
161161 return value ;
162162}
@@ -412,6 +412,16 @@ pub inline fn canCastToOptionalObjectPtr(comptime T: type) bool {
412412 };
413413}
414414
415+ // Check at comptime that a zig tuple of arguments can all be casted to *Object
416+ pub inline fn checkArgsAreObjects (comptime label : []const u8 , args : anytype ) void {
417+ inline for (args , 0.. ) | arg , i | {
418+ const ArgType = @TypeOf (arg );
419+ if (comptime ! canCastToObject (ArgType )) {
420+ @compileError (std .fmt .comptimePrint ("{s} args must be castable to *Object, got {} for argument {}" , .{ label , ArgType , i }));
421+ }
422+ }
423+ }
424+
415425// Object Protocol
416426pub inline fn ObjectProtocol (comptime T : type ) type {
417427 return struct {
@@ -772,7 +782,7 @@ pub inline fn ObjectProtocol(comptime T: type) type {
772782 }
773783
774784 // Format
775- pub fn format (
785+ pub fn formatObject (
776786 self : * const T ,
777787 comptime fmt : []const u8 ,
778788 options : std.fmt.FormatOptions ,
@@ -788,6 +798,8 @@ pub inline fn ObjectProtocol(comptime T: type) type {
788798 try writer .print ("{s}" , .{s .data ()});
789799 }
790800 }
801+ // Use custom format if defined
802+ pub const format = if (@hasDecl (T , "format" )) T .format else formatObject ;
791803
792804 // Add the mapping protocol
793805 pub usingnamespace MappingProtocol (T );
@@ -876,6 +888,7 @@ pub inline fn CallProtocol(comptime T: type) type {
876888 // Calls PyObject_CallNoArgs. PyObject_CallOneArg, or
877889 // Return the result of the call on success, or raise an exception and return NULL on failure.
878890 pub inline fn callArgsUnchecked (self : * T , args : anytype ) ? * Object {
891+ checkArgsAreObjects ("callArgs" , args );
879892 return @ptrCast (switch (comptime args .len ) {
880893 0 = > c .PyObject_CallNoArgs (@ptrCast (self )),
881894 1 = > c .PyObject_CallOneArg (@ptrCast (self ), @ptrCast (args [0 ])),
@@ -919,6 +932,7 @@ pub inline fn CallProtocol(comptime T: type) type {
919932
920933 // Same as callMethod with no error checking
921934 pub inline fn callMethodUnchecked (self : * T , name : * Str , args : anytype ) ? * Object {
935+ checkArgsAreObjects ("callMethod" , args );
922936 return @ptrCast (switch (comptime args .len ) {
923937 0 = > c .PyObject_CallMethodNoArgs (@ptrCast (self ), @ptrCast (name )),
924938 1 = > c .PyObject_CallMethodOneArg (@ptrCast (self ), @ptrCast (name ), @ptrCast (args [0 ])),
@@ -944,6 +958,7 @@ pub inline fn CallProtocol(comptime T: type) type {
944958 }
945959
946960 pub inline fn vectorCallUnchecked (self : * T , args : anytype , kwnames : ? * Object ) ? * Object {
961+ checkArgsAreObjects ("vectorCall" , args );
947962 return @ptrCast (c .PyObject_Vectorcall (@ptrCast (self ), args , args .len , kwnames ));
948963 }
949964
@@ -955,6 +970,7 @@ pub inline fn CallProtocol(comptime T: type) type {
955970 }
956971
957972 pub inline fn vectorCallMethodUnchecked (self : * T , name : * Str , args : anytype , kwnames : ? * Object ) ? * Object {
973+ checkArgsAreObjects ("vectorCallMethod" , args );
958974 return @ptrCast (c .PyObject_Vectorcall (@ptrCast (name ), .{self } + args , args .len + 1 , kwnames ));
959975 }
960976 };
0 commit comments