New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC — DtSh, shell-like interface with Devicetree #59863
base: main
Are you sure you want to change the base?
Conversation
7057216
to
66b9925
Compare
7f86207
to
b170331
Compare
I think VS Code extension: nRF DeviceTree is a good graphical tool. But it's not open source. Not particularly friendly to non-nRF devices |
b1c9d74
to
b5d6d2c
Compare
Thanks for this. I think it's a great idea and I especially appreciate the attention to detail you put into the RFC as well as volunteering maintenance. Consider me onboard with this idea. I'll give it some testing and review. |
Some unboxing comments:
I can't get tab completion working as I expect using the homebrew python 3.11. From the prompt:
I press TAB and expect commands to be completed. But instead I see a tab character is inserted. Is that expected? Here is my python info (using a virtual environment):
I can The command parser also doesn't seem to be stripping leading whitespace:
this isn't like what you'd expect from a shell in my opinion -- I would expect both of those to quit. |
Command options to configure formatted outputs. Base command with boilerplate code to support formatted output. Unit tests and examples: tests/test_dtsh_rich_shellutils.py Signed-off-by: Christophe Dufaza <chris@openmarl.org>
Unit tests and examples: tests/test_dtsh_builtin_pwd.py Signed-off-by: Christophe Dufaza <chris@openmarl.org>
Unit tests and examples: tests/test_dtsh_builtin_cd.py Signed-off-by: Christophe Dufaza <chris@openmarl.org>
Unit tests and examples: tests/test_dtsh_builtin_ls.py Signed-off-by: Christophe Dufaza <chris@openmarl.org>
Unit tests and examples: tests/test_dtsh_builtin_tree.py Signed-off-by: Christophe Dufaza <chris@openmarl.org>
Search for nodes with pre-defined criteria. Unit tests and examples: tests/test_dtsh_builtin_find.py Signed-off-by: Christophe Dufaza <chris@openmarl.org>
Print information about aliased nodes. Unit tests and examples: tests/test_dtsh_builtin_alias.py Signed-off-by: Christophe Dufaza <chris@openmarl.org>
Print information about chosen nodes. Unit tests and examples: tests/test_dtsh_builtin_chosen.py Signed-off-by: Christophe Dufaza <chris@openmarl.org>
Base interactive devicetree shell session. A session binds a devicetree shell and a VT to run an interactive loop. Signed-off-by: Christophe Dufaza <chris@openmarl.org>
Rich interactive devicetree shell session. Extend the base session with a few rich TUI elements and support for SVG and HTML command output redirection formats. Signed-off-by: Christophe Dufaza <chris@openmarl.org>
Run the devicetree shell without West. Signed-off-by: Christophe Dufaza <chris@openmarl.org>
Assuming the reviewers assigned to this PR were all busy working on the "Introduction of board and SoC scheme v2" and "Better support for multi-core AMP SoCs" (which look interesting), I haven't pushed nor commented in two month, and this PR has eventually been automatically closed by a bot. IIUC (e.g. issue #59177 and Allow to reopen pull requests after a force push):
I should then be able to rebase it with the actual contents that's ready there. Changes since November include (history has been squashed numerous times, this is what comes to mind):
I thinks this PR, once properly rebased, will be ready for review. It was a personal choice not to communicate (e.g. Zephyr mailing lists) too early, I think now is the time and I will do it once this is reopened to also get some user oriented feedback. Thanks. |
@dottspina I've reopened the PR for you. |
West command implementation: - class DTShell in zephyr/scripts/west_commands/dtshell.py - packages dtsh and devicetree imported with os.sys.insert() statements Add dtsh extension to West in zephyr/scripts/west-commands.yml. Add dtsh requirements to "used by west_commands" in zephyr/scripts/requirements-base.txt: - rich (https://github.com/Textualize/rich) - Pygments (https://github.com/pygments/pygments) - gnureadline (https://pypi.org/project/gnureadline/), macOS only Add support for West completion in: - zephyr/scripts/west_commands/completion/west-completion.bash - zephyr/scripts/west_commands/completion/west-completion.zsh Signed-off-by: Christophe Dufaza <chris@openmarl.org>
Add to Zephyr documentation: - West command usage - DTSh user guide Signed-off-by: Christophe Dufaza <chris@openmarl.org>
Thank you @pdgendt. [Edit: the "Stale" label has also been removed] |
This looks like an absolutely amazing tool with a lot of power to save everyone time, nice work! I have a strong preference for dependencies like this to live as PyPI packages so that they can:
How would you feel about publishing to PyPI and only committing the West integration to the Zephyr repo? |
Backport RFC-DTSh code base for dtsh-0.2rc1. See zephyrproject-rtos/zephyr#59863
Mirror and package RFC-DTSh code base. See zephyrproject-rtos/zephyr#59863
Mirror and package RFC-DTSh code base. See zephyrproject-rtos/zephyr#59863
Thanks for your feedback, @JPHutchins.
I agree that maintenance should not be overlooked: this concern is part of the RFC, and I indeed expect it to be discussed.
Dependencies first go the other way: although this RFC/PR does not affect Zephyr aside from the new West command, DTSh is tightly coupled to the Zephyr's python-devicetree library, and to the hardware model it's an API for. Therefore, when distributed independently, DTSh releases have to pin the python-devicetree versions they're developed and tested with:
One way or another, Zephyr users will end up with two instances of the python-devicetree library:
Which raises the question of what should happen when running
If Zephyr in turn pins DTSh, we add mutual dependencies to the picture. Although these might be handled through a coordinated release (and testing !) process, I'm afraid this will turn out painful for maintainers and sub-optimal for users, especially when releasing and distributing bug fixes.
To me, users needing to change the version of DTSh they are using with a given version of Zephyr would show that the above coordinated release process is indeed a failure.
DTSh still makes little sense outside of Zephyr, as does the python-devicetree library: both might eventually be helpful with e.g. the Linux kernel's Devicetree, but AFAICT we're still far from that. This doesn't mean DTSh can't be installed independently of Zephyr, and tried to experiment with arbitrary DTS and binding files, see bellow.
Aside from the personal concerns I've already mentioned, I don't think making the DTSh shell an external dependency installed as a Zephyr requirement, while the West command would be maintained upstream, can be acceptable to Zephyr maintainers:
To answer your question, my feeling is thus that if DTSh were to be maintained, as much as possible, in isolation of the Zephyr repository, we would better off abandoning the Publishing on PyPI has issues, but could work: the DTSh project's default branch now mirrors and packages the code base of this RFC, that you can install and run independently of West or even Zephyr (more details here). Note that this package can't provide the West integration: just run Why I think having this upstream could nonetheless benefit to Zephyr users:
Thanks. |
Mirror and package RFC-DTSh code base, minus West integration. To be released as DTSh 0.2-rc1. See zephyrproject-rtos/zephyr#59863
I understand really well that those who might review this RFC have other legit priorities, and I don't want to rush anyone. But I'm a bit bothered. At some point, to not actually freeze all DTSh development until this is approved or rejected, I somewhat rebased a new project branch onto the source code in this PR minus the West command (DTSh v0.2.0-rc1), and made it the default after a few additional patches to better take into account both installation types, bundled with Zephyr or downloaded from PyPI (DTSh v0.2.0). DTSh has since gained a batch mode, two new commands, beside bug fixes and improvements in various areas. The commit history could permit to cherry-pick just a few things, or I could rebase this PR onto the latest DTSh release (v0.2.2) or any tag in between. And that's what bothers me: I don't know what to do ? What is certain is that reviewing this RFC as it is would make no sense: we're now far from the idea of merging this, then adding short incremental PRs (something like when the rabbit can't ever catch up with the turtle, you know). I still personally think that developing and maintaining DTSh upstream as a Zephyr extension to West makes sense:
So I would lean toward rebasing this PR onto at least DTSh v0.2.1, to get the batch mode and the But I don't want to decide alone, go the wrong approach, and send to much time myself to Any ideas or opinions, e.g. @mbolivar-nordic , @kartben , @galak ? I'm not getting impatient, I just don't know what I should do now ;-) Thanks. References: |
RFC: DTSh: DTS file viewer with a shell-like command line interface
Introduction
Problem description
Prior to Zephyr, I've only approached Devicetree while looking through LKML or The Linux Kernel documentation.
And, quoting @mbolivar-nordic (October 2020):
I can agree that, when learning Zephyr use of Devicetree, I've personally felt the lack of a quick, simple tool to:
References:
Proposed change
The proposed change is a new West command that opens a Devicetree in a shell-like command line interface:
of commands to files
where:
west dtsh
: when invoked without any argument, the Devicetree shell will open the DTS filebuild/zephyr/zephyr.dts
, and retrieve the bindings Zephyr has used at build-time from the CMake cache filebuild/CMakeCache.txt
cd &flash_controller
changes the current working directory from the devicetree's root to the node at/soc/flash-controller@4001e000
, using its DTS labelflash_controller
find
is with no surprise a shell command that will search for devices, bindings, buses, interrupts, etc-E --also-known-as (image|storage).*
will match nodes with a label or alias starting withimage
orstorage
; predicates like--with-reg-size >4k
are also supported--format NKd
: set the node output format to the columns "nodeN
ame,", "AlsoK
nown As" (all labels and aliases), and "d
escription" (D
is the "Depends-on" column)-T
: list found nodes in tree-like format> doc/partitions.svg
to the last command line would save the partitions tree to the filedoc/partitions.svg
, in SVG formatThe considered use cases include:
This proposal started with a Proof of Concept project: source code and documentation for this prototype are still available as the main branch of the DTSh repository.
The new code base in this RFC is also distributed as a stand-alone package you can install from PyPI without messing with your Zephyr wokspaces: for details, take a look the dtsh-next branch which mirrors this PR in the DTSh repository. Note that this version can't provide West integration: just replace
west dtsh
withdtsh
.Please refer to the attached DTSh User Guide (PDF) for the complete documentation of what this RFC implements and examples of use.
Detailed RFC
This RFC includes:
Proposed change (Detailed)
This RFC wouldn't be review-able as a single commit: it is introduced as a series, where each commit adds a new feature or API, with its companion unit tests when they exist.
Once reviewed, we can squash or rearrange the whole thing according to the maintainers' preferences.
DTSh
DTSh is implemented in Python and is a Devicetree tool: it seems its natural location is
zephyr/scripts/dts/dtsh
, sibling topython-devicetree
with which it's tightly coupled.Source files are located in
dtsh/src
, anddtsh
is the root Python package.Unit tests are implemented with pytest, and located in
dtsh/tests
.The
res
sub-directory contains test resource files.Devicetree model
DTSh introduces its own model layer above
edtlib.EDT
.Rationale:
edtlib
API (python-devicetree)dtsh.dts
test_dtsh_dts
dtsh.model
test_dtsh_model
dtsh.modelutils
test_dtsh_modelutils
GNU Readline integration
Responsibilities:
from the Readline hooks machinery
dtsh.rl
dtsh.autocomp
test_dtsh_autocomp
Devicetree shell
Responsibilities:
dtsh.io
test_dtsh_io
dtsh.config
test_dtsh_config
dtsh.shell
test_dtsh_shell
dtsh.shellutils
test_dtsh_shellutils
dtsh.session
rich TUI
DTSh's rich Textual User Interface is built on Texualize's rich library.
dtsh.rich.theme
test_dtsh_theme
dtsh.rich.tui
dtsh.rich.text
dtsh.rich.modelview
dtsh.rich.svg
test_dtsh_rich_svg
dtsh.rich.io
dtsh.rich.autocomp
dtsh.rich.shellutils
test_dtsh_rich_shellutils
dtsh.rich.session
Built-in Commands
Bellow are the currently implemented commands.
dtsh.builtins.cd
cd
: change the current working branchtest_dtsh_builtin_cd
dtsh.builtins.pwd
pwd
: print path of current working branch.test_dtsh_builtin_pwd
dtsh.builtins.ls
ls
: list branch contentstest_dtsh_builtin_ls
dtsh.builtins.tree
tree
: list branch contents in tree-like formattest_dtsh_builtin_tree
dtsh.builtins.find
find
: search branches for nodestest_dtsh_builtin_find
dtsh.builtins.alias
alias
: list aliased nodestest_dtsh_builtin_alias
dtsh.builtins.chosen
chosen
: list chosen nodestest_dtsh_builtin_chosen
West extension
West command implementation:
DTShell
inzephyr/scripts/west_commands/dtshell.py
dtsh
anddevicetree
imported withos.sys.insert()
statementsAdded
dtsh
extension to West inzephyr/scripts/west-commands.yml
.Added DTSh run-time requirements to
zephyr/scripts/requirements-base.txt
:Added support for West completion to
west-completion.bash
andwest-completion.zsh
.Documentation
The proposed change:
zephyr-cmds.rst
to document the West commanddtsh.rst
) in the same directoryDependencies
DTSh should not affect other components or needs changes in other areas.
But that's not true the other way around: changes in the Zephyr's hardware model may require changes in DTSh (see bellow).
Concerns and Unresolved Questions
Maintenance
This is a valid concern:
edtlib
API: this might introduce some additional maintenance for it to consistently follow changesThe everyday maintenance should be low, though:
dtsh.model
encapsulates all uses of theedtlib
API: if breaking changes are introduced, DTSh will fail thereThe above observations come from my own experience (an example of breaking change was identifying top-level bindings with
(compat, bus)
tuples rather than just compatible strings).More significant changes, like "Hardware model v2" or "Better support for multi-core AMP SoCs", could however involve more work, to either fix DTSh or add support for the new model.
Fortunately:
Finally, I'll gladly continue myself contributing support, features and bug fixing in the long run.
Limitations
This RFC is not a complete Devicetree shell:
cat
command, with a syntax likecat soc/timer$max-bit-width
man
command, with manual pages for DTSh itself, but more importantly also for bindings and boardsI've already implemented these when experimenting with the PoC project: I know what to do, and how.
But this RFC is already sizable, and will require quite some work from its reviewers: I'd prefer we first agree on the initial design, implementation and documentation, then I'll push the missing commands with shortest individual PRs. This has been discussed and so far seems to be a consensus.
GNU Realine on Windows
Or the lack of.
For auto-completion, command history and key bindings, DTSh relies on the GNU Readline variant of the standard Python
readline
API.Basically, there's no sane and straight forward way to build and distribute the GNU Readline library on non POSIX systems: on Windows, Python simply gave up and does no longer include the
readline
module with its standard library (see e.g. There's no readline module on Windows Python (cmd.Cmd) for some historical context).The stand-alone module pyrealine3 cited in the above reference has been investigated as a work-around, but its API is incomplete, and its implementation too much coupled with
cmd.Cmd
, which we don't use. The project does not seem actively maintained.To get a cross-platform user experience, I've also considered the pure Python Prompt Toolkit:
Although DTSh may eventually work around this limitation, this is clearly not a priority at the moment.
As a consequence, the GNU Readline integration will very likely be disabled on Windows, resulting in a degraded user experience.
However, I am quite optimistic that this will not be considered a merge blocker: Zephyr seems to admit this kind of little (though very unfortunate here) difference between POSIX and non POSIX systems, e.g.
west
itself also supports auto-completion only with the Bash and Zsh shells.User Guide Integration
The DTSh User Guide (
dtsh.rst
) is quite long, and contains sections, subsections, sub-subsections, etc.Its integration with Zephyr's documentation is almost fine in HTML, and I'm not sure how to do better without messing with the
:toctree:
, which I prefer to avoid.Its integration when generating PDF is more debatable (look at the attached PDF, concerns should be obvious):
The final PDF document is still legible, but I admit it's not optimal: I will gladly try any ideas for improvement.
Correctness
DTSh use cases include educational tools for newcomers to Zephyr Devicetree: if not correct, erroneous results (commands output) will do more harm than good.
Although correctness is the focus of unit tests, and code coverage for the core modules should be almost complete, these tests involve only a small subset of the possible configurations (MCU, SoC, boards, shields, peripherals).
I think we could define a minimum level of correctness as:
Security
The proposed change is not that hazardous:
dtsh
does not evaluate (eval()
) any part of the user inputdtsh
does not pipe commands to the system interpreter (e.g.os.system()
oros.popen()
), nor create any kind of child process (e.g.subprocess.run()
)$XDG_CONFIG_HOME
or%LOCALAPPDATA%
)dtsh
won't override any existing file (including when redirecting commands output)Personal biases
Why a command line application ? Well, when you've done
west build
, you're already at the command line, and I think continuing from there withwest dtsh
, getting a different prompt but the same user interface paradigms and even key bindings (the base ones used by Zsh, GNU Bash, Emacs, GDB), is more ditrsaction-free than opening a GUI.Beyond this personal biases, things like PyGObject or Qt for Python have nonetheless been considered, but:
Alternatives
There doesn't seem to be many DTS file viewers.
Nordic Semiconductor's distributes the nRF DeviceTree extension for VS Code, which looks interesting but does not address the initial problem (as @hongshui3000 also pointed out):