Skip to content

Commit

Permalink
Merge pull request #1709 from rmartin16/log-pyproject
Browse files Browse the repository at this point in the history
Include `pyproject.toml` in log file
  • Loading branch information
freakboy3742 committed Mar 24, 2024
2 parents 52dd46d + 8d9f210 commit f322cf1
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 20 deletions.
1 change: 1 addition & 0 deletions changes/1674.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The contents of ``pyproject.toml`` is now included in the log file.
35 changes: 24 additions & 11 deletions src/briefcase/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,9 +398,9 @@ def save_log_to_file(self, command):
self.warning(f"Log saved to {log_filepath}")
self.print.to_console()

def _build_log(self, command):
def _build_log(self, command) -> str:
"""Accumulate all information to include in the log file."""
# add the exception stacktrace to end of log if one was captured
# Add the exception stacktraces to end of log if any were captured
if self.stacktraces:
# using print.log.print() instead of print.to_log() to avoid
# timestamp and code location inclusion for the stacktrace box.
Expand All @@ -415,6 +415,7 @@ def _build_log(self, command):
new_line_start=True,
)

# Retrieve additional logging added by the Command
if self.log_file_extras:
with command.input.wait_bar(
"Collecting extra information for log...",
Expand All @@ -428,21 +429,30 @@ def _build_log(self, command):
except Exception:
self.error(traceback.format_exc())

# build log header and export buffered log from Rich
uname = platform.uname()
# Capture env vars removing any potentially sensitive information
sanitized_env_vars = "\n".join(
f"\t{env_var}={value if not SENSITIVE_SETTING_RE.search(env_var) else '********************'}"
for env_var, value in sorted(command.tools.os.environ.items())
)

# Capture pyproject.toml if one exists in the current directory
try:
with open(Path.cwd() / "pyproject.toml", encoding="utf-8") as f:
pyproject_toml = f.read().strip()
except OSError as e:
pyproject_toml = str(e)

# Build log with buffered log from Rich
uname = platform.uname()
return (
f"Date/Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S %Z')}\n"
f"Command line: {' '.join(sys.argv)}\n"
f"\n"
"\n"
f"OS Release: {uname.system} {uname.release}\n"
f"OS Version: {uname.version}\n"
f"Architecture: {uname.machine}\n"
f"Platform: {platform.platform(aliased=True)}\n"
f"\n"
"\n"
f"Python exe: {sys.executable}\n"
# replace line breaks with spaces (use chr(10) since '\n' isn't allowed in f-strings...)
f"Python version: {sys.version.replace(chr(10), ' ')}\n"
Expand All @@ -452,15 +462,18 @@ def _build_log(self, command):
f"Virtual env: {hasattr(sys, 'real_prefix') or sys.base_prefix != sys.prefix}\n"
# for conda, prefix and base_prefix are likely the same but contain a conda-meta dir.
f"Conda env: {(Path(sys.prefix) / 'conda-meta').exists()}\n"
f"\n"
"\n"
f"Briefcase: {__version__}\n"
f"Target platform: {command.platform}\n"
f"Target format: {command.output_format}\n"
f"\n"
f"Environment Variables:\n"
"\n"
"Environment Variables:\n"
f"{sanitized_env_vars}\n"
f"\n"
f"Briefcase Log:\n"
"\n"
"pyproject.toml:\n"
f"{pyproject_toml}\n"
"\n"
"Briefcase Log:\n"
f"{self.print.export_log()}"
)

Expand Down
41 changes: 32 additions & 9 deletions tests/console/test_Log.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import datetime
import logging
from io import TextIOBase
from pathlib import Path
from unittest.mock import MagicMock, PropertyMock, call

import pytest
Expand Down Expand Up @@ -162,7 +163,7 @@ def test_save_log_to_file_do_not_log(command):
assert len(logger.stacktraces) == 0


def test_save_log_to_file_no_exception(mock_now, command, tmp_path):
def test_save_log_to_file_no_exception(mock_now, command, tmp_path, monkeypatch):
"""Log file contains everything printed to log; env vars are sanitized; no
stacktrace if one is not captured."""
command.tools.os.environ = {
Expand Down Expand Up @@ -203,13 +204,18 @@ def test_save_log_to_file_no_exception(mock_now, command, tmp_path):
with command.tools.input.wait_bar("abort message..."):
raise KeyboardInterrupt

project_root = tmp_path / "project_root"
project_root.mkdir(exist_ok=True)
monkeypatch.chdir(project_root)
with open("pyproject.toml", "w", encoding="utf-8") as f:
f.writelines(["[section]\n", "name = 'project'\n\n\n\n\n"])

logger.save_log_to_file(command=command)

log_filepath = tmp_path / "logs/briefcase.2022_06_25-16_12_29.dev.log"

assert log_filepath.exists()
with open(log_filepath, encoding="utf-8") as log:
log_contents = log.read()
log_contents = log_filepath.read_text(encoding="utf-8")

assert log_contents.startswith("Date/Time: 2022-06-25 16:12:29")
assert "this is debug output" in log_contents
Expand All @@ -235,6 +241,7 @@ def test_save_log_to_file_no_exception(mock_now, command, tmp_path):
assert "wait message... done" in log_contents
assert "abort message... started" in log_contents
assert "abort message... aborted" in log_contents
assert "pyproject.toml:\n[section]\nname = 'project'\n\nBriefcase" in log_contents

assert TRACEBACK_HEADER not in log_contents
assert EXTRA_HEADER not in log_contents
Expand All @@ -253,8 +260,7 @@ def test_save_log_to_file_with_exception(mock_now, command, tmp_path):
log_filepath = tmp_path / "logs/briefcase.2022_06_25-16_12_29.dev.log"

assert log_filepath.exists()
with open(log_filepath, encoding="utf-8") as log:
log_contents = log.read()
log_contents = log_filepath.read_text(encoding="utf-8")

assert len(logger.stacktraces) == 1
assert log_contents.startswith("Date/Time: 2022-06-25 16:12:29")
Expand All @@ -277,8 +283,7 @@ def test_save_log_to_file_with_multiple_exceptions(mock_now, command, tmp_path):
log_filepath = tmp_path / "logs/briefcase.2022_06_25-16_12_29.dev.log"

assert log_filepath.exists()
with open(log_filepath, encoding="utf-8") as log:
log_contents = log.read()
log_contents = log_filepath.read_text(encoding="utf-8")

assert len(logger.stacktraces) == 4
assert log_contents.startswith("Date/Time: 2022-06-25 16:12:29")
Expand Down Expand Up @@ -306,8 +311,7 @@ def extra3():
logger.add_log_file_extra(extra)
logger.save_log_to_file(command=command)
log_filepath = tmp_path / "logs/briefcase.2022_06_25-16_12_29.dev.log"
with open(log_filepath, encoding="utf-8") as log:
log_contents = log.read()
log_contents = log_filepath.read_text(encoding="utf-8")

assert EXTRA_HEADER in log_contents
assert "Log extra 1" in log_contents
Expand All @@ -334,6 +338,25 @@ def extra1():
assert log_filepath.stat().st_size == 0


def test_save_log_to_file_missing_pyproject(mock_now, command, tmp_path, monkeypatch):
"""Log file contains pyproject read exception if it's missing."""
logger = Log()
logger.save_log = True

# ensure in a directory without a pyproject.toml
monkeypatch.chdir(tmp_path)
Path(tmp_path / "pyproject.toml").unlink(missing_ok=True)

logger.save_log_to_file(command=command)

log_filepath = tmp_path / "logs/briefcase.2022_06_25-16_12_29.dev.log"

assert log_filepath.exists()
log_contents = log_filepath.read_text(encoding="utf-8")

assert "pyproject.toml:\n[Errno 2] No such file or directory" in log_contents


def test_save_log_to_file_fail_to_make_logs_dir(
mock_now,
command,
Expand Down

0 comments on commit f322cf1

Please sign in to comment.