Skip to content

Commit

Permalink
pw_watch: Generic watcher and bazel integration
Browse files Browse the repository at this point in the history
- Introduce //pw_watch/py:run, a generic file watcher. It watches files
  and runs commands when they change. The commands may share a common
  prefix (e.g. bazelisk) to reduce typing. For now, this tool uses
  pw_presubmit's console UI elements.
- Introduce //pw_watch/py:bazel, which runs one or more bazelisk
  commands when files change. Arguments are forwarded directly to bazel/
  bazelisk, so all subcommands and options are available. This tool is a
  simple entrypoint to the generic //pw_watch/py:run tool.
- Make a few pw_presubmit.presubmit UI-related functions public.

Fixes: b/375421339
Change-Id: I3d2e73b65378a65e94b79a3b5b2dc59db96d5e6e
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/258775
Pigweed-Auto-Submit: Wyatt Hepler <[email protected]>
Lint: Lint 🤖 <[email protected]>
Reviewed-by: Anthony DiGirolamo <[email protected]>
Commit-Queue: Wyatt Hepler <[email protected]>
  • Loading branch information
255 authored and CQ Bot Account committed Jan 9, 2025
1 parent f94267a commit 5976c3a
Show file tree
Hide file tree
Showing 6 changed files with 409 additions and 12 deletions.
5 changes: 5 additions & 0 deletions pw_cli/py/pw_cli/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ def pigweed_environment() -> envparse.EnvNamespace:
name='__main__',
function='watch_setup',
),
AllowedCaller(
filename='pw_watch/py/pw_watch/run.py',
name='__main__',
function='_parse_args',
),
]


Expand Down
28 changes: 18 additions & 10 deletions pw_presubmit/py/pw_presubmit/presubmit.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,28 +96,31 @@ def run_the_build():

_LEFT = 7
_RIGHT = 11
BOX_CENTER_WIDTH = WIDTH - _LEFT - _RIGHT - 4


def _title(msg, style=_SUMMARY_BOX) -> str:
msg = f' {msg} '.center(WIDTH - 2)
return tools.make_box('^').format(*style, section1=msg, width1=len(msg))


def _format_time(time_s: float) -> str:
def format_time(time_s: float) -> str:
minutes, seconds = divmod(time_s, 60)
if minutes < 60:
return f' {int(minutes)}:{seconds:04.1f}'
hours, minutes = divmod(minutes, 60)
return f'{int(hours):d}:{int(minutes):02}:{int(seconds):02}'


def _box(style, left, middle, right, box=tools.make_box('><>')) -> str:
def _box(
style: str, left: str, middle: str, right: str, box=tools.make_box('><>')
) -> str:
return box.format(
*style,
section1=left + ('' if left.endswith(' ') else ' '),
width1=_LEFT,
section2=' ' + middle,
width2=WIDTH - _LEFT - _RIGHT - 4,
width2=BOX_CENTER_WIDTH,
section3=right + ' ',
width3=_RIGHT,
)
Expand All @@ -144,6 +147,14 @@ def color(value):
return padding + color(self.value) + padding


def step_header(left: str, middle: str, right: str) -> str:
return _box(_CHECK_UPPER, left, middle, right)


def step_footer(left: str, middle: str, right: str) -> str:
return _box(_CHECK_LOWER, left, middle, right)


class Program(collections.abc.Sequence):
"""A sequence of presubmit checks; basically a tuple with a name."""

Expand Down Expand Up @@ -447,7 +458,7 @@ def _log_summary(
_SUMMARY_BOX,
result.colorized(_LEFT, invert=True),
f'{total} checks on {plural(self._paths, "file")}: {summary}',
_format_time(time_s),
format_time(time_s),
)
)

Expand Down Expand Up @@ -911,8 +922,7 @@ def run(
"""Runs the presubmit check on the provided paths."""

_print_ui(
_box(
_CHECK_UPPER,
step_header(
f'{count}/{total}',
self.name,
plural(ctx.paths, "file"),
Expand All @@ -935,15 +945,13 @@ def run(
result = self.run_substep(ctx, substep)
else:
result = self(ctx)
time_str = _format_time(time.time() - start_time_s)
time_str = format_time(time.time() - start_time_s)
_LOG.debug('%s %s', self.name, result.value)

if ctx.dry_run:
log_check_traces(ctx)

_print_ui(
_box(_CHECK_LOWER, result.colorized(_LEFT), self.name, time_str)
)
_print_ui(step_footer(result.colorized(_LEFT), self.name, time_str))
_LOG.debug('%s duration:%s', self.name, time_str)

return result
Expand Down
34 changes: 34 additions & 0 deletions pw_watch/docs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ takes to run tests.
-----------
Get started
-----------

GN
==
.. code-block:: bash
cd ~/pigweed
Expand All @@ -67,6 +70,37 @@ To override this behavior, provide the ``-C`` argument to ``pw watch``.
See :ref:`module-pw_watch-guide` for more examples and
:ref:`module-pw_watch-cli` for detailed CLI usage information.

Bazel
=====
The Bazel build provides a ``//pw_watch:bazel`` entrypoint, which executes
commands with ``bazelisk``. Arguments are forwarded directly to ``bazel`` /
``bazelisk``, so any ``bazel`` subcommands may be used.

.. code-block:: sh
# Runs bazelisk build //... when files change.
bazelisk run //pw_watch:bazel build //...
# Runs an executable when files change.
bazelisk run //pw_watch:bazel -- run //important:script -a --value 52
# Builds //..., then runs the //foo:bar test.
bazelisk run //pw_watch:bazel build //... , test //foo:bar
.. important::

``bazelisk run`` interprets arguments that start with ``-``. Pass ``--``
before any other arguments to separate arguments to Bazel from command
arguments.

.. code-block:: sh
bazelisk run //pw_watch:bazel -- <commands to run>
Custom commands
===============
.. automodule:: pw_watch.run

.. toctree::
:hidden:
:maxdepth: 1
Expand Down
22 changes: 20 additions & 2 deletions pw_watch/py/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ py_library(
"pw_watch/argparser.py",
"pw_watch/common.py",
"pw_watch/debounce.py",
"pw_watch/run.py",
"pw_watch/watch.py",
"pw_watch/watch_app.py",
],
Expand All @@ -43,9 +44,26 @@ py_library(
pw_py_binary(
name = "watch",
srcs = ["pw_watch/watch.py"],
deps = [
":pw_watch",
deps = [":pw_watch"],
)

pw_py_binary(
name = "bazel",
srcs = ["pw_watch/run.py"],
args = [
"--keep-going",
"--prefix",
"bazelisk",
"--pw-watch-commands",
],
main = "pw_watch/run.py",
deps = [":pw_watch"],
)

pw_py_binary(
name = "run",
srcs = ["pw_watch/run.py"],
deps = [":pw_watch"],
)

pw_py_test(
Expand Down
1 change: 1 addition & 0 deletions pw_watch/py/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pw_python_package("py") {
"pw_watch/argparser.py",
"pw_watch/common.py",
"pw_watch/debounce.py",
"pw_watch/run.py",
"pw_watch/watch.py",
"pw_watch/watch_app.py",
]
Expand Down
Loading

0 comments on commit 5976c3a

Please sign in to comment.