Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into nr/263
Browse files Browse the repository at this point in the history
  • Loading branch information
NiklasRosenstein committed Aug 5, 2024
2 parents f652695 + c19220a commit 1e29fb0
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 61 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"
11 changes: 11 additions & 0 deletions kraken-build/.changelog/_unreleased.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[[entries]]
id = "91681271-376e-45b5-b8c3-7bf718053586"
type = "feature"
description = "Propagate `SSL_CERT_FILE` or `REQUESTS_CA_BUNDLE` environment variable to PDM repository configuration on non-Linux systems (due to https://github.com/pdm-project/pdm/issues/3076)"
author = "@NiklasRosenstein"

[[entries]]
id = "7b0576b8-d990-44c1-ab5b-395f06ab1e5f"
type = "improvement"
description = "Permit PyPI index URLs with trailing slash (e.g. `.../simple/`) in `PythonSettings.add_package_index()`"
author = "@NiklasRosenstein"
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
56 changes: 43 additions & 13 deletions kraken-build/src/kraken/std/python/buildsystem/pdm.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import subprocess as sp
from collections.abc import Sequence
from pathlib import Path
import sys
from typing import Any

from kraken.common import NotSet
Expand All @@ -21,6 +22,11 @@

logger = logging.getLogger(__name__)

# NOTE: We can't inline this expression where we need it because Mypy understands the expression and will permanently
# turn off a code path on the corresponding systme, which can lead to type errors downstream (typically
# unreachable code).
_is_linux = sys.platform == "linux"


class PdmPyprojectHandler(PyprojectHandler):
"""
Expand Down Expand Up @@ -136,23 +142,47 @@ def requires_login(self) -> bool:
return True

def login(self, settings: PythonSettings) -> None:
# PDM does not support SSL_CERT_FILE or REQUESTS_CA_BUNDLE directly on non-Linux because it uses the
# `truststore` package (see https://github.com/pdm-project/pdm/issues/3076 for more information).
# On these systems, if these variables are set, we configure the certificates in the PDM configuration
# instead.
if not _is_linux:
ca_certs = next(filter(None, (os.environ.get(k) for k in ["SSL_CERT_FILE", "REQUESTS_CA_BUNDLE"])), None)
else:
ca_certs = None

for index in settings.package_indexes.values():
if index.is_package_source and index.credentials:
if index.is_package_source and (index.credentials or ca_certs):
commands = [
["pdm", "config", f"pypi.{index.alias}.url", index.index_url],
[
"pdm",
"config",
f"pypi.{index.alias}.username",
index.credentials[0],
],
[
"pdm",
"config",
f"pypi.{index.alias}.password",
index.credentials[1],
],
]
if index.credentials:
commands.append(
[
"pdm",
"config",
f"pypi.{index.alias}.username",
index.credentials[0],
]
)
commands.append(
[
"pdm",
"config",
f"pypi.{index.alias}.password",
index.credentials[1],
]
)
if ca_certs is not None:
# See https://pdm-project.org/latest/usage/config/#configure-https-certificates
commands.append(
[
"pdm",
"config",
f"pypi.{index.alias}.ca_certs",
os.path.abspath(ca_certs),
]
)
for command in commands:
safe_command = command[:-1] + ["MASKED"]
logger.info("$ %s", safe_command)
Expand Down
2 changes: 2 additions & 0 deletions kraken-build/src/kraken/std/python/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ def add_package_index(
upload_url = "https://test.pypi.org/legacy"
elif index_url.endswith("/simple"):
upload_url = index_url[: -len("/simple")]
elif index_url.endswith("/simple/"):
upload_url = index_url[: -len("/simple/")]
else:
raise ValueError(f"cannot derive upload URL for alias {alias!r} and index URL {index_url!r}")

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 1e29fb0

Please sign in to comment.