mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-11-12 03:55:05 +00:00
refactor(tracks): honour the best token and share one match rule
sort_subtitles resolved only the all token, while the video and audio sorts resolved all and best. by_language now asks matching_languages rather than repeating the RFC 4647 preference, with no behaviour change.
This commit is contained in:
@@ -180,11 +180,18 @@ def test_no_priority_leaves_order_unchanged(many: Tracks) -> None:
|
||||
assert langs(many) == ["ar", "bg", "en", "es", "fr", "ja"]
|
||||
|
||||
|
||||
def test_all_alone_still_floats_the_original_language(many: Tracks) -> None:
|
||||
many.sort_subtitles(by_language=["all"], group_by="language")
|
||||
@pytest.mark.parametrize("token", ["all", "best"])
|
||||
def test_magic_token_alone_floats_the_original_language(many: Tracks, token: str) -> None:
|
||||
many.sort_subtitles(by_language=[token], group_by="language")
|
||||
assert langs(many) == ["ja", "ar", "bg", "en", "es", "fr"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("token", ["all", "best"])
|
||||
def test_priority_outranks_either_magic_token(many: Tracks, token: str) -> None:
|
||||
many.sort_subtitles(by_language=["en", "es", token], group_by="language")
|
||||
assert langs(many) == ["en", "es", "ja", "ar", "bg", "fr"]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def regionals() -> Tracks:
|
||||
t = Tracks()
|
||||
|
||||
@@ -7,7 +7,7 @@ from functools import partial
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable, Iterator, Optional, Sequence, Union
|
||||
|
||||
from langcodes import Language, closest_supported_match
|
||||
from langcodes import Language
|
||||
from rich.progress import Progress, SpinnerColumn, TaskID, TextColumn, TimeRemainingColumn
|
||||
from rich.table import Table
|
||||
from rich.tree import Tree
|
||||
@@ -15,7 +15,7 @@ from rich.tree import Tree
|
||||
from unshackle.core import binaries
|
||||
from unshackle.core.config import config
|
||||
from unshackle.core.console import GradientPulseBarColumn, console
|
||||
from unshackle.core.constants import LANGUAGE_EXACT_DISTANCE, LANGUAGE_MAX_DISTANCE, AnyTrack, TrackT
|
||||
from unshackle.core.constants import AnyTrack, TrackT
|
||||
from unshackle.core.events import events
|
||||
from unshackle.core.tracks.attachment import Attachment
|
||||
from unshackle.core.tracks.audio import Audio
|
||||
@@ -351,7 +351,7 @@ class Tracks:
|
||||
by_type()
|
||||
# sections
|
||||
for language in reversed(by_language or []):
|
||||
if str(language) == "all":
|
||||
if str(language) in ("all", "best"):
|
||||
language = next((x.language for x in self.subtitles if x.is_original_lang), "")
|
||||
if not language:
|
||||
continue
|
||||
@@ -469,21 +469,11 @@ class Tracks:
|
||||
def by_language(
|
||||
tracks: list[TrackT], languages: list[str], per_language: int = 0, exact_match: bool = False
|
||||
) -> list[TrackT]:
|
||||
distance = LANGUAGE_EXACT_DISTANCE if exact_match else LANGUAGE_MAX_DISTANCE
|
||||
selected: list[TrackT] = []
|
||||
seen_ids: set[str] = set()
|
||||
for language in languages:
|
||||
matches = [x for x in tracks if closest_supported_match(str(x.language), [language], distance)]
|
||||
if exact_match and len(matches) > 1:
|
||||
# CLDR tag_distance measures intelligibility, not tag identity: it rates a base
|
||||
# language and its "paradigm" regional variant as the same language (distance 0
|
||||
# for ar/ar-EG, en/en-US, pt/pt-BR), so exact mode alone cannot separate them.
|
||||
# Follow RFC 4647 Lookup: prefer the most specific (string-equal) tag, and fall
|
||||
# back to the fuzzy match only when none exists (e.g. zh matches cmn).
|
||||
want = Language.get(language).to_tag().casefold()
|
||||
exact_hits = [x for x in matches if Language.get(str(x.language)).to_tag().casefold() == want]
|
||||
if exact_hits:
|
||||
matches = exact_hits
|
||||
wanted = matching_languages(language, [x.language for x in tracks], exact_match)
|
||||
matches = [x for x in tracks if str(x.language) in wanted]
|
||||
# Overlapping tags can still resolve to the same physical track; dedupe by id so
|
||||
# callers never get duplicate tracks.
|
||||
for track in matches[: per_language or None]:
|
||||
|
||||
Reference in New Issue
Block a user