Skip to content

Commit 6fb23c1

Browse files
authored
Unify Printer, Logger and Console classes (#2124)
Refactors Printer, Log and Console into a single Console class. This providers a single point of entry for all user input/ouput handling.
1 parent d07d9ef commit 6fb23c1

203 files changed

Lines changed: 1448 additions & 1577 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

changes/2114.feature.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Project bootstraps now have access to the Briefcase logger, console, and the overrides specified with ``-Q`` options at the command line.
1+
Project bootstraps now have access to the Briefcase console and the overrides specified with ``-Q`` options at the command line.

changes/2114.removal.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
The API for project bootstraps has been slightly modified. The constructor for a bootstrap must now accept a logger and console argument; the ``extra_context()`` method must now accept a ``project_overrides`` argument.
1+
The API for project bootstraps has been slightly modified. The constructor for a bootstrap must now accept a console argument; the ``extra_context()`` method must now accept a ``project_overrides`` argument.

changes/2124.misc.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The Printer, Logger and Console classes have been unified into a single Console class.

src/briefcase/__main__.py

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from pathlib import Path
44

55
from briefcase.cmdline import parse_cmdline
6-
from briefcase.console import Console, Log, Printer
6+
from briefcase.console import Console
77
from briefcase.exceptions import (
88
BriefcaseError,
99
BriefcaseTestSuiteFailure,
@@ -15,49 +15,47 @@
1515
def main():
1616
result = 0
1717
command = None
18-
printer = Printer()
19-
console = Console(printer=printer)
20-
logger = Log(printer=printer)
18+
console = Console()
2119
try:
2220
Command, extra_cmdline = parse_cmdline(sys.argv[1:], console=console)
23-
command = Command(logger=logger, console=console)
21+
command = Command(console=console)
2422
options, overrides = command.parse_options(extra=extra_cmdline)
2523
command.parse_config(
2624
Path.cwd() / "pyproject.toml",
2725
overrides=overrides,
2826
)
2927
command(**options)
3028
except HelpText as e:
31-
logger.info()
32-
logger.info(str(e))
29+
console.info()
30+
console.info(str(e))
3331
result = e.error_code
3432
except BriefcaseWarning as w:
3533
# The case of something that hasn't gone right, but in an
3634
# acceptable way.
37-
logger.warning(str(w))
35+
console.warning(str(w))
3836
result = w.error_code
3937
except BriefcaseTestSuiteFailure as e:
4038
# Test suite status is logged when the test is executed.
4139
# Set the return code, but don't log anything else.
4240
result = e.error_code
4341
except BriefcaseError as e:
44-
logger.error()
45-
logger.error(str(e))
42+
console.error()
43+
console.error(str(e))
4644
result = e.error_code
47-
logger.capture_stacktrace()
45+
console.capture_stacktrace()
4846
except Exception:
49-
logger.capture_stacktrace()
47+
console.capture_stacktrace()
5048
raise
5149
except KeyboardInterrupt:
52-
logger.warning()
53-
logger.warning("Aborted by user.")
54-
logger.warning()
50+
console.warning()
51+
console.warning("Aborted by user.")
52+
console.warning()
5553
result = -42
56-
if logger.save_log:
57-
logger.capture_stacktrace()
54+
if console.save_log:
55+
console.capture_stacktrace()
5856
finally:
5957
with suppress(KeyboardInterrupt):
60-
logger.save_log_to_file(command)
58+
console.save_log_to_file(command)
6159

6260
return result
6361

src/briefcase/bootstraps/base.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from pathlib import Path
55
from typing import Any, TypedDict
66

7-
from briefcase.console import Console, Log
7+
from briefcase.console import Console
88

99

1010
class AppContext(TypedDict):
@@ -54,9 +54,8 @@ class BaseGuiBootstrap(ABC):
5454
# is presented with the options to create a new project.
5555
display_name_annotation: str = ""
5656

57-
def __init__(self, logger: Log, input: Console, context: AppContext):
58-
self.logger = logger
59-
self.input = input
57+
def __init__(self, console: Console, context: AppContext):
58+
self.console = console
6059

6160
# context contains metadata about the app being created
6261
self.context = context

src/briefcase/commands/base.py

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import briefcase
2929
from briefcase import __version__
3030
from briefcase.config import AppConfig, GlobalConfig, parse_config
31-
from briefcase.console import MAX_TEXT_WIDTH, Console, Log
31+
from briefcase.console import MAX_TEXT_WIDTH, Console
3232
from briefcase.exceptions import (
3333
BriefcaseCommandError,
3434
BriefcaseConfigError,
@@ -140,7 +140,6 @@ class BaseCommand(ABC):
140140

141141
def __init__(
142142
self,
143-
logger: Log,
144143
console: Console,
145144
tools: ToolCache = None,
146145
apps: dict = None,
@@ -150,7 +149,6 @@ def __init__(
150149
):
151150
"""Base for all Commands.
152151
153-
:param logger: Logger for console and logfile.
154152
:param console: Facilitates console interaction and input solicitation.
155153
:param tools: Cache of tools populated by Commands as they are required.
156154
:param apps: Dictionary of project's Apps keyed by app name.
@@ -169,7 +167,6 @@ def __init__(
169167
self.is_clone = is_clone
170168

171169
self.tools = tools or ToolCache(
172-
logger=logger,
173170
console=console,
174171
base_path=self.data_path / "tools",
175172
)
@@ -185,12 +182,8 @@ def __init__(
185182
self._briefcase_toml: dict[AppConfig, dict[str, ...]] = {}
186183

187184
@property
188-
def logger(self):
189-
return self.tools.logger
190-
191-
@property
192-
def input(self):
193-
return self.tools.input
185+
def console(self):
186+
return self.tools.console
194187

195188
def validate_data_path(self, data_path):
196189
"""Validate provided data path or determine OS-specific path.
@@ -275,7 +268,7 @@ def validate_data_path(self, data_path):
275268
def validate_locale(self):
276269
"""Validate the system's locale is compatible."""
277270
if self.tools.host_os == "Linux" and self.tools.system_encoding != "UTF-8":
278-
self.logger.warning(
271+
self.console.warning(
279272
f"""
280273
*************************************************************************
281274
** WARNING: Default system encoding is not supported **
@@ -304,8 +297,7 @@ def _command_factory(self, command_name: str):
304297
command = getattr(format_module, command_name)(
305298
base_path=self.base_path,
306299
apps=self.apps,
307-
logger=self.logger,
308-
console=self.input,
300+
console=self.console,
309301
tools=self.tools,
310302
is_clone=True,
311303
)
@@ -731,7 +723,7 @@ def parse_options(self, extra):
731723
platform=self.platform,
732724
output_format=self.output_format,
733725
),
734-
description=self.input.textwrap(
726+
description=self.console.textwrap(
735727
f"{self.description}\n\n{supported_formats_helptext}"
736728
),
737729
formatter_class=(
@@ -765,9 +757,9 @@ def parse_options(self, extra):
765757
options["passthrough"] = passthrough
766758

767759
# Extract the base default options onto the command
768-
self.input.enabled = options.pop("input_enabled")
769-
self.logger.verbosity = options.pop("verbosity")
770-
self.logger.save_log = options.pop("save_log")
760+
self.console.input_enabled = options.pop("input_enabled")
761+
self.console.verbosity = options.pop("verbosity")
762+
self.console.save_log = options.pop("save_log")
771763

772764
# Parse the configuration overrides
773765
overrides = parse_config_overrides(options.pop("config_overrides"))
@@ -902,7 +894,7 @@ def parse_config(self, filename, overrides):
902894
config_file,
903895
platform=self.platform,
904896
output_format=self.output_format,
905-
logger=self.logger,
897+
console=self.console,
906898
)
907899

908900
# Create the global config
@@ -958,7 +950,7 @@ def update_cookiecutter_cache(self, template: str, branch="master"):
958950
repo = self.tools.git.Repo(cached_template)
959951
except self.tools.git.exc.GitError:
960952
# Template repository is in a weird state. Delete it
961-
self.logger.warning(
953+
self.console.warning(
962954
"Template cache is in a weird state. Getting a clean clone."
963955
)
964956
self.tools.shutil.rmtree(cached_template)
@@ -968,7 +960,7 @@ def update_cookiecutter_cache(self, template: str, branch="master"):
968960
# the template, or the template was in a weird state. Perform a blobless
969961
# clone.
970962
try:
971-
self.logger.info(f"Cloning template {template!r}...")
963+
self.console.info(f"Cloning template {template!r}...")
972964
cached_template.mkdir(exist_ok=True, parents=True)
973965
repo = self.tools.git.Repo.clone_from(
974966
url=template,
@@ -1022,8 +1014,8 @@ def update_cookiecutter_cache(self, template: str, branch="master"):
10221014
# We are offline, or otherwise unable to contact the origin git
10231015
# repo. It's OK to continue; but capture the error in the log and
10241016
# warn the user that the template may be stale.
1025-
self.logger.debug(str(e))
1026-
self.logger.warning(
1017+
self.console.debug(str(e))
1018+
self.console.warning(
10271019
"""
10281020
*************************************************************************
10291021
** WARNING: Unable to update template **
@@ -1041,7 +1033,7 @@ def update_cookiecutter_cache(self, template: str, branch="master"):
10411033
# Check out the branch for the required version tag.
10421034
head = remote.refs[branch]
10431035

1044-
self.logger.info(
1036+
self.console.info(
10451037
f"Using existing template (sha {head.commit.hexsha}, "
10461038
f"updated {head.commit.committed_datetime.strftime('%c')})"
10471039
)
@@ -1082,7 +1074,7 @@ def _generate_template(self, template, branch, output_path, extra_context):
10821074
branch=branch,
10831075
)
10841076

1085-
self.logger.configure_stdlib_logging("cookiecutter")
1077+
self.console.configure_stdlib_logging("cookiecutter")
10861078
try:
10871079
# Unroll the template.
10881080
self.tools.cookiecutter(
@@ -1136,7 +1128,7 @@ def generate_template(
11361128
)
11371129

11381130
try:
1139-
self.logger.info(
1131+
self.console.info(
11401132
f"Using app template: {template}, branch {template_branch}"
11411133
)
11421134
# Unroll the new app template
@@ -1153,7 +1145,7 @@ def generate_template(
11531145
raise
11541146

11551147
# Development branches can use the main template.
1156-
self.logger.info(
1148+
self.console.info(
11571149
f"Template branch {template_branch} not found; falling back to development template"
11581150
)
11591151

src/briefcase/commands/build.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def _build_app(
7777
state = self.build_app(app, test_mode=test_mode, **full_options(state, options))
7878

7979
qualifier = " (test mode)" if test_mode else ""
80-
self.logger.info(
80+
self.console.info(
8181
f"Built {self.binary_path(app).relative_to(self.base_path)}{qualifier}",
8282
prefix=app.app_name,
8383
)

0 commit comments

Comments
 (0)