summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
authorPaul Sokolovsky <pfalcon@users.sourceforge.net>2014-12-06 14:29:09 +0200
committerDamien George <damien.p.george@gmail.com>2014-12-08 20:25:49 +0000
commit46c3ab20049af16e97863e90e5761fae329f872a (patch)
treecbe6230dcad6972d7d50c6d08c4e4c4da215abb1 /py
parentd0caaadaeea48e8f76dca3125a2dea3465a58416 (diff)
downloadmicropython-46c3ab20049af16e97863e90e5761fae329f872a.tar.gz
micropython-46c3ab20049af16e97863e90e5761fae329f872a.zip
modsys: Add sys.print_exception(exc, file=sys.stdout) function.
The function is modeled after traceback.print_exception(), but unbloated, and put into existing module to save overhead on adding another module. Compliant traceback.print_exception() is intended to be implemented in micropython-lib in terms of sys.print_exception(). This change required refactoring mp_obj_print_exception() to take pfenv_t interface arguments. Addresses #751.
Diffstat (limited to 'py')
-rw-r--r--py/modsys.c27
-rw-r--r--py/obj.c16
-rw-r--r--py/obj.h2
-rw-r--r--py/pfenv.h3
-rw-r--r--py/qstrdefs.h1
5 files changed, 40 insertions, 9 deletions
diff --git a/py/modsys.c b/py/modsys.c
index d9be7d1bc1..06bd4c80e1 100644
--- a/py/modsys.c
+++ b/py/modsys.c
@@ -38,6 +38,8 @@
#include "objstr.h"
#include "mpz.h"
#include "objint.h"
+#include "pfenv.h"
+#include "stream.h"
#if MICROPY_PY_SYS
@@ -78,6 +80,25 @@ STATIC mp_obj_t mp_sys_exit(mp_uint_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_exit_obj, 0, 1, mp_sys_exit);
+STATIC mp_obj_t mp_sys_print_exception(mp_uint_t n_args, const mp_obj_t *args) {
+ #if MICROPY_PY_IO
+ mp_obj_t stream_obj = &mp_sys_stdout_obj;
+ if (n_args > 1) {
+ stream_obj = args[1];
+ }
+
+ pfenv_t pfenv;
+ pfenv.data = stream_obj;
+ pfenv.print_strn = (void (*)(void *, const char *, mp_uint_t))mp_stream_write;
+ mp_obj_print_exception((void (*)(void *env, const char *fmt, ...))pfenv_printf, &pfenv, args[0]);
+ #else
+ mp_obj_print_exception(printf_wrapper, NULL, args[0]);
+ #endif
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_print_exception_obj, 1, 2, mp_sys_print_exception);
+
STATIC const mp_map_elem_t mp_module_sys_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_sys) },
@@ -118,6 +139,12 @@ STATIC const mp_map_elem_t mp_module_sys_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_stdout), (mp_obj_t)&mp_sys_stdout_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_stderr), (mp_obj_t)&mp_sys_stderr_obj },
#endif
+
+ /*
+ * Extensions to CPython
+ */
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_print_exception), (mp_obj_t)&mp_sys_print_exception_obj },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_sys_globals, mp_module_sys_globals_table);
diff --git a/py/obj.c b/py/obj.c
index c869a65465..d2801a3968 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -85,31 +85,31 @@ void mp_obj_print(mp_obj_t o_in, mp_print_kind_t kind) {
}
// helper function to print an exception with traceback
-void mp_obj_print_exception(mp_obj_t exc) {
+void mp_obj_print_exception(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t exc) {
if (mp_obj_is_exception_instance(exc)) {
mp_uint_t n, *values;
mp_obj_exception_get_traceback(exc, &n, &values);
if (n > 0) {
assert(n % 3 == 0);
- printf("Traceback (most recent call last):\n");
+ print(env, "Traceback (most recent call last):\n");
for (int i = n - 3; i >= 0; i -= 3) {
#if MICROPY_ENABLE_SOURCE_LINE
- printf(" File \"%s\", line %d", qstr_str(values[i]), (int)values[i + 1]);
+ print(env, " File \"%s\", line %d", qstr_str(values[i]), (int)values[i + 1]);
#else
- printf(" File \"%s\"", qstr_str(values[i]));
+ print(env, " File \"%s\"", qstr_str(values[i]));
#endif
// the block name can be NULL if it's unknown
qstr block = values[i + 2];
if (block == MP_QSTR_NULL) {
- printf("\n");
+ print(env, "\n");
} else {
- printf(", in %s\n", qstr_str(block));
+ print(env, ", in %s\n", qstr_str(block));
}
}
}
}
- mp_obj_print(exc, PRINT_EXC);
- printf("\n");
+ mp_obj_print_helper(print, env, exc, PRINT_EXC);
+ print(env, "\n");
}
bool mp_obj_is_true(mp_obj_t arg) {
diff --git a/py/obj.h b/py/obj.h
index 3721bea925..6db76405e9 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -418,7 +418,7 @@ mp_obj_t mp_instance_cast_to_native_base(mp_const_obj_t self_in, mp_const_obj_t
void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind);
void mp_obj_print(mp_obj_t o, mp_print_kind_t kind);
-void mp_obj_print_exception(mp_obj_t exc);
+void mp_obj_print_exception(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t exc);
bool mp_obj_is_true(mp_obj_t arg);
diff --git a/py/pfenv.h b/py/pfenv.h
index fea2c883e9..98c1885f35 100644
--- a/py/pfenv.h
+++ b/py/pfenv.h
@@ -52,3 +52,6 @@ int pfenv_print_float(const pfenv_t *pfenv, mp_float_t f, char fmt, int flags, c
//int pfenv_vprintf(const pfenv_t *pfenv, const char *fmt, va_list args);
int pfenv_printf(const pfenv_t *pfenv, const char *fmt, ...);
+
+// Wrapper for system printf
+void printf_wrapper(void *env, const char *fmt, ...);
diff --git a/py/qstrdefs.h b/py/qstrdefs.h
index 449f44d3bc..f183c256fb 100644
--- a/py/qstrdefs.h
+++ b/py/qstrdefs.h
@@ -403,6 +403,7 @@ Q(version_info)
#if MICROPY_PY_SYS_MAXSIZE
Q(maxsize)
#endif
+Q(print_exception)
#endif
#if MICROPY_PY_STRUCT