aboutsummaryrefslogtreecommitdiff
path: root/pw_cli/py
diff options
context:
space:
mode:
Diffstat (limited to 'pw_cli/py')
-rw-r--r--pw_cli/py/BUILD.bazel4
-rw-r--r--pw_cli/py/BUILD.gn2
-rw-r--r--pw_cli/py/pw_cli/arguments.py4
-rw-r--r--pw_cli/py/pw_cli/color.py30
-rw-r--r--pw_cli/py/pw_cli/log.py4
-rw-r--r--pw_cli/py/pw_cli/toml_config_loader_mixin.py50
-rw-r--r--pw_cli/py/pw_cli/yaml_config_loader_mixin.py166
7 files changed, 26 insertions, 234 deletions
diff --git a/pw_cli/py/BUILD.bazel b/pw_cli/py/BUILD.bazel
index c77ce2ca2..d6d0ff36e 100644
--- a/pw_cli/py/BUILD.bazel
+++ b/pw_cli/py/BUILD.bazel
@@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations under
# the License.
-load("@rules_python//python:defs.bzl", "py_library")
+load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test")
package(default_visibility = ["//visibility:public"])
@@ -34,8 +34,6 @@ py_library(
"pw_cli/process.py",
"pw_cli/pw_command_plugins.py",
"pw_cli/requires.py",
- "pw_cli/toml_config_loader_mixin.py",
- "pw_cli/yaml_config_loader_mixin.py",
],
imports = ["."],
)
diff --git a/pw_cli/py/BUILD.gn b/pw_cli/py/BUILD.gn
index 6b7ff68c4..91966de0c 100644
--- a/pw_cli/py/BUILD.gn
+++ b/pw_cli/py/BUILD.gn
@@ -40,8 +40,6 @@ pw_python_package("py") {
"pw_cli/shell_completion/zsh/__init__.py",
"pw_cli/shell_completion/zsh/pw/__init__.py",
"pw_cli/shell_completion/zsh/pw_build/__init__.py",
- "pw_cli/toml_config_loader_mixin.py",
- "pw_cli/yaml_config_loader_mixin.py",
]
tests = [
"envparse_test.py",
diff --git a/pw_cli/py/pw_cli/arguments.py b/pw_cli/py/pw_cli/arguments.py
index a5b8e4b27..724dc07bb 100644
--- a/pw_cli/py/pw_cli/arguments.py
+++ b/pw_cli/py/pw_cli/arguments.py
@@ -23,6 +23,7 @@ from typing import List, NoReturn, Optional
from pw_cli import argument_types, plugins
from pw_cli.branding import banner
+import pw_cli.env
_HELP_HEADER = '''The Pigweed command line interface (CLI).
@@ -108,6 +109,9 @@ def print_completions_for_option(
def print_banner() -> None:
"""Prints the PIGWEED (or project specific) banner to stderr."""
+ parsed_env = pw_cli.env.pigweed_environment()
+ if parsed_env.PW_ENVSETUP_NO_BANNER or parsed_env.PW_ENVSETUP_QUIET:
+ return
print(banner() + '\n', file=sys.stderr)
diff --git a/pw_cli/py/pw_cli/color.py b/pw_cli/py/pw_cli/color.py
index 6b9074bf5..d435b2a55 100644
--- a/pw_cli/py/pw_cli/color.py
+++ b/pw_cli/py/pw_cli/color.py
@@ -61,28 +61,34 @@ class _NoColor:
return str
+def is_enabled():
+ env = pw_cli.env.pigweed_environment()
+ # Checking if PW_USE_COLOR is in os.environ and not env since it's always
+ # in env. If it's in os.environ then use the value retrieved in env.
+ if 'PW_USE_COLOR' in os.environ:
+ return env.PW_USE_COLOR
+
+ # These are semi-standard ways to turn colors off or on for many projects.
+ # See https://bixense.com/clicolors/ and https://no-color.org/ for more.
+ if 'NO_COLOR' in os.environ:
+ return False
+ if 'CLICOLOR_FORCE' in os.environ:
+ return os.environ['CLICOLOR_FORCE'] != '0'
+
+ return sys.stdout.isatty() and sys.stderr.isatty()
+
+
def colors(enabled: Optional[bool] = None) -> Union[_Color, _NoColor]:
"""Returns an object for colorizing strings.
By default, the object only colorizes if both stderr and stdout are TTYs.
"""
if enabled is None:
- env = pw_cli.env.pigweed_environment()
- if 'PW_USE_COLOR' in os.environ:
- enabled = env.PW_USE_COLOR
- else:
- enabled = sys.stdout.isatty() and sys.stderr.isatty()
+ enabled = is_enabled()
if enabled and os.name == 'nt':
# Enable ANSI color codes in Windows cmd.exe.
kernel32 = ctypes.windll.kernel32 # type: ignore
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
- # These are semi-standard ways to turn colors off or on for many projects.
- # See https://bixense.com/clicolors/ and https://no-color.org/ for more.
- if 'NO_COLOR' in os.environ:
- enabled = False
- elif 'CLICOLOR_FORCE' in os.environ:
- enabled = True
-
return _Color() if enabled else _NoColor()
diff --git a/pw_cli/py/pw_cli/log.py b/pw_cli/py/pw_cli/log.py
index e1ef13fde..37877e6cf 100644
--- a/pw_cli/py/pw_cli/log.py
+++ b/pw_cli/py/pw_cli/log.py
@@ -58,7 +58,7 @@ def c_to_py_log_level(c_level: int) -> int:
return c_level * 10
-def main() -> None:
+def main() -> int:
"""Shows how logs look at various levels."""
# Force the log level to make sure all logs are shown.
@@ -73,6 +73,8 @@ def main() -> None:
_LOG.log(LOGLEVEL_STDOUT, 'Standard output of subprocess')
_LOG.debug('Adding 1 to i')
+ return 0
+
def _setup_handler(
handler: logging.Handler,
diff --git a/pw_cli/py/pw_cli/toml_config_loader_mixin.py b/pw_cli/py/pw_cli/toml_config_loader_mixin.py
deleted file mode 100644
index bac57ae24..000000000
--- a/pw_cli/py/pw_cli/toml_config_loader_mixin.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright 2022 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.
-"""Toml config file loader mixin."""
-
-from typing import Any, Dict, List
-
-import toml # type: ignore
-
-from pw_cli.yaml_config_loader_mixin import YamlConfigLoaderMixin
-
-
-class TomlConfigLoaderMixin(YamlConfigLoaderMixin):
- """TOML Config file loader mixin.
-
- Use this mixin to load toml file settings and save them into
- ``self._config``. For example:
-
- ::
-
- from pw_cli.toml_config_loader_mixin import TomlConfigLoaderMixin
-
- class PwBloatPrefs(TomlConfigLoaderMixin):
- def __init__(self) -> None:
- self.config_init(
- config_section_title='pw_bloat',
- project_file=Path('$PW_PROJECT_ROOT/.pw_bloat.toml'),
- project_user_file=Path(
- '$PW_PROJECT_ROOT/.pw_bloat.user.toml'),
- user_file=Path('~/.pw_bloat.toml'),
- default_config={},
- environment_var='PW_BLOAT_CONFIG_FILE',
- )
-
- """
-
- def _load_config_from_string( # pylint: disable=no-self-use
- self, file_contents: str
- ) -> List[Dict[Any, Any]]:
- return [toml.loads(file_contents)]
diff --git a/pw_cli/py/pw_cli/yaml_config_loader_mixin.py b/pw_cli/py/pw_cli/yaml_config_loader_mixin.py
deleted file mode 100644
index 4bbf47bef..000000000
--- a/pw_cli/py/pw_cli/yaml_config_loader_mixin.py
+++ /dev/null
@@ -1,166 +0,0 @@
-# Copyright 2022 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.
-"""Yaml config file loader mixin."""
-
-import os
-import logging
-from pathlib import Path
-from typing import Any, Dict, List, Optional, Union
-
-import yaml
-
-_LOG = logging.getLogger(__package__)
-
-
-class MissingConfigTitle(Exception):
- """Exception for when an existing YAML file is missing config_title."""
-
-
-class YamlConfigLoaderMixin:
- """Yaml Config file loader mixin.
-
- Use this mixin to load yaml file settings and save them into
- ``self._config``. For example:
-
- ::
-
- class ConsolePrefs(YamlConfigLoaderMixin):
- def __init__(self) -> None:
- self.config_init(
- config_section_title='pw_console',
- project_file=Path('project_file.yaml'),
- project_user_file=Path('project_user_file.yaml'),
- user_file=Path('~/user_file.yaml'),
- default_config={},
- environment_var='PW_CONSOLE_CONFIG_FILE',
- )
-
- """
-
- def config_init(
- self,
- config_section_title: str,
- project_file: Optional[Union[Path, bool]] = None,
- project_user_file: Optional[Union[Path, bool]] = None,
- user_file: Optional[Union[Path, bool]] = None,
- default_config: Optional[Dict[Any, Any]] = None,
- environment_var: Optional[str] = None,
- ) -> None:
- """Call this to load YAML config files in order of precedence.
-
- The following files are loaded in this order:
- 1. project_file
- 2. project_user_file
- 3. user_file
-
- Lastly, if a valid file path is specified at
- ``os.environ[environment_var]`` then load that file overriding all
- config options.
-
- Args:
- config_section_title: String name of this config section. For
- example: ``pw_console`` or ``pw_watch``. In the YAML file this
- is represented by a ``config_title`` key.
-
- ::
-
- ---
- config_title: pw_console
-
- project_file: Project level config file. This is intended to be a
- file living somewhere under a project folder and is checked into
- the repo. It serves as a base config all developers can inherit
- from.
- project_user_file: User's personal config file for a specific
- project. This can be a file that lives in a project folder that
- is git-ignored and not checked into the repo.
- user_file: A global user based config file. This is typically a file
- in the users home directory and settings here apply to all
- projects.
- default_config: A Python dict representing the base default
- config. This dict will be applied as a starting point before
- loading any yaml files.
- environment_var: The name of an environment variable to check for a
- config file. If a config file exists there it will be loaded on
- top of the default_config ignoring project and user files.
- """
-
- self._config_section_title: str = config_section_title
- self.default_config = default_config if default_config else {}
- self.reset_config()
-
- if project_file and isinstance(project_file, Path):
- self.project_file = Path(
- os.path.expandvars(str(project_file.expanduser()))
- )
- self.load_config_file(self.project_file)
-
- if project_user_file and isinstance(project_user_file, Path):
- self.project_user_file = Path(
- os.path.expandvars(str(project_user_file.expanduser()))
- )
- self.load_config_file(self.project_user_file)
-
- if user_file and isinstance(user_file, Path):
- self.user_file = Path(
- os.path.expandvars(str(user_file.expanduser()))
- )
- self.load_config_file(self.user_file)
-
- # Check for a config file specified by an environment variable.
- if environment_var is None:
- return
- environment_config = os.environ.get(environment_var, None)
- if environment_config:
- env_file_path = Path(environment_config)
- if not env_file_path.is_file():
- raise FileNotFoundError(
- f'Cannot load config file: {env_file_path}'
- )
- self.reset_config()
- self.load_config_file(env_file_path)
-
- def _update_config(self, cfg: Dict[Any, Any]) -> None:
- if cfg is None:
- cfg = {}
- self._config.update(cfg)
-
- def reset_config(self) -> None:
- self._config: Dict[Any, Any] = {}
- self._update_config(self.default_config)
-
- def _load_config_from_string( # pylint: disable=no-self-use
- self, file_contents: str
- ) -> List[Dict[Any, Any]]:
- return list(yaml.safe_load_all(file_contents))
-
- def load_config_file(self, file_path: Path) -> None:
- if not file_path.is_file():
- return
-
- cfgs = self._load_config_from_string(file_path.read_text())
-
- for cfg in cfgs:
- if self._config_section_title in cfg:
- self._update_config(cfg[self._config_section_title])
-
- elif cfg.get('config_title', False) == self._config_section_title:
- self._update_config(cfg)
- else:
- raise MissingConfigTitle(
- '\n\nThe config file "{}" is missing the expected '
- '"config_title: {}" setting.'.format(
- str(file_path), self._config_section_title
- )
- )