From f439f024924cc93bea3942b3f01a45289bec53df Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 25 Oct 2023 15:36:23 -0700 Subject: [PATCH 1/2] Add `warnings` and warn about displayio changes Follow up to #8493 --- locale/circuitpython.pot | 73 +++++++++++------- py/circuitpy_defns.mk | 8 +- py/circuitpy_mpconfig.mk | 3 + py/modbuiltins.c | 4 + py/mpstate.h | 8 ++ py/obj.h | 4 + py/objexcept.c | 6 +- py/objmodule.c | 35 +++++++++ py/runtime.c | 23 ++++++ shared-bindings/warnings/__init__.c | 112 ++++++++++++++++++++++++++++ shared-bindings/warnings/__init__.h | 39 ++++++++++ shared-module/warnings/__init__.c | 73 ++++++++++++++++++ shared-module/warnings/__init__.h | 29 +++++++ 13 files changed, 384 insertions(+), 33 deletions(-) create mode 100644 shared-bindings/warnings/__init__.c create mode 100644 shared-bindings/warnings/__init__.h create mode 100644 shared-module/warnings/__init__.c create mode 100644 shared-module/warnings/__init__.h diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 98a8d01e4f..0aaca6ce69 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -175,19 +175,23 @@ msgstr "" msgid "%q length must be >= %d" msgstr "" +#: py/objmodule.c py/runtime.c +msgid "%q moved from %q to %q" +msgstr "" + #: py/argcheck.c msgid "%q must be %d" msgstr "" -#: py/argcheck.c shared-bindings/displayio/Bitmap.c -#: shared-bindings/displayio/Display.c +#: py/argcheck.c shared-bindings/busdisplay/BusDisplay.c +#: shared-bindings/displayio/Bitmap.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/is31fl3741/FrameBuffer.c #: shared-bindings/rgbmatrix/RGBMatrix.c msgid "%q must be %d-%d" msgstr "" -#: shared-bindings/displayio/Display.c +#: shared-bindings/busdisplay/BusDisplay.c msgid "%q must be 1 when %q is True" msgstr "" @@ -212,6 +216,10 @@ msgstr "" msgid "%q must be a bytearray or array of type 'h', 'H', 'b', or 'B'" msgstr "" +#: shared-bindings/warnings/__init__.c +msgid "%q must be a subclass of %q" +msgstr "" + #: ports/espressif/common-hal/analogbufio/BufferedIn.c msgid "%q must be array of type 'H'" msgstr "" @@ -247,6 +255,10 @@ msgstr "" msgid "%q out of range" msgstr "" +#: py/objmodule.c py/runtime.c +msgid "%q renamed %q" +msgstr "" + #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "" @@ -434,8 +446,8 @@ msgstr "" msgid ", in %q\n" msgstr "" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c +#: shared-bindings/busdisplay/BusDisplay.c +#: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid ".show(x) removed. Use .root_group = x" msgstr "" @@ -625,7 +637,7 @@ msgstr "" msgid "Baudrate not supported by peripheral" msgstr "" -#: shared-module/displayio/Display.c +#: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c msgid "Below minimum frame rate" msgstr "" @@ -658,7 +670,7 @@ msgstr "" msgid "Both pins must support hardware interrupts" msgstr "" -#: shared-bindings/displayio/Display.c +#: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Brightness not adjustable" msgstr "" @@ -695,7 +707,8 @@ msgstr "" msgid "Buffer too short by %d bytes" msgstr "" -#: ports/cxd56/common-hal/camera/Camera.c shared-bindings/displayio/Display.c +#: ports/cxd56/common-hal/camera/Camera.c +#: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/struct/__init__.c shared-module/struct/__init__.c msgid "Buffer too small" @@ -705,10 +718,10 @@ msgstr "" msgid "Buffers must be same size" msgstr "" -#: ports/atmel-samd/common-hal/paralleldisplay/ParallelBus.c -#: ports/espressif/common-hal/paralleldisplay/ParallelBus.c -#: ports/nrf/common-hal/paralleldisplay/ParallelBus.c -#: ports/raspberrypi/common-hal/paralleldisplay/ParallelBus.c +#: ports/atmel-samd/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/nrf/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/raspberrypi/common-hal/paralleldisplaybus/ParallelBus.c #, c-format msgid "Bus pin %d is already in use" msgstr "" @@ -893,8 +906,8 @@ msgstr "" msgid "DAC already in use" msgstr "" -#: ports/atmel-samd/common-hal/paralleldisplay/ParallelBus.c -#: ports/nrf/common-hal/paralleldisplay/ParallelBus.c +#: ports/atmel-samd/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/nrf/common-hal/paralleldisplaybus/ParallelBus.c msgid "Data 0 pin must be byte aligned" msgstr "" @@ -924,13 +937,13 @@ msgstr "" msgid "Device in use" msgstr "" -#: shared-bindings/displayio/Display.c +#: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Display must have a 16 bit colorspace." msgstr "" -#: shared-bindings/displayio/Display.c -#: shared-bindings/displayio/EPaperDisplay.c +#: shared-bindings/busdisplay/BusDisplay.c +#: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Display rotation must be in 90 degree increments" msgstr "" @@ -1104,7 +1117,7 @@ msgid "Generic Failure" msgstr "" #: shared-bindings/framebufferio/FramebufferDisplay.c -#: shared-module/displayio/Display.c +#: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c msgid "Group already used" msgstr "" @@ -1202,7 +1215,7 @@ msgstr "" msgid "Internal define error" msgstr "" -#: ports/espressif/common-hal/paralleldisplay/ParallelBus.c +#: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c #: shared-module/os/getenv.c msgid "Internal error" msgstr "" @@ -1225,7 +1238,7 @@ msgstr "" #: ports/raspberrypi/bindings/picodvi/Framebuffer.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c -#: shared-bindings/displayio/EPaperDisplay.c +#: shared-bindings/epaperdisplay/EPaperDisplay.c msgid "Invalid %q" msgstr "" @@ -1428,9 +1441,10 @@ msgstr "" #: ports/mimxrt10xx/common-hal/busio/SPI.c #: ports/mimxrt10xx/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: ports/raspberrypi/common-hal/busio/UART.c ports/stm/common-hal/busio/SPI.c -#: ports/stm/common-hal/busio/UART.c shared-bindings/displayio/FourWire.c -#: shared-bindings/displayio/I2CDisplay.c -#: shared-bindings/paralleldisplay/ParallelBus.c shared-module/bitbangio/SPI.c +#: ports/stm/common-hal/busio/UART.c shared-bindings/fourwire/FourWire.c +#: shared-bindings/i2cdisplaybus/I2CDisplayBus.c +#: shared-bindings/paralleldisplaybus/ParallelBus.c +#: shared-module/bitbangio/SPI.c msgid "No %q pin" msgstr "" @@ -1562,7 +1576,7 @@ msgstr "" msgid "Not playing" msgstr "" -#: ports/espressif/common-hal/paralleldisplay/ParallelBus.c +#: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c #, c-format msgid "Number of data_pins must be 8 or 16, not %d" msgstr "" @@ -1852,7 +1866,7 @@ msgstr "" msgid "Reconnecting" msgstr "" -#: shared-bindings/displayio/EPaperDisplay.c +#: shared-bindings/epaperdisplay/EPaperDisplay.c msgid "Refresh too soon" msgstr "" @@ -1953,7 +1967,7 @@ msgstr "" msgid "Source and destination buffers must be the same length" msgstr "" -#: shared-bindings/paralleldisplay/ParallelBus.c +#: shared-bindings/paralleldisplaybus/ParallelBus.c msgid "Specify exactly one of data0 or data_pins" msgstr "" @@ -2013,7 +2027,7 @@ msgstr "" msgid "This microcontroller does not support continuous capture." msgstr "" -#: shared-module/paralleldisplay/ParallelBus.c +#: shared-module/paralleldisplaybus/ParallelBus.c msgid "" "This microcontroller only supports data0=, not data_pins=, because it " "requires contiguous pins." @@ -2148,7 +2162,8 @@ msgstr "" msgid "Unable to create lock" msgstr "" -#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c +#: shared-module/i2cdisplaybus/I2CDisplayBus.c +#: shared-module/is31fl3741/IS31FL3741.c #, c-format msgid "Unable to find I2C Display at %x" msgstr "" @@ -2258,7 +2273,7 @@ msgstr "" msgid "Unsupported colorspace" msgstr "" -#: shared-module/displayio/display_core.c +#: shared-module/displayio/bus_core.c msgid "Unsupported display bus type" msgstr "" diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 614fae4064..5f0af02a6e 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -395,6 +395,9 @@ endif ifeq ($(CIRCUITPY_VIDEOCORE),1) SRC_PATTERNS += videocore/% endif +ifeq ($(CIRCUITPY_WARNINGS),1) +SRC_PATTERNS += warnings/% +endif ifeq ($(CIRCUITPY_WATCHDOG),1) SRC_PATTERNS += watchdog/% endif @@ -680,13 +683,14 @@ SRC_SHARED_MODULE_ALL = \ usb/core/__init__.c \ usb/core/Device.c \ ustack/__init__.c \ - watchdog/__init__.c \ - zlib/__init__.c \ vectorio/Circle.c \ vectorio/Polygon.c \ vectorio/Rectangle.c \ vectorio/VectorShape.c \ vectorio/__init__.c \ + warnings/__init__.c \ + watchdog/__init__.c \ + zlib/__init__.c \ # All possible sources are listed here, and are filtered by SRC_PATTERNS. SRC_SHARED_MODULE = $(filter $(SRC_PATTERNS), $(SRC_SHARED_MODULE_ALL)) diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 84aacaecd3..b3b11458c3 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -589,6 +589,9 @@ CIRCUITPY_ULAB_OPTIMIZE_SIZE ?= 0 CIRCUITPY_VIDEOCORE ?= 0 CFLAGS += -DCIRCUITPY_VIDEOCORE=$(CIRCUITPY_VIDEOCORE) +CIRCUITPY_WARNINGS ?= 1 +CFLAGS += -DCIRCUITPY_WARNINGS=$(CIRCUITPY_WARNINGS) + # watchdog hardware support CIRCUITPY_WATCHDOG ?= 0 CFLAGS += -DCIRCUITPY_WATCHDOG=$(CIRCUITPY_WATCHDOG) diff --git a/py/modbuiltins.c b/py/modbuiltins.c index 6ba3d6f800..3faa6a9489 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -785,6 +785,10 @@ STATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_ViperTypeError), MP_ROM_PTR(&mp_type_ViperTypeError) }, #endif { MP_ROM_QSTR(MP_QSTR_ZeroDivisionError), MP_ROM_PTR(&mp_type_ZeroDivisionError) }, + #if CIRCUITPY_WARNINGS + { MP_ROM_QSTR(MP_QSTR_Warning), MP_ROM_PTR(&mp_type_Warning) }, + { MP_ROM_QSTR(MP_QSTR_FutureWarning), MP_ROM_PTR(&mp_type_FutureWarning) }, + #endif // Extra builtins as defined by a port MICROPY_PORT_BUILTINS diff --git a/py/mpstate.h b/py/mpstate.h index 1995b7623e..3717cc15c2 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -36,6 +36,10 @@ #include "py/objlist.h" #include "py/objexcept.h" +#if CIRCUITPY_WARNINGS +#include "shared-bindings/warnings/__init__.h" +#endif + // #if CIRCUITPY // #error CIRCUITPY is TRUE in mpstate.h. // #else @@ -311,6 +315,10 @@ typedef struct _mp_state_thread_t { bool prof_callback_is_executing; struct _mp_code_state_t *current_code_state; #endif + + #if CIRCUITPY_WARNINGS + warnings_action_t warnings_action; + #endif } mp_state_thread_t; // This structure combines the above 3 structures. diff --git a/py/obj.h b/py/obj.h index a32971904b..74034824a6 100644 --- a/py/obj.h +++ b/py/obj.h @@ -916,6 +916,10 @@ extern const mp_obj_type_t mp_type_ZeroDivisionError; #if CIRCUITPY_ALARM extern const mp_obj_type_t mp_type_DeepSleepRequest; #endif +#if CIRCUITPY_WARNINGS +extern const mp_obj_type_t mp_type_Warning; +extern const mp_obj_type_t mp_type_FutureWarning; +#endif // Constant objects, globally accessible: None, False, True diff --git a/py/objexcept.c b/py/objexcept.c index 0f7dd06e3d..c6641d8937 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -452,14 +452,16 @@ MP_DEFINE_EXCEPTION(Exception, BaseException) #if CIRCUITPY_ALARM MP_DEFINE_EXCEPTION(DeepSleepRequest, BaseException) #endif -/* +#if CIRCUITPY_WARNINGS MP_DEFINE_EXCEPTION(Warning, Exception) + MP_DEFINE_EXCEPTION(FutureWarning, Warning) +#endif +/* MP_DEFINE_EXCEPTION(DeprecationWarning, Warning) MP_DEFINE_EXCEPTION(PendingDeprecationWarning, Warning) MP_DEFINE_EXCEPTION(RuntimeWarning, Warning) MP_DEFINE_EXCEPTION(SyntaxWarning, Warning) MP_DEFINE_EXCEPTION(UserWarning, Warning) - MP_DEFINE_EXCEPTION(FutureWarning, Warning) MP_DEFINE_EXCEPTION(ImportWarning, Warning) MP_DEFINE_EXCEPTION(UnicodeWarning, Warning) MP_DEFINE_EXCEPTION(BytesWarning, Warning) diff --git a/py/objmodule.c b/py/objmodule.c index 7c85cb911c..a127449bcf 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -34,6 +34,10 @@ #include "py/runtime.h" #include "py/builtin.h" +#if CIRCUITPY_WARNINGS +#include "shared-module/warnings/__init__.h" +#endif + STATIC void module_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in); @@ -62,6 +66,32 @@ STATIC void module_attr_try_delegation(mp_obj_t self_in, qstr attr, mp_obj_t *de STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in); if (dest[0] == MP_OBJ_NULL) { + #if CIRCUITPY_DISPLAYIO && CIRCUITPY_WARNINGS + if (self == &displayio_module) { + #if CIRCUITPY_BUSDISPLAY + if (attr == MP_QSTR_Display) { + warnings_warn(&mp_type_FutureWarning, translate("%q moved from %q to %q"), MP_QSTR_Display, MP_QSTR_displayio, MP_QSTR_busdisplay); + warnings_warn(&mp_type_FutureWarning, translate("%q renamed %q"), MP_QSTR_Display, MP_QSTR_BusDisplay); + } + #endif + #if CIRCUITPY_EPAPERDISPLAY + if (attr == MP_QSTR_EPaperDisplay) { + warnings_warn(&mp_type_FutureWarning, translate("%q moved from %q to %q"), MP_QSTR_EPaperDisplay, MP_QSTR_displayio, MP_QSTR_epaperdisplay); + } + #endif + #if CIRCUITPY_FOURWIRE + if (attr == MP_QSTR_FourWire) { + warnings_warn(&mp_type_FutureWarning, translate("%q moved from %q to %q"), MP_QSTR_FourWire, MP_QSTR_displayio, MP_QSTR_fourwire); + } + #endif + #if CIRCUITPY_I2CDISPLAYBUS + if (attr == MP_QSTR_I2CDisplay) { + warnings_warn(&mp_type_FutureWarning, translate("%q moved from %q to %q"), MP_QSTR_I2CDisplay, MP_QSTR_displayio, MP_QSTR_i2cdisplaybus); + warnings_warn(&mp_type_FutureWarning, translate("%q renamed %q"), MP_QSTR_I2CDisplay, MP_QSTR_I2CDisplayBus); + } + #endif + } + #endif // load attribute mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP); if (elem != NULL) { @@ -173,6 +203,11 @@ STATIC const mp_module_delegation_entry_t mp_builtin_module_delegation_table[] = // Attempts to find (and initialise) a built-in, otherwise returns // MP_OBJ_NULL. mp_obj_t mp_module_get_builtin(qstr module_name, bool extensible) { + #if CIRCUITPY_PARALLELDISPLAYBUS && CIRCUITPY_WARNINGS + if (module_name == MP_QSTR_paralleldisplay) { + warnings_warn(&mp_type_FutureWarning, translate("%q renamed %q"), MP_QSTR_paralleldisplay, MP_QSTR_paralleldisplaybus); + } + #endif mp_map_elem_t *elem = mp_map_lookup((mp_map_t *)(extensible ? &mp_builtin_extensible_module_map : &mp_builtin_module_map), MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP); if (!elem) { #if MICROPY_PY_SYS diff --git a/py/runtime.c b/py/runtime.c index 5b205cd764..c9ba9e6096 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -47,6 +47,10 @@ #include "py/stream.h" #include "py/gc.h" +#if CIRCUITPY_WARNINGS +#include "shared-module/warnings/__init__.h" +#endif + #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) #define DEBUG_printf DEBUG_printf @@ -1659,6 +1663,25 @@ mp_obj_t __attribute__((noinline, )) mp_import_from(mp_obj_t module, qstr name) void mp_import_all(mp_obj_t module) { DEBUG_printf("import all %p\n", module); + #if CIRCUITPY_DISPLAYIO && CIRCUITPY_WARNINGS + if (module == &displayio_module) { + #if CIRCUITPY_BUSDISPLAY + warnings_warn(&mp_type_FutureWarning, translate("%q moved from %q to %q"), MP_QSTR_Display, MP_QSTR_displayio, MP_QSTR_busdisplay); + warnings_warn(&mp_type_FutureWarning, translate("%q renamed %q"), MP_QSTR_Display, MP_QSTR_BusDisplay); + #endif + #if CIRCUITPY_EPAPERDISPLAY + warnings_warn(&mp_type_FutureWarning, translate("%q moved from %q to %q"), MP_QSTR_EPaperDisplay, MP_QSTR_displayio, MP_QSTR_epaperdisplay); + #endif + #if CIRCUITPY_FOURWIRE + warnings_warn(&mp_type_FutureWarning, translate("%q moved from %q to %q"), MP_QSTR_FourWire, MP_QSTR_displayio, MP_QSTR_fourwire); + #endif + #if CIRCUITPY_I2CDISPLAYBUS + warnings_warn(&mp_type_FutureWarning, translate("%q moved from %q to %q"), MP_QSTR_I2CDisplay, MP_QSTR_displayio, MP_QSTR_i2cdisplaybus); + warnings_warn(&mp_type_FutureWarning, translate("%q renamed %q"), MP_QSTR_I2CDisplay, MP_QSTR_I2CDisplayBus); + #endif + } + #endif + // TODO: Support __all__ mp_map_t *map = &mp_obj_module_get_globals(module)->map; for (size_t i = 0; i < map->alloc; i++) { diff --git a/shared-bindings/warnings/__init__.c b/shared-bindings/warnings/__init__.c new file mode 100644 index 0000000000..ca051953f7 --- /dev/null +++ b/shared-bindings/warnings/__init__.c @@ -0,0 +1,112 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/mpstate.h" +#include "py/obj.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "shared-bindings/warnings/__init__.h" + +//| """Warn about potential code issues. +//| +//| This is a slimmed down version of the full CPython module. It defaults to +//| the "always" action instead of "default", which prints once per occurrence. +//| Only "error" and "ignore" are also supported. No filtering on category is +//| available. +//| +//| |see_cpython_module| :mod:`cpython:warnings`. +//| +//| """ +//| +//| import typing +//| + +//| def warn(message: str, category: type = Warning) -> None: +//| """Issue a warning with an optional category. Use `simplefilter()` to +//| set if warnings are ignored, printed or raise an exception. +//| +//| """ +//| ... +//| +STATIC mp_obj_t warnings_warn(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_message, ARG_category }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_message, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_category, MP_ARG_OBJ, {.u_obj = MP_OBJ_FROM_PTR(&mp_type_Warning)} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_obj_t category_obj = args[ARG_category].u_obj; + if (!mp_obj_is_type(category_obj, &mp_type_type) || + !mp_obj_is_subclass_fast(category_obj, MP_OBJ_FROM_PTR(&mp_type_Warning))) { + mp_raise_TypeError_varg(translate("%q must be a subclass of %q"), MP_QSTR_category, MP_QSTR_Warning); + } + + common_hal_warnings_warn(mp_obj_str_get_str(args[ARG_message].u_obj), MP_OBJ_TO_PTR(category_obj)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(warnings_warn_obj, 1, warnings_warn); + +//| def simplefilter(action: str) -> None: +//| """Set the action to take on all warnings. This is a subset of the CPython +//| behavior because it allows for per-category changes.""" +//| ... +//| +STATIC mp_obj_t warnings_simplefilter(mp_obj_t action_in) { + const char *action_str = mp_obj_str_get_str(action_in); + warnings_action_t action; + if (strcmp(action_str, "error") == 0) { + action = WARNINGS_ERROR; + } else if (strcmp(action_str, "ignore") == 0) { + action = WARNINGS_IGNORE; + } else if (strcmp(action_str, "always") == 0) { + action = WARNINGS_ALWAYS; + } else { + mp_raise_ValueError(NULL); + } + common_hal_warnings_simplefilter(action); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(warnings_simplefilter_obj, warnings_simplefilter); + +STATIC const mp_rom_map_elem_t warnings_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_warnings) }, + + { MP_ROM_QSTR(MP_QSTR_warn), MP_ROM_PTR(&warnings_warn_obj) }, + { MP_ROM_QSTR(MP_QSTR_simplefilter), MP_ROM_PTR(&warnings_simplefilter_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(warnings_module_globals, warnings_module_globals_table); + +const mp_obj_module_t warnings_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&warnings_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_warnings, warnings_module); diff --git a/shared-bindings/warnings/__init__.h b/shared-bindings/warnings/__init__.h new file mode 100644 index 0000000000..23781cf9d1 --- /dev/null +++ b/shared-bindings/warnings/__init__.h @@ -0,0 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +typedef enum { + WARNINGS_DEFAULT, + WARNINGS_ERROR, + WARNINGS_IGNORE, + WARNINGS_ALWAYS, + WARNINGS_MODULE, + WARNINGS_ONCE +} warnings_action_t; + +void common_hal_warnings_warn(const char *message, const mp_obj_type_t *category); +void common_hal_warnings_simplefilter(warnings_action_t action); diff --git a/shared-module/warnings/__init__.c b/shared-module/warnings/__init__.c new file mode 100644 index 0000000000..e12958600f --- /dev/null +++ b/shared-module/warnings/__init__.c @@ -0,0 +1,73 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2015 Josef Gajdusek + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "py/mpprint.h" +#include "py/mpstate.h" +#include "py/runtime.h" +#include "shared-bindings/warnings/__init__.h" +#include "shared-module/warnings/__init__.h" + +void common_hal_warnings_warn(const char *message, const mp_obj_type_t *category) { + warnings_action_t action = MP_STATE_THREAD(warnings_action); + if (action == WARNINGS_IGNORE) { + return; + } + if (action == WARNINGS_ERROR) { + mp_raise_msg_str(category, message); + // Doesn't get here + return; + } + mp_printf(MICROPY_ERROR_PRINTER, "%q: %s\n", category->name, message); +} + +void warnings_warn(const mp_obj_type_t *category, const compressed_string_t *message, ...) { + warnings_action_t action = MP_STATE_THREAD(warnings_action); + if (action == WARNINGS_IGNORE) { + return; + } + va_list argptr; + va_start(argptr, message); + if (action == WARNINGS_ERROR) { + mp_raise_msg_vlist(category, message, argptr); + va_end(argptr); + // Doesn't get here + return; + } + + mp_printf(MICROPY_ERROR_PRINTER, "%q: ", category->name); + mp_vcprintf(MICROPY_ERROR_PRINTER, message, argptr); + mp_print_str(MICROPY_ERROR_PRINTER, "\n"); + va_end(argptr); +} + +void common_hal_warnings_simplefilter(warnings_action_t action) { + MP_STATE_THREAD(warnings_action) = action; +} diff --git a/shared-module/warnings/__init__.h b/shared-module/warnings/__init__.h new file mode 100644 index 0000000000..2b9e544079 --- /dev/null +++ b/shared-module/warnings/__init__.h @@ -0,0 +1,29 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +void warnings_warn(const mp_obj_type_t *category, const compressed_string_t *message, ...); From cf08ef0b80ea2b275304c3a3161e5f3fbf0b9ca1 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 26 Oct 2023 13:43:04 -0700 Subject: [PATCH 2/2] Enable warnings in full builds only --- py/circuitpy_mpconfig.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index b3b11458c3..b3628a9c10 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -589,7 +589,7 @@ CIRCUITPY_ULAB_OPTIMIZE_SIZE ?= 0 CIRCUITPY_VIDEOCORE ?= 0 CFLAGS += -DCIRCUITPY_VIDEOCORE=$(CIRCUITPY_VIDEOCORE) -CIRCUITPY_WARNINGS ?= 1 +CIRCUITPY_WARNINGS ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_WARNINGS=$(CIRCUITPY_WARNINGS) # watchdog hardware support