mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-03-12 01:19:02 +00:00
refactor: remove unnecessary underscore prefixes from function names
This commit is contained in:
@@ -12,7 +12,7 @@ from unshackle.core.vault import Vault
|
||||
from unshackle.core.vaults import Vaults
|
||||
|
||||
|
||||
def _load_vaults(vault_names: list[str]) -> Vaults:
|
||||
def load_vaults(vault_names: list[str]) -> Vaults:
|
||||
"""Load and validate vaults by name."""
|
||||
vaults = Vaults()
|
||||
for vault_name in vault_names:
|
||||
@@ -30,7 +30,7 @@ def _load_vaults(vault_names: list[str]) -> Vaults:
|
||||
return vaults
|
||||
|
||||
|
||||
def _process_service_keys(from_vault: Vault, service: str, log: logging.Logger) -> dict[str, str]:
|
||||
def process_service_keys(from_vault: Vault, service: str, log: logging.Logger) -> dict[str, str]:
|
||||
"""Get and validate keys from a vault for a specific service."""
|
||||
content_keys = list(from_vault.get_keys(service))
|
||||
|
||||
@@ -41,9 +41,9 @@ def _process_service_keys(from_vault: Vault, service: str, log: logging.Logger)
|
||||
return {kid: key for kid, key in content_keys if kid not in bad_keys}
|
||||
|
||||
|
||||
def _copy_service_data(to_vault: Vault, from_vault: Vault, service: str, log: logging.Logger) -> int:
|
||||
def copy_service_data(to_vault: Vault, from_vault: Vault, service: str, log: logging.Logger) -> int:
|
||||
"""Copy data for a single service between vaults."""
|
||||
content_keys = _process_service_keys(from_vault, service, log)
|
||||
content_keys = process_service_keys(from_vault, service, log)
|
||||
total_count = len(content_keys)
|
||||
|
||||
if total_count == 0:
|
||||
@@ -95,7 +95,7 @@ def copy(to_vault_name: str, from_vault_names: list[str], service: Optional[str]
|
||||
log = logging.getLogger("kv")
|
||||
|
||||
all_vault_names = [to_vault_name] + list(from_vault_names)
|
||||
vaults = _load_vaults(all_vault_names)
|
||||
vaults = load_vaults(all_vault_names)
|
||||
|
||||
to_vault = vaults.vaults[0]
|
||||
from_vaults = vaults.vaults[1:]
|
||||
@@ -112,7 +112,7 @@ def copy(to_vault_name: str, from_vault_names: list[str], service: Optional[str]
|
||||
services_to_copy = [service] if service else from_vault.get_services()
|
||||
|
||||
for service_tag in services_to_copy:
|
||||
added = _copy_service_data(to_vault, from_vault, service_tag, log)
|
||||
added = copy_service_data(to_vault, from_vault, service_tag, log)
|
||||
total_added += added
|
||||
|
||||
if total_added > 0:
|
||||
@@ -164,7 +164,7 @@ def add(file: Path, service: str, vaults: list[str]) -> None:
|
||||
log = logging.getLogger("kv")
|
||||
service = Services.get_tag(service)
|
||||
|
||||
vaults_ = _load_vaults(list(vaults))
|
||||
vaults_ = load_vaults(list(vaults))
|
||||
|
||||
data = file.read_text(encoding="utf8")
|
||||
kid_keys: dict[str, str] = {}
|
||||
@@ -194,7 +194,7 @@ def prepare(vaults: list[str]) -> None:
|
||||
"""Create Service Tables on Vaults if not yet created."""
|
||||
log = logging.getLogger("kv")
|
||||
|
||||
vaults_ = _load_vaults(vaults)
|
||||
vaults_ = load_vaults(vaults)
|
||||
|
||||
for vault in vaults_:
|
||||
if hasattr(vault, "has_table") and hasattr(vault, "create_table"):
|
||||
|
||||
@@ -91,7 +91,7 @@ class Cacher:
|
||||
except jwt.DecodeError:
|
||||
pass
|
||||
|
||||
self.expiration = self._resolve_datetime(expiration) if expiration else None
|
||||
self.expiration = self.resolve_datetime(expiration) if expiration else None
|
||||
|
||||
payload = {"data": self.data, "expiration": self.expiration, "version": self.version}
|
||||
payload["crc32"] = zlib.crc32(jsonpickle.dumps(payload).encode("utf8"))
|
||||
@@ -109,7 +109,7 @@ class Cacher:
|
||||
return self.path.stat()
|
||||
|
||||
@staticmethod
|
||||
def _resolve_datetime(timestamp: EXP_T) -> datetime:
|
||||
def resolve_datetime(timestamp: EXP_T) -> datetime:
|
||||
"""
|
||||
Resolve multiple formats of a Datetime or Timestamp to an absolute Datetime.
|
||||
|
||||
@@ -118,15 +118,15 @@ class Cacher:
|
||||
datetime.datetime(2022, 6, 27, 9, 49, 13, 657208)
|
||||
>>> iso8601 = now.isoformat()
|
||||
'2022-06-27T09:49:13.657208'
|
||||
>>> Cacher._resolve_datetime(iso8601)
|
||||
>>> Cacher.resolve_datetime(iso8601)
|
||||
datetime.datetime(2022, 6, 27, 9, 49, 13, 657208)
|
||||
>>> Cacher._resolve_datetime(iso8601 + "Z")
|
||||
>>> Cacher.resolve_datetime(iso8601 + "Z")
|
||||
datetime.datetime(2022, 6, 27, 9, 49, 13, 657208)
|
||||
>>> Cacher._resolve_datetime(3600)
|
||||
>>> Cacher.resolve_datetime(3600)
|
||||
datetime.datetime(2022, 6, 27, 10, 52, 50, 657208)
|
||||
>>> Cacher._resolve_datetime('3600')
|
||||
>>> Cacher.resolve_datetime('3600')
|
||||
datetime.datetime(2022, 6, 27, 10, 52, 51, 657208)
|
||||
>>> Cacher._resolve_datetime(7800.113)
|
||||
>>> Cacher.resolve_datetime(7800.113)
|
||||
datetime.datetime(2022, 6, 27, 11, 59, 13, 770208)
|
||||
|
||||
In the int/float examples you may notice that it did not return now + 3600 seconds
|
||||
|
||||
@@ -79,7 +79,7 @@ class CurlSession(Session):
|
||||
)
|
||||
self.log = logging.getLogger(self.__class__.__name__)
|
||||
|
||||
def _get_sleep_time(self, response: Response | None, attempt: int) -> float | None:
|
||||
def get_sleep_time(self, response: Response | None, attempt: int) -> float | None:
|
||||
if response:
|
||||
retry_after = response.headers.get("Retry-After")
|
||||
if retry_after:
|
||||
@@ -123,7 +123,7 @@ class CurlSession(Session):
|
||||
)
|
||||
|
||||
if attempt < self.max_retries:
|
||||
if sleep_duration := self._get_sleep_time(response, attempt + 1):
|
||||
if sleep_duration := self.get_sleep_time(response, attempt + 1):
|
||||
if sleep_duration > 0:
|
||||
time.sleep(sleep_duration)
|
||||
else:
|
||||
|
||||
@@ -25,7 +25,7 @@ from unshackle.core.constants import DOWNLOAD_CANCELLED, DOWNLOAD_LICENCE_ONLY
|
||||
from unshackle.core.downloaders import aria2c, curl_impersonate, n_m3u8dl_re, requests
|
||||
from unshackle.core.drm import DRM_T, PlayReady, Widevine
|
||||
from unshackle.core.events import events
|
||||
from unshackle.core.utilities import get_boxes, try_ensure_utf8, get_extension
|
||||
from unshackle.core.utilities import get_boxes, get_extension, try_ensure_utf8
|
||||
from unshackle.core.utils.subprocess import ffprobe
|
||||
|
||||
|
||||
|
||||
@@ -28,21 +28,21 @@ class UpdateChecker:
|
||||
DEFAULT_CHECK_INTERVAL = 24 * 60 * 60
|
||||
|
||||
@classmethod
|
||||
def _get_cache_file(cls) -> Path:
|
||||
def get_cache_file(cls) -> Path:
|
||||
"""Get the path to the update check cache file."""
|
||||
from unshackle.core.config import config
|
||||
|
||||
return config.directories.cache / "update_check.json"
|
||||
|
||||
@classmethod
|
||||
def _load_cache_data(cls) -> dict:
|
||||
def load_cache_data(cls) -> dict:
|
||||
"""
|
||||
Load cache data from file.
|
||||
|
||||
Returns:
|
||||
Cache data dictionary or empty dict if loading fails
|
||||
"""
|
||||
cache_file = cls._get_cache_file()
|
||||
cache_file = cls.get_cache_file()
|
||||
|
||||
if not cache_file.exists():
|
||||
return {}
|
||||
@@ -54,7 +54,7 @@ class UpdateChecker:
|
||||
return {}
|
||||
|
||||
@staticmethod
|
||||
def _parse_version(version_string: str) -> str:
|
||||
def parse_version(version_string: str) -> str:
|
||||
"""
|
||||
Parse and normalize version string by removing 'v' prefix.
|
||||
|
||||
@@ -107,7 +107,7 @@ class UpdateChecker:
|
||||
return None
|
||||
|
||||
data = response.json()
|
||||
latest_version = cls._parse_version(data.get("tag_name", ""))
|
||||
latest_version = cls.parse_version(data.get("tag_name", ""))
|
||||
|
||||
return latest_version if cls._is_valid_version(latest_version) else None
|
||||
|
||||
@@ -125,7 +125,7 @@ class UpdateChecker:
|
||||
Returns:
|
||||
True if we should check for updates, False otherwise
|
||||
"""
|
||||
cache_data = cls._load_cache_data()
|
||||
cache_data = cls.load_cache_data()
|
||||
|
||||
if not cache_data:
|
||||
return True
|
||||
@@ -144,7 +144,7 @@ class UpdateChecker:
|
||||
latest_version: The latest version found, if any
|
||||
current_version: The current version being used
|
||||
"""
|
||||
cache_file = cls._get_cache_file()
|
||||
cache_file = cls.get_cache_file()
|
||||
|
||||
try:
|
||||
cache_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
@@ -231,7 +231,7 @@ class UpdateChecker:
|
||||
Returns:
|
||||
The latest version string if an update is available from cache, None otherwise
|
||||
"""
|
||||
cache_data = cls._load_cache_data()
|
||||
cache_data = cls.load_cache_data()
|
||||
|
||||
if not cache_data:
|
||||
return None
|
||||
|
||||
@@ -485,7 +485,7 @@ def extract_font_family(font_path: Path) -> Optional[str]:
|
||||
return None
|
||||
|
||||
|
||||
def _get_windows_fonts() -> dict[str, Path]:
|
||||
def get_windows_fonts() -> dict[str, Path]:
|
||||
"""
|
||||
Get fonts from Windows registry.
|
||||
|
||||
@@ -504,7 +504,7 @@ def _get_windows_fonts() -> dict[str, Path]:
|
||||
}
|
||||
|
||||
|
||||
def _scan_font_directory(font_dir: Path, fonts: dict[str, Path], log: logging.Logger) -> None:
|
||||
def scan_font_directory(font_dir: Path, fonts: dict[str, Path], log: logging.Logger) -> None:
|
||||
"""
|
||||
Scan a single directory for fonts.
|
||||
|
||||
@@ -524,7 +524,7 @@ def _scan_font_directory(font_dir: Path, fonts: dict[str, Path], log: logging.Lo
|
||||
log.debug(f"Failed to process {font_file}: {e}")
|
||||
|
||||
|
||||
def _get_unix_fonts() -> dict[str, Path]:
|
||||
def get_unix_fonts() -> dict[str, Path]:
|
||||
"""
|
||||
Get fonts from Linux/macOS standard directories.
|
||||
|
||||
@@ -546,11 +546,9 @@ def _get_unix_fonts() -> dict[str, Path]:
|
||||
continue
|
||||
|
||||
try:
|
||||
_scan_font_directory(font_dir, fonts, log)
|
||||
scan_font_directory(font_dir, fonts, log)
|
||||
except Exception as e:
|
||||
log.warning(f"Failed to scan {font_dir}: {e}")
|
||||
|
||||
log.debug(f"Discovered {len(fonts)} system font families")
|
||||
return fonts
|
||||
|
||||
|
||||
@@ -565,8 +563,8 @@ def get_system_fonts() -> dict[str, Path]:
|
||||
Dictionary mapping font family names to their file paths
|
||||
"""
|
||||
if sys.platform == "win32":
|
||||
return _get_windows_fonts()
|
||||
return _get_unix_fonts()
|
||||
return get_windows_fonts()
|
||||
return get_unix_fonts()
|
||||
|
||||
|
||||
# Common Windows font names mapped to their Linux equivalents
|
||||
@@ -754,9 +752,9 @@ class DebugLogger:
|
||||
if self.enabled:
|
||||
self.log_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
self.file_handle = open(self.log_path, "a", encoding="utf-8")
|
||||
self._log_session_start()
|
||||
self.log_session_start()
|
||||
|
||||
def _log_session_start(self):
|
||||
def log_session_start(self):
|
||||
"""Log the start of a new session with environment information."""
|
||||
import platform
|
||||
|
||||
@@ -821,11 +819,11 @@ class DebugLogger:
|
||||
if service:
|
||||
entry["service"] = service
|
||||
if context:
|
||||
entry["context"] = self._sanitize_data(context)
|
||||
entry["context"] = self.sanitize_data(context)
|
||||
if request:
|
||||
entry["request"] = self._sanitize_data(request)
|
||||
entry["request"] = self.sanitize_data(request)
|
||||
if response:
|
||||
entry["response"] = self._sanitize_data(response)
|
||||
entry["response"] = self.sanitize_data(response)
|
||||
if duration_ms is not None:
|
||||
entry["duration_ms"] = duration_ms
|
||||
if success is not None:
|
||||
@@ -840,7 +838,7 @@ class DebugLogger:
|
||||
|
||||
for key, value in kwargs.items():
|
||||
if key not in entry:
|
||||
entry[key] = self._sanitize_data(value)
|
||||
entry[key] = self.sanitize_data(value)
|
||||
|
||||
try:
|
||||
self.file_handle.write(json.dumps(entry, default=str) + "\n")
|
||||
@@ -848,7 +846,7 @@ class DebugLogger:
|
||||
except Exception as e:
|
||||
print(f"Failed to write debug log: {e}", file=sys.stderr)
|
||||
|
||||
def _sanitize_data(self, data: Any) -> Any:
|
||||
def sanitize_data(self, data: Any) -> Any:
|
||||
"""
|
||||
Sanitize data for JSON serialization.
|
||||
Handles complex objects and removes sensitive information.
|
||||
@@ -860,7 +858,7 @@ class DebugLogger:
|
||||
return data
|
||||
|
||||
if isinstance(data, (list, tuple)):
|
||||
return [self._sanitize_data(item) for item in data]
|
||||
return [self.sanitize_data(item) for item in data]
|
||||
|
||||
if isinstance(data, dict):
|
||||
sanitized = {}
|
||||
@@ -883,7 +881,7 @@ class DebugLogger:
|
||||
if should_redact:
|
||||
sanitized[key] = "[REDACTED]"
|
||||
else:
|
||||
sanitized[key] = self._sanitize_data(value)
|
||||
sanitized[key] = self.sanitize_data(value)
|
||||
return sanitized
|
||||
|
||||
if isinstance(data, bytes):
|
||||
|
||||
@@ -3,8 +3,11 @@ import sys
|
||||
import typing
|
||||
from typing import Optional
|
||||
|
||||
import pysubs2
|
||||
from pycaption import Caption, CaptionList, CaptionNode, CaptionReadError, WebVTTReader, WebVTTWriter
|
||||
|
||||
from unshackle.core.config import config
|
||||
|
||||
|
||||
class CaptionListExt(CaptionList):
|
||||
@typing.no_type_check
|
||||
@@ -142,7 +145,24 @@ def merge_segmented_webvtt(vtt_raw: str, segment_durations: Optional[list[int]]
|
||||
"""
|
||||
MPEG_TIMESCALE = 90_000
|
||||
|
||||
vtt = WebVTTReaderExt().read(vtt_raw)
|
||||
# Check config for conversion method preference
|
||||
conversion_method = config.subtitle.get("conversion_method", "auto")
|
||||
use_pysubs2 = conversion_method in ("pysubs2", "auto")
|
||||
|
||||
if use_pysubs2:
|
||||
# Try using pysubs2 first for more lenient parsing
|
||||
try:
|
||||
# Use pysubs2 to parse and normalize the VTT
|
||||
subs = pysubs2.SSAFile.from_string(vtt_raw)
|
||||
# Convert back to WebVTT string for pycaption processing
|
||||
normalized_vtt = subs.to_string("vtt")
|
||||
vtt = WebVTTReaderExt().read(normalized_vtt)
|
||||
except Exception:
|
||||
# Fall back to direct pycaption parsing
|
||||
vtt = WebVTTReaderExt().read(vtt_raw)
|
||||
else:
|
||||
# Use pycaption directly
|
||||
vtt = WebVTTReaderExt().read(vtt_raw)
|
||||
for lang in vtt.get_languages():
|
||||
prev_caption = None
|
||||
duplicate_index: list[int] = []
|
||||
|
||||
Reference in New Issue
Block a user