refactor: add __all__ and more decouple
This commit is contained in:
+1
-1
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "lrx-cli"
|
||||
version = "0.7.8"
|
||||
version = "0.7.9"
|
||||
description = "Fetch line-synced lyrics for your music player."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.13"
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
from .config import AppConfig, GeneralConfig, CredentialConfig, load_config
|
||||
from .core import LrcManager
|
||||
from .models import CacheStatus, TrackMeta, LyricResult
|
||||
from .lrc import LRCData, LyricLine
|
||||
from .fetchers import FetcherMethodType
|
||||
from .utils import get_sidecar_path
|
||||
|
||||
__all__ = [
|
||||
"AppConfig",
|
||||
"GeneralConfig",
|
||||
"CredentialConfig",
|
||||
"load_config",
|
||||
"LrcManager",
|
||||
"CacheStatus",
|
||||
"TrackMeta",
|
||||
"LRCData",
|
||||
"LyricLine",
|
||||
"LyricResult",
|
||||
"FetcherMethodType",
|
||||
"get_sidecar_path",
|
||||
]
|
||||
|
||||
@@ -24,7 +24,7 @@ from .config import (
|
||||
SLOT_UNSYNCED,
|
||||
)
|
||||
from .models import TrackMeta, LyricResult, CacheStatus
|
||||
from .ranking import is_positive_status, select_best_positive
|
||||
from .utils import is_positive_status, select_best_positive
|
||||
|
||||
|
||||
_ALL_SLOTS = (SLOT_SYNCED, SLOT_UNSYNCED)
|
||||
|
||||
+1
-1
@@ -23,11 +23,11 @@ from .config import (
|
||||
load_config,
|
||||
enable_debug,
|
||||
)
|
||||
from .utils import get_sidecar_path
|
||||
from .models import TrackMeta
|
||||
from .mpris import get_current_track
|
||||
from .core import LrcManager
|
||||
from .fetchers import FetcherMethodType
|
||||
from .lrc import get_sidecar_path
|
||||
from .watch import WatchCoordinator
|
||||
from .watch.control import ControlClient, parse_delta
|
||||
from .watch.view.pipe import PipeOutput
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ from .config import (
|
||||
)
|
||||
from .models import TrackMeta, LyricResult, CacheStatus
|
||||
from .enrichers import create_enrichers, enrich_track
|
||||
from .ranking import is_better_result, select_best_positive
|
||||
from .utils import is_better_result, select_best_positive
|
||||
|
||||
|
||||
# Maps CacheStatus to the default TTL used when storing results
|
||||
|
||||
@@ -12,7 +12,7 @@ from mutagen._file import File, FileType
|
||||
|
||||
from .base import BaseEnricher
|
||||
from ..models import TrackMeta
|
||||
from ..lrc import get_audio_path
|
||||
from ..utils import get_audio_path
|
||||
|
||||
|
||||
class AudioTagEnricher(BaseEnricher):
|
||||
|
||||
@@ -12,7 +12,7 @@ from loguru import logger
|
||||
|
||||
from .base import BaseEnricher
|
||||
from ..models import TrackMeta
|
||||
from ..lrc import get_audio_path
|
||||
from ..utils import get_audio_path
|
||||
|
||||
|
||||
# Common track-number prefixes: "01 - ", "01. ", "1 - ", etc.
|
||||
|
||||
@@ -16,7 +16,8 @@ from mutagen.flac import FLAC
|
||||
|
||||
from .base import BaseFetcher, FetchResult
|
||||
from ..models import CacheStatus, TrackMeta, LyricResult
|
||||
from ..lrc import get_audio_path, get_sidecar_path, LRCData
|
||||
from ..lrc import LRCData
|
||||
from ..utils import get_audio_path, get_sidecar_path
|
||||
|
||||
|
||||
class LocalFetcher(BaseFetcher):
|
||||
|
||||
@@ -9,9 +9,7 @@ from __future__ import annotations
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass, field
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from urllib.parse import unquote
|
||||
|
||||
from .models import CacheStatus
|
||||
|
||||
@@ -465,34 +463,3 @@ class LRCData:
|
||||
"""
|
||||
normalized = self.normalize()
|
||||
return self._serialize_lines(normalized._lines, include_word_sync=False)
|
||||
|
||||
|
||||
def get_audio_path(audio_url: str, ensure_exists: bool = False) -> Optional[Path]:
|
||||
"""Convert file:// URL to Path, return None if invalid or (if ensure_exists) file doesn't exist."""
|
||||
if not audio_url.startswith("file://"):
|
||||
return None
|
||||
file_path = unquote(audio_url.replace("file://", "", 1))
|
||||
path = Path(file_path)
|
||||
if ensure_exists and not path.exists():
|
||||
return None
|
||||
return path
|
||||
|
||||
|
||||
def get_sidecar_path(
|
||||
audio_url: str,
|
||||
ensure_audio_exists: bool = False,
|
||||
ensure_exists: bool = False,
|
||||
extension: str = ".lrc",
|
||||
) -> Optional[Path]:
|
||||
"""Given a file:// URL, return the corresponding .lrc sidecar path.
|
||||
|
||||
If ensure_audio_exists is True, return None if the audio file does not exist.
|
||||
If ensure_exists is True, return None if the .lrc file does not exist.
|
||||
"""
|
||||
audio_path = get_audio_path(audio_url, ensure_exists=ensure_audio_exists)
|
||||
if not audio_path:
|
||||
return None
|
||||
lrc_path = audio_path.with_suffix(extension)
|
||||
if ensure_exists and not lrc_path.exists():
|
||||
return None
|
||||
return lrc_path
|
||||
|
||||
@@ -1,14 +1,56 @@
|
||||
"""Shared ranking rules for LyricResult selection.
|
||||
|
||||
This module centralizes how positive lyric results are compared so cache/core
|
||||
and other callers use the same precedence and edge-case handling.
|
||||
"""
|
||||
Author: Uyanide pywang0608@foxmail.com
|
||||
Date: 2026-04-10 17:06:37
|
||||
Description: Utility functions
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Optional
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
from urllib.parse import unquote
|
||||
from pathlib import Path
|
||||
|
||||
from .models import CacheStatus, LyricResult
|
||||
from .models import CacheStatus
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .models import LyricResult
|
||||
|
||||
|
||||
# Paths
|
||||
|
||||
|
||||
def get_audio_path(audio_url: str, ensure_exists: bool = False) -> Optional[Path]:
|
||||
"""Convert file:// URL to Path, return None if invalid or (if ensure_exists) file doesn't exist."""
|
||||
if not audio_url.startswith("file://"):
|
||||
return None
|
||||
file_path = unquote(audio_url.replace("file://", "", 1))
|
||||
path = Path(file_path)
|
||||
if ensure_exists and not path.exists():
|
||||
return None
|
||||
return path
|
||||
|
||||
|
||||
def get_sidecar_path(
|
||||
audio_url: str,
|
||||
ensure_audio_exists: bool = False,
|
||||
ensure_exists: bool = False,
|
||||
extension: str = ".lrc",
|
||||
) -> Optional[Path]:
|
||||
"""Given a file:// URL, return the corresponding .lrc sidecar path.
|
||||
|
||||
If ensure_audio_exists is True, return None if the audio file does not exist.
|
||||
If ensure_exists is True, return None if the .lrc file does not exist.
|
||||
"""
|
||||
audio_path = get_audio_path(audio_url, ensure_exists=ensure_audio_exists)
|
||||
if not audio_path:
|
||||
return None
|
||||
lrc_path = audio_path.with_suffix(extension)
|
||||
if ensure_exists and not lrc_path.exists():
|
||||
return None
|
||||
return lrc_path
|
||||
|
||||
|
||||
# Ranking
|
||||
|
||||
|
||||
def is_positive_status(status: CacheStatus) -> bool:
|
||||
Reference in New Issue
Block a user