From f051942fb4eb307c6d18ab746c344e5cdbe22129 Mon Sep 17 00:00:00 2001 From: Brad Barnett <127794626+bdbarnett@users.noreply.github.com> Date: Tue, 10 Nov 2026 10:04:29 -0600 Subject: [PATCH] firmware modules: list modules pinned in DEPENDENCIES.lock micropython-pydevices is moving its pins into one DEPENDENCIES.lock, read through build_mp.py's lock(). The module listing takes the not yet fetched modules from there when build_mp.py has it, and from modules.lock otherwise. --- cli/src/mpftp/firmware_build.py | 9 +++++++-- cli/tests/test_firmware_build.py | 11 +++++++++++ docs/guides/build-firmware.md | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/cli/src/mpftp/firmware_build.py b/cli/src/mpftp/firmware_build.py index 5433c9c..a20b88c 100644 --- a/cli/src/mpftp/firmware_build.py +++ b/cli/src/mpftp/firmware_build.py @@ -161,9 +161,14 @@ def modules(g): need(g, "MODULES_DIR", "module_choices") md = g["MODULES_DIR"] names = set(g["module_choices"]()) + # The modules pinned but maybe not fetched yet: DEPENDENCIES.lock's module + # lines through lock(), or modules.lock in a checkout from before it. try: - names |= {row[0] for row in g["read_lock"]("modules.lock")} - except Exception: + if "lock" in g: + names |= {p.name for p in g["lock"]().values() if p.group == "modules"} + else: + names |= {row[0] for row in g["read_lock"]("modules.lock")} + except (Exception, SystemExit): pass recs = [] for n in sorted(names, key=lambda n: (n != "all", n)): diff --git a/cli/tests/test_firmware_build.py b/cli/tests/test_firmware_build.py index 6ea2876..2fe413e 100644 --- a/cli/tests/test_firmware_build.py +++ b/cli/tests/test_firmware_build.py @@ -359,6 +359,17 @@ def test_modules_are_build_mps_with_the_lock_ones_not_yet_fetched(self) -> None: self.assertIn("(opt-in)", text) self.assertIn("(fetched on first build)", text) + def test_modules_pinned_in_dependencies_lock_are_listed_too(self) -> None: + script = self.bs / "build_mp.py" + old = 'def read_lock(name):\n return [("audiodsp", "url", "sha"), ("ulab", "url", "sha")]' + new = ('def lock():\n from types import SimpleNamespace as P\n' + ' return {n: P(name=n, group=g) for n, g in (("micropython", "micropython"), ' + '("ulab", "modules"), ("esp-idf", "toolchains"), ("omnipython-lvgl", "sources"))}') + self.assertIn(old, script.read_text()) + script.write_text(script.read_text().replace(old, new)) + info = run_engine(["modules", "--build-system", str(self.bs)])[0] + self.assertEqual(sorted(m["name"] for m in info["modules"]), ["all", "audiodsp", "castif", "tflite", "ulab"]) + def test_circuitpython_lists_its_own_ports_and_our_boards(self) -> None: cp = self.bs / "deps" / "circuitpython" / "ports" cp.mkdir(parents=True) diff --git a/docs/guides/build-firmware.md b/docs/guides/build-firmware.md index fdc8333..e53ded7 100644 --- a/docs/guides/build-firmware.md +++ b/docs/guides/build-firmware.md @@ -49,7 +49,7 @@ build shows up, yours and upstream's alike. `mpftp firmware modules` lists what `--modules` takes: - A module's short name, from the checkout's `modules/` folder, marked **C** - or **Python**. A module pinned in `modules.lock` but not fetched yet is + or **Python**. A module the checkout pins but hasn't fetched yet is listed too, marked "fetched on first build". - `all`, which is every module except the opt-in ones (such as `tflite` and `vision`, which are large). Name an opt-in module to build it.