From 51f86037837b57e404a5acd5d8851d4b1d9756ac Mon Sep 17 00:00:00 2001 From: microDev <70126934+microDev1@users.noreply.github.com> Date: Sun, 8 Aug 2021 15:15:15 +0530 Subject: [PATCH] add getpass module --- locale/circuitpython.pot | 14 +-- .../mpconfigboard.mk | 2 + .../boards/sensebox_mcu/mpconfigboard.mk | 2 + py/circuitpy_defns.mk | 4 + py/circuitpy_mpconfig.h | 8 ++ py/circuitpy_mpconfig.mk | 3 + shared-bindings/getpass/__init__.c | 86 +++++++++++++++++++ shared-module/getpass/__init__.c | 61 +++++++++++++ shared-module/getpass/__init__.h | 34 ++++++++ 9 files changed, 209 insertions(+), 5 deletions(-) create mode 100644 shared-bindings/getpass/__init__.c create mode 100644 shared-module/getpass/__init__.c create mode 100644 shared-module/getpass/__init__.h diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index f10f7fd019..0659588ae0 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -35,11 +35,11 @@ msgid "" "https://github.com/adafruit/circuitpython/issues\n" msgstr "" -#: py/obj.c shared-bindings/traceback/__init__.c +#: py/obj.c shared-module/traceback/__init__.c msgid " File \"%q\"" msgstr "" -#: py/obj.c shared-bindings/traceback/__init__.c +#: py/obj.c shared-module/traceback/__init__.c msgid " File \"%q\", line %d" msgstr "" @@ -322,7 +322,7 @@ msgstr "" msgid "*x must be assignment target" msgstr "" -#: py/obj.c shared-bindings/traceback/__init__.c +#: py/obj.c shared-module/traceback/__init__.c msgid ", in %q\n" msgstr "" @@ -2211,7 +2211,7 @@ msgstr "" msgid "Touch alarms not available" msgstr "" -#: py/obj.c shared-bindings/traceback/__init__.c +#: py/obj.c shared-module/traceback/__init__.c msgid "Traceback (most recent call last):\n" msgstr "" @@ -3903,6 +3903,10 @@ msgstr "" #: ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.h #: ports/esp32s2/boards/franzininho_wifi_wroom/mpconfigboard.h #: ports/esp32s2/boards/franzininho_wifi_wrover/mpconfigboard.h +#: ports/esp32s2/boards/gravitech_cucumber_m/mpconfigboard.h +#: ports/esp32s2/boards/gravitech_cucumber_ms/mpconfigboard.h +#: ports/esp32s2/boards/gravitech_cucumber_r/mpconfigboard.h +#: ports/esp32s2/boards/gravitech_cucumber_rs/mpconfigboard.h #: ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h #: ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.h #: ports/esp32s2/boards/muselab_nanoesp32_s2_wroom/mpconfigboard.h @@ -4101,7 +4105,7 @@ msgstr "" msgid "stop not reachable from start" msgstr "" -#: py/stream.c +#: py/stream.c shared-bindings/getpass/__init__.c msgid "stream operation not supported" msgstr "" diff --git a/ports/atmel-samd/boards/adafruit_proxlight_trinkey_m0/mpconfigboard.mk b/ports/atmel-samd/boards/adafruit_proxlight_trinkey_m0/mpconfigboard.mk index cf9afb3d21..3ef6dafac6 100644 --- a/ports/atmel-samd/boards/adafruit_proxlight_trinkey_m0/mpconfigboard.mk +++ b/ports/atmel-samd/boards/adafruit_proxlight_trinkey_m0/mpconfigboard.mk @@ -19,6 +19,8 @@ CIRCUITPY_PWMIO = 0 CIRCUITPY_ROTARYIO = 0 CIRCUITPY_RTC = 0 CIRCUITPY_USB_MIDI = 0 + +CIRCUITPY_GETPASS = 0 CIRCUITPY_TRACEBACK = 0 CIRCUITPY_PIXELBUF = 1 diff --git a/ports/atmel-samd/boards/sensebox_mcu/mpconfigboard.mk b/ports/atmel-samd/boards/sensebox_mcu/mpconfigboard.mk index 196d36816f..94a255529f 100644 --- a/ports/atmel-samd/boards/sensebox_mcu/mpconfigboard.mk +++ b/ports/atmel-samd/boards/sensebox_mcu/mpconfigboard.mk @@ -9,3 +9,5 @@ CHIP_FAMILY = samd21 INTERNAL_FLASH_FILESYSTEM = 1 LONGINT_IMPL = NONE CIRCUITPY_FULL_BUILD = 0 + +CIRCUITPY_GETPASS = 0 diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 92bd3b4d1f..84c8e22b2b 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -188,6 +188,9 @@ endif ifeq ($(CIRCUITPY_GAMEPADSHIFT),1) SRC_PATTERNS += gamepadshift/% endif +ifeq ($(CIRCUITPY_GETPASS),1) +SRC_PATTERNS += getpass/% +endif ifeq ($(CIRCUITPY_GNSS),1) SRC_PATTERNS += gnss/% endif @@ -519,6 +522,7 @@ SRC_SHARED_MODULE_ALL = \ fontio/__init__.c \ framebufferio/FramebufferDisplay.c \ framebufferio/__init__.c \ + getpass/__init__.c \ ipaddress/IPv4Address.c \ ipaddress/__init__.c \ keypad/__init__.c \ diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 5a7be5b79e..b8dbcd6de2 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -483,6 +483,13 @@ extern const struct _mp_obj_module_t gamepadshift_module; #define GAMEPAD_ROOT_POINTERS #endif +#if CIRCUITPY_GETPASS +extern const struct _mp_obj_module_t getpass_module; +#define GETPASS_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_getpass), (mp_obj_t)&getpass_module }, +#else +#define GETPASS_MODULE +#endif + #if CIRCUITPY_GNSS extern const struct _mp_obj_module_t gnss_module; #define GNSS_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_gnss), (mp_obj_t)&gnss_module }, @@ -896,6 +903,7 @@ extern const struct _mp_obj_module_t msgpack_module; FRAMEBUFFERIO_MODULE \ FREQUENCYIO_MODULE \ GAMEPADSHIFT_MODULE \ + GETPASS_MODULE \ GNSS_MODULE \ I2CPERIPHERAL_MODULE \ IPADDRESS_MODULE \ diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 45bc2e8fed..4df9432efa 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -184,6 +184,9 @@ CFLAGS += -DCIRCUITPY_FREQUENCYIO=$(CIRCUITPY_FREQUENCYIO) CIRCUITPY_GAMEPADSHIFT ?= 0 CFLAGS += -DCIRCUITPY_GAMEPADSHIFT=$(CIRCUITPY_GAMEPADSHIFT) +CIRCUITPY_GETPASS ?= 1 +CFLAGS += -DCIRCUITPY_GETPASS=$(CIRCUITPY_GETPASS) + CIRCUITPY_GNSS ?= 0 CFLAGS += -DCIRCUITPY_GNSS=$(CIRCUITPY_GNSS) diff --git a/shared-bindings/getpass/__init__.c b/shared-bindings/getpass/__init__.c new file mode 100644 index 0000000000..d627087aae --- /dev/null +++ b/shared-bindings/getpass/__init__.c @@ -0,0 +1,86 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 microDev + * + * 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 "py/stream.h" +#include "shared-module/getpass/__init__.h" + +//| """Getpass Module +//| +//| This module provides a way to get input from user without echoing it. +//| +//| """ +//| ... +//| + +//| def getpass(prompt: Optional[str] = 'Password: ', stream: Optional[io.FileIO] = None) -> str: +//| +//| """Prompt the user without echoing. +//| +//| :param str prompt: The user is prompted using the string ``prompt``, which defaults to ``'Password: '``. +//| :param io.FileIO stream: The ``prompt`` is written to the file-like object ``stream`` if provided. +//| +//| """ +//| ... +//| +STATIC mp_obj_t getpass_getpass(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_prompt, ARG_stream }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_prompt, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_stream, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + const char *prompt = (args[ARG_prompt].u_obj == mp_const_none) ? "Password: " : mp_obj_str_get_str(args[ARG_prompt].u_obj); + + mp_print_t print = {.data = NULL}; + if (args[ARG_stream].u_obj != mp_const_none) { + #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES + mp_get_stream_raise(args[ARG_stream].u_obj, MP_STREAM_OP_WRITE); + print.data = MP_OBJ_TO_PTR(args[ARG_stream].u_obj); + print.print_strn = mp_stream_write_adaptor; + #else + mp_raise_NotImplementedError(translate("stream operation not supported")); + #endif + } + + return shared_module_getpass_getpass(prompt, ((print.data) ? &print : NULL)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(getpass_getpass_obj, 0, getpass_getpass); + +STATIC const mp_rom_map_elem_t getpass_module_globals_table[] = { + // module name + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_getpass) }, + // module functions + { MP_ROM_QSTR(MP_QSTR_getpass), MP_ROM_PTR(&getpass_getpass_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(getpass_module_globals, getpass_module_globals_table); + +const mp_obj_module_t getpass_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&getpass_module_globals, +}; diff --git a/shared-module/getpass/__init__.c b/shared-module/getpass/__init__.c new file mode 100644 index 0000000000..f7ab96c378 --- /dev/null +++ b/shared-module/getpass/__init__.c @@ -0,0 +1,61 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 microDev + * + * 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 "py/mphal.h" +#include "lib/mp-readline/readline.h" +#include "shared-module/getpass/__init__.h" + +mp_obj_t shared_module_getpass_getpass(const char *prompt, mp_print_t *print) { + vstr_t vstr; + vstr_init(&vstr, 16); + + if (print == NULL) { + mp_hal_stdout_tx_str(prompt); + } else { + mp_printf(print, prompt); + } + + for (;;) { + int c = mp_hal_stdin_rx_chr(); + if (c == CHAR_CTRL_C) { + mp_raise_type(&mp_type_KeyboardInterrupt); + } else if (c == CHAR_CTRL_D && vstr.len == 0) { + mp_raise_type(&mp_type_EOFError); + } else if (c == 8 || c == 127) { + // backspace + vstr_cut_tail_bytes(&vstr, 1); + } else if (c >= 32) { + // printable character + vstr_ins_char(&vstr, vstr.len, c); + } else if (c == '\r') { + // newline + mp_hal_stdout_tx_str("\r\n"); + break; + } + } + + return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); +} diff --git a/shared-module/getpass/__init__.h b/shared-module/getpass/__init__.h new file mode 100644 index 0000000000..80595d41ba --- /dev/null +++ b/shared-module/getpass/__init__.h @@ -0,0 +1,34 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 microDev + * + * 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. + */ + +#ifndef MICROPY_INCLUDED_SHARED_MODULE_GETPASS___INIT___H +#define MICROPY_INCLUDED_SHARED_MODULE_GETPASS___INIT___H + +#include "py/runtime.h" + +extern mp_obj_t shared_module_getpass_getpass(const char *prompt, mp_print_t *print); + +#endif // MICROPY_INCLUDED_SHARED_MODULE_GETPASS___INIT___H