Task 3: remove non-reentrant TMDB context in NFOService and mark task done
This commit is contained in:
@@ -98,6 +98,8 @@ If the TMDB API key is configured only via `config.json` (not the `TMDB_API_KEY`
|
|||||||
|
|
||||||
## Task 3 — Remove non-reentrant `async with self.tmdb_client:` from NFOService public methods
|
## Task 3 — Remove non-reentrant `async with self.tmdb_client:` from NFOService public methods
|
||||||
|
|
||||||
|
- [x] Completed
|
||||||
|
|
||||||
### Where
|
### Where
|
||||||
`src/core/services/nfo_service.py` — `create_tvshow_nfo` (~line 151) and `update_tvshow_nfo` (~line 265)
|
`src/core/services/nfo_service.py` — `create_tvshow_nfo` (~line 151) and `update_tvshow_nfo` (~line 265)
|
||||||
|
|
||||||
|
|||||||
@@ -146,36 +146,38 @@ class NFOService:
|
|||||||
logger.info("Creating series folder: %s", folder_path)
|
logger.info("Creating series folder: %s", folder_path)
|
||||||
folder_path.mkdir(parents=True, exist_ok=True)
|
folder_path.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
async with self.tmdb_client:
|
try:
|
||||||
|
await self.tmdb_client._ensure_session()
|
||||||
|
|
||||||
# Search for TV show with clean name (without year)
|
# Search for TV show with clean name (without year)
|
||||||
logger.debug("Searching TMDB for: %s", search_name)
|
logger.debug("Searching TMDB for: %s", search_name)
|
||||||
search_results = await self.tmdb_client.search_tv_show(search_name)
|
search_results = await self.tmdb_client.search_tv_show(search_name)
|
||||||
|
|
||||||
if not search_results.get("results"):
|
if not search_results.get("results"):
|
||||||
raise TMDBAPIError(f"No results found for: {search_name}")
|
raise TMDBAPIError(f"No results found for: {search_name}")
|
||||||
|
|
||||||
# Find best match (consider year if provided)
|
# Find best match (consider year if provided)
|
||||||
tv_show = self._find_best_match(search_results["results"], search_name, year)
|
tv_show = self._find_best_match(search_results["results"], search_name, year)
|
||||||
tv_id = tv_show["id"]
|
tv_id = tv_show["id"]
|
||||||
|
|
||||||
logger.info("Found match: %s (ID: %s)", tv_show['name'], tv_id)
|
logger.info("Found match: %s (ID: %s)", tv_show['name'], tv_id)
|
||||||
|
|
||||||
# Get detailed information with multi-language image support
|
# Get detailed information with multi-language image support
|
||||||
details = await self.tmdb_client.get_tv_show_details(
|
details = await self.tmdb_client.get_tv_show_details(
|
||||||
tv_id,
|
tv_id,
|
||||||
append_to_response="credits,external_ids,images"
|
append_to_response="credits,external_ids,images"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Get content ratings for FSK
|
# Get content ratings for FSK
|
||||||
content_ratings = await self.tmdb_client.get_tv_show_content_ratings(tv_id)
|
content_ratings = await self.tmdb_client.get_tv_show_content_ratings(tv_id)
|
||||||
|
|
||||||
# Enrich with fallback languages for empty overview/tagline
|
# Enrich with fallback languages for empty overview/tagline
|
||||||
# Pass search result overview as last resort fallback
|
# Pass search result overview as last resort fallback
|
||||||
search_overview = tv_show.get("overview") or None
|
search_overview = tv_show.get("overview") or None
|
||||||
details = await self._enrich_details_with_fallback(
|
details = await self._enrich_details_with_fallback(
|
||||||
details, search_overview=search_overview
|
details, search_overview=search_overview
|
||||||
)
|
)
|
||||||
|
|
||||||
# Convert TMDB data to TVShowNFO model
|
# Convert TMDB data to TVShowNFO model
|
||||||
nfo_model = tmdb_to_nfo_model(
|
nfo_model = tmdb_to_nfo_model(
|
||||||
details,
|
details,
|
||||||
@@ -183,15 +185,15 @@ class NFOService:
|
|||||||
self.tmdb_client.get_image_url,
|
self.tmdb_client.get_image_url,
|
||||||
self.image_size,
|
self.image_size,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Generate XML
|
# Generate XML
|
||||||
nfo_xml = generate_tvshow_nfo(nfo_model)
|
nfo_xml = generate_tvshow_nfo(nfo_model)
|
||||||
|
|
||||||
# Save NFO file
|
# Save NFO file
|
||||||
nfo_path = folder_path / "tvshow.nfo"
|
nfo_path = folder_path / "tvshow.nfo"
|
||||||
nfo_path.write_text(nfo_xml, encoding="utf-8")
|
nfo_path.write_text(nfo_xml, encoding="utf-8")
|
||||||
logger.info("Created NFO: %s", nfo_path)
|
logger.info("Created NFO: %s", nfo_path)
|
||||||
|
|
||||||
# Download media files
|
# Download media files
|
||||||
await self._download_media_files(
|
await self._download_media_files(
|
||||||
details,
|
details,
|
||||||
@@ -200,8 +202,10 @@ class NFOService:
|
|||||||
download_logo=download_logo,
|
download_logo=download_logo,
|
||||||
download_fanart=download_fanart
|
download_fanart=download_fanart
|
||||||
)
|
)
|
||||||
|
|
||||||
return nfo_path
|
return nfo_path
|
||||||
|
finally:
|
||||||
|
await self.tmdb_client.close()
|
||||||
|
|
||||||
async def update_tvshow_nfo(
|
async def update_tvshow_nfo(
|
||||||
self,
|
self,
|
||||||
@@ -260,19 +264,19 @@ class NFOService:
|
|||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise TMDBAPIError(f"Invalid TMDB ID format in NFO: {e}")
|
raise TMDBAPIError(f"Invalid TMDB ID format in NFO: {e}")
|
||||||
|
|
||||||
# Fetch fresh data from TMDB
|
try:
|
||||||
async with self.tmdb_client:
|
await self.tmdb_client._ensure_session()
|
||||||
logger.debug("Fetching fresh data for TMDB ID: %s", tmdb_id)
|
logger.debug("Fetching fresh data for TMDB ID: %s", tmdb_id)
|
||||||
details = await self.tmdb_client.get_tv_show_details(
|
details = await self.tmdb_client.get_tv_show_details(
|
||||||
tmdb_id,
|
tmdb_id,
|
||||||
append_to_response="credits,external_ids,images"
|
append_to_response="credits,external_ids,images"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Get content ratings for FSK
|
# Get content ratings for FSK
|
||||||
content_ratings = await self.tmdb_client.get_tv_show_content_ratings(tmdb_id)
|
content_ratings = await self.tmdb_client.get_tv_show_content_ratings(tmdb_id)
|
||||||
|
|
||||||
# Enrich with fallback languages for empty overview/tagline
|
# Enrich with fallback languages for empty overview/tagline
|
||||||
details = await self._enrich_details_with_fallback(details)
|
details = await self._enrich_details_with_fallback(details)
|
||||||
# Convert TMDB data to TVShowNFO model
|
# Convert TMDB data to TVShowNFO model
|
||||||
nfo_model = tmdb_to_nfo_model(
|
nfo_model = tmdb_to_nfo_model(
|
||||||
details,
|
details,
|
||||||
@@ -280,14 +284,14 @@ class NFOService:
|
|||||||
self.tmdb_client.get_image_url,
|
self.tmdb_client.get_image_url,
|
||||||
self.image_size,
|
self.image_size,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Generate XML
|
# Generate XML
|
||||||
nfo_xml = generate_tvshow_nfo(nfo_model)
|
nfo_xml = generate_tvshow_nfo(nfo_model)
|
||||||
|
|
||||||
# Save updated NFO file
|
# Save updated NFO file
|
||||||
nfo_path.write_text(nfo_xml, encoding="utf-8")
|
nfo_path.write_text(nfo_xml, encoding="utf-8")
|
||||||
logger.info("Updated NFO: %s", nfo_path)
|
logger.info("Updated NFO: %s", nfo_path)
|
||||||
|
|
||||||
# Re-download media files if requested
|
# Re-download media files if requested
|
||||||
if download_media:
|
if download_media:
|
||||||
await self._download_media_files(
|
await self._download_media_files(
|
||||||
@@ -297,8 +301,10 @@ class NFOService:
|
|||||||
download_logo=True,
|
download_logo=True,
|
||||||
download_fanart=True
|
download_fanart=True
|
||||||
)
|
)
|
||||||
|
|
||||||
return nfo_path
|
return nfo_path
|
||||||
|
finally:
|
||||||
|
await self.tmdb_client.close()
|
||||||
|
|
||||||
def parse_nfo_ids(self, nfo_path: Path) -> Dict[str, Optional[int]]:
|
def parse_nfo_ids(self, nfo_path: Path) -> Dict[str, Optional[int]]:
|
||||||
"""Parse TMDB ID and TVDB ID from an existing NFO file.
|
"""Parse TMDB ID and TVDB ID from an existing NFO file.
|
||||||
|
|||||||
Reference in New Issue
Block a user