132 lines
5.2 KiB
Python
132 lines
5.2 KiB
Python
from .text_formatter import TextFormatter
|
|
from .duration_formatter import DurationFormatter
|
|
from .size_formatter import SizeFormatter
|
|
from .date_formatter import DateFormatter
|
|
from .extension_formatter import ExtensionFormatter
|
|
from .resolution_formatter import ResolutionFormatter
|
|
from .track_formatter import TrackFormatter
|
|
from .special_info_formatter import SpecialInfoFormatter
|
|
import logging
|
|
import inspect
|
|
import os
|
|
|
|
|
|
# Set up logging conditionally
|
|
if os.getenv('FORMATTER_LOG', '0') == '1':
|
|
logging.basicConfig(filename='formatter.log', level=logging.INFO,
|
|
format='%(asctime)s - %(levelname)s - %(message)s')
|
|
else:
|
|
logging.basicConfig(level=logging.CRITICAL) # Disable logging
|
|
|
|
|
|
class FormatterApplier:
|
|
"""Class to apply multiple formatters in correct order"""
|
|
|
|
# Define the global order of all formatters
|
|
FORMATTER_ORDER = [
|
|
# Data formatters first (transform raw data)
|
|
DurationFormatter.format_seconds,
|
|
DurationFormatter.format_hhmmss,
|
|
DurationFormatter.format_hhmm,
|
|
DurationFormatter.format_full,
|
|
SizeFormatter.format_size,
|
|
SizeFormatter.format_size_full,
|
|
DateFormatter.format_modification_date,
|
|
DateFormatter.format_year,
|
|
ExtensionFormatter.format_extension_info,
|
|
ResolutionFormatter.get_frame_class_from_resolution,
|
|
ResolutionFormatter.format_resolution_p,
|
|
ResolutionFormatter.format_resolution_dimensions,
|
|
TrackFormatter.format_video_track,
|
|
TrackFormatter.format_audio_track,
|
|
TrackFormatter.format_subtitle_track,
|
|
SpecialInfoFormatter.format_special_info,
|
|
|
|
# Text formatters second (transform text content)
|
|
TextFormatter.uppercase,
|
|
TextFormatter.lowercase,
|
|
TextFormatter.camelcase,
|
|
|
|
# Markup formatters last (add visual styling)
|
|
TextFormatter.bold,
|
|
TextFormatter.italic,
|
|
TextFormatter.underline,
|
|
TextFormatter.bold_green,
|
|
TextFormatter.bold_cyan,
|
|
TextFormatter.bold_magenta,
|
|
TextFormatter.bold_yellow,
|
|
TextFormatter.green,
|
|
TextFormatter.yellow,
|
|
TextFormatter.magenta,
|
|
TextFormatter.cyan,
|
|
TextFormatter.red,
|
|
TextFormatter.blue,
|
|
TextFormatter.grey,
|
|
TextFormatter.dim,
|
|
]
|
|
|
|
@staticmethod
|
|
def apply_formatters(value, formatters):
|
|
"""Apply multiple formatters to value in the global order"""
|
|
if not isinstance(formatters, list):
|
|
formatters = [formatters] if formatters else []
|
|
|
|
# Sort formatters according to the global order
|
|
ordered_formatters = sorted(formatters, key=lambda f: FormatterApplier.FORMATTER_ORDER.index(f) if f in FormatterApplier.FORMATTER_ORDER else len(FormatterApplier.FORMATTER_ORDER))
|
|
|
|
# Get caller info
|
|
frame = inspect.currentframe()
|
|
if frame and frame.f_back:
|
|
caller = f"{frame.f_back.f_code.co_filename}:{frame.f_back.f_lineno} in {frame.f_back.f_code.co_name}"
|
|
else:
|
|
caller = "Unknown"
|
|
|
|
logging.info(f"Caller: {caller}")
|
|
logging.info(f"Original formatters: {[f.__name__ if hasattr(f, '__name__') else str(f) for f in formatters]}")
|
|
logging.info(f"Ordered formatters: {[f.__name__ if hasattr(f, '__name__') else str(f) for f in ordered_formatters]}")
|
|
logging.info(f"Input value: {repr(value)}")
|
|
|
|
# Apply in the ordered sequence
|
|
for formatter in ordered_formatters:
|
|
try:
|
|
old_value = value
|
|
value = formatter(value)
|
|
logging.debug(f"Applied {formatter.__name__ if hasattr(formatter, '__name__') else str(formatter)}: {repr(old_value)} -> {repr(value)}")
|
|
except Exception as e:
|
|
logging.error(f"Error applying {formatter.__name__ if hasattr(formatter, '__name__') else str(formatter)}: {e}")
|
|
value = "Unknown"
|
|
|
|
logging.info(f"Final value: {repr(value)}")
|
|
return value
|
|
|
|
@staticmethod
|
|
def format_data_item(item: dict) -> str | None:
|
|
"""Apply all formatting to a data item and return the formatted string"""
|
|
# Handle value formatting first (e.g., size formatting)
|
|
value = item.get("value")
|
|
if value is not None and value != "Not extracted":
|
|
value_formatters = item.get("value_formatters", [])
|
|
value = FormatterApplier.apply_formatters(value, value_formatters)
|
|
|
|
# Handle label formatting
|
|
label = item.get("label", "")
|
|
if label:
|
|
label_formatters = item.get("label_formatters", [])
|
|
label = FormatterApplier.apply_formatters(label, label_formatters)
|
|
|
|
# Create the display string
|
|
if value is not None:
|
|
display_string = f"{label}: {value}"
|
|
else:
|
|
display_string = label
|
|
|
|
# Handle display formatting (e.g., color)
|
|
display_formatters = item.get("display_formatters", [])
|
|
display_string = FormatterApplier.apply_formatters(display_string, display_formatters)
|
|
|
|
return display_string
|
|
|
|
@staticmethod
|
|
def format_data_items(data: list[dict]) -> list:
|
|
"""Apply formatting to a list of data items"""
|
|
return [FormatterApplier.format_data_item(item) for item in data] |