Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 28 additions & 10 deletions src/repoman/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@
import sys
from dataclasses import dataclass
from importlib import metadata
from typing import TYPE_CHECKING

from rich.console import Console
from rich.layout import Layout
from rich.panel import Panel
from rich.table import Table
from rich.text import Text

from repoman.utils.theme.theme import set_theme
from repoman.utils.ui import get_console

if TYPE_CHECKING:
from rich.console import Console


@dataclass
Expand Down Expand Up @@ -146,11 +149,26 @@ def get_debug_info() -> Environment:

def _make_debug_layout(env: Environment) -> Layout:
"""Build a Layout for debug info: header + packages | env vars."""
header_text = Text(
f"{env.interpreter_name} {env.interpreter_version} | {env.interpreter_path} | {env.platform}",
style="bold",
header_table = Table(highlight=True, box=None, show_header=False)
header_table.add_row(
Text("Interpreter Name", style="rosewater"),
Text(env.interpreter_name, style="bold"),
)
header_table.add_row(
Text("Interpreter Version", style="rosewater"),
Text(env.interpreter_version, style="bold"),
)
header_table.add_row(
Text("Interpreter Path", style="rosewater"),
Text(env.interpreter_path, style="bold"),
)
header_table.add_row(Text("Platform", style="rosewater"), Text(env.platform, style="bold"))
header = Panel(
header_table,
title="Debug Information",
title_align="left",
border_style="bright_blue",
)
header = Panel(header_text, title="Debug Info", title_align="left", border_style="bright_blue")

packages_table = Table(
highlight=True,
Expand All @@ -171,7 +189,7 @@ def _make_debug_layout(env: Environment) -> Layout:

layout = Layout()
layout.split_column(
Layout(header, name="header", size=5),
Layout(header, name="header", size=7),
Layout(name="main", ratio=1),
)
layout["main"].split_row(
Expand Down Expand Up @@ -207,7 +225,7 @@ def _make_debug_panel(env: Environment) -> Panel:
Text.assemble(*[Text(str(pkg), style="bold") for pkg in env.packages]),
)
table.add_row(
Text("Enviroment Variables", style="rosewater"),
Text("Environment Variables", style="rosewater"),
Text.assemble(*[Text(str(var), style="bold") for var in env.variables]),
)
return Panel(table, title="Debug Information", title_align="left")
Expand All @@ -216,11 +234,11 @@ def _make_debug_panel(env: Environment) -> Panel:
def debug_info(console: Console | None = None) -> None:
"""Return debug information."""
if not console:
console = Console(theme=set_theme())
console = get_console()

env = get_debug_info()

from repoman.cli.messages.layout import ( # noqa: PLC0415 - deferred to avoid circular import
from repoman.utils.ui.layout import ( # noqa: PLC0415 - deferred to avoid circular import
use_layout,
)

Expand Down
2 changes: 1 addition & 1 deletion src/repoman/cli/commands/config/show.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
key_not_in_template,
warning_panel,
)
from repoman.cli.messages.layout import layout_config_show_template, use_layout
from repoman.resources import get_copier_answers_template
from repoman.utils.logging import get_logger_console
from repoman.utils.ui.layout import layout_config_show_template, use_layout

app = Typer(
add_completion=True,
Expand Down
2 changes: 1 addition & 1 deletion src/repoman/cli/commands/config/validate_.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
schema_not_found_skipping_validation,
warning_panel,
)
from repoman.cli.messages.layout import layout_validation_failed, use_layout
from repoman.config import load_answers, missing_commit_for_copier_update
from repoman.copier import ValidationReport, load_prompt_schema, validate_answers
from repoman.utils.logging import get_logger_console
from repoman.utils.ui.layout import layout_validation_failed, use_layout

app = Typer(
add_completion=True,
Expand Down
2 changes: 1 addition & 1 deletion src/repoman/cli/messages/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
warning: warning_panel() — yellow panels for warnings.
success: project_created(), project_updated(), command_created() — green panels.
dry_run: dry_run_create(), dry_run_update(), dry_run_command_add() — blue panels.
layout: use_layout() and layout builders — multi-panel Layout for wide terminals.
repoman.utils.ui.layout: use_layout() and layout builders — multi-panel Layout for wide terminals.
error_text: Pure string helpers (e.g. answers_file_not_found()) for panel content.
capability: supports_unicode_markdown() — Unicode/terminal capability detection.
"""
Expand Down
2 changes: 1 addition & 1 deletion src/repoman/cli/messages/dry_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from rich.panel import Panel
from rich.text import Text

from repoman.cli.messages.layout import (
from repoman.utils.ui.layout import (
layout_dry_run_command_add,
layout_dry_run_create,
layout_dry_run_update,
Expand Down
2 changes: 1 addition & 1 deletion src/repoman/cli/messages/success.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from rich.text import Text

from repoman.cli.messages.capability import supports_unicode_markdown
from repoman.cli.messages.layout import (
from repoman.utils.ui.layout import (
layout_command_created,
layout_project_created,
layout_project_updated,
Expand Down
46 changes: 4 additions & 42 deletions src/repoman/utils/logging.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Logging utilities for repoman CLI application."""

import os
import sys
from datetime import UTC, datetime
from logging import DEBUG, INFO, Formatter, Logger, getLogger
from logging.handlers import RotatingFileHandler
Expand All @@ -12,22 +11,7 @@
from rich.logging import RichHandler

from repoman.config import Config
from repoman.utils.theme.theme import set_theme


def _is_running_in_pytest() -> bool:
"""Check if code is running inside pytest.

Returns:
True if running in pytest, False otherwise
"""
# Check for pytest in sys.modules or environment variable
# Also check if we're being imported during pytest collection
return (
"pytest" in sys.modules
or "PYTEST_CURRENT_TEST" in os.environ
or any("pytest" in str(arg) for arg in sys.argv if isinstance(arg, str))
)
from repoman.utils.ui.console import get_console


def _set_up_logger(
Expand Down Expand Up @@ -61,18 +45,7 @@ def _set_up_logger(
return module_logger

if not console:
# In pytest, disable Rich formatting to avoid ANSI codes in test assertions
if _is_running_in_pytest():
# Use a console that outputs plain text (no colors/formatting)
# Write to stdout instead of stderr so CliRunner can capture it
console = Console(
file=sys.stdout,
force_terminal=False,
legacy_windows=False,
no_color=True,
)
else:
console = Console(theme=set_theme("dark"))
console = get_console()

rich_handler = RichHandler(rich_tracebacks=True, console=console)

Expand Down Expand Up @@ -139,6 +112,7 @@ def get_logger_console(
# Fall back to default if conversion fails
log_level = INFO
root_logger = _set_up_logger(
console=console,
use_rotating_file_handler=True,
log_level=log_level,
)
Expand All @@ -163,19 +137,7 @@ def get_logger_console(
console = rich_handler.console
return logger, console

# If no console was found and none was provided, create a new one
if console is None:
# In pytest, disable Rich formatting to avoid ANSI codes in test assertions
if _is_running_in_pytest():
# Use a console that outputs plain text (no colors/formatting)
# Write to stdout instead of stderr so CliRunner can capture it
console = Console(
file=sys.stdout,
force_terminal=False,
legacy_windows=False,
no_color=True,
)
else:
console = Console()
console = get_console()

return logger, console
7 changes: 7 additions & 0 deletions src/repoman/utils/ui/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""Shared Rich UI utilities for the repoman CLI."""

from repoman.utils.ui.console import get_console
from repoman.utils.ui.layout import use_layout
from repoman.utils.ui.theme.theme import set_theme

__all__ = ["get_console", "set_theme", "use_layout"]
50 changes: 50 additions & 0 deletions src/repoman/utils/ui/console.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""Shared Rich console helpers for CLI output."""

import os
import sys

from rich.console import Console

from repoman.utils.ui.theme.theme import set_theme

_console_cache: list[Console | None] = [None]


def _is_running_in_pytest() -> bool:
"""Check if code is running inside pytest.

Returns:
True if running in pytest, False otherwise
"""
# Check for pytest in sys.modules or environment variable
# Also check if we're being imported during pytest collection
return (
"pytest" in sys.modules
or "PYTEST_CURRENT_TEST" in os.environ
or any("pytest" in str(arg) for arg in sys.argv if isinstance(arg, str))
)


def get_console() -> Console:
"""Return the process-wide Rich console used by CLI rendering."""
console = _console_cache[0]

if console is not None:
if _is_running_in_pytest():
console.file = sys.stdout
return console

if _is_running_in_pytest():
# Use a console that outputs plain text (no colors/formatting)
# Write to stdout instead of stderr so CliRunner can capture it
console = Console(
file=sys.stdout,
force_terminal=False,
legacy_windows=False,
no_color=True,
)
else:
console = Console(theme=set_theme("dark"))

_console_cache[0] = console
return console
Loading
Loading