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
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
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
# Changelog

## v1.1.5 (2025-09-14)

### Improvements

- **Adaptive Console Sizing**: Enhanced terminal output display
- Console width is 80% of terminal width, capped at 120 characters
- Console height is terminal height minus buffer (5 lines)
- Automatic terminal size detection with fallback to default sizes (80x24)
- Dynamic sizing based on actual terminal dimensions

### Fixes

- **Text Truncation Prevention**: Completely eliminated text truncation in CLI output
- Template names and descriptions are now fully displayed without "..." truncation
- Table columns automatically adjust to content length to prevent text cutting
- Added `overflow="fold"` and `no_wrap=False` settings to Rich tables
- Template listing now shows complete template names (e.g., `fastapi-custom-response` instead of `fastapi-custom-respo...`)
- **Fixing the object `console` not found error**
- this critical error was occurred every version before this version.
- this error was occurred because of the mismatched logic between distribute github actions workflow and the top `__init__.py` file of fastkit project package.
- This issue was discovered during the development of version 1.1.2, and I spent a lot of time troubleshooting it. I believe this was due to my lack of development experience. I sincerely apologize.

## v1.1.4 (deprecated)

this version was hotfix build, but it is deprecated.

The issues that were being addressed during the development of this version remained unresolved and were fixed in version v1.1.5.

For more details, please refer to the CHANGELOG.md file for v1.1.5.

## v1.1.3 (2025-09-13)

### Templates
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