summaryrefslogtreecommitdiff
path: root/py
AgeCommit message (Collapse)Author
2023-06-05py/builtinimport: Remove partially-loaded modules from sys.modules.David Grayson
Prior to this commit, importing a module that exists but has a syntax error or some other problem that happens at import time would result in a potentially-incomplete module object getting added to sys.modules. Subsequent imports would use that object, resulting in confusing error messages that hide the root cause of the problem. This commit fixes that issue by removing the failed module from sys.modules using the new NLR callback mechanism. Note that it is still important to add the module to sys.modules while the import is happening so that we can support circular imports just like CPython does. Fixes issue #967. Signed-off-by: David Grayson <davidegrayson@gmail.com>
2023-06-02py: Use nlr jump callbacks to optimise compile/execute functions.Damien George
The changed functions now use less stack, and don't have any issues with local variables needing to be declared volatile. Testing on a PYBv1.0, imports (of .py, .mpy and frozen code) now use 64 less bytes of C stack per import depth. Signed-off-by: Damien George <damien@micropython.org>
2023-06-02py/nlr: Implement jump callbacks.Damien George
NLR buffers are usually quite large (use lots of C stack) and expensive to push and pop. Some of the time they are only needed to perform clean up if an exception happens, and then they re-raise the exception. This commit allows optimizing that scenario by introducing a linked-list of NLR callbacks that are called automatically when an exception is raised. They are essentially a light-weight NLR handler that can implement a "finally" block, i.e. clean-up when an exception is raised, or (by passing `true` to nlr_pop_jump_callback) when execution leaves the scope. Signed-off-by: Damien George <damien@micropython.org>
2023-06-02py/nlr: Remove commented-out debugging code.Damien George
Also remove the unnecessary include of mpstate.h. Signed-off-by: Damien George <damien@micropython.org>
2023-06-02py/nlrsetjmp: Use MP_NLR_JUMP_HEAD macro to simplify code.Damien George
Signed-off-by: Damien George <damien@micropython.org>
2023-06-01py/objmodule: Don't use sys.modules to track a builtin __init__.Jim Mussared
This can lead to duplicate initialisations if a module can be imported via multiple names, so the module must track this itself anyway. This reduces code size (diff is -40 bytes), and avoids special treatment of builtin-modules-with-init with respect to sys.modules. No other builtin modules get put into sys.modules. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-06-01py/builtinimport: Allow builtin modules to be packages.Jim Mussared
To use this: - Create a built-in module, and add the module object as a member of the parent module's globals dict. - The submodule can set its `__name__` to either `QSTR_foo_dot_bar` or `QSTR_bar`. The former requires using qstrdefs(port).h to make the qstr. Because `bar` is a member of `foo`'s globals, it is possible to write `import foo` and then immediately use `foo.bar` without importing it explicitly. This means that if `bar` has an `__init__`, it will not be called in this situation, and for that reason, sub-modules should not have `__init__` methods. If this is required, then all initalisation for sub-modules should be done by the top-level module's (i.e. `foo`'s) `__init__` method. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-06-01py/builtinimport: Optimise sub-package loading.Jim Mussared
This makes it so that sub-packages are resolved relative to their parent's `__path__`, rather than re-resolving each parent's filesystem path. The previous behavior was that `import foo.bar` would first re-search `sys.path` for `foo`, then use the resulting path to find `bar`. For already-loaded and u-prefixed modules, because we no longer need to build the path from level to level, we no longer unnecessarily search the filesystem. This should improve startup time. Explicitly makes the resolving process clear: - Loaded modules are returned immediately without touching the filesystem. - Exact-match of builtins are also returned immediately. - Then the filesystem search happens. - If that fails, then the weak-link handling is applied. This maintains the existing behavior: if a user writes `import time` they will get time.py if it exits, otherwise the built-in utime. Whereas `import utime` will always return the built-in. This also fixes a regression from a7fa18c203a241f670f12ab507aa8b349fcd45a1 where we search the filesystem for built-ins. It is now only possible to override u-prefixed builtins. This will remove a lot of filesystem stats at startup, as micropython-specific modules (e.g. `pyb`) will no longer attempt to look at the filesystem. Added several improvements to the comments and some minor renaming and refactoring to make it clearer how the import mechanism works. Overall code size diff is +56 bytes on STM32. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-06-01py/builtinimport: Handle empty sys.path correctly.Jim Mussared
If sys.path is enabled, but empty, this will now no longer search the filesystem. Previously an empty sys.path was equivalent to having `sys.path=[""]`. This is a breaking change, but this behavior now matches CPython. This also provides an alternative mechanism to the u-prefix to force an import of a builtin module: ``` import sys _path = sys.path[:] sys.path.clear() import foo # Forces the built-in foo. sys.path.extend(_path) del _path ``` Code size diff is -32 bytes on PYBV11. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-06-01py/objint: Allow int() to parse anything with the buffer protocol.Damien George
This generalises and simplifies the code and follows CPython behaviour. See similar change for floats in a07fc5b6403b9a8bf7e7cb64f857272e5346d7e2. Signed-off-by: Damien George <damien@micropython.org>
2023-06-01py/obj: Accept user types in mp_obj_get_int_maybe.Damien George
This is possible now that MP_UNARY_OP_INT_MAYBE exists. As a consequence mp_obj_get_int now also supports user types, which was previously possible with MP_UNARY_OP_INT but no tests existed for it. Signed-off-by: Damien George <damien@micropython.org>
2023-06-01py: Change MP_UNARY_OP_INT to MP_UNARY_OP_INT_MAYBE.Damien George
To be consistent with MP_UNARY_OP_INT_FLOAT and MP_UNARY_OP_INT_COMPLEX, and allow int() to first check if a type supports __int__ before trying other things (as per CPython). Signed-off-by: Damien George <damien@micropython.org>
2023-05-19py/runtime: If inplace binop fails then try corresponding normal binop.Damien George
The code that handles inplace-operator to normal-binary-operator fallback is moved in this commit from py/objtype.c to py/runtime.c, making it apply to all types, not just user classes. Signed-off-by: Damien George <damien@micropython.org>
2023-05-19py/objstr: Return unsupported binop instead of raising TypeError.Damien George
So that user types can implement reverse operators and have them work with str on the left-hand-side, eg `"a" + UserType()`. Signed-off-by: Damien George <damien@micropython.org>
2023-05-19py/objarray: Disallow memoryview addition.Damien George
Following CPython. This is important for subsequent commits to work correctly. Signed-off-by: Damien George <damien@micropython.org>
2023-05-19py/objdict: Fix __hash__ for dict_view types.David Lechner
This adds a unary_op implementation for the dict_view type that makes the implementation of `hash()` for these types compatible with CPython. Signed-off-by: David Lechner <david@pybricks.com>
2023-05-19py/objslice: Ensure slice is not hashable.David Lechner
As per https://bugs.python.org/issue408326, the slice object should not be hashable. Since MicroPython has an implicit fallback when the unary_op slot is empty, we need to fill this slot. Signed-off-by: David Lechner <david@pybricks.com>
2023-05-19py/obj: Remove mp_generic_unary_op().David Lechner
Since converting to variable sized slots in mp_obj_type_t, we can now reduce the code size a bit by removing mp_generic_unary_op() and the corresponding slots where it is used. Instead we just implement the generic `__hash__` operation in the runtime. Signed-off-by: David Lechner <david@pybricks.com>
2023-05-09py/gc: Make improvements to MICROPY_GC_HOOK_LOOP.David Lechner
Changes in this commit: - Add MICROPY_GC_HOOK_LOOP to gc_info() and gc_alloc(). Both of these can be long running (many milliseconds) which is too long to be blocking in some applications. - Pass loop variable to MICROPY_GC_HOOK_LOOP(i) macro so that implementers can use it, e.g. to improve performance by only calling a function every X number of iterations. - Drop outer call to MICROPY_GC_HOOK_LOOP in gc_mark_subtree().
2023-05-04py/stackctrl: Add gcc pragmas to ignore dangling-pointer warning.Damien George
This warning became apparent in gcc 13. Signed-off-by: Damien George <damien@micropython.org>
2023-05-03py/compile: Remove over-eager optimisation of tuples as if condition.Damien George
When a tuple is the condition of an if statement, it's only possible to optimise that tuple away when it is a constant tuple (ie all its elements are constants), because if it's not constant then the elements must be evaluated in case they have side effects (even though the resulting tuple will always be "true"). The code before this change handled the empty tuple OK (because it doesn't need to be evaluated), but it discarded non-empty tuples without evaluating them, which is incorrect behaviour (as show by the updated test). This optimisation is anyway rarely applied because it's not common Python coding practice to write things like `if (): ...` and `if (1, 2): ...`, so removing this optimisation completely won't affect much code, if any. Furthermore, when MICROPY_COMP_CONST_TUPLE is enabled, constant tuples are already optimised by the parser, so expression with constant tuples like `if (): ...` and `if (1, 2): ...` will continue to be optimised properly (and so when this option is enabled the code that's deleted in this commit is actually unreachable when the if condition is a constant tuple). Signed-off-by: Damien George <damien@micropython.org>
2023-05-03py/parse: Fix build when COMP_CONST_FOLDING=0 and COMP_MODULE_CONST=1.Damien George
Signed-off-by: Damien George <damien@micropython.org>
2023-05-01py/ringbuf: Implement put_bytes/get_bytes functions.glenn20
2023-04-27all: Fix spelling mistakes based on codespell check.Damien George
Signed-off-by: Damien George <damien@micropython.org>
2023-04-27extmod/modutime: Provide a generic time module.Damien George
Based on extmod/utime_mphal.c, with: - a globals dict added - time.localtime wrapper added - time.time wrapper added - time.time_ns function added New configuration options are added for this module: - MICROPY_PY_UTIME (enabled at basic features level) - MICROPY_PY_UTIME_GMTIME_LOCALTIME_MKTIME - MICROPY_PY_UTIME_TIME_TIME_NS Signed-off-by: Damien George <damien@micropython.org>
2023-04-26all: Bump version to 1.20.0.v1.20.0Damien George
Signed-off-by: Damien George <damien@micropython.org>
2023-04-26extmod/btstack: Fix indicate/notify queuing.Jim Mussared
This adds a mechanism to track a pending notify/indicate operation that is deferred due to the send buffer being full. This uses a tracked alloc that is passed as the content arg to the callback. This replaces the previous mechanism that did this via the global pending op queue, shared with client read/write ops. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-04-11py/makeqstrdefs.py: Fix handling GreenHills C/C++ preprocessor output.Alex Riesen
The GreenHills preprocessor produces #line directives without a file name, which the regular expression used to distiguish between "# <number> file..." (GCC and similar) and "#line <number> file..." (Microsoft C and similar) does not match, aborting processing. Besides, the regular expression was unnecessarily wide, matching lines containing a "#", followed by any number of 'l','i','n', and 'e' characters. Signed-off-by: Alex Riesen <alexander.riesen@cetitec.com>
2023-03-28py/obj: Fix spelling of staticmethod.David Lechner
Signed-off-by: David Lechner <david@pybricks.com>
2023-03-21py/scheduler: Implement VM abort flag and mp_sched_vm_abort().Damien George
This is intended to be used by the very outer caller of the VM/runtime. It allows setting a top-level NLR handler that can be jumped to directly, in order to forcefully abort the VM/runtime. Enable using: #define MICROPY_ENABLE_VM_ABORT (1) Set up the handler at the top level using: nlr_buf_t nlr; nlr.ret_val = NULL; if (nlr_push(&nlr) == 0) { nlr_set_abort(&nlr); // call into the VM/runtime ... nlr_pop(); } else { if (nlr.ret_val == NULL) { // handle abort ... } else { // handle other exception that propagated to the top level ... } } nlr_set_abort(NULL); Schedule an abort, eg from an interrupt handler, using: mp_sched_vm_abort(); Signed-off-by: Damien George <damien@micropython.org>
2023-03-21py/mpstate: Add mp_thread_is_main_thread() helper macro.Damien George
Signed-off-by: Damien George <damien@micropython.org>
2023-03-17py/obj: Add MP_NOINLINE to mp_obj_malloc_helper.David Lechner
As the comment in py/obj.h says: > Implementing this as a call rather than inline saves 8 bytes per usage. So in order to get this savings, we need to tell the compiler to never inline the function. Signed-off-by: David Lechner <david@pybricks.com>
2023-03-10py/makeversionhdr.py: Always add micro to version string even if it's 0.Damien George
Moving forward, tags in this repository will always have three components. Signed-off-by: Damien George <damien@micropython.org>
2023-03-10py/builtinimport: Fix unix port build with external imports disabled.Laurens Valk
Without this, building the unix port variants gives: ports/unix/main.c:667: undefined reference to `mp_obj_is_package', when MICROPY_ENABLE_EXTERNAL_IMPORT is 0. Signed-off-by: Laurens Valk <laurens@pybricks.com>
2023-03-10py/mpconfig: Provide config option for internal printf printer.Damien George
The C-level printf is usually used for internal debugging prints, and a port/board may want to redirect this somewhere other than stdout. Signed-off-by: Damien George <damien@micropython.org>
2023-03-10py/gc: Make gc_dump_info/gc_dump_alloc_table take a printer as argument.Damien George
So that callers can redirect the output if needed. Signed-off-by: Damien George <damien@micropython.org>
2023-03-09py/compile: Fix scope of assignment expression target in comprehensions.Damien George
When := is used in a comprehension the target variable is bound to the parent scope, so it's either a global or a nonlocal. Prior to this commit that was handled by simply using the parent scope's id_info for the target variable. That's completely wrong because it uses the slot number for the parent's Python stack to store the variable, rather than the slot number for the comprehension. This will in most cases lead to incorrect behaviour or memory faults. This commit fixes the scoping of the target variable by explicitly declaring it a global or nonlocal, depending on whether the parent is the global scope or not. Then the id_info of the comprehension can be used to access the target variable. This fixes a lot of cases of using := in a comprehension. Code size change for this commit: bare-arm: +0 +0.000% minimal x86: +0 +0.000% unix x64: +152 +0.019% standard stm32: +96 +0.024% PYBV10 cc3200: +96 +0.052% esp8266: +196 +0.028% GENERIC esp32: +156 +0.010% GENERIC[incl +8(data)] mimxrt: +96 +0.027% TEENSY40 renesas-ra: +88 +0.014% RA6M2_EK nrf: +88 +0.048% pca10040 rp2: +104 +0.020% PICO samd: +88 +0.033% ADAFRUIT_ITSYBITSY_M4_EXPRESS Fixes issue #10895. Signed-off-by: Damien George <damien@micropython.org>
2023-03-02py/makeversionhdr.py: Optionally get git tag and git hash from env vars.David Grayson
This is handy when you are doing builds outside of the Git repository but still want to record that information. Signed-off-by: David Grayson <davidegrayson@gmail.com>
2023-02-27py/emitnative: Explicitly compare comparison ops in binary_op emitter.Pepijn de Vos
Without this it's possible to get a compiler error about the comparison always being true, because MP_BINARY_OP_LESS is 0. And it seems that gcc optimises these 6 equality comparisons into the same size machine code as before.
2023-02-24py/modmath: Fix two-argument math function domain check.Damien George
Prior to this fix, pow(1.5, inf) and pow(0.5, -inf) (among other things) would incorrectly raise a ValueError, because the result is inf with the first argument being finite. This commit fixes this by allowing the result to be infinite if the first or second (or both) argument is infinite. This fix doesn't affect the other three math functions that have two arguments: - atan2 never returns inf, so always fails isinf(ans) - copysign returns inf only if the first argument x is inf, so will never reach the isinf(y) check - fmod never returns inf, so always fails isinf(ans) Signed-off-by: Damien George <damien@micropython.org>
2023-02-08py/mkrules.cmake: Force build mpversion.h and frozen_content.c.Jim Mussared
This ensures that all builds unconditionally run makeversionhdr.py and makemanifest.py to generate mpversion.h and frozen_content.c respectively. This now matches the Makefile behavior, and in particular this fixes the issue on ESP32 builds that changes in code-to-be-frozen will cause the build to update. Both these already tools know not to touch their output if there is no change. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-02-02top: Update Python formatting to black "2023 stable style".Jim Mussared
See https://black.readthedocs.io/en/stable/the_black_code_style/index.html Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-01-24py/mkrules: Support mpy-tool-flags in cmake frozen code generation.Damien George
Signed-off-by: Damien George <damien@micropython.org>
2023-01-23py/objint_mpz: Catch and reject @ and @= operating on big integers.Damien George
This will also catch / and /= when float support is disabled. Fixes issue #10544. Signed-off-by: Damien George <damien@micropython.org>
2023-01-20py: Add parenthesis to default impl of MP_OBJ_TO_PTR, MP_OBJ_FROM_PTR.Alex Riesen
Unless MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D, these macros only work with values and "->"/"." expressions as their sole argument. In other words, the macros are broken with expressions which contain operations of lower precedence than the cast operator. Depending on situation, the old code either results in compiler error: MP_OBJ_TO_PTR(flag ? o1 : o2) expands into "(void *)flag ? o1 : o2", which some compiler configurations will reject (e.g. GCC -Wint-conversion -Wint-to-pointer-cast -Werror) Or in an incorrect address calculation: For ptr declared as "uint8_t *" the MP_OBJ_FROM_PTR(ptr + off) expands into ((mp_obj_t)ptr) + off, resulting in an obviously wrong address. Signed-off-by: Alex Riesen <alexander.riesen@cetitec.com>
2023-01-20py/lexer: Wrap in parenthesis all f-string arguments passed to format.Jim Mussared
This is important for literal tuples, e.g. f"{a,b,}, {c}" --> "{}".format((a,b), (c),) which would otherwise result in either a syntax error or the wrong result. Fixes issue #9635. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-01-20py/objarray: Raise error on out-of-bound memoryview slice start.Andrew Leech
32-bit platforms only support a slice offset start of 24 bit max due to the limited size of the mp_obj_array_t.free member. Similarly on 64-bit platforms the limit is 56 bits. This commit adds an OverflowError if the user attempts to slice a memoryview beyond this limit. Signed-off-by: Damien George <damien@micropython.org>
2023-01-16py/gc: Increase the address length in gc_dump_alloc_table().robert-hh
Showing 8 digits instead of 5, supporting devices with more than 1 MByte of RAM (which is common these days). The masking was never needed, and the related commented-out line can go.
2023-01-13py/map: Clear value when re-using slot with ordered dictionaries.Philip Peitsch
To adhere to the contract of mp_map_lookup, namely: MP_MAP_LOOKUP_ADD_IF_NOT_FOUND behaviour: - returns slot, with key non-null and value=MP_OBJ_NULL if it was added
2022-12-16py/emitnative: Initialise locals as Python object type for native code.Damien George
In @micropython.native code the types of variables and expressions are always Python objects, so they can be initialised as such. This prevents problems with compiling optimised code like while-loops where a local may be referenced before it is assigned to. Signed-off-by: Damien George <damien@micropython.org>