aboutsummaryrefslogtreecommitdiff
path: root/pw_cli
diff options
context:
space:
mode:
authorAlexei Frolov <frolv@google.com>2020-01-03 10:02:26 -0800
committerCQ Bot Account <commit-bot@chromium.org>2020-01-03 23:57:15 +0000
commit7b8528e85d2a475a0d87f94d598c6183a08c2d5c (patch)
tree81c31a4ffe732018e29da884f46ef25fdd776db9 /pw_cli
parentb3fca3a02ad14ab71de2bd62644cedac49dad1af (diff)
downloadpigweed-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.py33
-rw-r--r--pw_cli/py/pw_cli/env.py45
-rw-r--r--pw_cli/py/pw_cli/envparse.py4
-rw-r--r--pw_cli/py/pw_cli/envparse_test.py12
-rw-r--r--pw_cli/py/pw_cli/log.py23
-rwxr-xr-xpw_cli/py/pw_cli/watch.py9
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)