Skip to content

Commit

Permalink
♻️ Order Logger methods alphabetically and add docstrings
Browse files Browse the repository at this point in the history
  • Loading branch information
jemrobinson committed Jul 27, 2023
1 parent 66138de commit f5522dc
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 45 deletions.
4 changes: 2 additions & 2 deletions data_safe_haven/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ def callback(
"""Arguments to the main executable"""
logger = LoggingSingleton()
if output:
logger.log_file(output)
logger.set_log_file(output)
if verbosity:
logger.verbosity(verbosity)
logger.set_verbosity(verbosity)
if version:
print(f"Data Safe Haven {__version__}") # noqa: T201
raise typer.Exit()
Expand Down
100 changes: 57 additions & 43 deletions data_safe_haven/utility/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,21 +111,29 @@ def __init__(self):
logging.getLogger("azure.mgmt.core.policies").setLevel(logging.ERROR)
logging.getLogger("urllib3.connectionpool").setLevel(logging.ERROR)

def log_file(self, file_path: PathType) -> None:
"""Set a log file handler"""
file_handler = LoggingHandlerPlainFile(
self.rich_format, self.date_fmt, str(file_path)
)
for h in self.handlers:
if isinstance(h, LoggingHandlerPlainFile):
self.removeHandler(h)
self.addHandler(file_handler)
def ask(self, message: str, default: str | None = None) -> str:
"""Ask user a question, formatted as a log message"""
formatted = self.format_msg(message, logging.INFO)
if default:
return Prompt.ask(formatted, default=default)
return Prompt.ask(formatted)

def verbosity(self, verbosity: int) -> None:
"""Set verbosity"""
self.setLevel(
max(logging.INFO - 10 * (verbosity if verbosity else 0), logging.NOTSET)
)
def choose(
self,
message: str,
choices: list[str] | None = None,
default: str | None = None,
) -> str:
"""Ask a user to choose among options, formatted as a log message"""
formatted = self.format_msg(message, logging.INFO)
if default:
return Prompt.ask(formatted, choices=choices, default=default)
return Prompt.ask(formatted, choices=choices)

def confirm(self, message: str, *, default_to_yes: bool) -> bool:
"""Ask a user to confirm an action, formatted as a log message"""
formatted = self.format_msg(message, logging.INFO)
return Confirm.ask(formatted, default=default_to_yes)

def format_msg(self, message: str, level: int = logging.INFO) -> str:
"""Format a message using rich handler"""
Expand All @@ -147,35 +155,12 @@ def format_msg(self, message: str, level: int = logging.INFO) -> str:
)
return message

def style(self, message: str) -> str:
"""Apply logging style to a string"""
markup = self.format_msg(message)
return RichStringAdaptor(coloured=True).to_string(markup)

# Loggable wrappers for confirm/ask/choice
def confirm(self, message: str, *, default_to_yes: bool) -> bool:
formatted = self.format_msg(message, logging.INFO)
return Confirm.ask(formatted, default=default_to_yes)

def ask(self, message: str, default: str | None = None) -> str:
formatted = self.format_msg(message, logging.INFO)
if default:
return Prompt.ask(formatted, default=default)
return Prompt.ask(formatted)

def choose(
self,
message: str,
choices: list[str] | None = None,
default: str | None = None,
) -> str:
formatted = self.format_msg(message, logging.INFO)
if default:
return Prompt.ask(formatted, choices=choices, default=default)
return Prompt.ask(formatted, choices=choices)

# Apply a level to non-leveled messages
def parse(self, message: str) -> None:
"""
Parse a message that starts with a log-level token.
This function is designed to handle messages from non-Python code inside this package.
"""
tokens = message.split(":")
level, remainder = tokens[0], ":".join(tokens[1:]).strip()
if level == "CRITICAL":
Expand All @@ -191,10 +176,39 @@ def parse(self, message: str) -> None:
else:
return self.info(message.strip())

# Create a table
def set_log_file(self, file_path: PathType) -> None:
"""Set a log file handler"""
file_handler = LoggingHandlerPlainFile(
self.rich_format, self.date_fmt, str(file_path)
)
for h in self.handlers:
if isinstance(h, LoggingHandlerPlainFile):
self.removeHandler(h)
self.addHandler(file_handler)

def set_verbosity(self, verbosity: int) -> None:
"""Set verbosity"""
self.setLevel(
max(logging.INFO - 10 * (verbosity if verbosity else 0), logging.NOTSET)
)

def style(self, message: str) -> str:
"""Apply logging style to a string"""
markup = self.format_msg(message)
return RichStringAdaptor(coloured=True).to_string(markup)

def tabulate(
self, header: list[str] | None = None, rows: list[list[str]] | None = None
) -> list[str]:
"""Generate a table from header and rows
Args:
header: The table header
rows: The table rows
Returns:
A list of strings representing the table
"""
table = Table()
if header:
for item in header:
Expand Down

0 comments on commit f5522dc

Please sign in to comment.