This commit adds support for t-strings by leveraging the existing f-string
parser in the lexer. It includes:
- t-string parsing in `py/lexer.c`
- new built-in `__template__()` function to construct t-string objects
- new built-in `Template` and `Interpolation` classes which implement all
the functionality from PEP 750
- new built-in `string` module with `templatelib` sub-module, which
contains the classes `Template` and `Interpolation`
The way the t-string parser works is that an input t-string like:
t"hello {name:5}"
is converted character-by-character by the lexer/tokenizer to:
__template__(("hello ", "",), name, "name", None, "5")
For reference, if it were an f-string it would be converted to:
"hello {:5}".format(name)
Some properties of this implementation:
- it's enabled by default at the full feature level,
MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_FULL_FEATURES
- when enabled on a Cortex-M bare-metal port it costs about +3000 bytes
- there are no limits on the size or complexity of t-strings, and it allows
arbitrary levels of nesting of f-strings and t-strings (up to the memory
available to the compiler)
- the 'a' (ascii) conversion specifier is not supported (MicroPython does
not have the built-in `ascii` function)
- space after conversion specifier, eg t"{x!r :10}", is not supported
- arguments to `__template__` and `Interpolation` are not fully validated
(it's not necessary, it won't crash if the wrong arguments are passed in)
Otherwise the implementation here matches CPython.
Signed-off-by: Damien George <damien@micropython.org>
This is a linker option, so provided it's added to LDFLAGS then it can be
dropped from CFLAGS without changing the compiler behaviour.
This work was funded through GitHub Sponsors.
Signed-off-by: Angus Gratton <angus@redyak.com.au>
Because it requires a different configuration of the pins (in `setUp`).
Eg on mimxrt pins used for a `machine.Counter` cannot be read.
Signed-off-by: Damien George <damien@micropython.org>
Because it requires a different configuration of the pins (in `setUp`).
Eg on mimxrt pins used for an Encoder cannot be read.
Signed-off-by: Damien George <damien@micropython.org>
This adds MIMXRT-specific arguments and methods, as a superset of the
original Encoder/Counter documentation.
The mimxrt pinout and quickref docs are updated with relevant information.
Signed-off-by: robert-hh <robert@hammelrath.com>
These classes are based on the Quadrature Encoder blocks of the i.MXRT
MCUs. The i.MXRT 102x has two encoders, the other ones four. The i.MXRT
101x does not support this function. It is implemented as two classes,
Encoder and Counter.
The number of pins that can be uses as inputs is limited by the MCU
architecture and the board schematics. The Encoder class supports:
- Defining the module.
- Defining the input pins.
- Defining a pin for an index signal.
- Defining a pin for a reset signal.
- Defining an output pin showing the compare match signal.
- Setting the number of cycles per revolution (min/max).
- Setting the initial value for the position.
- Setting the counting direction.
- Setting a glitch filter.
- Defining callbacks for getting to a specific position, overrun and
underrun (starting the next revolution). These callbacks can be hard
interrupts to ensure short latency.
The encoder counts all phases of a cycle. The span for the position is
2**32, for the revolution is 2**16. The highest input frequency is
CPU-Clock/24. Note that the "phases" argument is emulated at the API
level (the hardware will always count all phases).
The Counter mode counts single pulses on input A of the Encoder. The
configuration supports:
- Defining the module.
- Defining the input pin.
- Defining the counting direction, either fixed or controlled by the level
of an input pin.
- Defining a pin for an index signal.
- Defining an output pin showing the compare match signal.
- Setting the counter value.
- Setting the glitch filter.
- Defining a callback which is called at a certain value.
- Settings for MIMXRT1015. The MIMXRT1015 MCU has only one encoder/counter
unit.
The counting range is 0 - 2**32-1 and a 16 bit overrun counter. The
highest input frequency is CPU-Clock/12.
The implementation of the `.irq()` method uses the common code from
`shared/runtime/mpirq.c`, including the `irq().flags()` and
`irq().trigger()` methods.
Signed-off-by: robert-hh <robert@hammelrath.com>
The rp2.asm_pio() decorator saves and temporarily replaces the globals
dictionary to allow the wrapped functions to reference PIO instructions
and register names in a natural way, restoring them before returning the
assembled program.
However, if an exception occurs while assembling the program, the globals
are not changed back, leaving them corrupted.
Wrap with try/finally to ensure they are always restored correctly.
Signed-off-by: Chris Webb <chris@arachsys.com>
As per CPython behaviour, `b"".hex()` should return an empty str object
(not an empty bytes object).
Fixes issue #18807.
Signed-off-by: Damien George <damien@micropython.org>
As of CPython 3.7 `bytes.fromhex()` skips all ASCII whitespace. And as of
CPython 3.8 `bytes.hex()` supports the optional separator argument. So
this test no longer needs a .exp file.
Signed-off-by: Damien George <damien@micropython.org>
Fixes rp2 issue where socket.getaddrinfo() could block indefinitely if an
interface goes down and still has a DNS server configured, as the LWIP
timer stops running and can't time out the DNS query.
Adds a regression test under multi_wlan that times out on rp2 without this
fix.
Fixes issue #18797.
This work was funded through GitHub Sponsors.
Signed-off-by: Angus Gratton <angus@redyak.com.au>
This commit adds `machine.PWM` support to the alif port. It uses the
existing common machine bindings and implements the standard set of
functionality: `freq()`, `duty_u16()`, `duty_ns()` and `invert`.
It uses the UTIMER peripheral and makes PWM available on all pins that have
an alt function connection to a UTIMER, which is 54 pins. It does not use
UTIMER11 which is already in use by the HE core for its systick timer. So
the following pins don't have PWM available because they need UTIMER11:
P2_6, P2_7, P7_6, P7_7, P12_6, P12_7.
Signed-off-by: Damien George <damien@micropython.org>
This allows `machine.deepsleep(N)` to wake the device after the timout N
seconds.
Could probably also do the same thing for lightsleep.
Note that this uses the LPTIMER0 resource, which would not work if
`MICROPY_HW_SYSTEM_TICK_USE_LPTIMER` was ever enabled (it's currently never
enabled, so OK for now).
Signed-off-by: Damien George <damien@micropython.org>
Occasionally, it's useful to be able to compare MicroPython's performance
figures to CPython's. This change adds the ability to run the internalbench
test runner with `--test-instance=cpython` in order to execute the same
test routines against CPython and produce a benchmark performance report in
the same format as MicroPython.
Signed-off-by: Anson Mansfield <amansfield@mantaro.com>
Previously, mpycert.der was the Intermediate certificate which is regularly
re-issued by Letsencrypt.
Also changes ssl_cert.py to load the cert data from the same file as
test_sslcontext_client.py, so the DER string doesn't have to be pasted
into the source.
This work was funded through GitHub Sponsors.
Signed-off-by: Angus Gratton <angus@redyak.com.au>
Over the time, these are manufactured with different flash types.
All changed boards still build and run with the Giga Devices chip.
The ItsyBitsy M4 board was confirmed to work with the Winbond chip.
Signed-off-by: robert-hh <robert@hammelrath.com>
This gives a more user-friendly name when the Python object (eg Pin) is
printed. If the nodelabel is unavailable then it uses `dev->name` as a
fallback.
Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
Fixes fatal crash if serial port access returns an error (for example: port
is native USB-CDC and the host hard faults during the test run). Instead of
crashing, have the runner mark this as a test run error and continue.
It's not certain the next test will run successfully, but this provides the
context of output showing what was happening when the communication error
occurred. Without this change, that output is lost when the fatal exception
terminates the runner process.
This work was funded through GitHub Sponsors.
Signed-off-by: Angus Gratton <angus@redyak.com.au>
Test file paths which get passed to the run_tests function can be
absolute or relative and with or without leading slash in the latter
case, depending on the arguments to run-tests.py, but since that path
is used to:
- display which tests run
- record which tests ran in the results.json
- craft the filename for the .exp/.out file for failed tests
it is desirable to always use the same file path irregardless of
how the user passed the path.
In practice this means that all forms of running our own tests like:
>python ./run-tests.py -i extmod
>python ./run-tests.py -d extmod
>python ./run-tests.py -d ./extmod
>python ./run-tests.py -d ../tests/extmod
>python ./run-tests.py -d /full/path/to/tests/extmod
will now consistently all display the tests like
pass extmod/time_time_ns.py
FAIL extmod/some_failing_test.py
and produce output files like
results/extmod_some_failing_test.py.exp
results/extmod_some_failing_test.py.out
instead of displaying/using the exact path as passed.
For external tests, meaning not in the tests/ directory, we also want
to be consistent so there the choice was made to always use absolute
paths.
Signed-off-by: stijn <stijn@ignitron.net>
Scan the --test-dirs argument for the main tests directory being
passed and if so do the same thing as if running from within that
main test directory.
In practice this makes the following (which used to counterintuitively
try and fail to run the .py files in the tests/ directory itself)
>python micropython/tests/run-tests.py -d micropython/tests
do the same thing as
>cd micropython/tests
>python ./run-tests.py
which is logical and convenient.
Signed-off-by: stijn <stijn@ignitron.net>
Test file paths which get passed to the run_tests function can be
absolute or relative and with or without leading slash in the latter
case, depending on the arguments to run-tests.py, but the skip_tests
list with tests to skip only contains relative paths so using simple
string equality comparison easily leads to false negatives.
Compare the full absolute path instead such that it doesn't matter
anymore in which form the tests are passed. Note:
- use realpath to resolve symlinks plus make the comparison case
insensitive on windows
- the test_file passed to run_one_test is not altered by this commit,
such that when the user inputs relative paths the tests are also
still displayed with relative paths
- likewise the test_file_abspath is not modified because functions
like run_micropython rely on it having forward slashes
In practice this means that it used to be so that the only forms
of running tests for which the skip_tests lists actually worked were:
>python ./run-tests.py
>python ./run-tests.py -d extmod
whereas it now works consistently so also for these invocations,
which in the end all point to the exact same path:
>python ./run-tests.py -d ./extmod
>python ./run-tests.py -d ../tests/extmod
>python ./run-tests.py -d /full/path/to/tests/extmod
These examples used to not skip any of the tests in the extmod/
directory thereby leading to test failures.
Signed-off-by: stijn <stijn@ignitron.net>
This is convenient when trying to figure out the correct values
for --include/--exclude/--test-dirs/... arguments.
Signed-off-by: stijn <stijn@ignitron.net>
This turns the reproducer into a sensible-ish crash:
TypeError: exceptions must derive from BaseException
Closes: #17117
Signed-off-by: Jeff Epler <jepler@unpythonic.net>