diff options
Diffstat (limited to 'pw_cli/py')
-rw-r--r-- | pw_cli/py/BUILD.bazel | 4 | ||||
-rw-r--r-- | pw_cli/py/BUILD.gn | 2 | ||||
-rw-r--r-- | pw_cli/py/pw_cli/arguments.py | 4 | ||||
-rw-r--r-- | pw_cli/py/pw_cli/color.py | 30 | ||||
-rw-r--r-- | pw_cli/py/pw_cli/log.py | 4 | ||||
-rw-r--r-- | pw_cli/py/pw_cli/toml_config_loader_mixin.py | 50 | ||||
-rw-r--r-- | pw_cli/py/pw_cli/yaml_config_loader_mixin.py | 166 |
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 - ) - ) |