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>
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>
Previously when using --via-mpy, the file was compiled to tests/<tmp>.mpy
and then run using `micropython -m <tmp>` in the current cwd
(usually tests/). This meant that an import in the test would be resolved
relative to tests/.
This is different to regular (non-via-mpy) tests, where we run (for
example) `micropython basics/test.py` which means that an import would be
resolved relative to basics/.
Now --via-mpy matches the .py behavior. This is important because:
a) It makes it so import tests do the right thing.
b) There are directory names in tests/ that match built-in module names.
Furthermore, it always ensures the cwd (for both micropython and cpython)
is the test directory (e.g. basics/) rather than being left unset. This
also makes it clearer inside the test that e.g. file access is relative to
the Python file.
Updated tests with file paths to match.
This work was funded through GitHub Sponsors.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
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>
ESP-NOW is a proprietary wireless communication protocol which supports
connectionless communication between ESP32 and ESP8266 devices, using
vendor specific WiFi frames. This commit adds support for this protocol
through a new `espnow` module.
This commit builds on original work done by @nickzoic, @shawwwn and with
contributions from @zoland. Features include:
- Use of (extended) ring buffers in py/ringbuf.[ch] for robust IO.
- Signal strength (RSSI) monitoring.
- Core support in `_espnow` C module, extended by `espnow.py` module.
- Asyncio support via `aioespnow.py` module (separate to this commit).
- Docs provided at `docs/library/espnow.rst`.
Methods available in espnow.ESPNow class are:
- active(True/False)
- config(): set rx buffer size, read timeout and tx rate
- recv()/irecv()/recvinto() to read incoming messages from peers
- send() to send messages to peer devices
- any() to test if a message is ready to read
- irq() to set callback for received messages
- stats() returns transfer stats:
(tx_pkts, tx_pkt_responses, tx_failures, rx_pkts, lost_rx_pkts)
- add_peer(mac, ...) registers a peer before sending messages
- get_peer(mac) returns peer info: (mac, lmk, channel, ifidx, encrypt)
- mod_peer(mac, ...) changes peer info parameters
- get_peers() returns all peer info tuples
- peers_table supports RSSI signal monitoring for received messages:
{peer1: [rssi, time_ms], peer2: [rssi, time_ms], ...}
ESP8266 is a pared down version of the ESP32 ESPNow support due to code
size restrictions and differences in the low-level API. See docs for
details.
Also included is a test suite in tests/multi_espnow. This tests basic
espnow data transfer, multiple transfers, various message sizes, encrypted
messages (pmk and lmk), and asyncio support.
Initial work is from https://github.com/micropython/micropython/pull/4115.
Initial import of code is from:
https://github.com/nickzoic/micropython/tree/espnow-4115.
Changes in this commit:
- Change MICROPY_HW_BOARD_NAME definition to match the product name.
- Rename board folder's name to match the product name style.
- Change related files like Makefile, document descriptions, test cases, CI
and tools.
Signed-off-by: Takeo Takahashi <takeo.takahashi.xv@renesas.com>
btstack only supports central-initiated, so this allows us to have a test
that works on both (ble_mtu.py), and then another one for just the NimBLE
supported behavior (ble_mtu_peripheral.py).
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
On unix, time.sleep is implemented as select(timeout=<time>) which means
that it does not run the poll hook during sleeping.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Following other vfs_fat tests, so the test works on ports like stm32 that
only support 512-byte block size.
Signed-off-by: Damien George <damien@micropython.org>
If a multitest calls `multitest.output_metric(...)` then that output will
be collected separately, not considered as part of the test verification
output, and instead be printed at the end. This is useful for tests that
want to output performance/timing metrics that may change from one run to
the next.
Signed-off-by: Damien George <damien@micropython.org>
When iterating over os.ilistdir(), the special directories '.' and '..'
are filtered from the results. But the code inadvertently also filtered
any file/directory which happened to match '..*'. This change fixes the
filter.
Fixes issue #11032.
Signed-off-by: Jeremy Rand <jeremy@rand-family.com>
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>
The device-under-test should use `multitest.expect_reboot()` to indicate
that it will reboot.
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
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>
So it can run on targets with low memory, eg esp8266.
Also enable the viper_4args() sub-test, which is now supported.
Signed-off-by: Damien George <damien@micropython.org>
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>
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>
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>
During the initial handshake or subsequent renegotiation, the protocol
might need to read in order to write (or conversely to write in order
to read). It might be blocked from doing so by the state of the
underlying socket (i.e. there is no data to read, or there is no space
to write).
The library indicates this condition by returning one of the errors
`MBEDTLS_ERR_SSL_WANT_READ` or `MBEDTLS_ERR_SSL_WANT_WRITE`. When that
happens, we need to enforce that the next poll operation only considers
the direction that the library indicated.
In addition, mbedtls does its own read buffering that we need to take
into account while polling, and we need to save the last error between
read()/write() and ioctl().
The assertion that is added here (to gc.c) fails when running this new test
if ALLOC_TABLE_GAP_BYTE is set to 0.
Signed-off-by: Jeff Epler <jepler@gmail.com>
Signed-off-by: Damien George <damien@micropython.org>
The code was already checking for duplicate kwargs for named parameters but
if `**kwargs` was given as a parameter, it did not check for multiples of
the same argument name.
This fixes the issue by adding an addition test to catch duplicates and
adds a test to exercise the code.
Fixes issue #10083.
Signed-off-by: David Lechner <david@pybricks.com>
This test could occasionally fail because some operations take longer
than expected. This relaxes the timing constraints and defers printing
until the very end.
Signed-off-by: Laurens Valk <laurens@pybricks.com>
Now that the Timer class has been merged in a separate pull request,
this can be added to the module test too.
Signed-off-by: Laurens Valk <laurens@pybricks.com>
Implements dictionary union according to PEP 584's specifications, minus
the fact that dictionary entries are not guaranteed to be in insertion
order. This feature is enabled with MICROPY_CPYTHON_COMPAT.
Includes a new test.
With the assistance of Fangrui Qin <qinf@purdue.edu>
Signed-off-by: Rayane Chatrieux <rayane.chatrieux@gmail.com>
Signed-off-by: Damien George <damien@micropython.org>
This shows how ports can add their own custom types/classes.
It is part of the unix coverage build, so we can use it for tests too.
Signed-off-by: Laurens Valk <laurens@pybricks.com>
This will make mpy-cross auto-detect. Allow overriding for non-default
configurations (e.g. using 32-bit build of the unix port).
Also use armv7m by default for qemu-arm (the default qemu target is
Cortex-M3).
This work was funded through GitHub Sponsors.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
This prevents a very subtle bug caused by writing e.g. `bytearray('\xfd')`
which gives you `(0xc3, 0xbd)`.
This work was funded through GitHub Sponsors.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Gives the absolute path to the unix micropython binary.
This work was funded through GitHub Sponsors.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Signed-off-by: Damien George <damien@micropython.org>
`b'\xaa \xaa'.count(b'\xaa')` now (correctly) returns 2 instead of 1.
Fixes issue #9404.
This work was funded through GitHub Sponsors.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Allows optimisation of cases like:
import micropython
_DEBUG = micropython.const(False)
if _DEBUG:
print('Debugging info')
Previously the 'if' statement was only optimised out if the type of the
const() argument was integer.
The change is implemented in a way that makes the compiler slightly smaller
(-16 bytes on PYBV11) but compilation will also be very slightly slower.
As a bonus, if const support is enabled then the compiler can now optimise
const truthy/falsey expressions of other types, like:
while "something":
pass
... unclear if that is useful, but perhaps it could be.
Signed-off-by: Angus Gratton <angus@redyak.com.au>
This uses the frozentest.mpy that is also used by ports/minimal.
Also fixes two bugs that these new tests picked up:
- File extension matching in manifestfile.py.
- Handling of freeze_mpy results in makemanifest.
This work was funded through GitHub Sponsors.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
frozentest.mpy was previously duplicated in ports/minimal and
ports/powerpc.
This needs to be re-generated on every .mpy version increase, so might as
well just have a single copy of it.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Prevent handle leaks when file objects aren't closed explicitly and
fix some MICROPY_CPYTHON_COMPAT issues: this wasn't properly adhered
to because #ifdef was used so it was always on, and closing files
multiple times should be avoided unconditionally.
This matches class `__dict__`, and is similarly gated on
MICROPY_CPYTHON_COMPAT. Unlike class though, because modules's globals are
actually dict instances, the result is a mutable dictionary.
This work was funded through GitHub Sponsors.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
The intent is to allow us to make breaking changes to the native ABI (e.g.
changes to dynruntime.h) without needing the bytecode version to increment.
With this commit the two bits previously used for the feature flags (but
now unused as of .mpy version 6) encode a sub-version. A bytecode-only
.mpy file can be loaded as long as MPY_VERSION matches, but a native .mpy
(i.e. one with an arch set) must also match MPY_SUB_VERSION. This allows 3
additional updates to the native ABI per bytecode revision.
The sub-version is set to 1 because the previous commits that changed the
layout of mp_obj_type_t have changed the native ABI.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Signed-off-by: Damien George <damien@micropython.org>
The goal here is to remove a slot (making way to turn make_new into a slot)
as well as reduce code size by the ~40 references to mp_identity_getiter
and mp_stream_unbuffered_iter.
This introduces two new type flags:
- MP_TYPE_FLAG_ITER_IS_ITERNEXT: This means that the "iter" slot in the
type is "iternext", and should use the identity getiter.
- MP_TYPE_FLAG_ITER_IS_CUSTOM: This means that the "iter" slot is a pointer
to a mp_getiter_iternext_custom_t instance, which then defines both
getiter and iternext.
And a third flag that is the OR of both, MP_TYPE_FLAG_ITER_IS_STREAM: This
means that the type should use the identity getiter, and
mp_stream_unbuffered_iter as iternext.
Finally, MP_TYPE_FLAG_ITER_IS_GETITER is defined as a no-op flag to give
the default case where "iter" is "getiter".
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
This is a latent issue that wasn't caught by CI because there was no
configuration that had both stackless+uasyncio.
The previous check to skip with stackless builds only worked when the
bytecode emitter was used by default. Force the check to use the bytecode
emitter.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
When iterating over filesystem/folders with os.iterdir(), an open file
(directory) handle is used internally. Currently this file handle is only
closed once the iterator is completely drained, eg. once all entries have
been looped over / converted into list etc.
If a program opens an iterdir but does not loop over it, or starts to loop
over the iterator but breaks out of the loop, then the handle never gets
closed. In this state, when the iter object is cleaned up by the garbage
collector this open handle can cause corruption of the filesystem.
Fixes issues #6568 and #8506.
Rather than drawing the entire boundary to catch missing pixels, just
detect the cases where boundary pixels are skipped during node calculation
and pre-emptively draw them then.
This adds 72 bytes on PYBV11, but makes filled poly() 20% faster.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Add method for drawing polygons.
For non-filled polygons, uses the existing line-drawing code to render
arbitrary polygons using the given coords list, at the given x,y position,
in the given colour.
For filled polygons, arbitrary closed polygons are rendered using a fast
point-in-polygon algorithm to determine where the edges of the polygon lie
on each pixel row.
Tests and documentation updates are also included.
Signed-off-by: Mat Booth <mat.booth@gmail.com>
Rework the conversion of floats to decimal strings so it aligns precisely
with the conversion of strings to floats in parsenum.c. This is to avoid
rendering 1eX as 9.99999eX-1 etc. This is achieved by removing the power-
of-10 tables and using pow() to compute the exponent directly, and that's
done efficiently by first estimating the power-of-10 exponent from the
power-of-2 exponent in the floating-point representation.
Code size is reduced by roughly 100 to 200 bytes by this commit.
Signed-off-by: Dan Ellis <dan.ellis@gmail.com>
This is useful in situations where the ThreadSafeFlag is reused and needs
to be cleared of any previous, unwanted event.
For example, clear the flag at the start of an operation, trigger the
operation (eg an I2C write), then (a)wait for an external event to set the
flag (eg a pin IRQ). Further events may trigger the flag again but these
are unwanted and should be cleared before the next cycle starts.
This commit adds the bytes methods to bytearray, matching CPython. The
existing implementations of these methods for str/bytes are reused for
bytearray with minor updates to match CPython return types.
For details on the CPython behaviour see
https://docs.python.org/3/library/stdtypes.html#bytes-and-bytearray-operations
The work to merge locals tables for str/bytes/bytearray/array was done by
@jimmo. Because of this merging of locals the change in code size for this
commit is mostly negative:
bare-arm: +0 +0.000%
minimal x86: +29 +0.018%
unix x64: -792 -0.128% standard[incl -448(data)]
unix nanbox: -436 -0.078% nanbox[incl -448(data)]
stm32: -40 -0.010% PYBV10
cc3200: -32 -0.017%
esp8266: -28 -0.004% GENERIC
esp32: -72 -0.005% GENERIC[incl -200(data)]
mimxrt: -40 -0.011% TEENSY40
renesas-ra: -40 -0.006% RA6M2_EK
nrf: -16 -0.009% pca10040
rp2: -64 -0.013% PICO
samd: +148 +0.105% ADAFRUIT_ITSYBITSY_M4_EXPRESS
The executable now lives in the build directory, and since the build
directory already contains the variant name there is no need to also add
it to the executable.
Signed-off-by: Damien George <damien@micropython.org>
Binaries built using the Make build system now no longer appear in the
working directory of the build, but rather in the build directory. Thus
some paths had to be adjusted.
The reallocation trigger for unpacking star args with unknown length
did not take into account the number of fixed args remaining. So it was
possible that the unpacked iterators could take up exactly the memory
allocated then nothing would be left for fixed args after the star args.
This causes a segfault crash.
This is fixed by taking into account the remaining number of fixed args
in the check to decide whether to realloc yet or not.
Signed-off-by: David Lechner <david@pybricks.com>
Formerly, py/formatfloat would print whole numbers inaccurately with
nonzero digits beyond the decimal place. This resulted from its strategy
of successive scaling of the argument by 0.1 which cannot be exactly
represented in floating point. The change in this commit avoids scaling
until the value is smaller than 1, so all whole numbers print with zero
fractional part.
Fixes issue #4212.
Signed-off-by: Dan Ellis dan.ellis@gmail.com
On ports with more than one filesystem, the type will be wrong, for example
if using LFS but FAT enabled, then the type will be FAT. So it's not
possible to use these classes to identify a file object type.
Furthermore, constructing an io.FileIO currently crashes on FAT, and
make_new isn't supported on LFS.
And the io.TextIOWrapper class does not match CPython at all.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
This commit simplifies mp_obj_get_complex_maybe() by first calling
mp_obj_get_float_maybe() to handle the cases corresponding to floats.
Only if that fails does it attempt to extra a full complex number.
This reduces code size and also means that mp_obj_get_complex_maybe() now
supports user-defined classes defining __float__; in particular this allows
user-defined classes to be used as arguments to cmath-module function.
Furthermore, complex_make_new() can now be simplified to directly call
mp_obj_get_complex(), instead of mp_obj_get_complex_maybe() followed by
mp_obj_get_float(). This also improves error messages from complex with
an invalid argument, it now raises "can't convert <type> to complex" rather
than "can't convert <type> to float".
Signed-off-by: Damien George <damien@micropython.org>
Add cert_reqs and cadata keyword-args to ssl.wrap_socket() and
ssl.CERT_NONE, ssl.CERT_OPTIONAL, ssl.CERT_REQUIRED constants to allow
certificate validation.
CPython doesn't accept cadata in ssl.wrap_socket(), but it does in
SSLContext.load_verify_locations(), so we use this name to at least match
the same name in load_verify_locations().
Add docs for these new arguments, as well as docs for the existing
server_hostname argument which is important for certificate validation.
Tests are added as well.
Signed-off-by: Carlos Gil <carlosgilglez@gmail.com>
The empty tuple is usually a constant object, but named tuples must be
allocated to allow modification. Added explicit allocation to fix this.
Also added a regression test to verify creating an empty named tuple works.
Fixes issue #7870.
Signed-off-by: Lars Haulin <lars.haulin@gmail.com>
For STM32L072 and similar, very low end targets.
The other perf_bench tests run out of memory, crash, or fail on
prerequisite features.
Signed-off-by: Angus Gratton <gus@projectgus.com>