Skip to content

Commit

Permalink
improvement: Replace rich logger with loguru which produces nicer…
Browse files Browse the repository at this point in the history
… log formatting and requires less setup (#250)

* improvement: Replace `rich` logger with `loguru` which produces nicer log formatting and requires less setup

* enable selftest CI to see log format in CI

* more thoroughly switch to loguru

* fix

* Remove Loguru loggers from pickle

* add Loguru intercept handler

* because of the intercept handler we can continue to use a standard logger

* use loguru for global logs in Task class

* stick to the default loggers for most stuff now

* add changelog

* more logger reverts
  • Loading branch information
NiklasRosenstein authored Aug 5, 2024
1 parent 5eca574 commit c19220a
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 48 deletions.
5 changes: 5 additions & 0 deletions .changelog/_unreleased.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

[[entries]]
id = "b6fb5e00-0bed-4e07-8cf3-c16c394d40fe"
type = "improvement"
description = "Replace `rich` logger with `loguru` which produces nicer log formatting and requires less setup"
2 changes: 1 addition & 1 deletion kraken-build/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ networkx = "^3.1"
packaging = "^23.1"
pex = "^2.1.156"
python = ">=3.10"
rich = "^13.4.2"
termcolor = "^2.3.0"
tomli = "^2.0.1"
tomli-w = "^1.0.0"
tomlkit = "^0.13.0"
typeapi = "^2.0.0"
typing-extensions = ">=4.6.0"
loguru = "^0.7.2"

[tool.poetry.dev-dependencies]
localimport = "^1.7.6"
Expand Down
41 changes: 29 additions & 12 deletions kraken-build/src/kraken/common/_option_sets.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import argparse
import inspect
import logging
import sys
from dataclasses import dataclass
from typing import ClassVar

logger = logging.getLogger(__name__)
from loguru import logger


@dataclass(frozen=True)
Expand Down Expand Up @@ -41,25 +43,40 @@ def collect(cls, args: argparse.Namespace) -> "LoggingOptions":
)

def init_logging(self, force_color: bool = False) -> None:
import logging

from rich.console import Console
from rich.logging import RichHandler

verbosity = self.verbosity - self.quietness
if verbosity > 1:
level = logging.DEBUG
level = "DEBUG"
elif verbosity > 0:
level = logging.INFO
level = "INFO"
elif verbosity == 0:
level = logging.WARNING
level = "WARNING"
elif verbosity < 0:
level = logging.ERROR
level = "ERROR"
else:
assert False, verbosity

console = Console(force_terminal=True if force_color else None)
logging.basicConfig(level=level, format="%(message)s", handlers=[RichHandler(console=console)])
# Intercept standard logs and send them to Loguru.
class InterceptHandler(logging.Handler):
def emit(self, record: logging.LogRecord) -> None:
# Get corresponding Loguru level if it exists.
level: str | int
try:
level = logger.level(record.levelname).name
except ValueError:
level = record.levelno

# Find caller from where originated the logged message.
frame, depth = inspect.currentframe(), 0
while frame and (depth == 0 or frame.f_code.co_filename == logging.__file__):
frame = frame.f_back
depth += 1

logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())

logging.basicConfig(handlers=[InterceptHandler()], level=0, force=True)

logger.remove()
logger.add(sys.stderr, level=level)


@dataclass
Expand Down
37 changes: 10 additions & 27 deletions kraken-build/src/kraken/common/findpython.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,10 @@
import sys
from collections.abc import Iterable, Iterator, Sequence
from pathlib import Path
from typing import TYPE_CHECKING, ClassVar
from typing import ClassVar

from typing_extensions import NotRequired, TypedDict

if TYPE_CHECKING:
import rich.table

logger = logging.getLogger(__name__)
DEFAULT_CACHE_PATH = Path("~/.cache/krakenw/python-interpreters.json")

Expand Down Expand Up @@ -217,22 +214,21 @@ def evaluate_candidates(
return interpreters


def build_rich_table(interpreters: Iterable[Interpreter]) -> rich.table.Table:
def print_interpreters(interpreters: Iterable[Interpreter]) -> None:
"""
Gets a table of all viable Python interpreters on the system.
Requires that the `rich` package is installed.
Prints the interpeter information to stdout, colored.
"""

import rich.table
from kraken.common import Color, colored

tb = rich.table.Table("Path", "Version")
for interpreter in interpreters:
prefix = " "
version = interpreter["version"]
version_color: Color = "grey"
if interpreter.get("selected"):
version += " *"
tb.add_row(interpreter["path"], version)
return tb
prefix = " *"
version_color = "cyan"
print(colored(prefix, "grey"), colored(interpreter["path"], "green"), f"({colored(version, version_color)})")


def match_version_constraint(constraint: str, version: str) -> bool:
Expand All @@ -248,19 +244,6 @@ def match_version_constraint(constraint: str, version: str) -> bool:
def main() -> None:
import argparse

try:
import rich
import rich.table

def tabulate(interpreters: Iterable[Interpreter]) -> None:
rich.print(build_rich_table(interpreters))

except ImportError:

def tabulate(interpreters: Iterable[Interpreter]) -> None:
for interpreter in interpreters:
print(interpreter)

parser = argparse.ArgumentParser()
parser.add_argument("-c", "--constraint", help="Find a Python interpreter with the given constraint.")
args = parser.parse_args()
Expand All @@ -272,7 +255,7 @@ def tabulate(interpreters: Iterable[Interpreter]) -> None:
if match_version_constraint(args.constraint, interpreter["version"]):
interpreter["selected"] = True

tabulate(interpreters)
print_interpreters(interpreters)


if __name__ == "__main__":
Expand Down
10 changes: 5 additions & 5 deletions kraken-build/src/kraken/core/system/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from pathlib import Path
from typing import TYPE_CHECKING, Any, ForwardRef, Generic, Literal, TypeVar, cast, overload

from loguru import logger

from kraken.common import Supplier
from kraken.core.address import Address
Expand All @@ -32,7 +33,6 @@

T = TypeVar("T")
T_Task = TypeVar("T_Task", bound="Task")
logger = logging.getLogger(__name__)


@dataclasses.dataclass
Expand Down Expand Up @@ -247,7 +247,7 @@ def add_tag(self, name: str, *, reason: str, origin: str | None = None) -> None:
if name not in self.__tags:
self.__tags[name] = set()

logger.debug("Adding tag %r (reason: %r, origin: %r) to %s", name, reason, origin, self.address)
logger.debug("Adding tag {!r} (reason: {!r}, origin: {!r}) to {}", name, reason, origin, self.address)
self.__tags[name].add(TaskTag(name, reason, origin))

def remove_tag(self, tag: TaskTag) -> None:
Expand All @@ -258,10 +258,10 @@ def remove_tag(self, tag: TaskTag) -> None:
try:
self.__tags[tag.name].discard(tag)
except KeyError:
logger.debug("Attempted to remove tag %r from %s, but it does not exist", tag, self.address)
logger.debug("Attempted to remove tag {!r} from {}, but it does not exist", tag, self.address)
pass
else:
logger.debug("Removed tag %r from %s", tag, self.address)
logger.debug("Removed tag {!r} from {}", tag, self.address)

def get_tags(self, name: str) -> Collection[TaskTag]:
"""
Expand Down Expand Up @@ -539,7 +539,7 @@ def __del__(self) -> None:
pass
else:
logger.warning(
'BackgroundTask.teardown() did not get called on task "%s". This may cause some issues, such '
'BackgroundTask.teardown() did not get called on task "{}". This may cause some issues, such '
"as an error during serialization or zombie processes.",
self.address,
)
Expand Down
1 change: 1 addition & 0 deletions kraken-wrapper/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Repository = "https://github.com/kraken-build/kraken-build/"

[tool.poetry.dependencies]
kraken-build = "0.37.3"
loguru = "^0.7.2"
packaging = "^23.1"
python = ">=3.10"
termcolor = "^2.3.0"
Expand Down
4 changes: 1 addition & 3 deletions kraken-wrapper/src/kraken/wrapper/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,16 +228,14 @@ def auth_check(auth: AuthModel, args: AuthOptions, host: str, username: str, pas


def list_pythons(prog: str, argv: list[str]) -> NoReturn:
import rich
from kraken.common import findpython

if argv:
logger.error(f"{prog}: unexpected arguments")
sys.exit(1)

interpreters = findpython.evaluate_candidates(findpython.get_candidates(), findpython.InterpreterVersionCache())
table = findpython.build_rich_table(interpreters)
rich.print(table)
findpython.print_interpreters(interpreters)
sys.exit(0)


Expand Down

0 comments on commit c19220a

Please sign in to comment.