Add YAPF style + ignore, and format tracked Python files
This commit is contained in:
@@ -16,7 +16,6 @@ try: # Optional dependency
|
||||
except ImportError: # pragma: no cover - optional
|
||||
musicbrainzngs = None
|
||||
|
||||
|
||||
try: # Optional dependency
|
||||
import yt_dlp # type: ignore
|
||||
except ImportError: # pragma: no cover - optional
|
||||
@@ -62,9 +61,18 @@ class ITunesProvider(MetadataProvider):
|
||||
"""Metadata provider using the iTunes Search API."""
|
||||
|
||||
def search(self, query: str, limit: int = 10) -> List[Dict[str, Any]]:
|
||||
params = {"term": query, "media": "music", "entity": "song", "limit": limit}
|
||||
params = {
|
||||
"term": query,
|
||||
"media": "music",
|
||||
"entity": "song",
|
||||
"limit": limit
|
||||
}
|
||||
try:
|
||||
resp = requests.get("https://itunes.apple.com/search", params=params, timeout=10)
|
||||
resp = requests.get(
|
||||
"https://itunes.apple.com/search",
|
||||
params=params,
|
||||
timeout=10
|
||||
)
|
||||
resp.raise_for_status()
|
||||
results = resp.json().get("results", [])
|
||||
except Exception as exc:
|
||||
@@ -77,7 +85,8 @@ class ITunesProvider(MetadataProvider):
|
||||
"title": r.get("trackName"),
|
||||
"artist": r.get("artistName"),
|
||||
"album": r.get("collectionName"),
|
||||
"year": str(r.get("releaseDate", ""))[:4],
|
||||
"year": str(r.get("releaseDate",
|
||||
""))[:4],
|
||||
"provider": self.name,
|
||||
"raw": r,
|
||||
}
|
||||
@@ -100,17 +109,22 @@ class OpenLibraryMetadataProvider(MetadataProvider):
|
||||
|
||||
try:
|
||||
# Prefer ISBN-specific search when the query looks like one
|
||||
if query_clean.replace("-", "").isdigit() and len(query_clean.replace("-", "")) in (
|
||||
10,
|
||||
13,
|
||||
):
|
||||
if query_clean.replace("-",
|
||||
"").isdigit() and len(query_clean.replace("-",
|
||||
"")) in (
|
||||
10,
|
||||
13,
|
||||
):
|
||||
q = f"isbn:{query_clean.replace('-', '')}"
|
||||
else:
|
||||
q = query_clean
|
||||
|
||||
resp = requests.get(
|
||||
"https://openlibrary.org/search.json",
|
||||
params={"q": q, "limit": limit},
|
||||
params={
|
||||
"q": q,
|
||||
"limit": limit
|
||||
},
|
||||
timeout=10,
|
||||
)
|
||||
resp.raise_for_status()
|
||||
@@ -202,7 +216,10 @@ class GoogleBooksMetadataProvider(MetadataProvider):
|
||||
return []
|
||||
|
||||
# Prefer ISBN queries when possible
|
||||
if query_clean.replace("-", "").isdigit() and len(query_clean.replace("-", "")) in (10, 13):
|
||||
if query_clean.replace("-",
|
||||
"").isdigit() and len(query_clean.replace("-",
|
||||
"")) in (10,
|
||||
13):
|
||||
q = f"isbn:{query_clean.replace('-', '')}"
|
||||
else:
|
||||
q = query_clean
|
||||
@@ -210,7 +227,10 @@ class GoogleBooksMetadataProvider(MetadataProvider):
|
||||
try:
|
||||
resp = requests.get(
|
||||
"https://www.googleapis.com/books/v1/volumes",
|
||||
params={"q": q, "maxResults": limit},
|
||||
params={
|
||||
"q": q,
|
||||
"maxResults": limit
|
||||
},
|
||||
timeout=10,
|
||||
)
|
||||
resp.raise_for_status()
|
||||
@@ -228,7 +248,10 @@ class GoogleBooksMetadataProvider(MetadataProvider):
|
||||
year = str(published_date)[:4] if published_date else ""
|
||||
|
||||
identifiers_raw = info.get("industryIdentifiers") or []
|
||||
identifiers: Dict[str, Optional[str]] = {"googlebooks": volume.get("id")}
|
||||
identifiers: Dict[str,
|
||||
Optional[str]] = {
|
||||
"googlebooks": volume.get("id")
|
||||
}
|
||||
for ident in identifiers_raw:
|
||||
if not isinstance(ident, dict):
|
||||
continue
|
||||
@@ -253,7 +276,8 @@ class GoogleBooksMetadataProvider(MetadataProvider):
|
||||
"authors": authors,
|
||||
"publisher": publisher,
|
||||
"identifiers": identifiers,
|
||||
"description": info.get("description", ""),
|
||||
"description": info.get("description",
|
||||
""),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -341,7 +365,8 @@ class ISBNsearchMetadataProvider(MetadataProvider):
|
||||
if m_title:
|
||||
title = self._strip_html_to_text(m_title.group(1))
|
||||
|
||||
raw_fields: Dict[str, str] = {}
|
||||
raw_fields: Dict[str,
|
||||
str] = {}
|
||||
strong_matches = list(re.finditer(r"(?is)<strong\b[^>]*>(.*?)</strong>", html))
|
||||
for idx, m in enumerate(strong_matches):
|
||||
label_raw = self._strip_html_to_text(m.group(1))
|
||||
@@ -354,13 +379,14 @@ class ISBNsearchMetadataProvider(MetadataProvider):
|
||||
chunk_start = m.end()
|
||||
# Stop at next <strong> or end of document.
|
||||
chunk_end = (
|
||||
strong_matches[idx + 1].start() if (idx + 1) < len(strong_matches) else len(html)
|
||||
strong_matches[idx + 1].start() if
|
||||
(idx + 1) < len(strong_matches) else len(html)
|
||||
)
|
||||
chunk = html[chunk_start:chunk_end]
|
||||
# Prefer stopping within the same paragraph when possible.
|
||||
m_end = re.search(r"(?is)(</p>|<br\s*/?>)", chunk)
|
||||
if m_end:
|
||||
chunk = chunk[: m_end.start()]
|
||||
chunk = chunk[:m_end.start()]
|
||||
|
||||
val_text = self._strip_html_to_text(chunk)
|
||||
if not val_text:
|
||||
@@ -391,7 +417,9 @@ class ISBNsearchMetadataProvider(MetadataProvider):
|
||||
authors: List[str] = []
|
||||
if author_text:
|
||||
# Split on common separators; keep multi-part names intact.
|
||||
for part in re.split(r"\s*(?:,|;|\band\b|\&|\|)\s*", author_text, flags=re.IGNORECASE):
|
||||
for part in re.split(r"\s*(?:,|;|\band\b|\&|\|)\s*",
|
||||
author_text,
|
||||
flags=re.IGNORECASE):
|
||||
p = str(part or "").strip()
|
||||
if p:
|
||||
authors.append(p)
|
||||
@@ -412,23 +440,28 @@ class ISBNsearchMetadataProvider(MetadataProvider):
|
||||
if t and t not in isbn_tokens:
|
||||
isbn_tokens.append(t)
|
||||
|
||||
item: Dict[str, Any] = {
|
||||
"title": title or "",
|
||||
# Keep UI columns compatible with the generic metadata table.
|
||||
"artist": ", ".join(authors) if authors else "",
|
||||
"album": publisher or "",
|
||||
"year": year or "",
|
||||
"provider": self.name,
|
||||
"authors": authors,
|
||||
"publisher": publisher or "",
|
||||
"language": language or "",
|
||||
"pages": pages or "",
|
||||
"identifiers": {
|
||||
"isbn_13": next((t for t in isbn_tokens if len(t) == 13), None),
|
||||
"isbn_10": next((t for t in isbn_tokens if len(t) == 10), None),
|
||||
},
|
||||
"raw_fields": raw_fields,
|
||||
}
|
||||
item: Dict[str,
|
||||
Any] = {
|
||||
"title": title or "",
|
||||
# Keep UI columns compatible with the generic metadata table.
|
||||
"artist": ", ".join(authors) if authors else "",
|
||||
"album": publisher or "",
|
||||
"year": year or "",
|
||||
"provider": self.name,
|
||||
"authors": authors,
|
||||
"publisher": publisher or "",
|
||||
"language": language or "",
|
||||
"pages": pages or "",
|
||||
"identifiers": {
|
||||
"isbn_13":
|
||||
next((t for t in isbn_tokens if len(t) == 13),
|
||||
None),
|
||||
"isbn_10":
|
||||
next((t for t in isbn_tokens if len(t) == 10),
|
||||
None),
|
||||
},
|
||||
"raw_fields": raw_fields,
|
||||
}
|
||||
|
||||
# Only return usable items.
|
||||
if not item.get("title") and not any(item["identifiers"].values()):
|
||||
@@ -495,7 +528,10 @@ class MusicBrainzMetadataProvider(MetadataProvider):
|
||||
|
||||
def search(self, query: str, limit: int = 10) -> List[Dict[str, Any]]:
|
||||
if not musicbrainzngs:
|
||||
log("musicbrainzngs is not installed; skipping MusicBrainz scrape", file=sys.stderr)
|
||||
log(
|
||||
"musicbrainzngs is not installed; skipping MusicBrainz scrape",
|
||||
file=sys.stderr
|
||||
)
|
||||
return []
|
||||
|
||||
q = (query or "").strip()
|
||||
@@ -526,12 +562,15 @@ class MusicBrainzMetadataProvider(MetadataProvider):
|
||||
if isinstance(artist_credit, list) and artist_credit:
|
||||
first = artist_credit[0]
|
||||
if isinstance(first, dict):
|
||||
artist = first.get("name") or first.get("artist", {}).get("name", "")
|
||||
artist = first.get("name") or first.get("artist",
|
||||
{}).get("name",
|
||||
"")
|
||||
elif isinstance(first, str):
|
||||
artist = first
|
||||
|
||||
album = ""
|
||||
release_list = rec.get("release-list") or rec.get("releases") or rec.get("release")
|
||||
release_list = rec.get("release-list") or rec.get("releases"
|
||||
) or rec.get("release")
|
||||
if isinstance(release_list, list) and release_list:
|
||||
first_rel = release_list[0]
|
||||
if isinstance(first_rel, dict):
|
||||
@@ -634,7 +673,8 @@ class YtdlpMetadataProvider(MetadataProvider):
|
||||
|
||||
upload_date = str(info.get("upload_date") or "")
|
||||
release_date = str(info.get("release_date") or "")
|
||||
year = (release_date or upload_date)[:4] if (release_date or upload_date) else ""
|
||||
year = (release_date
|
||||
or upload_date)[:4] if (release_date or upload_date) else ""
|
||||
|
||||
# Provide basic columns for the standard metadata selection table.
|
||||
# NOTE: This is best-effort; many extractors don't provide artist/album.
|
||||
@@ -716,15 +756,16 @@ class YtdlpMetadataProvider(MetadataProvider):
|
||||
|
||||
# Registry ---------------------------------------------------------------
|
||||
|
||||
_METADATA_PROVIDERS: Dict[str, Type[MetadataProvider]] = {
|
||||
"itunes": ITunesProvider,
|
||||
"openlibrary": OpenLibraryMetadataProvider,
|
||||
"googlebooks": GoogleBooksMetadataProvider,
|
||||
"google": GoogleBooksMetadataProvider,
|
||||
"isbnsearch": ISBNsearchMetadataProvider,
|
||||
"musicbrainz": MusicBrainzMetadataProvider,
|
||||
"ytdlp": YtdlpMetadataProvider,
|
||||
}
|
||||
_METADATA_PROVIDERS: Dict[str,
|
||||
Type[MetadataProvider]] = {
|
||||
"itunes": ITunesProvider,
|
||||
"openlibrary": OpenLibraryMetadataProvider,
|
||||
"googlebooks": GoogleBooksMetadataProvider,
|
||||
"google": GoogleBooksMetadataProvider,
|
||||
"isbnsearch": ISBNsearchMetadataProvider,
|
||||
"musicbrainz": MusicBrainzMetadataProvider,
|
||||
"ytdlp": YtdlpMetadataProvider,
|
||||
}
|
||||
|
||||
|
||||
def register_provider(name: str, provider_cls: Type[MetadataProvider]) -> None:
|
||||
@@ -732,7 +773,8 @@ def register_provider(name: str, provider_cls: Type[MetadataProvider]) -> None:
|
||||
|
||||
|
||||
def list_metadata_providers(config: Optional[Dict[str, Any]] = None) -> Dict[str, bool]:
|
||||
availability: Dict[str, bool] = {}
|
||||
availability: Dict[str,
|
||||
bool] = {}
|
||||
for name, cls in _METADATA_PROVIDERS.items():
|
||||
try:
|
||||
_ = cls(config)
|
||||
@@ -743,9 +785,10 @@ def list_metadata_providers(config: Optional[Dict[str, Any]] = None) -> Dict[str
|
||||
return availability
|
||||
|
||||
|
||||
def get_metadata_provider(
|
||||
name: str, config: Optional[Dict[str, Any]] = None
|
||||
) -> Optional[MetadataProvider]:
|
||||
def get_metadata_provider(name: str,
|
||||
config: Optional[Dict[str,
|
||||
Any]] = None
|
||||
) -> Optional[MetadataProvider]:
|
||||
cls = _METADATA_PROVIDERS.get(name.lower())
|
||||
if not cls:
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user