This is an automated email from the ASF dual-hosted git repository. potiuk pushed a commit to branch v2-3-test in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 2357959845b99da1e2b1eb4fa95ff1cf102db53b Author: Jarek Potiuk <[email protected]> AuthorDate: Thu Apr 28 17:35:05 2022 +0200 Unify style of communication with the users for Breeze. (#23311) Fixes: #22906 (cherry picked from commit 505af06303d8160c71f6a7abe4792746f640083d) --- BREEZE.rst | 11 ++ .../0011-unified-communication-with-the-users.md | 94 ++++++++++++++++ .../build_image/ci/build_ci_image.py | 35 +++--- .../build_image/ci/build_ci_params.py | 4 +- .../build_image/prod/build_prod_image.py | 30 ++--- .../build_image/prod/build_prod_params.py | 10 +- .../src/airflow_breeze/commands/ci_image_tools.py | 8 +- .../commands/configuration_and_maintenance.py | 125 ++++++++++++--------- .../commands/configure_rich_click.py | 2 +- .../airflow_breeze/commands/custom_param_types.py | 10 +- .../airflow_breeze/commands/developer_commands.py | 10 +- .../commands/production_image_tools.py | 8 +- .../airflow_breeze/commands/release_management.py | 12 +- dev/breeze/src/airflow_breeze/commands/testing.py | 4 +- dev/breeze/src/airflow_breeze/shell/enter_shell.py | 18 +-- .../src/airflow_breeze/shell/shell_params.py | 16 +-- dev/breeze/src/airflow_breeze/utils/cache.py | 8 +- dev/breeze/src/airflow_breeze/utils/console.py | 51 ++++++--- dev/breeze/src/airflow_breeze/utils/constraints.py | 6 +- .../airflow_breeze/utils/docker_command_utils.py | 41 +++---- .../utils/find_newer_dependencies.py | 23 ++-- .../src/airflow_breeze/utils/md5_build_check.py | 14 ++- dev/breeze/src/airflow_breeze/utils/parallel.py | 22 ++-- dev/breeze/src/airflow_breeze/utils/path_utils.py | 8 +- dev/breeze/src/airflow_breeze/utils/pulll_image.py | 26 +++-- .../src/airflow_breeze/utils/python_versions.py | 8 +- dev/breeze/src/airflow_breeze/utils/registry.py | 10 +- dev/breeze/src/airflow_breeze/utils/reinstall.py | 30 ++--- dev/breeze/src/airflow_breeze/utils/run_tests.py | 8 +- dev/breeze/src/airflow_breeze/utils/run_utils.py | 61 +++++----- dev/breeze/src/airflow_breeze/utils/visuals.py | 8 +- dev/breeze/tests/test_docker_command_utils.py | 68 ++++++----- dev/provider_packages/prepare_provider_packages.py | 2 +- docs/build_docs.py | 32 +++--- docs/exts/docs_build/docs_builder.py | 18 +-- docs/exts/docs_build/errors.py | 4 +- docs/exts/docs_build/spelling_checks.py | 4 +- images/breeze/output-config.svg | 3 +- .../ci/pre_commit/pre_commit_check_order_setup.py | 10 +- 39 files changed, 520 insertions(+), 342 deletions(-) diff --git a/BREEZE.rst b/BREEZE.rst index 64ae2ea346..37b47f29cf 100644 --- a/BREEZE.rst +++ b/BREEZE.rst @@ -378,6 +378,17 @@ default settings. You can see which value of the parameters that can be stored persistently in cache marked with >VALUE< in the help of the commands. +Another part of configuration is enabling/disabling cheatsheet, asciiart. The cheatsheet and asciiart can +be disabled - they are "nice looking" and cheatsheet +contains useful information for first time users but eventually you might want to disable both if you +find it repetitive and annoying. + +With the config setting colour-blind-friendly communication for Breeze messages. By default we communicate +with the users about information/errors/warnings/successes via colour-coded messages, but we can switch +it off by passing ``--no-colour`` to config in which case the messages to the user printed by Breeze +will be printed using different schemes (italic/bold/underline) to indicate different kind of messages +rather than colours. + Here is the part of Breeze video which is relevant (note that it refers to the old ``./breeze-legacy`` command but it is very similar to current ``breeze`` command): diff --git a/dev/breeze/doc/adr/0011-unified-communication-with-the-users.md b/dev/breeze/doc/adr/0011-unified-communication-with-the-users.md new file mode 100644 index 0000000000..89f967e350 --- /dev/null +++ b/dev/breeze/doc/adr/0011-unified-communication-with-the-users.md @@ -0,0 +1,94 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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 + + http://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. + --> + +<!-- START doctoc generated TOC please keep comment here to allow auto update --> +<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> +**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + +- [11. Unified communication with the users](#11-unified-communication-with-the-users) + - [Status](#status) + - [Context](#context) + - [Decision](#decision) + - [Consequences](#consequences) + +<!-- END doctoc generated TOC please keep comment here to allow auto update --> + +# 11. Unified communication with the users + +Date: 2022-04-27 + +## Status + +Accepted + +## Context + +We communicate with the user via messages printed in get_console() And we should +make sure we communicate the msssages in a consistent way so that the users would +understand: + +* whether verification of a condition succeeded +* whether a message is just informational that might be used to understand what's going on +* whether there is some important warning to potentially act on +* whether there is a definite error that the user should fix +* instructions how to proceed + +The messages should be: + +* short +* informative +* readable +* actionable + +## Decision + +We are using rich and colours to communicate the type of messages: + +* [success] - to show verification success (green) +* [info] - to present inform users (bright_blue) +* [warning] - to print warning that the user probably should read and act on (bright_yellow) +* [error] - when there is an error that the user should fix (red) +* instructions should be printed without style and default rich rendering should be used + +By default, we map those styles to those colors, but we can change configuration of Breeze to +be colour-blind-friendly by disabling colours in communication via `breeze config --no-colour`. + +When signalling warning or error The communication should not be confusing and +should not contain "noise". It should contain simple - usually one-liner - +information on what's wrong or what the user is warned against, possibly +followed by instructions telling the user what to do. When we are able to +foresee that error will happen, we should print the message only with +explanation, and we should suppress any stack-traces as they are not really +useful for the users. When an error is unexpected, full stack trace should +be written to allow easier investigation of the problem. + +We should also support `--verbose` flag to display all the commands being executed, and +the --dry-run flag to only display commands and not execute the commands. This will allow to +diagnose any problems that the user might have. + +Whenever we print a logically separated message we should add EOL to separate the logical part of the +message as well as when you want to separate the header description from bullet lists (very similar to +what .rst rules are for readability). Whitespace improves readability of communication and messages +separated in sections separated by whitespace and marked with colors are much more readable than the +wall of text without visible structure. + +## Consequences + +Users will get consistent approach when it comes to context and expectations of their reaction for the +messages. Developers will use consistent styles. diff --git a/dev/breeze/src/airflow_breeze/build_image/ci/build_ci_image.py b/dev/breeze/src/airflow_breeze/build_image/ci/build_ci_image.py index 7c1bca1eb1..f511c7ac55 100644 --- a/dev/breeze/src/airflow_breeze/build_image/ci/build_ci_image.py +++ b/dev/breeze/src/airflow_breeze/build_image/ci/build_ci_image.py @@ -28,7 +28,7 @@ from airflow_breeze.build_image.ci.build_ci_params import ( from airflow_breeze.utils.cache import touch_cache_file from airflow_breeze.utils.ci_group import ci_group from airflow_breeze.utils.confirm import Answer, user_confirm -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.docker_command_utils import ( construct_docker_build_command, construct_empty_docker_build_command, @@ -71,9 +71,8 @@ def should_we_run_the_build(build_ci_params: BuildCiParams) -> bool: if is_repo_rebased(build_ci_params.github_repository, build_ci_params.airflow_branch): return True else: - console.print( - "\n[bright_yellow]This might take a lot of time, w" - "e think you should rebase first.[/]\n" + get_console().print( + "\n[warning]This might take a lot of time, w" "e think you should rebase first.[/]\n" ) answer = user_confirm( "But if you really, really want - you can do it", timeout=5, default_answer=Answer.NO @@ -81,25 +80,25 @@ def should_we_run_the_build(build_ci_params: BuildCiParams) -> bool: if answer == Answer.YES: return True else: - console.print( - "[bright_blue]Please rebase your code before continuing.[/]\n" + get_console().print( + "[info]Please rebase your code before continuing.[/]\n" "Check this link to know more " "https://github.com/apache/airflow/blob/main/CONTRIBUTING.rst#id15\n" ) - console.print('[red]Exiting the process[/]\n') + get_console().print('[error]Exiting the process[/]\n') sys.exit(1) elif answer == Answer.NO: instruct_build_image(build_ci_params.python) return False else: # users_status == Answer.QUIT: - console.print('\n[bright_yellow]Quitting the process[/]\n') + get_console().print('\n[warning]Quitting the process[/]\n') sys.exit() except TimeoutOccurred: - console.print('\nTimeout. Considering your response as No\n') + get_console().print('\nTimeout. Considering your response as No\n') instruct_build_image(build_ci_params.python) return False except Exception as e: - console.print(f'\nTerminating the process on {e}') + get_console().print(f'\nTerminating the process on {e}') sys.exit(1) @@ -126,8 +125,8 @@ def build_ci_image( """ fix_group_permissions() if verbose or dry_run: - console.print( - f"\n[bright_blue]Building CI image of airflow from {AIRFLOW_SOURCES_ROOT} " + get_console().print( + f"\n[info]Building CI image of airflow from {AIRFLOW_SOURCES_ROOT} " f"python version: {ci_image_params.python}[/]\n" ) with ci_group( @@ -158,7 +157,7 @@ def build_ci_image( if ci_image_params.empty_image: env = os.environ.copy() env['DOCKER_BUILDKIT'] = "1" - console.print(f"\n[blue]Building empty CI Image for Python {ci_image_params.python}\n") + get_console().print(f"\n[info]Building empty CI Image for Python {ci_image_params.python}\n") cmd = construct_empty_docker_build_command(image_params=ci_image_params) build_result = run_command( cmd, @@ -170,7 +169,7 @@ def build_ci_image( env=env, ) else: - console.print(f"\n[blue]Building CI Image for Python {ci_image_params.python}\n") + get_console().print(f"\n[info]Building CI Image for Python {ci_image_params.python}\n") build_result = run_command( cmd, verbose=verbose, dry_run=dry_run, cwd=AIRFLOW_SOURCES_ROOT, text=True, check=False ) @@ -181,13 +180,13 @@ def build_ci_image( touch_cache_file(f"built_{ci_image_params.python}", root_dir=ci_image_cache_dir) calculate_md5_checksum_for_files(ci_image_params.md5sum_cache_dir, update=True) else: - console.print("[red]Error when building image![/]") + get_console().print("[error]Error when building image![/]") return ( build_result.returncode, f"Image build: {ci_image_params.python}", ) else: - console.print("[blue]Not updating build cache because we are in `dry_run` mode.[/]") + get_console().print("[info]Not updating build cache because we are in `dry_run` mode.[/]") if ci_image_params.push_image: return tag_and_push_image(image_params=ci_image_params, dry_run=dry_run, verbose=verbose) return build_result.returncode, f"Image build: {ci_image_params.python}" @@ -197,8 +196,8 @@ def build_ci_image_in_parallel( verbose: bool, dry_run: bool, parallelism: int, python_version_list: List[str], **kwargs ): """Run CI image builds in parallel.""" - console.print( - f"\n[bright_blue]Running with parallelism = {parallelism} for the images: {python_version_list}:" + get_console().print( + f"\n[info]Running with parallelism = {parallelism} for the images: {python_version_list}:" ) pool = mp.Pool(parallelism) results = [pool.apply_async(build_ci_image, args=(verbose, dry_run, False), kwds=kwargs)] diff --git a/dev/breeze/src/airflow_breeze/build_image/ci/build_ci_params.py b/dev/breeze/src/airflow_breeze/build_image/ci/build_ci_params.py index f726b000f7..da5364d087 100644 --- a/dev/breeze/src/airflow_breeze/build_image/ci/build_ci_params.py +++ b/dev/breeze/src/airflow_breeze/build_image/ci/build_ci_params.py @@ -23,7 +23,7 @@ from typing import List, Optional from airflow_breeze.branch_defaults import AIRFLOW_BRANCH, DEFAULT_AIRFLOW_CONSTRAINTS_BRANCH from airflow_breeze.global_constants import get_airflow_version -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.path_utils import BUILD_CACHE_DIR @@ -149,7 +149,7 @@ class BuildCiParams: return Path(BUILD_CACHE_DIR, self.airflow_branch, self.python, "CI") def print_info(self): - console.print(f"CI Image: {self.airflow_version} Python: {self.python}.") + get_console().print(f"CI Image: {self.airflow_version} Python: {self.python}.") REQUIRED_CI_IMAGE_ARGS = [ diff --git a/dev/breeze/src/airflow_breeze/build_image/prod/build_prod_image.py b/dev/breeze/src/airflow_breeze/build_image/prod/build_prod_image.py index 2caeeb7ef5..967a655899 100644 --- a/dev/breeze/src/airflow_breeze/build_image/prod/build_prod_image.py +++ b/dev/breeze/src/airflow_breeze/build_image/prod/build_prod_image.py @@ -22,7 +22,7 @@ from typing import Tuple from airflow_breeze.build_image.prod.build_prod_params import BuildProdParams from airflow_breeze.utils.ci_group import ci_group -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.docker_command_utils import ( construct_docker_build_command, construct_empty_docker_build_command, @@ -76,7 +76,7 @@ def clean_docker_context_files(verbose: bool, dry_run: bool): Cleans up docker context files folder - leaving only .README.md there. """ if verbose or dry_run: - console.print("[bright_blue]Cleaning docker-context-files[/]") + get_console().print("[info]Cleaning docker-context-files[/]") if dry_run: return with contextlib.suppress(FileNotFoundError): @@ -101,20 +101,20 @@ def check_docker_context_files(install_packages_from_context: bool): ) if number_of_context_files == 0: if install_packages_from_context: - console.print('[bright_yellow]\nERROR! You want to install packages from docker-context-files') - console.print('[bright_yellow]\n but there are no packages to install in this folder.') + get_console().print('[warning]\nERROR! You want to install packages from docker-context-files') + get_console().print('[warning]\n but there are no packages to install in this folder.') sys.exit(1) else: if not install_packages_from_context: - console.print( - '[bright_yellow]\n ERROR! There are some extra files in docker-context-files except README.md' + get_console().print( + '[warning]\n ERROR! There are some extra files in docker-context-files except README.md' ) - console.print('[bright_yellow]\nAnd you did not choose --install-packages-from-context flag') - console.print( - '[bright_yellow]\nThis might result in unnecessary cache invalidation and long build times' + get_console().print('[warning]\nAnd you did not choose --install-packages-from-context flag') + get_console().print( + '[warning]\nThis might result in unnecessary cache invalidation and long build times' ) - console.print( - '[bright_yellow]\nExiting now \ + get_console().print( + '[warning]\nExiting now \ - please restart the command with --cleanup-context switch' ) sys.exit(1) @@ -145,8 +145,8 @@ def build_production_image( """ fix_group_permissions() if verbose or dry_run: - console.print( - f"\n[bright_blue]Building PROD image of airflow from {AIRFLOW_SOURCES_ROOT} " + get_console().print( + f"\n[info]Building PROD image of airflow from {AIRFLOW_SOURCES_ROOT} " f"python version: {prod_image_params.python}[/]\n" ) with ci_group( @@ -168,11 +168,11 @@ def build_production_image( text=True, check=False, ) - console.print(f"\n[blue]Building PROD Image for Python {prod_image_params.python}\n") + get_console().print(f"\n[info]Building PROD Image for Python {prod_image_params.python}\n") if prod_image_params.empty_image: env = os.environ.copy() env['DOCKER_BUILDKIT'] = "1" - console.print(f"\n[blue]Building empty PROD Image for Python {prod_image_params.python}\n") + get_console().print(f"\n[info]Building empty PROD Image for Python {prod_image_params.python}\n") cmd = construct_empty_docker_build_command(image_params=prod_image_params) build_command_result = run_command( cmd, diff --git a/dev/breeze/src/airflow_breeze/build_image/prod/build_prod_params.py b/dev/breeze/src/airflow_breeze/build_image/prod/build_prod_params.py index 50eeca452b..116fae9333 100644 --- a/dev/breeze/src/airflow_breeze/build_image/prod/build_prod_params.py +++ b/dev/breeze/src/airflow_breeze/build_image/prod/build_prod_params.py @@ -31,7 +31,7 @@ from airflow_breeze.global_constants import ( get_airflow_extras, get_airflow_version, ) -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console @dataclass @@ -173,10 +173,10 @@ class BuildProdParams: self.airflow_version = self.install_airflow_reference elif len(self.install_airflow_version) > 0: if not re.match(r'^[0-9\.]+((a|b|rc|alpha|beta|pre)[0-9]+)?$', self.install_airflow_version): - console.print( - f'\n[red]ERROR: Bad value for install-airflow-version:{self.install_airflow_version}' + get_console().print( + f'\n[error]ERROR: Bad value for install-airflow-version:{self.install_airflow_version}' ) - console.print('[red]Only numerical versions allowed for PROD image here !') + get_console().print('[error]Only numerical versions allowed for PROD image here !') sys.exit() extra_build_flags.extend(["--build-arg", "AIRFLOW_INSTALLATION_METHOD=apache-airflow"]) extra_build_flags.extend( @@ -239,7 +239,7 @@ class BuildProdParams: return "https://raw.githubusercontent.com/apache/airflow/main/docs/docker-stack/README.md" def print_info(self): - console.print(f"CI Image: {self.airflow_version} Python: {self.python}.") + get_console().print(f"CI Image: {self.airflow_version} Python: {self.python}.") @property def airflow_pre_cached_pip_packages(self) -> str: diff --git a/dev/breeze/src/airflow_breeze/commands/ci_image_tools.py b/dev/breeze/src/airflow_breeze/commands/ci_image_tools.py index eb7ec5f667..15fd2d52f5 100644 --- a/dev/breeze/src/airflow_breeze/commands/ci_image_tools.py +++ b/dev/breeze/src/airflow_breeze/commands/ci_image_tools.py @@ -66,7 +66,7 @@ from airflow_breeze.commands.common_options import ( from airflow_breeze.commands.main import main from airflow_breeze.utils.ci_group import ci_group from airflow_breeze.utils.confirm import set_forced_answer -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.pulll_image import run_pull_image, run_pull_in_parallel from airflow_breeze.utils.python_versions import get_python_version_list from airflow_breeze.utils.run_tests import verify_an_image @@ -216,7 +216,7 @@ def build_image( verbose=verbose, dry_run=dry_run, with_ci_group=with_ci_group, ci_image_params=ci_image_params ) if return_code != 0: - console.print(f"[red]Error when building image! {info}") + get_console().print(f"[error]Error when building image! {info}") sys.exit(return_code) set_forced_answer(answer) @@ -290,7 +290,7 @@ def pull_image( poll_time=10.0, ) if return_code != 0: - console.print(f"[red]There was an error when pulling CI image: {info}[/]") + get_console().print(f"[error]There was an error when pulling CI image: {info}[/]") sys.exit(return_code) @@ -321,7 +321,7 @@ def verify_image( if image_name is None: build_params = BuildCiParams(python=python, image_tag=image_tag, github_repository=github_repository) image_name = build_params.airflow_image_name_with_tag - console.print(f"[bright_blue]Verifying CI image: {image_name}[/]") + get_console().print(f"[info]Verifying CI image: {image_name}[/]") return_code, info = verify_an_image( image_name=image_name, verbose=verbose, diff --git a/dev/breeze/src/airflow_breeze/commands/configuration_and_maintenance.py b/dev/breeze/src/airflow_breeze/commands/configuration_and_maintenance.py index 153a11b208..a83d24c921 100644 --- a/dev/breeze/src/airflow_breeze/commands/configuration_and_maintenance.py +++ b/dev/breeze/src/airflow_breeze/commands/configuration_and_maintenance.py @@ -41,7 +41,7 @@ from airflow_breeze.global_constants import DEFAULT_PYTHON_MAJOR_MINOR_VERSION, from airflow_breeze.shell.shell_params import ShellParams from airflow_breeze.utils.cache import check_if_cache_exists, delete_cache, touch_cache_file from airflow_breeze.utils.confirm import Answer, set_forced_answer, user_confirm -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.docker_command_utils import ( check_docker_resources, construct_env_variables_docker_compose_command, @@ -109,6 +109,7 @@ CONFIGURATION_AND_MAINTENANCE_PARAMETERS = { "--backend", "--cheatsheet", "--asciiart", + "--colour", ], }, ], @@ -131,12 +132,12 @@ CONFIGURATION_AND_MAINTENANCE_PARAMETERS = { def cleanup(verbose: bool, dry_run: bool, github_repository: str, all: bool, answer: Optional[str]): set_forced_answer(answer) if all: - console.print( - "\n[bright_yellow]Removing cache of parameters, clean up docker cache " + get_console().print( + "\n[info]Removing cache of parameters, clean up docker cache " "and remove locally downloaded images[/]" ) else: - console.print("\n[bright_yellow]Removing cache of parameters, and cleans up docker cache[/]") + get_console().print("[info]Removing cache of parameters, and cleans up docker cache[/]") if all: docker_images_command_to_execute = [ 'docker', @@ -151,10 +152,10 @@ def cleanup(verbose: bool, dry_run: bool, github_repository: str, all: bool, ans ) images = command_result.stdout.splitlines() if command_result and command_result.stdout else [] if images: - console.print("[light_blue]Removing images:[/]") + get_console().print("[light_blue]Removing images:[/]") for image in images: - console.print(f"[light_blue] * {image}[/]") - console.print() + get_console().print(f"[light_blue] * {image}[/]") + get_console().print() docker_rmi_command_to_execute = [ 'docker', 'rmi', @@ -167,15 +168,15 @@ def cleanup(verbose: bool, dry_run: bool, github_repository: str, all: bool, ans elif given_answer == Answer.QUIT: sys.exit(0) else: - console.print("[light_blue]No locally downloaded images to remove[/]\n") - console.print("Pruning docker images") + get_console().print("[light_blue]No locally downloaded images to remove[/]\n") + get_console().print("Pruning docker images") given_answer = user_confirm("Are you sure?", timeout=None) if given_answer == Answer.YES: system_prune_command_to_execute = ['docker', 'system', 'prune'] run_command(system_prune_command_to_execute, verbose=verbose, dry_run=dry_run, check=False) elif given_answer == Answer.QUIT: sys.exit(0) - console.print(f"Removing build cache dir ${BUILD_CACHE_DIR}") + get_console().print(f"Removing build cache dir ${BUILD_CACHE_DIR}") given_answer = user_confirm("Are you sure?", timeout=None) if given_answer == Answer.YES: if not dry_run: @@ -239,14 +240,14 @@ def setup_autocomplete(verbose: bool, dry_run: bool, force: bool, answer: Option detected_shell = os.environ.get('SHELL') detected_shell = None if detected_shell is None else detected_shell.split(os.sep)[-1] if detected_shell not in ['bash', 'zsh', 'fish']: - console.print(f"\n[red] The shell {detected_shell} is not supported for autocomplete![/]\n") + get_console().print(f"\n[error] The shell {detected_shell} is not supported for autocomplete![/]\n") sys.exit(1) - console.print(f"Installing {detected_shell} completion for local user") + get_console().print(f"Installing {detected_shell} completion for local user") autocomplete_path = ( AIRFLOW_SOURCES_ROOT / "dev" / "breeze" / "autocomplete" / f"{NAME}-complete-{detected_shell}.sh" ) - console.print(f"[bright_blue]Activation command script is available here: {autocomplete_path}[/]\n") - console.print(f"[bright_yellow]We need to add above script to your {detected_shell} profile.[/]\n") + get_console().print(f"[info]Activation command script is available here: {autocomplete_path}[/]\n") + get_console().print(f"[info]We need to add above script to your {detected_shell} profile.[/]\n") given_answer = user_confirm("Should we proceed ?", default_answer=Answer.NO, timeout=3) if given_answer == Answer.YES: if detected_shell == 'bash': @@ -261,8 +262,8 @@ def setup_autocomplete(verbose: bool, dry_run: bool, force: bool, answer: Option # Include steps for fish shell script_path = str(Path('~').expanduser() / f'.config/fish/completions/{NAME}.fish') if os.path.exists(script_path) and not force: - console.print( - "\n[bright_yellow]Autocompletion is already setup. Skipping. " + get_console().print( + "\n[warning]Autocompletion is already setup. Skipping. " "You can force autocomplete installation by adding --force/]\n" ) else: @@ -278,7 +279,7 @@ def setup_autocomplete(verbose: bool, dry_run: bool, force: bool, answer: Option command_to_execute = f". {autocomplete_path}" write_to_shell(command_to_execute, dry_run, script_path, force) elif given_answer == Answer.NO: - console.print( + get_console().print( "\nPlease follow the https://click.palletsprojects.com/en/8.1.x/shell-completion/ " "to setup autocompletion for breeze manually if you want to use it.\n" ) @@ -290,20 +291,21 @@ def setup_autocomplete(verbose: bool, dry_run: bool, force: bool, answer: Option @main.command() def version(verbose: bool, python: str): """Print information about version of apache-airflow-breeze.""" - console.print(ASCIIART, style=ASCIIART_STYLE) - console.print(f"\n[bright_blue]Breeze version: {VERSION}[/]") - console.print(f"[bright_blue]Breeze installed from: {get_installation_airflow_sources()}[/]") - console.print(f"[bright_blue]Used Airflow sources : {get_used_airflow_sources()}[/]\n") + + get_console().print(ASCIIART, style=ASCIIART_STYLE) + get_console().print(f"\n[info]Breeze version: {VERSION}[/]") + get_console().print(f"[info]Breeze installed from: {get_installation_airflow_sources()}[/]") + get_console().print(f"[info]Used Airflow sources : {get_used_airflow_sources()}[/]\n") if verbose: - console.print( - f"[bright_blue]Installation sources config hash : " + get_console().print( + f"[info]Installation sources config hash : " f"{get_installation_sources_config_metadata_hash()}[/]" ) - console.print( - f"[bright_blue]Used sources config hash : " f"{get_used_sources_setup_metadata_hash()}[/]" + get_console().print( + f"[info]Used sources config hash : " f"{get_used_sources_setup_metadata_hash()}[/]" ) - console.print( - f"[bright_blue]Package config hash : " f"{(get_package_setup_metadata_hash())}[/]\n" + get_console().print( + f"[info]Package config hash : " f"{(get_package_setup_metadata_hash())}[/]\n" ) @@ -315,6 +317,12 @@ def version(verbose: bool, python: str): @option_mssql_version @click.option('-C/-c', '--cheatsheet/--no-cheatsheet', help="Enable/disable cheatsheet.", default=None) @click.option('-A/-a', '--asciiart/--no-asciiart', help="Enable/disable ASCIIart.", default=None) [email protected]( + '-B/-b', + '--colour/--no-colour', + help="Enable/disable Colour mode (useful for colour blind-friendly communication).", + default=None, +) def change_config( python: str, backend: str, @@ -323,44 +331,56 @@ def change_config( mssql_version: str, cheatsheet: bool, asciiart: bool, + colour: bool, ): """ Show/update configuration (Python, Backend, Cheatsheet, ASCIIART). """ asciiart_file = "suppress_asciiart" cheatsheet_file = "suppress_cheatsheet" + colour_file = "suppress_colour" if asciiart is not None: if asciiart: delete_cache(asciiart_file) - console.print('[bright_blue]Enable ASCIIART![/]') + get_console().print('[info]Enable ASCIIART![/]') else: touch_cache_file(asciiart_file) - console.print('[bright_blue]Disable ASCIIART![/]') + get_console().print('[info]Disable ASCIIART![/]') if cheatsheet is not None: if cheatsheet: delete_cache(cheatsheet_file) - console.print('[bright_blue]Enable Cheatsheet[/]') + get_console().print('[info]Enable Cheatsheet[/]') elif cheatsheet is not None: touch_cache_file(cheatsheet_file) - console.print('[bright_blue]Disable Cheatsheet[/]') + get_console().print('[info]Disable Cheatsheet[/]') + if colour is not None: + if colour: + delete_cache(colour_file) + get_console().print('[info]Enable Colour[/]') + elif colour is not None: + touch_cache_file(colour_file) + get_console().print('[info]Disable Colour[/]') def get_status(file: str): return "disabled" if check_if_cache_exists(file) else "enabled" - console.print() - console.print("[bright_blue]Current configuration:[/]") - console.print() - console.print(f"[bright_blue]* Python: {python}[/]") - console.print(f"[bright_blue]* Backend: {backend}[/]") - console.print() - console.print(f"[bright_blue]* Postgres version: {postgres_version}[/]") - console.print(f"[bright_blue]* MySQL version: {mysql_version}[/]") - console.print(f"[bright_blue]* MsSQL version: {mssql_version}[/]") - console.print() - console.print(f"[bright_blue]* ASCIIART: {get_status(asciiart_file)}[/]") - console.print(f"[bright_blue]* Cheatsheet: {get_status(cheatsheet_file)}[/]") - console.print() + get_console().print() + get_console().print("[info]Current configuration:[/]") + get_console().print() + get_console().print(f"[info]* Python: {python}[/]") + get_console().print(f"[info]* Backend: {backend}[/]") + get_console().print() + get_console().print(f"[info]* Postgres version: {postgres_version}[/]") + get_console().print(f"[info]* MySQL version: {mysql_version}[/]") + get_console().print(f"[info]* MsSQL version: {mssql_version}[/]") + get_console().print() + get_console().print(f"[info]* ASCIIART: {get_status(asciiart_file)}[/]") + get_console().print(f"[info]* Cheatsheet: {get_status(cheatsheet_file)}[/]") + get_console().print() + get_console().print() + get_console().print(f"[info]* Colour: {get_status(colour_file)}[/]") + get_console().print() @main.command(name="free-space", help="Free space for jobs run in CI.") @@ -426,8 +446,8 @@ def write_to_shell(command_to_execute: str, dry_run: bool, script_path: str, for if not skip_check: if BREEZE_COMMENT in script_path_file.read_text(): if not force_setup: - console.print( - "\n[bright_yellow]Autocompletion is already setup. Skipping. " + get_console().print( + "\n[warning]Autocompletion is already setup. Skipping. " "You can force autocomplete installation by adding --force[/]\n" ) return False @@ -436,13 +456,13 @@ def write_to_shell(command_to_execute: str, dry_run: bool, script_path: str, for remove_autogenerated_code(script_path) text = '' if script_path_file.exists(): - console.print(f"\nModifying the {script_path} file!\n") - console.print(f"\nCopy of the original file is held in {script_path}.bak !\n") + get_console().print(f"\nModifying the {script_path} file!\n") + get_console().print(f"\nCopy of the original file is held in {script_path}.bak !\n") if not dry_run: backup(script_path_file) text = script_path_file.read_text() else: - console.print(f"\nCreating the {script_path} file!\n") + get_console().print(f"\nCreating the {script_path} file!\n") if not dry_run: script_path_file.write_text( text @@ -453,10 +473,9 @@ def write_to_shell(command_to_execute: str, dry_run: bool, script_path: str, for + END_LINE ) else: - console.print(f"[bright_blue]The autocomplete script would be added to {script_path}[/]") - console.print( - f"\n[bright_yellow]IMPORTANT!!!! Please exit and re-enter your shell or run:[/]" - f"\n\n source {script_path}\n" + get_console().print(f"[info]The autocomplete script would be added to {script_path}[/]") + get_console().print( + f"\n[warning]Please exit and re-enter your shell or run:[/]" f"\n\n source {script_path}\n" ) return True diff --git a/dev/breeze/src/airflow_breeze/commands/configure_rich_click.py b/dev/breeze/src/airflow_breeze/commands/configure_rich_click.py index 2eeac20db0..1807ad3fb0 100644 --- a/dev/breeze/src/airflow_breeze/commands/configure_rich_click.py +++ b/dev/breeze/src/airflow_breeze/commands/configure_rich_click.py @@ -44,7 +44,7 @@ try: click.rich_click.STYLE_ERRORS_SUGGESTION = "bright_blue italic" click.rich_click.ERRORS_SUGGESTION = "\nTry running the '--help' flag for more information.\n" click.rich_click.ERRORS_EPILOGUE = ( - "\nTo find out more, visit [bright_blue]https://github.com/apache/airflow/blob/main/BREEZE.rst[/]\n" + "\nTo find out more, visit [info]https://github.com/apache/airflow/blob/main/BREEZE.rst[/]\n" ) click.rich_click.OPTION_GROUPS = { **DEVELOPER_PARAMETERS, diff --git a/dev/breeze/src/airflow_breeze/commands/custom_param_types.py b/dev/breeze/src/airflow_breeze/commands/custom_param_types.py index 7a779865f6..4737aa2737 100644 --- a/dev/breeze/src/airflow_breeze/commands/custom_param_types.py +++ b/dev/breeze/src/airflow_breeze/commands/custom_param_types.py @@ -26,7 +26,7 @@ from airflow_breeze.utils.cache import ( read_from_cache_file, write_to_cache_file, ) -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.recording import output_file_for_recording @@ -71,8 +71,8 @@ class CacheableChoice(click.Choice): if isinstance(value, CacheableDefault): is_cached, new_value = read_and_validate_value_from_cache(param_name, value.value) if not is_cached: - console.print( - f"\n[bright_blue]Default value of {param.name} " f"parameter {new_value} used.[/]\n" + get_console().print( + f"\n[info]Default value of {param.name} " f"parameter {new_value} used.[/]\n" ) else: allowed, allowed_values = check_if_values_allowed(param_name, value) @@ -81,8 +81,8 @@ class CacheableChoice(click.Choice): write_to_cache_file(param_name, new_value, check_allowed_values=False) else: new_value = allowed_values[0] - console.print( - f"\n[yellow]The value {value} is not allowed for parameter {param.name}. " + get_console().print( + f"\n[warning]The value {value} is not allowed for parameter {param.name}. " f"Setting default value to {new_value}" ) write_to_cache_file(param_name, new_value, check_allowed_values=False) diff --git a/dev/breeze/src/airflow_breeze/commands/developer_commands.py b/dev/breeze/src/airflow_breeze/commands/developer_commands.py index c909821d38..e44c360b6c 100644 --- a/dev/breeze/src/airflow_breeze/commands/developer_commands.py +++ b/dev/breeze/src/airflow_breeze/commands/developer_commands.py @@ -53,7 +53,7 @@ from airflow_breeze.pre_commit_ids import PRE_COMMIT_LIST from airflow_breeze.shell.enter_shell import enter_shell from airflow_breeze.shell.shell_params import ShellParams from airflow_breeze.utils.confirm import set_forced_answer -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.docker_command_utils import ( construct_env_variables_docker_compose_command, get_extra_docker_flags, @@ -221,8 +221,8 @@ def shell( """Enter breeze.py environment. this is the default command use when no other is selected.""" set_forced_answer(answer) if verbose or dry_run: - console.print("\n[green]Welcome to breeze.py[/]\n") - console.print(f"\n[green]Root of Airflow Sources = {AIRFLOW_SOURCES_ROOT}[/]\n") + get_console().print("\n[success]Welcome to breeze.py[/]\n") + get_console().print(f"\n[success]Root of Airflow Sources = {AIRFLOW_SOURCES_ROOT}[/]\n") enter_shell( verbose=verbose, dry_run=dry_run, @@ -409,7 +409,7 @@ def static_checks( assert_pre_commit_installed(verbose=verbose) command_to_execute = [sys.executable, "-m", "pre_commit", 'run'] if last_commit and commit_ref: - console.print("\n[red]You cannot specify both --last-commit and --commit-ref[/]\n") + get_console().print("\n[error]You cannot specify both --last-commit and --commit-ref[/]\n") sys.exit(1) for single_check in type: command_to_execute.append(single_check) @@ -439,7 +439,7 @@ def static_checks( env=env, ) if static_checks_result.returncode != 0: - console.print("[red]There were errors during pre-commit check. They should be fixed[/]") + get_console().print("[error]There were errors during pre-commit check. They should be fixed[/]") sys.exit(static_checks_result.returncode) diff --git a/dev/breeze/src/airflow_breeze/commands/production_image_tools.py b/dev/breeze/src/airflow_breeze/commands/production_image_tools.py index 06ba3142da..52fd3ec2a3 100644 --- a/dev/breeze/src/airflow_breeze/commands/production_image_tools.py +++ b/dev/breeze/src/airflow_breeze/commands/production_image_tools.py @@ -67,7 +67,7 @@ from airflow_breeze.commands.main import main from airflow_breeze.global_constants import ALLOWED_INSTALLATION_METHODS, DEFAULT_EXTRAS from airflow_breeze.utils.ci_group import ci_group from airflow_breeze.utils.confirm import set_forced_answer -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.pulll_image import run_pull_image, run_pull_in_parallel from airflow_breeze.utils.python_versions import get_python_version_list from airflow_breeze.utils.run_tests import verify_an_image @@ -268,7 +268,7 @@ def build_prod_image( verbose=verbose, dry_run=dry_run, with_ci_group=with_ci_group, prod_image_params=prod_image_params ) if return_code != 0: - console.print(f"[red]Error when building image! {info}") + get_console().print(f"[error]Error when building image! {info}") sys.exit(return_code) set_forced_answer(answer) @@ -344,7 +344,7 @@ def pull_prod_image( poll_time=10.0, ) if return_code != 0: - console.print(f"[red]There was an error when pulling PROD image: {info}[/]") + get_console().print(f"[error]There was an error when pulling PROD image: {info}[/]") sys.exit(return_code) @@ -377,7 +377,7 @@ def verify_prod_image( python=python, image_tag=image_tag, github_repository=github_repository ) image_name = build_params.airflow_image_name_with_tag - console.print(f"[bright_blue]Verifying PROD image: {image_name}[/]") + get_console().print(f"[info]Verifying PROD image: {image_name}[/]") return_code, info = verify_an_image( image_name=image_name, verbose=verbose, diff --git a/dev/breeze/src/airflow_breeze/commands/release_management.py b/dev/breeze/src/airflow_breeze/commands/release_management.py index f9fe3a3948..72e2756878 100644 --- a/dev/breeze/src/airflow_breeze/commands/release_management.py +++ b/dev/breeze/src/airflow_breeze/commands/release_management.py @@ -49,7 +49,7 @@ from airflow_breeze.global_constants import ( from airflow_breeze.shell.shell_params import ShellParams from airflow_breeze.utils.ci_group import ci_group from airflow_breeze.utils.confirm import Answer, set_forced_answer, user_confirm -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.constraints import run_generate_constraints, run_generate_constraints_in_parallel from airflow_breeze.utils.docker_command_utils import ( construct_env_variables_docker_compose_command, @@ -331,8 +331,8 @@ def generate_constraints( ) if given_answer != Answer.YES: if run_in_parallel: - console.print("\n[yellow]Use this command to build the images:[/]\n") - console.print( + get_console().print("\n[info]Use this command to build the images:[/]\n") + get_console().print( f" breeze build-image --run-in-parallel --python-versions '{python_versions}' " f"--upgrade-to-newer-dependencies true\n" ) @@ -340,8 +340,8 @@ def generate_constraints( shell_params = ShellParams( image_tag=image_tag, python=python, github_repository=github_repository, answer=answer ) - console.print("\n[yellow]Use this command to build the image:[/]\n") - console.print( + get_console().print("\n[info]Use this command to build the image:[/]\n") + get_console().print( f" breeze build-image --python'{shell_params.python}' " f"--upgrade-to-newer-dependencies true\n" ) @@ -375,7 +375,7 @@ def generate_constraints( generate_constraints_mode=generate_constraints_mode, ) if return_code != 0: - console.print(f"[red]There was an error when generating constraints: {info}[/]") + get_console().print(f"[error]There was an error when generating constraints: {info}[/]") sys.exit(return_code) diff --git a/dev/breeze/src/airflow_breeze/commands/testing.py b/dev/breeze/src/airflow_breeze/commands/testing.py index df124749c4..456544b57f 100644 --- a/dev/breeze/src/airflow_breeze/commands/testing.py +++ b/dev/breeze/src/airflow_breeze/commands/testing.py @@ -30,7 +30,7 @@ from airflow_breeze.commands.common_options import ( option_verbose, ) from airflow_breeze.commands.main import main -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.run_tests import run_docker_compose_tests TESTING_COMMANDS = { @@ -83,7 +83,7 @@ def docker_compose_tests( python=python, image_tag=image_tag, github_repository=github_repository ) image_name = build_params.airflow_image_name_with_tag - console.print(f"[bright_blue]Running docker-compose with PROD image: {image_name}[/]") + get_console().print(f"[info]Running docker-compose with PROD image: {image_name}[/]") return_code, info = run_docker_compose_tests( image_name=image_name, verbose=verbose, diff --git a/dev/breeze/src/airflow_breeze/shell/enter_shell.py b/dev/breeze/src/airflow_breeze/shell/enter_shell.py index 933f85ca4d..51294d55bb 100644 --- a/dev/breeze/src/airflow_breeze/shell/enter_shell.py +++ b/dev/breeze/src/airflow_breeze/shell/enter_shell.py @@ -29,7 +29,7 @@ from airflow_breeze.utils.cache import ( read_from_cache_file, write_to_cache_file, ) -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.docker_command_utils import ( SOURCE_OF_DEFAULT_VALUES_FOR_VARIABLES, VARIABLES_IN_CACHE, @@ -83,18 +83,18 @@ def enter_shell(**kwargs) -> Union[subprocess.CompletedProcess, subprocess.Calle verbose = kwargs['verbose'] dry_run = kwargs['dry_run'] if not check_docker_is_running(verbose): - console.print( - '[red]Docker is not running.[/]\n' - '[bright_yellow]Please make sure Docker is installed and running.[/]' + get_console().print( + '[error]Docker is not running.[/]\n' + '[warning]Please make sure Docker is installed and running.[/]' ) sys.exit(1) check_docker_version(verbose) check_docker_compose_version(verbose) updated_kwargs = synchronize_cached_params(kwargs) if read_from_cache_file('suppress_asciiart') is None: - console.print(ASCIIART, style=ASCIIART_STYLE) + get_console().print(ASCIIART, style=ASCIIART_STYLE) if read_from_cache_file('suppress_cheatsheet') is None: - console.print(CHEATSHEET, style=CHEATSHEET_STYLE) + get_console().print(CHEATSHEET, style=CHEATSHEET_STYLE) enter_shell_params = ShellParams(**filter_out_none(**updated_kwargs)) return run_shell_with_build_image_checks(verbose, dry_run, enter_shell_params) @@ -122,10 +122,10 @@ def run_shell_with_build_image_checks( ) ci_image_params = BuildCiParams(python=shell_params.python, upgrade_to_newer_dependencies="false") if build_ci_image_check_cache.exists(): - console.print(f'[bright_blue]{shell_params.the_image_type} image already built locally.[/]') + get_console().print(f'[info]{shell_params.the_image_type} image already built locally.[/]') else: - console.print( - f'[bright_yellow]{shell_params.the_image_type} image not built locally. ' f'Forcing build.[/]' + get_console().print( + f'[warning]{shell_params.the_image_type} image not built locally. Forcing build.[/]' ) ci_image_params.force_build = True diff --git a/dev/breeze/src/airflow_breeze/shell/shell_params.py b/dev/breeze/src/airflow_breeze/shell/shell_params.py index eb4ae34a7a..7d7f1daf53 100644 --- a/dev/breeze/src/airflow_breeze/shell/shell_params.py +++ b/dev/breeze/src/airflow_breeze/shell/shell_params.py @@ -31,7 +31,7 @@ from airflow_breeze.global_constants import ( MOUNT_SELECTED, get_airflow_version, ) -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.path_utils import AIRFLOW_SOURCES_ROOT, BUILD_CACHE_DIR, SCRIPTS_CI_DIR from airflow_breeze.utils.run_utils import get_filesystem_type, run_command @@ -143,13 +143,13 @@ class ShellParams: return sqlite_url def print_badge_info(self): - console.print(f'Use {self.the_image_type} image') - console.print(f'Branch Name: {self.airflow_branch}') - console.print(f'Docker Image: {self.airflow_image_name_with_tag}') - console.print(f'Airflow source version:{self.airflow_version}') - console.print(f'Python Version: {self.python}') - console.print(f'Backend: {self.backend} {self.backend_version}') - console.print(f'Airflow used at runtime: {self.use_airflow_version}') + get_console().print(f'Use {self.the_image_type} image') + get_console().print(f'Branch Name: {self.airflow_branch}') + get_console().print(f'Docker Image: {self.airflow_image_name_with_tag}') + get_console().print(f'Airflow source version:{self.airflow_version}') + get_console().print(f'Python Version: {self.python}') + get_console().print(f'Backend: {self.backend} {self.backend_version}') + get_console().print(f'Airflow used at runtime: {self.use_airflow_version}') @property def compose_files(self): diff --git a/dev/breeze/src/airflow_breeze/utils/cache.py b/dev/breeze/src/airflow_breeze/utils/cache.py index 2319ee4505..19b0fae0bd 100644 --- a/dev/breeze/src/airflow_breeze/utils/cache.py +++ b/dev/breeze/src/airflow_breeze/utils/cache.py @@ -27,7 +27,7 @@ from pathlib import Path from typing import Any, List, Optional, Tuple from airflow_breeze import global_constants -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.path_utils import BUILD_CACHE_DIR @@ -64,9 +64,9 @@ def write_to_cache_file(param_name: str, param_value: str, check_allowed_values: cache_path.parent.mkdir(parents=True, exist_ok=True) cache_path.write_text(param_value) else: - console.print(f'[cyan]You have sent the {param_value} for {param_name}') - console.print(f'[cyan]Allowed value for the {param_name} are {allowed_values}') - console.print('[cyan]Provide one of the supported params. Write to cache dir failed') + get_console().print(f'[cyan]You have sent the {param_value} for {param_name}') + get_console().print(f'[cyan]Allowed value for the {param_name} are {allowed_values}') + get_console().print('[cyan]Provide one of the supported params. Write to cache dir failed') sys.exit(1) diff --git a/dev/breeze/src/airflow_breeze/utils/console.py b/dev/breeze/src/airflow_breeze/utils/console.py index ca5a4a3096..9a14d91eae 100644 --- a/dev/breeze/src/airflow_breeze/utils/console.py +++ b/dev/breeze/src/airflow_breeze/utils/console.py @@ -19,24 +19,49 @@ Console used by all processes. We are forcing colors and terminal output as Bree to be only run in CI or real development terminal - in both cases we want to have colors on. """ import os +from functools import lru_cache -try: - from rich.console import Console - from rich.theme import Theme +from rich.console import Console +from rich.theme import Theme - recording_width = os.environ.get("RECORD_BREEZE_WIDTH") - recording_file = os.environ.get("RECORD_BREEZE_OUTPUT_FILE") +recording_width = os.environ.get("RECORD_BREEZE_WIDTH") +recording_file = os.environ.get("RECORD_BREEZE_OUTPUT_FILE") - custom_theme = Theme({"info": "blue", "warning": "magenta", "error": "red"}) - console = Console( + +def get_theme() -> Theme: + try: + from airflow_breeze.utils.cache import read_from_cache_file + + if read_from_cache_file('suppress_colour') is not None: + return Theme( + { + "success": "bold italic", + "info": "bold", + "warning": "italic", + "error": "italic underline", + } + ) + except ImportError: + # sometimes we might want to use console before the cache folder is determined + # and in this case we will get an import error due to partial initialization. + # in this case we switch to default theme + pass + return Theme( + { + "success": "green", + "info": "bright_blue", + "warning": "bright_yellow", + "error": "red", + } + ) + + +@lru_cache(maxsize=None) +def get_console() -> Console: + return Console( force_terminal=True, color_system="standard", width=180 if not recording_width else int(recording_width), - theme=custom_theme, + theme=get_theme(), record=True if recording_file else False, ) - -except ImportError: - # We handle the ImportError so that autocomplete works with just click installed - custom_theme = None # type: ignore[assignment] - console = None # type: ignore[assignment] diff --git a/dev/breeze/src/airflow_breeze/utils/constraints.py b/dev/breeze/src/airflow_breeze/utils/constraints.py index e8b28ca7dd..779b0d4924 100644 --- a/dev/breeze/src/airflow_breeze/utils/constraints.py +++ b/dev/breeze/src/airflow_breeze/utils/constraints.py @@ -19,7 +19,7 @@ import multiprocessing as mp from typing import List, Tuple from airflow_breeze.shell.shell_params import ShellParams -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.docker_command_utils import ( construct_env_variables_docker_compose_command, get_extra_docker_flags, @@ -63,8 +63,8 @@ def run_generate_constraints_in_parallel( verbose: bool, ): """Run generate constraints in parallel""" - console.print( - f"\n[bright_blue]Generating constraints with parallelism = {parallelism} " + get_console().print( + f"\n[info]Generating constraints with parallelism = {parallelism} " f"for the constraints: {python_version_list}[/]" ) pool = mp.Pool(parallelism) diff --git a/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py b/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py index b6a0c7f20f..4598a6ce97 100644 --- a/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py +++ b/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py @@ -51,7 +51,7 @@ from airflow_breeze.global_constants import ( SSH_PORT, WEBSERVER_HOST_PORT, ) -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.run_utils import commit_sha, prepare_build_command, run_command NECESSARY_HOST_VOLUMES = [ @@ -101,7 +101,7 @@ def get_extra_docker_flags(mount_sources: str) -> List[str]: for flag in NECESSARY_HOST_VOLUMES: extra_docker_flags.extend(["-v", str(AIRFLOW_SOURCES_ROOT) + flag]) else: # none - console.print('[bright_blue]Skip mounting host volumes to Docker[/]') + get_console().print('[info]Skip mounting host volumes to Docker[/]') extra_docker_flags.extend(["-v", f"{AIRFLOW_SOURCES_ROOT}/files:/files"]) extra_docker_flags.extend(["-v", f"{AIRFLOW_SOURCES_ROOT}/dist:/dist"]) extra_docker_flags.extend(["--rm"]) @@ -159,8 +159,10 @@ def check_docker_permission_denied(verbose) -> bool: if command_result.returncode != 0: permission_denied = True if command_result.stdout and 'Got permission denied while trying to connect' in command_result.stdout: - console.print('ERROR: You have `permission denied` error when trying to communicate with docker.') - console.print( + get_console().print( + 'ERROR: You have `permission denied` error when trying to communicate with docker.' + ) + get_console().print( 'Most likely you need to add your user to `docker` group: \ https://docs.docker.com/ engine/install/linux-postinstall/ .' ) @@ -215,20 +217,21 @@ def check_docker_version(verbose: bool): if docker_version_result.returncode == 0: docker_version = docker_version_result.stdout.strip() if docker_version == '': - console.print( + get_console().print( f""" -[yellow]Your version of docker is unknown. If the scripts fail, please make sure to[/] -[yellow]install docker at least: {MIN_DOCKER_VERSION} version.[/] +[warning]Your version of docker is unknown. If the scripts fail, please make sure to[/] +[warning]install docker at least: {MIN_DOCKER_VERSION} version.[/] """ ) else: good_version = compare_version(docker_version, MIN_DOCKER_VERSION) if good_version: - console.print(f'[green]Good version of Docker: {docker_version}.[/]') + get_console().print(f'[success]Good version of Docker: {docker_version}.[/]') else: - console.print( + get_console().print( f""" -[yellow]Your version of docker is too old:{docker_version}. Please upgrade to at least {MIN_DOCKER_VERSION}[/] +[warning]Your version of docker is too old:{docker_version}. +Please upgrade to at least {MIN_DOCKER_VERSION}[/] """ ) @@ -257,24 +260,24 @@ def check_docker_compose_version(verbose: bool): version = '.'.join(version_extracted.groups()) good_version = compare_version(version, MIN_DOCKER_COMPOSE_VERSION) if good_version: - console.print(f'[green]Good version of docker-compose: {version}[/]') + get_console().print(f'[success]Good version of docker-compose: {version}[/]') else: - console.print( + get_console().print( f""" -[yellow]You have too old version of docker-compose: {version}! At least 1.29 is needed! Please upgrade! +[warning]You have too old version of docker-compose: {version}! At least 1.29 is needed! Please upgrade! """ ) - console.print( + get_console().print( """ See https://docs.docker.com/compose/install/ for instructions. Make sure docker-compose you install is first on the PATH variable of yours. """ ) else: - console.print( + get_console().print( """ -[yellow]Unknown docker-compose version. At least 1.29 is needed![/] -[yellow]If Breeze fails upgrade to latest available docker-compose version.[/] +[warning]Unknown docker-compose version. At least 1.29 is needed![/] +[warning]If Breeze fails upgrade to latest available docker-compose version.[/] """ ) @@ -376,8 +379,8 @@ def tag_and_push_image( :param verbose: whethere we produce verbose output :return: """ - console.print( - f"[blue]Tagging and pushing the {image_params.airflow_image_name} as " + get_console().print( + f"[info]Tagging and pushing the {image_params.airflow_image_name} as " f"{image_params.airflow_image_name_with_tag}.[/]" ) cmd = construct_docker_tag_command(image_params) diff --git a/dev/breeze/src/airflow_breeze/utils/find_newer_dependencies.py b/dev/breeze/src/airflow_breeze/utils/find_newer_dependencies.py index 17d577a090..f4c37d9f22 100644 --- a/dev/breeze/src/airflow_breeze/utils/find_newer_dependencies.py +++ b/dev/breeze/src/airflow_breeze/utils/find_newer_dependencies.py @@ -32,10 +32,9 @@ import json from datetime import timedelta from typing import Any, Dict, List, Tuple -from rich.console import Console from rich.progress import Progress -console = Console(width=400, color_system="standard") +from airflow_breeze.utils.console import get_console def find_newer_dependencies( @@ -58,12 +57,12 @@ def find_newer_dependencies( min_date = (pendulum.now(tz=tz) - timedelta(days=max_age)).replace( hour=0, minute=0, second=0, microsecond=0 ) - console.print( - "\n[bright_yellow]Those are possible candidates that broke current " + get_console().print( + "\n[info]Those are possible candidates that broke current " "`pip` resolution mechanisms by falling back to long backtracking[/]\n" ) - console.print(f"\n[bright_yellow]We are limiting to packages updated after {min_date} ({timezone})[/]\n") - with Progress(console=console) as progress: + get_console().print(f"\n[info]We are limiting to packages updated after {min_date} ({timezone})[/]\n") + with Progress(console=get_console()) as progress: task = progress.add_task(f"Processing {count_packages} packages.", total=count_packages) for package_line in package_lines: package, _, constraints_package_version_string = package_line.split("=") @@ -79,17 +78,17 @@ def find_newer_dependencies( constrained_packages[package] = constraints_package_version progress.advance(task) progress.refresh() - console.print( - "\n[bright_yellow]If you see long running builds with `pip` backtracking, you should follow[/]" + get_console().print( + "\n[warning]If you see long running builds with `pip` backtracking, you should follow[/]" ) - console.print( - "[bright_yellow]https://github.com/apache/airflow/blob/main/dev/TRACKING_BACKTRACKING_ISSUES.md[/]\n" + get_console().print( + "[warning]https://github.com/apache/airflow/blob/main/dev/TRACKING_BACKTRACKING_ISSUES.md[/]\n" ) constraint_string = "" for package, constrained_version in constrained_packages.items(): constraint_string += f' "{package}=={constrained_version}"' - console.print("[bright_yellow]Use the following pip install command (see the doc above for details)\n") - console.print( + get_console().print("[info]Use the following pip install command (see the doc above for details)\n") + get_console().print( 'pip install ".[devel_all]" --upgrade --upgrade-strategy eager ' '"dill<0.3.3" "certifi<2021.0.0" "google-ads<14.0.1"' + constraint_string, markup=False, diff --git a/dev/breeze/src/airflow_breeze/utils/md5_build_check.py b/dev/breeze/src/airflow_breeze/utils/md5_build_check.py index 5d445a207f..d0933e3c2c 100644 --- a/dev/breeze/src/airflow_breeze/utils/md5_build_check.py +++ b/dev/breeze/src/airflow_breeze/utils/md5_build_check.py @@ -22,7 +22,7 @@ from pathlib import Path from typing import List, Tuple from airflow_breeze.global_constants import FILES_FOR_REBUILD_CHECK -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.path_utils import AIRFLOW_SOURCES_ROOT @@ -96,15 +96,17 @@ def md5sum_check_if_build_is_needed(md5sum_cache_dir: Path) -> bool: build_needed = False modified_files, not_modified_files = calculate_md5_checksum_for_files(md5sum_cache_dir, update=False) if len(modified_files) > 0: - console.print( - '[bright_yellow]The following files are modified since last time image was built: [/]\n\n' + get_console().print( + '[warning]The following files are modified since last time image was built: [/]\n\n' ) for file in modified_files: - console.print(f" * [bright_blue]{file}[/]") - console.print('\n[bright_yellow]Likely CI image needs rebuild[/]\n') + get_console().print(f" * [info]{file}[/]") + get_console().print('\n[warning]Likely CI image needs rebuild[/]\n') build_needed = True else: - console.print('Docker image build is not needed for CI build as no important files are changed!') + get_console().print( + 'Docker image build is not needed for CI build as no important files are changed!' + ) return build_needed diff --git a/dev/breeze/src/airflow_breeze/utils/parallel.py b/dev/breeze/src/airflow_breeze/utils/parallel.py index 565a1a52c9..211824d019 100644 --- a/dev/breeze/src/airflow_breeze/utils/parallel.py +++ b/dev/breeze/src/airflow_breeze/utils/parallel.py @@ -20,7 +20,7 @@ import time from multiprocessing.pool import ApplyResult from typing import List -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console def print_async_summary(completed_list: List[ApplyResult]) -> None: @@ -29,14 +29,14 @@ def print_async_summary(completed_list: List[ApplyResult]) -> None: :param completed_list: list of completed async results. """ completed_list.sort(key=lambda x: x.get()[1]) - console.print() + get_console().print() for result in completed_list: return_code, info = result.get() if return_code != 0: - console.print(f"[red]NOK[/] for {info}: Return code: {return_code}.") + get_console().print(f"[error]NOK[/] for {info}: Return code: {return_code}.") else: - console.print(f"[green]OK [/] for {info}.") - console.print() + get_console().print(f"[success]OK [/] for {info}.") + get_console().print() def get_completed_result_list(results: List[ApplyResult]) -> List[ApplyResult]: @@ -57,16 +57,16 @@ def check_async_run_results(results: List[ApplyResult], poll_time: float = 0.2): current_completed_number = len(completed_list) if current_completed_number != completed_number: completed_number = current_completed_number - console.print( - f"\n[bright_blue]Completed {completed_number} out of {total_number_of_results} " + get_console().print( + f"\n[info]Completed {completed_number} out of {total_number_of_results} " f"({int(100*completed_number/total_number_of_results)}%).[/]\n" ) print_async_summary(completed_list) time.sleep(poll_time) completed_list = get_completed_result_list(results) completed_number = len(completed_list) - console.print( - f"\n[bright_blue]Completed {completed_number} out of {total_number_of_results} " + get_console().print( + f"\n[info]Completed {completed_number} out of {total_number_of_results} " f"({int(100*completed_number/total_number_of_results)}%).[/]\n" ) print_async_summary(completed_list) @@ -75,7 +75,7 @@ def check_async_run_results(results: List[ApplyResult], poll_time: float = 0.2): if result.get()[0] != 0: errors = True if errors: - console.print("\n[red]There were errors when running some tasks. Quitting.[/]\n") + get_console().print("\n[error]There were errors when running some tasks. Quitting.[/]\n") sys.exit(1) else: - console.print("\n[green]All images are OK.[/]\n") + get_console().print("\n[success]All images are OK.[/]\n") diff --git a/dev/breeze/src/airflow_breeze/utils/path_utils.py b/dev/breeze/src/airflow_breeze/utils/path_utils.py index b61fb59e20..d3003305f8 100644 --- a/dev/breeze/src/airflow_breeze/utils/path_utils.py +++ b/dev/breeze/src/airflow_breeze/utils/path_utils.py @@ -26,7 +26,7 @@ from pathlib import Path from typing import Optional from airflow_breeze import NAME -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.reinstall import ( ask_to_reinstall_breeze, warn_dependencies_changed, @@ -200,9 +200,9 @@ def find_airflow_sources_root_to_operate_on() -> Path: """ installation_airflow_sources = get_installation_airflow_sources() if installation_airflow_sources is None and not skip_upgrade_check(): - console.print( - "\n[red]Breeze should only be installed with -e flag[/]\n\n" - "[bright_yellow]Please go to Airflow sources and run[/]\n\n" + get_console().print( + "\n[error]Breeze should only be installed with -e flag[/]\n\n" + "[warning]Please go to Airflow sources and run[/]\n\n" f" {NAME} self-upgrade --force\n" ) sys.exit(1) diff --git a/dev/breeze/src/airflow_breeze/utils/pulll_image.py b/dev/breeze/src/airflow_breeze/utils/pulll_image.py index a60a3b15e2..357fa1b77e 100644 --- a/dev/breeze/src/airflow_breeze/utils/pulll_image.py +++ b/dev/breeze/src/airflow_breeze/utils/pulll_image.py @@ -21,7 +21,7 @@ from typing import List, Tuple, Union from airflow_breeze.build_image.ci.build_ci_params import BuildCiParams from airflow_breeze.build_image.prod.build_prod_params import BuildProdParams -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.parallel import check_async_run_results from airflow_breeze.utils.run_tests import verify_an_image from airflow_breeze.utils.run_utils import run_command @@ -39,8 +39,8 @@ def run_pull_in_parallel( extra_pytest_args: Tuple, ): """Run image pull in parallel""" - console.print( - f"\n[bright_blue]Pulling with parallelism = {parallelism} for the images: {python_version_list}:" + get_console().print( + f"\n[info]Pulling with parallelism = {parallelism} for the images: {python_version_list}:" ) pool = mp.Pool(parallelism) poll_time = 10.0 @@ -89,8 +89,8 @@ def run_pull_image( :param poll_time: what's the polling time between checks if images are there :return: Tuple of return code and description of the image pulled """ - console.print( - f"\n[bright_blue]Pulling {image_params.the_image_type} image of airflow python version: " + get_console().print( + f"\n[info]Pulling {image_params.the_image_type} image of airflow python version: " f"{image_params.python} image: {image_params.airflow_image_name_with_tag} " f"with wait for image: {wait_for_image}[/]\n" ) @@ -115,10 +115,12 @@ def run_pull_image( if command_result.returncode == 0: image_size = int(command_result.stdout.strip()) if image_size == 0: - console.print("\n[red]The image size was 0 - image creation failed.[/]\n") + get_console().print("\n[error]The image size was 0 - image creation failed.[/]\n") return 1, f"Image Python {image_params.python}" else: - console.print("\n[red]There was an error pulling the size of the image. Failing.[/]\n") + get_console().print( + "\n[error]There was an error pulling the size of the image. Failing.[/]\n" + ) return ( command_result.returncode, f"Image Python {image_params.python}", @@ -139,11 +141,13 @@ def run_pull_image( return command_result.returncode, f"Image Python {image_params.python}" if wait_for_image: if verbose or dry_run: - console.print(f"\n[bright_blue]Waiting for {poll_time} seconds.[/]\n") + get_console().print(f"\n[info]Waiting for {poll_time} seconds.[/]\n") time.sleep(poll_time) continue else: - console.print(f"\n[red]There was an error pulling the image {image_params.python}. Failing.[/]\n") + get_console().print( + f"\n[error]There was an error pulling the image {image_params.python}. Failing.[/]\n" + ) return command_result.returncode, f"Image Python {image_params.python}" @@ -160,7 +164,9 @@ def run_pull_and_verify_image( image_params, dry_run, verbose, wait_for_image, tag_as_latest, poll_time ) if return_code != 0: - console.print(f"\n[red]Not running verification for {image_params.python} as pulling failed.[/]\n") + get_console().print( + f"\n[error]Not running verification for {image_params.python} as pulling failed.[/]\n" + ) return verify_an_image( image_name=image_params.airflow_image_name_with_tag, image_type=image_params.the_image_type, diff --git a/dev/breeze/src/airflow_breeze/utils/python_versions.py b/dev/breeze/src/airflow_breeze/utils/python_versions.py index e3e7523454..658d2a6958 100644 --- a/dev/breeze/src/airflow_breeze/utils/python_versions.py +++ b/dev/breeze/src/airflow_breeze/utils/python_versions.py @@ -19,7 +19,7 @@ import sys from typing import List from airflow_breeze.global_constants import ALLOWED_PYTHON_MAJOR_MINOR_VERSIONS -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console def get_python_version_list(python_versions: str) -> List[str]: @@ -32,10 +32,12 @@ def get_python_version_list(python_versions: str) -> List[str]: errors = False for python in python_version_list: if python not in ALLOWED_PYTHON_MAJOR_MINOR_VERSIONS: - console.print(f"[red]The Python version {python} passed in {python_versions} is wrong.[/]") + get_console().print( + f"[error]The Python version {python} passed in {python_versions} is wrong.[/]" + ) errors = True if errors: - console.print( + get_console().print( f"\nSome of the Python versions passed are not in the " f"list: {ALLOWED_PYTHON_MAJOR_MINOR_VERSIONS}. Quitting.\n" ) diff --git a/dev/breeze/src/airflow_breeze/utils/registry.py b/dev/breeze/src/airflow_breeze/utils/registry.py index 4eac7be01a..7c2e8a6fdb 100644 --- a/dev/breeze/src/airflow_breeze/utils/registry.py +++ b/dev/breeze/src/airflow_breeze/utils/registry.py @@ -20,7 +20,7 @@ from typing import Tuple, Union from airflow_breeze.build_image.ci.build_ci_params import BuildCiParams from airflow_breeze.build_image.prod.build_prod_params import BuildProdParams -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.run_utils import run_command @@ -36,10 +36,10 @@ def login_to_docker_registry( """ if os.environ.get("CI"): if len(image_params.github_token) == 0: - console.print("\n[bright_blue]Skip logging in to GitHub Registry. No Token available!") + get_console().print("\n[info]Skip logging in to GitHub Registry. No Token available!") elif image_params.login_to_github_registry != "true": - console.print( - "\n[bright_blue]Skip logging in to GitHub Registry.\ + get_console().print( + "\n[info]Skip logging in to GitHub Registry.\ LOGIN_TO_GITHUB_REGISTRY is set as false" ) elif len(image_params.github_token) > 0: @@ -60,5 +60,5 @@ def login_to_docker_registry( ) return command_result.returncode, "Docker login" else: - console.print('\n[bright_blue]Skip Login to GitHub Container Registry as token is missing') + get_console().print('\n[info]Skip Login to GitHub Container Registry as token is missing') return 0, "Docker login skipped" diff --git a/dev/breeze/src/airflow_breeze/utils/reinstall.py b/dev/breeze/src/airflow_breeze/utils/reinstall.py index 7854fc9474..ca869fd643 100644 --- a/dev/breeze/src/airflow_breeze/utils/reinstall.py +++ b/dev/breeze/src/airflow_breeze/utils/reinstall.py @@ -21,7 +21,7 @@ from pathlib import Path from airflow_breeze import NAME from airflow_breeze.utils.confirm import Answer, user_confirm -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console def reinstall_breeze(breeze_sources: Path): @@ -32,11 +32,11 @@ def reinstall_breeze(breeze_sources: Path): # Note that we cannot use `pipx upgrade` here because we sometimes install # Breeze from different sources than originally installed (i.e. when we reinstall airflow # From the current directory. - console.print(f"\n[bright_blue]Reinstalling Breeze from {breeze_sources}\n") + get_console().print(f"\n[info]Reinstalling Breeze from {breeze_sources}\n") subprocess.check_call(["pipx", "install", "-e", str(breeze_sources), "--force"]) - console.print( - f"\n[bright_blue]Breeze has been reinstalled from {breeze_sources}. Exiting now.[/]\n\n" - f"[bright_yellow]Please run your command again[/]\n" + get_console().print( + f"\n[info]Breeze has been reinstalled from {breeze_sources}. Exiting now.[/]\n\n" + f"[warning]Please run your command again[/]\n" ) sys.exit(0) @@ -58,30 +58,30 @@ def ask_to_reinstall_breeze(breeze_sources: Path): def warn_non_editable(): - console.print( - "\n[red]Breeze is installed in a wrong way.[/]\n" - "\n[red]It should only be installed in editable mode[/]\n\n" - "[bright_yellow]Please go to Airflow sources and run[/]\n\n" + get_console().print( + "\n[error]Breeze is installed in a wrong way.[/]\n" + "\n[error]It should only be installed in editable mode[/]\n\n" + "[info]Please go to Airflow sources and run[/]\n\n" f" {NAME} self-upgrade --force --use-current-airflow-sources\n" ) def warn_different_location(installation_airflow_sources: Path, current_airflow_sources: Path): - console.print( - f"\n[bright_yellow]WARNING! Breeze was installed from " + get_console().print( + f"\n[warning]Breeze was installed from " f"different location![/]\n\n" f"Breeze installed from : {installation_airflow_sources}\n" f"Current Airflow sources : {current_airflow_sources}\n\n" - f"[bright_yellow]This might cause various problems!![/]\n\n" + f"[warning]This might cause various problems!![/]\n\n" f"If you experience problems - reinstall Breeze with:\n\n" f" {NAME} self-upgrade --force --use-current-airflow-sources\n\n" ) def warn_dependencies_changed(): - console.print( - f"\n[bright_yellow]WARNING! Breeze dependencies changed since the installation![/]\n\n" - f"[bright_yellow]This might cause various problems!![/]\n\n" + get_console().print( + f"\n[warning]Breeze dependencies changed since the installation![/]\n\n" + f"[warning]This might cause various problems!![/]\n\n" f"If you experience problems - reinstall Breeze with:\n\n" f" {NAME} self-upgrade --force\n\n" ) diff --git a/dev/breeze/src/airflow_breeze/utils/run_tests.py b/dev/breeze/src/airflow_breeze/utils/run_tests.py index b8b0a2276f..63c507afe4 100644 --- a/dev/breeze/src/airflow_breeze/utils/run_tests.py +++ b/dev/breeze/src/airflow_breeze/utils/run_tests.py @@ -20,7 +20,7 @@ import sys from subprocess import DEVNULL from typing import Tuple -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.path_utils import AIRFLOW_SOURCES_ROOT from airflow_breeze.utils.run_utils import run_command @@ -32,7 +32,9 @@ def verify_an_image( ["docker", "inspect", image_name], dry_run=dry_run, verbose=verbose, check=False, stdout=DEVNULL ) if command_result.returncode != 0: - console.print(f"[red]Error when inspecting {image_type} image: {command_result.returncode}[/]") + get_console().print( + f"[error]Error when inspecting {image_type} image: {command_result.returncode}[/]" + ) return command_result.returncode, f"Testing {image_type} python {image_name}" pytest_args = ("-n", "auto", "--color=yes") if image_type == 'PROD': @@ -58,7 +60,7 @@ def run_docker_compose_tests( ["docker", "inspect", image_name], dry_run=dry_run, verbose=verbose, check=False, stdout=DEVNULL ) if command_result.returncode != 0: - console.print(f"[red]Error when inspecting PROD image: {command_result.returncode}[/]") + get_console().print(f"[error]Error when inspecting PROD image: {command_result.returncode}[/]") return command_result.returncode, f"Testing docker-compose python with {image_name}" pytest_args = ("-n", "auto", "--color=yes") test_path = AIRFLOW_SOURCES_ROOT / "docker_tests" / "test_docker_compose_quick_start.py" diff --git a/dev/breeze/src/airflow_breeze/utils/run_utils.py b/dev/breeze/src/airflow_breeze/utils/run_utils.py index 6ef639862a..cc2d679584 100644 --- a/dev/breeze/src/airflow_breeze/utils/run_utils.py +++ b/dev/breeze/src/airflow_breeze/utils/run_utils.py @@ -26,7 +26,7 @@ from functools import lru_cache from pathlib import Path from typing import List, Mapping, Optional, Union -from airflow_breeze.utils.console import console +from airflow_breeze.utils.console import get_console from airflow_breeze.utils.path_utils import AIRFLOW_SOURCES_ROOT @@ -70,9 +70,9 @@ def run_command( env_to_print = ' '.join(f'{key}="{val}"' for (key, val) in env.items()) if env else '' if env_to_print: env_to_print += ' ' - console.print(f"\n[bright_blue]Working directory {workdir} [/]\n") + get_console().print(f"\n[info]Working directory {workdir} [/]\n") # Soft wrap allows to copy&paste and run resulting output as it has no hard EOL - console.print(f"\n[bright_blue]{env_to_print}{command_to_print}[/]\n", soft_wrap=True) + get_console().print(f"\n[info]{env_to_print}{command_to_print}[/]\n", soft_wrap=True) if dry_run: return subprocess.CompletedProcess(cmd, returncode=0) try: @@ -83,13 +83,21 @@ def run_command( except subprocess.CalledProcessError as ex: if not no_output_dump_on_exception: if ex.stdout: - console.print("[blue]========================= OUTPUT start ============================[/]") - console.print(ex.stdout) - console.print("[blue]========================= OUTPUT end ==============================[/]") + get_console().print( + "[info]========================= OUTPUT start ============================[/]" + ) + get_console().print(ex.stdout) + get_console().print( + "[info]========================= OUTPUT end ==============================[/]" + ) if ex.stderr: - console.print("[red]========================= STDERR start ============================[/]") - console.print(ex.stderr) - console.print("[red]========================= STDERR end ==============================[/]") + get_console().print( + "[error]========================= STDERR start ============================[/]" + ) + get_console().print(ex.stderr) + get_console().print( + "[error]========================= STDERR end ==============================[/]" + ) if check: raise return ex @@ -108,7 +116,7 @@ def assert_pre_commit_installed(verbose: bool): min_pre_commit_version = pre_commit_config["minimum_pre_commit_version"] python_executable = sys.executable - console.print(f"[bright_blue]Checking pre-commit installed for {python_executable}[/]") + get_console().print(f"[info]Checking pre-commit installed for {python_executable}[/]") command_result = run_command( [python_executable, "-m", "pre_commit", "--version"], verbose=verbose, @@ -120,25 +128,24 @@ def assert_pre_commit_installed(verbose: bool): if command_result.stdout: pre_commit_version = command_result.stdout.split(" ")[-1].strip() if StrictVersion(pre_commit_version) >= StrictVersion(min_pre_commit_version): - console.print( - f"\n[green]Package pre_commit is installed. " + get_console().print( + f"\n[success]Package pre_commit is installed. " f"Good version {pre_commit_version} (>= {min_pre_commit_version})[/]\n" ) else: - console.print( - f"\n[red]Package name pre_commit version is wrong. It should be" + get_console().print( + f"\n[error]Package name pre_commit version is wrong. It should be" f"aat least {min_pre_commit_version} and is {pre_commit_version}.[/]\n\n" ) sys.exit(1) else: - console.print( - "\n[bright_yellow]Could not determine version of pre-commit. " - "You might need to update it![/]\n" + get_console().print( + "\n[warning]Could not determine version of pre-commit. " "You might need to update it![/]\n" ) else: - console.print("\n[red]Error checking for pre-commit-installation:[/]\n") - console.print(command_result.stderr) - console.print("\nMake sure to run:\n breeze self-upgrade\n\n") + get_console().print("\n[error]Error checking for pre-commit-installation:[/]\n") + get_console().print(command_result.stderr) + get_console().print("\nMake sure to run:\n breeze self-upgrade\n\n") sys.exit(1) @@ -164,8 +171,8 @@ def get_filesystem_type(filepath): def instruct_build_image(python: str): """Print instructions to the user that they should build the image""" - console.print(f'[bright_yellow]\nThe CI image for ' f'python version {python} may be outdated[/]\n') - print(f"\n[yellow]Please run at the earliest convenience:[/]\n\nbreeze build-image --python {python}\n\n") + get_console().print(f'[warning]\nThe CI image for ' f'python version {python} may be outdated[/]\n') + print(f"\n[info]Please run at the earliest convenience:[/]\n\nbreeze build-image --python {python}\n\n") @contextlib.contextmanager @@ -206,7 +213,7 @@ def change_directory_permission(directory_to_fix: Path): @working_directory(AIRFLOW_SOURCES_ROOT) def fix_group_permissions(): """Fixes permissions of all the files and directories that have group-write access.""" - console.print("[bright_blue]Fixing group permissions[/]") + get_console().print("[info]Fixing group permissions[/]") files_to_fix_result = run_command(['git', 'ls-files', './'], capture_output=True, text=True) if files_to_fix_result.returncode == 0: files_to_fix = files_to_fix_result.stdout.strip().split('\n') @@ -288,11 +295,11 @@ def prepare_build_command(prepare_buildx_cache: bool, verbose: bool) -> List[str build_command_param.extend(["buildx", "build", "--builder", "default", "--progress=tty"]) else: if prepare_buildx_cache: - console.print( - '\n[red] Buildx cli plugin is not available and you need it to prepare buildx cache. \n' + get_console().print( + '\n[error] Buildx cli plugin is not available and you need it to prepare buildx cache. \n' ) - console.print( - '[red] Please install it following https://docs.docker.com/buildx/working-with-buildx/ \n' + get_console().print( + '[error] Please install it following https://docs.docker.com/buildx/working-with-buildx/ \n' ) sys.exit(1) build_command_param.append("build") diff --git a/dev/breeze/src/airflow_breeze/utils/visuals.py b/dev/breeze/src/airflow_breeze/utils/visuals.py index effbdd27ae..b5db534514 100644 --- a/dev/breeze/src/airflow_breeze/utils/visuals.py +++ b/dev/breeze/src/airflow_breeze/utils/visuals.py @@ -74,9 +74,9 @@ ASCIIART = """ """ CHEATSHEET = f""" - [bold][bright_blue]Airflow Breeze Cheatsheet[/][/] + [bold][info]Airflow Breeze Cheatsheet[/][/] - [bright_blue]* Port forwarding:[/] + [info]* Port forwarding:[/] Ports are forwarded to the running docker containers for webserver and database * {SSH_PORT} -> forwarded to Airflow ssh server -> airflow:22 @@ -98,7 +98,7 @@ CHEATSHEET = f""" Airflow123 * Redis: redis://127.0.0.1:{REDIS_HOST_PORT}/0 - [bright_blue]* How can I add my stuff in Breeze:[/] + [info]* How can I add my stuff in Breeze:[/] * Your dags for webserver and scheduler are read from `/files/dags` directory which is mounted from folder in Airflow sources: @@ -115,7 +115,7 @@ CHEATSHEET = f""" `{AIRFLOW_SOURCES_ROOT}/files` folder and they will be visible in `/files/` folder inside the container - [bright_blue]* Other options[/] + [info]* Other options[/] Check out `--help` for ./breeze commands. It will show you other options, such as running integration or starting complete Airflow using `start-airflow` command as well as ways diff --git a/dev/breeze/tests/test_docker_command_utils.py b/dev/breeze/tests/test_docker_command_utils.py index 8d168844b9..5be489c65e 100644 --- a/dev/breeze/tests/test_docker_command_utils.py +++ b/dev/breeze/tests/test_docker_command_utils.py @@ -23,8 +23,10 @@ from airflow_breeze.utils.docker_command_utils import check_docker_compose_versi @mock.patch('airflow_breeze.utils.docker_command_utils.check_docker_permission_denied') @mock.patch('airflow_breeze.utils.docker_command_utils.run_command') [email protected]('airflow_breeze.utils.docker_command_utils.console') -def test_check_docker_version_unknown(mock_console, mock_run_command, mock_check_docker_permission_denied): [email protected]('airflow_breeze.utils.docker_command_utils.get_console') +def test_check_docker_version_unknown( + mock_get_console, mock_run_command, mock_check_docker_permission_denied +): mock_check_docker_permission_denied.return_value = False check_docker_version(verbose=True) expected_run_command_calls = [ @@ -38,18 +40,20 @@ def test_check_docker_version_unknown(mock_console, mock_run_command, mock_check ), ] mock_run_command.assert_has_calls(expected_run_command_calls) - mock_console.print.assert_called_with( + mock_get_console.return_value.print.assert_called_with( """ -[yellow]Your version of docker is unknown. If the scripts fail, please make sure to[/] -[yellow]install docker at least: 20.10.0 version.[/] +[warning]Your version of docker is unknown. If the scripts fail, please make sure to[/] +[warning]install docker at least: 20.10.0 version.[/] """ ) @mock.patch('airflow_breeze.utils.docker_command_utils.check_docker_permission_denied') @mock.patch('airflow_breeze.utils.docker_command_utils.run_command') [email protected]('airflow_breeze.utils.docker_command_utils.console') -def test_check_docker_version_too_low(mock_console, mock_run_command, mock_check_docker_permission_denied): [email protected]('airflow_breeze.utils.docker_command_utils.get_console') +def test_check_docker_version_too_low( + mock_get_console, mock_run_command, mock_check_docker_permission_denied +): mock_check_docker_permission_denied.return_value = False mock_run_command.return_value.returncode = 0 mock_run_command.return_value.stdout = "0.9" @@ -63,17 +67,17 @@ def test_check_docker_version_too_low(mock_console, mock_run_command, mock_check text=True, check=False, ) - mock_console.print.assert_called_with( + mock_get_console.return_value.print.assert_called_with( """ -[yellow]Your version of docker is too old:0.9. Please upgrade to at least 20.10.0[/] +[warning]Your version of docker is too old:0.9.\nPlease upgrade to at least 20.10.0[/] """ ) @mock.patch('airflow_breeze.utils.docker_command_utils.check_docker_permission_denied') @mock.patch('airflow_breeze.utils.docker_command_utils.run_command') [email protected]('airflow_breeze.utils.docker_command_utils.console') -def test_check_docker_version_ok(mock_console, mock_run_command, mock_check_docker_permission_denied): [email protected]('airflow_breeze.utils.docker_command_utils.get_console') +def test_check_docker_version_ok(mock_get_console, mock_run_command, mock_check_docker_permission_denied): mock_check_docker_permission_denied.return_value = False mock_run_command.return_value.returncode = 0 mock_run_command.return_value.stdout = "20.10.0" @@ -87,13 +91,13 @@ def test_check_docker_version_ok(mock_console, mock_run_command, mock_check_dock text=True, check=False, ) - mock_console.print.assert_called_with("[green]Good version of Docker: 20.10.0.[/]") + mock_get_console.return_value.print.assert_called_with("[success]Good version of Docker: 20.10.0.[/]") @mock.patch('airflow_breeze.utils.docker_command_utils.check_docker_permission_denied') @mock.patch('airflow_breeze.utils.docker_command_utils.run_command') [email protected]('airflow_breeze.utils.docker_command_utils.console') -def test_check_docker_version_higher(mock_console, mock_run_command, mock_check_docker_permission_denied): [email protected]('airflow_breeze.utils.docker_command_utils.get_console') +def test_check_docker_version_higher(mock_get_console, mock_run_command, mock_check_docker_permission_denied): mock_check_docker_permission_denied.return_value = False mock_run_command.return_value.returncode = 0 mock_run_command.return_value.stdout = "21.10.0" @@ -107,12 +111,12 @@ def test_check_docker_version_higher(mock_console, mock_run_command, mock_check_ text=True, check=False, ) - mock_console.print.assert_called_with("[green]Good version of Docker: 21.10.0.[/]") + mock_get_console.return_value.print.assert_called_with("[success]Good version of Docker: 21.10.0.[/]") @mock.patch('airflow_breeze.utils.docker_command_utils.run_command') [email protected]('airflow_breeze.utils.docker_command_utils.console') -def test_check_docker_compose_version_unknown(mock_console, mock_run_command): [email protected]('airflow_breeze.utils.docker_command_utils.get_console') +def test_check_docker_compose_version_unknown(mock_get_console, mock_run_command): check_docker_compose_version(verbose=True) expected_run_command_calls = [ call( @@ -124,17 +128,17 @@ def test_check_docker_compose_version_unknown(mock_console, mock_run_command): ), ] mock_run_command.assert_has_calls(expected_run_command_calls) - mock_console.print.assert_called_with( + mock_get_console.return_value.print.assert_called_with( """ -[yellow]Unknown docker-compose version. At least 1.29 is needed![/] -[yellow]If Breeze fails upgrade to latest available docker-compose version.[/] +[warning]Unknown docker-compose version. At least 1.29 is needed![/] +[warning]If Breeze fails upgrade to latest available docker-compose version.[/] """ ) @mock.patch('airflow_breeze.utils.docker_command_utils.run_command') [email protected]('airflow_breeze.utils.docker_command_utils.console') -def test_check_docker_compose_version_low(mock_console, mock_run_command): [email protected]('airflow_breeze.utils.docker_command_utils.get_console') +def test_check_docker_compose_version_low(mock_get_console, mock_run_command): mock_run_command.return_value.returncode = 0 mock_run_command.return_value.stdout = "1.28.5" check_docker_compose_version(verbose=True) @@ -148,7 +152,7 @@ def test_check_docker_compose_version_low(mock_console, mock_run_command): expected_print_calls = [ call( """ -[yellow]You have too old version of docker-compose: 1.28.5! At least 1.29 is needed! Please upgrade! +[warning]You have too old version of docker-compose: 1.28.5! At least 1.29 is needed! Please upgrade! """ ), call( @@ -158,12 +162,12 @@ Make sure docker-compose you install is first on the PATH variable of yours. """ ), ] - mock_console.print.assert_has_calls(expected_print_calls) + mock_get_console.return_value.print.assert_has_calls(expected_print_calls) @mock.patch('airflow_breeze.utils.docker_command_utils.run_command') [email protected]('airflow_breeze.utils.docker_command_utils.console') -def test_check_docker_compose_version_ok(mock_console, mock_run_command): [email protected]('airflow_breeze.utils.docker_command_utils.get_console') +def test_check_docker_compose_version_ok(mock_get_console, mock_run_command): mock_run_command.return_value.returncode = 0 mock_run_command.return_value.stdout = "1.29.0" check_docker_compose_version(verbose=True) @@ -174,12 +178,14 @@ def test_check_docker_compose_version_ok(mock_console, mock_run_command): capture_output=True, text=True, ) - mock_console.print.assert_called_with("[green]Good version of docker-compose: 1.29.0[/]") + mock_get_console.return_value.print.assert_called_with( + "[success]Good version of docker-compose: 1.29.0[/]" + ) @mock.patch('airflow_breeze.utils.docker_command_utils.run_command') [email protected]('airflow_breeze.utils.docker_command_utils.console') -def test_check_docker_compose_version_higher(mock_console, mock_run_command): [email protected]('airflow_breeze.utils.docker_command_utils.get_console') +def test_check_docker_compose_version_higher(mock_get_console, mock_run_command): mock_run_command.return_value.returncode = 0 mock_run_command.return_value.stdout = "1.29.2" check_docker_compose_version(verbose=True) @@ -190,4 +196,6 @@ def test_check_docker_compose_version_higher(mock_console, mock_run_command): capture_output=True, text=True, ) - mock_console.print.assert_called_with("[green]Good version of docker-compose: 1.29.2[/]") + mock_get_console.return_value.print.assert_called_with( + "[success]Good version of docker-compose: 1.29.2[/]" + ) diff --git a/dev/provider_packages/prepare_provider_packages.py b/dev/provider_packages/prepare_provider_packages.py index 1a46c7292d..319f4447fd 100755 --- a/dev/provider_packages/prepare_provider_packages.py +++ b/dev/provider_packages/prepare_provider_packages.py @@ -171,7 +171,7 @@ def with_group(title): https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#grouping-log-lines """ if os.environ.get('GITHUB_ACTIONS', 'false') != "true": - console.print("[blue]" + "#" * 10 + ' ' + title + ' ' + "#" * 10 + "[/]") + console.print("[info]" + "#" * 10 + ' ' + title + ' ' + "#" * 10 + "[/]") yield return console.print(f"::group::{title}") diff --git a/docs/build_docs.py b/docs/build_docs.py index f2361f00ab..d7edad1cad 100755 --- a/docs/build_docs.py +++ b/docs/build_docs.py @@ -69,21 +69,21 @@ def _promote_new_flags(): console.print() if ON_GITHUB_ACTIONS: console.print("You can quickly build documentation locally with just one command.") - console.print(" [blue]breeze build-docs[/]") + console.print(" [info]breeze build-docs[/]") console.print() console.print("[yellow]Still too slow?[/]") console.print() console.print("You can only build one documentation package:") - console.print(" [blue]breeze build-docs --package-filter <PACKAGE-NAME>[/]") + console.print(" [info]breeze build-docs --package-filter <PACKAGE-NAME>[/]") console.print() console.print("This usually takes from [yellow]20 seconds[/] to [yellow]2 minutes[/].") console.print() console.print("You can also use other extra flags to iterate faster:") - console.print(" [blue]--docs-only - Only build documentation[/]") - console.print(" [blue]--spellcheck-only - Only perform spellchecking[/]") + console.print(" [info]--docs-only - Only build documentation[/]") + console.print(" [info]--spellcheck-only - Only perform spellchecking[/]") console.print() console.print("For more info:") - console.print(" [blue]breeze build-docs --help[/]") + console.print(" [info]breeze build-docs --help[/]") console.print() @@ -177,7 +177,7 @@ def perform_docs_build_for_single_package(build_specification: BuildSpecificatio builder = AirflowDocsBuilder( package_name=build_specification.package_name, for_production=build_specification.for_production ) - console.print(f"[blue]{build_specification.package_name:60}:[/] Building documentation") + console.print(f"[info]{build_specification.package_name:60}:[/] Building documentation") result = BuildDocsResult( package_name=build_specification.package_name, errors=builder.build_sphinx_docs( @@ -193,7 +193,7 @@ def perform_spell_check_for_single_package(build_specification: BuildSpecificati builder = AirflowDocsBuilder( package_name=build_specification.package_name, for_production=build_specification.for_production ) - console.print(f"[blue]{build_specification.package_name:60}:[/] Checking spelling started") + console.print(f"[info]{build_specification.package_name:60}:[/] Checking spelling started") result = SpellCheckResult( package_name=build_specification.package_name, errors=builder.check_spelling( @@ -201,7 +201,7 @@ def perform_spell_check_for_single_package(build_specification: BuildSpecificati ), log_file_name=builder.log_spelling_filename, ) - console.print(f"[blue]{build_specification.package_name:60}:[/] Checking spelling completed") + console.print(f"[info]{build_specification.package_name:60}:[/] Checking spelling completed") return result @@ -218,7 +218,7 @@ def build_docs_for_packages( all_spelling_errors: Dict[str, List[SpellingError]] = defaultdict(list) with with_group("Cleaning documentation files"): for package_name in current_packages: - console.print(f"[blue]{package_name:60}:[/] Cleaning files") + console.print(f"[info]{package_name:60}:[/] Cleaning files") builder = AirflowDocsBuilder(package_name=package_name, for_production=for_production) builder.clean_files() if jobs > 1: @@ -315,11 +315,11 @@ def print_build_output(result: BuildDocsResult): """Prints output of docs build job.""" with with_group(f"{TEXT_RED}Output for documentation build {result.package_name}{TEXT_RESET}"): console.print() - console.print(f"[blue]{result.package_name:60}: " + "#" * 80) + console.print(f"[info]{result.package_name:60}: " + "#" * 80) with open(result.log_file_name) as output: for line in output.read().splitlines(): console.print(f"{result.package_name:60} {line}") - console.print(f"[blue]{result.package_name:60}: " + "#" * 80) + console.print(f"[info]{result.package_name:60}: " + "#" * 80) def run_docs_build_in_parallel( @@ -333,7 +333,7 @@ def run_docs_build_in_parallel( doc_build_specifications: List[BuildSpecification] = [] with with_group("Scheduling documentation to build"): for package_name in current_packages: - console.print(f"[blue]{package_name:60}:[/] Scheduling documentation to build") + console.print(f"[info]{package_name:60}:[/] Scheduling documentation to build") doc_build_specifications.append( BuildSpecification( package_name=package_name, @@ -354,11 +354,11 @@ def print_spelling_output(result: SpellCheckResult): """Prints output of spell check job.""" with with_group(f"{TEXT_RED}Output for spelling check: {result.package_name}{TEXT_RESET}"): console.print() - console.print(f"[blue]{result.package_name:60}: " + "#" * 80) + console.print(f"[info]{result.package_name:60}: " + "#" * 80) with open(result.log_file_name) as output: for line in output.read().splitlines(): console.print(f"{result.package_name:60} {line}") - console.print(f"[blue]{result.package_name:60}: " + "#" * 80) + console.print(f"[info]{result.package_name:60}: " + "#" * 80) console.print() @@ -373,7 +373,7 @@ def run_spell_check_in_parallel( spell_check_specifications: List[BuildSpecification] = [] with with_group("Scheduling spell checking of documentation"): for package_name in current_packages: - console.print(f"[blue]{package_name:60}:[/] Scheduling spellchecking") + console.print(f"[info]{package_name:60}:[/] Scheduling spellchecking") spell_check_specifications.append( BuildSpecification(package_name=package_name, for_production=for_production, verbose=verbose) ) @@ -393,7 +393,7 @@ def display_packages_summary( packages_names = {*build_errors.keys(), *spelling_errors.keys()} tabular_data = [ { - "Package name": f"[blue]{package_name}[/]", + "Package name": f"[info]{package_name}[/]", "Count of doc build errors": len(build_errors.get(package_name, [])), "Count of spelling errors": len(spelling_errors.get(package_name, [])), } diff --git a/docs/exts/docs_build/docs_builder.py b/docs/exts/docs_build/docs_builder.py index ad343b46cf..cc65f3f170 100644 --- a/docs/exts/docs_build/docs_builder.py +++ b/docs/exts/docs_build/docs_builder.py @@ -157,10 +157,10 @@ class AirflowDocsBuilder: env['AIRFLOW_FOR_PRODUCTION'] = 'true' if verbose: console.print( - f"[blue]{self.package_name:60}:[/] Executing cmd: ", + f"[info]{self.package_name:60}:[/] Executing cmd: ", " ".join(shlex.quote(c) for c in build_cmd), ) - console.print(f"[blue]{self.package_name:60}:[/] The output is hidden until an error occurs.") + console.print(f"[info]{self.package_name:60}:[/] The output is hidden until an error occurs.") with open(self.log_spelling_filename, "wt") as output: completed_proc = run( build_cmd, @@ -189,15 +189,15 @@ class AirflowDocsBuilder: warning_text += spelling_file.read() spelling_errors.extend(parse_spelling_warnings(warning_text, self._src_dir)) - console.print(f"[blue]{self.package_name:60}:[/] [red]Finished spell-checking with errors[/]") + console.print(f"[info]{self.package_name:60}:[/] [red]Finished spell-checking with errors[/]") else: if spelling_errors: console.print( - f"[blue]{self.package_name:60}:[/] [yellow]Finished spell-checking with warnings[/]" + f"[info]{self.package_name:60}:[/] [yellow]Finished spell-checking with warnings[/]" ) else: console.print( - f"[blue]{self.package_name:60}:[/] [green]Finished spell-checking successfully[/]" + f"[info]{self.package_name:60}:[/] [green]Finished spell-checking successfully[/]" ) return spelling_errors @@ -232,12 +232,12 @@ class AirflowDocsBuilder: env['AIRFLOW_FOR_PRODUCTION'] = 'true' if verbose: console.print( - f"[blue]{self.package_name:60}:[/] Executing cmd: ", + f"[info]{self.package_name:60}:[/] Executing cmd: ", " ".join(shlex.quote(c) for c in build_cmd), ) else: console.print( - f"[blue]{self.package_name:60}:[/] Running sphinx. " + f"[info]{self.package_name:60}:[/] Running sphinx. " f"The output is hidden until an error occurs." ) with open(self.log_build_filename, "wt") as output: @@ -264,9 +264,9 @@ class AirflowDocsBuilder: warning_text = re.sub(r"\x1B[@-_][0-?]*[ -/]*[@-~]", "", warning_text) build_errors.extend(parse_sphinx_warnings(warning_text, self._src_dir)) if build_errors: - console.print(f"[blue]{self.package_name:60}:[/] [red]Finished docs building with errors[/]") + console.print(f"[info]{self.package_name:60}:[/] [red]Finished docs building with errors[/]") else: - console.print(f"[blue]{self.package_name:60}:[/] [green]Finished docs building successfully[/]") + console.print(f"[info]{self.package_name:60}:[/] [green]Finished docs building successfully[/]") return build_errors def publish(self, override_versioned: bool): diff --git a/docs/exts/docs_build/errors.py b/docs/exts/docs_build/errors.py index b654fc6621..d1dc48d7cd 100644 --- a/docs/exts/docs_build/errors.py +++ b/docs/exts/docs_build/errors.py @@ -62,9 +62,9 @@ def display_errors_summary(build_errors: Dict[str, List[DocBuildError]]) -> None console.print() for package_name, errors in build_errors.items(): if package_name: - console.print("=" * 30 + f" [blue]{package_name}[/] " + "=" * 30) + console.print("=" * 30 + f" [info]{package_name}[/] " + "=" * 30) else: - console.print("=" * 30, " [blue]General[/] ", "=" * 30) + console.print("=" * 30, " [info]General[/] ", "=" * 30) for warning_no, error in enumerate(sorted(errors), 1): console.print("-" * 30, f"[red]Error {warning_no:3}[/]", "-" * 20) console.print(error.message) diff --git a/docs/exts/docs_build/spelling_checks.py b/docs/exts/docs_build/spelling_checks.py index 62d4baeccb..5106d80e21 100644 --- a/docs/exts/docs_build/spelling_checks.py +++ b/docs/exts/docs_build/spelling_checks.py @@ -142,9 +142,9 @@ def display_spelling_error_summary(spelling_errors: Dict[str, List[SpellingError for package_name, errors in sorted(spelling_errors.items()): if package_name: - console.print("=" * 30, f" [blue]{package_name}[/] ", "=" * 30) + console.print("=" * 30, f" [info]{package_name}[/] ", "=" * 30) else: - console.print("=" * 30, " [blue]General[/] ", "=" * 30) + console.print("=" * 30, " [info]General[/] ", "=" * 30) for warning_no, error in enumerate(sorted(errors), 1): console.print("-" * 30, f"Error {warning_no:3}", "-" * 30) diff --git a/images/breeze/output-config.svg b/images/breeze/output-config.svg index 5d20779549..35d0962e15 100644 --- a/images/breeze/output-config.svg +++ b/images/breeze/output-config.svg @@ -1,4 +1,4 @@ -<svg width="1720.0" height="802" viewBox="0 0 1720.0 802" +<svg width="1720.0" height="824" viewBox="0 0 1720.0 824" xmlns="http://www.w3.org/2000/svg"> <style> @font-face { @@ -128,6 +128,7 @@ <div><span class="r4">│</span><span class="r1"> </span><span class="r4">[default: sqlite] </span><span class="r1"> </span><span class="r1"> </span><span class="r1"> </span><span class="r4">│</span></div> <div><span class="r4">│</span><span class="r1"> </span><span class="r5">--cheatsheet</span><span class="r1">/</span><span class="r5">--no-cheatsheet</span><span class="r1"> </span><span class="r6">-C</span><span class="r1">/</span><span class="r6">-c</span><span class="r1"> </span><span class="r1">Enable/disable cheatsheet. </span><span class="r1"> </span><span class="r4">│</span></div> <div><span class="r4">│</span><span class="r1"> </span><span class="r5">--asciiart</span><span class="r1">/</span><span class="r5">--no-asciiart</span><span class="r1"> </span><span class="r6">-A</span><span class="r1">/</span><span class="r6">-a</span><span class="r1"> </span><span class="r1">Enable/disable ASCIIart. </span><span class="r1"> </span><span class="r4">│</span></div> +<div><span class="r4">│</span><span class="r1"> </span><span class="r5">--colour</span><span class="r1">/</span><span class="r5">--no-colour</span><span class="r1"> </span><span class="r6">-B</span><span class="r1">/</span><span class="r6">-b</span><span class="r1"> </span><span class="r1">Enable/disable Colour mode (useful for colour blind-friendly communication). </span><span class="r1"> </span><span class="r4">│</span></div> <div><span class="r4">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span></div> <div><span class="r4">╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮</span></div> <div><span class="r4">│</span><span class="r1"> </span><span class="r5">--postgres-version</span><span class="r1"> </span><span class="r6">-P</span><span class="r1"> </span><span class="r1">Version of Postgres used.</span><span class="r1"> </span><span class="r7">(>10< | 11 | 12 | 13)</span><span class="r1"> </span><span class="r4">[default: 10]</span><span class="r1"> </span><span class="r1"> </span><span class="r4">│</span></div> diff --git a/scripts/ci/pre_commit/pre_commit_check_order_setup.py b/scripts/ci/pre_commit/pre_commit_check_order_setup.py index 82c5f53ba8..8e4ac563f6 100755 --- a/scripts/ci/pre_commit/pre_commit_check_order_setup.py +++ b/scripts/ci/pre_commit/pre_commit_check_order_setup.py @@ -65,7 +65,7 @@ def check_main_dependent_group(setup_contents: str) -> None: Test for an order of dependencies groups between mark '# Start dependencies group' and '# End dependencies group' in setup.py """ - print("[blue]Checking main dependency group[/]") + print("[info]Checking main dependency group[/]") pattern_main_dependent_group = re.compile( '# Start dependencies group\n(.*)# End dependencies group', re.DOTALL ) @@ -86,7 +86,7 @@ def check_sub_dependent_group(group_name: str) -> None: Test for an order of each dependencies groups declare like `^dependent_group_name = [.*?]\n` in setup.py """ - print(f"[blue]Checking dependency group {group_name}[/]") + print(f"[info]Checking dependency group {group_name}[/]") _check_list_sorted(getattr(setup, group_name), f"Order of dependency group: {group_name}") @@ -99,13 +99,13 @@ def check_alias_dependent_group(setup_context: str) -> None: dependents = pattern.findall(setup_context) for dependent in dependents: - print(f"[blue]Checking alias-dependent group {dependent}[/]") + print(f"[info]Checking alias-dependent group {dependent}[/]") src = dependent.split(' + ') _check_list_sorted(src, f"Order of alias dependencies group: {dependent}") def check_variable_order(var_name: str) -> None: - print(f"[blue]Checking {var_name}[/]") + print(f"[info]Checking {var_name}[/]") var = getattr(setup, var_name) @@ -129,7 +129,7 @@ def check_install_and_setup_requires() -> None: pattern_dependent_version = re.compile('[~|><=;].*') for key in ('install_requires', 'setup_requires'): - print(f"[blue]Checking setup.cfg group {key}[/]") + print(f"[info]Checking setup.cfg group {key}[/]") deps = config['options'][key] dists = [pattern_dependent_version.sub('', p) for p in deps] _check_list_sorted(dists, f"Order of dependencies in do_setup section: {key}")
