diff --git a/.github/build-each-commit.py b/.github/build-each-commit.py index 8ac7054ef..157344d72 100755 --- a/.github/build-each-commit.py +++ b/.github/build-each-commit.py @@ -57,7 +57,15 @@ # update only required submodules pybricks.git.submodule("update", "--init", "micropython") - if args.hub in ["cityhub", "movehub", "technichub", "primehub", "essentialhub", "nxt", "ev3"]: + if args.hub in [ + "cityhub", + "movehub", + "technichub", + "primehub", + "essentialhub", + "nxt", + "ev3", + ]: pybricks.submodule("micropython").module().git.submodule( "update", "--init", "lib/micropython-lib" ) @@ -66,7 +74,9 @@ ) if args.hub == "primehub" or args.hub == "essentialhub": pybricks.git.submodule("update", "--init", "--checkout", "lib/btstack") - pybricks.git.submodule("update", "--init", "--checkout", "lib/STM32_USB_Device_Library") + pybricks.git.submodule( + "update", "--init", "--checkout", "lib/STM32_USB_Device_Library" + ) # build the firmware subprocess.check_call( diff --git a/.github/build-missing-commits.py b/.github/build-missing-commits.py index d5320db1c..63e1af367 100755 --- a/.github/build-missing-commits.py +++ b/.github/build-missing-commits.py @@ -97,7 +97,9 @@ "update", "--init", "lib/stm32lib" ) pybricks.git.submodule("update", "--init", "--checkout", "lib/btstack") - pybricks.git.submodule("update", "--init", "--checkout", "lib/STM32_USB_Device_Library") + pybricks.git.submodule( + "update", "--init", "--checkout", "lib/STM32_USB_Device_Library" + ) # Make mpy-cross once print("Building mpy-cross") diff --git a/.github/download-commit-metadata.py b/.github/download-commit-metadata.py index 1be335ea2..af1806be2 100755 --- a/.github/download-commit-metadata.py +++ b/.github/download-commit-metadata.py @@ -65,7 +65,9 @@ def main(): ) sizes = { item["RowKey"]: { - k: v.value if isinstance(v, EntityProperty) else v for k, v in item.items() if k in HUBS + k: v.value if isinstance(v, EntityProperty) else v + for k, v in item.items() + if k in HUBS } for item in firmware_size_table.query_entities( "PartitionKey eq 'size'", diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 321d0ace5..cf089e3c9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -76,6 +76,7 @@ jobs: - name: Test if: ${{ success() }} run: | + ulimit -n 1024 # needed for micropython/tests/extmod/select_poll_fd.py cd micropython make -C ports/unix VARIANT=coverage test_full (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-multitests.py multi_net/*.py) diff --git a/bricks/_common/micropython.c b/bricks/_common/micropython.c index 37cc71f0e..bec3db0d7 100644 --- a/bricks/_common/micropython.c +++ b/bricks/_common/micropython.c @@ -55,8 +55,6 @@ void pbsys_main_stop_program(bool force_stop) { if (force_stop) { mp_sched_vm_abort(); } else { - pyexec_system_exit = PYEXEC_FORCED_EXIT; - static mp_obj_exception_t system_exit; system_exit.base.type = &mp_type_SystemExit; system_exit.traceback_alloc = system_exit.traceback_len = 0; @@ -106,9 +104,9 @@ static void mp_vfs_map_minimal_new_reader(mp_reader_t *reader, mp_vfs_map_minima } // Prints the exception that ended the program. -static void print_final_exception(mp_obj_t exc) { +static void print_final_exception(mp_obj_t exc, int ret) { // Handle graceful stop with button. - if (pyexec_system_exit == PYEXEC_FORCED_EXIT && + if ((ret & PYEXEC_FORCED_EXIT) && mp_obj_exception_match(exc, MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { mp_printf(&mp_plat_print, "The program was stopped (%q).\n", ((mp_obj_exception_t *)MP_OBJ_TO_PTR(exc))->base.type->name); @@ -121,8 +119,9 @@ static void print_final_exception(mp_obj_t exc) { #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL static void run_repl(void) { + int ret = 0; + readline_init0(); - pyexec_system_exit = 0; nlr_buf_t nlr; nlr.ret_val = NULL; @@ -134,12 +133,12 @@ static void run_repl(void) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { // Compatibility with mpremote. mp_printf(&mp_plat_print, "MPY: soft reboot\n"); - pyexec_raw_repl(); + ret = pyexec_raw_repl(); } else { - pyexec_friendly_repl(); + ret = pyexec_friendly_repl(); } #else // PYBRICKS_OPT_RAW_REPL - pyexec_friendly_repl(); + ret = pyexec_friendly_repl(); #endif // PYBRICKS_OPT_RAW_REPL nlr_pop(); } else { @@ -152,7 +151,7 @@ static void run_repl(void) { // clear any pending exceptions (and run any callbacks). mp_handle_pending(false); // Print which exception triggered this. - print_final_exception(MP_OBJ_FROM_PTR(nlr.ret_val)); + print_final_exception(MP_OBJ_FROM_PTR(nlr.ret_val), ret); } nlr_set_abort(NULL); @@ -175,7 +174,7 @@ static void do_execute_raw_code(mp_module_context_t *context, const mp_raw_code_ nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { - mp_obj_t module_fun = mp_make_function_from_raw_code(rc, mc, NULL); + mp_obj_t module_fun = mp_make_function_from_proto_fun(rc, mc, NULL); mp_call_function_0(module_fun); // finish nlr block, restore context @@ -241,7 +240,7 @@ static mpy_info_t *mpy_data_find(qstr name) { * Runs the __main__ module from user RAM. */ static void run_user_program(void) { - pyexec_system_exit = 0; + int ret = 0; nlr_buf_t nlr; nlr.ret_val = NULL; @@ -264,7 +263,7 @@ static void run_user_program(void) { mp_compiled_module_t compiled_module; compiled_module.context = context; mp_raw_code_load(&reader, &compiled_module); - mp_obj_t module_fun = mp_make_function_from_raw_code(compiled_module.rc, context, NULL); + mp_obj_t module_fun = mp_make_function_from_proto_fun(compiled_module.rc, context, NULL); // Run the script while letting CTRL-C interrupt it. mp_hal_set_interrupt_char(CHAR_CTRL_C); @@ -287,7 +286,12 @@ static void run_user_program(void) { // Clear any pending exceptions (and run any callbacks). mp_handle_pending(false); - print_final_exception(MP_OBJ_FROM_PTR(nlr.ret_val)); + if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t *)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { + // at the moment, the value of SystemExit is unused + ret = PYEXEC_FORCED_EXIT; + } + + print_final_exception(MP_OBJ_FROM_PTR(nlr.ret_val), ret); #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL // On KeyboardInterrupt, drop to REPL for debugging. @@ -430,9 +434,21 @@ mp_obj_t pb_builtin_import(size_t n_args, const mp_obj_t *args) { mp_raise_NotImplementedError(MP_ERROR_TEXT("relative import")); } - // Check if module already exists, and return it if it does + // Check if the module is already loaded. + mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_VM(mp_loaded_modules_dict).map, args[0], MP_MAP_LOOKUP); + if (elem) { + return elem->value; + } + + // Try the name directly as a non-extensible built-in (e.g. `micropython`). qstr module_name_qstr = mp_obj_str_get_qstr(args[0]); - mp_obj_t module_obj = mp_module_get_loaded_or_builtin(module_name_qstr); + mp_obj_t module_obj = mp_module_get_builtin(module_name_qstr, false); + if (module_obj != MP_OBJ_NULL) { + return module_obj; + } + + // Now try as an extensible built-in (e.g. `struct`/`ustruct`). + module_obj = mp_module_get_builtin(module_name_qstr, true); if (module_obj != MP_OBJ_NULL) { return module_obj; } @@ -473,7 +489,7 @@ mp_obj_t pb_builtin_import(size_t n_args, const mp_obj_t *args) { mp_module_context_t *context = MP_OBJ_TO_PTR(module_obj); const mp_frozen_module_t *frozen = modref; context->constants = frozen->constants; - do_execute_raw_code(context, frozen->rc, context); + do_execute_raw_code(context, frozen->proto_fun, context); return module_obj; } #endif @@ -486,7 +502,7 @@ mp_import_stat_t mp_import_stat(const char *path) { return MP_IMPORT_STAT_NO_EXIST; } -mp_lexer_t *mp_lexer_new_from_file(const char *filename) { +mp_lexer_t *mp_lexer_new_from_file(qstr filename) { mp_raise_OSError(MP_ENOENT); } diff --git a/bricks/_common/mpconfigport.h b/bricks/_common/mpconfigport.h index 7fc63b972..446ed955a 100644 --- a/bricks/_common/mpconfigport.h +++ b/bricks/_common/mpconfigport.h @@ -20,12 +20,12 @@ #define MICROPY_PY_MICROPYTHON (PYBRICKS_OPT_EXTRA_LEVEL1) #define MICROPY_PY_STRUCT (PYBRICKS_OPT_EXTRA_LEVEL1) #define MICROPY_PY_SYS (PYBRICKS_OPT_EXTRA_LEVEL1) -#define MICROPY_PY_UERRNO (1) -#define MICROPY_PY_UJSON (PYBRICKS_OPT_EXTRA_LEVEL1) -#define MICROPY_PY_URANDOM (PYBRICKS_OPT_EXTRA_LEVEL1) -#define MICROPY_PY_USELECT (PYBRICKS_OPT_EXTRA_LEVEL1) +#define MICROPY_PY_ERRNO (1) +#define MICROPY_PY_JSON (PYBRICKS_OPT_EXTRA_LEVEL1) +#define MICROPY_PY_RANDOM (PYBRICKS_OPT_EXTRA_LEVEL1) +#define MICROPY_PY_SELECT (PYBRICKS_OPT_EXTRA_LEVEL1) -#define MICROPY_PY_UERRNO_LIST \ +#define MICROPY_PY_ERRNO_LIST \ X(EPERM) \ X(EIO) \ X(EBUSY) \ @@ -93,11 +93,9 @@ #define MICROPY_PY_SYS_STDFILES (PYBRICKS_OPT_EXTRA_LEVEL1) #define MICROPY_PY_SYS_STDIO_BUFFER (PYBRICKS_OPT_EXTRA_LEVEL1) #define MICROPY_PY_SYS_STDIO_FLUSH (PYBRICKS_OPT_EXTRA_LEVEL1) -#define MICROPY_PY_URANDOM_EXTRA_FUNCS (PYBRICKS_OPT_EXTRA_LEVEL1) -#define MICROPY_PY_URANDOM_SEED_INIT_FUNC ({ extern uint32_t pbdrv_clock_get_us(void); pbdrv_clock_get_us(); }) -#define MICROPY_PY_UTIME_MP_HAL (0) +#define MICROPY_PY_RANDOM_EXTRA_FUNCS (PYBRICKS_OPT_EXTRA_LEVEL1) +#define MICROPY_PY_RANDOM_SEED_INIT_FUNC ({ extern uint32_t pbdrv_clock_get_us(void); pbdrv_clock_get_us(); }) #define MICROPY_MODULE_BUILTIN_INIT (1) -#define MICROPY_MODULE_WEAK_LINKS (0) #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) #if PYBRICKS_OPT_FLOAT diff --git a/bricks/_common_stm32/mphalport.c b/bricks/_common_stm32/mphalport.c index 4cfd7ad98..7b94c6bd4 100644 --- a/bricks/_common_stm32/mphalport.c +++ b/bricks/_common_stm32/mphalport.c @@ -64,11 +64,13 @@ int mp_hal_stdin_rx_chr(void) { } // Send string of given length -void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { while (pbsys_host_tx((const uint8_t *)str, len) == PBIO_ERROR_AGAIN) { MICROPY_EVENT_POLL_HOOK } // Not raising the error. This means stdout lost if host is not connected. + + return len; } void mp_hal_stdout_tx_flush(void) { diff --git a/bricks/ev3/make_bootable_image.py b/bricks/ev3/make_bootable_image.py index fd7b59e7d..309f50d81 100755 --- a/bricks/ev3/make_bootable_image.py +++ b/bricks/ev3/make_bootable_image.py @@ -23,7 +23,6 @@ def make_firmware(uboot_blob: bytes, uimage_blob: bytes) -> bytes: - if len(uboot_blob) > UBOOT_MAX_SIZE: print( f"u-boot file is bigger than 256KiB ({len(uboot_blob)} bytes), it is not safe to use.", @@ -32,13 +31,18 @@ def make_firmware(uboot_blob: bytes, uimage_blob: bytes) -> bytes: exit(1) if len(uimage_blob) > UIMAGE_MAX_SIZE: - print(f"uImage file is too big ({len(uimage_blob)} > {UIMAGE_MAX_SIZE}).", file=sys.stderr) + print( + f"uImage file is too big ({len(uimage_blob)} > {UIMAGE_MAX_SIZE}).", + file=sys.stderr, + ) exit(1) # Gets combined size, rounded to nearest expected size. combined_size = UIMAGE_OFFSET + len(uimage_blob) combined_size = ( - (combined_size + FIRMWARE_ROUND_SIZE) // FIRMWARE_ROUND_SIZE * FIRMWARE_ROUND_SIZE + (combined_size + FIRMWARE_ROUND_SIZE) + // FIRMWARE_ROUND_SIZE + * FIRMWARE_ROUND_SIZE ) # Put it all together. @@ -59,9 +63,11 @@ def make_firmware(uboot_blob: bytes, uimage_blob: bytes) -> bytes: parser.add_argument("output", help="The output file") args = parser.parse_args() - with open(args.uboot, "rb") as uboot_file, open(args.uimage, "rb") as uimage_file, open( - args.output, "wb" - ) as output_file: + with ( + open(args.uboot, "rb") as uboot_file, + open(args.uimage, "rb") as uimage_file, + open(args.output, "wb") as output_file, + ): combined = make_firmware(uboot_file.read(), uimage_file.read()) output_file.write(combined) print(f"Created {args.output} with size {len(combined) // 1024} KB.") diff --git a/bricks/ev3/mphalport.c b/bricks/ev3/mphalport.c index fa142988a..14f75be20 100644 --- a/bricks/ev3/mphalport.c +++ b/bricks/ev3/mphalport.c @@ -57,7 +57,7 @@ int mp_hal_stdin_rx_chr(void) { extern uint32_t pbdrv_usb_write(const uint8_t *data, uint32_t size); -void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { pbdrv_uart_debug_printf("%.*s", len, str); uint32_t done = 0; @@ -69,6 +69,8 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { while (!pbdrv_uart_debug_is_done()) { MICROPY_VM_HOOK_LOOP; } + + return len; } extern void pbdrv_usb_tx_flush(void); diff --git a/bricks/nxt/mphalport.c b/bricks/nxt/mphalport.c index a81939a32..b917500e7 100644 --- a/bricks/nxt/mphalport.c +++ b/bricks/nxt/mphalport.c @@ -74,17 +74,19 @@ int mp_hal_stdin_rx_chr(void) { } // Send string of given length -void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { // Nothing to do if disconnected or empty data if (!nx_bt_stream_opened() || len == 0) { - return; + return len; } nx_bt_stream_write((uint8_t *)str, len); while (!nx_bt_stream_data_written()) { MICROPY_EVENT_POLL_HOOK; } + + return len; } void mp_hal_stdout_tx_flush(void) { diff --git a/bricks/primehub/modules/_imu_calibrate.py b/bricks/primehub/modules/_imu_calibrate.py index cc04705db..c2cb394df 100644 --- a/bricks/primehub/modules/_imu_calibrate.py +++ b/bricks/primehub/modules/_imu_calibrate.py @@ -36,21 +36,21 @@ def wait_for_stationary(side): def roll_over_axis(axis, new_side): - global bias, bias_count print("Roll it towards you, without lifting the hub up!") angle_start = hub.imu.rotation(axis, calibrated=False) while hub.imu.up(calibrated=False) != new_side or not hub.imu.stationary(): - _, _, z = hub.imu.orientation() * axis if abs(z) > 0.07: print(hub.imu.orientation() * axis) raise RuntimeError("Lifted it!") wait(100) - uncalibrated_90_deg_rotation = abs(hub.imu.rotation(axis, calibrated=False) - angle_start) + uncalibrated_90_deg_rotation = abs( + hub.imu.rotation(axis, calibrated=False) - angle_start + ) if abs(uncalibrated_90_deg_rotation - 90) > 10: raise RuntimeError("Not 90 deg!") diff --git a/bricks/virtualhub/mpconfigvariant.h b/bricks/virtualhub/mpconfigvariant.h index a18f4a4af..ab4e2cd1a 100644 --- a/bricks/virtualhub/mpconfigvariant.h +++ b/bricks/virtualhub/mpconfigvariant.h @@ -56,15 +56,16 @@ #define MICROPY_DEBUG_PRINTERS (1) #define MICROPY_MODULE_ATTR_DELEGATION (1) #define MICROPY_MODULE_BUILTIN_INIT (1) +#define MICROPY_MODULE_BUILTIN_SUBPACKAGES (1) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_MODULES (1) #define MICROPY_PY_SYS_SETTRACE (1) -#define MICROPY_PY_UERRNO (1) -#define MICROPY_PY_UOS (1) -#define MICROPY_PY_UOS_GETENV_PUTENV_UNSETENV (1) -#define MICROPY_PY_UOS_INCLUDEFILE "ports/unix/moduos.c" -#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) +#define MICROPY_PY_ERRNO (1) +#define MICROPY_PY_OS (1) +#define MICROPY_PY_OS_GETENV_PUTENV_UNSETENV (1) +#define MICROPY_PY_OS_INCLUDEFILE "ports/unix/modos.c" +#define MICROPY_PY_RANDOM_EXTRA_FUNCS (1) #define MICROPY_PY_BUILTINS_SLICE_INDICES (1) #define MICROPY_PERSISTENT_CODE_SAVE (1) #define MICROPY_STREAMS_POSIX_API (1) @@ -72,7 +73,7 @@ #define MICROPY_KBD_EXCEPTION (1) // REVISIT: This list currently matches the stm32 builds. -#define MICROPY_PY_UERRNO_LIST \ +#define MICROPY_PY_ERRNO_LIST \ X(EPERM) \ X(EIO) \ X(EBUSY) \ diff --git a/bricks/virtualhub/mpconfigvariant.mk b/bricks/virtualhub/mpconfigvariant.mk index c62c464b7..d7dd65e53 100644 --- a/bricks/virtualhub/mpconfigvariant.mk +++ b/bricks/virtualhub/mpconfigvariant.mk @@ -30,8 +30,8 @@ MICROPY_PY_SOCKET = 1 # ffi module requires libffi (libffi-dev Debian package) MICROPY_PY_FFI = 1 -# ussl module requires one of the TLS libraries below -MICROPY_PY_USSL = 0 +# ssl module requires one of the TLS libraries below +MICROPY_PY_SSL = 0 # axTLS has minimal size but implements only a subset of modern TLS # functionality, so may have problems with some servers. MICROPY_SSL_AXTLS = 0 diff --git a/lib/pbio/doc/control/motor_model.py b/lib/pbio/doc/control/motor_model.py index cf9e65fe0..e8e6f33ae 100755 --- a/lib/pbio/doc/control/motor_model.py +++ b/lib/pbio/doc/control/motor_model.py @@ -151,7 +151,9 @@ def make_model(name, *, V, tau_0, tau_x, w_0, w_x, i_0, i_x, a, Lm, h): model[L] = Lm # Substitute parameters into model to get numeric system matrices - exponent_numeric = numpy.array(exponent.subs(model).evalf().tolist()).astype(numpy.float64) + exponent_numeric = numpy.array(exponent.subs(model).evalf().tolist()).astype( + numpy.float64 + ) # Get matrix exponential and system matrices exponential = scipy.linalg.expm(exponent_numeric * h) @@ -196,7 +198,6 @@ def make_model(name, *, V, tau_0, tau_x, w_0, w_x, i_0, i_x, a, Lm, h): if __name__ == "__main__": - print(HEADER) print( diff --git a/lib/pbio/test/animator/data_parser.py b/lib/pbio/test/animator/data_parser.py index ad7e705fa..c3fb9b4ea 100755 --- a/lib/pbio/test/animator/data_parser.py +++ b/lib/pbio/test/animator/data_parser.py @@ -37,13 +37,11 @@ # Write the CSS component with frames. with open("../results/frames.css", "w") as frame_file: - for info in FRAME_INFO: - # CSS rows for each frame. frames = "".join( [ - f"{i * 100 // (len(angles) - 1)}% {{transform: translate({info.x}px, {info.y}px) rotate( {int(row[info.index])// info.gearing}deg );}}\n" + f"{i * 100 // (len(angles) - 1)}% {{transform: translate({info.x}px, {info.y}px) rotate( {int(row[info.index]) // info.gearing}deg );}}\n" for i, row in enumerate(angles) ] ) diff --git a/micropython b/micropython index 9305b73d7..73cbdab14 160000 --- a/micropython +++ b/micropython @@ -1 +1 @@ -Subproject commit 9305b73d7e6c6761367624a0077d4bdf96601c5a +Subproject commit 73cbdab1465aa1772659b764524bddf316bc059c diff --git a/poetry.lock b/poetry.lock index 7a54d6922..3726074f2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -316,41 +316,6 @@ files = [ {file = "bidict-0.23.1.tar.gz", hash = "sha256:03069d763bc387bbd20e7d49914e75fc4132a41937fa3405417e1a5a2d006d71"}, ] -[[package]] -name = "black" -version = "22.12.0" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.7" -groups = ["lint"] -files = [ - {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"}, - {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"}, - {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"}, - {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"}, - {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"}, - {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"}, - {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"}, - {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"}, - {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"}, - {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"}, - {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"}, - {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - [[package]] name = "bleach" version = "6.2.0" @@ -615,33 +580,18 @@ files = [ {file = "charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63"}, ] -[[package]] -name = "click" -version = "8.2.0" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.10" -groups = ["lint"] -files = [ - {file = "click-8.2.0-py3-none-any.whl", hash = "sha256:6b303f0b2aa85f1cb4e5303078fadcbcd4e476f114fab9b5007005711839325c"}, - {file = "click-8.2.0.tar.gz", hash = "sha256:f5452aeddd9988eefa20f90f05ab66f17fce1ee2a36907fd30b05bbb5953814d"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - [[package]] name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["dev", "lint"] +groups = ["dev"] +markers = "sys_platform == \"win32\" or platform_system == \"Windows\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -markers = {dev = "sys_platform == \"win32\" or platform_system == \"Windows\"", lint = "platform_system == \"Windows\""} [[package]] name = "comm" @@ -2211,18 +2161,6 @@ files = [ [package.dependencies] typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.11\""} -[[package]] -name = "mypy-extensions" -version = "1.1.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.8" -groups = ["lint"] -files = [ - {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, - {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, -] - [[package]] name = "nbclassic" version = "1.3.1" @@ -2526,18 +2464,6 @@ files = [ qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] testing = ["docopt", "pytest"] -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -groups = ["lint"] -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - [[package]] name = "pexpect" version = "4.9.0" @@ -2660,7 +2586,7 @@ version = "4.3.8" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.9" -groups = ["dev", "lint"] +groups = ["dev"] files = [ {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, @@ -3724,6 +3650,34 @@ files = [ {file = "rpds_py-0.25.0.tar.gz", hash = "sha256:4d97661bf5848dd9e5eb7ded480deccf9d32ce2cd500b88a26acbf7bd2864985"}, ] +[[package]] +name = "ruff" +version = "0.12.1" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +groups = ["lint"] +files = [ + {file = "ruff-0.12.1-py3-none-linux_armv6l.whl", hash = "sha256:6013a46d865111e2edb71ad692fbb8262e6c172587a57c0669332a449384a36b"}, + {file = "ruff-0.12.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b3f75a19e03a4b0757d1412edb7f27cffb0c700365e9d6b60bc1b68d35bc89e0"}, + {file = "ruff-0.12.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:9a256522893cb7e92bb1e1153283927f842dea2e48619c803243dccc8437b8be"}, + {file = "ruff-0.12.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:069052605fe74c765a5b4272eb89880e0ff7a31e6c0dbf8767203c1fbd31c7ff"}, + {file = "ruff-0.12.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a684f125a4fec2d5a6501a466be3841113ba6847827be4573fddf8308b83477d"}, + {file = "ruff-0.12.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdecdef753bf1e95797593007569d8e1697a54fca843d78f6862f7dc279e23bd"}, + {file = "ruff-0.12.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:70d52a058c0e7b88b602f575d23596e89bd7d8196437a4148381a3f73fcd5010"}, + {file = "ruff-0.12.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84d0a69d1e8d716dfeab22d8d5e7c786b73f2106429a933cee51d7b09f861d4e"}, + {file = "ruff-0.12.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6cc32e863adcf9e71690248607ccdf25252eeeab5193768e6873b901fd441fed"}, + {file = "ruff-0.12.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7fd49a4619f90d5afc65cf42e07b6ae98bb454fd5029d03b306bd9e2273d44cc"}, + {file = "ruff-0.12.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ed5af6aaaea20710e77698e2055b9ff9b3494891e1b24d26c07055459bb717e9"}, + {file = "ruff-0.12.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:801d626de15e6bf988fbe7ce59b303a914ff9c616d5866f8c79eb5012720ae13"}, + {file = "ruff-0.12.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:2be9d32a147f98a1972c1e4df9a6956d612ca5f5578536814372113d09a27a6c"}, + {file = "ruff-0.12.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:49b7ce354eed2a322fbaea80168c902de9504e6e174fd501e9447cad0232f9e6"}, + {file = "ruff-0.12.1-py3-none-win32.whl", hash = "sha256:d973fa626d4c8267848755bd0414211a456e99e125dcab147f24daa9e991a245"}, + {file = "ruff-0.12.1-py3-none-win_amd64.whl", hash = "sha256:9e1123b1c033f77bd2590e4c1fe7e8ea72ef990a85d2484351d408224d603013"}, + {file = "ruff-0.12.1-py3-none-win_arm64.whl", hash = "sha256:78ad09a022c64c13cc6077707f036bab0fac8cd7088772dcd1e5be21c5002efc"}, + {file = "ruff-0.12.1.tar.gz", hash = "sha256:806bbc17f1104fd57451a98a58df35388ee3ab422e029e8f5cf30aa4af2c138c"}, +] + [[package]] name = "scipy" version = "1.15.3" @@ -4000,49 +3954,6 @@ webencodings = ">=0.4" doc = ["sphinx", "sphinx_rtd_theme"] test = ["pytest", "ruff"] -[[package]] -name = "tomli" -version = "2.2.1" -description = "A lil' TOML parser" -optional = false -python-versions = ">=3.8" -groups = ["lint"] -markers = "python_full_version < \"3.11.0a7\"" -files = [ - {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, - {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, - {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, - {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, - {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, - {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, - {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, - {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, - {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, - {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, - {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, - {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, - {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, - {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, - {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, - {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, - {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, - {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, - {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, - {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, - {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, - {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, - {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, - {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, - {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, - {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, - {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, - {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, - {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, - {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, - {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, - {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, -] - [[package]] name = "tornado" version = "6.5" @@ -4697,4 +4608,4 @@ propcache = ">=0.2.1" [metadata] lock-version = "2.1" python-versions = ">=3.10,<3.13" -content-hash = "f7c805bbd89804d884a596ea8f78ac1a2c24b7adb6c2e20dd13c4ef51409d7f7" +content-hash = "a97622ebb5b5c33bb1503137186c8d810841ef73ac4f0a8e68af4e79562174ef" diff --git a/pybricks/common/pb_type_ble.c b/pybricks/common/pb_type_ble.c index cd3105cbb..348a58de4 100644 --- a/pybricks/common/pb_type_ble.c +++ b/pybricks/common/pb_type_ble.c @@ -566,7 +566,7 @@ mp_obj_t pb_type_BLE_new(mp_obj_t broadcast_channel_in, mp_obj_t observe_channel } #endif // PBSYS_CONFIG_BLUETOOTH_TOGGLE - pb_obj_BLE_t *self = mp_obj_malloc_var(pb_obj_BLE_t, observed_data_t, num_observe_channels, &pb_type_BLE); + pb_obj_BLE_t *self = mp_obj_malloc_var(pb_obj_BLE_t, observed_data, observed_data_t, num_observe_channels, &pb_type_BLE); self->broadcast_channel = broadcast_channel_in; for (mp_int_t i = 0; i < num_observe_channels; i++) { diff --git a/pybricks/common/pb_type_device.c b/pybricks/common/pb_type_device.c index 2c5c1120d..6fdb108a1 100644 --- a/pybricks/common/pb_type_device.c +++ b/pybricks/common/pb_type_device.c @@ -117,9 +117,7 @@ mp_obj_t pb_type_device_method_call(mp_obj_t self_in, size_t n_args, size_t n_kw */ MP_DEFINE_CONST_OBJ_TYPE( pb_type_device_method, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN, - call, pb_type_device_method_call, - unary_op, mp_generic_unary_op - ); + call, pb_type_device_method_call); /** * Set data for a Powered Up device, such as the brightness of multiple external diff --git a/pybricks/common/pb_type_imu.c b/pybricks/common/pb_type_imu.c index 8a21fd232..503bc77f8 100644 --- a/pybricks/common/pb_type_imu.c +++ b/pybricks/common/pb_type_imu.c @@ -311,7 +311,7 @@ static mp_obj_t pb_type_imu_heading(size_t n_args, const mp_obj_t *pos_args, mp_ static MP_DEFINE_CONST_FUN_OBJ_KW(pb_type_imu_heading_obj, 1, pb_type_imu_heading); // pybricks._common.IMU.orientation -STATIC mp_obj_t common_IMU_orientation(mp_obj_t self_in) { +static mp_obj_t common_IMU_orientation(mp_obj_t self_in) { // Make matrix. REVISIT: Dedicated call from orientation matrix. pb_type_Matrix_obj_t *matrix = MP_OBJ_TO_PTR(pb_type_Matrix_make_bitmap(3, 3, 1.0f, 0)); diff --git a/pybricks/parameters/pb_type_button.c b/pybricks/parameters/pb_type_button.c index 421a8190e..331336713 100644 --- a/pybricks/parameters/pb_type_button.c +++ b/pybricks/parameters/pb_type_button.c @@ -104,7 +104,6 @@ MP_DEFINE_CONST_OBJ_TYPE(pb_type_button_, MP_TYPE_FLAG_NONE, print, pb_type_button_print, attr, pb_type_button_attribute_handler, - unary_op, mp_generic_unary_op, binary_op, pb_type_button_binary_op ); diff --git a/pybricks/parameters/pb_type_color.c b/pybricks/parameters/pb_type_color.c index 459944abb..3a14e43a5 100644 --- a/pybricks/parameters/pb_type_color.c +++ b/pybricks/parameters/pb_type_color.c @@ -354,7 +354,6 @@ MP_DEFINE_CONST_OBJ_TYPE(pb_type_Color, call, pb_type_Color_call, attr, pb_type_Color_attr, print, pb_type_Color_print, - unary_op, mp_generic_unary_op, binary_op, pb_type_Color_binary_op, subscr, pb_type_Color_subscr, iter, pb_type_Color_getiter); diff --git a/pybricks/parameters/pb_type_direction.c b/pybricks/parameters/pb_type_direction.c index ed97837e0..577e3f0ac 100644 --- a/pybricks/parameters/pb_type_direction.c +++ b/pybricks/parameters/pb_type_direction.c @@ -33,7 +33,6 @@ MP_DEFINE_CONST_OBJ_TYPE(pb_enum_type_Direction, MP_QSTR_Direction, MP_TYPE_FLAG_NONE, print, pb_type_enum_print, - unary_op, mp_generic_unary_op, locals_dict, &(pb_enum_type_Direction_locals_dict)); #endif // PYBRICKS_PY_PARAMETERS diff --git a/pybricks/parameters/pb_type_port.c b/pybricks/parameters/pb_type_port.c index a696b7640..fa04cd011 100644 --- a/pybricks/parameters/pb_type_port.c +++ b/pybricks/parameters/pb_type_port.c @@ -131,7 +131,6 @@ MP_DEFINE_CONST_OBJ_TYPE(pb_enum_type_Port, MP_QSTR_Port, MP_TYPE_FLAG_NONE, print, pb_type_enum_print, - unary_op, mp_generic_unary_op, locals_dict, &(pb_enum_type_Port_locals_dict)); #endif // PYBRICKS_PY_PARAMETERS diff --git a/pybricks/parameters/pb_type_side.c b/pybricks/parameters/pb_type_side.c index f65bfb18c..df5a21194 100644 --- a/pybricks/parameters/pb_type_side.c +++ b/pybricks/parameters/pb_type_side.c @@ -61,7 +61,6 @@ MP_DEFINE_CONST_OBJ_TYPE(pb_enum_type_Side, MP_QSTR_Side, MP_TYPE_FLAG_NONE, print, pb_type_enum_print, - unary_op, mp_generic_unary_op, locals_dict, &(pb_enum_type_Side_locals_dict)); #endif // PYBRICKS_PY_PARAMETERS diff --git a/pybricks/parameters/pb_type_stop.c b/pybricks/parameters/pb_type_stop.c index 245b1e526..72ab647e2 100644 --- a/pybricks/parameters/pb_type_stop.c +++ b/pybricks/parameters/pb_type_stop.c @@ -61,7 +61,6 @@ MP_DEFINE_CONST_OBJ_TYPE(pb_enum_type_Stop, MP_QSTR_Stop, MP_TYPE_FLAG_NONE, print, pb_type_enum_print, - unary_op, mp_generic_unary_op, locals_dict, &(pb_enum_type_Stop_locals_dict)); #endif // PYBRICKS_PY_PARAMETERS diff --git a/pybricks/pybricks.c b/pybricks/pybricks.c index c71fd8891..f3ddec2d8 100644 --- a/pybricks/pybricks.c +++ b/pybricks/pybricks.c @@ -39,7 +39,7 @@ static const mp_rom_obj_tuple_t pybricks_info_obj = { }; #if MICROPY_MODULE_ATTR_DELEGATION -static void pb_package_pybricks_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +void pb_package_pybricks_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { // This will get called when external imports tries to store the module // as an attribute to this package. This is not currently supported, but // it should not cause an exception, so indicate success. @@ -50,8 +50,37 @@ static void pb_package_pybricks_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest static const mp_rom_map_elem_t pybricks_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pybricks) }, { MP_ROM_QSTR(MP_QSTR_version), MP_ROM_PTR(&pybricks_info_obj)}, - #if MICROPY_MODULE_ATTR_DELEGATION - MP_MODULE_ATTR_DELEGATION_ENTRY(&pb_package_pybricks_attr), + #if MICROPY_MODULE_BUILTIN_SUBPACKAGES + #if PYBRICKS_PY_EXPERIMENTAL + { MP_ROM_QSTR(MP_QSTR_experimental), MP_ROM_PTR(&pb_module_experimental) }, + #endif + #if PYBRICKS_PY_HUBS + { MP_ROM_QSTR(MP_QSTR_hubs), MP_ROM_PTR(&pb_module_hubs) }, + #endif + #if PYBRICKS_PY_NXTDEVICES + { MP_ROM_QSTR(MP_QSTR_nxtdevices), MP_ROM_PTR(&pb_module_nxtdevices) }, + #endif + #if PYBRICKS_PY_EV3DEVICES + { MP_ROM_QSTR(MP_QSTR_ev3devices), MP_ROM_PTR(&pb_module_ev3devices) }, + #endif + #if PYBRICKS_PY_PUPDEVICES + { MP_ROM_QSTR(MP_QSTR_pupdevices), MP_ROM_PTR(&pb_module_pupdevices) }, + #endif + #if PYBRICKS_PY_IODEVICES + { MP_ROM_QSTR(MP_QSTR_iodevices), MP_ROM_PTR(&pb_module_iodevices) }, + #endif + #if PYBRICKS_PY_MEDIA + { MP_ROM_QSTR(MP_QSTR_media), MP_ROM_PTR(&pb_module_media) }, + #endif + #if PYBRICKS_PY_PARAMETERS + { MP_ROM_QSTR(MP_QSTR_parameters), MP_ROM_PTR(&pb_module_parameters) }, + #endif + #if PYBRICKS_PY_TOOLS + { MP_ROM_QSTR(MP_QSTR_tools), MP_ROM_PTR(&pb_module_tools) }, + #endif + #if PYBRICKS_PY_ROBOTICS + { MP_ROM_QSTR(MP_QSTR_robotics), MP_ROM_PTR(&pb_module_robotics) }, + #endif #endif }; static MP_DEFINE_CONST_DICT(pb_package_pybricks_globals, pybricks_globals_table); @@ -62,6 +91,7 @@ const mp_obj_module_t pb_package_pybricks = { }; MP_REGISTER_MODULE(MP_QSTR_pybricks, pb_package_pybricks); +MP_REGISTER_MODULE_DELEGATION(pb_package_pybricks, pb_package_pybricks_attr); #if PYBRICKS_OPT_COMPILER /** diff --git a/pybricks/tools/pb_type_app_data.c b/pybricks/tools/pb_type_app_data.c index 0591b19e1..038a99732 100644 --- a/pybricks/tools/pb_type_app_data.c +++ b/pybricks/tools/pb_type_app_data.c @@ -42,16 +42,16 @@ static pbio_error_t handle_incoming_app_data(uint16_t offset, uint32_t size, con return PBIO_SUCCESS; } -STATIC mp_obj_t pb_type_app_data_get_bytes(mp_obj_t self_in) { +static mp_obj_t pb_type_app_data_get_bytes(mp_obj_t self_in) { pb_type_app_data_obj_t *self = MP_OBJ_TO_PTR(self_in); // Don't return internal bytes object but make a copy so the user bytes // object is constant as would be expected. Revisit: enable and return // a memoryview, especially if using large buffers. return mp_obj_new_bytes(self->rx_bytes_obj.data, self->rx_bytes_obj.len); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pb_type_app_data_get_bytes_obj, pb_type_app_data_get_bytes); +static MP_DEFINE_CONST_FUN_OBJ_1(pb_type_app_data_get_bytes_obj, pb_type_app_data_get_bytes); -STATIC mp_obj_t pb_type_app_data_get_values(mp_obj_t self_in) { +static mp_obj_t pb_type_app_data_get_values(mp_obj_t self_in) { // Implementation in MicroPython is static, so import from ustruct.unpack. mp_obj_t ustruct_unpack = pb_function_import_helper(MP_QSTR_ustruct, MP_QSTR_unpack); @@ -62,9 +62,9 @@ STATIC mp_obj_t pb_type_app_data_get_values(mp_obj_t self_in) { pb_type_app_data_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_call_function_2(ustruct_unpack, self->rx_format, MP_OBJ_FROM_PTR(&self->rx_bytes_obj)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pb_type_app_data_get_values_obj, pb_type_app_data_get_values); +static MP_DEFINE_CONST_FUN_OBJ_1(pb_type_app_data_get_values_obj, pb_type_app_data_get_values); -STATIC mp_obj_t pb_type_app_data_write_bytes(mp_obj_t self_in, mp_obj_t data_in) { +static mp_obj_t pb_type_app_data_write_bytes(mp_obj_t self_in, mp_obj_t data_in) { pb_type_app_data_obj_t *self = MP_OBJ_TO_PTR(self_in); // Copy data to local buffer. Needs to remain valid while sending. @@ -82,11 +82,11 @@ STATIC mp_obj_t pb_type_app_data_write_bytes(mp_obj_t self_in, mp_obj_t data_in) pbdrv_bluetooth_send_queued(&self->tx_task, &self->tx_context); return pb_module_tools_pbio_task_wait_or_await(&self->tx_task); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(pb_type_app_data_write_bytes_obj, pb_type_app_data_write_bytes); +static MP_DEFINE_CONST_FUN_OBJ_2(pb_type_app_data_write_bytes_obj, pb_type_app_data_write_bytes); static const mp_obj_str_t pb_const_empty_str_obj = {{&mp_type_str}, 0, 0, (const byte *)""}; -STATIC mp_obj_t pb_type_app_data_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t pb_type_app_data_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { PB_PARSE_ARGS_CLASS(n_args, n_kw, args, PB_ARG_DEFAULT_OBJ(rx_format, pb_const_empty_str_obj)); @@ -101,8 +101,7 @@ STATIC mp_obj_t pb_type_app_data_make_new(const mp_obj_type_t *type, size_t n_ar } // Use finalizer so we can deactivate the data callback when rx_buffer is garbage collected. - app_data_instance = m_new_obj_var_with_finaliser(pb_type_app_data_obj_t, uint8_t, size); - app_data_instance->base.type = type; + app_data_instance = mp_obj_malloc_var_with_finaliser(pb_type_app_data_obj_t, uint8_t, size, type); app_data_instance->rx_format = rx_format_in; // Keep rx_buffer in bytes object rx_format for compatibility with unpack. @@ -131,14 +130,14 @@ mp_obj_t pb_type_app_data_close(mp_obj_t stream) { } MP_DEFINE_CONST_FUN_OBJ_1(pb_type_app_data_close_obj, pb_type_app_data_close); -STATIC const mp_rom_map_elem_t pb_type_app_data_locals_dict_table[] = { +static const mp_rom_map_elem_t pb_type_app_data_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&pb_type_app_data_close_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&pb_type_app_data_close_obj) }, { MP_ROM_QSTR(MP_QSTR_get_bytes), MP_ROM_PTR(&pb_type_app_data_get_bytes_obj) }, { MP_ROM_QSTR(MP_QSTR_get_values), MP_ROM_PTR(&pb_type_app_data_get_values_obj) }, { MP_ROM_QSTR(MP_QSTR_write_bytes), MP_ROM_PTR(&pb_type_app_data_write_bytes_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(pb_type_app_data_locals_dict, pb_type_app_data_locals_dict_table); +static MP_DEFINE_CONST_DICT(pb_type_app_data_locals_dict, pb_type_app_data_locals_dict_table); MP_DEFINE_CONST_OBJ_TYPE(pb_type_app_data, MP_QSTR_AppData, diff --git a/pyproject.toml b/pyproject.toml index 1c40343a5..81ade7260 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,10 @@ pygithub = "^1.58.1" [tool.poetry.group.lint.dependencies] micropython-uncrustify = "^1.0.0.post1" -black = "^22.3.0" +ruff = "^0.12.1" + +[tool.ruff] +extend-exclude = ["lib/btstack/", "micropython/"] [build-system] requires = ["poetry>=0.12"] diff --git a/tests/motors/loop_time.py b/tests/motors/loop_time.py index 68752dc29..3c0ce0e54 100644 --- a/tests/motors/loop_time.py +++ b/tests/motors/loop_time.py @@ -20,7 +20,6 @@ watch = StopWatch() while watch.time() < DURATION + 500: - # Compute sine angle. phase = watch.time() / DURATION * 2 * pi speed = sin(phase) * 750 diff --git a/tests/motors/run_test.py b/tests/motors/run_test.py index 611967b20..3be338e91 100755 --- a/tests/motors/run_test.py +++ b/tests/motors/run_test.py @@ -171,20 +171,31 @@ def plot_servo_data(time, data, build_dir, subtitle=None): speed_ax.plot(time, rate, drawstyle="steps-post", label="Reported rate") speed_ax.plot(time, rate_est, drawstyle="steps-post", label="Observer") speed_ax.plot( - time, gradient(count, time / 1000), drawstyle="steps-post", label="Future count derivative" + time, + gradient(count, time / 1000), + drawstyle="steps-post", + label="Future count derivative", ) speed_ax.set_ylabel("speed (deg/s)") torque_ax.plot(time, torque_feedback, label="Feedback", drawstyle="steps-post") - torque_ax.plot(time, torque_feedforward, label="Feedforward", drawstyle="steps-post") + torque_ax.plot( + time, torque_feedforward, label="Feedforward", drawstyle="steps-post" + ) torque_ax.set_ylabel("Torque") duty_ax.plot(time, voltage, label="Motor", drawstyle="steps-post") duty_ax.plot( - time, observer_feedback_voltage, label="Observer Feedback", drawstyle="steps-post" + time, + observer_feedback_voltage, + label="Observer Feedback", + drawstyle="steps-post", ) duty_ax.plot( - time, voltage + observer_feedback_voltage, label="Model voltage", drawstyle="steps-post" + time, + voltage + observer_feedback_voltage, + label="Model voltage", + drawstyle="steps-post", ) duty_ax.set_ylabel("Voltage (mV)") duty_ax.set_ylim([-10000, 10000]) @@ -195,7 +206,9 @@ def plot_servo_data(time, data, build_dir, subtitle=None): loop_time_max = math.ceil((numpy.max(loop_time) + 1) / 5) * 5 time_ax.set_ylim(0, loop_time_max) - plot_status(actuate_ax, actuation_type, {0: "Coast", 1: "N/A", 2: "Voltage"}, "Act.") + plot_status( + actuate_ax, actuation_type, {0: "Coast", 1: "N/A", 2: "Voltage"}, "Act." + ) plot_status(stall_ax, stalled, {0: "No", 1: "Yes"}, "Stall.") for axis in axes: @@ -230,11 +243,23 @@ def plot_control_data(time, data, build_dir, subtitle=None): title = "control" if subtitle is None else "control_" + subtitle figure, axes = matplotlib.pyplot.subplots( - nrows=8, ncols=1, figsize=(15, 15), height_ratios=[1, 1, 1, 1, 0.05, 0.05, 0.05, 0.5] + nrows=8, + ncols=1, + figsize=(15, 15), + height_ratios=[1, 1, 1, 1, 0.05, 0.05, 0.05, 0.5], ) figure.suptitle(title, fontsize=20) - (position_ax, error_ax, speed_ax, torque_ax, actuate_ax, stall_ax, done_ax, time_ax) = axes + ( + position_ax, + error_ax, + speed_ax, + torque_ax, + actuate_ax, + stall_ax, + done_ax, + time_ax, + ) = axes status_axes = (actuate_ax, stall_ax, done_ax) position_ax.plot(time, count, drawstyle="steps-post", label="Reported count") @@ -242,15 +267,24 @@ def plot_control_data(time, data, build_dir, subtitle=None): position_ax.plot(time, count_ref, drawstyle="steps-post", label="Reference") position_ax.set_ylabel("angle (deg)") - error_ax.plot(time, count_ref - count, drawstyle="steps-post", label="Reported error") - error_ax.plot(time, count_ref - count_est, drawstyle="steps-post", label="Estimated error") - error_ax.plot(time, count_est - count, drawstyle="steps-post", label="Estimation error") + error_ax.plot( + time, count_ref - count, drawstyle="steps-post", label="Reported error" + ) + error_ax.plot( + time, count_ref - count_est, drawstyle="steps-post", label="Estimated error" + ) + error_ax.plot( + time, count_est - count, drawstyle="steps-post", label="Estimation error" + ) error_ax.set_ylabel("angle error (deg)") speed_ax.plot(time, rate, drawstyle="steps-post", label="Reported rate") speed_ax.plot(time, rate_est, drawstyle="steps-post", label="Observer") speed_ax.plot( - time, gradient(count, time / 1000), drawstyle="steps-post", label="Future count derivative" + time, + gradient(count, time / 1000), + drawstyle="steps-post", + label="Future count derivative", ) speed_ax.plot(time, rate_ref, drawstyle="steps-post", label="Reference") speed_ax.set_ylabel("speed (deg/s)") @@ -370,7 +404,9 @@ def make_plots(build_dir, show=True): if "PBIO_VIRTUAL_PLATFORM_MODULE" not in os.environ: os.environ["PBIO_VIRTUAL_PLATFORM_MODULE"] = "pbio_virtual.platform.turtle" result = subprocess.run( - [bin_path, script_archive.absolute()], capture_output=True, cwd=build_dir.absolute() + [bin_path, script_archive.absolute()], + capture_output=True, + cwd=build_dir.absolute(), ) hub_output = (result.stdout or result.stderr).split(b"\n") for line in hub_output: diff --git a/tests/pup/benchmark/pystone.py b/tests/pup/benchmark/pystone.py index 2dfe934e7..4959e52fb 100644 --- a/tests/pup/benchmark/pystone.py +++ b/tests/pup/benchmark/pystone.py @@ -48,7 +48,9 @@ def __init__(self, PtrComp=None, Discr=0, EnumComp=0, IntComp=0, StringComp=0): self.StringComp = StringComp def copy(self): - return Record(self.PtrComp, self.Discr, self.EnumComp, self.IntComp, self.StringComp) + return Record( + self.PtrComp, self.Discr, self.EnumComp, self.IntComp, self.StringComp + ) TRUE = 1 diff --git a/tests/pup/benchmark/pystone_lowmem.py b/tests/pup/benchmark/pystone_lowmem.py index 8c6794c38..d1ddbd502 100644 --- a/tests/pup/benchmark/pystone_lowmem.py +++ b/tests/pup/benchmark/pystone_lowmem.py @@ -41,7 +41,9 @@ def __init__(self, PtrComp=None, Discr=0, EnumComp=0, IntComp=0, StringComp=0): self.StringComp = StringComp def copy(self): - return Record(self.PtrComp, self.Discr, self.EnumComp, self.IntComp, self.StringComp) + return Record( + self.PtrComp, self.Discr, self.EnumComp, self.IntComp, self.StringComp + ) TRUE = 1 @@ -218,7 +220,9 @@ def Proc8(Array1Par, Array2Par, IntParI1, IntParI2): Array1Par[(IntLoc + 30) // 2] = IntLoc for IntIndex in range(IntLoc, IntLoc + 2): Array2Par[IntLoc // 2][IntIndex // 2] = IntLoc - Array2Par[IntLoc // 2][(IntLoc - 1) // 2] = Array2Par[IntLoc // 2][(IntLoc - 1) // 2] + 1 + Array2Par[IntLoc // 2][(IntLoc - 1) // 2] = ( + Array2Par[IntLoc // 2][(IntLoc - 1) // 2] + 1 + ) Array2Par[(IntLoc + 20) // 2][IntLoc // 2] = Array1Par[IntLoc // 2] IntGlob = 5 diff --git a/tests/pup/motors/gears.py b/tests/pup/motors/gears.py index 3d2ef0c3e..9c11f7f70 100644 --- a/tests/pup/motors/gears.py +++ b/tests/pup/motors/gears.py @@ -64,6 +64,6 @@ def get_gear_ratio(gear_arg): # Allow at most one degree of error, or up to 1/ratio when speeding up. tolerance = 1 if ratio >= 1 else 1 / ratio - assert abs(motor.angle() - expected) <= tolerance, "{0} != {1} for ratio: {2}".format( - expected, measured, gears + assert abs(motor.angle() - expected) <= tolerance, ( + "{0} != {1} for ratio: {2}".format(expected, measured, gears) ) diff --git a/tests/pup/motors/measurements.py b/tests/pup/motors/measurements.py index 7759523f5..b184d645a 100644 --- a/tests/pup/motors/measurements.py +++ b/tests/pup/motors/measurements.py @@ -60,7 +60,6 @@ # Test DC positive direction signs. for direction in (Direction.CLOCKWISE, Direction.COUNTERCLOCKWISE, "default"): - # Initialize the motor with given sign. motor.close() if direction == "default": @@ -94,7 +93,6 @@ # Test reported speed value. watch = StopWatch() for dc in (-100, 50, 0, 50, 100): - # Get the motor going at steady speed. motor.dc(dc) wait(500) diff --git a/tests/pup/run_all.py b/tests/pup/run_all.py index 33894d601..cb211376c 100644 --- a/tests/pup/run_all.py +++ b/tests/pup/run_all.py @@ -10,12 +10,13 @@ async def main(): - # Get all script paths. scripts = [] - for (dirpath, dirnames, filenames) in os.walk("."): + for dirpath, dirnames, filenames in os.walk("."): if dirpath != ".": - scripts += [os.path.join(dirpath, name) for name in filenames if ".py" == name[-3:]] + scripts += [ + os.path.join(dirpath, name) for name in filenames if ".py" == name[-3:] + ] # Sort tests to re-run previously failed tests first. test_passed = lambda name: (not os.path.exists(name[:-3] + ".out"), name) @@ -28,7 +29,6 @@ async def main(): # Run all scripts. for file_name in scripts: - # Run it. print("Now running:", file_name) await hub.run(file_name) diff --git a/tests/pup/sensors/color_color.py b/tests/pup/sensors/color_color.py index 5b5bca6fb..6c50580db 100644 --- a/tests/pup/sensors/color_color.py +++ b/tests/pup/sensors/color_color.py @@ -31,7 +31,9 @@ for name in ("GREEN", "BLUE", "RED", "YELLOW"): motor.run_target(SPEED, angles[name]) detected = color_sensor.color() - assert detected == Color[name], "Expected {0} but got {1}".format(Color[name], detected) + assert detected == Color[name], "Expected {0} but got {1}".format( + Color[name], detected + ) # Update all colors. for name in angles.keys(): @@ -45,4 +47,6 @@ for name in angles.keys(): motor.run_target(SPEED, angles[name]) detected = color_sensor.color() - assert detected == Color[name], "Expected {0} but got {1}".format(Color[name], detected) + assert detected == Color[name], "Expected {0} but got {1}".format( + Color[name], detected + ) diff --git a/tests/pup/sensors/color_mode.py b/tests/pup/sensors/color_mode.py index ae1e4cb9b..823f776fc 100644 --- a/tests/pup/sensors/color_mode.py +++ b/tests/pup/sensors/color_mode.py @@ -44,4 +44,6 @@ detected = color_sensor.color() # With the built-in delay, the stale blue value should be gone, now giving red. -assert detected == Color["RED"], "Expected {0} but got {1}".format(Color["RED"], detected) +assert detected == Color["RED"], "Expected {0} but got {1}".format( + Color["RED"], detected +) diff --git a/tests/pup/sensors/ultrasonic_distance.py b/tests/pup/sensors/ultrasonic_distance.py index 5f4c91b19..eba3f7ea9 100644 --- a/tests/pup/sensors/ultrasonic_distance.py +++ b/tests/pup/sensors/ultrasonic_distance.py @@ -46,4 +46,6 @@ # Assert that we have made as many turns. rotations = round(motor.angle() / 360) -assert rotations == DETECTIONS, "Expected {0} turns, got {1}.".format(DETECTIONS, rotations) +assert rotations == DETECTIONS, "Expected {0} turns, got {1}.".format( + DETECTIONS, rotations +) diff --git a/tests/pup/sensors/ultrasonic_presence.py b/tests/pup/sensors/ultrasonic_presence.py index 7c73ea91c..68c6ea7d2 100644 --- a/tests/pup/sensors/ultrasonic_presence.py +++ b/tests/pup/sensors/ultrasonic_presence.py @@ -7,6 +7,7 @@ Description: Verifies that the Ultrasonic Sensor does not sense ultrasonic interference by default. """ + from pybricks.pupdevices import UltrasonicSensor from pybricks.parameters import Port diff --git a/tests/virtualhub/motor/drivebase.py b/tests/virtualhub/motor/drivebase.py index 00183af36..64b080941 100644 --- a/tests/virtualhub/motor/drivebase.py +++ b/tests/virtualhub/motor/drivebase.py @@ -26,7 +26,9 @@ def expect_state( or abs(expected_angle - angle) > 10 or abs(expected_angular_velocity - angular_velocity) > 30 ): - raise ValueError("Expected {0} but got {1}".format(expected_state, drive_base.state())) + raise ValueError( + "Expected {0} but got {1}".format(expected_state, drive_base.state()) + ) # Expect zeroed state on startup. @@ -63,6 +65,9 @@ def expect_state( # Drive fast. drive_base.settings( - straight_speed=500, straight_acceleration=1000, turn_rate=500, turn_acceleration=2000 + straight_speed=500, + straight_acceleration=1000, + turn_rate=500, + turn_acceleration=2000, ) drive_base.straight(500) diff --git a/tests/virtualhub/motor/drivebase_turns.py b/tests/virtualhub/motor/drivebase_turns.py index e818e6fcb..7ece9d939 100644 --- a/tests/virtualhub/motor/drivebase_turns.py +++ b/tests/virtualhub/motor/drivebase_turns.py @@ -15,6 +15,7 @@ except ImportError: virtual = False + # Wait on a real robot but not in the simulator. def delay(ms): if virtual: @@ -42,13 +43,17 @@ def wait_until_done(): drive_base.straight(200, wait=False) wait(STARTUP_DELAY) assert motorL.speed() > 0, "When driving Fwd in straight line, left speed should be +ve" -assert motorR.speed() > 0, "When driving Fwd in straight line, right speed should be +ve" +assert motorR.speed() > 0, ( + "When driving Fwd in straight line, right speed should be +ve" +) wait_until_done() drive_base.straight(-200, wait=False) wait(STARTUP_DELAY) assert motorL.speed() < 0, "When driving Rev in straight line, left speed should be -ve" -assert motorR.speed() < 0, "When driving Rev in straight line, right speed should be -ve" +assert motorR.speed() < 0, ( + "When driving Rev in straight line, right speed should be -ve" +) wait_until_done() # Demo 2: Using turn() for in-place turns by angle (+ve = CW, -ve = CCW) @@ -67,19 +72,27 @@ def wait_until_done(): drive_base.turn(-270, wait=False) wait(STARTUP_DELAY) assert motorL.speed() < 0, "For CCW in-place turn 270 degrees, left speed should be -ve" -assert motorR.speed() > 0, "For CCW in-place turn 270 degrees, right speed should be +ve" +assert motorR.speed() > 0, ( + "For CCW in-place turn 270 degrees, right speed should be +ve" +) wait_until_done() drive_base.turn(1080, wait=False) wait(STARTUP_DELAY) assert motorL.speed() > 0, "For CW in-place turn 1080 degrees, left speed should be +ve" -assert motorR.speed() < 0, "For CW in-place turn 1080 degrees, right speed should be -ve" +assert motorR.speed() < 0, ( + "For CW in-place turn 1080 degrees, right speed should be -ve" +) wait_until_done() drive_base.turn(-1440, wait=False) wait(STARTUP_DELAY) -assert motorL.speed() < 0, "For CCW in-place turn 1440 degrees, left speed should be -ve" -assert motorR.speed() > 0, "For CCW in-place turn 1440 degrees, right speed should be +ve" +assert motorL.speed() < 0, ( + "For CCW in-place turn 1440 degrees, left speed should be -ve" +) +assert motorR.speed() > 0, ( + "For CCW in-place turn 1440 degrees, right speed should be +ve" +) wait_until_done() @@ -89,43 +102,47 @@ def wait_until_done(): wait(STARTUP_DELAY) assert motorL.speed() > 0, "When driving Fwd in CW Curve, left speed should be +ve" assert motorR.speed() > 0, "When driving Fwd in CW Curve, right speed should be +ve" -assert ( - motorL.speed() > motorR.speed() -), "When driving Fwd in CW Curve, motorL should be greater than motorR" +assert motorL.speed() > motorR.speed(), ( + "When driving Fwd in CW Curve, motorL should be greater than motorR" +) wait_until_done() drive_base.curve(-140, 360, wait=False) # Drives backward along circle to robot's right wait(STARTUP_DELAY) assert motorL.speed() < 0, "When driving Rev in CCW Curve, left speed should be -ve" assert motorR.speed() < 0, "When driving Rev in CCW Curve, right speed should be -ve" -assert ( - motorL.speed() < motorR.speed() -), "When driving Rev in CCW Curve, motorL should be less (i.e. faster) than motorR" +assert motorL.speed() < motorR.speed(), ( + "When driving Rev in CCW Curve, motorL should be less (i.e. faster) than motorR" +) wait_until_done() drive_base.curve(120, -360, wait=False) # Drives forward along circle to robot's left wait(STARTUP_DELAY) assert motorL.speed() > 0, "When driving Fwd in CCW Curve, left speed should be +ve" assert motorR.speed() > 0, "When driving Fwd in CCW Curve, right speed should be +ve" -assert ( - motorL.speed() < motorR.speed() -), "When driving Fwd in CCW Curve, motorL should be less than motorR" +assert motorL.speed() < motorR.speed(), ( + "When driving Fwd in CCW Curve, motorL should be less than motorR" +) wait_until_done() -drive_base.curve(-120, -360, wait=False) # Drives in reverse along circle to robot's left +drive_base.curve( + -120, -360, wait=False +) # Drives in reverse along circle to robot's left wait(STARTUP_DELAY) assert motorL.speed() < 0, "When driving Rev in CW Curve, left speed should be -ve" assert motorR.speed() < 0, "When driving Rev in CW Curve, right speed should be -ve" -assert ( - motorL.speed() > motorR.speed() -), "When driving Rev in CW Curve, motorL should be greater than motorR" +assert motorL.speed() > motorR.speed(), ( + "When driving Rev in CW Curve, motorL should be greater than motorR" +) wait_until_done() # Demo 4: Using drive() to control the robot in various ways. drive_base.drive(200, 0) # Drive straight Fwd wait(STARTUP_DELAY_LONG) assert motorL.speed() > 0, "When driving Fwd in straight line, left speed should be +ve" -assert motorR.speed() > 0, "When driving Fwd in straight line, right speed should be +ve" +assert motorR.speed() > 0, ( + "When driving Fwd in straight line, right speed should be +ve" +) delay(500) drive_base.stop() delay(250) @@ -133,7 +150,9 @@ def wait_until_done(): drive_base.drive(-200, 0) # Drive straight Rev wait(STARTUP_DELAY_LONG) assert motorL.speed() < 0, "When driving Rev in straight line, left speed should be -ve" -assert motorR.speed() < 0, "When driving Rev in straight line, right speed should be -ve" +assert motorR.speed() < 0, ( + "When driving Rev in straight line, right speed should be -ve" +) delay(500) drive_base.stop() delay(250) @@ -142,9 +161,9 @@ def wait_until_done(): wait(STARTUP_DELAY_LONG) assert motorL.speed() > 0, "When driving CW Curve Fwd, left speed should be +ve" assert motorR.speed() > 0, "When driving CW Curve Fwd, right speed should be +ve" -assert ( - motorL.speed() > motorR.speed() -), "When driving Fwd in CW Curve, motorL should be greater than motorR" +assert motorL.speed() > motorR.speed(), ( + "When driving Fwd in CW Curve, motorL should be greater than motorR" +) delay(3000) # 4 seconds x 90 deg/s approx full circle drive_base.stop() delay(250) @@ -153,9 +172,9 @@ def wait_until_done(): wait(STARTUP_DELAY_LONG) assert motorL.speed() < 0, "When driving CCW Curve Rev, left speed should be -ve" assert motorR.speed() < 0, "When driving CCW Curve Rev, right speed should be -ve" -assert ( - motorR.speed() < motorL.speed() -), "When driving Rev in CCW Curve, motorR should be less than motorL" +assert motorR.speed() < motorL.speed(), ( + "When driving Rev in CCW Curve, motorR should be less than motorL" +) delay(3000) # 4 seconds x 90 deg/s = full circle drive_base.stop() delay(250) @@ -164,9 +183,9 @@ def wait_until_done(): wait(STARTUP_DELAY_LONG) assert motorL.speed() > 0, "When driving CCW Curve Fwd, left speed should be +ve" assert motorR.speed() > 0, "When driving CCW Curve Fwd, right speed should be +ve" -assert ( - motorL.speed() < motorR.speed() -), "When driving Fwd in CCW Curve, motorL should be less than motorR" +assert motorL.speed() < motorR.speed(), ( + "When driving Fwd in CCW Curve, motorL should be less than motorR" +) delay(3000) # 4 seconds x 90 deg/s = full circle drive_base.stop() delay(250) @@ -175,9 +194,9 @@ def wait_until_done(): wait(STARTUP_DELAY_LONG) assert motorL.speed() < 0, "When driving CW Curve Rev, left speed should be +ve" assert motorR.speed() < 0, "When driving CW Curve Rev, right speed should be +ve" -assert ( - motorL.speed() < motorR.speed() -), "When driving Rev in CW Curve, motorL should be less than motorR" +assert motorL.speed() < motorR.speed(), ( + "When driving Rev in CW Curve, motorL should be less than motorR" +) delay(3000) # 4 seconds x 90 deg/s = full circle drive_base.stop() delay(250) diff --git a/tests/virtualhub/motor/test_1.py b/tests/virtualhub/motor/test_1.py index 376e7654b..7fd433c88 100644 --- a/tests/virtualhub/motor/test_1.py +++ b/tests/virtualhub/motor/test_1.py @@ -23,7 +23,6 @@ motor.run_target(speed=SPEED, target_angle=TARGET_ANGLE, wait=False) while not motor.done(): - if watch.time() > TIMEOUT: raise OSError(ETIMEDOUT) diff --git a/tools/codeformat.py b/tools/codeformat.py index f49a82476..fdee412c4 100755 --- a/tools/codeformat.py +++ b/tools/codeformat.py @@ -6,7 +6,9 @@ # import codeformat from upstream micropython tools spec = importlib.util.spec_from_file_location( "codeformat", - os.path.join(os.path.dirname(__file__), "..", "micropython", "tools", "codeformat.py"), + os.path.join( + os.path.dirname(__file__), "..", "micropython", "tools", "codeformat.py" + ), ) codeformat = importlib.util.module_from_spec(spec) spec.loader.exec_module(codeformat) @@ -19,11 +21,6 @@ "lib/lego/**/*.[ch]", "py/*.[ch]", "pybricks/**/*.[ch]", - # Python - "bricks/**/*.py", - "lib/pbio/**/*.py", - "tests/**/*.py", - "tools/**/*.py", ] codeformat.EXCLUSIONS = [ diff --git a/tools/metadata.py b/tools/metadata.py index e024be594..b114a308c 100755 --- a/tools/metadata.py +++ b/tools/metadata.py @@ -83,7 +83,9 @@ def generate( flash_origin = None # Starting address of firmware area in flash memory flash_firmware_size = None # Size of flash memory allocated to firmware - flash_user_0_size = 0 # Size of flash memory within checksum area allocated to user + flash_user_0_size = ( + 0 # Size of flash memory within checksum area allocated to user + ) name_start = None # Starting address of custom hub name name_size = None # Size reserved for custom hub name user_start = None # Starting address of user .mpy file @@ -104,7 +106,9 @@ def generate( flash_user_0_size = int(match[2], base=0) continue - match = re.match(r"^\.name\s+(0x[0-9A-Fa-f]{8,16})\s+(0x[0-9A-Fa-f]+)", line) + match = re.match( + r"^\.name\s+(0x[0-9A-Fa-f]{8,16})\s+(0x[0-9A-Fa-f]+)", line + ) if match: name_start = int(match[1], base=0) name_size = int(match[2], base=0) diff --git a/tools/playground.ipynb b/tools/playground.ipynb index 27a0084e3..d53a777a6 100644 --- a/tools/playground.ipynb +++ b/tools/playground.ipynb @@ -17,6 +17,7 @@ "source": [ "# Pybricksdev and pybricks api stubs are available.\n", "from pybricks.parameters import Color\n", + "\n", "print(Color.YELLOW)" ] }, @@ -39,13 +40,13 @@ "import matplotlib.pyplot\n", "\n", "# Make some data.\n", - "time = numpy.array([t/10 for t in range(0, 10, 1)])\n", + "time = numpy.array([t / 10 for t in range(0, 10, 1)])\n", "speed = time * 0.8\n", "other = time * time\n", "more = 1 - time\n", "\n", "# Get two axes in one figure.\n", - "figure, axes = matplotlib.pyplot.subplots(nrows=1, ncols=2,figsize=(15, 5))\n", + "figure, axes = matplotlib.pyplot.subplots(nrows=1, ncols=2, figsize=(15, 5))\n", "speed_axis, other_axis = axes\n", "\n", "# Plot the data.\n", diff --git a/tools/trigonometry.ipynb b/tools/trigonometry.ipynb index ed528de8e..b01427ef0 100644 --- a/tools/trigonometry.ipynb +++ b/tools/trigonometry.ipynb @@ -27,20 +27,22 @@ "metadata": {}, "outputs": [], "source": [ - "px = numpy.array([0, 0.40, 0.95, 1.60, 2.50, 3.8, 5.00, 7.00, 15, 25])\n", - "py = numpy.array([0, 0.39, 0.76, 1.03, 1.19, 1.32, 1.38, 1.44, 1.51, 1.54])\n", + "px = numpy.array([0, 0.40, 0.95, 1.60, 2.50, 3.8, 5.00, 7.00, 15, 25])\n", + "py = numpy.array([0, 0.39, 0.76, 1.03, 1.19, 1.32, 1.38, 1.44, 1.51, 1.54])\n", "\n", "for x, y in zip(px, py):\n", " print(f\" {{ .x = {int(x * 1024)}, .y = {int(y * 180 / numpy.pi * 8)} }},\")\n", "\n", + "\n", "# Python implementation of pbio_int_math_atan2_positive.\n", "def atan_single_pos(y, x):\n", " ratio = abs(y / x)\n", - " for i in range(len(px)-1):\n", - " if ratio < px[i+1]:\n", - " return py[i] + (ratio - px[i]) * (py[i+1] - py[i]) / (px[i+1] - px[i]) \n", + " for i in range(len(px) - 1):\n", + " if ratio < px[i + 1]:\n", + " return py[i] + (ratio - px[i]) * (py[i + 1] - py[i]) / (px[i + 1] - px[i])\n", " return py[-1]\n", "\n", + "\n", "# Python implementation of pbio_int_math_atan2.\n", "def atan2_single(y, x):\n", " atan = atan_single_pos(abs(y), abs(x))\n", @@ -53,12 +55,14 @@ " else:\n", " return atan + numpy.pi\n", "\n", + "\n", "# Numpy-like variant that can deal with arrays.\n", "def atan2(y, x):\n", " return numpy.array([atan2_single(b, a) for b, a in zip(y, x)])\n", "\n", + "\n", "# Get two axes in one figure.\n", - "figure, axes = matplotlib.pyplot.subplots(nrows=1, ncols=2,figsize=(20, 10))\n", + "figure, axes = matplotlib.pyplot.subplots(nrows=1, ncols=2, figsize=(20, 10))\n", "atan_axis, error_axis = axes\n", "\n", "ratios = numpy.linspace(-40, 40, num=10000)\n", @@ -110,14 +114,16 @@ "roll_simple = numpy.degrees(atan2(accel_y, accel_z))\n", "\n", "# Get two axes in one figure.\n", - "figure, (angle_axis, error_axis) = matplotlib.pyplot.subplots(nrows=1, ncols=2,figsize=(15, 10))\n", + "figure, (angle_axis, error_axis) = matplotlib.pyplot.subplots(\n", + " nrows=1, ncols=2, figsize=(15, 10)\n", + ")\n", "\n", "# Plot angle data\n", "angle_axis.plot(angle_deg, roll, label=\"roll via atan2\")\n", "angle_axis.plot(angle_deg, roll_simple, label=\"roll approximation\")\n", "\n", "# Plot angle data\n", - "error_axis.plot(angle_deg, roll-roll_simple, label=\"Error (deg)\")\n", + "error_axis.plot(angle_deg, roll - roll_simple, label=\"Error (deg)\")\n", "error_axis.set_ylim(-3, 3)\n", "\n", "# Show grid, legend, and fix bounds.\n",