py/warning: Support categories for warnings.

Python defines warnings as belonging to categories, where category is a
warning type (descending from exception type). This is useful, as e.g.
allows to disable warnings selectively and provide user-defined warning
types.  So, implement this in MicroPython, except that categories are
represented just with strings.  However, enough hooks are left to implement
categories differently per-port (e.g. as types), without need to patch each
and every usage.
This commit is contained in:
Paul Sokolovsky 2018-12-21 14:20:55 +03:00 committed by Damien George
parent 86f06d6a87
commit 2f5d113fad
8 changed files with 32 additions and 8 deletions

View File

@ -1454,7 +1454,7 @@ STATIC mp_obj_t lwip_getaddrinfo(size_t n_args, const mp_obj_t *args) {
&& (type == 0 || type == MOD_NETWORK_SOCK_STREAM)
&& proto == 0
&& flags == 0)) {
mp_warning("unsupported getaddrinfo constraints");
mp_warning(MP_WARN_CAT(RuntimeWarning), "unsupported getaddrinfo constraints");
}
}

View File

@ -36,6 +36,7 @@
#define MICROPY_FLOAT_HIGH_QUALITY_HASH (1)
#define MICROPY_ENABLE_SCHEDULER (1)
#define MICROPY_READER_VFS (1)
#define MICROPY_WARNINGS_CATEGORY (1)
#define MICROPY_MODULE_GETATTR (1)
#define MICROPY_PY_DELATTR_SETATTR (1)
#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1)

View File

@ -288,7 +288,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv);
STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) {
(void)n_args; // always 4
mp_warning("setsockopt() not implemented");
mp_warning(MP_WARN_CAT(RuntimeWarning), "setsockopt() not implemented");
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt);

View File

@ -598,6 +598,11 @@ typedef long long mp_longint_impl_t;
#define MICROPY_WARNINGS (0)
#endif
// Whether to support warning categories
#ifndef MICROPY_WARNINGS_CATEGORY
#define MICROPY_WARNINGS_CATEGORY (0)
#endif
// This macro is used when printing runtime warnings and errors
#ifndef MICROPY_ERROR_PRINTER
#define MICROPY_ERROR_PRINTER (&mp_plat_print)
@ -1508,4 +1513,15 @@ typedef double mp_float_t;
#endif
#endif
// Warning categories are by default implemented as strings, though
// hook is left for a port to define them as something else.
#if MICROPY_WARNINGS_CATEGORY
# ifndef MP_WARN_CAT
# define MP_WARN_CAT(x) #x
# endif
#else
# undef MP_WARN_CAT
# define MP_WARN_CAT(x) (NULL)
#endif
#endif // MICROPY_INCLUDED_PY_MPCONFIG_H

View File

@ -202,7 +202,7 @@ bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) {
str_cmp_err:
#if MICROPY_PY_STR_BYTES_CMP_WARN
if (MP_OBJ_IS_TYPE(o1, &mp_type_bytes) || MP_OBJ_IS_TYPE(o2, &mp_type_bytes)) {
mp_warning("Comparison between bytes and str");
mp_warning(MP_WARN_CAT(BytesWarning), "Comparison between bytes and str");
}
#endif
return false;

View File

@ -179,7 +179,9 @@ void mp_native_raise(mp_obj_t o);
#define mp_sys_argv (MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_sys_argv_obj)))
#if MICROPY_WARNINGS
void mp_warning(const char *msg, ...);
#ifndef mp_warning
void mp_warning(const char *category, const char *msg, ...);
#endif
#else
#define mp_warning(...)
#endif

View File

@ -1116,7 +1116,7 @@ unwind_return:
mp_uint_t unum = *ip;
mp_obj_t obj;
if (unum == 2) {
mp_warning("exception chaining not supported");
mp_warning(NULL, "exception chaining not supported");
// ignore (pop) "from" argument
sp--;
}

View File

@ -32,10 +32,15 @@
#if MICROPY_WARNINGS
void mp_warning(const char *msg, ...) {
void mp_warning(const char *category, const char *msg, ...) {
if (category == NULL) {
category = "Warning";
}
mp_print_str(MICROPY_ERROR_PRINTER, category);
mp_print_str(MICROPY_ERROR_PRINTER, ": ");
va_list args;
va_start(args, msg);
mp_print_str(MICROPY_ERROR_PRINTER, "Warning: ");
mp_vprintf(MICROPY_ERROR_PRINTER, msg, args);
mp_print_str(MICROPY_ERROR_PRINTER, "\n");
va_end(args);
@ -43,7 +48,7 @@ void mp_warning(const char *msg, ...) {
void mp_emitter_warning(pass_kind_t pass, const char *msg) {
if (pass == MP_PASS_CODE_SIZE) {
mp_warning(msg, NULL);
mp_warning(NULL, msg);
}
}