blob: fa5da5943b3c18fbace933f72ccabae9d3fc5fa9 [file] [log] [blame]
.. _chapter-pw-cli:
.. default-domain:: python
.. highlight:: sh
------
pw_cli
------
This directory contains the ``pw`` command line interface (CLI) that facilitates
working with Pigweed. The CLI module adds several subcommands prefixed with
``pw``, and provides a mechanism for other Pigweed modules to behave as
"plugins" and register themselves as ``pw`` commands as well. After activating
the Pigweed environment, these commands will be available for use.
``pw`` includes the following commands by default:
.. code-block:: text
doctor Check that the environment is set up correctly for Pigweed.
format Check and fix formatting for source files.
help Display detailed information about pw commands.
logdemo Show how logs look at various levels.
module-check Check that a module matches Pigweed's module guidelines.
test Run Pigweed unit tests built using GN.
watch Watch files for changes and rebuild.
To see an up-to-date list of ``pw`` subcommands, run ``pw --help``.
Invoking ``pw``
================
``pw`` subcommands are invoked by providing the command name. Arguments prior to
the command are interpreted by ``pw`` itself; all arguments after the command
name are interpreted by the command.
Here are some example invocations of ``pw``:
.. code-block:: text
# Run the doctor command
$ pw doctor
# Run format --fix with debug-level logs
$ pw --loglevel debug format --fix
# Display help for the pw command
$ pw -h watch
# Display help for the watch command
$ pw watch -h
Registering ``pw`` plugins
==========================
Projects can register their own Python scripts as ``pw`` commands. ``pw``
plugins are registered by providing the command name, module, and function in a
``PW_PLUGINS`` file. ``PW_PLUGINS`` files can add new commands or override
built-in commands. Since they are accessed by module name, plugins must be
defined in Python packages that are installed in the Pigweed virtual
environment.
Plugin registrations in a ``PW_PLUGINS`` file apply to the their directory and
all subdirectories, similarly to configuration files like ``.clang-format``.
Registered plugins appear as commands in the ``pw`` tool when ``pw`` is run from
those directories.
Projects that wish to register commands might place a ``PW_PLUGINS`` file in the
root of their repo. Multiple ``PW_PLUGINS`` files may be applied, but the ``pw``
tool gives precedence to a ``PW_PLUGINS`` file in the current working directory
or the nearest parent directory.
PW_PLUGINS file format
----------------------
``PW_PLUGINS`` contains one plugin entry per line in the following format:
.. code-block:: python
# Lines that start with a # are ignored.
<command name> <Python module> <function>
The following example registers three commands:
.. code-block:: python
# Register the presubmit script as pw presubmit
presubmit my_cool_project.tools run_presubmit
# Override the pw test command with a custom version
test my_cool_project.testing run_test
# Add a custom command
flash my_cool_project.flash main
Defining a plugin function
--------------------------
Any function without required arguments may be used as a plugin function. The
function should return an int, which the ``pw`` uses as the exit code. The
``pw`` tool uses the function docstring as the help string for the command.
Typically, ``pw`` commands parse their arguments with the ``argparse`` module.
``pw`` sets ``sys.argv`` so it contains only the arguments for the plugin,
so plugins can behave the same whether they are executed independently or
through ``pw``.
Example
^^^^^^^
This example shows a function that is registered as a ``pw`` plugin.
.. code-block:: python
# my_package/my_module.py
def _do_something(device):
...
def main() -> int:
"""Do something to a connected device."""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--device', help='Set which device to target')
return _do_something(**vars(parser.parse_args()))
if __name__ == '__main__':
logging.basicConfig(format='%(message)s', level=logging.INFO)
sys.exit(main())
This plugin is registered in a ``PW_PLUGINS`` file in the current working
directory or a parent of it.
.. code-block:: python
# Register my_commmand
my_command my_package.my_module main
The function is now available through the ``pw`` command, and will be listed in
``pw``'s help. Arguments after the command name are passed to the plugin.
.. code-block:: text
$ pw
▒█████▄ █▓ ▄███▒ ▒█ ▒█ ░▓████▒ ░▓████▒ ▒▓████▄
▒█░ █░ ░█▒ ██▒ ▀█▒ ▒█░ █ ▒█ ▒█ ▀ ▒█ ▀ ▒█ ▀█▌
▒█▄▄▄█░ ░█▒ █▓░ ▄▄░ ▒█░ █ ▒█ ▒███ ▒███ ░█ █▌
▒█▀ ░█░ ▓█ █▓ ░█░ █ ▒█ ▒█ ▄ ▒█ ▄ ░█ ▄█▌
▒█ ░█░ ░▓███▀ ▒█▓▀▓█░ ░▓████▒ ░▓████▒ ▒▓████▀
usage: pw [-h] [-C DIRECTORY] [-l LOGLEVEL] [--no-banner] [command] ...
The Pigweed command line interface (CLI).
...
supported commands:
doctor Check that the environment is set up correctly for Pigweed.
format Check and fix formatting for source files.
help Display detailed information about pw commands.
...
my_command Do something to a connected device.
$ pw my_command -h
▒█████▄ █▓ ▄███▒ ▒█ ▒█ ░▓████▒ ░▓████▒ ▒▓████▄
▒█░ █░ ░█▒ ██▒ ▀█▒ ▒█░ █ ▒█ ▒█ ▀ ▒█ ▀ ▒█ ▀█▌
▒█▄▄▄█░ ░█▒ █▓░ ▄▄░ ▒█░ █ ▒█ ▒███ ▒███ ░█ █▌
▒█▀ ░█░ ▓█ █▓ ░█░ █ ▒█ ▒█ ▄ ▒█ ▄ ░█ ▄█▌
▒█ ░█░ ░▓███▀ ▒█▓▀▓█░ ░▓████▒ ░▓████▒ ▒▓████▀
usage: pw my_command [-h] [--device DEVICE]
Do something to a connected device.
optional arguments:
-h, --help show this help message and exit
--device DEVICE Set which device to target