loads of import fixes

This commit is contained in:
pacnpal
2024-11-17 19:47:18 +00:00
parent f71e174c0d
commit 97dd6d72f2
49 changed files with 1061 additions and 1062 deletions

View File

@@ -4,40 +4,59 @@ import logging
from enum import Enum, auto
from dataclasses import dataclass, field
from datetime import datetime
from typing import Dict, Any, List, Optional, Callable, TypeVar, Union, TypedDict, ClassVar, Tuple
import discord
from typing import (
Dict,
Any,
List,
Optional,
Callable,
TypeVar,
Union,
TypedDict,
ClassVar,
Tuple,
)
import discord # type: ignore
from .utils.exceptions import DisplayError
from ..utils.exceptions import DisplayError
logger = logging.getLogger("VideoArchiver")
T = TypeVar('T')
T = TypeVar("T")
class DisplayTheme(TypedDict):
"""Type definition for display theme"""
title_color: discord.Color
success_color: discord.Color
warning_color: discord.Color
error_color: discord.Color
info_color: discord.Color
class DisplaySection(Enum):
"""Available display sections"""
QUEUE_STATS = auto()
DOWNLOADS = auto()
COMPRESSIONS = auto()
ERRORS = auto()
HARDWARE = auto()
class DisplayCondition(Enum):
"""Display conditions for sections"""
HAS_ERRORS = "has_errors"
HAS_DOWNLOADS = "has_downloads"
HAS_COMPRESSIONS = "has_compressions"
@dataclass
class DisplayTemplate:
"""Template for status display sections"""
name: str
format_string: str
inline: bool = False
@@ -46,27 +65,28 @@ class DisplayTemplate:
formatter: Optional[Callable[[Dict[str, Any]], str]] = None
max_items: int = field(default=5) # Maximum items to display in lists
class StatusFormatter:
"""Formats status information for display"""
BYTE_UNITS: ClassVar[List[str]] = ['B', 'KB', 'MB', 'GB', 'TB']
BYTE_UNITS: ClassVar[List[str]] = ["B", "KB", "MB", "GB", "TB"]
TIME_THRESHOLDS: ClassVar[List[Tuple[float, str]]] = [
(60, 's'),
(3600, 'm'),
(float('inf'), 'h')
(60, "s"),
(3600, "m"),
(float("inf"), "h"),
]
@staticmethod
def format_bytes(bytes_value: Union[int, float]) -> str:
"""
Format bytes into human readable format.
Args:
bytes_value: Number of bytes to format
Returns:
Formatted string with appropriate unit
Raises:
ValueError: If bytes_value is negative
"""
@@ -84,13 +104,13 @@ class StatusFormatter:
def format_time(seconds: float) -> str:
"""
Format time duration.
Args:
seconds: Number of seconds to format
Returns:
Formatted time string
Raises:
ValueError: If seconds is negative
"""
@@ -107,13 +127,13 @@ class StatusFormatter:
def format_percentage(value: float) -> str:
"""
Format percentage value.
Args:
value: Percentage value to format (0-100)
Returns:
Formatted percentage string
Raises:
ValueError: If value is outside valid range
"""
@@ -125,14 +145,14 @@ class StatusFormatter:
def truncate_url(url: str, max_length: int = 50) -> str:
"""
Truncate URL to specified length.
Args:
url: URL to truncate
max_length: Maximum length for URL
Returns:
Truncated URL string
Raises:
ValueError: If max_length is less than 4
"""
@@ -140,6 +160,7 @@ class StatusFormatter:
raise ValueError("max_length must be at least 4")
return f"{url[:max_length]}..." if len(url) > max_length else url
class DisplayManager:
"""Manages status display configuration"""
@@ -148,7 +169,7 @@ class DisplayManager:
success_color=discord.Color.green(),
warning_color=discord.Color.gold(),
error_color=discord.Color.red(),
info_color=discord.Color.blurple()
info_color=discord.Color.blurple(),
)
def __init__(self) -> None:
@@ -165,7 +186,7 @@ class DisplayManager:
"Avg Processing Time: {avg_processing_time}\n"
"```"
),
order=1
order=1,
),
DisplaySection.DOWNLOADS: DisplayTemplate(
name="Active Downloads",
@@ -181,7 +202,7 @@ class DisplayManager:
"```"
),
order=2,
condition=DisplayCondition.HAS_DOWNLOADS
condition=DisplayCondition.HAS_DOWNLOADS,
),
DisplaySection.COMPRESSIONS: DisplayTemplate(
name="Active Compressions",
@@ -198,13 +219,13 @@ class DisplayManager:
"```"
),
order=3,
condition=DisplayCondition.HAS_COMPRESSIONS
condition=DisplayCondition.HAS_COMPRESSIONS,
),
DisplaySection.ERRORS: DisplayTemplate(
name="Error Statistics",
format_string="```\n{error_stats}```",
condition=DisplayCondition.HAS_ERRORS,
order=4
order=4,
),
DisplaySection.HARDWARE: DisplayTemplate(
name="Hardware Statistics",
@@ -215,11 +236,12 @@ class DisplayManager:
"Peak Memory Usage: {memory_usage}\n"
"```"
),
order=5
)
order=5,
),
}
self.theme = self.DEFAULT_THEME.copy()
class StatusDisplay:
"""Handles formatting and display of queue status information"""
@@ -229,20 +251,18 @@ class StatusDisplay:
@classmethod
async def create_queue_status_embed(
cls,
queue_status: Dict[str, Any],
active_ops: Dict[str, Any]
cls, queue_status: Dict[str, Any], active_ops: Dict[str, Any]
) -> discord.Embed:
"""
Create an embed displaying queue status and active operations.
Args:
queue_status: Dictionary containing queue status information
active_ops: Dictionary containing active operations information
Returns:
Discord embed containing formatted status information
Raises:
DisplayError: If there's an error creating the embed
"""
@@ -251,13 +271,12 @@ class StatusDisplay:
embed = discord.Embed(
title="Queue Status Details",
color=display.display_manager.theme["title_color"],
timestamp=datetime.utcnow()
timestamp=datetime.utcnow(),
)
# Add sections in order
sections = sorted(
display.display_manager.templates.items(),
key=lambda x: x[1].order
display.display_manager.templates.items(), key=lambda x: x[1].order
)
for section, template in sections:
@@ -265,9 +284,7 @@ class StatusDisplay:
# Check condition if exists
if template.condition:
if not display._check_condition(
template.condition,
queue_status,
active_ops
template.condition, queue_status, active_ops
):
continue
@@ -275,9 +292,13 @@ class StatusDisplay:
if section == DisplaySection.QUEUE_STATS:
display._add_queue_statistics(embed, queue_status, template)
elif section == DisplaySection.DOWNLOADS:
display._add_active_downloads(embed, active_ops.get('downloads', {}), template)
display._add_active_downloads(
embed, active_ops.get("downloads", {}), template
)
elif section == DisplaySection.COMPRESSIONS:
display._add_active_compressions(embed, active_ops.get('compressions', {}), template)
display._add_active_compressions(
embed, active_ops.get("compressions", {}), template
)
elif section == DisplaySection.ERRORS:
display._add_error_statistics(embed, queue_status, template)
elif section == DisplaySection.HARDWARE:
@@ -297,7 +318,7 @@ class StatusDisplay:
self,
condition: DisplayCondition,
queue_status: Dict[str, Any],
active_ops: Dict[str, Any]
active_ops: Dict[str, Any],
) -> bool:
"""Check if condition for displaying section is met"""
try:
@@ -316,185 +337,214 @@ class StatusDisplay:
self,
embed: discord.Embed,
queue_status: Dict[str, Any],
template: DisplayTemplate
template: DisplayTemplate,
) -> None:
"""Add queue statistics to the embed"""
try:
metrics = queue_status.get('metrics', {})
metrics = queue_status.get("metrics", {})
embed.add_field(
name=template.name,
value=template.format_string.format(
pending=queue_status.get('pending', 0),
processing=queue_status.get('processing', 0),
completed=queue_status.get('completed', 0),
failed=queue_status.get('failed', 0),
pending=queue_status.get("pending", 0),
processing=queue_status.get("processing", 0),
completed=queue_status.get("completed", 0),
failed=queue_status.get("failed", 0),
success_rate=self.formatter.format_percentage(
metrics.get('success_rate', 0) * 100
metrics.get("success_rate", 0) * 100
),
avg_processing_time=self.formatter.format_time(
metrics.get('avg_processing_time', 0)
)
metrics.get("avg_processing_time", 0)
),
),
inline=template.inline
inline=template.inline,
)
except Exception as e:
logger.error(f"Error adding queue statistics: {e}")
embed.add_field(
name=template.name,
value="```\nError displaying queue statistics```",
inline=template.inline
inline=template.inline,
)
def _add_active_downloads(
self,
embed: discord.Embed,
downloads: Dict[str, Any],
template: DisplayTemplate
self, embed: discord.Embed, downloads: Dict[str, Any], template: DisplayTemplate
) -> None:
"""Add active downloads information to the embed"""
try:
if downloads:
content = []
for url, progress in list(downloads.items())[:template.max_items]:
for url, progress in list(downloads.items())[: template.max_items]:
try:
content.append(template.format_string.format(
url=self.formatter.truncate_url(url),
percent=self.formatter.format_percentage(progress.get('percent', 0)),
speed=progress.get('speed', 'N/A'),
eta=progress.get('eta', 'N/A'),
size=f"{self.formatter.format_bytes(progress.get('downloaded_bytes', 0))}/"
f"{self.formatter.format_bytes(progress.get('total_bytes', 0))}",
start_time=progress.get('start_time', 'N/A'),
retries=progress.get('retries', 0)
))
content.append(
template.format_string.format(
url=self.formatter.truncate_url(url),
percent=self.formatter.format_percentage(
progress.get("percent", 0)
),
speed=progress.get("speed", "N/A"),
eta=progress.get("eta", "N/A"),
size=f"{self.formatter.format_bytes(progress.get('downloaded_bytes', 0))}/"
f"{self.formatter.format_bytes(progress.get('total_bytes', 0))}",
start_time=progress.get("start_time", "N/A"),
retries=progress.get("retries", 0),
)
)
except Exception as e:
logger.error(f"Error formatting download {url}: {e}")
continue
if len(downloads) > template.max_items:
content.append(f"\n... and {len(downloads) - template.max_items} more")
content.append(
f"\n... and {len(downloads) - template.max_items} more"
)
embed.add_field(
name=template.name,
value="".join(content) if content else "```\nNo active downloads```",
inline=template.inline
value=(
"".join(content) if content else "```\nNo active downloads```"
),
inline=template.inline,
)
else:
embed.add_field(
name=template.name,
value="```\nNo active downloads```",
inline=template.inline
inline=template.inline,
)
except Exception as e:
logger.error(f"Error adding active downloads: {e}")
embed.add_field(
name=template.name,
value="```\nError displaying downloads```",
inline=template.inline
inline=template.inline,
)
def _add_active_compressions(
self,
embed: discord.Embed,
compressions: Dict[str, Any],
template: DisplayTemplate
template: DisplayTemplate,
) -> None:
"""Add active compressions information to the embed"""
try:
if compressions:
content = []
for file_id, progress in list(compressions.items())[:template.max_items]:
for file_id, progress in list(compressions.items())[
: template.max_items
]:
try:
content.append(template.format_string.format(
filename=progress.get('filename', 'Unknown'),
percent=self.formatter.format_percentage(progress.get('percent', 0)),
elapsed_time=progress.get('elapsed_time', 'N/A'),
input_size=self.formatter.format_bytes(progress.get('input_size', 0)),
current_size=self.formatter.format_bytes(progress.get('current_size', 0)),
target_size=self.formatter.format_bytes(progress.get('target_size', 0)),
codec=progress.get('codec', 'Unknown'),
hardware_accel=progress.get('hardware_accel', False)
))
content.append(
template.format_string.format(
filename=progress.get("filename", "Unknown"),
percent=self.formatter.format_percentage(
progress.get("percent", 0)
),
elapsed_time=progress.get("elapsed_time", "N/A"),
input_size=self.formatter.format_bytes(
progress.get("input_size", 0)
),
current_size=self.formatter.format_bytes(
progress.get("current_size", 0)
),
target_size=self.formatter.format_bytes(
progress.get("target_size", 0)
),
codec=progress.get("codec", "Unknown"),
hardware_accel=progress.get("hardware_accel", False),
)
)
except Exception as e:
logger.error(f"Error formatting compression {file_id}: {e}")
continue
if len(compressions) > template.max_items:
content.append(f"\n... and {len(compressions) - template.max_items} more")
content.append(
f"\n... and {len(compressions) - template.max_items} more"
)
embed.add_field(
name=template.name,
value="".join(content) if content else "```\nNo active compressions```",
inline=template.inline
value=(
"".join(content)
if content
else "```\nNo active compressions```"
),
inline=template.inline,
)
else:
embed.add_field(
name=template.name,
value="```\nNo active compressions```",
inline=template.inline
inline=template.inline,
)
except Exception as e:
logger.error(f"Error adding active compressions: {e}")
embed.add_field(
name=template.name,
value="```\nError displaying compressions```",
inline=template.inline
inline=template.inline,
)
def _add_error_statistics(
self,
embed: discord.Embed,
queue_status: Dict[str, Any],
template: DisplayTemplate
template: DisplayTemplate,
) -> None:
"""Add error statistics to the embed"""
try:
metrics = queue_status.get('metrics', {})
errors_by_type = metrics.get('errors_by_type', {})
metrics = queue_status.get("metrics", {})
errors_by_type = metrics.get("errors_by_type", {})
if errors_by_type:
error_stats = "\n".join(
f"{error_type}: {count}"
for error_type, count in list(errors_by_type.items())[:template.max_items]
for error_type, count in list(errors_by_type.items())[
: template.max_items
]
)
if len(errors_by_type) > template.max_items:
error_stats += f"\n... and {len(errors_by_type) - template.max_items} more"
error_stats += (
f"\n... and {len(errors_by_type) - template.max_items} more"
)
embed.add_field(
name=template.name,
value=template.format_string.format(error_stats=error_stats),
inline=template.inline
inline=template.inline,
)
except Exception as e:
logger.error(f"Error adding error statistics: {e}")
embed.add_field(
name=template.name,
value="```\nError displaying error statistics```",
inline=template.inline
inline=template.inline,
)
def _add_hardware_statistics(
self,
embed: discord.Embed,
queue_status: Dict[str, Any],
template: DisplayTemplate
template: DisplayTemplate,
) -> None:
"""Add hardware statistics to the embed"""
try:
metrics = queue_status.get('metrics', {})
metrics = queue_status.get("metrics", {})
embed.add_field(
name=template.name,
value=template.format_string.format(
hw_failures=metrics.get('hardware_accel_failures', 0),
comp_failures=metrics.get('compression_failures', 0),
hw_failures=metrics.get("hardware_accel_failures", 0),
comp_failures=metrics.get("compression_failures", 0),
memory_usage=self.formatter.format_bytes(
metrics.get('peak_memory_usage', 0) * 1024 * 1024 # Convert MB to bytes
)
metrics.get("peak_memory_usage", 0)
* 1024
* 1024 # Convert MB to bytes
),
),
inline=template.inline
inline=template.inline,
)
except Exception as e:
logger.error(f"Error adding hardware statistics: {e}")
embed.add_field(
name=template.name,
value="```\nError displaying hardware statistics```",
inline=template.inline
inline=template.inline,
)