diff options
author | Alexei Frolov <frolv@google.com> | 2020-01-03 10:02:26 -0800 |
---|---|---|
committer | CQ Bot Account <commit-bot@chromium.org> | 2020-01-03 23:57:15 +0000 |
commit | 7b8528e85d2a475a0d87f94d598c6183a08c2d5c (patch) | |
tree | 81c31a4ffe732018e29da884f46ef25fdd776db9 /pw_cli | |
parent | b3fca3a02ad14ab71de2bd62644cedac49dad1af (diff) | |
download | pigweed-7b8528e85d2a475a0d87f94d598c6183a08c2d5c.tar.gz |
pw_cli: Define Pigweed environment variables
This change adds an environment module to pw_cli which defines all of
the environment variables used by Pigweed.
A new variable named PW_USE_COLOR added, forcing the use of log colors
even if not printing to a TTY. This is set by the watch command for its
subprocesses.
The check for the PW_SUBPROCESS variable in logging is updated to use
the environment module.
Change-Id: I84007691f3ae9bb262c6bf6471afa43db831268f
Diffstat (limited to 'pw_cli')
-rw-r--r-- | pw_cli/py/pw_cli/color.py | 33 | ||||
-rw-r--r-- | pw_cli/py/pw_cli/env.py | 45 | ||||
-rw-r--r-- | pw_cli/py/pw_cli/envparse.py | 4 | ||||
-rw-r--r-- | pw_cli/py/pw_cli/envparse_test.py | 12 | ||||
-rw-r--r-- | pw_cli/py/pw_cli/log.py | 23 | ||||
-rwxr-xr-x | pw_cli/py/pw_cli/watch.py | 9 |
6 files changed, 87 insertions, 39 deletions
diff --git a/pw_cli/py/pw_cli/color.py b/pw_cli/py/pw_cli/color.py index c31718aab..bfd05445f 100644 --- a/pw_cli/py/pw_cli/color.py +++ b/pw_cli/py/pw_cli/color.py @@ -1,4 +1,4 @@ -# Copyright 2019 The Pigweed Authors +# Copyright 2020 The Pigweed Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy of @@ -16,6 +16,8 @@ import sys from typing import Optional, Union +import pw_cli.env + def _make_color(*codes): # Apply all the requested ANSI color codes. Note that this is unbalanced @@ -30,17 +32,18 @@ def _make_color(*codes): # 'colorful' module. class _Color: # pylint: disable=too-few-public-methods """Helpers to surround text with ASCII color escapes""" - red = _make_color(31, 1) - bold_red = _make_color(30, 41) - yellow = _make_color(33, 1) - bold_yellow = _make_color(30, 43, 1) - green = _make_color(32) - bold_green = _make_color(30, 42) - blue = _make_color(34, 1) - cyan = _make_color(36, 1) - magenta = _make_color(35, 1) - bold_white = _make_color(37, 1) - black_on_white = _make_color(30, 47) # black fg white bg + def __init__(self): + self.red = _make_color(31, 1) + self.bold_red = _make_color(30, 41) + self.yellow = _make_color(33, 1) + self.bold_yellow = _make_color(30, 43, 1) + self.green = _make_color(32) + self.bold_green = _make_color(30, 42) + self.blue = _make_color(34, 1) + self.cyan = _make_color(36, 1) + self.magenta = _make_color(35, 1) + self.bold_white = _make_color(37, 1) + self.black_on_white = _make_color(30, 47) # black fg white bg class _NoColor: @@ -55,6 +58,8 @@ def colors(enabled: Optional[bool] = None) -> Union[_Color, _NoColor]: By default, the object only colorizes if both stderr and stdout are TTYs. """ if enabled is None: - enabled = sys.stdout.isatty() and sys.stderr.isatty() + env = pw_cli.env.pigweed_environment() + enabled = env.PW_USE_COLOR or (sys.stdout.isatty() + and sys.stderr.isatty()) - return _Color if enabled else _NoColor() + return _Color() if enabled else _NoColor() diff --git a/pw_cli/py/pw_cli/env.py b/pw_cli/py/pw_cli/env.py new file mode 100644 index 000000000..8631afd9f --- /dev/null +++ b/pw_cli/py/pw_cli/env.py @@ -0,0 +1,45 @@ +# Copyright 2020 The Pigweed Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +"""The env module defines the environment variables used by Pigweed.""" + +from typing import Optional + +from pw_cli import envparse + + +def pigweed_environment_parser() -> envparse.EnvironmentParser: + """Defines Pigweed's environment variables on an EnvironmentParser.""" + parser = envparse.EnvironmentParser(prefix='PW_') + + parser.add_var('PW_ENVSETUP') + parser.add_var('PW_ROOT') + parser.add_var('PW_SUBPROCESS', type=envparse.strict_bool, default=False) + parser.add_var('PW_USE_COLOR', type=envparse.strict_bool, default=False) + + return parser + + +# Internal: memoize environment parsing to avoid unnecessary computation in +# multiple calls to pigweed_environment(). +_memoized_environment: Optional[envparse.EnvNamespace] = None + + +def pigweed_environment() -> envparse.EnvNamespace: + """Returns Pigweed's parsed environment.""" + global _memoized_environment # pylint: disable=global-statement + + if _memoized_environment is None: + _memoized_environment = pigweed_environment_parser().parse_env() + + return _memoized_environment diff --git a/pw_cli/py/pw_cli/envparse.py b/pw_cli/py/pw_cli/envparse.py index a5c101c99..5a6376899 100644 --- a/pw_cli/py/pw_cli/envparse.py +++ b/pw_cli/py/pw_cli/envparse.py @@ -62,7 +62,7 @@ class EnvironmentParser: parser = envparse.EnvironmentParser(prefix='PW_') parser.add_var('PW_LOG_LEVEL') parser.add_var('PW_LOG_FILE', type=envparse.FileType('w')) - parser.add_var('PW_USE_COLOR', type=envparse.bool_type, default=False) + parser.add_var('PW_USE_COLOR', type=envparse.strict_bool, default=False) env = parser.parse_env() configure_logging(env.PW_LOG_LEVEL, env.PW_LOG_FILE) @@ -135,7 +135,7 @@ class EnvironmentParser: return f'{type(self).__name__}(prefix={self._prefix})' -def bool_type(value: str) -> bool: +def strict_bool(value: str) -> bool: return value == '1' or value.lower() == 'true' diff --git a/pw_cli/py/pw_cli/envparse_test.py b/pw_cli/py/pw_cli/envparse_test.py index 8962e5e51..8917a4212 100644 --- a/pw_cli/py/pw_cli/envparse_test.py +++ b/pw_cli/py/pw_cli/envparse_test.py @@ -122,8 +122,8 @@ class TestEnvironmentParserWithPrefix(unittest.TestCase): parser.add_var('FOO') -class TestBoolType(unittest.TestCase): - """Tests for envparse.bool_type.""" +class TestStrictBool(unittest.TestCase): + """Tests for envparse.strict_bool.""" def setUp(self): self.good_bools = ['true', '1', 'TRUE', 'tRuE'] self.bad_bools = [ @@ -131,12 +131,12 @@ class TestBoolType(unittest.TestCase): ] def test_good_bools(self): - self.assertTrue(all( - envparse.bool_type(val) for val in self.good_bools)) + self.assertTrue( + all(envparse.strict_bool(val) for val in self.good_bools)) def test_bad_bools(self): - self.assertFalse(any( - envparse.bool_type(val) for val in self.bad_bools)) + self.assertFalse( + any(envparse.strict_bool(val) for val in self.bad_bools)) if __name__ == '__main__': diff --git a/pw_cli/py/pw_cli/log.py b/pw_cli/py/pw_cli/log.py index f5730281f..cd4250009 100644 --- a/pw_cli/py/pw_cli/log.py +++ b/pw_cli/py/pw_cli/log.py @@ -1,4 +1,4 @@ -# Copyright 2019 The Pigweed Authors +# Copyright 2020 The Pigweed Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy of @@ -14,11 +14,10 @@ """Configure the system logger for the default pw command log format.""" import logging -import os -import sys from typing import Optional import pw_cli.color +import pw_cli.env import pw_cli.plugins # Log level used for captured output of a subprocess run through pw. @@ -45,22 +44,18 @@ def install(level: int = logging.INFO, use_color: Optional[bool] = None) -> None: """Configure the system logger for the default pw command log format.""" - colors = pw_cli.color.colors( - sys.stderr.isatty() if use_color is None else use_color) + colors = pw_cli.color.colors(use_color) - pw_subprocess = os.getenv('PW_SUBPROCESS') - if pw_subprocess is None: - # This applies a gray background to the time to make the log lines - # distinct from other input, in a way that's easier to see than plain - # colored text. - timestamp_fmt = colors.black_on_white('%(asctime)s') + ' ' - elif pw_subprocess == '1': + env = pw_cli.env.pigweed_environment() + if env.PW_SUBPROCESS: # If the logger is being run in the context of a pw subprocess, the # time and date are omitted (since pw_cli.process will provide them). timestamp_fmt = '' else: - raise ValueError( - f'Invalid environment variable PW_SUBPROCESS={pw_subprocess}') + # This applies a gray background to the time to make the log lines + # distinct from other input, in a way that's easier to see than plain + # colored text. + timestamp_fmt = colors.black_on_white('%(asctime)s') + ' ' # Set log level on root logger to debug, otherwise any higher levels # elsewhere are ignored. diff --git a/pw_cli/py/pw_cli/watch.py b/pw_cli/py/pw_cli/watch.py index 7603c4b6c..fc8fc9030 100755 --- a/pw_cli/py/pw_cli/watch.py +++ b/pw_cli/py/pw_cli/watch.py @@ -1,4 +1,4 @@ -# Copyright 2019 The Pigweed Authors +# Copyright 2020 The Pigweed Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy of @@ -155,7 +155,7 @@ class PigweedBuildWatcher(FileSystemEventHandler): """Run all the builds in serial and capture pass/fail for each.""" # Clear the screen and show a banner indicating the build is starting. - print("\033c", end="") # TODO(pwbug/38): Not Windows compatible. + print('\033c', end='') # TODO(pwbug/38): Not Windows compatible. print(_COLOR.magenta(_BUILD_MESSAGE)) _LOG.info('Change detected: %s', matching_path) @@ -167,7 +167,10 @@ class PigweedBuildWatcher(FileSystemEventHandler): # Run the build. Put a blank before/after for visual separation. print() - result = subprocess.run(['ninja', '-C', build_dir]) + env = os.environ.copy() + # Force colors in Pigweed subcommands run through the watcher. + env['PW_USE_COLOR'] = '1' + result = subprocess.run(['ninja', '-C', build_dir], env=env) print() build_ok = (result.returncode == 0) |