Skip to content

Commit 6f7ba06

Browse files
authored
Merge branch 'micropython:master' into master
2 parents baf6532 + e6b89ea commit 6f7ba06

File tree

182 files changed

+7300
-1364
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

182 files changed

+7300
-1364
lines changed

.github/workflows/build_packages.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@ jobs:
99
build:
1010
runs-on: ubuntu-latest
1111
steps:
12-
- uses: actions/checkout@v2
13-
- uses: actions/setup-python@v1
12+
- uses: actions/checkout@v3
13+
- uses: actions/setup-python@v4
1414
- name: Setup environment
1515
run: source tools/ci.sh && ci_build_packages_setup
1616
- name: Check manifest files
1717
run: source tools/ci.sh && ci_build_packages_check_manifest
1818
- name: Compile package index
1919
run: source tools/ci.sh && ci_build_packages_compile_index
20+
- name: Compile package examples
21+
run: source tools/ci.sh && ci_build_packages_examples
2022
- name: Publish packages for branch
2123
if: vars.MICROPY_PUBLISH_MIP_INDEX && github.event_name == 'push' && ! github.event.deleted
2224
run: source tools/ci.sh && ci_push_package_index

.github/workflows/cleanup_published_packages.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ jobs:
77
runs-on: ubuntu-latest
88
if: vars.MICROPY_PUBLISH_MIP_INDEX
99
steps:
10-
- uses: actions/checkout@v2
10+
- uses: actions/checkout@v3
1111
- name: Clean up published files
1212
run: source tools/ci.sh && ci_cleanup_package_index ${{ github.event.ref }}

.github/workflows/code_formatting.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ jobs:
66
build:
77
runs-on: ubuntu-latest
88
steps:
9-
- uses: actions/checkout@v2
10-
- uses: actions/setup-python@v1
9+
- uses: actions/checkout@v3
10+
- uses: actions/setup-python@v4
1111
- name: Install packages
1212
run: source tools/ci.sh && ci_code_formatting_setup
1313
- name: Run code formatting

.github/workflows/ruff.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
2+
name: Python code lint with ruff
3+
on: [push, pull_request]
4+
jobs:
5+
ruff:
6+
runs-on: ubuntu-latest
7+
steps:
8+
- uses: actions/checkout@v3
9+
- run: pip install --user ruff
10+
- run: ruff --format=github .

.pre-commit-config.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
repos:
2+
- repo: local
3+
hooks:
4+
- id: codeformat
5+
name: MicroPython codeformat.py for changed files
6+
entry: tools/codeformat.py -v -f
7+
language: python
8+
- repo: https://github.com/charliermarsh/ruff-pre-commit
9+
rev: v0.0.280
10+
hooks:
11+
- id: ruff

CONTRIBUTING.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,21 @@ or packages from micropython-lib, please post at the
2525
### Pull requests
2626

2727
The same rules for commit messages, signing-off commits, and commit structure
28-
apply as for the main MicroPython repository. All Python code is formatted
29-
using `black`. See [`tools/codeformat.py`](tools/codeformat.py) to apply
30-
`black` automatically before submitting a PR.
28+
apply [as for the main MicroPython repository](https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md).
3129

32-
There are some specific conventions and guidelines for micropython-lib:
30+
All Python code is formatted using the [black](https://github.com/psf/black)
31+
tool. You can run [`tools/codeformat.py`](tools/codeformat.py) to apply
32+
`black` automatically before submitting a PR. The GitHub CI will also run the
33+
[ruff](https://github.com/astral-sh/ruff) tool to apply further "linting"
34+
checks.
35+
36+
Similar to the main repository, a configuration is provided for the
37+
[pre-commit](https://pre-commit.com/) tool to apply `black` code formatting
38+
rules and run `ruff` automatically. See the documentation for using pre-commit
39+
in [the code conventions document](https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md#automatic-pre-commit-hooks)
40+
41+
In addition to the conventions from the main repository, there are some
42+
specific conventions and guidelines for micropython-lib:
3343

3444
* The first line of the commit message should start with the name of the
3545
package, followed by a short description of the commit. Package names are

micropython/aioespnow/README.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# `aioespnow`
2+
3+
A supplementary module which extends the micropython `espnow` module to provide
4+
`asyncio` support.
5+
6+
- Asyncio support is available on all ESP32 targets as well as those ESP8266
7+
boards which include the `uasyncio` module (ie. ESP8266 devices with at least
8+
2MB flash storage).
9+
10+
## API reference
11+
12+
- class `AIOESPNow()`: inherits all the methods of the `ESPNow` class and
13+
extends the interface with the following async methods:
14+
15+
- `async AIOESPNow.arecv()`
16+
17+
Asyncio support for ESPNow.recv(). Note that this method does not take a
18+
timeout value as argument.
19+
20+
- `async AIOESPNow.airecv()`
21+
22+
Asyncio support for ESPNow.irecv(). Use this method to reduce memory
23+
fragmentation, as it will reuse common storage for each new message
24+
received, whereas the `arecv()` method will allocate new memory for every
25+
message received.
26+
27+
- `async AIOESPNow.asend(mac, msg, sync=True)`
28+
- `async AIOESPNow.asend(msg)`
29+
30+
Asyncio support for ESPNow.send().
31+
32+
- `__aiter__()/async __anext__()`
33+
34+
AIOESPNow also supports reading incoming messages by asynchronous
35+
iteration using `async for`, eg:
36+
37+
```python
38+
e = AIOESPNow()
39+
e.active(True)
40+
async def recv_till_halt(e):
41+
async for mac, msg in e:
42+
print(mac, msg)
43+
if msg == b'halt':
44+
break
45+
asyncio.run(recv_till_halt(e))
46+
```
47+
48+
## Example Usage
49+
50+
A small async server example::
51+
52+
```python
53+
import network
54+
import aioespnow
55+
import uasyncio as asyncio
56+
57+
# A WLAN interface must be active to send()/recv()
58+
network.WLAN(network.STA_IF).active(True)
59+
60+
e = aioespnow.AIOESPNow() # Returns AIOESPNow enhanced with async support
61+
e.active(True)
62+
peer = b'\xbb\xbb\xbb\xbb\xbb\xbb'
63+
e.add_peer(peer)
64+
65+
# Send a periodic ping to a peer
66+
async def heartbeat(e, peer, period=30):
67+
while True:
68+
if not await e.asend(peer, b'ping'):
69+
print("Heartbeat: peer not responding:", peer)
70+
else:
71+
print("Heartbeat: ping", peer)
72+
await asyncio.sleep(period)
73+
74+
# Echo any received messages back to the sender
75+
async def echo_server(e):
76+
async for mac, msg in e:
77+
print("Echo:", msg)
78+
try:
79+
await e.asend(mac, msg)
80+
except OSError as err:
81+
if len(err.args) > 1 and err.args[1] == 'ESP_ERR_ESPNOW_NOT_FOUND':
82+
e.add_peer(mac)
83+
await e.asend(mac, msg)
84+
85+
async def main(e, peer, timeout, period):
86+
asyncio.create_task(heartbeat(e, peer, period))
87+
asyncio.create_task(echo_server(e))
88+
await asyncio.sleep(timeout)
89+
90+
asyncio.run(main(e, peer, 120, 10))
91+
```

micropython/aioespnow/aioespnow.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# aioespnow module for MicroPython on ESP32 and ESP8266
2+
# MIT license; Copyright (c) 2022 Glenn Moloney @glenn20
3+
4+
import uasyncio as asyncio
5+
import espnow
6+
7+
8+
# Modelled on the uasyncio.Stream class (extmod/stream/stream.py)
9+
# NOTE: Relies on internal implementation of uasyncio.core (_io_queue)
10+
class AIOESPNow(espnow.ESPNow):
11+
# Read one ESPNow message
12+
async def arecv(self):
13+
yield asyncio.core._io_queue.queue_read(self)
14+
return self.recv(0) # type: ignore[misc]
15+
16+
async def airecv(self):
17+
yield asyncio.core._io_queue.queue_read(self)
18+
return self.irecv(0) # type: ignore[misc]
19+
20+
async def asend(self, mac, msg=None, sync=None):
21+
if msg is None:
22+
msg, mac = mac, None # If msg is None: swap mac and msg
23+
yield asyncio.core._io_queue.queue_write(self)
24+
return self.send(mac, msg, sync) # type: ignore[misc]
25+
26+
# "async for" support
27+
def __aiter__(self):
28+
return self
29+
30+
async def __anext__(self):
31+
return await self.airecv()

micropython/aioespnow/manifest.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
metadata(
2+
description="Extends the micropython espnow module with methods to support asyncio.",
3+
version="0.1.0",
4+
)
5+
6+
module("aioespnow.py")

micropython/aiorepl/README.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,17 @@ async def main():
5050
asyncio.run(main())
5151
```
5252

53-
The optional globals passed to `task([globals])` allows you to specify what
54-
will be in scope for the REPL. By default it uses `__main__`, which is the
55-
same scope as the regular REPL (and `main.py`). In the example above, the
56-
REPL will be able to call the `demo()` function as well as get/set the
57-
`state` variable.
53+
An optional globals dictionary can be passed to `aiorepl.task()`, which allows
54+
you to specify what will be in scope for the REPL. By default it uses the
55+
globals dictionary from the `__main__` module, which is the same scope as the
56+
regular REPL (and `main.py`). In the example above, the REPL will be able to
57+
call the `demo()` function as well as get/set the `state` variable.
58+
59+
You can also provide your own dictionary, e.g. `aiorepl.task({"obj": obj })`,
60+
or use the globals dict from the current module, e.g.
61+
`aiorepl.task(globals())`. Note that you cannot use a class instance's members
62+
dictionary, e.g. `aiorepl.task(obj.__dict__)`, as this is read-only in
63+
MicroPython.
5864

5965
Instead of the regular `>>> ` prompt, the asyncio REPL will show `--> `.
6066

micropython/aiorepl/aiorepl.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# MIT license; Copyright (c) 2022 Jim Mussared
22

33
import micropython
4+
from micropython import const
45
import re
56
import sys
67
import time
@@ -26,19 +27,21 @@ async def execute(code, g, s):
2627
if "await " in code:
2728
# Execute the code snippet in an async context.
2829
if m := _RE_IMPORT.match(code) or _RE_FROM_IMPORT.match(code):
29-
code = f"global {m.group(3) or m.group(1)}\n {code}"
30+
code = "global {}\n {}".format(m.group(3) or m.group(1), code)
3031
elif m := _RE_GLOBAL.match(code):
31-
code = f"global {m.group(1)}\n {code}"
32+
code = "global {}\n {}".format(m.group(1), code)
3233
elif not _RE_ASSIGN.search(code):
33-
code = f"return {code}"
34+
code = "return {}".format(code)
3435

35-
code = f"""
36+
code = """
3637
import uasyncio as asyncio
3738
async def __code():
38-
{code}
39+
{}
3940
4041
__exec_task = asyncio.create_task(__code())
41-
"""
42+
""".format(
43+
code
44+
)
4245

4346
async def kbd_intr_task(exec_task, s):
4447
while True:
@@ -81,7 +84,7 @@ async def kbd_intr_task(exec_task, s):
8184
micropython.kbd_intr(-1)
8285

8386
except Exception as err:
84-
print(f"{type(err).__name__}: {err}")
87+
print("{}: {}".format(type(err).__name__, err))
8588

8689

8790
# REPL task. Invoke this with an optional mutable globals dict.

micropython/aiorepl/manifest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
metadata(
2-
version="0.1",
2+
version="0.1.1",
33
description="Provides an asynchronous REPL that can run concurrently with an asyncio, also allowing await expressions.",
44
)
55

micropython/bluetooth/aioble-client/manifest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
metadata(version="0.2.0")
1+
metadata(version="0.3.0")
22

33
require("aioble-core")
44

micropython/bluetooth/aioble-server/manifest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
metadata(version="0.2.0")
1+
metadata(version="0.3.0")
22

33
require("aioble-core")
44

micropython/bluetooth/aioble/aioble/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ class ClientDescriptor(BaseClientCharacteristic):
439439
def __init__(self, characteristic, dsc_handle, uuid):
440440
self.characteristic = characteristic
441441

442-
super().__init__(dsc_handle, _FLAG_READ | _FLAG_WRITE_NO_RESPONSE, uuid)
442+
super().__init__(dsc_handle, _FLAG_READ | _FLAG_WRITE, uuid)
443443

444444
def __str__(self):
445445
return "Descriptor: {} {} {}".format(self._value_handle, self.properties, self.uuid)

micropython/bluetooth/aioble/aioble/server.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,6 @@
3838

3939
_FLAG_WRITE_CAPTURE = const(0x10000)
4040

41-
_FLAG_DESC_READ = const(1)
42-
_FLAG_DESC_WRITE = const(2)
43-
4441

4542
_WRITE_CAPTURE_QUEUE_LIMIT = const(10)
4643

@@ -307,14 +304,13 @@ class Descriptor(BaseCharacteristic):
307304
def __init__(self, characteristic, uuid, read=False, write=False, initial=None):
308305
characteristic.descriptors.append(self)
309306

310-
# Workaround for https://github.com/micropython/micropython/issues/6864
311307
flags = 0
312308
if read:
313-
flags |= _FLAG_DESC_READ
309+
flags |= _FLAG_READ
314310
if write:
311+
flags |= _FLAG_WRITE
315312
self._write_event = asyncio.ThreadSafeFlag()
316313
self._write_data = None
317-
flags |= _FLAG_DESC_WRITE
318314

319315
self.uuid = uuid
320316
self.flags = flags

micropython/bluetooth/aioble/examples/l2cap_file_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ async def download(self, path, dest):
8787

8888
send_seq = await self._command(_COMMAND_SEND, path.encode())
8989

90-
with open(dest, "wb") as f:
90+
with open(dest, "wb") as f: # noqa: ASYNC101
9191
total = 0
9292
buf = bytearray(self._channel.our_mtu)
9393
mv = memoryview(buf)

micropython/bluetooth/aioble/examples/l2cap_file_server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ async def l2cap_task(connection):
8282

8383
if send_file:
8484
print("Sending:", send_file)
85-
with open(send_file, "rb") as f:
85+
with open(send_file, "rb") as f: # noqa: ASYNC101
8686
buf = bytearray(channel.peer_mtu)
8787
mv = memoryview(buf)
8888
while n := f.readinto(buf):

micropython/bluetooth/aioble/manifest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# code. This allows (for development purposes) all the files to live in the
44
# one directory.
55

6-
metadata(version="0.2.1")
6+
metadata(version="0.3.1")
77

88
# Default installation gives you everything. Install the individual
99
# components (or a combination of them) if you want a more minimal install.

micropython/bundles/bundle-networking/manifest.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,9 @@
55

66
require("mip")
77
require("ntptime")
8-
require("urequests")
8+
require("requests")
99
require("webrepl")
10+
11+
# Provide urequests (which just forwards to requests) for backwards
12+
# compatibility.
13+
require("urequests")
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
metadata(description="Onewire driver.", version="0.1.0")
2+
13
module("onewire.py", opt=3)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
metadata(description="WM8960 codec.", version="0.1.1")
2+
13
module("wm8960.py", opt=3)

0 commit comments

Comments
 (0)