refactor: Consolidate text color decorators and update related properties

This commit is contained in:
sHa
2026-01-04 20:49:55 +00:00
parent 3f8b158135
commit 336b030a6b
11 changed files with 136 additions and 280 deletions

BIN
dist/renamer-0.8.3-py3-none-any.whl vendored Normal file

Binary file not shown.

View File

@@ -1,6 +1,6 @@
[project] [project]
name = "renamer" name = "renamer"
version = "0.8.2" version = "0.8.3"
description = "Terminal-based media file renamer and metadata viewer" description = "Terminal-based media file renamer and metadata viewer"
readme = "README.md" readme = "README.md"
requires-python = ">=3.11" requires-python = ">=3.11"

View File

@@ -1,6 +1,6 @@
class SizeFormatter: class SizeFormatter:
"""Class for formatting file sizes""" """Class for formatting file sizes"""
@staticmethod @staticmethod
def format_size(bytes_size: int) -> str: def format_size(bytes_size: int) -> str:
"""Format bytes to human readable with unit""" """Format bytes to human readable with unit"""
@@ -9,9 +9,14 @@ class SizeFormatter:
return f"{bytes_size:.1f} {unit}" return f"{bytes_size:.1f} {unit}"
bytes_size /= 1024 bytes_size /= 1024
return f"{bytes_size:.1f} TB" return f"{bytes_size:.1f} TB"
@staticmethod @staticmethod
def format_size_full(bytes_size: int) -> str: def format_size_full(bytes_size: int) -> str:
"""Format size with both human readable and bytes""" """Format size with both human readable and bytes"""
size_formatted = SizeFormatter.format_size(bytes_size) size_formatted = SizeFormatter.format_size(bytes_size)
return f"{size_formatted} ({bytes_size:,} bytes)" return f"{size_formatted} ({bytes_size:,} bytes)"
@staticmethod
def format_size_short(bytes_size: int) -> str:
"""Format size with only human readable"""
return SizeFormatter.format_size(bytes_size)

View File

@@ -42,106 +42,15 @@ class TextDecorators:
return decorator return decorator
@staticmethod @staticmethod
def green() -> Callable: def colour(name) -> Callable:
"""Decorator to color text green.""" """Decorator to colour text."""
def decorator(func: Callable) -> Callable:
@wraps(func)
def wrapper(*args, **kwargs) -> str:
result = func(*args, **kwargs)
if result == "":
return ""
return TextFormatter.green(str(result))
return wrapper
return decorator
@staticmethod
def yellow() -> Callable:
"""Decorator to color text yellow."""
def decorator(func: Callable) -> Callable: def decorator(func: Callable) -> Callable:
@wraps(func) @wraps(func)
def wrapper(*args, **kwargs) -> str: def wrapper(*args, **kwargs) -> str:
result = func(*args, **kwargs) result = func(*args, **kwargs)
if not result: if not result:
return "" return ""
return TextFormatter.yellow(str(result)) return TextFormatter.colour(name, str(result))
return wrapper
return decorator
@staticmethod
def cyan() -> Callable:
"""Decorator to color text cyan."""
def decorator(func: Callable) -> Callable:
@wraps(func)
def wrapper(*args, **kwargs) -> str:
result = func(*args, **kwargs)
if not result:
return ""
return TextFormatter.cyan(str(result))
return wrapper
return decorator
@staticmethod
def magenta() -> Callable:
"""Decorator to color text magenta."""
def decorator(func: Callable) -> Callable:
@wraps(func)
def wrapper(*args, **kwargs) -> str:
result = func(*args, **kwargs)
if not result:
return ""
return TextFormatter.magenta(str(result))
return wrapper
return decorator
@staticmethod
def red() -> Callable:
"""Decorator to color text red."""
def decorator(func: Callable) -> Callable:
@wraps(func)
def wrapper(*args, **kwargs) -> str:
result = func(*args, **kwargs)
if not result:
return ""
return TextFormatter.red(str(result))
return wrapper
return decorator
@staticmethod
def orange() -> Callable:
"""Decorator to color text orange."""
def decorator(func: Callable) -> Callable:
@wraps(func)
def wrapper(*args, **kwargs) -> str:
result = func(*args, **kwargs)
if not result:
return ""
return TextFormatter.orange(str(result))
return wrapper
return decorator
@staticmethod
def blue() -> Callable:
"""Decorator to color text blue."""
def decorator(func: Callable) -> Callable:
@wraps(func)
def wrapper(*args, **kwargs) -> str:
result = func(*args, **kwargs)
if not result:
return ""
return TextFormatter.blue(str(result))
return wrapper
return decorator
@staticmethod
def grey() -> Callable:
"""Decorator to color text grey."""
def decorator(func: Callable) -> Callable:
@wraps(func)
def wrapper(*args, **kwargs) -> str:
result = func(*args, **kwargs)
if not result:
return ""
return TextFormatter.grey(str(result))
return wrapper return wrapper
return decorator return decorator

View File

@@ -27,84 +27,45 @@ class TextFormatter:
return ''.join(word.capitalize() for word in text.split()) return ''.join(word.capitalize() for word in text.split())
@staticmethod @staticmethod
def bold_green(text: str) -> str: def colour(colour_name: str, text: str) -> str:
"""Deprecated: Use [TextFormatter.bold, TextFormatter.green] instead""" """Generic method to color text with given colour name."""
import warnings return f"[{colour_name}]{text}[/{colour_name}]"
warnings.warn(
"TextFormatter.bold_green is deprecated. Use [TextFormatter.bold, TextFormatter.green] instead.",
DeprecationWarning,
stacklevel=2
)
return f"[bold green]{text}[/bold green]"
@staticmethod
def bold_cyan(text: str) -> str:
"""Deprecated: Use [TextFormatter.bold, TextFormatter.cyan] instead"""
import warnings
warnings.warn(
"TextFormatter.bold_cyan is deprecated. Use [TextFormatter.bold, TextFormatter.cyan] instead.",
DeprecationWarning,
stacklevel=2
)
return f"[bold cyan]{text}[/bold cyan]"
@staticmethod
def bold_magenta(text: str) -> str:
"""Deprecated: Use [TextFormatter.bold, TextFormatter.magenta] instead"""
import warnings
warnings.warn(
"TextFormatter.bold_magenta is deprecated. Use [TextFormatter.bold, TextFormatter.magenta] instead.",
DeprecationWarning,
stacklevel=2
)
return f"[bold magenta]{text}[/bold magenta]"
@staticmethod
def bold_yellow(text: str) -> str:
"""Deprecated: Use [TextFormatter.bold, TextFormatter.yellow] instead"""
import warnings
warnings.warn(
"TextFormatter.bold_yellow is deprecated. Use [TextFormatter.bold, TextFormatter.yellow] instead.",
DeprecationWarning,
stacklevel=2
)
return f"[bold yellow]{text}[/bold yellow]"
@staticmethod @staticmethod
def green(text: str) -> str: def green(text: str) -> str:
return f"[green]{text}[/green]" return TextFormatter.colour("green", text)
@staticmethod @staticmethod
def yellow(text: str) -> str: def yellow(text: str) -> str:
return f"[yellow]{text}[/yellow]" return TextFormatter.colour("yellow", text)
@staticmethod @staticmethod
def orange(text: str) -> str: def orange(text: str) -> str:
return f"[orange]{text}[/orange]" return TextFormatter.colour("orange", text)
@staticmethod @staticmethod
def magenta(text: str) -> str: def magenta(text: str) -> str:
return f"[magenta]{text}[/magenta]" return TextFormatter.colour("magenta", text)
@staticmethod @staticmethod
def cyan(text: str) -> str: def cyan(text: str) -> str:
return f"[cyan]{text}[/cyan]" return TextFormatter.colour("cyan", text)
@staticmethod @staticmethod
def red(text: str) -> str: def red(text: str) -> str:
return f"[red]{text}[/red]" return TextFormatter.colour("red", text)
@staticmethod @staticmethod
def blue(text: str) -> str: def blue(text: str) -> str:
return f"[blue]{text}[/blue]" return TextFormatter.colour("blue", text)
@staticmethod @staticmethod
def grey(text: str) -> str: def grey(text: str) -> str:
return f"[grey]{text}[/grey]" return TextFormatter.colour("grey", text)
@staticmethod @staticmethod
def dim(text: str) -> str: def dim(text: str) -> str:
return f"[dim]{text}[/dim]" return TextFormatter.colour("dimgray", text)
@staticmethod @staticmethod
def link(url: str, text: str | None = None) -> str: def link(url: str, text: str | None = None) -> str:
@@ -119,4 +80,4 @@ class TextFormatter:
if url and url != "<None>" and url.startswith("http"): if url and url != "<None>" and url.startswith("http"):
# Use OSC 8 hyperlink escape sequence for clickable links # Use OSC 8 hyperlink escape sequence for clickable links
return f"\x1b]8;;{url}\x1b\\Open in TMDB\x1b]8;;\x1b\\" return f"\x1b]8;;{url}\x1b\\Open in TMDB\x1b]8;;\x1b\\"
return url return url

View File

@@ -78,9 +78,9 @@ class TestTextDecorators:
assert obj.get_text() == "[bold]Hello[/bold]" assert obj.get_text() == "[bold]Hello[/bold]"
def test_green_decorator(self): def test_green_decorator(self):
"""Test @text_decorators.green() decorator.""" """Test @text_decorators.colour(name="green") decorator."""
class TestClass: class TestClass:
@text_decorators.green() @text_decorators.colour(name="green")
def get_text(self): def get_text(self):
return "Success" return "Success"

View File

@@ -78,12 +78,6 @@ class TestTextFormatter:
result = TextFormatter.red("test") result = TextFormatter.red("test")
assert result == "[red]test[/red]" assert result == "[red]test[/red]"
def test_bold_green_deprecated(self):
"""Test deprecated bold_green method."""
with pytest.warns(DeprecationWarning):
result = TextFormatter.bold_green("test")
assert "[bold green]" in result
class TestDurationFormatter: class TestDurationFormatter:
"""Test DurationFormatter functionality.""" """Test DurationFormatter functionality."""

View File

@@ -32,17 +32,16 @@ class MediaPanelView:
"""Return formatted selected data""" """Return formatted selected data"""
return "\n".join( return "\n".join(
[ [
self._props.title("Media Info Summary"),
self._props.media_title, self._props.media_title,
self._props.media_year, self._props.media_year,
self._props.media_genres, self._props.tmdb_genres,
self._props.media_duration, self._props.media_duration,
self._props.media_file_size, self._props.media_file_size,
self._props.media_file_extension, self._props.media_file_extension,
self._props.selected_frame_class, self._props.selected_frame_class,
self._props.selected_source, self._props.selected_source,
self._props.selected_audio_langs, self._props.selected_audio_langs,
self._props.selected_database_info, self._props.tmdb_database_info,
self._props.selected_order, self._props.selected_order,
] ]
) )
@@ -52,7 +51,7 @@ class MediaPanelView:
"""Return formatted file info""" """Return formatted file info"""
return "\n".join( return "\n".join(
[ [
self._props.title("File Info"), self._props.file_info_title,
self._props.file_path, self._props.file_path,
self._props.file_size, self._props.file_size,
self._props.file_name, self._props.file_name,
@@ -66,7 +65,6 @@ class MediaPanelView:
"""Return formatted TMDB data""" """Return formatted TMDB data"""
return "\n".join( return "\n".join(
[ [
self._props.title("TMDB Data"),
self._props.tmdb_id, self._props.tmdb_id,
self._props.tmdb_title, self._props.tmdb_title,
self._props.tmdb_original_title, self._props.tmdb_original_title,

View File

@@ -44,40 +44,48 @@ class MediaPanelProperties:
# ============================================================ # ============================================================
@property @property
@conditional_decorators.wrap("Path: ") @conditional_decorators.wrap(left="󰷊 ", right="")
@text_decorators.blue() @text_decorators.uppercase()
@text_decorators.bold()
def file_info_title(self) -> str:
"""Get file info title formatted with label."""
return "File Info"
@property
@conditional_decorators.wrap("├ 󰙅 : ")
@text_decorators.colour(name="blue")
@text_decorators.escape() @text_decorators.escape()
def file_path(self) -> str: def file_path(self) -> str:
"""Get file path formatted with label.""" """Get file path formatted with label."""
return self._extractor.get("file_path") return self._extractor.get("file_path")
@property @property
@conditional_decorators.wrap("Size: ") @conditional_decorators.wrap(left="├  : ")
@text_decorators.green() @text_decorators.colour(name="bisque")
@size_decorators.size_full() @size_decorators.size_full()
def file_size(self) -> str: def file_size(self) -> str:
"""Get file size formatted with label.""" """Get file size formatted with label."""
return self._extractor.get("file_size") return self._extractor.get("file_size")
@property @property
@conditional_decorators.wrap("Name: ") @conditional_decorators.wrap(left="├ 󰈙 : ")
@text_decorators.cyan() @text_decorators.colour(name="bisque")
@text_decorators.escape() @text_decorators.escape()
def file_name(self) -> str: def file_name(self) -> str:
"""Get file name formatted with label.""" """Get file name formatted with label."""
return self._extractor.get("file_name") return self._extractor.get("file_name")
@property @property
@conditional_decorators.wrap("Modified: ") @conditional_decorators.wrap(left="├ 󱋡 : ")
@text_decorators.magenta() @text_decorators.colour("bisque")
@date_decorators.modification_date() @date_decorators.modification_date()
def modification_time(self) -> str: def modification_time(self) -> str:
"""Get modification time formatted with label.""" """Get modification time formatted with label."""
return self._extractor.get("modification_time") return self._extractor.get("modification_time")
@property @property
@conditional_decorators.wrap("Extension: ") @conditional_decorators.wrap(left="└  : ")
@text_decorators.green() @text_decorators.colour(name="bisque")
@extension_decorators.extension_info() @extension_decorators.extension_info()
def extension_fileinfo(self) -> str: def extension_fileinfo(self) -> str:
"""Get extension from FileInfo formatted with label.""" """Get extension from FileInfo formatted with label."""
@@ -88,63 +96,62 @@ class MediaPanelProperties:
# ============================================================ # ============================================================
@property @property
@text_decorators.blue() @conditional_decorators.wrap("󰈚 TMDB : ")
@conditional_decorators.wrap("ID: ") @text_decorators.colour(name="yellow")
@text_decorators.yellow()
@conditional_decorators.default("<None>") @conditional_decorators.default("<None>")
def tmdb_id(self) -> str: def tmdb_id(self) -> str:
"""Get TMDB ID formatted with label.""" """Get TMDB ID formatted with label."""
return self._extractor.get("tmdb_id", "TMDB") return self._extractor.get("tmdb_id", "TMDB")
@property @property
@text_decorators.blue() @text_decorators.colour(name="blue")
@conditional_decorators.wrap("Title: ") @conditional_decorators.wrap(left="├ 󰗴 : ")
@text_decorators.yellow() @text_decorators.colour(name="yellow")
@conditional_decorators.default("<None>") @conditional_decorators.default("<None>")
def tmdb_title(self) -> str: def tmdb_title(self) -> str:
"""Get TMDB title formatted with label.""" """Get TMDB title formatted with label."""
return self._extractor.get("title", "TMDB") return self._extractor.get("title", "TMDB")
@property @property
@text_decorators.blue() @text_decorators.colour(name="blue")
@conditional_decorators.wrap("Original Title: ") @conditional_decorators.wrap(left="├ 󰗴 : ")
@text_decorators.yellow() @text_decorators.colour(name="bisque")
@conditional_decorators.default("<None>") @conditional_decorators.default("<None>")
def tmdb_original_title(self) -> str: def tmdb_original_title(self) -> str:
"""Get TMDB original title formatted with label.""" """Get TMDB original title formatted with label."""
return self._extractor.get("original_title", "TMDB") return self._extractor.get("original_title", "TMDB")
@property @property
@text_decorators.blue() @text_decorators.colour(name="blue")
@conditional_decorators.wrap("Year: ") @conditional_decorators.wrap(left="├  : ")
@text_decorators.yellow() @text_decorators.colour(name="bisque")
@conditional_decorators.default("<None>") @conditional_decorators.default("<None>")
def tmdb_year(self) -> str: def tmdb_year(self) -> str:
"""Get TMDB year formatted with label.""" """Get TMDB year formatted with label."""
return self._extractor.get("year", "TMDB") return self._extractor.get("year", "TMDB")
@property @property
@text_decorators.blue() @text_decorators.colour(name="blue")
@conditional_decorators.wrap("Countries: ") @conditional_decorators.wrap(left="├  : ")
@text_decorators.yellow() @text_decorators.colour(name="bisque")
@conditional_decorators.default("<None>") @conditional_decorators.default("<None>")
def tmdb_countries(self) -> str: def tmdb_countries(self) -> str:
"""Get TMDB production countries formatted with label.""" """Get TMDB production countries formatted with label."""
return self._extractor.get("production_countries", "TMDB") return self._extractor.get("production_countries", "TMDB")
@property @property
@text_decorators.blue() @text_decorators.colour(name="blue")
@conditional_decorators.wrap("Genres: ") @conditional_decorators.wrap(left="├ 󰴂 : ")
@text_decorators.yellow() @text_decorators.colour(name="cyan")
@conditional_decorators.default("<None>") @conditional_decorators.default("<None>")
def tmdb_genres(self) -> str: def tmdb_genres(self) -> str:
"""Get TMDB genres formatted with label.""" """Get TMDB genres formatted with label."""
return self._extractor.get("genres", "TMDB") return self._extractor.get("genres", "TMDB")
@property @property
@text_decorators.blue() @text_decorators.colour(name="blue")
@conditional_decorators.wrap("Database Info: ") @conditional_decorators.wrap(left="├ 󰻾 : ")
@text_decorators.yellow() @text_decorators.colour(name="bisque")
@conditional_decorators.default("<None>") @conditional_decorators.default("<None>")
@special_info_decorators.database_info() @special_info_decorators.database_info()
def tmdb_database_info(self) -> str: def tmdb_database_info(self) -> str:
@@ -152,8 +159,9 @@ class MediaPanelProperties:
return self._extractor.get("movie_db", "TMDB") return self._extractor.get("movie_db", "TMDB")
@property @property
# @text_decorators.blue() # @text_decorators.colour(name="blue")
@conditional_decorators.default("") @conditional_decorators.wrap(left="")
@conditional_decorators.default(default_value="")
@text_decorators.url() @text_decorators.url()
def tmdb_url(self) -> str: def tmdb_url(self) -> str:
"""Get TMDB URL formatted with label.""" """Get TMDB URL formatted with label."""
@@ -165,7 +173,7 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("Title: ") @conditional_decorators.wrap("Title: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
def metadata_title(self) -> str: def metadata_title(self) -> str:
"""Get metadata title formatted with label.""" """Get metadata title formatted with label."""
@@ -173,7 +181,7 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("Duration: ") @conditional_decorators.wrap("Duration: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
@duration_decorators.duration_full() @duration_decorators.duration_full()
def metadata_duration(self) -> str: def metadata_duration(self) -> str:
@@ -182,7 +190,7 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("Artist: ") @conditional_decorators.wrap("Artist: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
def metadata_artist(self) -> str: def metadata_artist(self) -> str:
"""Get metadata artist formatted with label.""" """Get metadata artist formatted with label."""
@@ -194,7 +202,7 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("Duration: ") @conditional_decorators.wrap("Duration: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
@duration_decorators.duration_full() @duration_decorators.duration_full()
def mediainfo_duration(self) -> str: def mediainfo_duration(self) -> str:
@@ -203,7 +211,7 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("Frame Class: ") @conditional_decorators.wrap("Frame Class: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
def mediainfo_frame_class(self) -> str: def mediainfo_frame_class(self) -> str:
"""Get MediaInfo frame class formatted with label.""" """Get MediaInfo frame class formatted with label."""
@@ -211,7 +219,7 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("Resolution: ") @conditional_decorators.wrap("Resolution: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
@resolution_decorators.resolution_dimensions() @resolution_decorators.resolution_dimensions()
def mediainfo_resolution(self) -> str: def mediainfo_resolution(self) -> str:
@@ -220,7 +228,7 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("Aspect Ratio: ") @conditional_decorators.wrap("Aspect Ratio: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
def mediainfo_aspect_ratio(self) -> str: def mediainfo_aspect_ratio(self) -> str:
"""Get MediaInfo aspect ratio formatted with label.""" """Get MediaInfo aspect ratio formatted with label."""
@@ -228,7 +236,7 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("HDR: ") @conditional_decorators.wrap("HDR: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
def mediainfo_hdr(self) -> str: def mediainfo_hdr(self) -> str:
"""Get MediaInfo HDR formatted with label.""" """Get MediaInfo HDR formatted with label."""
@@ -236,7 +244,7 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("Audio Languages: ") @conditional_decorators.wrap("Audio Languages: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
def mediainfo_audio_langs(self) -> str: def mediainfo_audio_langs(self) -> str:
"""Get MediaInfo audio languages formatted with label.""" """Get MediaInfo audio languages formatted with label."""
@@ -244,7 +252,7 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("Anamorphic: ") @conditional_decorators.wrap("Anamorphic: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
def mediainfo_anamorphic(self) -> str: def mediainfo_anamorphic(self) -> str:
"""Get MediaInfo anamorphic formatted with label.""" """Get MediaInfo anamorphic formatted with label."""
@@ -252,7 +260,7 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("Extension: ") @conditional_decorators.wrap("Extension: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
@extension_decorators.extension_info() @extension_decorators.extension_info()
def mediainfo_extension(self) -> str: def mediainfo_extension(self) -> str:
@@ -261,7 +269,7 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("3D Layout: ") @conditional_decorators.wrap("3D Layout: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
def mediainfo_3d_layout(self) -> str: def mediainfo_3d_layout(self) -> str:
"""Get MediaInfo 3D layout formatted with label.""" """Get MediaInfo 3D layout formatted with label."""
@@ -273,7 +281,7 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("Order: ") @conditional_decorators.wrap("Order: ")
@text_decorators.yellow() @text_decorators.colour(name="yellow")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
def filename_order(self) -> str: def filename_order(self) -> str:
"""Get filename order formatted with label.""" """Get filename order formatted with label."""
@@ -281,15 +289,15 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("Movie title: ") @conditional_decorators.wrap("Movie title: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("") @conditional_decorators.default("")
def filename_title(self) -> str: def filename_title(self) -> str:
"""Get filename title formatted with label.""" """Get filename title formatted with label."""
return self._extractor.get("title", "Filename") return self._extractor.get("title", "Filename")
@property @property
@conditional_decorators.wrap("Year: ") @conditional_decorators.wrap(left="├  : ")
@text_decorators.grey() @text_decorators.colour(name="bisque")
@conditional_decorators.default("") @conditional_decorators.default("")
def filename_year(self) -> str: def filename_year(self) -> str:
"""Get filename year formatted with label.""" """Get filename year formatted with label."""
@@ -297,7 +305,7 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("Video source: ") @conditional_decorators.wrap("Video source: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
def filename_source(self) -> str: def filename_source(self) -> str:
"""Get filename source formatted with label.""" """Get filename source formatted with label."""
@@ -305,7 +313,7 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("Frame class: ") @conditional_decorators.wrap("Frame class: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
def filename_frame_class(self) -> str: def filename_frame_class(self) -> str:
"""Get filename frame class formatted with label.""" """Get filename frame class formatted with label."""
@@ -313,7 +321,7 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("HDR: ") @conditional_decorators.wrap("HDR: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
def filename_hdr(self) -> str: def filename_hdr(self) -> str:
"""Get filename HDR formatted with label.""" """Get filename HDR formatted with label."""
@@ -321,7 +329,7 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("Audio langs: ") @conditional_decorators.wrap("Audio langs: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
def filename_audio_langs(self) -> str: def filename_audio_langs(self) -> str:
"""Get filename audio languages formatted with label.""" """Get filename audio languages formatted with label."""
@@ -329,9 +337,9 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("Special info: ") @conditional_decorators.wrap("Special info: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
@text_decorators.blue() @text_decorators.colour(name="blue")
@special_info_decorators.special_info() @special_info_decorators.special_info()
def filename_special_info(self) -> str: def filename_special_info(self) -> str:
"""Get filename special info formatted with label.""" """Get filename special info formatted with label."""
@@ -339,7 +347,7 @@ class MediaPanelProperties:
@property @property
@conditional_decorators.wrap("Movie DB: ") @conditional_decorators.wrap("Movie DB: ")
@text_decorators.grey() @text_decorators.colour(name="grey")
@conditional_decorators.default("Not extracted") @conditional_decorators.default("Not extracted")
def filename_movie_db(self) -> str: def filename_movie_db(self) -> str:
"""Get filename movie DB formatted with label.""" """Get filename movie DB formatted with label."""
@@ -350,72 +358,63 @@ class MediaPanelProperties:
# ============================================================ # ============================================================
@property @property
@text_decorators.blue() @text_decorators.colour(name="blue")
@conditional_decorators.wrap("Duration: ") @conditional_decorators.wrap(left="├ 󰔚 : ")
@text_decorators.yellow() @text_decorators.colour(name="bisque")
@duration_decorators.duration_full() @duration_decorators.duration_full()
def media_duration(self) -> str: def media_duration(self) -> str:
"""Get media duration from best available source.""" """Get media duration from best available source."""
return self._extractor.get("duration") return self._extractor.get("duration")
@property @property
@text_decorators.blue() @text_decorators.colour(name="blue")
@conditional_decorators.wrap("Order: ") @conditional_decorators.wrap(left="└ 󰒾 : ")
@text_decorators.yellow() @text_decorators.colour(name="bisque")
@conditional_decorators.default("<None>") @conditional_decorators.default("<None>")
def selected_order(self) -> str: def selected_order(self) -> str:
"""Get selected order formatted with label.""" """Get selected order formatted with label."""
return self._extractor.get("order") return self._extractor.get("order")
@property @property
@text_decorators.blue() @text_decorators.colour(name="blue")
@conditional_decorators.wrap(left="󰿎 ") @conditional_decorators.wrap(left="󰿎 MOVIE : ")
@text_decorators.yellow() @text_decorators.colour(name="yellow")
@conditional_decorators.default("<None>") @conditional_decorators.default("<None>")
def media_title(self) -> str: def media_title(self) -> str:
"""Get selected title formatted with label.""" """Get selected title formatted with label."""
return self._extractor.get("title") return self._extractor.get("title")
@property @property
@text_decorators.blue() @text_decorators.colour(name="blue")
@conditional_decorators.wrap("Year: ") @conditional_decorators.wrap(left="├  : ")
@text_decorators.yellow() @text_decorators.colour(name="bisque")
@conditional_decorators.default("<None>") @conditional_decorators.default("<None>")
def media_year(self) -> str: def media_year(self) -> str:
"""Get selected year formatted with label.""" """Get selected year formatted with label."""
return self._extractor.get("year") return self._extractor.get("year")
@property @property
@text_decorators.blue() @text_decorators.colour(name="blue")
@conditional_decorators.wrap("Genres: ") @conditional_decorators.wrap(left="├  : ")
@text_decorators.cyan() @text_decorators.colour(name="green")
@conditional_decorators.default("<None>") @size_decorators.size_short()
def media_genres(self) -> str:
"""Get TMDB genres formatted with label."""
return self._extractor.get("genres")
@property
@text_decorators.blue()
@conditional_decorators.wrap("File size: ")
@text_decorators.green()
@size_decorators.size_full()
def media_file_size(self) -> str: def media_file_size(self) -> str:
"""Get media file size formatted with label.""" """Get media file size formatted with label."""
return self._extractor.get("file_size") return self._extractor.get("file_size")
@property @property
@text_decorators.blue() @text_decorators.colour(name="blue")
@conditional_decorators.wrap("Extension: ") @conditional_decorators.wrap(left="├  : ")
@text_decorators.green() @text_decorators.colour(name="bisque")
@extension_decorators.extension_info() @extension_decorators.extension_info()
def media_file_extension(self) -> str: def media_file_extension(self) -> str:
"""Get media file extension formatted with label.""" """Get media file extension formatted with label."""
return self._extractor.get("extension") return self._extractor.get("extension")
@property @property
@text_decorators.blue() @text_decorators.colour(name="blue")
@conditional_decorators.wrap("Special info: ") @conditional_decorators.wrap("Special info: ")
@text_decorators.yellow() @text_decorators.colour(name="yellow")
@conditional_decorators.default("<None>") @conditional_decorators.default("<None>")
@special_info_decorators.special_info() @special_info_decorators.special_info()
def selected_special_info(self) -> str: def selected_special_info(self) -> str:
@@ -423,58 +422,48 @@ class MediaPanelProperties:
return self._extractor.get("special_info") return self._extractor.get("special_info")
@property @property
@text_decorators.blue() @text_decorators.colour(name="blue")
@conditional_decorators.wrap("Source: ") @conditional_decorators.wrap(left="├  : ")
@text_decorators.yellow() @text_decorators.colour(name="bisque")
@conditional_decorators.default("<None>") @conditional_decorators.default("<None>")
def selected_source(self) -> str: def selected_source(self) -> str:
"""Get selected source formatted with label.""" """Get selected source formatted with label."""
return self._extractor.get("source") return self._extractor.get("source")
@property @property
@text_decorators.blue() @text_decorators.colour(name="blue")
@conditional_decorators.wrap("Frame class: ") @conditional_decorators.wrap(left="├ 󱣴 : ")
@text_decorators.yellow() @text_decorators.colour(name="bisque")
@conditional_decorators.default("<None>") @conditional_decorators.default("<None>")
def selected_frame_class(self) -> str: def selected_frame_class(self) -> str:
"""Get selected frame class formatted with label.""" """Get selected frame class formatted with label."""
return self._extractor.get("frame_class") return self._extractor.get("frame_class")
@property @property
@text_decorators.blue() @text_decorators.colour(name="blue")
@conditional_decorators.wrap("HDR: ") @conditional_decorators.wrap(left="├ 󰵽 : ")
@text_decorators.yellow() @text_decorators.colour(name="bisque")
@conditional_decorators.default("<None>") @conditional_decorators.default("<None>")
def selected_hdr(self) -> str: def selected_hdr(self) -> str:
"""Get selected HDR formatted with label.""" """Get selected HDR formatted with label."""
return self._extractor.get("hdr") return self._extractor.get("hdr")
@property @property
@text_decorators.blue() @text_decorators.colour(name="blue")
@conditional_decorators.wrap("Audio langs: ") @conditional_decorators.wrap(left="├ 󰗊 : ")
@text_decorators.yellow() @text_decorators.colour(name="bisque")
@conditional_decorators.default("<None>") @conditional_decorators.default("<None>")
def selected_audio_langs(self) -> str: def selected_audio_langs(self) -> str:
"""Get selected audio languages formatted with label.""" """Get selected audio languages formatted with label."""
return self._extractor.get("audio_langs") return self._extractor.get("audio_langs")
@property
@text_decorators.blue()
@conditional_decorators.wrap("Database Info: ")
@text_decorators.yellow()
@conditional_decorators.default("<None>")
@special_info_decorators.database_info()
def selected_database_info(self) -> str:
"""Get selected database info formatted with label."""
return self._extractor.get("movie_db")
@property @property
def video_tracks(self) -> list[str]: def video_tracks(self) -> list[str]:
"""Return formatted video track data""" """Return formatted video track data"""
tracks = self._extractor.get("video_tracks", "MediaInfo") or [] tracks = self._extractor.get("video_tracks", "MediaInfo") or []
return [self.video_track(track, i) for i, track in enumerate(tracks, start=1)] return [self.video_track(track, i) for i, track in enumerate(tracks, start=1)]
@text_decorators.green() @text_decorators.colour(name="green")
@conditional_decorators.wrap("Video Track {index}: ") @conditional_decorators.wrap("Video Track {index}: ")
@track_decorators.video_track() @track_decorators.video_track()
def video_track(self, track, index) -> str: def video_track(self, track, index) -> str:
@@ -487,7 +476,7 @@ class MediaPanelProperties:
tracks = self._extractor.get("audio_tracks", "MediaInfo") or [] tracks = self._extractor.get("audio_tracks", "MediaInfo") or []
return [self.audio_track(track, i) for i, track in enumerate(tracks, start=1)] return [self.audio_track(track, i) for i, track in enumerate(tracks, start=1)]
@text_decorators.yellow() @text_decorators.colour(name="yellow")
@conditional_decorators.wrap("Audio Track {index}: ") @conditional_decorators.wrap("Audio Track {index}: ")
@track_decorators.audio_track() @track_decorators.audio_track()
def audio_track(self, track, index) -> str: def audio_track(self, track, index) -> str:
@@ -502,7 +491,7 @@ class MediaPanelProperties:
self.subtitle_track(track, i) for i, track in enumerate(tracks, start=1) self.subtitle_track(track, i) for i, track in enumerate(tracks, start=1)
] ]
@text_decorators.magenta() @text_decorators.colour(name="magenta")
@conditional_decorators.wrap("Subtitle Track {index}: ") @conditional_decorators.wrap("Subtitle Track {index}: ")
@track_decorators.subtitle_track() @track_decorators.subtitle_track()
def subtitle_track(self, track, index) -> str: def subtitle_track(self, track, index) -> str:

View File

@@ -92,14 +92,14 @@ class ProposedFilenameView:
@property @property
@conditional_decorators.wrap(">> ", " <<") @conditional_decorators.wrap(">> ", " <<")
@text_decorators.green() @text_decorators.colour(name="green")
def rename_line_similar(self) -> str: def rename_line_similar(self) -> str:
"""Generate a simplified proposed filename for similarity checks.""" """Generate a simplified proposed filename for similarity checks."""
return escape(str(self)) return escape(str(self))
@property @property
@conditional_decorators.wrap(">> ", " <<") @conditional_decorators.wrap(left=">> ", right=" <<")
@text_decorators.orange() @text_decorators.colour(name="orange")
def rename_line_different(self) -> str: def rename_line_different(self) -> str:
"""Generate a detailed proposed filename for difference checks.""" """Generate a detailed proposed filename for difference checks."""
return escape(str(self)) return escape(str(self))

2
uv.lock generated
View File

@@ -462,7 +462,7 @@ wheels = [
[[package]] [[package]]
name = "renamer" name = "renamer"
version = "0.8.2" version = "0.8.3"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "langcodes" }, { name = "langcodes" },