Skip to content

Commit a96d3d0

Browse files
committed
objexcept: No more magic messages in exceptions, only exception arguments.
One of the reason for separate "message" (besides still unfulfilled desire to optimize memory usage) was apparent special handling of exception with messages by CPython. Well, the message is still just an exception argument, it just printed specially. Implement that with PRINT_EXC printing format.
1 parent e0f2979 commit a96d3d0

3 files changed

Lines changed: 28 additions & 32 deletions

File tree

py/obj.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ void mp_obj_print_exception(mp_obj_t exc) {
6262
}
6363
}
6464
}
65-
mp_obj_print(exc, PRINT_REPR);
65+
mp_obj_print(exc, PRINT_EXC);
6666
printf("\n");
6767
}
6868

py/obj.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,9 @@ typedef mp_obj_t (*mp_fun_var_t)(uint n, const mp_obj_t *);
141141
typedef mp_obj_t (*mp_fun_kw_t)(uint n, const mp_obj_t *, mp_map_t *);
142142

143143
typedef enum {
144-
PRINT_STR, PRINT_REPR
144+
PRINT_STR,
145+
PRINT_REPR,
146+
PRINT_EXC, // Special format for printing exception in unhandled exception message
145147
} mp_print_kind_t;
146148

147149
typedef void (*mp_print_fun_t)(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o, mp_print_kind_t kind);

py/objexcept.c

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,42 +11,34 @@
1111
#include "runtime.h"
1212
#include "runtime0.h"
1313

14-
// This is unified class for C-level and Python-level exceptions
15-
// Python-level exceptions have empty ->msg and all arguments are in
16-
// args tuple. C-level exceptions likely have ->msg set, and args is empty.
1714
typedef struct _mp_obj_exception_t {
1815
mp_obj_base_t base;
1916
mp_obj_t traceback; // a list object, holding (file,line,block) as numbers (not Python objects); a hack for now
20-
vstr_t *msg;
2117
mp_obj_tuple_t args;
2218
} mp_obj_exception_t;
2319

2420
// Instance of GeneratorExit exception - needed by generator.close()
2521
// This would belong to objgenerator.c, but to keep mp_obj_exception_t
2622
// definition module-private so far, have it here.
27-
const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, MP_OBJ_NULL, NULL, {{&mp_type_tuple}, 0}};
23+
const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, MP_OBJ_NULL, {{&mp_type_tuple}, 0}};
2824

2925
STATIC void mp_obj_exception_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
3026
mp_obj_exception_t *o = o_in;
31-
if (o->msg != NULL) {
32-
print(env, "%s: %s", qstr_str(o->base.type->name), vstr_str(o->msg));
33-
} else {
34-
// Yes, that's how CPython has it
35-
// TODO now that exceptions are classes and instances, I think this needs to be changed to match CPython
36-
if (kind == PRINT_REPR) {
37-
print(env, "%s", qstr_str(o->base.type->name));
38-
}
39-
if (kind == PRINT_STR) {
40-
if (o->args.len == 0) {
41-
print(env, "");
42-
return;
43-
} else if (o->args.len == 1) {
44-
mp_obj_print_helper(print, env, o->args.items[0], PRINT_STR);
45-
return;
46-
}
27+
if (kind == PRINT_REPR) {
28+
print(env, "%s", qstr_str(o->base.type->name));
29+
} else if (kind == PRINT_EXC) {
30+
print(env, "%s: ", qstr_str(o->base.type->name));
31+
}
32+
if (kind == PRINT_STR || kind == PRINT_EXC) {
33+
if (o->args.len == 0) {
34+
print(env, "");
35+
return;
36+
} else if (o->args.len == 1) {
37+
mp_obj_print_helper(print, env, o->args.items[0], PRINT_STR);
38+
return;
4739
}
48-
tuple_print(print, env, &o->args, kind);
4940
}
41+
tuple_print(print, env, &o->args, kind);
5042
}
5143

5244
STATIC mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
@@ -59,7 +51,6 @@ STATIC mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, uint n_args, uint n_
5951
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t, n_args);
6052
o->base.type = type;
6153
o->traceback = MP_OBJ_NULL;
62-
o->msg = NULL;
6354
o->args.base.type = &mp_type_tuple;
6455
o->args.len = n_args;
6556
memcpy(o->args.items, args, n_args * sizeof(mp_obj_t));
@@ -185,7 +176,7 @@ MP_DEFINE_EXCEPTION(Exception, BaseException)
185176
*/
186177

187178
mp_obj_t mp_obj_new_exception(const mp_obj_type_t *exc_type) {
188-
return mp_obj_new_exception_msg_varg(exc_type, NULL);
179+
return mp_obj_new_exception_args(exc_type, 0, NULL);
189180
}
190181

191182
mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, uint n_args, const mp_obj_t *args) {
@@ -202,22 +193,25 @@ mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char
202193
assert(exc_type->make_new == mp_obj_exception_make_new);
203194

204195
// make exception object
205-
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t, 0);
196+
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t, 1);
206197
o->base.type = exc_type;
207198
o->traceback = MP_OBJ_NULL;
208199
o->args.base.type = &mp_type_tuple;
209-
o->args.len = 0;
200+
o->args.len = 1;
210201

211202
if (fmt == NULL) {
212203
// no message
213-
o->msg = NULL;
204+
assert(0);
214205
} else {
215-
// render exception message
216-
o->msg = vstr_new();
206+
// render exception message and store as .args[0]
207+
// TODO: optimize bufferbloat
208+
vstr_t *vstr = vstr_new();
217209
va_list ap;
218210
va_start(ap, fmt);
219-
vstr_vprintf(o->msg, fmt, ap);
211+
vstr_vprintf(vstr, fmt, ap);
220212
va_end(ap);
213+
o->args.items[0] = mp_obj_new_str((byte*)vstr->buf, vstr->len, false);
214+
vstr_free(vstr);
221215
}
222216

223217
return o;

0 commit comments

Comments
 (0)