From ef2bfdb5db464eec9b947750cfa7eb9467adfa85 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 1 Dec 2022 16:43:08 -0600 Subject: [PATCH 01/34] dotenv becomes settings.toml --- devices/ble_hci/common-hal/_bleio/Adapter.c | 16 +- docs/environment.rst | 32 +- docs/workflows.md | 14 +- locale/circuitpython.pot | 18 + .../espressif/bindings/esp32_camera/Camera.c | 2 +- ports/espressif/bindings/espidf/__init__.c | 2 +- ports/espressif/common-hal/_bleio/Adapter.c | 34 +- ports/espressif/supervisor/port.c | 4 +- ports/nrf/common-hal/_bleio/Adapter.c | 15 +- .../unix/variants/coverage/mpconfigvariant.mk | 6 +- py/circuitpy_defns.mk | 6 +- py/circuitpy_mpconfig.mk | 6 +- .../{dotenv => _environ}/__init__.c | 39 +- .../{dotenv => _environ}/__init__.h | 10 +- shared-module/_environ/__init__.c | 402 ++++++++++++++++++ shared-module/{dotenv => _environ}/__init__.h | 25 +- shared-module/dotenv/__init__.c | 312 -------------- shared-module/os/__init__.c | 9 +- .../shared/web_workflow/static/directory.js | 2 +- .../shared/web_workflow/static/welcome.html | 2 +- supervisor/shared/web_workflow/web_workflow.c | 65 ++- tests/circuitpython/bad1.toml | 1 + tests/circuitpython/bad2.toml | 1 + tests/circuitpython/bad3.toml | 1 + tests/circuitpython/dotenv_test.env | 37 -- tests/circuitpython/dotenv_test.py | 31 -- tests/circuitpython/dotenv_test.py.exp | 35 -- tests/circuitpython/environ_test.py | 42 ++ tests/circuitpython/environ_test.py.exp | 17 + tests/circuitpython/good.toml | 14 + tests/unix/extra_coverage.py.exp | 8 +- 31 files changed, 642 insertions(+), 566 deletions(-) rename shared-bindings/{dotenv => _environ}/__init__.c (68%) rename shared-bindings/{dotenv => _environ}/__init__.h (81%) create mode 100644 shared-module/_environ/__init__.c rename shared-module/{dotenv => _environ}/__init__.h (66%) delete mode 100644 shared-module/dotenv/__init__.c create mode 100644 tests/circuitpython/bad1.toml create mode 100644 tests/circuitpython/bad2.toml create mode 100644 tests/circuitpython/bad3.toml delete mode 100644 tests/circuitpython/dotenv_test.env delete mode 100644 tests/circuitpython/dotenv_test.py delete mode 100644 tests/circuitpython/dotenv_test.py.exp create mode 100644 tests/circuitpython/environ_test.py create mode 100644 tests/circuitpython/environ_test.py.exp create mode 100644 tests/circuitpython/good.toml diff --git a/devices/ble_hci/common-hal/_bleio/Adapter.c b/devices/ble_hci/common-hal/_bleio/Adapter.c index 8c7b8f67eb..018b65de12 100644 --- a/devices/ble_hci/common-hal/_bleio/Adapter.c +++ b/devices/ble_hci/common-hal/_bleio/Adapter.c @@ -49,8 +49,8 @@ #include "shared-bindings/_bleio/ScanEntry.h" #include "shared-bindings/time/__init__.h" -#if CIRCUITPY_DOTENV -#include "shared-module/dotenv/__init__.h" +#if CIRCUITPY_ENVIRON +#include "shared-bindings/_environ/__init__.h" #endif #define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) @@ -284,15 +284,15 @@ char default_ble_name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 0, 0, 0 STATIC void bleio_adapter_hci_init(bleio_adapter_obj_t *self) { mp_int_t name_len = 0; - #if CIRCUITPY_DOTENV - char ble_name[32]; - name_len = dotenv_get_key("/.env", "CIRCUITPY_BLE_NAME", ble_name, sizeof(ble_name) - 1); - if (name_len > 0) { - self->name = mp_obj_new_str(ble_name, (size_t)name_len); + #if CIRCUITPY_ENVIRON + mp_obj_t name = common_hal__environ_get_key("CIRCUITPY_BLE_NAME"); + if (name != mp_const_none) { + mp_arg_validate_type_string(name, MP_QSTR_CIRCUITPY_BLE_NAME); + self->name = name; } #endif - if (name_len <= 0) { + if (!self->name) { name_len = sizeof(default_ble_name); bt_addr_t addr; hci_check_error(hci_read_bd_addr(&addr)); diff --git a/docs/environment.rst b/docs/environment.rst index 5766b54380..457e5c3f88 100644 --- a/docs/environment.rst +++ b/docs/environment.rst @@ -6,24 +6,36 @@ variables are commonly used to store "secrets" such as Wi-Fi passwords and API keys. This method *does not* make them secure. It only separates them from the code. -CircuitPython supports these by mimicking the `dotenv `_ -CPython library. Other languages such as Javascript, PHP and Ruby also have -dotenv libraries. +CircuitPython supports these by parsing a subset of the `toml `_ file format internally. -These libraries store environment variables in a ``.env`` file. Here is a simple -example: +Here is a simple example: .. code-block:: bash - KEY1='value1' + KEY1="value1" # Comment - KEY2='value2 - is multiple lines' + KEY2="value2\ncontains a newline" -CircuitPython uses the ``.env`` at the drive root (no folder) as the environment. + [SECTION] # Only values in the "root table" are parsed + SECTION_VALUE = ... # so this value cannot be seen by getenv + +CircuitPython uses the ``settings.toml`` at the drive root (no folder) as the environment. User code can access the values from the file using `os.getenv()`. It is recommended to save any values used repeatedly in a variable because `os.getenv()` -will parse the ``/.env`` on every access. +will parse the ``settings.toml`` file contents on every access. + +Details of the toml language subset +----------------------------------- + +* The content is required to be in UTF-8 encoding +* The supported data types are string and integer +* Only basic strings are supported, not triple-quoted strings +* Only integers supported by strtol. (no 0o, no 0b, no underscores 1_000, 011 + is 9, not 11) +* Only bare keys are supported +* Duplicate keys are not diagnosed. +* Comments are supported +* Only values from the "root table" can be retrieved CircuitPython behavior ---------------------- diff --git a/docs/workflows.md b/docs/workflows.md index 26f5179b51..29229bd00e 100644 --- a/docs/workflows.md +++ b/docs/workflows.md @@ -46,7 +46,7 @@ connection, the central device can discover two default services. One for file t CircuitPython specifically that includes serial characteristics. To change the default BLE advertising name without (or before) running user code, the desired name -can be put in the `/.env` file. The key is `CIRCUITPY_BLE_NAME`. It's limited to approximately +can be put in the `settings.toml` file. The key is `CIRCUITPY_BLE_NAME`. It's limited to approximately 30 characters depending on the port's settings and will be truncated if longer. ### File Transfer API @@ -69,21 +69,21 @@ Read-only characteristic that returns the UTF-8 encoded version string. ## Web -The web workflow is depends on adding Wi-Fi credentials into the `/.env` file. The keys are +The web workflow is depends on adding Wi-Fi credentials into the `settings.toml` file. The keys are `CIRCUITPY_WIFI_SSID` and `CIRCUITPY_WIFI_PASSWORD`. Once these are defined, CircuitPython will automatically connect to the network and start the webserver used for the workflow. The webserver is on port 80 unless overridden by `CIRCUITPY_WEB_API_PORT`. It also enables MDNS. -Here is an example `/.env`: +Here is an example `/settings.toml`: ```bash # To auto-connect to Wi-Fi -CIRCUITPY_WIFI_SSID='scottswifi' -CIRCUITPY_WIFI_PASSWORD='secretpassword' +CIRCUITPY_WIFI_SSID="scottswifi" +CIRCUITPY_WIFI_PASSWORD="secretpassword" # To enable modifying files from the web. Change this too! # Leave the User field blank in the browser. -CIRCUITPY_WEB_API_PASSWORD='passw0rd' +CIRCUITPY_WEB_API_PASSWORD="passw0rd" CIRCUITPY_WEB_API_PORT=80 ``` @@ -124,7 +124,7 @@ All file system related APIs are protected by HTTP basic authentication. It is * hopefully prevent some griefing in shared settings. The password is sent unencrypted so do not reuse a password with something important. The user field is left blank. -The password is taken from `/.env` with the key `CIRCUITPY_WEB_API_PASSWORD`. If this is unset, the +The password is taken from `settings.toml` with the key `CIRCUITPY_WEB_API_PASSWORD`. If this is unset, the server will respond with `403 Forbidden`. When a password is set, but not provided in a request, it will respond `401 Unauthorized`. diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 450b2eabd7..16a682cfdd 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -1002,6 +1002,10 @@ msgstr "" msgid "File exists" msgstr "" +#: shared-module/dotenv/__init__.c +msgid "File not found" +msgstr "" + #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c @@ -1184,6 +1188,7 @@ msgid "Internal define error" msgstr "" #: ports/espressif/common-hal/paralleldisplay/ParallelBus.c +#: shared-module/dotenv/__init__.c msgid "Internal error" msgstr "" @@ -1230,6 +1235,11 @@ msgstr "" msgid "Invalid bits per value" msgstr "" +#: shared-module/dotenv/__init__.c +#, c-format +msgid "Invalid byte %.*s" +msgstr "" + #: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c #, c-format msgid "Invalid data_pins[%d]" @@ -1260,10 +1270,18 @@ msgstr "" msgid "Invalid state" msgstr "" +#: shared-module/dotenv/__init__.c +msgid "Invalid unicode escape" +msgstr "" + #: shared-bindings/aesio/aes.c msgid "Key must be 16, 24, or 32 bytes long" msgstr "" +#: shared-module/dotenv/__init__.c +msgid "Key not found" +msgstr "" + #: shared-module/is31fl3741/FrameBuffer.c msgid "LED mappings must match display size" msgstr "" diff --git a/ports/espressif/bindings/esp32_camera/Camera.c b/ports/espressif/bindings/esp32_camera/Camera.c index a770ea8ff7..9bcd398612 100644 --- a/ports/espressif/bindings/esp32_camera/Camera.c +++ b/ports/espressif/bindings/esp32_camera/Camera.c @@ -63,7 +63,7 @@ //| """ //| Configure and initialize a camera with the given properties //| -//| This driver requires that the ``CIRCUITPY_RESERVED_PSRAM`` in ``/.env`` be large enough to hold the camera frambuffer(s). Generally, boards with built-in cameras will have a default setting that is large enough. If the constructor raises a MemoryError or an IDFError, this probably indicates the setting is too small and should be increased. +//| This driver requires that the ``CIRCUITPY_RESERVED_PSRAM`` in ``settings.toml`` be large enough to hold the camera frambuffer(s). Generally, boards with built-in cameras will have a default setting that is large enough. If the constructor raises a MemoryError or an IDFError, this probably indicates the setting is too small and should be increased. //| //| //| .. important:: diff --git a/ports/espressif/bindings/espidf/__init__.c b/ports/espressif/bindings/espidf/__init__.c index c42a9e549d..12781000ae 100644 --- a/ports/espressif/bindings/espidf/__init__.c +++ b/ports/espressif/bindings/espidf/__init__.c @@ -132,7 +132,7 @@ STATIC mp_obj_t espidf_get_total_psram(void) { MP_DEFINE_CONST_FUN_OBJ_0(espidf_get_total_psram_obj, espidf_get_total_psram); //| def get_reserved_psram() -> int: -//| """Returns number of bytes of psram reserved for use by esp-idf, either a board-specific default value or the value defined in ``/.env``.""" +//| """Returns number of bytes of psram reserved for use by esp-idf, either a board-specific default value or the value defined in ``settings.toml``.""" //| STATIC mp_obj_t espidf_get_reserved_psram(void) { return MP_OBJ_NEW_SMALL_INT(common_hal_espidf_get_reserved_psram()); diff --git a/ports/espressif/common-hal/_bleio/Adapter.c b/ports/espressif/common-hal/_bleio/Adapter.c index 5eaf6e9cf4..121beb8e90 100644 --- a/ports/espressif/common-hal/_bleio/Adapter.c +++ b/ports/espressif/common-hal/_bleio/Adapter.c @@ -59,8 +59,8 @@ #include "esp_bt.h" #include "esp_nimble_hci.h" -#if CIRCUITPY_DOTENV -#include "shared-module/dotenv/__init__.h" +#if CIRCUITPY_ENVIRON +#include "shared-module/_environ/__init__.h" #endif bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; @@ -101,28 +101,24 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable ble_hs_cfg.sync_cb = _on_sync; // ble_hs_cfg.store_status_cb = ble_store_util_status_rr; - #if CIRCUITPY_DOTENV - mp_int_t name_len = 0; - char ble_name[32]; - name_len = dotenv_get_key("/.env", "CIRCUITPY_BLE_NAME", ble_name, sizeof(ble_name) - 1); - if (name_len > 0) { - if (name_len > MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH) { - name_len = MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH; - } - ble_name[name_len] = '\0'; + #if CIRCUITPY_ENVIRON + char ble_name[1 + MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH]; + _environ_err_t result = _environ_get_key_str("CIRCUITPY_BLE_NAME", ble_name, sizeof(ble_name)); + if (result == ENVIRON_OK) { ble_svc_gap_device_name_set(ble_name); - } else { + } else + #else + { ble_svc_gap_device_name_set("CIRCUITPY"); } - #else - ble_svc_gap_device_name_set("CIRCUITPY"); #endif - // Clear all of the internal connection objects. - for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { - bleio_connection_internal_t *connection = &bleio_connections[i]; - // Reset connection. - connection->conn_handle = BLEIO_HANDLE_INVALID; + {// Clear all of the internal connection objects. + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &bleio_connections[i]; + // Reset connection. + connection->conn_handle = BLEIO_HANDLE_INVALID; + } } cp_task = xTaskGetCurrentTaskHandle(); diff --git a/ports/espressif/supervisor/port.c b/ports/espressif/supervisor/port.c index 3106f4b991..e89fb8c976 100644 --- a/ports/espressif/supervisor/port.c +++ b/ports/espressif/supervisor/port.c @@ -55,7 +55,7 @@ #include "shared-bindings/microcontroller/RunMode.h" #include "shared-bindings/rtc/__init__.h" #include "shared-bindings/socketpool/__init__.h" -#include "shared-module/dotenv/__init__.h" +#include "shared-module/_environ/__init__.h" #include "peripherals/rmt.h" #include "peripherals/timer.h" @@ -519,7 +519,7 @@ void port_idle_until_interrupt(void) { void port_post_boot_py(bool heap_valid) { if (!heap_valid && filesystem_present()) { mp_int_t reserved; - if (dotenv_get_key_int("/.env", "CIRCUITPY_RESERVED_PSRAM", &reserved)) { + if (_environ_get_key_int("CIRCUITPY_RESERVED_PSRAM", &reserved) == ENVIRON_OK) { common_hal_espidf_set_reserved_psram(reserved); } common_hal_espidf_reserve_psram(); diff --git a/ports/nrf/common-hal/_bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c index 49b5d638f3..012430704a 100644 --- a/ports/nrf/common-hal/_bleio/Adapter.c +++ b/ports/nrf/common-hal/_bleio/Adapter.c @@ -52,8 +52,8 @@ #include "shared-bindings/_bleio/ScanEntry.h" #include "shared-bindings/time/__init__.h" -#if CIRCUITPY_DOTENV -#include "shared-module/dotenv/__init__.h" +#if CIRCUITPY_ENVIRON +#include "shared-bindings/_environ/__init__.h" #endif #define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS) @@ -345,12 +345,11 @@ STATIC void bleio_adapter_reset_name(bleio_adapter_obj_t *self) { mp_int_t name_len = 0; - #if CIRCUITPY_DOTENV - char ble_name[32]; - name_len = dotenv_get_key("/.env", "CIRCUITPY_BLE_NAME", ble_name, sizeof(ble_name) - 1); - if (name_len > 0) { - ble_name[name_len] = '\0'; - common_hal_bleio_adapter_set_name(self, (char *)ble_name); + #if CIRCUITPY_ENVIRON + mp_obj_t ble_name = common_hal__environ_get_key("CIRCUITPY_BLE_NAME"); + if (ble_name != mp_const_none) { + common_hal_bleio_adapter_set_name(self, mp_obj_str_get_str(ble_name)); + return; } #endif diff --git a/ports/unix/variants/coverage/mpconfigvariant.mk b/ports/unix/variants/coverage/mpconfigvariant.mk index 1e8e59f9a9..a0e0f4f3bb 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.mk +++ b/ports/unix/variants/coverage/mpconfigvariant.mk @@ -33,7 +33,7 @@ SRC_BITMAP := \ shared-bindings/aesio/__init__.c \ shared-bindings/bitmaptools/__init__.c \ shared-bindings/displayio/Bitmap.c \ - shared-bindings/dotenv/__init__.c \ + shared-bindings/_environ/__init__.c \ shared-bindings/rainbowio/__init__.c \ shared-bindings/traceback/__init__.c \ shared-bindings/util.c \ @@ -45,7 +45,7 @@ SRC_BITMAP := \ shared-module/displayio/Bitmap.c \ shared-module/displayio/ColorConverter.c \ shared-module/displayio/ColorConverter.c \ - shared-module/dotenv/__init__.c \ + shared-module/_environ/__init__.c \ shared-module/rainbowio/__init__.c \ shared-module/traceback/__init__.c \ shared-module/zlib/__init__.c \ @@ -56,7 +56,7 @@ CFLAGS += \ -DCIRCUITPY_AESIO=1 \ -DCIRCUITPY_BITMAPTOOLS=1 \ -DCIRCUITPY_DISPLAYIO_UNIX=1 \ - -DCIRCUITPY_DOTENV=1 \ + -DCIRCUITPY_ENVIRON=1 \ -DCIRCUITPY_GIFIO=1 \ -DCIRCUITPY_RAINBOWIO=1 \ -DCIRCUITPY_TRACEBACK=1 \ diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 70310106f0..7d8fa6bada 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -182,8 +182,8 @@ endif ifeq ($(CIRCUITPY_DISPLAYIO),1) SRC_PATTERNS += displayio/% endif -ifeq ($(CIRCUITPY_DOTENV),1) -SRC_PATTERNS += dotenv/% +ifeq ($(CIRCUITPY_ENVIRON),1) +SRC_PATTERNS += _environ/% endif ifeq ($(CIRCUITPY__EVE),1) SRC_PATTERNS += _eve/% @@ -589,7 +589,7 @@ SRC_SHARED_MODULE_ALL = \ displayio/TileGrid.c \ displayio/area.c \ displayio/__init__.c \ - dotenv/__init__.c \ + _environ/__init__.c \ floppyio/__init__.c \ fontio/BuiltinFont.c \ fontio/__init__.c \ diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 3ca23263d4..a6a1118d2d 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -208,9 +208,6 @@ CFLAGS += -DCIRCUITPY_BITMAPTOOLS=$(CIRCUITPY_BITMAPTOOLS) CFLAGS += -DCIRCUITPY_FRAMEBUFFERIO=$(CIRCUITPY_FRAMEBUFFERIO) CFLAGS += -DCIRCUITPY_VECTORIO=$(CIRCUITPY_VECTORIO) -CIRCUITPY_DOTENV ?= $(CIRCUITPY_FULL_BUILD) -CFLAGS += -DCIRCUITPY_DOTENV=$(CIRCUITPY_DOTENV) - CIRCUITPY_DUALBANK ?= 0 CFLAGS += -DCIRCUITPY_DUALBANK=$(CIRCUITPY_DUALBANK) @@ -218,6 +215,9 @@ CFLAGS += -DCIRCUITPY_DUALBANK=$(CIRCUITPY_DUALBANK) CIRCUITPY_ENABLE_MPY_NATIVE ?= 0 CFLAGS += -DCIRCUITPY_ENABLE_MPY_NATIVE=$(CIRCUITPY_ENABLE_MPY_NATIVE) +CIRCUITPY_ENVIRON ?= $(CIRCUITPY_FULL_BUILD) +CFLAGS += -DCIRCUITPY_ENVIRON=$(CIRCUITPY_ENVIRON) + CIRCUITPY_ERRNO ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_ERRNO=$(CIRCUITPY_ERRNO) diff --git a/shared-bindings/dotenv/__init__.c b/shared-bindings/_environ/__init__.c similarity index 68% rename from shared-bindings/dotenv/__init__.c rename to shared-bindings/_environ/__init__.c index 193338c7c2..81d778f3ed 100644 --- a/shared-bindings/dotenv/__init__.c +++ b/shared-bindings/_environ/__init__.c @@ -33,11 +33,11 @@ #include "py/obj.h" #include "py/objstr.h" #include "py/runtime.h" -#include "shared-bindings/dotenv/__init__.h" +#include "shared-bindings/_environ/__init__.h" //| """Functions to manage environment variables from a .env file. //| -//| A subset of the CPython `dotenv library `_. It does +//| A subset of the CPython `_environ library `_. It does //| not support variables or double quotes. //| //| Keys and values may be put in single quotes. @@ -71,43 +71,30 @@ //| import typing //| -//| def get_key(dotenv_path: str, key_to_get: str) -> Optional[str]: +//| def get_key(_environ_path: str, key_to_get: str) -> Optional[str]: //| """Get the value for the given key from the given .env file. If the key occurs multiple //| times in the file, then the last value will be returned. //| //| Returns None if the key isn't found or doesn't have a value.""" //| ... //| -STATIC mp_obj_t _dotenv_get_key(mp_obj_t path_in, mp_obj_t key_to_get_in) { - return common_hal_dotenv_get_key(mp_obj_str_get_str(path_in), +STATIC mp_obj_t __environ_get_key(mp_obj_t path_in, mp_obj_t key_to_get_in) { + return common_hal__environ_get_key_path(mp_obj_str_get_str(path_in), mp_obj_str_get_str(key_to_get_in)); } -MP_DEFINE_CONST_FUN_OBJ_2(dotenv_get_key_obj, _dotenv_get_key); +MP_DEFINE_CONST_FUN_OBJ_2(_environ_get_key_obj, __environ_get_key); -//| def load_dotenv() -> None: -//| """Does nothing in CircuitPython because os.getenv will automatically read .env when -//| available. -//| -//| Present in CircuitPython so CPython-compatible code can use it without error.""" -//| ... -//| -STATIC mp_obj_t dotenv_load_dotenv(void) { - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_0(dotenv_load_dotenv_obj, dotenv_load_dotenv); +STATIC const mp_rom_map_elem_t _environ_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__environ) }, -STATIC const mp_rom_map_elem_t dotenv_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_dotenv) }, - - { MP_ROM_QSTR(MP_QSTR_get_key), MP_ROM_PTR(&dotenv_get_key_obj) }, - { MP_ROM_QSTR(MP_QSTR_load_dotenv), MP_ROM_PTR(&dotenv_load_dotenv_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_key), MP_ROM_PTR(&_environ_get_key_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(dotenv_module_globals, dotenv_module_globals_table); +STATIC MP_DEFINE_CONST_DICT(_environ_module_globals, _environ_module_globals_table); -const mp_obj_module_t dotenv_module = { +const mp_obj_module_t _environ_module = { .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&dotenv_module_globals, + .globals = (mp_obj_dict_t *)&_environ_module_globals, }; -MP_REGISTER_MODULE(MP_QSTR_dotenv, dotenv_module, CIRCUITPY_DOTENV); +MP_REGISTER_MODULE(MP_QSTR__environ, _environ_module, CIRCUITPY_ENVIRON); diff --git a/shared-bindings/dotenv/__init__.h b/shared-bindings/_environ/__init__.h similarity index 81% rename from shared-bindings/dotenv/__init__.h rename to shared-bindings/_environ/__init__.h index 18a6c280dd..7779f3ac82 100644 --- a/shared-bindings/dotenv/__init__.h +++ b/shared-bindings/_environ/__init__.h @@ -24,16 +24,14 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_DOTENV___INIT___H -#define MICROPY_INCLUDED_SHARED_BINDINGS_DOTENV___INIT___H +#pragma once #include #include #include "py/objtuple.h" -#include "shared-module/dotenv/__init__.h" +#include "shared-module/_environ/__init__.h" -mp_obj_t common_hal_dotenv_get_key(const char *path, const char *key); - -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DOTENV___INIT___H +mp_obj_t common_hal__environ_get_key_path(const char *path, const char *key); +mp_obj_t common_hal__environ_get_key(const char *key); diff --git a/shared-module/_environ/__init__.c b/shared-module/_environ/__init__.c new file mode 100644 index 0000000000..7e6e133e1a --- /dev/null +++ b/shared-module/_environ/__init__.c @@ -0,0 +1,402 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * SPDX-FileCopyrightText: 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. + */ + +#include +#include + +#include "shared-bindings/_environ/__init__.h" + +#include "py/gc.h" +#include "py/misc.h" +#include "py/mpstate.h" +#include "py/objstr.h" +#include "py/parsenum.h" +#include "py/runtime.h" +#include "supervisor/filesystem.h" +#include "supervisor/memory.h" + +#define ENVIRON_PATH "settings.toml" + +#if defined(UNIX) +typedef FILE *file_arg; +STATIC bool open_file(const char *name, file_arg *active_file) { + FILE *result = fopen(name, "r"); + if (result) { + *active_file = result; + } + return result != NULL; +} +STATIC void close_file(file_arg *active_file) { + fclose(*active_file); +} +STATIC bool is_eof(file_arg *active_file) { + return feof(*active_file); +} +STATIC uint8_t get_next_byte(file_arg *active_file) { + int value = fgetc(*active_file); + if (value == EOF) { + return 0; + } + return value; +} +__attribute__((unused)) +STATIC void seek_eof(file_arg *active_file) { + fseek(*active_file, 0, SEEK_END); + (void)fgetc(*active_file); +} +#else +#include "extmod/vfs.h" +#include "extmod/vfs_fat.h" +typedef FIL file_arg; +STATIC bool open_file(const char *name, file_arg *active_file) { + FATFS *fs = filesystem_circuitpy(); + FRESULT result = f_open(fs, active_file, name, FA_READ); + return result == FR_OK; +} +STATIC void close_file(file_arg *active_file) { + // nothing +} +STATIC bool is_eof(file_arg *active_file) { + return f_eof(active_file); +} + +// Return 0 if there is no next character (EOF). +STATIC uint8_t get_next_byte(FIL *active_file) { + uint8_t character = 0; + UINT quantity_read; + // If there's an error or quantity_read is 0, character will remain 0. + f_read(active_file, &character, 1, &quantity_read); + return character; +} +STATIC void seek_eof(file_arg *active_file) { + f_lseek(active_file, f_size(active_file)); +} +#endif + +// For a fixed buffer, record the required size rather than throwing +STATIC void vstr_add_byte_nonstd(vstr_t *vstr, byte b) { + if (!vstr->fixed_buf || vstr->alloc > vstr->len) { + vstr_add_byte(vstr, b); + } else { + vstr->len++; + } +} + +// For a fixed buffer, record the required size rather than throwing +STATIC void vstr_add_char_nonstd(vstr_t *vstr, unichar c) { + size_t ulen = + (c < 0x80) ? 1 : + (c < 0x800) ? 2 : + (c < 0x10000) ? 3 : 4; + if (!vstr->fixed_buf || vstr->alloc > vstr->len + ulen) { + vstr_add_char(vstr, c); + } else { + vstr->len += ulen; + } +} + +STATIC void next_line(file_arg *active_file) { + uint8_t character; + do { + character = get_next_byte(active_file); + } while (character != 0 && character != '\n'); +} + +// Discard whitespace, except for newlines, returning the next character after the whitespace. +// Return 0 if there is no next character (EOF). +STATIC uint8_t consume_whitespace(file_arg *active_file) { + uint8_t character; + do { + character = get_next_byte(active_file); + } while (character != '\n' && character != 0 && unichar_isspace(character)); + return character; +} + +// Starting at the start of a new line, determines if the key matches the given +// key. +// +// If result is true, the key matches and file pointer is pointing just after the "=". +// If the result is false, the key does NOT match and the file pointer is +// pointing at the start of the next line, if any +STATIC bool key_matches(file_arg *active_file, const char *key) { + uint8_t character; + character = consume_whitespace(active_file); + if (character == '[' || character == 0) { + seek_eof(active_file); + return false; + } + while (*key) { + if (character != *key++) { + // A character didn't match the key, so it's not a match + // If the non-matching char was not the end of the line, + // then consume the rest of the line + if (character != '\n') { + next_line(active_file); + } + return false; + } + character = get_next_byte(active_file); + } + // the next character could be whitespace; consume if necessary + if (unichar_isspace(character)) { + character = consume_whitespace(active_file); + } + // If we're not looking at the "=" then the key didn't match + if (character != '=') { + // A character didn't match the key, so it's not a match + // If the non-matching char was not the end of the line, + // then consume the rest of the line + if (character != '\n') { + next_line(active_file); + } + return false; + } + return true; +} + +STATIC _environ_err_t read_unicode_escape(file_arg *active_file, int sz, vstr_t *buf) { + char hex_buf[sz + 1]; + for (int i = 0; i < sz; i++) { + hex_buf[i] = get_next_byte(active_file); + } + hex_buf[sz] = 0; + char *end; + unsigned long c = strtoul(hex_buf, &end, 16); + if (end != &hex_buf[sz]) { + return ENVIRON_ERR_UNEXPECTED | *end; + } + if (c >= 0x110000) { + return ENVIRON_ERR_UNICODE; + } + vstr_add_char_nonstd(buf, c); + return ENVIRON_OK; +} + +// Read a quoted string +STATIC _environ_err_t read_string_value(file_arg *active_file, vstr_t *buf) { + while (true) { + int character = get_next_byte(active_file); + switch (character) { + case 0: + case '\n': + return ENVIRON_ERR_UNEXPECTED | character; + + case '"': + character = consume_whitespace(active_file); + switch (character) { + case '#': + next_line(active_file); + MP_FALLTHROUGH; + case '\n': + return ENVIRON_OK; + default: + return ENVIRON_ERR_UNEXPECTED | character; + } + + case '\\': + character = get_next_byte(active_file); + switch (character) { + case 0: + case '\n': + return ENVIRON_ERR_UNEXPECTED | character; + case 'b': + character = '\b'; + break; + case 'r': + character = '\r'; + break; + case 'n': + character = '\n'; + break; + case 't': + character = '\t'; + break; + case 'v': + character = '\v'; + break; + case 'f': + character = '\f'; + break; + case 'U': + case 'u': { + int sz = (character == 'u') ? 4 : 8; + _environ_err_t res; + res = read_unicode_escape(active_file, sz, buf); + if (res != ENVIRON_OK) { + return res; + } + continue; + } + // default falls through, other escaped characters + // represent themselves + } + MP_FALLTHROUGH; + default: + vstr_add_byte_nonstd(buf, character); + } + } +} + +// Read a numeric value (non-quoted value) as a string +STATIC _environ_err_t read_bare_value(file_arg *active_file, vstr_t *buf, int first_character) { + int character = first_character; + while (true) { + switch (character) { + case 0: + return ENVIRON_ERR_UNEXPECTED | character; + case '\n': + return ENVIRON_OK; + case '#': + next_line(active_file); + return ENVIRON_OK; + default: + vstr_add_byte_nonstd(buf, character); + } + character = get_next_byte(active_file); + } +} + +STATIC mp_int_t read_value(file_arg *active_file, vstr_t *buf, bool *quoted) { + uint8_t character; + character = consume_whitespace(active_file); + *quoted = (character == '"'); + + if (*quoted) { + return read_string_value(active_file, buf); + } else { + return read_bare_value(active_file, buf, character); + } +} + +STATIC _environ_err_t _environ_get_key_vstr(const char *path, const char *key, vstr_t *buf, bool *quoted) { + file_arg active_file; + if (!open_file(path, &active_file)) { + return ENVIRON_ERR_OPEN; + } + + _environ_err_t result = ENVIRON_ERR_NOT_FOUND; + while (!is_eof(&active_file)) { + if (key_matches(&active_file, key)) { + result = read_value(&active_file, buf, quoted); + } + } + close_file(&active_file); + return result; +} + +STATIC _environ_err_t _environ_get_key_buf_terminated(const char *key, char *value, size_t value_len, bool *quoted) { + vstr_t buf; + vstr_init_fixed_buf(&buf, value_len, value); + _environ_err_t result = _environ_get_key_vstr(ENVIRON_PATH, key, &buf, quoted); + + if (result == ENVIRON_OK) { + vstr_add_byte_nonstd(&buf, 0); + memcpy(value, buf.buf, MIN(buf.len, value_len)); + if (buf.len > value_len) { + result = ENVIRON_ERR_LENGTH; + } + } + return result; +} + +_environ_err_t _environ_get_key_str(const char *key, char *value, size_t value_len) { + bool quoted; + _environ_err_t result = _environ_get_key_buf_terminated(key, value, value_len, "ed); + if (result == ENVIRON_OK && !quoted) { + result = ENVIRON_ERR_UNEXPECTED | value[0]; + } + return result; +} + +STATIC void throw__environ_error(_environ_err_t error) { + if (error == ENVIRON_OK) { + return; + } + if (error & ENVIRON_ERR_UNEXPECTED) { + byte character = (error & 0xff); + mp_print_t print; + vstr_t vstr; + vstr_init_print(&vstr, 8 + 4 + 1, &print); + if (character) { + mp_str_print_quoted(&print, &character, 1, true); + } else { + mp_str_print_quoted(&print, (byte *)"EOF", 3, true); + } + mp_raise_ValueError_varg(translate("Invalid byte %.*s"), + vstr.len, vstr.buf); + } + switch (error) { + case ENVIRON_ERR_OPEN: + mp_raise_ValueError(translate("File not found")); + case ENVIRON_ERR_UNICODE: + mp_raise_ValueError(translate("Invalid unicode escape")); + case ENVIRON_ERR_NOT_FOUND: + mp_raise_ValueError(translate("Key not found")); + default: + mp_raise_RuntimeError(translate("Internal error")); + } +} + +mp_obj_t common_hal__environ_get_key_path(const char *path, const char *key) { + vstr_t buf; + bool quoted; + + vstr_init(&buf, 64); + _environ_err_t result = _environ_get_key_vstr(path, key, &buf, "ed); + if (result == ENVIRON_ERR_NOT_FOUND) { + return mp_const_none; + } + throw__environ_error(result); + + if (quoted) { + return mp_obj_new_str_from_vstr(&mp_type_str, &buf); + } else { + return mp_parse_num_integer(buf.buf, buf.len, 0, NULL); + } +} + +mp_obj_t common_hal__environ_get_key(const char *key) { + return common_hal__environ_get_key_path(ENVIRON_PATH, key); +} + +_environ_err_t _environ_get_key_int(const char *key, mp_int_t *value) { + char buf[16]; + bool quoted; + _environ_err_t result = _environ_get_key_buf_terminated(key, buf, sizeof(buf), "ed); + if (result != ENVIRON_OK) { + return result; + } + if (quoted) { + return ENVIRON_ERR_UNEXPECTED | '"'; + } + char *end; + long num = strtol(buf, &end, 0); + if (end == buf || *end) { // If the whole buffer was not consumed it's an error + return ENVIRON_ERR_UNEXPECTED | *end; + } + *value = (mp_int_t)num; + return ENVIRON_OK; +} diff --git a/shared-module/dotenv/__init__.h b/shared-module/_environ/__init__.h similarity index 66% rename from shared-module/dotenv/__init__.h rename to shared-module/_environ/__init__.h index fb27233692..c96eb028b8 100644 --- a/shared-module/dotenv/__init__.h +++ b/shared-module/_environ/__init__.h @@ -24,13 +24,22 @@ * THE SOFTWARE. */ +#pragma once + +typedef enum { + ENVIRON_OK = 0, + ENVIRON_ERR_OPEN, + ENVIRON_ERR_UNICODE, + ENVIRON_ERR_LENGTH, + ENVIRON_ERR_NOT_FOUND, + ENVIRON_ERR_UNEXPECTED = 0xff00, // logical or'd with the byte value +} _environ_err_t; + // Allocation free version that returns the full length of the value. -mp_int_t dotenv_get_key(const char *path, const char *key, char *value, mp_int_t value_len); +// If it fits, the return value is 0-terminated. If the value doesn't fit, +// *value_len may be an over-estimate but never an under-estimate. +_environ_err_t _environ_get_key_str(const char *key, char *value, size_t value_len); -// Returns true and sets value to a '\0'-terminated string if key is present -// and the value (including the terminating '\0') fits strictly within -// value_len bytes. -bool dotenv_get_key_terminated(const char *path, const char *key, char *value, mp_int_t value_len); - -// Returns true and sets value to the read value. Returns false if the value was not numeric. -bool dotenv_get_key_int(const char *path, const char *key, mp_int_t *value); +// Returns ENVIRON_ERR_OK and sets value to the read value. Returns +// ENVIRON_ERR_... if the value was not numeric. allocation-free. +_environ_err_t _environ_get_key_int(const char *key, mp_int_t *value); diff --git a/shared-module/dotenv/__init__.c b/shared-module/dotenv/__init__.c deleted file mode 100644 index ead7c6561b..0000000000 --- a/shared-module/dotenv/__init__.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * SPDX-FileCopyrightText: 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. - */ - -#include -#include - -#include "shared-bindings/dotenv/__init__.h" - -#include "py/misc.h" -#include "py/mpstate.h" -#include "py/objstr.h" -#include "supervisor/filesystem.h" - -#if defined(UNIX) -typedef FILE *file_arg; -STATIC bool open_file(const char *name, file_arg *active_file) { - FILE *result = fopen(name, "r"); - if (result) { - *active_file = result; - } - return result != NULL; -} -STATIC void close_file(file_arg *active_file) { - fclose(*active_file); -} -STATIC uint8_t get_next_character(file_arg *active_file) { - int value = fgetc(*active_file); - if (value == EOF) { - return 0; - } - return value; -} -STATIC void seek_minus_one(file_arg *active_file) { - fseek(*active_file, -1, SEEK_CUR); -} -#else -#include "extmod/vfs.h" -#include "extmod/vfs_fat.h" -typedef FIL file_arg; -STATIC bool open_file(const char *name, file_arg *active_file) { - FATFS *fs = filesystem_circuitpy(); - FRESULT result = f_open(fs, active_file, name, FA_READ); - return result == FR_OK; -} -STATIC void close_file(file_arg *active_file) { - // nothing -} - -// Return 0 if there is no next character (EOF). -STATIC uint8_t get_next_character(FIL *active_file) { - uint8_t character = 0; - UINT quantity_read; - // If there's an error or quantity_read is 0, character will remain 0. - f_read(active_file, &character, 1, &quantity_read); - return character; -} -STATIC void seek_minus_one(file_arg *active_file) { - f_lseek(active_file, f_tell(active_file) - 1); -} -#endif - -// Discard whitespace, except for newlines, returning the next character after the whitespace. -// Return 0 if there is no next character (EOF). -STATIC uint8_t consume_whitespace(file_arg *active_file) { - uint8_t character; - do { - character = get_next_character(active_file); - } while (character != '\n' && character != 0 && unichar_isspace(character)); - return character; -} - -// Starting at the start of a new line, determines if the key matches the given -// key. File pointer is set to be just before the = after the key. -STATIC bool key_matches(file_arg *active_file, const char *key) { - uint8_t character; - character = consume_whitespace(active_file); - if (character == 0) { - return false; - } - bool quoted = false; - if (character == '\'') { - // Beginning of single-quoted string. - quoted = true; - character = get_next_character(active_file); - } - size_t key_pos = 0; - bool escaped = false; - bool matches = true; - size_t key_len = strlen(key); - while (character != 0) { - if (character == '\\' && !escaped && quoted) { - escaped = true; - } else if (!escaped && quoted && character == '\'') { - quoted = false; - // End of quoted key. Skip over the ending quote. - character = get_next_character(active_file); - break; - } else if (!quoted && (unichar_isspace(character) || character == '=' || character == '\n' || character == '#' || character == 0)) { - // End of unquoted key. - break; - } else { - // Still on tentative key; see if it matches the next supplied key character, - // but don't run off the end of the supplied key. - if (key_pos < key_len) { - matches = matches && (unsigned char)key[key_pos] == character; - escaped = false; - key_pos++; - } else { - // Key on line is too long. - matches = false; - } - } - character = get_next_character(active_file); - } - if (character == '=' || character == '\n' || character == '#' || character == 0) { - // Rewind one so the value, if any, can be found. - seek_minus_one(active_file); - } else if (!unichar_isspace(character)) { - // We're followed by something else that is invalid syntax. - matches = false; - } - - return matches && key_pos == key_len; -} - -STATIC bool next_line(file_arg *active_file) { - uint8_t character; - bool quoted = false; - bool escaped = false; - // Track comments because they last until the end of the line. - bool comment = false; - // Consume all characters while quoted or others up to \n. - do { - character = get_next_character(active_file); - - if ((!quoted || character == '#') || comment) { - // Comments consume any escaping. - comment = true; - } else if (!escaped) { - if (character == '\'') { - quoted = !quoted; - } else if (character == '\\') { - escaped = true; - } - } else { - escaped = false; - } - } while (character != 0 && (quoted || character != '\n')); - - return character != 0; -} - -STATIC mp_int_t read_value(file_arg *active_file, char *value, size_t value_len) { - uint8_t character; - // Consume spaces before "=", and get first character of interest. - character = consume_whitespace(active_file); - if (character != '=') { - if (character == '#' || character == '\n') { - // Keys without an = after them are valid with the value None. - return -1; - } - // All other characters are invalid. - return -1; - } - // Consume space after = - if (character != '#') { - // a # immediately after = is part of the value! - character = consume_whitespace(active_file); - } - bool quoted = false; - if (character == '\'') { - quoted = true; - character = get_next_character(active_file); - } - if (character == '"') { - // We don't support double quoted values. - return -1; - } - // Copy the value over. - size_t value_pos = 0; - bool escaped = false; - // Count trailing spaces so we can ignore them at the end of unquoted - // values. - size_t trailing_spaces = 0; - bool first_char = true; - while (character != 0) { - // Consume the first \ if the value is quoted. - if (quoted && character == '\\' && !escaped) { - escaped = true; - // Drop this backslash by short circuiting the rest of the loop. - character = get_next_character(active_file); - continue; - } - if (quoted && !escaped && character == '\'') { - // trailing ' means the value is done. - break; - } - // Unquoted values are ended by a newline or comment. - if (!quoted && (character == '\n' || (character == '#' && !first_char))) { - if (character == '\n') { - // Rewind one so the next_line can find the \n. - seek_minus_one(active_file); - } - break; - } - if (!quoted && unichar_isspace(character)) { - trailing_spaces += 1; - } else { - trailing_spaces = 0; - } - escaped = false; - // Only copy the value over if we have space. Otherwise, we'll just - // count the overall length. - if (value_pos < value_len) { - value[value_pos] = character; - } - value_pos++; - character = get_next_character(active_file); - first_char = false; - } - - return value_pos - trailing_spaces; -} - -mp_int_t dotenv_get_key(const char *path, const char *key, char *value, mp_int_t value_len) { - file_arg active_file; - if (!open_file(path, &active_file)) { - return -1; - } - - mp_int_t actual_value_len = -1; - bool read_ok = true; - while (read_ok) { - if (key_matches(&active_file, key)) { - actual_value_len = read_value(&active_file, value, value_len); - } - - read_ok = next_line(&active_file); - } - close_file(&active_file); - return actual_value_len; -} - -mp_obj_t common_hal_dotenv_get_key(const char *path, const char *key) { - // Use the stack for short values. Longer values will require a heap allocation after we know - // the length. - char value[64]; - mp_int_t actual_len = dotenv_get_key(path, key, value, sizeof(value)); - if (actual_len < 0) { - return mp_const_none; - } - if ((size_t)actual_len >= sizeof(value)) { - byte *buf = m_new(byte, actual_len + 1); - dotenv_get_key(path, key, (char *)buf, actual_len); - buf[actual_len] = 0; - - mp_obj_str_t *o = m_new_obj(mp_obj_str_t); - o->base.type = &mp_type_str; - o->len = actual_len; - o->data = buf; - o->hash = qstr_compute_hash(buf, actual_len); - - return MP_OBJ_FROM_PTR(o); - } - return mp_obj_new_str(value, actual_len); -} - -bool dotenv_get_key_terminated(const char *path, const char *key, char *value, mp_int_t value_len) { - mp_int_t actual_len = dotenv_get_key(path, key, value, value_len - 1); - if (actual_len >= value_len) { - return false; - } - value[actual_len] = '\0'; // terminate string - return true; -} - -bool dotenv_get_key_int(const char *path, const char *key, mp_int_t *value) { - char buf[16]; - if (!dotenv_get_key_terminated(path, key, buf, (mp_int_t)sizeof(buf))) { - return false; - } - char *end; - long result = strtol(buf, &end, 0); - if (end == buf || *end) { // If the whole buffer was not consumed it's an error - return false; - } - *value = (mp_int_t)result; - return true; -} diff --git a/shared-module/os/__init__.c b/shared-module/os/__init__.c index 200fcb2f61..57e7e62932 100644 --- a/shared-module/os/__init__.c +++ b/shared-module/os/__init__.c @@ -36,8 +36,8 @@ #include "py/runtime.h" #include "shared-bindings/os/__init__.h" -#if CIRCUITPY_DOTENV -#include "shared-bindings/dotenv/__init__.h" +#if CIRCUITPY_ENVIRON +#include "shared-bindings/_environ/__init__.h" #endif // This provides all VFS related OS functions so that ports can share the code @@ -112,8 +112,9 @@ mp_obj_t common_hal_os_getcwd(void) { } mp_obj_t common_hal_os_getenv(const char *key, mp_obj_t default_) { - #if CIRCUITPY_DOTENV - mp_obj_t env_obj = common_hal_dotenv_get_key("/.env", key); + #if CIRCUITPY_ENVIRON + mp_obj_t env_obj = common_hal__environ_get_key(key); + // TODO must be a str object if (env_obj != mp_const_none) { return env_obj; } diff --git a/supervisor/shared/web_workflow/static/directory.js b/supervisor/shared/web_workflow/static/directory.js index c1d934c1a8..a89d5e5602 100644 --- a/supervisor/shared/web_workflow/static/directory.js +++ b/supervisor/shared/web_workflow/static/directory.js @@ -95,7 +95,7 @@ async function refresh_list() { if (f.directory) { icon = "📁"; } else if(f.name.endsWith(".txt") || - f.name.endsWith(".env") || + f.name.endsWith(".toml") || f.name.endsWith(".py") || f.name.endsWith(".js") || f.name.endsWith(".json")) { diff --git a/supervisor/shared/web_workflow/static/welcome.html b/supervisor/shared/web_workflow/static/welcome.html index e773bb6a2e..efbb30e312 100644 --- a/supervisor/shared/web_workflow/static/welcome.html +++ b/supervisor/shared/web_workflow/static/welcome.html @@ -12,7 +12,7 @@

 Welcome!

-

Welcome to CircuitPython's Web API. Go to the file browser to work with files in the CIRCUITPY drive. Go to the full code editor for a more enriching experience which requires an active internet connection. Go to the serial terminal to see code output and interact with the REPL. Make sure you've set CIRCUITPY_WEB_API_PASSWORD='somepassword' in /.env. Provide the password when the browser prompts for it. Leave the username blank.

+

Welcome to CircuitPython's Web API. Go to the file browser to work with files in the CIRCUITPY drive. Go to the full code editor for a more enriching experience which requires an active internet connection. Go to the serial terminal to see code output and interact with the REPL. Make sure you've set CIRCUITPY_WEB_API_PASSWORD='somepassword' in /settings.toml. Provide the password when the browser prompts for it. Leave the username blank.

Device Info:

diff --git a/supervisor/shared/web_workflow/web_workflow.c b/supervisor/shared/web_workflow/web_workflow.c index 231b1e8ffb..d54f853891 100644 --- a/supervisor/shared/web_workflow/web_workflow.c +++ b/supervisor/shared/web_workflow/web_workflow.c @@ -64,8 +64,8 @@ #include "shared-bindings/wifi/__init__.h" #endif -#if CIRCUITPY_DOTENV -#include "shared-module/dotenv/__init__.h" +#if CIRCUITPY_ENVIRON +#include "shared-module/_environ/__init__.h" #endif enum request_state { @@ -115,7 +115,7 @@ static wifi_radio_error_t _last_wifi_status = WIFI_RADIO_ERROR_NONE; static mdns_server_obj_t mdns; #endif -static uint32_t web_api_port = 80; +static mp_int_t web_api_port = 80; static socketpool_socketpool_obj_t pool; static socketpool_socket_obj_t listening; @@ -244,22 +244,23 @@ void supervisor_web_workflow_status(void) { #endif void supervisor_start_web_workflow(void) { - #if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI - + #if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI && CIRCUITPY_ENVIRON char ssid[33]; char password[64]; - mp_int_t ssid_len = 0; - mp_int_t password_len = 0; + size_t ssid_len = 0; + size_t password_len = 0; - #if CIRCUITPY_DOTENV - ssid_len = dotenv_get_key("/.env", "CIRCUITPY_WIFI_SSID", ssid, sizeof(ssid) - 1); - password_len = dotenv_get_key("/.env", "CIRCUITPY_WIFI_PASSWORD", password, sizeof(password) - 1); - #endif - if (ssid_len <= 0 || (size_t)ssid_len >= sizeof(ssid) || - password_len <= 0 || (size_t)password_len >= sizeof(password)) { + _environ_err_t result = _environ_get_key_str("CIRCUITPY_WIFI_SSID", ssid, sizeof(ssid)); + if (result != ENVIRON_OK) { return; } + + result = _environ_get_key_str("CIRCUITPY_WIFI_PASSWORD", password, sizeof(password)); + if (result != ENVIRON_OK) { + return; + } + if (!common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj)) { common_hal_wifi_init(false); common_hal_wifi_radio_set_enabled(&common_hal_wifi_radio_obj, true); @@ -268,9 +269,6 @@ void supervisor_start_web_workflow(void) { // TODO: Do our own scan so that we can find the channel we want before calling connect. // Otherwise, connect will do a full slow scan to pick the best AP. - // NUL terminate the strings because dotenv doesn't. - ssid[ssid_len] = '\0'; - password[password_len] = '\0'; // We can all connect again because it will return early if we're already connected to the // network. If we are connected to a different network, then it will disconnect before // attempting to connect to the given network. @@ -283,21 +281,15 @@ void supervisor_start_web_workflow(void) { return; } - char port_encoded[6]; - size_t port_len = 0; - size_t new_port = web_api_port; - #if CIRCUITPY_DOTENV - port_len = dotenv_get_key("/.env", "CIRCUITPY_WEB_API_PORT", port_encoded, sizeof(port_encoded) - 1); - #endif - if (0 < port_len && port_len < sizeof(port_encoded)) { - port_encoded[port_len] = '\0'; - new_port = strtoul(port_encoded, NULL, 10); - } + mp_int_t new_port = web_api_port; + // (leaves new_port unchanged on any failure) + (void)_environ_get_key_int("CIRCUITPY_WEB_API_PORT", &new_port); bool first_start = pool.base.type != &socketpool_socketpool_type; bool port_changed = new_port != web_api_port; if (first_start) { + port_changed = false; #if CIRCUITPY_MDNS mdns_server_construct(&mdns, true); mdns.base.type = &mdns_server_type; @@ -326,11 +318,12 @@ void supervisor_start_web_workflow(void) { common_hal_socketpool_socket_listen(&listening, 1); } - mp_int_t api_password_len = dotenv_get_key("/.env", "CIRCUITPY_WEB_API_PASSWORD", _api_password + 1, sizeof(_api_password) - 2); - if (api_password_len > 0) { + + const size_t api_password_len = sizeof(_api_password) - 1; + result = _environ_get_key_str("CIRCUITPY_WEB_API_PASSWORD", _api_password + 1, api_password_len); + if (result == ENVIRON_OK) { _api_password[0] = ':'; - _api_password[api_password_len + 1] = '\0'; - _base64_in_place(_api_password, api_password_len + 1, sizeof(_api_password)); + _base64_in_place(_api_password, strlen(_api_password), sizeof(_api_password) - 1); } #endif } @@ -691,16 +684,16 @@ static void _reply_with_file(socketpool_socket_obj_t *socket, _request *request, mp_print_t _socket_print = {socket, _print_raw}; mp_printf(&_socket_print, "Content-Length: %d\r\n", total_length); // TODO: Make this a table to save space. - if (_endswith(filename, ".txt") || _endswith(filename, ".py")) { - _send_strs(socket, "Content-Type: text/plain", ";charset=UTF-8\r\n", NULL); + if (_endswith(filename, ".txt") || _endswith(filename, ".py") || _endswith(filename, ".toml")) { + _send_strs(socket, "Content-Type:", "text/plain", ";charset=UTF-8\r\n", NULL); } else if (_endswith(filename, ".js")) { - _send_strs(socket, "Content-Type: text/javascript", ";charset=UTF-8\r\n", NULL); + _send_strs(socket, "Content-Type:", "text/javascript", ";charset=UTF-8\r\n", NULL); } else if (_endswith(filename, ".html")) { - _send_strs(socket, "Content-Type: text/html", ";charset=UTF-8\r\n", NULL); + _send_strs(socket, "Content-Type:", "text/html", ";charset=UTF-8\r\n", NULL); } else if (_endswith(filename, ".json")) { - _send_strs(socket, "Content-Type: application/json", ";charset=UTF-8\r\n", NULL); + _send_strs(socket, "Content-Type:", "application/json", ";charset=UTF-8\r\n", NULL); } else { - _send_str(socket, "Content-Type: application/octet-stream\r\n"); + _send_strs(socket, "Content-Type:", "application/octet-stream\r\n"); } _cors_header(socket, request); _send_str(socket, "\r\n"); diff --git a/tests/circuitpython/bad1.toml b/tests/circuitpython/bad1.toml new file mode 100644 index 0000000000..fce8db1800 --- /dev/null +++ b/tests/circuitpython/bad1.toml @@ -0,0 +1 @@ +string = " diff --git a/tests/circuitpython/bad2.toml b/tests/circuitpython/bad2.toml new file mode 100644 index 0000000000..666c573716 --- /dev/null +++ b/tests/circuitpython/bad2.toml @@ -0,0 +1 @@ +string = """ diff --git a/tests/circuitpython/bad3.toml b/tests/circuitpython/bad3.toml new file mode 100644 index 0000000000..705443a1c6 --- /dev/null +++ b/tests/circuitpython/bad3.toml @@ -0,0 +1 @@ +string = diff --git a/tests/circuitpython/dotenv_test.env b/tests/circuitpython/dotenv_test.env deleted file mode 100644 index 63753b0ea4..0000000000 --- a/tests/circuitpython/dotenv_test.env +++ /dev/null @@ -1,37 +0,0 @@ -# Key "notpresent" is not present - # comment preceded by spaces -plain_value=value -value_with_comment=value # value followed by a comment -quoted_value='value' -quoted_value_with_comment='value' # quoted value followed by a comment -should_be_none -should_be_empty_string= -should_be_hash=# -quoted_should_be_empty_string='' -duplicate_key=wrong -duplicate_key=right -value_with_hash=value#value -quoted_value_with_hash='value#value' -multi_line_value='multi -line' - space_before_key=value -space_before_value= value -space_before_hash_value= #value -space_after_key =value -space_after_key_before_value = value -quoted_then_comment='value'#comment -hash_with_spaces=#value value -aa🐍bb=key with emoji -value_with_emoji=aa🐍bb -sz0=x -sz1=xx -sz2=xxxx -sz3=xxxxxxxx -sz4=xxxxxxxxxxxxxxxx -sz5=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -sz6=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -sz7=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -sz8=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -sz9=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -sz10=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -sz11=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx diff --git a/tests/circuitpython/dotenv_test.py b/tests/circuitpython/dotenv_test.py deleted file mode 100644 index 109a3bf221..0000000000 --- a/tests/circuitpython/dotenv_test.py +++ /dev/null @@ -1,31 +0,0 @@ -import dotenv - -FILE = __file__.rsplit(".", 1)[0] + ".env" - -print(f"notpresent={dotenv.get_key(FILE, 'notpresent')}") -print(f"plain_value={dotenv.get_key(FILE, 'plain_value')}") -print(f"value_with_comment={dotenv.get_key(FILE, 'value_with_comment')}") -print(f"quoted_value={dotenv.get_key(FILE, 'quoted_value')}") -print(f"quoted_value_with_comment={dotenv.get_key(FILE, 'quoted_value_with_comment')}") -print(f"should_be_none={dotenv.get_key(FILE, 'should_be_none')}") -print(f"should_be_empty_string={dotenv.get_key(FILE, 'should_be_empty_string')}") -print(f"should_be_hash={dotenv.get_key(FILE, 'should_be_hash')}") -print(f"quoted_should_be_empty_string={dotenv.get_key(FILE, 'quoted_should_be_empty_string')}") -print(f"duplicate_key={dotenv.get_key(FILE, 'duplicate_key')}") -### This is the a difference from CPython dotenv. The trailing #value is taken as a comment. -print(f"value_with_hash={dotenv.get_key(FILE, 'value_with_hash')}") -print(f"quoted_value_with_hash={dotenv.get_key(FILE, 'quoted_value_with_hash')}") -print(f"multi_line_value={dotenv.get_key(FILE, 'multi_line_value')}") -print(f"space_before_key={dotenv.get_key(FILE, 'space_before_key')}") -print(f"space_before_value={dotenv.get_key(FILE, 'space_before_value')}") -print(f"space_before_hash_value={dotenv.get_key(FILE, 'space_before_hash_value')}") -print(f"space_after_key={dotenv.get_key(FILE, 'space_after_key')}") -print(f"space_after_key_before_value={dotenv.get_key(FILE, 'space_after_key_before_value')}") -print(f"quoted_then_comment={dotenv.get_key(FILE, 'quoted_then_comment')}") -print(f"hash_with_spaces={dotenv.get_key(FILE, 'hash_with_spaces')}") -print(f"aa🐍bb={dotenv.get_key(FILE, 'aa🐍bb')}") -print(f"value_with_emoji={dotenv.get_key(FILE, 'value_with_emoji')}") - -for i in range(12): - key = f"sz{i}" - print(f"len({key})={len(dotenv.get_key(FILE, key))}") diff --git a/tests/circuitpython/dotenv_test.py.exp b/tests/circuitpython/dotenv_test.py.exp deleted file mode 100644 index e0ed5f1505..0000000000 --- a/tests/circuitpython/dotenv_test.py.exp +++ /dev/null @@ -1,35 +0,0 @@ -notpresent=None -plain_value=value -value_with_comment=value -quoted_value=value -quoted_value_with_comment=value -should_be_none=None -should_be_empty_string= -should_be_hash=# -quoted_should_be_empty_string= -duplicate_key=right -value_with_hash=value -quoted_value_with_hash=value#value -multi_line_value=multi -line -space_before_key=value -space_before_value=value -space_before_hash_value=#value -space_after_key=value -space_after_key_before_value=value -quoted_then_comment=value -hash_with_spaces=#value value -aa🐍bb=key with emoji -value_with_emoji=aa🐍bb -len(sz0)=1 -len(sz1)=2 -len(sz2)=4 -len(sz3)=8 -len(sz4)=16 -len(sz5)=32 -len(sz6)=64 -len(sz7)=128 -len(sz8)=256 -len(sz9)=512 -len(sz10)=1024 -len(sz11)=2048 diff --git a/tests/circuitpython/environ_test.py b/tests/circuitpython/environ_test.py new file mode 100644 index 0000000000..46ceff5c9d --- /dev/null +++ b/tests/circuitpython/environ_test.py @@ -0,0 +1,42 @@ +import os + +try: + from _environ import get_key +except: + # Because run-tests.py suppresses site-packages, this test can't be run + # on the host interpreter. However, it can be run manually to + # generate/update the expected file. + # + # After 3.11 becomes standard, change this to use tomllib. + import tomlkit + + def get_key(filename, key): + with open(filename) as f: + s = tomlkit.load(f) + return s.get(key, None) + + +def run_test(f, k=None): + try: + v = get_key(f"{BASE}/{f}.toml", k or f) + print(f, k, repr(v)) + except Exception as e: + print(f, k, "err") + + +if "/" in __file__: + BASE = __file__.rsplit("/", 1)[0] +else: + BASE = "." + +run_test("good", "notpresent") +run_test("good", "string") +run_test("good", "number") +run_test("good", "cstring") +run_test("good", "cnumber") +run_test("good", "subvalue") +for i in range(8): + run_test("good", f"string{i}") +run_test("bad1", "string") +run_test("bad2", "string") +run_test("bad3", "string") diff --git a/tests/circuitpython/environ_test.py.exp b/tests/circuitpython/environ_test.py.exp new file mode 100644 index 0000000000..f168b089c0 --- /dev/null +++ b/tests/circuitpython/environ_test.py.exp @@ -0,0 +1,17 @@ +good notpresent None +good string 'hello world' +good number 7 +good cstring 'hello comment' +good cnumber 127 +good subvalue None +good string0 None +good string1 '\n' +good string2 'Áx' +good string3 'Áx' +good string4 '\x0c"\\' +good string5 '\t\r\x08' +good string6 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +good string7 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +bad1 string err +bad2 string err +bad3 string err diff --git a/tests/circuitpython/good.toml b/tests/circuitpython/good.toml new file mode 100644 index 0000000000..17e5c054f4 --- /dev/null +++ b/tests/circuitpython/good.toml @@ -0,0 +1,14 @@ +# comment +string = "hello world" +number = 7 + cstring = "hello comment" # comment + cnumber = 0x7f # comment +string1= "\n" +string2 ="\u00c1x" +string3 = "\U000000c1x" +string4 = "\f\"\\" +string5 = "\t\r\b" +string6 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +string7 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +[section] +subvalue = "hi" diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index 782ab95cc8..4483eeb0c1 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -29,10 +29,10 @@ RuntimeError: ame__ mport -builtins micropython _asyncio _thread -_uasyncio aesio array binascii -bitmaptools btree cexample cmath -collections cppexample displayio dotenv +builtins micropython _asyncio _environ +_thread _uasyncio aesio array +binascii bitmaptools btree cexample +cmath collections cppexample displayio errno ffi framebuf gc gifio hashlib json math qrio rainbowio re sys From 1fe05cb8cd5d46252dff65436b58d5bfb965e23b Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 8 Dec 2022 12:44:34 -0600 Subject: [PATCH 02/34] pico w: re-use previous connection if ssid matches --- ports/raspberrypi/common-hal/wifi/Radio.c | 26 +++++++++++++++++++++++ ports/raspberrypi/common-hal/wifi/Radio.h | 2 ++ 2 files changed, 28 insertions(+) diff --git a/ports/raspberrypi/common-hal/wifi/Radio.c b/ports/raspberrypi/common-hal/wifi/Radio.c index 313363dd32..a13222152b 100644 --- a/ports/raspberrypi/common-hal/wifi/Radio.c +++ b/ports/raspberrypi/common-hal/wifi/Radio.c @@ -206,6 +206,22 @@ void common_hal_wifi_radio_stop_ap(wifi_radio_obj_t *self) { */ } +static bool connection_unchanged(wifi_radio_obj_t *self, const uint8_t *ssid, size_t ssid_len) { + if (cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) != CYW43_LINK_UP) { + mp_printf(&mp_plat_print, "(not connected)\n"); + return false; + } + if (ssid_len != self->connected_ssid_len) { + mp_printf(&mp_plat_print, "(length mismatch)\n"); + return false; + } + if (memcmp(ssid, self->connected_ssid, self->connected_ssid_len)) { + mp_printf(&mp_plat_print, "(ssid mismatch)\n"); + return false; + } + return true; +} + wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t *ssid, size_t ssid_len, uint8_t *password, size_t password_len, uint8_t channel, mp_float_t timeout, uint8_t *bssid, size_t bssid_len) { if (!common_hal_wifi_radio_get_enabled(self)) { mp_raise_RuntimeError(translate("Wifi is not enabled")); @@ -215,11 +231,19 @@ wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t mp_raise_RuntimeError(translate("Wifi is in access point mode.")); } + if (ssid_len > 32) { + return WIFI_RADIO_ERROR_CONNECTION_FAIL; + } size_t timeout_ms = timeout <= 0 ? 8000 : (size_t)MICROPY_FLOAT_C_FUN(ceil)(timeout * 1000); uint64_t start = port_get_raw_ticks(NULL); uint64_t deadline = start + timeout_ms; + if (connection_unchanged(self, ssid, ssid_len)) { + mp_printf(&mp_plat_print, "re-used existing wifi connection"); + return WIFI_RADIO_ERROR_NONE; + } + // disconnect common_hal_wifi_radio_stop_station(self); @@ -237,6 +261,8 @@ wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t switch (result) { case CYW43_LINK_UP: + memcpy(self->connected_ssid, ssid, ssid_len); + self->connected_ssid_len = ssid_len; bindings_cyw43_wifi_enforce_pm(); return WIFI_RADIO_ERROR_NONE; case CYW43_LINK_FAIL: diff --git a/ports/raspberrypi/common-hal/wifi/Radio.h b/ports/raspberrypi/common-hal/wifi/Radio.h index b2e9df9e3a..a4125fe7ba 100644 --- a/ports/raspberrypi/common-hal/wifi/Radio.h +++ b/ports/raspberrypi/common-hal/wifi/Radio.h @@ -35,6 +35,8 @@ typedef struct { mp_obj_base_t base; char hostname[254]; // hostname max is 253 chars, + 1 for trailing NUL wifi_scannednetworks_obj_t *current_scan; + uint8_t connected_ssid[32]; + uint8_t connected_ssid_len; bool enabled; } wifi_radio_obj_t; From 47339d42489822ecc65367f1e94328d144e0bb84 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 8 Dec 2022 12:56:24 -0600 Subject: [PATCH 03/34] make a settings.toml file on boards that support the feature --- supervisor/shared/filesystem.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/supervisor/shared/filesystem.c b/supervisor/shared/filesystem.c index 01aba0a9ac..2c963b78ef 100644 --- a/supervisor/shared/filesystem.c +++ b/supervisor/shared/filesystem.c @@ -129,6 +129,9 @@ bool filesystem_init(bool create_allowed, bool force_create) { make_empty_file(&vfs_fat->fatfs, "/.metadata_never_index"); make_empty_file(&vfs_fat->fatfs, "/.Trashes"); make_empty_file(&vfs_fat->fatfs, "/.fseventsd/no_log"); + #if CIRCUITPY_ENVIRON + make_empty_file(&vfs_fat->fatfs, "/settings.toml"); + #endif // make a sample code.py file make_sample_code_file(&vfs_fat->fatfs); From a05829528b8a2525b1e887b708838fa3af99035e Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 8 Dec 2022 13:36:48 -0600 Subject: [PATCH 04/34] _environ: update documentation --- shared-bindings/_environ/__init__.c | 58 ++++++++++++++++------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/shared-bindings/_environ/__init__.c b/shared-bindings/_environ/__init__.c index 81d778f3ed..a35181b754 100644 --- a/shared-bindings/_environ/__init__.c +++ b/shared-bindings/_environ/__init__.c @@ -35,47 +35,55 @@ #include "py/runtime.h" #include "shared-bindings/_environ/__init__.h" -//| """Functions to manage environment variables from a .env file. +//| """Functions to manage environment variables from a settings.toml file. //| -//| A subset of the CPython `_environ library `_. It does -//| not support variables or double quotes. +//| This library can read a subset of `toml files `_. //| -//| Keys and values may be put in single quotes. -//| ``\`` and ``'`` are escaped by ``\`` in single quotes. Newlines can occur in quotes for multiline values. -//| Comments start with ``#`` and apply for the rest of the line. -//| A ``#`` immediately following an ``=`` is part of the value, not the start of a comment, -//| and a ``#`` embedded in a value without whitespace will be part of that value. -//| This corresponds to how assignments and comments work in most Unix shells. +//| It is recommended to not use this module directly. Instead, retrieve string +//| values using `os.getenv`. //| +//| Due to technical limitations it probably also accepts some files that are +//| not valid TOML files; bugs of this nature are subject to change (i.e., be +//| fixed) without the usual deprecation period for incompatible changes. +//| +//| Details of the format understood by this module: +//| * the content is required to be in UTF-8 encoding +//| * the supported data types are string and integer +//| * only integers and basic strings are supported +//| * only integers supported by strtol are supported (no 0o, no 0b, no +//| underscores 1_000, 011 is 9, not 11) +//| * In quoted strings, all standard eescape codes, including ``\\uxxxx`` +//| and ``\\Uxxxxxxxx``, are supported +//| * only bare keys are supported +//| * duplicate keys are not diagnosed. +//| * comments are supported +//| * only values from the "root table" can be retrieved (parsing ends when it +//| encounters a line starting with [) +//| * due to technical limitations, the content of multi-line +//| strings can erroneously be parsed as a value. //| //| File format example: //| //| .. code-block:: //| -//| key=value -//| key2 = value2 -//| 'key3' = 'value with spaces' +//| str_key="Hello world" # with trailing comment +//| int_key = 7 +//| unicode_key="👨" +//| unicode_key2="\\U0001f468" # same as above +//| escape_codes="supported, including \\r\\n\\"\\\\" //| # comment -//| key4 = value3 # comment 2 -//| 'key5'=value4 -//| key=value5 # overrides the first one -//| multiline = 'hello -//| world -//| how are you?' -//| # The #'s below will be included in the value. They do not start a comment. -//| key6=#value -//| key7=abc#def +//| [subtable] +//| subvalue="cannot retrieve this using _environ or getenv" //| //| """ //| //| import typing //| -//| def get_key(_environ_path: str, key_to_get: str) -> Optional[str]: -//| """Get the value for the given key from the given .env file. If the key occurs multiple -//| times in the file, then the last value will be returned. +//| def get_key(_environ_path: str, key_to_get: str) -> Union[str, int, None]: +//| """Get the value for the given key from the given .env file. //| -//| Returns None if the key isn't found or doesn't have a value.""" +//| Returns None if the key isn't found""" //| ... //| STATIC mp_obj_t __environ_get_key(mp_obj_t path_in, mp_obj_t key_to_get_in) { From 19ad1d5f53e649de34214611f367c8f3a54b550e Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 8 Dec 2022 14:12:59 -0600 Subject: [PATCH 05/34] update translations --- locale/circuitpython.pot | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 16a682cfdd..43c7a79ff7 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -1002,7 +1002,7 @@ msgstr "" msgid "File exists" msgstr "" -#: shared-module/dotenv/__init__.c +#: shared-module/_environ/__init__.c msgid "File not found" msgstr "" @@ -1062,6 +1062,8 @@ msgstr "" #: shared-bindings/displayio/Display.c #: shared-bindings/displayio/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c +#: shared-module/displayio/Display.c +#: shared-module/framebufferio/FramebufferDisplay.c msgid "Group already used" msgstr "" @@ -1188,7 +1190,7 @@ msgid "Internal define error" msgstr "" #: ports/espressif/common-hal/paralleldisplay/ParallelBus.c -#: shared-module/dotenv/__init__.c +#: shared-module/_environ/__init__.c msgid "Internal error" msgstr "" @@ -1235,7 +1237,7 @@ msgstr "" msgid "Invalid bits per value" msgstr "" -#: shared-module/dotenv/__init__.c +#: shared-module/_environ/__init__.c #, c-format msgid "Invalid byte %.*s" msgstr "" @@ -1270,7 +1272,7 @@ msgstr "" msgid "Invalid state" msgstr "" -#: shared-module/dotenv/__init__.c +#: shared-module/_environ/__init__.c msgid "Invalid unicode escape" msgstr "" @@ -1278,7 +1280,7 @@ msgstr "" msgid "Key must be 16, 24, or 32 bytes long" msgstr "" -#: shared-module/dotenv/__init__.c +#: shared-module/_environ/__init__.c msgid "Key not found" msgstr "" @@ -2280,7 +2282,7 @@ msgid "Unkown error code %d" msgstr "" #: shared-bindings/adafruit_pixelbuf/PixelBuf.c -#: shared-module/adafruit_pixelbuf/PixelMap.c +#: shared-module/_pixelmap/PixelMap.c #, c-format msgid "Unmatched number of items on RHS (expected %d, got %d)." msgstr "" @@ -3161,7 +3163,7 @@ msgstr "" msgid "index is out of bounds" msgstr "" -#: shared-bindings/adafruit_pixelbuf/PixelMap.c +#: shared-bindings/_pixelmap/PixelMap.c msgid "index must be tuple or int" msgstr "" @@ -3540,7 +3542,7 @@ msgstr "" msgid "negative shift count" msgstr "" -#: shared-bindings/adafruit_pixelbuf/PixelMap.c +#: shared-bindings/_pixelmap/PixelMap.c msgid "nested index must be int" msgstr "" From 170918995c1a3fde1b9c7694e451c2292181fc45 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 8 Dec 2022 14:14:48 -0600 Subject: [PATCH 06/34] fix mistaken code formatting I wanted to use the idiom ```c #if GUARD if (condition) { alternate code } else #else { common default code } ``` idiom, in which the common default code is conditioned both on a compile-time check and a run-time check. However, I got it wrong and uncrustify chipped in, adding extra brackets around a following piece of code and re-indenting it. --- ports/espressif/common-hal/_bleio/Adapter.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/ports/espressif/common-hal/_bleio/Adapter.c b/ports/espressif/common-hal/_bleio/Adapter.c index 121beb8e90..f89848f782 100644 --- a/ports/espressif/common-hal/_bleio/Adapter.c +++ b/ports/espressif/common-hal/_bleio/Adapter.c @@ -107,18 +107,16 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable if (result == ENVIRON_OK) { ble_svc_gap_device_name_set(ble_name); } else - #else + #endif { ble_svc_gap_device_name_set("CIRCUITPY"); } - #endif - {// Clear all of the internal connection objects. - for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { - bleio_connection_internal_t *connection = &bleio_connections[i]; - // Reset connection. - connection->conn_handle = BLEIO_HANDLE_INVALID; - } + // Clear all of the internal connection objects. + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &bleio_connections[i]; + // Reset connection. + connection->conn_handle = BLEIO_HANDLE_INVALID; } cp_task = xTaskGetCurrentTaskHandle(); From 243ecc250289fe66fd3b7ccedba117f2ec8924fb Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 8 Dec 2022 14:18:22 -0600 Subject: [PATCH 07/34] remove debugging prints --- ports/raspberrypi/common-hal/wifi/Radio.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ports/raspberrypi/common-hal/wifi/Radio.c b/ports/raspberrypi/common-hal/wifi/Radio.c index a13222152b..4cd80fb4b7 100644 --- a/ports/raspberrypi/common-hal/wifi/Radio.c +++ b/ports/raspberrypi/common-hal/wifi/Radio.c @@ -208,15 +208,12 @@ void common_hal_wifi_radio_stop_ap(wifi_radio_obj_t *self) { static bool connection_unchanged(wifi_radio_obj_t *self, const uint8_t *ssid, size_t ssid_len) { if (cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) != CYW43_LINK_UP) { - mp_printf(&mp_plat_print, "(not connected)\n"); return false; } if (ssid_len != self->connected_ssid_len) { - mp_printf(&mp_plat_print, "(length mismatch)\n"); return false; } if (memcmp(ssid, self->connected_ssid, self->connected_ssid_len)) { - mp_printf(&mp_plat_print, "(ssid mismatch)\n"); return false; } return true; @@ -240,7 +237,6 @@ wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t uint64_t deadline = start + timeout_ms; if (connection_unchanged(self, ssid, ssid_len)) { - mp_printf(&mp_plat_print, "re-used existing wifi connection"); return WIFI_RADIO_ERROR_NONE; } From 3459fe322b45bd1443fca8e12126d3919aa8784c Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 8 Dec 2022 15:21:20 -0600 Subject: [PATCH 08/34] Withdraw the _environ module This existed solely for testing, so expose it a different way during the unix coverage build Also turn off os.getenv support on samd21. --- devices/ble_hci/common-hal/_bleio/Adapter.c | 8 +- docs/environment.rst | 36 ++++-- ports/atmel-samd/mpconfigport.mk | 1 + ports/espressif/common-hal/_bleio/Adapter.c | 8 +- ports/espressif/supervisor/port.c | 4 +- ports/nrf/common-hal/_bleio/Adapter.c | 8 +- ports/unix/coverage.c | 1 + ports/unix/main.c | 8 ++ .../unix/variants/coverage/mpconfigvariant.mk | 5 +- py/circuitpy_defns.mk | 4 +- py/circuitpy_mpconfig.mk | 4 +- shared-bindings/_environ/__init__.c | 108 ------------------ shared-bindings/_environ/__init__.h | 37 ------ shared-bindings/os/__init__.c | 4 + shared-bindings/os/__init__.h | 2 + shared-bindings/os/getenv.c | 1 + shared-module/os/__init__.c | 15 --- shared-module/{_environ => os}/__init__.h | 6 +- .../{_environ/__init__.c => os/getenv.c} | 39 ++++--- supervisor/shared/filesystem.c | 2 +- supervisor/shared/web_workflow/web_workflow.c | 14 +-- tests/circuitpython/environ_test.py | 4 +- 22 files changed, 93 insertions(+), 226 deletions(-) delete mode 100644 shared-bindings/_environ/__init__.c delete mode 100644 shared-bindings/_environ/__init__.h create mode 100644 shared-bindings/os/getenv.c rename shared-module/{_environ => os}/__init__.h (89%) rename shared-module/{_environ/__init__.c => os/getenv.c} (88%) diff --git a/devices/ble_hci/common-hal/_bleio/Adapter.c b/devices/ble_hci/common-hal/_bleio/Adapter.c index 018b65de12..f558d66d40 100644 --- a/devices/ble_hci/common-hal/_bleio/Adapter.c +++ b/devices/ble_hci/common-hal/_bleio/Adapter.c @@ -49,8 +49,8 @@ #include "shared-bindings/_bleio/ScanEntry.h" #include "shared-bindings/time/__init__.h" -#if CIRCUITPY_ENVIRON -#include "shared-bindings/_environ/__init__.h" +#if CIRCUITPY_OS_GETENV +#include "shared-bindings/os/__init__.h" #endif #define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) @@ -284,8 +284,8 @@ char default_ble_name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 0, 0, 0 STATIC void bleio_adapter_hci_init(bleio_adapter_obj_t *self) { mp_int_t name_len = 0; - #if CIRCUITPY_ENVIRON - mp_obj_t name = common_hal__environ_get_key("CIRCUITPY_BLE_NAME"); + #if CIRCUITPY_OS_GETENV + mp_obj_t name = common_hal_os_getenv("CIRCUITPY_BLE_NAME", mp_const_none); if (name != mp_const_none) { mp_arg_validate_type_string(name, MP_QSTR_CIRCUITPY_BLE_NAME); self->name = name; diff --git a/docs/environment.rst b/docs/environment.rst index 457e5c3f88..0a370d64d9 100644 --- a/docs/environment.rst +++ b/docs/environment.rst @@ -6,23 +6,33 @@ variables are commonly used to store "secrets" such as Wi-Fi passwords and API keys. This method *does not* make them secure. It only separates them from the code. -CircuitPython supports these by parsing a subset of the `toml `_ file format internally. +CircuitPython uses a file called ``settings.toml`` at the drive root (no +folder) as the environment. User code can access the values from the file +using `os.getenv()`. It is recommended to save any values used repeatedly in a +variable because `os.getenv()` will parse the ``settings.toml`` file contents +on every access. -Here is a simple example: +CircuitPython only supports a subset of the full toml specification, see below +for more details. The subset is very "Python-like", which is a key reason we +selected the format. -.. code-block:: bash +Due to technical limitations it probably also accepts some files that are +not valid TOML files; bugs of this nature are subject to change (i.e., be +fixed) without the usual deprecation period for incompatible changes. - KEY1="value1" - # Comment - KEY2="value2\ncontains a newline" +File format example: - [SECTION] # Only values in the "root table" are parsed - SECTION_VALUE = ... # so this value cannot be seen by getenv +.. code-block:: + + str_key="Hello world" # with trailing comment + int_key = 7 + unicode_key="👨" + unicode_key2="\\U0001f468" # same as above + escape_codes="supported, including \\r\\n\\"\\\\" + # comment + [subtable] + subvalue="cannot retrieve this using _environ or getenv" -CircuitPython uses the ``settings.toml`` at the drive root (no folder) as the environment. -User code can access the values from the file using `os.getenv()`. It is -recommended to save any values used repeatedly in a variable because `os.getenv()` -will parse the ``settings.toml`` file contents on every access. Details of the toml language subset ----------------------------------- @@ -36,6 +46,8 @@ Details of the toml language subset * Duplicate keys are not diagnosed. * Comments are supported * Only values from the "root table" can be retrieved +* due to technical limitations, the content of multi-line + strings can erroneously be parsed as a value. CircuitPython behavior ---------------------- diff --git a/ports/atmel-samd/mpconfigport.mk b/ports/atmel-samd/mpconfigport.mk index 05aed89eb2..72b1302227 100644 --- a/ports/atmel-samd/mpconfigport.mk +++ b/ports/atmel-samd/mpconfigport.mk @@ -33,6 +33,7 @@ CIRCUITPY_BLEIO_HCI = 0 CIRCUITPY_BUILTINS_POW3 ?= 0 CIRCUITPY_COMPUTED_GOTO_SAVE_SPACE ?= 1 CIRCUITPY_COUNTIO ?= 0 +CIRCUITPY_OS_GETENV ?= 0 # Not enough RAM for framebuffers CIRCUITPY_FRAMEBUFFERIO ?= 0 CIRCUITPY_FREQUENCYIO ?= 0 diff --git a/ports/espressif/common-hal/_bleio/Adapter.c b/ports/espressif/common-hal/_bleio/Adapter.c index f89848f782..7da1cd0b8c 100644 --- a/ports/espressif/common-hal/_bleio/Adapter.c +++ b/ports/espressif/common-hal/_bleio/Adapter.c @@ -59,8 +59,8 @@ #include "esp_bt.h" #include "esp_nimble_hci.h" -#if CIRCUITPY_ENVIRON -#include "shared-module/_environ/__init__.h" +#if CIRCUITPY_OS_GETENV +#include "shared-module/os/__init__.h" #endif bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; @@ -101,9 +101,9 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable ble_hs_cfg.sync_cb = _on_sync; // ble_hs_cfg.store_status_cb = ble_store_util_status_rr; - #if CIRCUITPY_ENVIRON + #if CIRCUITPY_OS_GETENV char ble_name[1 + MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH]; - _environ_err_t result = _environ_get_key_str("CIRCUITPY_BLE_NAME", ble_name, sizeof(ble_name)); + os_environ_err_t result = common_hal_os_environ_get_key_str("CIRCUITPY_BLE_NAME", ble_name, sizeof(ble_name)); if (result == ENVIRON_OK) { ble_svc_gap_device_name_set(ble_name); } else diff --git a/ports/espressif/supervisor/port.c b/ports/espressif/supervisor/port.c index e89fb8c976..2792792455 100644 --- a/ports/espressif/supervisor/port.c +++ b/ports/espressif/supervisor/port.c @@ -55,7 +55,7 @@ #include "shared-bindings/microcontroller/RunMode.h" #include "shared-bindings/rtc/__init__.h" #include "shared-bindings/socketpool/__init__.h" -#include "shared-module/_environ/__init__.h" +#include "shared-module/os/__init__.h" #include "peripherals/rmt.h" #include "peripherals/timer.h" @@ -519,7 +519,7 @@ void port_idle_until_interrupt(void) { void port_post_boot_py(bool heap_valid) { if (!heap_valid && filesystem_present()) { mp_int_t reserved; - if (_environ_get_key_int("CIRCUITPY_RESERVED_PSRAM", &reserved) == ENVIRON_OK) { + if (common_hal_os_environ_get_key_int("CIRCUITPY_RESERVED_PSRAM", &reserved) == ENVIRON_OK) { common_hal_espidf_set_reserved_psram(reserved); } common_hal_espidf_reserve_psram(); diff --git a/ports/nrf/common-hal/_bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c index 012430704a..f9e3bddc72 100644 --- a/ports/nrf/common-hal/_bleio/Adapter.c +++ b/ports/nrf/common-hal/_bleio/Adapter.c @@ -52,8 +52,8 @@ #include "shared-bindings/_bleio/ScanEntry.h" #include "shared-bindings/time/__init__.h" -#if CIRCUITPY_ENVIRON -#include "shared-bindings/_environ/__init__.h" +#if CIRCUITPY_OS_GETENV +#include "shared-bindings/os/getenv.h" #endif #define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS) @@ -345,8 +345,8 @@ STATIC void bleio_adapter_reset_name(bleio_adapter_obj_t *self) { mp_int_t name_len = 0; - #if CIRCUITPY_ENVIRON - mp_obj_t ble_name = common_hal__environ_get_key("CIRCUITPY_BLE_NAME"); + #if CIRCUITPY_OS_GETENV + mp_obj_t ble_name = common_hal_os_environ_get_key("CIRCUITPY_BLE_NAME"); if (ble_name != mp_const_none) { common_hal_bleio_adapter_set_name(self, mp_obj_str_get_str(ble_name)); return; diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index 0e4c6dbd48..8463c169e4 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -95,6 +95,7 @@ STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) }, + { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) }, }; STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); diff --git a/ports/unix/main.c b/ports/unix/main.c index 5ebcf9193b..aa7c92dcff 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -420,6 +420,13 @@ STATIC void set_sys_argv(char *argv[], int argc, int start_arg) { #define PATHLIST_SEP_CHAR ':' #endif +mp_obj_t common_hal_os_getenv_path(const char *path, const char *key, mp_obj_t default_); +STATIC mp_obj_t get_key(mp_obj_t path_in, mp_obj_t key_to_get_in) { + return common_hal_os_getenv_path(mp_obj_str_get_str(path_in), + mp_obj_str_get_str(key_to_get_in), mp_const_none); +} +MP_DEFINE_CONST_FUN_OBJ_2(get_key_obj, get_key); + MP_NOINLINE int main_(int argc, char **argv); int main(int argc, char **argv) { @@ -540,6 +547,7 @@ MP_NOINLINE int main_(int argc, char **argv) { MP_DECLARE_CONST_FUN_OBJ_0(extra_cpp_coverage_obj); mp_store_global(MP_QSTR_extra_coverage, MP_OBJ_FROM_PTR(&extra_coverage_obj)); mp_store_global(MP_QSTR_extra_cpp_coverage, MP_OBJ_FROM_PTR(&extra_cpp_coverage_obj)); + mp_store_global(MP_QSTR_get_key, MP_OBJ_FROM_PTR(&get_key_obj)); } #endif diff --git a/ports/unix/variants/coverage/mpconfigvariant.mk b/ports/unix/variants/coverage/mpconfigvariant.mk index a0e0f4f3bb..e351fc0836 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.mk +++ b/ports/unix/variants/coverage/mpconfigvariant.mk @@ -33,7 +33,6 @@ SRC_BITMAP := \ shared-bindings/aesio/__init__.c \ shared-bindings/bitmaptools/__init__.c \ shared-bindings/displayio/Bitmap.c \ - shared-bindings/_environ/__init__.c \ shared-bindings/rainbowio/__init__.c \ shared-bindings/traceback/__init__.c \ shared-bindings/util.c \ @@ -45,7 +44,7 @@ SRC_BITMAP := \ shared-module/displayio/Bitmap.c \ shared-module/displayio/ColorConverter.c \ shared-module/displayio/ColorConverter.c \ - shared-module/_environ/__init__.c \ + shared-module/os/getenv.c \ shared-module/rainbowio/__init__.c \ shared-module/traceback/__init__.c \ shared-module/zlib/__init__.c \ @@ -56,7 +55,7 @@ CFLAGS += \ -DCIRCUITPY_AESIO=1 \ -DCIRCUITPY_BITMAPTOOLS=1 \ -DCIRCUITPY_DISPLAYIO_UNIX=1 \ - -DCIRCUITPY_ENVIRON=1 \ + -DCIRCUITPY_OS_GETENV=1 \ -DCIRCUITPY_GIFIO=1 \ -DCIRCUITPY_RAINBOWIO=1 \ -DCIRCUITPY_TRACEBACK=1 \ diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 7d8fa6bada..df3f664864 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -182,9 +182,6 @@ endif ifeq ($(CIRCUITPY_DISPLAYIO),1) SRC_PATTERNS += displayio/% endif -ifeq ($(CIRCUITPY_ENVIRON),1) -SRC_PATTERNS += _environ/% -endif ifeq ($(CIRCUITPY__EVE),1) SRC_PATTERNS += _eve/% endif @@ -618,6 +615,7 @@ SRC_SHARED_MODULE_ALL = \ onewireio/__init__.c \ onewireio/OneWire.c \ os/__init__.c \ + os/getenv.c \ paralleldisplay/ParallelBus.c \ qrio/__init__.c \ qrio/QRDecoder.c \ diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index a6a1118d2d..f0e145998b 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -215,8 +215,8 @@ CFLAGS += -DCIRCUITPY_DUALBANK=$(CIRCUITPY_DUALBANK) CIRCUITPY_ENABLE_MPY_NATIVE ?= 0 CFLAGS += -DCIRCUITPY_ENABLE_MPY_NATIVE=$(CIRCUITPY_ENABLE_MPY_NATIVE) -CIRCUITPY_ENVIRON ?= $(CIRCUITPY_FULL_BUILD) -CFLAGS += -DCIRCUITPY_ENVIRON=$(CIRCUITPY_ENVIRON) +CIRCUITPY_OS_GETENV ?= $(CIRCUITPY_FULL_BUILD) +CFLAGS += -DCIRCUITPY_OS_GETENV=$(CIRCUITPY_OS_GETENV) CIRCUITPY_ERRNO ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_ERRNO=$(CIRCUITPY_ERRNO) diff --git a/shared-bindings/_environ/__init__.c b/shared-bindings/_environ/__init__.c deleted file mode 100644 index a35181b754..0000000000 --- a/shared-bindings/_environ/__init__.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * SPDX-FileCopyrightText: 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. - */ - -#include - -#include "extmod/vfs.h" -#include "lib/oofatfs/ff.h" -#include "lib/oofatfs/diskio.h" -#include "py/mpstate.h" -#include "py/obj.h" -#include "py/objstr.h" -#include "py/runtime.h" -#include "shared-bindings/_environ/__init__.h" - -//| """Functions to manage environment variables from a settings.toml file. -//| -//| This library can read a subset of `toml files `_. -//| -//| It is recommended to not use this module directly. Instead, retrieve string -//| values using `os.getenv`. -//| -//| Due to technical limitations it probably also accepts some files that are -//| not valid TOML files; bugs of this nature are subject to change (i.e., be -//| fixed) without the usual deprecation period for incompatible changes. -//| -//| Details of the format understood by this module: -//| * the content is required to be in UTF-8 encoding -//| * the supported data types are string and integer -//| * only integers and basic strings are supported -//| * only integers supported by strtol are supported (no 0o, no 0b, no -//| underscores 1_000, 011 is 9, not 11) -//| * In quoted strings, all standard eescape codes, including ``\\uxxxx`` -//| and ``\\Uxxxxxxxx``, are supported -//| * only bare keys are supported -//| * duplicate keys are not diagnosed. -//| * comments are supported -//| * only values from the "root table" can be retrieved (parsing ends when it -//| encounters a line starting with [) -//| * due to technical limitations, the content of multi-line -//| strings can erroneously be parsed as a value. -//| -//| File format example: -//| -//| .. code-block:: -//| -//| str_key="Hello world" # with trailing comment -//| int_key = 7 -//| unicode_key="👨" -//| unicode_key2="\\U0001f468" # same as above -//| escape_codes="supported, including \\r\\n\\"\\\\" -//| # comment -//| [subtable] -//| subvalue="cannot retrieve this using _environ or getenv" -//| -//| """ -//| -//| import typing -//| - -//| def get_key(_environ_path: str, key_to_get: str) -> Union[str, int, None]: -//| """Get the value for the given key from the given .env file. -//| -//| Returns None if the key isn't found""" -//| ... -//| -STATIC mp_obj_t __environ_get_key(mp_obj_t path_in, mp_obj_t key_to_get_in) { - return common_hal__environ_get_key_path(mp_obj_str_get_str(path_in), - mp_obj_str_get_str(key_to_get_in)); -} -MP_DEFINE_CONST_FUN_OBJ_2(_environ_get_key_obj, __environ_get_key); - -STATIC const mp_rom_map_elem_t _environ_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__environ) }, - - { MP_ROM_QSTR(MP_QSTR_get_key), MP_ROM_PTR(&_environ_get_key_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(_environ_module_globals, _environ_module_globals_table); - -const mp_obj_module_t _environ_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&_environ_module_globals, -}; - -MP_REGISTER_MODULE(MP_QSTR__environ, _environ_module, CIRCUITPY_ENVIRON); diff --git a/shared-bindings/_environ/__init__.h b/shared-bindings/_environ/__init__.h deleted file mode 100644 index 7779f3ac82..0000000000 --- a/shared-bindings/_environ/__init__.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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 - -#include -#include - -#include "py/objtuple.h" - -#include "shared-module/_environ/__init__.h" - -mp_obj_t common_hal__environ_get_key_path(const char *path, const char *key); -mp_obj_t common_hal__environ_get_key(const char *key); diff --git a/shared-bindings/os/__init__.c b/shared-bindings/os/__init__.c index 1260903203..b2fb8ff095 100644 --- a/shared-bindings/os/__init__.c +++ b/shared-bindings/os/__init__.c @@ -92,6 +92,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(os_getcwd_obj, os_getcwd); //| ... //| STATIC mp_obj_t os_getenv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + #if CIRCUITPY_OS_GETENV enum { ARG_key, ARG_default }; static const mp_arg_t allowed_args[] = { { MP_QSTR_key, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -101,6 +102,9 @@ STATIC mp_obj_t os_getenv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); return common_hal_os_getenv(mp_obj_str_get_str(args[ARG_key].u_obj), args[ARG_default].u_obj); + #else + return mp_const_none; + #endif } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(os_getenv_obj, 1, os_getenv); diff --git a/shared-bindings/os/__init__.h b/shared-bindings/os/__init__.h index 00d8c28a50..49b12cd52a 100644 --- a/shared-bindings/os/__init__.h +++ b/shared-bindings/os/__init__.h @@ -38,6 +38,8 @@ mp_obj_t common_hal_os_uname(void); void common_hal_os_chdir(const char *path); mp_obj_t common_hal_os_getcwd(void); mp_obj_t common_hal_os_getenv(const char *key, mp_obj_t default_); +mp_obj_t common_hal_os_getenv_path(const char *path, const char *key, mp_obj_t default_); + mp_obj_t common_hal_os_listdir(const char *path); void common_hal_os_mkdir(const char *path); void common_hal_os_remove(const char *path); diff --git a/shared-bindings/os/getenv.c b/shared-bindings/os/getenv.c new file mode 100644 index 0000000000..fdb5f0bb50 --- /dev/null +++ b/shared-bindings/os/getenv.c @@ -0,0 +1 @@ +// this file needs to exist but does not have any content diff --git a/shared-module/os/__init__.c b/shared-module/os/__init__.c index 57e7e62932..4a4c02e636 100644 --- a/shared-module/os/__init__.c +++ b/shared-module/os/__init__.c @@ -36,10 +36,6 @@ #include "py/runtime.h" #include "shared-bindings/os/__init__.h" -#if CIRCUITPY_ENVIRON -#include "shared-bindings/_environ/__init__.h" -#endif - // This provides all VFS related OS functions so that ports can share the code // as needed. It does not provide uname. @@ -111,17 +107,6 @@ mp_obj_t common_hal_os_getcwd(void) { return mp_vfs_getcwd(); } -mp_obj_t common_hal_os_getenv(const char *key, mp_obj_t default_) { - #if CIRCUITPY_ENVIRON - mp_obj_t env_obj = common_hal__environ_get_key(key); - // TODO must be a str object - if (env_obj != mp_const_none) { - return env_obj; - } - #endif - return default_; -} - mp_obj_t common_hal_os_listdir(const char *path) { mp_obj_t path_out; mp_vfs_mount_t *vfs = lookup_dir_path(path, &path_out); diff --git a/shared-module/_environ/__init__.h b/shared-module/os/__init__.h similarity index 89% rename from shared-module/_environ/__init__.h rename to shared-module/os/__init__.h index c96eb028b8..48bd06195e 100644 --- a/shared-module/_environ/__init__.h +++ b/shared-module/os/__init__.h @@ -33,13 +33,13 @@ typedef enum { ENVIRON_ERR_LENGTH, ENVIRON_ERR_NOT_FOUND, ENVIRON_ERR_UNEXPECTED = 0xff00, // logical or'd with the byte value -} _environ_err_t; +} os_environ_err_t; // Allocation free version that returns the full length of the value. // If it fits, the return value is 0-terminated. If the value doesn't fit, // *value_len may be an over-estimate but never an under-estimate. -_environ_err_t _environ_get_key_str(const char *key, char *value, size_t value_len); +os_environ_err_t common_hal_os_environ_get_key_str(const char *key, char *value, size_t value_len); // Returns ENVIRON_ERR_OK and sets value to the read value. Returns // ENVIRON_ERR_... if the value was not numeric. allocation-free. -_environ_err_t _environ_get_key_int(const char *key, mp_int_t *value); +os_environ_err_t common_hal_os_environ_get_key_int(const char *key, mp_int_t *value); diff --git a/shared-module/_environ/__init__.c b/shared-module/os/getenv.c similarity index 88% rename from shared-module/_environ/__init__.c rename to shared-module/os/getenv.c index 7e6e133e1a..ec9edbacac 100644 --- a/shared-module/_environ/__init__.c +++ b/shared-module/os/getenv.c @@ -27,7 +27,8 @@ #include #include -#include "shared-bindings/_environ/__init__.h" +#include "shared-bindings/os/__init__.h" +#include "shared-module/os/__init__.h" #include "py/gc.h" #include "py/misc.h" @@ -177,7 +178,7 @@ STATIC bool key_matches(file_arg *active_file, const char *key) { return true; } -STATIC _environ_err_t read_unicode_escape(file_arg *active_file, int sz, vstr_t *buf) { +STATIC os_environ_err_t read_unicode_escape(file_arg *active_file, int sz, vstr_t *buf) { char hex_buf[sz + 1]; for (int i = 0; i < sz; i++) { hex_buf[i] = get_next_byte(active_file); @@ -196,7 +197,7 @@ STATIC _environ_err_t read_unicode_escape(file_arg *active_file, int sz, vstr_t } // Read a quoted string -STATIC _environ_err_t read_string_value(file_arg *active_file, vstr_t *buf) { +STATIC os_environ_err_t read_string_value(file_arg *active_file, vstr_t *buf) { while (true) { int character = get_next_byte(active_file); switch (character) { @@ -243,7 +244,7 @@ STATIC _environ_err_t read_string_value(file_arg *active_file, vstr_t *buf) { case 'U': case 'u': { int sz = (character == 'u') ? 4 : 8; - _environ_err_t res; + os_environ_err_t res; res = read_unicode_escape(active_file, sz, buf); if (res != ENVIRON_OK) { return res; @@ -261,7 +262,7 @@ STATIC _environ_err_t read_string_value(file_arg *active_file, vstr_t *buf) { } // Read a numeric value (non-quoted value) as a string -STATIC _environ_err_t read_bare_value(file_arg *active_file, vstr_t *buf, int first_character) { +STATIC os_environ_err_t read_bare_value(file_arg *active_file, vstr_t *buf, int first_character) { int character = first_character; while (true) { switch (character) { @@ -291,13 +292,13 @@ STATIC mp_int_t read_value(file_arg *active_file, vstr_t *buf, bool *quoted) { } } -STATIC _environ_err_t _environ_get_key_vstr(const char *path, const char *key, vstr_t *buf, bool *quoted) { +STATIC os_environ_err_t os_environ_get_key_vstr(const char *path, const char *key, vstr_t *buf, bool *quoted) { file_arg active_file; if (!open_file(path, &active_file)) { return ENVIRON_ERR_OPEN; } - _environ_err_t result = ENVIRON_ERR_NOT_FOUND; + os_environ_err_t result = ENVIRON_ERR_NOT_FOUND; while (!is_eof(&active_file)) { if (key_matches(&active_file, key)) { result = read_value(&active_file, buf, quoted); @@ -307,10 +308,10 @@ STATIC _environ_err_t _environ_get_key_vstr(const char *path, const char *key, v return result; } -STATIC _environ_err_t _environ_get_key_buf_terminated(const char *key, char *value, size_t value_len, bool *quoted) { +STATIC os_environ_err_t os_environ_get_key_buf_terminated(const char *key, char *value, size_t value_len, bool *quoted) { vstr_t buf; vstr_init_fixed_buf(&buf, value_len, value); - _environ_err_t result = _environ_get_key_vstr(ENVIRON_PATH, key, &buf, quoted); + os_environ_err_t result = os_environ_get_key_vstr(ENVIRON_PATH, key, &buf, quoted); if (result == ENVIRON_OK) { vstr_add_byte_nonstd(&buf, 0); @@ -322,16 +323,16 @@ STATIC _environ_err_t _environ_get_key_buf_terminated(const char *key, char *val return result; } -_environ_err_t _environ_get_key_str(const char *key, char *value, size_t value_len) { +os_environ_err_t common_hal_os_environ_get_key_str(const char *key, char *value, size_t value_len) { bool quoted; - _environ_err_t result = _environ_get_key_buf_terminated(key, value, value_len, "ed); + os_environ_err_t result = os_environ_get_key_buf_terminated(key, value, value_len, "ed); if (result == ENVIRON_OK && !quoted) { result = ENVIRON_ERR_UNEXPECTED | value[0]; } return result; } -STATIC void throw__environ_error(_environ_err_t error) { +STATIC void throw__environ_error(os_environ_err_t error) { if (error == ENVIRON_OK) { return; } @@ -360,14 +361,14 @@ STATIC void throw__environ_error(_environ_err_t error) { } } -mp_obj_t common_hal__environ_get_key_path(const char *path, const char *key) { +mp_obj_t common_hal_os_getenv_path(const char *path, const char *key, mp_obj_t default_) { vstr_t buf; bool quoted; vstr_init(&buf, 64); - _environ_err_t result = _environ_get_key_vstr(path, key, &buf, "ed); + os_environ_err_t result = os_environ_get_key_vstr(path, key, &buf, "ed); if (result == ENVIRON_ERR_NOT_FOUND) { - return mp_const_none; + return default_; } throw__environ_error(result); @@ -378,14 +379,14 @@ mp_obj_t common_hal__environ_get_key_path(const char *path, const char *key) { } } -mp_obj_t common_hal__environ_get_key(const char *key) { - return common_hal__environ_get_key_path(ENVIRON_PATH, key); +mp_obj_t common_hal_os_getenv(const char *key, mp_obj_t default_) { + return common_hal_os_getenv_path(ENVIRON_PATH, key, default_); } -_environ_err_t _environ_get_key_int(const char *key, mp_int_t *value) { +os_environ_err_t common_hal_os_environ_get_key_int(const char *key, mp_int_t *value) { char buf[16]; bool quoted; - _environ_err_t result = _environ_get_key_buf_terminated(key, buf, sizeof(buf), "ed); + os_environ_err_t result = os_environ_get_key_buf_terminated(key, buf, sizeof(buf), "ed); if (result != ENVIRON_OK) { return result; } diff --git a/supervisor/shared/filesystem.c b/supervisor/shared/filesystem.c index 2c963b78ef..1eab59c384 100644 --- a/supervisor/shared/filesystem.c +++ b/supervisor/shared/filesystem.c @@ -129,7 +129,7 @@ bool filesystem_init(bool create_allowed, bool force_create) { make_empty_file(&vfs_fat->fatfs, "/.metadata_never_index"); make_empty_file(&vfs_fat->fatfs, "/.Trashes"); make_empty_file(&vfs_fat->fatfs, "/.fseventsd/no_log"); - #if CIRCUITPY_ENVIRON + #if CIRCUITPY_OS_GETENV make_empty_file(&vfs_fat->fatfs, "/settings.toml"); #endif // make a sample code.py file diff --git a/supervisor/shared/web_workflow/web_workflow.c b/supervisor/shared/web_workflow/web_workflow.c index d54f853891..ab9ded66a3 100644 --- a/supervisor/shared/web_workflow/web_workflow.c +++ b/supervisor/shared/web_workflow/web_workflow.c @@ -64,8 +64,8 @@ #include "shared-bindings/wifi/__init__.h" #endif -#if CIRCUITPY_ENVIRON -#include "shared-module/_environ/__init__.h" +#if CIRCUITPY_OS_GETENV +#include "shared-module/os/__init__.h" #endif enum request_state { @@ -244,19 +244,19 @@ void supervisor_web_workflow_status(void) { #endif void supervisor_start_web_workflow(void) { - #if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI && CIRCUITPY_ENVIRON + #if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI && CIRCUITPY_OS_GETENV char ssid[33]; char password[64]; size_t ssid_len = 0; size_t password_len = 0; - _environ_err_t result = _environ_get_key_str("CIRCUITPY_WIFI_SSID", ssid, sizeof(ssid)); + os_environ_err_t result = common_hal_os_environ_get_key_str("CIRCUITPY_WIFI_SSID", ssid, sizeof(ssid)); if (result != ENVIRON_OK) { return; } - result = _environ_get_key_str("CIRCUITPY_WIFI_PASSWORD", password, sizeof(password)); + result = common_hal_os_environ_get_key_str("CIRCUITPY_WIFI_PASSWORD", password, sizeof(password)); if (result != ENVIRON_OK) { return; } @@ -283,7 +283,7 @@ void supervisor_start_web_workflow(void) { mp_int_t new_port = web_api_port; // (leaves new_port unchanged on any failure) - (void)_environ_get_key_int("CIRCUITPY_WEB_API_PORT", &new_port); + (void)common_hal_os_environ_get_key_int("CIRCUITPY_WEB_API_PORT", &new_port); bool first_start = pool.base.type != &socketpool_socketpool_type; bool port_changed = new_port != web_api_port; @@ -320,7 +320,7 @@ void supervisor_start_web_workflow(void) { const size_t api_password_len = sizeof(_api_password) - 1; - result = _environ_get_key_str("CIRCUITPY_WEB_API_PASSWORD", _api_password + 1, api_password_len); + result = common_hal_os_environ_get_key_str("CIRCUITPY_WEB_API_PASSWORD", _api_password + 1, api_password_len); if (result == ENVIRON_OK) { _api_password[0] = ':'; _base64_in_place(_api_password, strlen(_api_password), sizeof(_api_password) - 1); diff --git a/tests/circuitpython/environ_test.py b/tests/circuitpython/environ_test.py index 46ceff5c9d..8dfab8812c 100644 --- a/tests/circuitpython/environ_test.py +++ b/tests/circuitpython/environ_test.py @@ -1,8 +1,8 @@ import os try: - from _environ import get_key -except: + get_key +except NameError: # Because run-tests.py suppresses site-packages, this test can't be run # on the host interpreter. However, it can be run manually to # generate/update the expected file. From f30d3ba02e23a30497d38b4905c1dab3194953fe Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 8 Dec 2022 15:39:19 -0600 Subject: [PATCH 09/34] update expected result --- tests/unix/extra_coverage.py.exp | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index 4483eeb0c1..582d90e1bc 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -29,22 +29,21 @@ RuntimeError: ame__ mport -builtins micropython _asyncio _environ -_thread _uasyncio aesio array -binascii bitmaptools btree cexample -cmath collections cppexample displayio -errno ffi framebuf gc -gifio hashlib json math -qrio rainbowio re sys -termios traceback ubinascii uctypes -uerrno uheapq uio ujson -ulab ulab.numpy ulab.numpy.fft -ulab.numpy.linalg ulab.scipy -ulab.scipy.linalg ulab.scipy.optimize -ulab.scipy.signal ulab.scipy.special -ulab.utils uos urandom ure -uselect ustruct utime utimeq -uzlib zlib +builtins micropython _asyncio _thread +_uasyncio aesio array binascii +bitmaptools btree cexample cmath +collections cppexample displayio errno +ffi framebuf gc gifio +hashlib json math qrio +rainbowio re sys termios +traceback ubinascii uctypes uerrno +uheapq uio ujson ulab +ulab.numpy ulab.numpy.fft ulab.numpy.linalg +ulab.scipy ulab.scipy.linalg +ulab.scipy.optimize ulab.scipy.signal +ulab.scipy.special ulab.utils uos +urandom ure uselect ustruct +utime utimeq uzlib zlib ime utime utimeq From 3cb628d290d80fd0f657e1b0bdb6af54c40335a5 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 8 Dec 2022 16:45:58 -0600 Subject: [PATCH 10/34] fix nrf build --- ports/nrf/common-hal/_bleio/Adapter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/nrf/common-hal/_bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c index f9e3bddc72..8948be1a5d 100644 --- a/ports/nrf/common-hal/_bleio/Adapter.c +++ b/ports/nrf/common-hal/_bleio/Adapter.c @@ -53,7 +53,7 @@ #include "shared-bindings/time/__init__.h" #if CIRCUITPY_OS_GETENV -#include "shared-bindings/os/getenv.h" +#include "shared-bindings/os/__init__.h" #endif #define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS) @@ -346,7 +346,7 @@ STATIC void bleio_adapter_reset_name(bleio_adapter_obj_t *self) { mp_int_t name_len = 0; #if CIRCUITPY_OS_GETENV - mp_obj_t ble_name = common_hal_os_environ_get_key("CIRCUITPY_BLE_NAME"); + mp_obj_t ble_name = common_hal_os_getenv("CIRCUITPY_BLE_NAME", mp_const_none); if (ble_name != mp_const_none) { common_hal_bleio_adapter_set_name(self, mp_obj_str_get_str(ble_name)); return; From 529ec23ecba3718a75ead98e0f43083e7b579f2c Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 8 Dec 2022 20:07:48 -0600 Subject: [PATCH 11/34] sadly, no emoji in the docs :( hopefully this works --- docs/environment.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/environment.rst b/docs/environment.rst index 0a370d64d9..1d4057b609 100644 --- a/docs/environment.rst +++ b/docs/environment.rst @@ -26,8 +26,9 @@ File format example: str_key="Hello world" # with trailing comment int_key = 7 - unicode_key="👨" - unicode_key2="\\U0001f468" # same as above + unicode_key="œuvre" + unicode_key2="\\u0153uvre" # same as above + unicode_key3="\\U00000153uvre" # same as above escape_codes="supported, including \\r\\n\\"\\\\" # comment [subtable] From 3a92c079fcc42c2ffe49963ddfb0312557acae6c Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 9 Dec 2022 14:07:23 -0600 Subject: [PATCH 12/34] Finish renaming os_environ_get_key to os_getenv .. for consistency. --- ports/espressif/common-hal/_bleio/Adapter.c | 2 +- ports/espressif/supervisor/port.c | 2 +- shared-module/os/__init__.h | 2 +- shared-module/os/getenv.c | 2 +- supervisor/shared/web_workflow/web_workflow.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ports/espressif/common-hal/_bleio/Adapter.c b/ports/espressif/common-hal/_bleio/Adapter.c index 7da1cd0b8c..414ef8b09c 100644 --- a/ports/espressif/common-hal/_bleio/Adapter.c +++ b/ports/espressif/common-hal/_bleio/Adapter.c @@ -103,7 +103,7 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable #if CIRCUITPY_OS_GETENV char ble_name[1 + MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH]; - os_environ_err_t result = common_hal_os_environ_get_key_str("CIRCUITPY_BLE_NAME", ble_name, sizeof(ble_name)); + os_environ_err_t result = common_hal_os_getenv_str("CIRCUITPY_BLE_NAME", ble_name, sizeof(ble_name)); if (result == ENVIRON_OK) { ble_svc_gap_device_name_set(ble_name); } else diff --git a/ports/espressif/supervisor/port.c b/ports/espressif/supervisor/port.c index 2792792455..546477cbf2 100644 --- a/ports/espressif/supervisor/port.c +++ b/ports/espressif/supervisor/port.c @@ -519,7 +519,7 @@ void port_idle_until_interrupt(void) { void port_post_boot_py(bool heap_valid) { if (!heap_valid && filesystem_present()) { mp_int_t reserved; - if (common_hal_os_environ_get_key_int("CIRCUITPY_RESERVED_PSRAM", &reserved) == ENVIRON_OK) { + if (common_hal_os_getenv_int("CIRCUITPY_RESERVED_PSRAM", &reserved) == ENVIRON_OK) { common_hal_espidf_set_reserved_psram(reserved); } common_hal_espidf_reserve_psram(); diff --git a/shared-module/os/__init__.h b/shared-module/os/__init__.h index 48bd06195e..7c32cdcd95 100644 --- a/shared-module/os/__init__.h +++ b/shared-module/os/__init__.h @@ -38,7 +38,7 @@ typedef enum { // Allocation free version that returns the full length of the value. // If it fits, the return value is 0-terminated. If the value doesn't fit, // *value_len may be an over-estimate but never an under-estimate. -os_environ_err_t common_hal_os_environ_get_key_str(const char *key, char *value, size_t value_len); +os_environ_err_t common_hal_os_getenv_str(const char *key, char *value, size_t value_len); // Returns ENVIRON_ERR_OK and sets value to the read value. Returns // ENVIRON_ERR_... if the value was not numeric. allocation-free. diff --git a/shared-module/os/getenv.c b/shared-module/os/getenv.c index ec9edbacac..2b610bd91c 100644 --- a/shared-module/os/getenv.c +++ b/shared-module/os/getenv.c @@ -323,7 +323,7 @@ STATIC os_environ_err_t os_environ_get_key_buf_terminated(const char *key, char return result; } -os_environ_err_t common_hal_os_environ_get_key_str(const char *key, char *value, size_t value_len) { +os_environ_err_t common_hal_os_getenv_str(const char *key, char *value, size_t value_len) { bool quoted; os_environ_err_t result = os_environ_get_key_buf_terminated(key, value, value_len, "ed); if (result == ENVIRON_OK && !quoted) { diff --git a/supervisor/shared/web_workflow/web_workflow.c b/supervisor/shared/web_workflow/web_workflow.c index ab9ded66a3..525b851b8f 100644 --- a/supervisor/shared/web_workflow/web_workflow.c +++ b/supervisor/shared/web_workflow/web_workflow.c @@ -251,7 +251,7 @@ void supervisor_start_web_workflow(void) { size_t ssid_len = 0; size_t password_len = 0; - os_environ_err_t result = common_hal_os_environ_get_key_str("CIRCUITPY_WIFI_SSID", ssid, sizeof(ssid)); + os_environ_err_t result = common_hal_os_getenv_str("CIRCUITPY_WIFI_SSID", ssid, sizeof(ssid)); if (result != ENVIRON_OK) { return; } From f2032dbf0f47cbc56e3688b361615e3cebf1d31b Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 9 Dec 2022 14:11:37 -0600 Subject: [PATCH 13/34] remove mention of _environ --- docs/environment.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/environment.rst b/docs/environment.rst index 1d4057b609..58ada402c6 100644 --- a/docs/environment.rst +++ b/docs/environment.rst @@ -32,7 +32,7 @@ File format example: escape_codes="supported, including \\r\\n\\"\\\\" # comment [subtable] - subvalue="cannot retrieve this using _environ or getenv" + subvalue="cannot retrieve this using getenv" Details of the toml language subset From 499af3ed000819cac89930a36c0499e92fd837d1 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 9 Dec 2022 14:11:57 -0600 Subject: [PATCH 14/34] update source locations in translation file --- locale/circuitpython.pot | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 43c7a79ff7..56c2396d46 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -1002,7 +1002,7 @@ msgstr "" msgid "File exists" msgstr "" -#: shared-module/_environ/__init__.c +#: shared-module/os/getenv.c msgid "File not found" msgstr "" @@ -1190,7 +1190,7 @@ msgid "Internal define error" msgstr "" #: ports/espressif/common-hal/paralleldisplay/ParallelBus.c -#: shared-module/_environ/__init__.c +#: shared-module/os/getenv.c msgid "Internal error" msgstr "" @@ -1237,7 +1237,7 @@ msgstr "" msgid "Invalid bits per value" msgstr "" -#: shared-module/_environ/__init__.c +#: shared-module/os/getenv.c #, c-format msgid "Invalid byte %.*s" msgstr "" @@ -1272,7 +1272,7 @@ msgstr "" msgid "Invalid state" msgstr "" -#: shared-module/_environ/__init__.c +#: shared-module/os/getenv.c msgid "Invalid unicode escape" msgstr "" @@ -1280,7 +1280,7 @@ msgstr "" msgid "Key must be 16, 24, or 32 bytes long" msgstr "" -#: shared-module/_environ/__init__.c +#: shared-module/os/getenv.c msgid "Key not found" msgstr "" From 678a466d1af3a6d1bcec01525af12e87182e475e Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 9 Dec 2022 14:12:27 -0600 Subject: [PATCH 15/34] alphabetize --- ports/atmel-samd/mpconfigport.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ports/atmel-samd/mpconfigport.mk b/ports/atmel-samd/mpconfigport.mk index 72b1302227..57f7ca339f 100644 --- a/ports/atmel-samd/mpconfigport.mk +++ b/ports/atmel-samd/mpconfigport.mk @@ -24,16 +24,15 @@ ifeq ($(CHIP_FAMILY),samd21) CIRCUITPY_AESIO ?= 0 CIRCUITPY_ATEXIT ?= 0 CIRCUITPY_AUDIOMIXER ?= 0 +CIRCUITPY_AUDIOMP3 ?= 0 CIRCUITPY_BINASCII ?= 0 CIRCUITPY_BITBANGIO ?= 0 CIRCUITPY_BITMAPTOOLS ?= 0 -CIRCUITPY_BUSDEVICE ?= 0 -CIRCUITPY_AUDIOMP3 ?= 0 CIRCUITPY_BLEIO_HCI = 0 CIRCUITPY_BUILTINS_POW3 ?= 0 +CIRCUITPY_BUSDEVICE ?= 0 CIRCUITPY_COMPUTED_GOTO_SAVE_SPACE ?= 1 CIRCUITPY_COUNTIO ?= 0 -CIRCUITPY_OS_GETENV ?= 0 # Not enough RAM for framebuffers CIRCUITPY_FRAMEBUFFERIO ?= 0 CIRCUITPY_FREQUENCYIO ?= 0 @@ -43,6 +42,7 @@ CIRCUITPY_I2CTARGET ?= 0 CIRCUITPY_JSON ?= 0 CIRCUITPY_KEYPAD ?= 0 CIRCUITPY_MSGPACK ?= 0 +CIRCUITPY_OS_GETENV ?= 0 CIRCUITPY_PIXELMAP ?= 0 CIRCUITPY_RE ?= 0 CIRCUITPY_SDCARDIO ?= 0 From 44f15d563dfea31606dc03fb5905c8b91615458f Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 9 Dec 2022 14:14:53 -0600 Subject: [PATCH 16/34] Rename "environ" errors to "getenv" errors --- ports/espressif/common-hal/_bleio/Adapter.c | 4 +-- ports/espressif/supervisor/port.c | 2 +- shared-module/os/__init__.h | 8 ++--- shared-module/os/getenv.c | 30 +++++++++---------- supervisor/shared/web_workflow/web_workflow.c | 4 +-- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/ports/espressif/common-hal/_bleio/Adapter.c b/ports/espressif/common-hal/_bleio/Adapter.c index 414ef8b09c..3239c501cc 100644 --- a/ports/espressif/common-hal/_bleio/Adapter.c +++ b/ports/espressif/common-hal/_bleio/Adapter.c @@ -103,8 +103,8 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable #if CIRCUITPY_OS_GETENV char ble_name[1 + MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH]; - os_environ_err_t result = common_hal_os_getenv_str("CIRCUITPY_BLE_NAME", ble_name, sizeof(ble_name)); - if (result == ENVIRON_OK) { + os_getenv_err_t result = common_hal_os_getenv_str("CIRCUITPY_BLE_NAME", ble_name, sizeof(ble_name)); + if (result == GETENV_OK) { ble_svc_gap_device_name_set(ble_name); } else #endif diff --git a/ports/espressif/supervisor/port.c b/ports/espressif/supervisor/port.c index 546477cbf2..baeba5ce90 100644 --- a/ports/espressif/supervisor/port.c +++ b/ports/espressif/supervisor/port.c @@ -519,7 +519,7 @@ void port_idle_until_interrupt(void) { void port_post_boot_py(bool heap_valid) { if (!heap_valid && filesystem_present()) { mp_int_t reserved; - if (common_hal_os_getenv_int("CIRCUITPY_RESERVED_PSRAM", &reserved) == ENVIRON_OK) { + if (common_hal_os_getenv_int("CIRCUITPY_RESERVED_PSRAM", &reserved) == GETENV_OK) { common_hal_espidf_set_reserved_psram(reserved); } common_hal_espidf_reserve_psram(); diff --git a/shared-module/os/__init__.h b/shared-module/os/__init__.h index 7c32cdcd95..ce7199c8f2 100644 --- a/shared-module/os/__init__.h +++ b/shared-module/os/__init__.h @@ -27,19 +27,19 @@ #pragma once typedef enum { - ENVIRON_OK = 0, + GETENV_OK = 0, ENVIRON_ERR_OPEN, ENVIRON_ERR_UNICODE, ENVIRON_ERR_LENGTH, ENVIRON_ERR_NOT_FOUND, ENVIRON_ERR_UNEXPECTED = 0xff00, // logical or'd with the byte value -} os_environ_err_t; +} os_getenv_err_t; // Allocation free version that returns the full length of the value. // If it fits, the return value is 0-terminated. If the value doesn't fit, // *value_len may be an over-estimate but never an under-estimate. -os_environ_err_t common_hal_os_getenv_str(const char *key, char *value, size_t value_len); +os_getenv_err_t common_hal_os_getenv_str(const char *key, char *value, size_t value_len); // Returns ENVIRON_ERR_OK and sets value to the read value. Returns // ENVIRON_ERR_... if the value was not numeric. allocation-free. -os_environ_err_t common_hal_os_environ_get_key_int(const char *key, mp_int_t *value); +os_getenv_err_t common_hal_os_environ_get_key_int(const char *key, mp_int_t *value); diff --git a/shared-module/os/getenv.c b/shared-module/os/getenv.c index 2b610bd91c..b883ae423c 100644 --- a/shared-module/os/getenv.c +++ b/shared-module/os/getenv.c @@ -39,7 +39,7 @@ #include "supervisor/filesystem.h" #include "supervisor/memory.h" -#define ENVIRON_PATH "settings.toml" +#define GETENV_PATH "settings.toml" #if defined(UNIX) typedef FILE *file_arg; @@ -178,7 +178,7 @@ STATIC bool key_matches(file_arg *active_file, const char *key) { return true; } -STATIC os_environ_err_t read_unicode_escape(file_arg *active_file, int sz, vstr_t *buf) { +STATIC os_getenv_err_t read_unicode_escape(file_arg *active_file, int sz, vstr_t *buf) { char hex_buf[sz + 1]; for (int i = 0; i < sz; i++) { hex_buf[i] = get_next_byte(active_file); @@ -197,7 +197,7 @@ STATIC os_environ_err_t read_unicode_escape(file_arg *active_file, int sz, vstr_ } // Read a quoted string -STATIC os_environ_err_t read_string_value(file_arg *active_file, vstr_t *buf) { +STATIC os_getenv_err_t read_string_value(file_arg *active_file, vstr_t *buf) { while (true) { int character = get_next_byte(active_file); switch (character) { @@ -244,7 +244,7 @@ STATIC os_environ_err_t read_string_value(file_arg *active_file, vstr_t *buf) { case 'U': case 'u': { int sz = (character == 'u') ? 4 : 8; - os_environ_err_t res; + os_getenv_err_t res; res = read_unicode_escape(active_file, sz, buf); if (res != ENVIRON_OK) { return res; @@ -262,7 +262,7 @@ STATIC os_environ_err_t read_string_value(file_arg *active_file, vstr_t *buf) { } // Read a numeric value (non-quoted value) as a string -STATIC os_environ_err_t read_bare_value(file_arg *active_file, vstr_t *buf, int first_character) { +STATIC os_getenv_err_t read_bare_value(file_arg *active_file, vstr_t *buf, int first_character) { int character = first_character; while (true) { switch (character) { @@ -292,13 +292,13 @@ STATIC mp_int_t read_value(file_arg *active_file, vstr_t *buf, bool *quoted) { } } -STATIC os_environ_err_t os_environ_get_key_vstr(const char *path, const char *key, vstr_t *buf, bool *quoted) { +STATIC os_getenv_err_t os_environ_get_key_vstr(const char *path, const char *key, vstr_t *buf, bool *quoted) { file_arg active_file; if (!open_file(path, &active_file)) { return ENVIRON_ERR_OPEN; } - os_environ_err_t result = ENVIRON_ERR_NOT_FOUND; + os_getenv_err_t result = ENVIRON_ERR_NOT_FOUND; while (!is_eof(&active_file)) { if (key_matches(&active_file, key)) { result = read_value(&active_file, buf, quoted); @@ -308,10 +308,10 @@ STATIC os_environ_err_t os_environ_get_key_vstr(const char *path, const char *ke return result; } -STATIC os_environ_err_t os_environ_get_key_buf_terminated(const char *key, char *value, size_t value_len, bool *quoted) { +STATIC os_getenv_err_t os_environ_get_key_buf_terminated(const char *key, char *value, size_t value_len, bool *quoted) { vstr_t buf; vstr_init_fixed_buf(&buf, value_len, value); - os_environ_err_t result = os_environ_get_key_vstr(ENVIRON_PATH, key, &buf, quoted); + os_getenv_err_t result = os_environ_get_key_vstr(ENVIRON_PATH, key, &buf, quoted); if (result == ENVIRON_OK) { vstr_add_byte_nonstd(&buf, 0); @@ -323,16 +323,16 @@ STATIC os_environ_err_t os_environ_get_key_buf_terminated(const char *key, char return result; } -os_environ_err_t common_hal_os_getenv_str(const char *key, char *value, size_t value_len) { +os_getenv_err_t common_hal_os_getenv_str(const char *key, char *value, size_t value_len) { bool quoted; - os_environ_err_t result = os_environ_get_key_buf_terminated(key, value, value_len, "ed); + os_getenv_err_t result = os_environ_get_key_buf_terminated(key, value, value_len, "ed); if (result == ENVIRON_OK && !quoted) { result = ENVIRON_ERR_UNEXPECTED | value[0]; } return result; } -STATIC void throw__environ_error(os_environ_err_t error) { +STATIC void throw__environ_error(os_getenv_err_t error) { if (error == ENVIRON_OK) { return; } @@ -366,7 +366,7 @@ mp_obj_t common_hal_os_getenv_path(const char *path, const char *key, mp_obj_t d bool quoted; vstr_init(&buf, 64); - os_environ_err_t result = os_environ_get_key_vstr(path, key, &buf, "ed); + os_getenv_err_t result = os_environ_get_key_vstr(path, key, &buf, "ed); if (result == ENVIRON_ERR_NOT_FOUND) { return default_; } @@ -383,10 +383,10 @@ mp_obj_t common_hal_os_getenv(const char *key, mp_obj_t default_) { return common_hal_os_getenv_path(ENVIRON_PATH, key, default_); } -os_environ_err_t common_hal_os_environ_get_key_int(const char *key, mp_int_t *value) { +os_getenv_err_t common_hal_os_environ_get_key_int(const char *key, mp_int_t *value) { char buf[16]; bool quoted; - os_environ_err_t result = os_environ_get_key_buf_terminated(key, buf, sizeof(buf), "ed); + os_getenv_err_t result = os_environ_get_key_buf_terminated(key, buf, sizeof(buf), "ed); if (result != ENVIRON_OK) { return result; } diff --git a/supervisor/shared/web_workflow/web_workflow.c b/supervisor/shared/web_workflow/web_workflow.c index 525b851b8f..5bac8522dd 100644 --- a/supervisor/shared/web_workflow/web_workflow.c +++ b/supervisor/shared/web_workflow/web_workflow.c @@ -251,8 +251,8 @@ void supervisor_start_web_workflow(void) { size_t ssid_len = 0; size_t password_len = 0; - os_environ_err_t result = common_hal_os_getenv_str("CIRCUITPY_WIFI_SSID", ssid, sizeof(ssid)); - if (result != ENVIRON_OK) { + os_getenv_err_t result = common_hal_os_getenv_str("CIRCUITPY_WIFI_SSID", ssid, sizeof(ssid)); + if (result != GETENV_OK) { return; } From 1f504e5c0f65d88212aa32f1b1cb4c9403d23a81 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 9 Dec 2022 14:15:00 -0600 Subject: [PATCH 17/34] Remove line accidentally duplicated --- ports/unix/coverage.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index 8463c169e4..0e4c6dbd48 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -95,7 +95,6 @@ STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) }, - { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) }, }; STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); From cc7d550407adf39c036ddd4ade38d1a35b990ebe Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 9 Dec 2022 14:28:46 -0600 Subject: [PATCH 18/34] Really finish renaming to getenv --- py/circuitpy_defns.mk | 1 - shared-module/os/__init__.h | 21 ++++++----- shared-module/os/getenv.c | 74 ++++++++++++++++++------------------- 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index df3f664864..2deefda030 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -586,7 +586,6 @@ SRC_SHARED_MODULE_ALL = \ displayio/TileGrid.c \ displayio/area.c \ displayio/__init__.c \ - _environ/__init__.c \ floppyio/__init__.c \ fontio/BuiltinFont.c \ fontio/__init__.c \ diff --git a/shared-module/os/__init__.h b/shared-module/os/__init__.h index ce7199c8f2..0e1d78c53b 100644 --- a/shared-module/os/__init__.h +++ b/shared-module/os/__init__.h @@ -28,18 +28,19 @@ typedef enum { GETENV_OK = 0, - ENVIRON_ERR_OPEN, - ENVIRON_ERR_UNICODE, - ENVIRON_ERR_LENGTH, - ENVIRON_ERR_NOT_FOUND, - ENVIRON_ERR_UNEXPECTED = 0xff00, // logical or'd with the byte value + GETENV_ERR_OPEN, + GETENV_ERR_UNICODE, + GETENV_ERR_LENGTH, + GETENV_ERR_NOT_FOUND, + GETENV_ERR_UNEXPECTED = 0xff00, // logical or'd with the byte value } os_getenv_err_t; // Allocation free version that returns the full length of the value. -// If it fits, the return value is 0-terminated. If the value doesn't fit, -// *value_len may be an over-estimate but never an under-estimate. +// If it fits, the return value is 0-terminated. The passed in buffer +// may be modified even if an error is returned. Allocation free. os_getenv_err_t common_hal_os_getenv_str(const char *key, char *value, size_t value_len); -// Returns ENVIRON_ERR_OK and sets value to the read value. Returns -// ENVIRON_ERR_... if the value was not numeric. allocation-free. -os_getenv_err_t common_hal_os_environ_get_key_int(const char *key, mp_int_t *value); +// Returns GETENV_OK and sets value to the read value. Returns +// GETENV_ERR_... if the value was not numeric. allocation-free. +// If any error code is returned, value is guaranteed not modified +os_getenv_err_t common_hal_os_getenv_int(const char *key, mp_int_t *value); diff --git a/shared-module/os/getenv.c b/shared-module/os/getenv.c index b883ae423c..dc1f640aec 100644 --- a/shared-module/os/getenv.c +++ b/shared-module/os/getenv.c @@ -187,13 +187,13 @@ STATIC os_getenv_err_t read_unicode_escape(file_arg *active_file, int sz, vstr_t char *end; unsigned long c = strtoul(hex_buf, &end, 16); if (end != &hex_buf[sz]) { - return ENVIRON_ERR_UNEXPECTED | *end; + return GETENV_ERR_UNEXPECTED | *end; } if (c >= 0x110000) { - return ENVIRON_ERR_UNICODE; + return GETENV_ERR_UNICODE; } vstr_add_char_nonstd(buf, c); - return ENVIRON_OK; + return GETENV_OK; } // Read a quoted string @@ -203,7 +203,7 @@ STATIC os_getenv_err_t read_string_value(file_arg *active_file, vstr_t *buf) { switch (character) { case 0: case '\n': - return ENVIRON_ERR_UNEXPECTED | character; + return GETENV_ERR_UNEXPECTED | character; case '"': character = consume_whitespace(active_file); @@ -212,9 +212,9 @@ STATIC os_getenv_err_t read_string_value(file_arg *active_file, vstr_t *buf) { next_line(active_file); MP_FALLTHROUGH; case '\n': - return ENVIRON_OK; + return GETENV_OK; default: - return ENVIRON_ERR_UNEXPECTED | character; + return GETENV_ERR_UNEXPECTED | character; } case '\\': @@ -222,7 +222,7 @@ STATIC os_getenv_err_t read_string_value(file_arg *active_file, vstr_t *buf) { switch (character) { case 0: case '\n': - return ENVIRON_ERR_UNEXPECTED | character; + return GETENV_ERR_UNEXPECTED | character; case 'b': character = '\b'; break; @@ -246,7 +246,7 @@ STATIC os_getenv_err_t read_string_value(file_arg *active_file, vstr_t *buf) { int sz = (character == 'u') ? 4 : 8; os_getenv_err_t res; res = read_unicode_escape(active_file, sz, buf); - if (res != ENVIRON_OK) { + if (res != GETENV_OK) { return res; } continue; @@ -267,12 +267,12 @@ STATIC os_getenv_err_t read_bare_value(file_arg *active_file, vstr_t *buf, int f while (true) { switch (character) { case 0: - return ENVIRON_ERR_UNEXPECTED | character; + return GETENV_ERR_UNEXPECTED | character; case '\n': - return ENVIRON_OK; + return GETENV_OK; case '#': next_line(active_file); - return ENVIRON_OK; + return GETENV_OK; default: vstr_add_byte_nonstd(buf, character); } @@ -292,13 +292,13 @@ STATIC mp_int_t read_value(file_arg *active_file, vstr_t *buf, bool *quoted) { } } -STATIC os_getenv_err_t os_environ_get_key_vstr(const char *path, const char *key, vstr_t *buf, bool *quoted) { +STATIC os_getenv_err_t os_getenv_vstr(const char *path, const char *key, vstr_t *buf, bool *quoted) { file_arg active_file; if (!open_file(path, &active_file)) { - return ENVIRON_ERR_OPEN; + return GETENV_ERR_OPEN; } - os_getenv_err_t result = ENVIRON_ERR_NOT_FOUND; + os_getenv_err_t result = GETENV_ERR_NOT_FOUND; while (!is_eof(&active_file)) { if (key_matches(&active_file, key)) { result = read_value(&active_file, buf, quoted); @@ -308,16 +308,16 @@ STATIC os_getenv_err_t os_environ_get_key_vstr(const char *path, const char *key return result; } -STATIC os_getenv_err_t os_environ_get_key_buf_terminated(const char *key, char *value, size_t value_len, bool *quoted) { +STATIC os_getenv_err_t os_getenv_buf_terminated(const char *key, char *value, size_t value_len, bool *quoted) { vstr_t buf; vstr_init_fixed_buf(&buf, value_len, value); - os_getenv_err_t result = os_environ_get_key_vstr(ENVIRON_PATH, key, &buf, quoted); + os_getenv_err_t result = os_getenv_vstr(GETENV_PATH, key, &buf, quoted); - if (result == ENVIRON_OK) { + if (result == GETENV_OK) { vstr_add_byte_nonstd(&buf, 0); memcpy(value, buf.buf, MIN(buf.len, value_len)); if (buf.len > value_len) { - result = ENVIRON_ERR_LENGTH; + result = GETENV_ERR_LENGTH; } } return result; @@ -325,18 +325,18 @@ STATIC os_getenv_err_t os_environ_get_key_buf_terminated(const char *key, char * os_getenv_err_t common_hal_os_getenv_str(const char *key, char *value, size_t value_len) { bool quoted; - os_getenv_err_t result = os_environ_get_key_buf_terminated(key, value, value_len, "ed); - if (result == ENVIRON_OK && !quoted) { - result = ENVIRON_ERR_UNEXPECTED | value[0]; + os_getenv_err_t result = os_getenv_buf_terminated(key, value, value_len, "ed); + if (result == GETENV_OK && !quoted) { + result = GETENV_ERR_UNEXPECTED | value[0]; } return result; } -STATIC void throw__environ_error(os_getenv_err_t error) { - if (error == ENVIRON_OK) { +STATIC void throw_getenv_error(os_getenv_err_t error) { + if (error == GETENV_OK) { return; } - if (error & ENVIRON_ERR_UNEXPECTED) { + if (error & GETENV_ERR_UNEXPECTED) { byte character = (error & 0xff); mp_print_t print; vstr_t vstr; @@ -350,11 +350,11 @@ STATIC void throw__environ_error(os_getenv_err_t error) { vstr.len, vstr.buf); } switch (error) { - case ENVIRON_ERR_OPEN: + case GETENV_ERR_OPEN: mp_raise_ValueError(translate("File not found")); - case ENVIRON_ERR_UNICODE: + case GETENV_ERR_UNICODE: mp_raise_ValueError(translate("Invalid unicode escape")); - case ENVIRON_ERR_NOT_FOUND: + case GETENV_ERR_NOT_FOUND: mp_raise_ValueError(translate("Key not found")); default: mp_raise_RuntimeError(translate("Internal error")); @@ -366,11 +366,11 @@ mp_obj_t common_hal_os_getenv_path(const char *path, const char *key, mp_obj_t d bool quoted; vstr_init(&buf, 64); - os_getenv_err_t result = os_environ_get_key_vstr(path, key, &buf, "ed); - if (result == ENVIRON_ERR_NOT_FOUND) { + os_getenv_err_t result = os_getenv_vstr(path, key, &buf, "ed); + if (result == GETENV_ERR_NOT_FOUND) { return default_; } - throw__environ_error(result); + throw_getenv_error(result); if (quoted) { return mp_obj_new_str_from_vstr(&mp_type_str, &buf); @@ -380,24 +380,24 @@ mp_obj_t common_hal_os_getenv_path(const char *path, const char *key, mp_obj_t d } mp_obj_t common_hal_os_getenv(const char *key, mp_obj_t default_) { - return common_hal_os_getenv_path(ENVIRON_PATH, key, default_); + return common_hal_os_getenv_path(GETENV_PATH, key, default_); } -os_getenv_err_t common_hal_os_environ_get_key_int(const char *key, mp_int_t *value) { +os_getenv_err_t common_hal_os_getenv_int(const char *key, mp_int_t *value) { char buf[16]; bool quoted; - os_getenv_err_t result = os_environ_get_key_buf_terminated(key, buf, sizeof(buf), "ed); - if (result != ENVIRON_OK) { + os_getenv_err_t result = os_getenv_buf_terminated(key, buf, sizeof(buf), "ed); + if (result != GETENV_OK) { return result; } if (quoted) { - return ENVIRON_ERR_UNEXPECTED | '"'; + return GETENV_ERR_UNEXPECTED | '"'; } char *end; long num = strtol(buf, &end, 0); if (end == buf || *end) { // If the whole buffer was not consumed it's an error - return ENVIRON_ERR_UNEXPECTED | *end; + return GETENV_ERR_UNEXPECTED | *end; } *value = (mp_int_t)num; - return ENVIRON_OK; + return GETENV_OK; } From 040fac07243fb61a66388d9bac9eb3f2d1c28ee6 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 9 Dec 2022 14:29:14 -0600 Subject: [PATCH 19/34] No need to track excess length .. this is a relic from when the actual required length was given back to the caller --- shared-module/os/getenv.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/shared-module/os/getenv.c b/shared-module/os/getenv.c index dc1f640aec..09dc19748d 100644 --- a/shared-module/os/getenv.c +++ b/shared-module/os/getenv.c @@ -101,8 +101,6 @@ STATIC void seek_eof(file_arg *active_file) { STATIC void vstr_add_byte_nonstd(vstr_t *vstr, byte b) { if (!vstr->fixed_buf || vstr->alloc > vstr->len) { vstr_add_byte(vstr, b); - } else { - vstr->len++; } } @@ -114,8 +112,6 @@ STATIC void vstr_add_char_nonstd(vstr_t *vstr, unichar c) { (c < 0x10000) ? 3 : 4; if (!vstr->fixed_buf || vstr->alloc > vstr->len + ulen) { vstr_add_char(vstr, c); - } else { - vstr->len += ulen; } } From 6dca9db225c851edb3236e5c613192a48f2a3496 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 9 Dec 2022 14:35:50 -0600 Subject: [PATCH 20/34] Rename test function & fix a bug with default value handling --- ports/unix/main.c | 8 ++++---- tests/circuitpython/environ_test.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ports/unix/main.c b/ports/unix/main.c index aa7c92dcff..506a8ed433 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -421,11 +421,11 @@ STATIC void set_sys_argv(char *argv[], int argc, int start_arg) { #endif mp_obj_t common_hal_os_getenv_path(const char *path, const char *key, mp_obj_t default_); -STATIC mp_obj_t get_key(mp_obj_t path_in, mp_obj_t key_to_get_in) { +STATIC mp_obj_t getenv_from_file(mp_obj_t path_in, mp_obj_t key_to_get_in) { return common_hal_os_getenv_path(mp_obj_str_get_str(path_in), - mp_obj_str_get_str(key_to_get_in), mp_const_none); + mp_obj_str_get_str(key_to_get_in), default_); } -MP_DEFINE_CONST_FUN_OBJ_2(get_key_obj, get_key); +MP_DEFINE_CONST_FUN_OBJ_2(getenv_from_file_obj, get_key); MP_NOINLINE int main_(int argc, char **argv); @@ -547,7 +547,7 @@ MP_NOINLINE int main_(int argc, char **argv) { MP_DECLARE_CONST_FUN_OBJ_0(extra_cpp_coverage_obj); mp_store_global(MP_QSTR_extra_coverage, MP_OBJ_FROM_PTR(&extra_coverage_obj)); mp_store_global(MP_QSTR_extra_cpp_coverage, MP_OBJ_FROM_PTR(&extra_cpp_coverage_obj)); - mp_store_global(MP_QSTR_get_key, MP_OBJ_FROM_PTR(&get_key_obj)); + mp_store_global(MP_QSTR_getenv_from_file, MP_OBJ_FROM_PTR(&getenv_from_file_obj)); } #endif diff --git a/tests/circuitpython/environ_test.py b/tests/circuitpython/environ_test.py index 8dfab8812c..9781444100 100644 --- a/tests/circuitpython/environ_test.py +++ b/tests/circuitpython/environ_test.py @@ -1,7 +1,7 @@ import os try: - get_key + getenv_from_file except NameError: # Because run-tests.py suppresses site-packages, this test can't be run # on the host interpreter. However, it can be run manually to @@ -10,7 +10,7 @@ except NameError: # After 3.11 becomes standard, change this to use tomllib. import tomlkit - def get_key(filename, key): + def getenv_from_file(filename, key): with open(filename) as f: s = tomlkit.load(f) return s.get(key, None) From 3ab71d7448a5dfb972ab2c2b06121507ed29d5a4 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 9 Dec 2022 14:46:06 -0600 Subject: [PATCH 21/34] Rename test function, make 'bad' files binary & add another test --- .gitignore | 1 + .pre-commit-config.yaml | 4 +- ports/unix/main.c | 4 +- tests/circuitpython/bad4.toml | 1 + tests/circuitpython/environ_test.py | 42 ------------------- tests/circuitpython/getenv_test.py | 20 +++++++++ ...environ_test.py.exp => getenv_test.py.exp} | 35 ++++++++-------- 7 files changed, 44 insertions(+), 63 deletions(-) create mode 100644 tests/circuitpython/bad4.toml delete mode 100644 tests/circuitpython/environ_test.py create mode 100644 tests/circuitpython/getenv_test.py rename tests/circuitpython/{environ_test.py.exp => getenv_test.py.exp} (69%) diff --git a/.gitignore b/.gitignore index 2fdfe207a2..9cb1e9ea5e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ !atmel-samd/asf/**/*.a *.elf *.bin +!*.toml.bin *.map *.hex *.dis diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1905b233cf..05e193f0e9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,9 +8,9 @@ repos: hooks: - id: check-yaml - id: end-of-file-fixer - exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|ports/espressif/esp-idf-config/.*|ports/espressif/boards/.*/sdkconfig)' + exclude: '^(tests/.*\.toml|tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|ports/espressif/esp-idf-config/.*|ports/espressif/boards/.*/sdkconfig)' - id: trailing-whitespace - exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|lib/mbedtls_errors/.*)' + exclude: '^(tests/.*\.toml|tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|lib/mbedtls_errors/.*)' - repo: local hooks: - id: translations diff --git a/ports/unix/main.c b/ports/unix/main.c index 506a8ed433..e423634e58 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -423,9 +423,9 @@ STATIC void set_sys_argv(char *argv[], int argc, int start_arg) { mp_obj_t common_hal_os_getenv_path(const char *path, const char *key, mp_obj_t default_); STATIC mp_obj_t getenv_from_file(mp_obj_t path_in, mp_obj_t key_to_get_in) { return common_hal_os_getenv_path(mp_obj_str_get_str(path_in), - mp_obj_str_get_str(key_to_get_in), default_); + mp_obj_str_get_str(key_to_get_in), mp_const_none); } -MP_DEFINE_CONST_FUN_OBJ_2(getenv_from_file_obj, get_key); +MP_DEFINE_CONST_FUN_OBJ_2(getenv_from_file_obj, getenv_from_file); MP_NOINLINE int main_(int argc, char **argv); diff --git a/tests/circuitpython/bad4.toml b/tests/circuitpython/bad4.toml new file mode 100644 index 0000000000..befe224084 --- /dev/null +++ b/tests/circuitpython/bad4.toml @@ -0,0 +1 @@ +string=" \ No newline at end of file diff --git a/tests/circuitpython/environ_test.py b/tests/circuitpython/environ_test.py deleted file mode 100644 index 9781444100..0000000000 --- a/tests/circuitpython/environ_test.py +++ /dev/null @@ -1,42 +0,0 @@ -import os - -try: - getenv_from_file -except NameError: - # Because run-tests.py suppresses site-packages, this test can't be run - # on the host interpreter. However, it can be run manually to - # generate/update the expected file. - # - # After 3.11 becomes standard, change this to use tomllib. - import tomlkit - - def getenv_from_file(filename, key): - with open(filename) as f: - s = tomlkit.load(f) - return s.get(key, None) - - -def run_test(f, k=None): - try: - v = get_key(f"{BASE}/{f}.toml", k or f) - print(f, k, repr(v)) - except Exception as e: - print(f, k, "err") - - -if "/" in __file__: - BASE = __file__.rsplit("/", 1)[0] -else: - BASE = "." - -run_test("good", "notpresent") -run_test("good", "string") -run_test("good", "number") -run_test("good", "cstring") -run_test("good", "cnumber") -run_test("good", "subvalue") -for i in range(8): - run_test("good", f"string{i}") -run_test("bad1", "string") -run_test("bad2", "string") -run_test("bad3", "string") diff --git a/tests/circuitpython/getenv_test.py b/tests/circuitpython/getenv_test.py new file mode 100644 index 0000000000..d3735cc260 --- /dev/null +++ b/tests/circuitpython/getenv_test.py @@ -0,0 +1,20 @@ +def run_test(f, k=None): + try: + v = getenv_from_file(f"{BASE}/{f}.toml", k or f) + print(f, k, repr(v)) + except Exception as e: + print(f, k, str(e)) + + +BASE = __file__.rpartition("/")[0] or "." + +run_test("good", "notpresent") +run_test("good", "string") +run_test("good", "number") +run_test("good", "cstring") +run_test("good", "cnumber") +run_test("good", "subvalue") +for i in range(8): + run_test("good", f"string{i}") +for i in range(1, 5): + run_test(f"bad{i}", f"string") diff --git a/tests/circuitpython/environ_test.py.exp b/tests/circuitpython/getenv_test.py.exp similarity index 69% rename from tests/circuitpython/environ_test.py.exp rename to tests/circuitpython/getenv_test.py.exp index f168b089c0..e7c58666c2 100644 --- a/tests/circuitpython/environ_test.py.exp +++ b/tests/circuitpython/getenv_test.py.exp @@ -1,17 +1,18 @@ -good notpresent None -good string 'hello world' -good number 7 -good cstring 'hello comment' -good cnumber 127 -good subvalue None -good string0 None -good string1 '\n' -good string2 'Áx' -good string3 'Áx' -good string4 '\x0c"\\' -good string5 '\t\r\x08' -good string6 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' -good string7 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' -bad1 string err -bad2 string err -bad3 string err +good.toml notpresent None +good.toml string 'hello world' +good.toml number 7 +good.toml cstring 'hello comment' +good.toml cnumber 127 +good.toml subvalue None +good.toml string0 None +good.toml string1 '\n' +good.toml string2 'Áx' +good.toml string3 'Áx' +good.toml string4 '\x0c"\\' +good.toml string5 '\t\r\x08' +good.toml string6 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +good.toml string7 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +bad1.toml.bin string Invalid byte '\n' +bad2.toml.bin string Invalid byte '"' +bad3.toml.bin string invalid syntax for integer with base 10: '' +bad4.toml.bin string Invalid byte 'EOF' From dd6dd5df21a3c7a83f7c5eaa24ff7cfe6ceb8aec Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sat, 10 Dec 2022 12:58:08 -0600 Subject: [PATCH 22/34] rework the getenv test again * use a virtual fat filesystem during the test * this makes the file I/O part more closely patch runtime which is nice * side-steps the need to add a special function for testing * but test still can't be run on a device, because the vfs calls are incompatible, and you intentionally can't remount "/" anyway * and side-steps problems with storing 'bad' toml files --- .pre-commit-config.yaml | 4 +- ports/unix/main.c | 8 --- ports/unix/modos.c | 5 ++ shared-module/os/getenv.c | 47 +++++--------- tests/circuitpython/bad1.toml | 1 - tests/circuitpython/bad2.toml | 1 - tests/circuitpython/bad3.toml | 1 - tests/circuitpython/bad4.toml | 1 - tests/circuitpython/getenv_test.py | 88 +++++++++++++++++++++----- tests/circuitpython/getenv_test.py.exp | 31 ++++----- tests/circuitpython/good.toml | 14 ---- 11 files changed, 109 insertions(+), 92 deletions(-) delete mode 100644 tests/circuitpython/bad1.toml delete mode 100644 tests/circuitpython/bad2.toml delete mode 100644 tests/circuitpython/bad3.toml delete mode 100644 tests/circuitpython/bad4.toml delete mode 100644 tests/circuitpython/good.toml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 05e193f0e9..1905b233cf 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,9 +8,9 @@ repos: hooks: - id: check-yaml - id: end-of-file-fixer - exclude: '^(tests/.*\.toml|tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|ports/espressif/esp-idf-config/.*|ports/espressif/boards/.*/sdkconfig)' + exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|ports/espressif/esp-idf-config/.*|ports/espressif/boards/.*/sdkconfig)' - id: trailing-whitespace - exclude: '^(tests/.*\.toml|tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|lib/mbedtls_errors/.*)' + exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|lib/mbedtls_errors/.*)' - repo: local hooks: - id: translations diff --git a/ports/unix/main.c b/ports/unix/main.c index e423634e58..5ebcf9193b 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -420,13 +420,6 @@ STATIC void set_sys_argv(char *argv[], int argc, int start_arg) { #define PATHLIST_SEP_CHAR ':' #endif -mp_obj_t common_hal_os_getenv_path(const char *path, const char *key, mp_obj_t default_); -STATIC mp_obj_t getenv_from_file(mp_obj_t path_in, mp_obj_t key_to_get_in) { - return common_hal_os_getenv_path(mp_obj_str_get_str(path_in), - mp_obj_str_get_str(key_to_get_in), mp_const_none); -} -MP_DEFINE_CONST_FUN_OBJ_2(getenv_from_file_obj, getenv_from_file); - MP_NOINLINE int main_(int argc, char **argv); int main(int argc, char **argv) { @@ -547,7 +540,6 @@ MP_NOINLINE int main_(int argc, char **argv) { MP_DECLARE_CONST_FUN_OBJ_0(extra_cpp_coverage_obj); mp_store_global(MP_QSTR_extra_coverage, MP_OBJ_FROM_PTR(&extra_coverage_obj)); mp_store_global(MP_QSTR_extra_cpp_coverage, MP_OBJ_FROM_PTR(&extra_cpp_coverage_obj)); - mp_store_global(MP_QSTR_getenv_from_file, MP_OBJ_FROM_PTR(&getenv_from_file_obj)); } #endif diff --git a/ports/unix/modos.c b/ports/unix/modos.c index 6241dfa6c3..deea3bfc91 100644 --- a/ports/unix/modos.c +++ b/ports/unix/modos.c @@ -193,7 +193,12 @@ STATIC mp_obj_t mod_os_system(mp_obj_t cmd_in) { } MP_DEFINE_CONST_FUN_OBJ_1(mod_os_system_obj, mod_os_system); +mp_obj_t common_hal_os_getenv(const char *key, mp_obj_t default_); STATIC mp_obj_t mod_os_getenv(mp_obj_t var_in) { + mp_obj_t result = common_hal_os_getenv(mp_obj_str_get_str(var_in), mp_const_none); + if (result != mp_const_none) { + return result; + } const char *s = getenv(mp_obj_str_get_str(var_in)); if (s == NULL) { return mp_const_none; diff --git a/shared-module/os/getenv.c b/shared-module/os/getenv.c index 09dc19748d..0112a8a5cd 100644 --- a/shared-module/os/getenv.c +++ b/shared-module/os/getenv.c @@ -39,43 +39,29 @@ #include "supervisor/filesystem.h" #include "supervisor/memory.h" -#define GETENV_PATH "settings.toml" +#define GETENV_PATH "/settings.toml" -#if defined(UNIX) -typedef FILE *file_arg; -STATIC bool open_file(const char *name, file_arg *active_file) { - FILE *result = fopen(name, "r"); - if (result) { - *active_file = result; - } - return result != NULL; -} -STATIC void close_file(file_arg *active_file) { - fclose(*active_file); -} -STATIC bool is_eof(file_arg *active_file) { - return feof(*active_file); -} -STATIC uint8_t get_next_byte(file_arg *active_file) { - int value = fgetc(*active_file); - if (value == EOF) { - return 0; - } - return value; -} -__attribute__((unused)) -STATIC void seek_eof(file_arg *active_file) { - fseek(*active_file, 0, SEEK_END); - (void)fgetc(*active_file); -} -#else #include "extmod/vfs.h" #include "extmod/vfs_fat.h" typedef FIL file_arg; STATIC bool open_file(const char *name, file_arg *active_file) { + #if defined(UNIX) + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_obj_t file_obj = mp_call_function_2(MP_OBJ_FROM_PTR(&mp_builtin_open_obj), mp_obj_new_str(name, strlen(name)), MP_ROM_QSTR(MP_QSTR_rb)); + mp_arg_validate_type(file_obj, &mp_type_vfs_fat_fileio, MP_QSTR_file); + pyb_file_obj_t *file = MP_OBJ_TO_PTR(file_obj); + *active_file = file->fp; + nlr_pop(); + return true; + } else { + return false; + } + #else FATFS *fs = filesystem_circuitpy(); FRESULT result = f_open(fs, active_file, name, FA_READ); return result == FR_OK; + #endif } STATIC void close_file(file_arg *active_file) { // nothing @@ -95,7 +81,6 @@ STATIC uint8_t get_next_byte(FIL *active_file) { STATIC void seek_eof(file_arg *active_file) { f_lseek(active_file, f_size(active_file)); } -#endif // For a fixed buffer, record the required size rather than throwing STATIC void vstr_add_byte_nonstd(vstr_t *vstr, byte b) { @@ -363,7 +348,7 @@ mp_obj_t common_hal_os_getenv_path(const char *path, const char *key, mp_obj_t d vstr_init(&buf, 64); os_getenv_err_t result = os_getenv_vstr(path, key, &buf, "ed); - if (result == GETENV_ERR_NOT_FOUND) { + if (result == GETENV_ERR_NOT_FOUND || result == GETENV_ERR_OPEN) { return default_; } throw_getenv_error(result); diff --git a/tests/circuitpython/bad1.toml b/tests/circuitpython/bad1.toml deleted file mode 100644 index fce8db1800..0000000000 --- a/tests/circuitpython/bad1.toml +++ /dev/null @@ -1 +0,0 @@ -string = " diff --git a/tests/circuitpython/bad2.toml b/tests/circuitpython/bad2.toml deleted file mode 100644 index 666c573716..0000000000 --- a/tests/circuitpython/bad2.toml +++ /dev/null @@ -1 +0,0 @@ -string = """ diff --git a/tests/circuitpython/bad3.toml b/tests/circuitpython/bad3.toml deleted file mode 100644 index 705443a1c6..0000000000 --- a/tests/circuitpython/bad3.toml +++ /dev/null @@ -1 +0,0 @@ -string = diff --git a/tests/circuitpython/bad4.toml b/tests/circuitpython/bad4.toml deleted file mode 100644 index befe224084..0000000000 --- a/tests/circuitpython/bad4.toml +++ /dev/null @@ -1 +0,0 @@ -string=" \ No newline at end of file diff --git a/tests/circuitpython/getenv_test.py b/tests/circuitpython/getenv_test.py index d3735cc260..2f80e465e3 100644 --- a/tests/circuitpython/getenv_test.py +++ b/tests/circuitpython/getenv_test.py @@ -1,20 +1,78 @@ -def run_test(f, k=None): +import uos + +uos.umount("/") + + +class RAMBlockDevice: + ERASE_BLOCK_SIZE = 512 + + def __init__(self, blocks): + self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) + + def readblocks(self, block, buf, off=0): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + buf[i] = self.data[addr + i] + + def writeblocks(self, block, buf, off=None): + if off is None: + # erase, then write + off = 0 + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + self.data[addr + i] = buf[i] + + def ioctl(self, op, arg): + if op == 4: # block count + return len(self.data) // self.ERASE_BLOCK_SIZE + if op == 5: # block size + return self.ERASE_BLOCK_SIZE + if op == 6: # erase block + return 0 + + +bdev = RAMBlockDevice(64) +uos.VfsFat.mkfs(bdev) +uos.mount(uos.VfsFat(bdev), "/") + +content_good = """ +# comment +key0 = "hello world" +key1 = 7 + cstring = "hello comment" # comment + cnumber = 0x7f # comment +key2= "\n" +key3 ="\u00c1x" +key4 = "\U000000c1x" +key5 = "\f\"\\" +key6 = "\t\r\b" +key7 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +key8 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +[section] +subvalue = "hi" +""" + +content_bad = [ + 'key = "\n', + 'key = """\n', + "key =\n", + 'key="', +] + + +def run_test(key, content): + with open("/settings.toml", "w") as f: + f.write(content) + try: - v = getenv_from_file(f"{BASE}/{f}.toml", k or f) - print(f, k, repr(v)) + v = uos.getenv(key) + print(key, repr(v)) except Exception as e: - print(f, k, str(e)) + print(key, str(e)) -BASE = __file__.rpartition("/")[0] or "." +for i in range(9): + run_test(f"key{i}", content_good) -run_test("good", "notpresent") -run_test("good", "string") -run_test("good", "number") -run_test("good", "cstring") -run_test("good", "cnumber") -run_test("good", "subvalue") -for i in range(8): - run_test("good", f"string{i}") -for i in range(1, 5): - run_test(f"bad{i}", f"string") +for content in content_bad: + run_test("key", content) diff --git a/tests/circuitpython/getenv_test.py.exp b/tests/circuitpython/getenv_test.py.exp index e7c58666c2..b09c376d19 100644 --- a/tests/circuitpython/getenv_test.py.exp +++ b/tests/circuitpython/getenv_test.py.exp @@ -1,18 +1,13 @@ -good.toml notpresent None -good.toml string 'hello world' -good.toml number 7 -good.toml cstring 'hello comment' -good.toml cnumber 127 -good.toml subvalue None -good.toml string0 None -good.toml string1 '\n' -good.toml string2 'Áx' -good.toml string3 'Áx' -good.toml string4 '\x0c"\\' -good.toml string5 '\t\r\x08' -good.toml string6 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' -good.toml string7 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' -bad1.toml.bin string Invalid byte '\n' -bad2.toml.bin string Invalid byte '"' -bad3.toml.bin string invalid syntax for integer with base 10: '' -bad4.toml.bin string Invalid byte 'EOF' +key0 'hello world' +key1 7 +key2 Invalid byte '\n' +key3 'Áx' +key4 'Áx' +key5 Invalid byte '\\' +key6 '\t\r\x08' +key7 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +key8 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +key Invalid byte '\n' +key Invalid byte '"' +key invalid syntax for integer with base 10: '' +key Invalid byte 'EOF' diff --git a/tests/circuitpython/good.toml b/tests/circuitpython/good.toml deleted file mode 100644 index 17e5c054f4..0000000000 --- a/tests/circuitpython/good.toml +++ /dev/null @@ -1,14 +0,0 @@ -# comment -string = "hello world" -number = 7 - cstring = "hello comment" # comment - cnumber = 0x7f # comment -string1= "\n" -string2 ="\u00c1x" -string3 = "\U000000c1x" -string4 = "\f\"\\" -string5 = "\t\r\b" -string6 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -string7 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -[section] -subvalue = "hi" From 6426ddb73bd6d3a4760a45b44f7eb9fa7a17badb Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 12 Dec 2022 08:22:54 -0600 Subject: [PATCH 23/34] Rename test and add some additional cases While working on adding 0o and 0b literals (which aren't added yet and may not be) I realized that my approach would likely cause a problem for the value "0" --- tests/circuitpython/{getenv_test.py => getenv.py} | 7 ++++--- tests/circuitpython/{getenv_test.py.exp => getenv.py.exp} | 4 ++++ 2 files changed, 8 insertions(+), 3 deletions(-) rename tests/circuitpython/{getenv_test.py => getenv.py} (97%) rename tests/circuitpython/{getenv_test.py.exp => getenv.py.exp} (97%) diff --git a/tests/circuitpython/getenv_test.py b/tests/circuitpython/getenv.py similarity index 97% rename from tests/circuitpython/getenv_test.py rename to tests/circuitpython/getenv.py index 2f80e465e3..ad8fdbfeeb 100644 --- a/tests/circuitpython/getenv_test.py +++ b/tests/circuitpython/getenv.py @@ -39,8 +39,6 @@ content_good = """ # comment key0 = "hello world" key1 = 7 - cstring = "hello comment" # comment - cnumber = 0x7f # comment key2= "\n" key3 ="\u00c1x" key4 = "\U000000c1x" @@ -48,6 +46,9 @@ key5 = "\f\"\\" key6 = "\t\r\b" key7 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" key8 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + key9 = "hello comment" # comment + key10 = 0x7f # comment +key11 = 0 [section] subvalue = "hi" """ @@ -71,7 +72,7 @@ def run_test(key, content): print(key, str(e)) -for i in range(9): +for i in range(13): run_test(f"key{i}", content_good) for content in content_bad: diff --git a/tests/circuitpython/getenv_test.py.exp b/tests/circuitpython/getenv.py.exp similarity index 97% rename from tests/circuitpython/getenv_test.py.exp rename to tests/circuitpython/getenv.py.exp index b09c376d19..f83143c80b 100644 --- a/tests/circuitpython/getenv_test.py.exp +++ b/tests/circuitpython/getenv.py.exp @@ -7,6 +7,10 @@ key5 Invalid byte '\\' key6 '\t\r\x08' key7 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' key8 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +key9 'hello comment' +key10 127 +key11 0 +key12 None key Invalid byte '\n' key Invalid byte '"' key invalid syntax for integer with base 10: '' From 1b15985783708fed54f83a60a33b04ee8705ea45 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 12 Dec 2022 09:15:35 -0600 Subject: [PATCH 24/34] Fix web workflow builds --- supervisor/shared/web_workflow/web_workflow.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/supervisor/shared/web_workflow/web_workflow.c b/supervisor/shared/web_workflow/web_workflow.c index 5bac8522dd..58a68f0ec9 100644 --- a/supervisor/shared/web_workflow/web_workflow.c +++ b/supervisor/shared/web_workflow/web_workflow.c @@ -256,8 +256,8 @@ void supervisor_start_web_workflow(void) { return; } - result = common_hal_os_environ_get_key_str("CIRCUITPY_WIFI_PASSWORD", password, sizeof(password)); - if (result != ENVIRON_OK) { + result = common_hal_os_getenv_str("CIRCUITPY_WIFI_PASSWORD", password, sizeof(password)); + if (result != GETENV_OK) { return; } @@ -283,7 +283,7 @@ void supervisor_start_web_workflow(void) { mp_int_t new_port = web_api_port; // (leaves new_port unchanged on any failure) - (void)common_hal_os_environ_get_key_int("CIRCUITPY_WEB_API_PORT", &new_port); + (void)common_hal_os_getenv_int("CIRCUITPY_WEB_API_PORT", &new_port); bool first_start = pool.base.type != &socketpool_socketpool_type; bool port_changed = new_port != web_api_port; @@ -320,8 +320,8 @@ void supervisor_start_web_workflow(void) { const size_t api_password_len = sizeof(_api_password) - 1; - result = common_hal_os_environ_get_key_str("CIRCUITPY_WEB_API_PASSWORD", _api_password + 1, api_password_len); - if (result == ENVIRON_OK) { + result = common_hal_os_getenv_str("CIRCUITPY_WEB_API_PASSWORD", _api_password + 1, api_password_len); + if (result == GETENV_OK) { _api_password[0] = ':'; _base64_in_place(_api_password, strlen(_api_password), sizeof(_api_password) - 1); } From 3620d14542ceafe293c449ca633865c2420260c4 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 12 Dec 2022 17:04:03 -0600 Subject: [PATCH 25/34] Pass string length when enabling radio --- supervisor/shared/web_workflow/web_workflow.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/supervisor/shared/web_workflow/web_workflow.c b/supervisor/shared/web_workflow/web_workflow.c index 58a68f0ec9..87da0bd2a6 100644 --- a/supervisor/shared/web_workflow/web_workflow.c +++ b/supervisor/shared/web_workflow/web_workflow.c @@ -248,8 +248,6 @@ void supervisor_start_web_workflow(void) { char ssid[33]; char password[64]; - size_t ssid_len = 0; - size_t password_len = 0; os_getenv_err_t result = common_hal_os_getenv_str("CIRCUITPY_WIFI_SSID", ssid, sizeof(ssid)); if (result != GETENV_OK) { @@ -273,7 +271,7 @@ void supervisor_start_web_workflow(void) { // network. If we are connected to a different network, then it will disconnect before // attempting to connect to the given network. _wifi_status = common_hal_wifi_radio_connect( - &common_hal_wifi_radio_obj, (uint8_t *)ssid, ssid_len, (uint8_t *)password, password_len, + &common_hal_wifi_radio_obj, (uint8_t *)ssid, strlen(ssid), (uint8_t *)password, strlen(password), 0, 8, NULL, 0); if (_wifi_status != WIFI_RADIO_ERROR_NONE) { From 808161eaaba61860e959515dc55696a780fb329d Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 12 Dec 2022 19:09:57 -0600 Subject: [PATCH 26/34] fix missing sentinel in call --- supervisor/shared/web_workflow/web_workflow.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/supervisor/shared/web_workflow/web_workflow.c b/supervisor/shared/web_workflow/web_workflow.c index 87da0bd2a6..35d5c46a94 100644 --- a/supervisor/shared/web_workflow/web_workflow.c +++ b/supervisor/shared/web_workflow/web_workflow.c @@ -351,7 +351,7 @@ static void _send_str(socketpool_socket_obj_t *socket, const char *str) { } // The last argument must be NULL! Otherwise, it won't stop. -static void _send_strs(socketpool_socket_obj_t *socket, ...) { +static __attribute__((sentinel)) void _send_strs(socketpool_socket_obj_t *socket, ...) { va_list ap; va_start(ap, socket); @@ -691,7 +691,7 @@ static void _reply_with_file(socketpool_socket_obj_t *socket, _request *request, } else if (_endswith(filename, ".json")) { _send_strs(socket, "Content-Type:", "application/json", ";charset=UTF-8\r\n", NULL); } else { - _send_strs(socket, "Content-Type:", "application/octet-stream\r\n"); + _send_strs(socket, "Content-Type:", "application/octet-stream\r\n", NULL); } _cors_header(socket, request); _send_str(socket, "\r\n"); From 90894014a2e146e07c2ea4f9f840242fc33bf6a0 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 12 Dec 2022 19:43:10 -0600 Subject: [PATCH 27/34] Use the HW LED as status indicator For me this made a rare startup failure stop, which is nonsense. --- ports/raspberrypi/boards/raspberry_pi_pico_w/mpconfigboard.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/raspberrypi/boards/raspberry_pi_pico_w/mpconfigboard.h b/ports/raspberrypi/boards/raspberry_pi_pico_w/mpconfigboard.h index e5d8660b2b..a31ee7327c 100644 --- a/ports/raspberrypi/boards/raspberry_pi_pico_w/mpconfigboard.h +++ b/ports/raspberrypi/boards/raspberry_pi_pico_w/mpconfigboard.h @@ -4,5 +4,7 @@ #define CIRCUITPY_DIGITALIO_HAVE_INVALID_PULL (1) #define CIRCUITPY_DIGITALIO_HAVE_INVALID_DRIVE_MODE (1) +#define MICROPY_HW_LED_STATUS (&pin_CYW0) + #define CIRCUITPY_BOARD_I2C (1) #define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO5, .sda = &pin_GPIO4}} From adff93c61a4ed49cd81893270f269232452b7516 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 12 Dec 2022 20:14:08 -0600 Subject: [PATCH 28/34] Mark cyw43 pins "never reset" before reset_port reset_port calls reset_all_pins, which disables the built-in pull down. In theory, this could allow some CYW43 interfacing pin to float to an inappropriate value. There's no proof of this! but the move can't really hurt, either --- ports/raspberrypi/supervisor/port.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ports/raspberrypi/supervisor/port.c b/ports/raspberrypi/supervisor/port.c index 05d53fcc8d..27012f2298 100644 --- a/ports/raspberrypi/supervisor/port.c +++ b/ports/raspberrypi/supervisor/port.c @@ -127,6 +127,13 @@ safe_mode_t port_init(void) { (&_ld_dtcm_bss_start)[i] = 0; } + #if CIRCUITPY_CYW43 + never_reset_pin_number(23); + never_reset_pin_number(24); + never_reset_pin_number(25); + never_reset_pin_number(29); + #endif + // Reset everything into a known state before board_init. reset_port(); @@ -140,10 +147,6 @@ safe_mode_t port_init(void) { // Check brownout. #if CIRCUITPY_CYW43 - never_reset_pin_number(23); - never_reset_pin_number(24); - never_reset_pin_number(25); - never_reset_pin_number(29); // A small number of samples of pico w need an additional delay before // initializing the cyw43 chip. Delays inside cyw43_arch_init_with_country // are intended to meet the power on timing requirements, but apparently From d49af4d7848b432998d1d7e28995c7224643390e Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 13 Dec 2022 08:11:47 -0600 Subject: [PATCH 29/34] make wording a bit clearer --- ports/raspberrypi/bindings/rp2pio/StateMachine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/raspberrypi/bindings/rp2pio/StateMachine.c b/ports/raspberrypi/bindings/rp2pio/StateMachine.c index f45dc07357..041d02e5cd 100644 --- a/ports/raspberrypi/bindings/rp2pio/StateMachine.c +++ b/ports/raspberrypi/bindings/rp2pio/StateMachine.c @@ -422,7 +422,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_write_obj, 2, rp2pio_statemachine //| ) -> None: //| """Write data to the TX fifo in the background, with optional looping. //| -//| First, if any previous ``once`` or ``loop`` buffer has not been started, this function blocks until they have. +//| First, if any previous ``once`` or ``loop`` buffer has not been started, this function blocks until they have been started. //| This means that any ``once`` or ``loop`` buffer will be written at least once. //| Then the ``once`` and/or ``loop`` buffers are queued. and the function returns. //| The ``once`` buffer (if specified) will be written just once. From 56d4f8f55265a104ed22a9905e24b1ac8ecca94b Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 13 Dec 2022 11:32:33 -0600 Subject: [PATCH 30/34] can't use object-based calls at this time --- ports/nrf/common-hal/_bleio/Adapter.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/ports/nrf/common-hal/_bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c index 8948be1a5d..2c0c343877 100644 --- a/ports/nrf/common-hal/_bleio/Adapter.c +++ b/ports/nrf/common-hal/_bleio/Adapter.c @@ -54,6 +54,7 @@ #if CIRCUITPY_OS_GETENV #include "shared-bindings/os/__init__.h" +#include "shared-module/os/__init__.h" #endif #define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS) @@ -343,19 +344,17 @@ STATIC void bleio_adapter_reset_name(bleio_adapter_obj_t *self) { default_ble_name[len - 1] = nibble_to_hex_lower[addr.addr[0] & 0xf]; default_ble_name[len] = '\0'; // for now we add null for compatibility with C ASCIIZ strings - mp_int_t name_len = 0; - #if CIRCUITPY_OS_GETENV - mp_obj_t ble_name = common_hal_os_getenv("CIRCUITPY_BLE_NAME", mp_const_none); - if (ble_name != mp_const_none) { - common_hal_bleio_adapter_set_name(self, mp_obj_str_get_str(ble_name)); + char ble_name[32]; + + os_getenv_err_t result = common_hal_os_getenv_str("CIRCUITPY_BLE_NAME", ble_name, sizeof(ble_name)); + if (result == GETENV_OK) { + common_hal_bleio_adapter_set_name(self, ble_name); return; } #endif - if (name_len <= 0) { - common_hal_bleio_adapter_set_name(self, (char *)default_ble_name); - } + common_hal_bleio_adapter_set_name(self, (char *)default_ble_name); } static void bluetooth_adapter_background(void *data) { From 35f2046ab2703b9d23eb230bc9cddbe5d40eeaad Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 13 Dec 2022 12:02:07 -0600 Subject: [PATCH 31/34] Fix returning GETENV_ERR_LENGTH for over-long strings --- shared-module/os/getenv.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/shared-module/os/getenv.c b/shared-module/os/getenv.c index 0112a8a5cd..47b479f17c 100644 --- a/shared-module/os/getenv.c +++ b/shared-module/os/getenv.c @@ -86,6 +86,8 @@ STATIC void seek_eof(file_arg *active_file) { STATIC void vstr_add_byte_nonstd(vstr_t *vstr, byte b) { if (!vstr->fixed_buf || vstr->alloc > vstr->len) { vstr_add_byte(vstr, b); + } else { + vstr->len++; } } @@ -97,6 +99,8 @@ STATIC void vstr_add_char_nonstd(vstr_t *vstr, unichar c) { (c < 0x10000) ? 3 : 4; if (!vstr->fixed_buf || vstr->alloc > vstr->len + ulen) { vstr_add_char(vstr, c); + } else { + vstr->len += ulen; } } @@ -297,7 +301,7 @@ STATIC os_getenv_err_t os_getenv_buf_terminated(const char *key, char *value, si if (result == GETENV_OK) { vstr_add_byte_nonstd(&buf, 0); memcpy(value, buf.buf, MIN(buf.len, value_len)); - if (buf.len > value_len) { + if (buf.len > value_len) { // this length includes trailing NUL result = GETENV_ERR_LENGTH; } } From 5ac622a30d22bac54e8c9652d34d1ef113eb9a4e Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 13 Dec 2022 13:13:01 -0600 Subject: [PATCH 32/34] get rid of nearly-empty getenv.c file --- py/circuitpy_defns.mk | 2 +- shared-bindings/os/getenv.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 shared-bindings/os/getenv.c diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 2deefda030..22ea67d05e 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -614,7 +614,6 @@ SRC_SHARED_MODULE_ALL = \ onewireio/__init__.c \ onewireio/OneWire.c \ os/__init__.c \ - os/getenv.c \ paralleldisplay/ParallelBus.c \ qrio/__init__.c \ qrio/QRDecoder.c \ @@ -715,6 +714,7 @@ endif SRC_SHARED_MODULE_INTERNAL = \ $(filter $(SRC_PATTERNS), \ displayio/display_core.c \ + os/getenv.c \ usb/utf16le.c \ ) diff --git a/shared-bindings/os/getenv.c b/shared-bindings/os/getenv.c deleted file mode 100644 index fdb5f0bb50..0000000000 --- a/shared-bindings/os/getenv.c +++ /dev/null @@ -1 +0,0 @@ -// this file needs to exist but does not have any content From d40ba94449b461035d032a69e5578826e6a9f5a6 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 13 Dec 2022 13:19:10 -0600 Subject: [PATCH 33/34] explain why this is its own file --- shared-module/os/getenv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/shared-module/os/getenv.c b/shared-module/os/getenv.c index 47b479f17c..d96b1fb306 100644 --- a/shared-module/os/getenv.c +++ b/shared-module/os/getenv.c @@ -24,6 +24,9 @@ * THE SOFTWARE. */ +// These functions are separate from __init__.c so that os.getenv() can be +// tested in the unix "coverage" build, without bringing in "our" os module + #include #include From 369507e1da49ab82f07ebdcc089783481552c3b2 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Tue, 13 Dec 2022 18:39:25 -0500 Subject: [PATCH 34/34] cxd56 was not using SRC_SHARED_MODULE_INTERNAL --- ports/cxd56/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ports/cxd56/Makefile b/ports/cxd56/Makefile index 5d06143f73..f90b6dd460 100644 --- a/ports/cxd56/Makefile +++ b/ports/cxd56/Makefile @@ -134,7 +134,8 @@ SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ $(addprefix common-hal/, $(SRC_COMMON_HAL)) SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE)) + $(addprefix shared-module/, $(SRC_SHARED_MODULE)) \ + $(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL)) SRC_S = supervisor/cpu.s