@@ -34,6 +34,18 @@ pub inline fn finalize() !void {
3434// The callee must set the python error or python will raise a SystemError.
3535pub const Error = error {PyError };
3636
37+ // Print a message to stdout. All *Objects will be formated using "str".
38+ pub fn print (comptime format : []const u8 , args : anytype ) Error ! void {
39+ // TODO: Use a lock?
40+ const stdout = std .io .getStdOut ().writer ();
41+ stdout .print (format , args ) catch {
42+ if (errorOccurred () != null ) {
43+ return error .PyError ;
44+ }
45+ try systemError ("print error" , .{});
46+ };
47+ }
48+
3749// Test whether the error indicator is set. If set, return the exception type (the first
3850// argument to the last call to one of the PyErr_Set* functions or to PyErr_Restore()).
3951// If not set, return NULL. You do not own a reference to the return value, so you do not
@@ -93,7 +105,7 @@ pub inline fn errorFormat(exc: *Object, format: []const u8, args: anytype) Error
93105 c .PyErr_SetString (@ptrCast (exc ), @ptrCast (format ));
94106 return error .PyError ;
95107 }
96- const msg = try Str .format (format , args ); // TODO: This squashes the error
108+ const msg = try Str .new (format , args ); // TODO: This squashes the error
97109 defer msg .decref ();
98110 c .PyErr_SetObject (@ptrCast (exc ), @ptrCast (msg ));
99111 return error .PyError ;
@@ -757,6 +769,24 @@ pub inline fn ObjectProtocol(comptime T: type) type {
757769 return @ptrCast (c .PyObject_RichCompare (@constCast (@ptrCast (self )), @constCast (@ptrCast (other )), op ));
758770 }
759771
772+ // Format
773+ pub fn format (
774+ self : * const T ,
775+ comptime fmt : []const u8 ,
776+ options : std.fmt.FormatOptions ,
777+ writer : anytype ,
778+ ) ! void {
779+ _ = fmt ;
780+ _ = options ;
781+ if (comptime T == Str ) {
782+ try writer .print ("{s}" , .{self .data ()});
783+ } else {
784+ const s = try str (@constCast (self ));
785+ defer s .decref ();
786+ try writer .print ("{s}" , .{s .data ()});
787+ }
788+ }
789+
760790 // Add the mapping protocol
761791 pub usingnamespace MappingProtocol (T );
762792
@@ -1386,18 +1416,22 @@ pub const Str = extern struct {
13861416 return error .PyError ;
13871417 }
13881418
1389- // Format a string using zig alloc print.
1390- pub inline fn format (comptime msg : []const u8 , args : anytype ) Error ! * Str {
1391- return formatAlloc (allocator , msg , args );
1419+ // Create a new string using zig alloc print. If no format args are provided
1420+ // This is equivalent to Str.fromSlice
1421+ pub inline fn new (comptime msg : []const u8 , args : anytype ) Error ! * Str {
1422+ return newAlloc (allocator , msg , args );
13921423 }
13931424
1394- pub inline fn formatAlloc (alloc : std.mem.Allocator , comptime msg : []const u8 , args : anytype ) Error ! * Str {
1425+ pub inline fn newAlloc (alloc : std.mem.Allocator , comptime msg : []const u8 , args : anytype ) Error ! * Str {
1426+ if (comptime args .len == 0 ) {
1427+ return fromSlice (msg );
1428+ }
13951429 const str = std .fmt .allocPrint (alloc , msg , args ) catch {
13961430 try memoryError (); // TODO: This squashes the error
13971431 };
13981432 defer allocator .free (str );
13991433 // TODO: is there a way to avoid a copy?
1400- return try Str . fromSlice (str );
1434+ return try fromSlice (str );
14011435 }
14021436
14031437 // A combination of PyUnicode_FromString() and PyUnicode_InternInPlace(),
@@ -1417,9 +1451,9 @@ pub const Str = extern struct {
14171451 }
14181452
14191453 // Return data as utf8
1420- pub inline fn data (self : * Str ) [:0 ]const u8 {
1454+ pub inline fn data (self : * const Str ) [:0 ]const u8 {
14211455 std .debug .assert (Str .check (@ptrCast (self )));
1422- return std .mem .span (c .PyUnicode_AsUTF8 (@ptrCast (self )));
1456+ return std .mem .span (c .PyUnicode_AsUTF8 (@constCast ( @ ptrCast (self ) )));
14231457 }
14241458};
14251459
0 commit comments