-
Notifications
You must be signed in to change notification settings - Fork 164
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
Commands - dot-prefixed, stdlib only #367
base: main
Are you sure you want to change the base?
Conversation
This implements a "cl" command using the drgn CLI command framework proposed in osandov/drgn#367. The "cl" command invokes Corelens modules as sub-commands. Signed-off-by: Stephen Brennan <[email protected]>
I fixed the Python 3.6-3.9 mypy failure which was present in the previous revision, but of course since I updated the pre-commit, you won't actually get a mypy run on 3.6 now. I don't have permissions to add the label to the PR, but it would be good to have CI run against all Python versions, just to verify. Of course I tested it locally on 3.9 and it worked. I also rebased this on main. I even checked this in combination with the #364 changes and they don't conflict. With those changes, it's pretty impressive how much less verbose the command line is! |
Very funny, I didn't realize that when Github Actions runs, it does an automatic merge with the |
As a debugger library, drgn can be a little bit verbose when running interactively. There has been general concensus that it would be nice to have a way to define shorthands for common operations, or define user scripts that are easy to run within the shell. However we have yet to settle upon a solution. Implementing a full CLI seems out of the scope of drgn. Leveraging the power of a system like IPython's "magic" commands is promising, but adds heavy dependencies. One example CLI to draw inspiration from is SQLite, which uses the "." prefix to define meta-commands that aren't part of the SQL language. Python, like SQL, cannot begin a statement with a ".", so it could be used to unambiguously signal that a command is being entered, and thanks to the code.InteractiveConsole, we can easily extend the console to handle these commands. So, let's add a command system. Commands are simply callables which take a program, the full line of text (which may contain arguments), and the CLI locals. They may return a Python object which is stored to `builtins._`. They can be registered using a decorator, and an API is available to retrieve the default list. The run_interactive() function allows the user to customize the available command list. Signed-off-by: Stephen Brennan <[email protected]>
The execscript() helper is intended to run from the CLI and access the calling scope's global variables. However, for CLI commands to use it, execscript() must optionally accept a global variable dict directly. Signed-off-by: Stephen Brennan <[email protected]>
This helper allows users to evaluate very basic C expressions of the form "(type)int_literal". This enables users to more easily copy and paste printed results back into the console to get the corresponding object. Signed-off-by: Stephen Brennan <[email protected]>
The "x" command is short for "eXecute" or execscript(). The "contrib" command is similar to "x", but runs scripts from the "contrib/" directory if it is present. The "let" command sets variables based on the typed expression. Signed-off-by: Stephen Brennan <[email protected]>
Signed-off-by: Stephen Brennan <[email protected]>
Signed-off-by: Stephen Brennan <[email protected]>
Since you mentioned it Wednesday, I thought I'd update the command pull request here. If you wanted to just assemble your own system from the idea (overriding The actual commands themselves from this pull request aren't too important. Though I do really like the I do think the major missing piece here is that, if we were going to have a command system, there should be a separate page in the documentation with a description of each command. Ideally it could be somehow generated from the docstring of each command function, but presented as something else. I'm not sure how that would work yet. |
This is another stab at the idea of commands in drgn.
Rather than using IPython like the first PR I shared, this one is based on the stdlib only. It integrates into the existing drgn CLI via a subclass of
InteractiveConsole
. Commands are simply a callable, since I didn't want to get too opinionated with a class-based solution, or even requiring the use of argparse.Commands in the CLI are prefixed by a
.
. No valid Python statement starts with that, so this shouldn't break any existing behavior. They are able to return results just like normal expressions, and they can access the locals too.The
drgn.cli
module has a registry of commands, which can be added to using the@command("name")
decorator. In order to ensure that user/third-party commands can be loaded, I've added adrgn.command.v1
entry point. Drgn automatically loads modules from that entry point prior to starting the CLI. (This is notable from a security standpoint. However, if you're running drgn as root, you would have needed to install that entry point as root as well.)Just like globals and everything else, commands can be customized in
run_interactive()
.I've added three useful commands into the default set. These aren't the only ones I would be interested in adding, just a demonstration.
.x
- execute a script (basically a wrapper on execscript).let
- set a variable equal to a drgn object.contrib
- run a contrib script by nameI also added support to the
ptdrgn.py
script because I use that constantly.In any case, I hope that the code is pretty straightforward. I think this is the most simple and direct way I could come up with to do commands in drgn.