Skip to content

Commit c47c495

Browse files
authored
Merge pull request #1329 from notro/oserror_errno
Support OSError subclasses and attributes
2 parents f6c73b3 + 704d0c6 commit c47c495

File tree

4 files changed

+66
-38
lines changed

4 files changed

+66
-38
lines changed

ports/atmel-samd/mpconfigport.h

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,18 @@ typedef long mp_off_t;
163163
#define MICROPY_PY_IO (0)
164164
#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0)
165165
#define MICROPY_PY_SYS_EXC_INFO (0)
166+
#define MICROPY_PY_UERRNO_LIST \
167+
X(EPERM) \
168+
X(ENOENT) \
169+
X(EIO) \
170+
X(EAGAIN) \
171+
X(ENOMEM) \
172+
X(EACCES) \
173+
X(EEXIST) \
174+
X(ENODEV) \
175+
X(EISDIR) \
176+
X(EINVAL) \
177+
166178
#endif
167179

168180
#ifdef SAMD51
@@ -179,6 +191,7 @@ typedef long mp_off_t;
179191
#define MICROPY_PY_IO (1)
180192
#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1)
181193
#define MICROPY_PY_SYS_EXC_INFO (1)
194+
// MICROPY_PY_UERRNO_LIST - Use the default
182195
#endif
183196

184197
#ifdef LONGINT_IMPL_NONE
@@ -405,18 +418,6 @@ extern const struct _mp_obj_module_t wiznet_module;
405418
{ MP_OBJ_NEW_QSTR(MP_QSTR_uheap),(mp_obj_t)&uheap_module }, \
406419
{ MP_OBJ_NEW_QSTR(MP_QSTR_ustack),(mp_obj_t)&ustack_module }
407420

408-
#define MICROPY_PY_UERRNO_LIST \
409-
X(EPERM) \
410-
X(ENOENT) \
411-
X(EIO) \
412-
X(EAGAIN) \
413-
X(ENOMEM) \
414-
X(EACCES) \
415-
X(EEXIST) \
416-
X(ENODEV) \
417-
X(EISDIR) \
418-
X(EINVAL) \
419-
420421
// We need to provide a declaration/definition of alloca()
421422
#include <alloca.h>
422423

py/moduerrno.c

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -136,19 +136,28 @@ const char* mp_errno_to_str(mp_obj_t errno_val) {
136136
#endif //MICROPY_PY_UERRNO
137137

138138

139-
// For commonly encountered errors, return human readable strings
140-
const compressed_string_t* mp_common_errno_to_str(mp_obj_t errno_val) {
141-
if (MP_OBJ_IS_SMALL_INT(errno_val)) {
142-
switch (MP_OBJ_SMALL_INT_VALUE(errno_val)) {
143-
case EPERM: return translate("Permission denied");
144-
case ENOENT: return translate("No such file/directory");
145-
case EIO: return translate("Input/output error");
146-
case EACCES: return translate("Permission denied");
147-
case EEXIST: return translate("File exists");
148-
case ENODEV: return translate("Unsupported operation");
149-
case EINVAL: return translate("Invalid argument");
150-
case EROFS: return translate("Read-only filesystem");
151-
}
139+
// For commonly encountered errors, return human readable strings, otherwise try errno name
140+
const char *mp_common_errno_to_str(mp_obj_t errno_val, char *buf, size_t len) {
141+
if (!MP_OBJ_IS_SMALL_INT(errno_val)) {
142+
return NULL;
143+
}
144+
145+
const compressed_string_t* desc = NULL;
146+
switch (MP_OBJ_SMALL_INT_VALUE(errno_val)) {
147+
case EPERM: desc = translate("Permission denied"); break;
148+
case ENOENT: desc = translate("No such file/directory"); break;
149+
case EIO: desc = translate("Input/output error"); break;
150+
case EACCES: desc = translate("Permission denied"); break;
151+
case EEXIST: desc = translate("File exists"); break;
152+
case ENODEV: desc = translate("Unsupported operation"); break;
153+
case EINVAL: desc = translate("Invalid argument"); break;
154+
case EROFS: desc = translate("Read-only filesystem"); break;
152155
}
153-
return NULL;
156+
if (desc != NULL && desc->length <= len) {
157+
decompress(desc, buf);
158+
return buf;
159+
}
160+
161+
const char *msg = mp_errno_to_str(errno_val);
162+
return msg[0] != '\0' ? msg : NULL;
154163
}

py/mperrno.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@
141141
#endif
142142

143143
const char* mp_errno_to_str(mp_obj_t errno_val);
144-
// For commonly encountered errors, return compressed human readable strings
145-
const compressed_string_t* mp_common_errno_to_str(mp_obj_t errno_val);
144+
const char *mp_common_errno_to_str(mp_obj_t errno_val, char *buf, size_t len);
146145

147146
#endif // MICROPY_INCLUDED_PY_MPERRNO_H

py/objexcept.c

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -114,17 +114,11 @@ void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kin
114114
return;
115115
} else if (o->args->len == 1) {
116116
// try to provide a nice OSError error message
117-
if (o->base.type == &mp_type_OSError && MP_OBJ_IS_SMALL_INT(o->args->items[0])) {
118-
const compressed_string_t* common = mp_common_errno_to_str(o->args->items[0]);
119-
const char* msg;
117+
if (MP_OBJ_IS_SMALL_INT(o->args->items[0]) &&
118+
mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(o->base.type), MP_OBJ_FROM_PTR(&mp_type_OSError))) {
120119
char decompressed[50];
121-
if (common != NULL && common->length <= 50) {
122-
decompress(common, decompressed);
123-
msg = decompressed;
124-
} else {
125-
msg = mp_errno_to_str(o->args->items[0]);
126-
}
127-
if (msg[0] != '\0') {
120+
const char *msg = mp_common_errno_to_str(o->args->items[0], decompressed, sizeof(decompressed));
121+
if (msg != NULL) {
128122
mp_printf(print, "[Errno " INT_FMT "] %s", MP_OBJ_SMALL_INT_VALUE(o->args->items[0]), msg);
129123
return;
130124
}
@@ -215,6 +209,31 @@ void mp_obj_exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
215209
dest[0] = MP_OBJ_FROM_PTR(self->args);
216210
} else if (self->base.type == &mp_type_StopIteration && attr == MP_QSTR_value) {
217211
dest[0] = mp_obj_exception_get_value(self_in);
212+
#if MICROPY_CPYTHON_COMPAT
213+
} else if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(self->base.type), MP_OBJ_FROM_PTR(&mp_type_OSError))) {
214+
if (attr == MP_QSTR_errno) {
215+
dest[0] = mp_obj_exception_get_value(self_in);
216+
} else if (attr == MP_QSTR_strerror) {
217+
if (self->args->len > 1) {
218+
dest[0] = self->args->items[1];
219+
} else if (self->args->len > 0) {
220+
char decompressed[50];
221+
const char *msg = mp_common_errno_to_str(self->args->items[0], decompressed, sizeof(decompressed));
222+
if (msg != NULL) {
223+
dest[0] = mp_obj_new_str(msg, strlen(msg));
224+
} else {
225+
dest[0] = mp_const_none;
226+
}
227+
} else {
228+
dest[0] = mp_const_none;
229+
}
230+
} else if (attr == MP_QSTR_filename) {
231+
dest[0] = self->args->len > 2 ? self->args->items[2] : mp_const_none;
232+
// skip winerror
233+
} else if (attr == MP_QSTR_filename2) {
234+
dest[0] = self->args->len > 4 ? self->args->items[4] : mp_const_none;
235+
}
236+
#endif
218237
}
219238
}
220239

0 commit comments

Comments
 (0)