-
Notifications
You must be signed in to change notification settings - Fork 0
Contributing and Development
This page covers working on PyCommander itself: setting up a development environment, running the tests, and the layout of the monorepo. For how releases are built and published, see Releasing.
- Source: SiliconLabsSoftware/pycommander
-
License: Silicon Labs Master Software License Agreement (MSLA),
LicenseRef-MSLA. - Code of Conduct: see the agreements-and-guidelines repository.
packages/
├── pycommander/ # meta-package (the `pycommander` command)
├── pycommander-cli/ # CLI flavor (bundles commander-cli, `pycommander-cli`)
├── pycommander-gui/ # GUI flavor (bundles commander, `pycommander-gui`)
└── pycommander-core/ # the framework (all real logic; no executable)
scripts/
├── run_tests.py
└── update_commander_archives.py
archives/ # platform Commander archives used at release time
See Architecture-and-Packages for how the packages relate and how the bundled executable is located and extracted at runtime.
PyCommander targets Python 3.10+. Install all four packages in editable mode so changes are picked up immediately:
python -m pip install --upgrade pip
python -m pip install -e packages/pycommander-core \
-e packages/pycommander-cli \
-e packages/pycommander-gui \
-e packages/pycommander \
--force-reinstallThe core package depends on pyyaml and platformdirs.
The flavor packages need a Simplicity Commander archive under their _archive/ directory to actually run hardware commands. The archives/ directory holds per-platform archives, and the convenience script copies the right ones into place:
# Fetch the latest Commander archives into archives/, then copy the
# platform-appropriate CLI and GUI archives into the flavor packages.
./scripts/update_commander_archives.py --update-local-archives
# Or pin a specific Commander version:
./scripts/update_commander_archives.py --version 1.2.3 -lupdate_commander_archives.py pulls archives from the Silicon Labs Artifactory repository. Without --version, it picks the highest available version number.
You can also point the API at a specific executable at runtime via
Commander(executable_path=...), which is handy for testing against a particular build without touching_archive/.
Each package has a tests/ suite. The aggregate runner discovers and runs all of them:
python scripts/run_tests.pyTo produce coverage like CI does:
python -m pip install coverage
python -m pip install -r packages/*/tests/requirements.txt
coverage run scripts/run_tests.py
coverage report
coverage html # writes htmlcov/The test suites use mock runners/adapters/commanders (see packages/pycommander-core/tests/), so most tests do not require real hardware.
Two GitHub Actions workflows live in .github/workflows/:
-
unittest-and-coverage.yml— runs the test suites and produces a combined coverage report across Linux (x86_64 / aarch64), macOS (arm64) and Windows. Triggered manually (workflow_dispatch). It copies the correct Commander archives into the flavor packages before installing and testing. -
build-wheels-and-publish.yml— builds platform-specific wheels and publishes to PyPI on av*.*.*tag. See Releasing.
A few patterns to keep in mind when extending the code:
-
One module per CLI suite under
pycommander_core/commands/. Each command class subclassesBaseCommand, builds an argument list with the provided helpers (_get_ranges,_get_patches,_get_regions,_get_tokens,_get_include_sections, …), and returnsself._run(...).output. -
CommanderBaseauto-registers every command class fromcommands.__all__, deriving the attribute name from the class name (FlashCommand→commander.flash). When you add a suite, export it fromcommands/__init__.pyand add a type-hint attribute onCommanderBase. -
High-level helpers (Adapter-Class, Target-Class,
AemStreamBase) parse Commander's JSON into the dataclasses intypes.py. Validate inputs and raiseValueError/FileNotFoundErrorearly; returnNonefor failed look-ups andboolfor actions. -
All subprocess work goes through
runner.Runner, which centralizes timeouts, logging, JSON handling, and the mapping of return codes to Error-Handling.
- Create
pycommander_core/commands/<suite>.pywith aclass <Suite>Command(BaseCommand). - Add public methods that assemble args and call
self._run("<suite>", "<subcommand>", *args).output. Document each with a docstring (Args/Returns) — this wiki is generated from those. - Export the class in
commands/__init__.py(from .<suite> import <Suite>Commandand add to__all__). - Add a type-hint attribute on
CommanderBase(<suite> : "<Suite>Command"). - (Optional) Add a typed wrapper on
Adapter/Targetif the command maps to a common task. - Add tests under the relevant package's
tests/.
PyCommander · GitHub · Simplicity Commander docs · Licensed under the Silicon Labs MSLA
Getting started
Using PyCommander
Topics
Command reference
- Overview
- adapter · aem · vcom · ctune
- device · flash · verify · readmem · extflash
- security
- tokens · nvm3 · littlefs
- convert · ebl · gbl3 · gbl4 · ota · rps · postbuild
- util · serial · mfg917
Contributing