Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 1 addition & 2 deletions .github/workflows/distribute.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ jobs:
run: echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT

- name: Update version in __init__.py
run: |
echo "__version__ = '${{ steps.tag.outputs.TAG_NAME }}'" > src/fastapi_fastkit/__init__.py
run: echo "__version__ = '${{ steps.tag.outputs.TAG_NAME }}'" > src/fastapi_fastkit/__init__.py

- name: Build package
run: pdm build
Expand Down
11 changes: 1 addition & 10 deletions src/fastapi_fastkit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1 @@
__version__ = "1.1.3"

import os

from rich.console import Console

if "PYTEST_CURRENT_TEST" in os.environ:
console = Console(no_color=True)
else:
console = Console()
__version__ = "1.1.5"
8 changes: 6 additions & 2 deletions src/fastapi_fastkit/backend/package_managers/pdm_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@
import sys
from typing import List

from fastapi_fastkit import console
from fastapi_fastkit.core.exceptions import BackendExceptions
from fastapi_fastkit.utils.logging import debug_log, get_logger
from fastapi_fastkit.utils.main import handle_exception, print_error, print_success
from fastapi_fastkit.utils.main import (
console,
handle_exception,
print_error,
print_success,
)

from .base import BasePackageManager

Expand Down
8 changes: 6 additions & 2 deletions src/fastapi_fastkit/backend/package_managers/pip_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@
import sys
from typing import List

from fastapi_fastkit import console
from fastapi_fastkit.core.exceptions import BackendExceptions
from fastapi_fastkit.utils.logging import debug_log, get_logger
from fastapi_fastkit.utils.main import handle_exception, print_error, print_success
from fastapi_fastkit.utils.main import (
console,
handle_exception,
print_error,
print_success,
)

from .base import BasePackageManager

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@
import subprocess
from typing import List

from fastapi_fastkit import console
from fastapi_fastkit.core.exceptions import BackendExceptions
from fastapi_fastkit.utils.logging import debug_log, get_logger
from fastapi_fastkit.utils.main import handle_exception, print_error, print_success
from fastapi_fastkit.utils.main import (
console,
handle_exception,
print_error,
print_success,
)

from .base import BasePackageManager

Expand Down
8 changes: 6 additions & 2 deletions src/fastapi_fastkit/backend/package_managers/uv_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@
import subprocess
from typing import List

from fastapi_fastkit import console
from fastapi_fastkit.core.exceptions import BackendExceptions
from fastapi_fastkit.utils.logging import debug_log, get_logger
from fastapi_fastkit.utils.main import handle_exception, print_error, print_success
from fastapi_fastkit.utils.main import (
console,
handle_exception,
print_error,
print_success,
)

from .base import BasePackageManager

Expand Down
13 changes: 8 additions & 5 deletions src/fastapi_fastkit/cli.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# TODO : add a feature to automatically fix appropriate fastkit output console size
# --------------------------------------------------------------------------
# The Module defines main and core CLI operations for FastAPI-fastkit.
#
Expand Down Expand Up @@ -31,6 +30,7 @@
from fastapi_fastkit.core.exceptions import CLIExceptions
from fastapi_fastkit.core.settings import FastkitConfig
from fastapi_fastkit.utils.logging import get_logger, setup_logging
from fastapi_fastkit.utils.main import console as utils_console
from fastapi_fastkit.utils.main import (
create_info_table,
is_fastkit_project,
Expand All @@ -41,7 +41,9 @@
validate_email,
)

from . import __version__, console
console = utils_console

from . import __version__


@click.group()
Expand Down Expand Up @@ -97,6 +99,7 @@ def echo(ctx: Context) -> None:
Deploy FastAPI app foundation instantly at your local!

---

- Project Maintainer : [link=mailto:bbbong9@gmail.com]bnbong(JunHyeok Lee)[/link]
- Current Version : {__version__}
- Github : [link]https://github.com/bnbong/FastAPI-fastkit[/link]
Expand Down Expand Up @@ -135,8 +138,7 @@ def list_templates(ctx: Context) -> None:
print_warning("No available templates.")
return

table = create_info_table("Available Templates")

template_data = {}
for template in templates:
template_path = os.path.join(template_dir, template)
readme_path = os.path.join(template_path, "README.md-tpl")
Expand All @@ -148,8 +150,9 @@ def list_templates(ctx: Context) -> None:
if first_line.startswith("# "):
description = first_line[2:]

table.add_row(template, description)
template_data[template] = description

table = create_info_table("Available Templates", template_data)
console.print(table)


Expand Down
131 changes: 121 additions & 10 deletions src/fastapi_fastkit/utils/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
from rich.table import Table
from rich.text import Text

from fastapi_fastkit import console
from fastapi_fastkit.core.settings import settings
from fastapi_fastkit.utils.logging import debug_log, get_logger

Expand All @@ -25,6 +24,66 @@
REGEX = r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b"


def get_optimal_console_size() -> tuple[int, int]:
Copy link

Copilot AI Sep 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Tuple[int, int] from typing module instead of tuple[int, int] for better compatibility with older Python versions. The lowercase tuple annotation requires Python 3.9+.

Copilot uses AI. Check for mistakes.
"""
Get optimal console size based on terminal dimensions.

Returns:
tuple: (width, height) - optimal console dimensions
"""
try:
# Get terminal size
terminal_size = os.get_terminal_size()
width = terminal_size.columns
height = terminal_size.lines

# Set minimum and maximum constraints
min_width = 80
max_width = 120
min_height = 24

# Calculate optimal width (80% of terminal width, but within constraints)
optimal_width = max(min_width, min(max_width, int(width * 0.8)))
# Calculate optimal height (leave some space for prompt and buffer)
optimal_height = max(min_height, height - 5)

return optimal_width, optimal_height
except (OSError, ValueError):
# Fallback to default size if terminal size detection fails
return 80, 24


def create_adaptive_console() -> Console:
"""
Create a console instance with adaptive sizing based on terminal dimensions.

Returns:
Console: Rich console instance with optimal sizing
"""
if "PYTEST_CURRENT_TEST" in os.environ:
return Console(no_color=True)

width, height = get_optimal_console_size()
return Console(width=width, height=height)


# Initialize console with adaptive sizing
console = create_adaptive_console()


def _get_adaptive_panel_width(message: str) -> int:
"""
Calculate optimal panel width based on message length and terminal size.

:param message: Message content
:return: Optimal panel width
"""
optimal_width, _ = get_optimal_console_size()
# Use message length + padding, but constrain to reasonable bounds
min_width = min(len(message) + 10, optimal_width - 4)
return max(40, min_width) # Minimum 40 chars, leave margin for borders


def print_error(
message: str,
title: str = "Error",
Expand All @@ -42,7 +101,9 @@ def print_error(
error_text = Text()
error_text.append("❌ ", style="bold red")
error_text.append(message)
console.print(Panel(error_text, border_style="red", title=title))

panel_width = _get_adaptive_panel_width(message)
console.print(Panel(error_text, border_style="red", title=title, width=panel_width))

# Log error for debugging purposes (internal logging)
debug_log(f"Error: {message}", "error")
Expand Down Expand Up @@ -81,7 +142,11 @@ def print_success(
success_text = Text()
success_text.append("✨ ", style="bold yellow")
success_text.append(message, style="bold green")
console.print(Panel(success_text, border_style="green", title=title))

panel_width = _get_adaptive_panel_width(message)
console.print(
Panel(success_text, border_style="green", title=title, width=panel_width)
)


def print_warning(
Expand All @@ -97,7 +162,11 @@ def print_warning(
warning_text = Text()
warning_text.append("⚠️ ", style="bold yellow")
warning_text.append(message)
console.print(Panel(warning_text, border_style="yellow", title=title))

panel_width = _get_adaptive_panel_width(message)
console.print(
Panel(warning_text, border_style="yellow", title=title, width=panel_width)
)


def print_info(message: str, title: str = "Info", console: Console = console) -> None:
Expand All @@ -111,7 +180,9 @@ def print_info(message: str, title: str = "Info", console: Console = console) ->
info_text = Text()
info_text.append("ℹ ", style="bold blue")
info_text.append(message)
console.print(Panel(info_text, border_style="blue", title=title))

panel_width = _get_adaptive_panel_width(message)
console.print(Panel(info_text, border_style="blue", title=title, width=panel_width))


def create_info_table(
Expand All @@ -121,21 +192,61 @@ def create_info_table(
console: Console = console,
) -> Table:
"""
Create a table for displaying information.
Create a table for displaying information that never truncates text.

:param title: Title for the table
:param data: Dictionary of data to populate the table
:param show_header: Whether to show table headers
:param console: Rich console instance
:return: Configured Rich Table instance
"""
table = Table(title=title, show_header=show_header, title_style="bold magenta")
table.add_column("Field", style="cyan")
table.add_column("Value", style="green")
# Calculate exact content lengths if data exists
if data:
max_field_length = max(len(str(key)) for key in data.keys())
max_value_length = max(len(str(value)) for value in data.values())

# Set column widths to exactly match the longest content
# Add small padding to ensure content fits comfortably
field_width = max_field_length + 2
value_width = max_value_length + 2
else:
# Default widths for empty tables
field_width = 15
value_width = 30

# Create table that prioritizes full text display over terminal fitting
table = Table(
title=title,
show_header=show_header,
title_style="bold magenta",
expand=False, # Never expand to terminal width
width=None, # Let table size itself based on content
pad_edge=False, # Reduce padding to save space
)

# Add columns with settings that prevent any truncation
table.add_column(
"Field",
style="cyan",
no_wrap=False, # Allow wrapping instead of truncating
width=field_width, # Exact width for content
min_width=field_width, # Minimum width to prevent shrinking
max_width=None, # No maximum width limit
overflow="fold", # Fold text instead of truncating
)
table.add_column(
"Value",
style="green",
no_wrap=False, # Allow wrapping instead of truncating
width=value_width, # Exact width for content
min_width=value_width, # Minimum width to prevent shrinking
max_width=None, # No maximum width limit
overflow="fold", # Fold text instead of truncating
)

if data:
for key, value in data.items():
table.add_row(key, value)
table.add_row(str(key), str(value))

return table

Expand Down
Loading
Loading