fix(architecture): satisfy ruff/mypy ratchets for media auxiliary

e02418bac 把新导入放在 settings = RuntimeSettingsCompat() 之后,
导致 5 个模块 E402 诊断超出只降不增基线;同时 media_auxiliary
把工厂函数 MetaInfo 误用作返回类型标注。将新增导入移回赋值语句
之前,返回类型修正为 MetaBase。
This commit is contained in:
jxxghp
2026-08-26 14:33:36 +08:00
parent df2ce103e1
commit cdab54254d
6 changed files with 42 additions and 46 deletions
+2 -1
View File
@@ -21,8 +21,9 @@ class MediaAuxiliaryProviderMixin:
def _build_auxiliary_meta( def _build_auxiliary_meta(
mediainfo: MediaInfo, mediainfo: MediaInfo,
metainfo: Optional[MetaBase] = None, metainfo: Optional[MetaBase] = None,
) -> MetaInfo: ) -> MetaBase:
"""根据主识别结果构造不携带原来源身份的标题查询参数。""" """根据主识别结果构造不携带原来源身份的标题查询参数。"""
# MetaInfo 是工厂函数,实际返回 MetaBase 及其子类实例
meta = MetaInfo(mediainfo.title or getattr(metainfo, "name", None) or "") meta = MetaInfo(mediainfo.title or getattr(metainfo, "name", None) or "")
if not meta.en_name: if not meta.en_name:
meta.en_name = mediainfo.en_title or getattr(metainfo, "en_name", None) meta.en_name = mediainfo.en_title or getattr(metainfo, "en_name", None)
+5 -6
View File
@@ -1,16 +1,15 @@
from typing import List, Optional, Tuple, Union from typing import List, Optional, Tuple, Union
from app.runtime.settings import RuntimeSettingsCompat from app.modules._base.media_auxiliary import MediaAuxiliaryProviderMixin
from app.runtime.settings import get_runtime_setting
from app.schemas.context import MediaPerson as _SchemaMediaPerson from app.schemas.context import MediaPerson as _SchemaMediaPerson
settings = RuntimeSettingsCompat()
from app.domain.context import MediaInfo from app.domain.context import MediaInfo
from app.domain.media import is_media_source_enabled from app.domain.media import is_media_source_enabled
from app.domain.meta.metabase import MetaBase from app.domain.meta.metabase import MetaBase
from app.domain.scraper import MediaScraperHelper from app.domain.scraper import MediaScraperHelper
from app.modules import _ModuleBase from app.modules import _ModuleBase
from app.modules.anilist.anilist import AniListApi from app.modules.anilist.anilist import AniListApi
from app.modules._base.media_auxiliary import MediaAuxiliaryProviderMixin
from app.runtime.log import logger from app.runtime.log import logger
from app.schemas.types import ( from app.schemas.types import (
MediaRecognizeType, MediaRecognizeType,
@@ -78,7 +77,7 @@ class AniListModule(MediaAuxiliaryProviderMixin, _ModuleBase):
:param media_source: 请求级识别数据源 :param media_source: 请求级识别数据源
:return: 是否启用 AniList 识别 :return: 是否启用 AniList 识别
""" """
return (media_source or settings.RECOGNIZE_SOURCE) == MediaSource.AniList return (media_source or get_runtime_setting("RECOGNIZE_SOURCE")) == MediaSource.AniList
@staticmethod @staticmethod
def _media_type(info: dict) -> MediaType: def _media_type(info: dict) -> MediaType:
@@ -571,7 +570,7 @@ class AniListModule(MediaAuxiliaryProviderMixin, _ModuleBase):
:param episode: 集号 :param episode: 集号
:return: NFO XML 文本 :return: NFO XML 文本
""" """
scrape_source = mediainfo.scrape_source or settings.SCRAP_SOURCE scrape_source = mediainfo.scrape_source or get_runtime_setting("SCRAP_SOURCE")
if scrape_source != "anilist": if scrape_source != "anilist":
return None return None
return self.scraper.get_metadata_nfo(mediainfo, season=season, episode=episode) return self.scraper.get_metadata_nfo(mediainfo, season=season, episode=episode)
@@ -590,7 +589,7 @@ class AniListModule(MediaAuxiliaryProviderMixin, _ModuleBase):
:param episode: 集号 :param episode: 集号
:return: 图片文件名与下载地址映射 :return: 图片文件名与下载地址映射
""" """
scrape_source = mediainfo.scrape_source or settings.SCRAP_SOURCE scrape_source = mediainfo.scrape_source or get_runtime_setting("SCRAP_SOURCE")
if scrape_source != "anilist": if scrape_source != "anilist":
return None return None
return self.scraper.get_metadata_img(mediainfo, season=season, episode=episode) return self.scraper.get_metadata_img(mediainfo, season=season, episode=episode)
+7 -8
View File
@@ -1,10 +1,10 @@
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any, List, Optional, Tuple, Union from typing import Any, List, Optional, Tuple, Union
from app.runtime.settings import RuntimeSettingsCompat from app.modules._base.media_auxiliary import MediaAuxiliaryProviderMixin
from app.runtime.settings import get_runtime_setting
from app.schemas.context import MediaPerson as _SchemaMediaPerson from app.schemas.context import MediaPerson as _SchemaMediaPerson
settings = RuntimeSettingsCompat()
from app.adapters.network.http import RequestUtils from app.adapters.network.http import RequestUtils
from app.domain.context import MediaInfo from app.domain.context import MediaInfo
from app.domain.media import is_media_source_enabled from app.domain.media import is_media_source_enabled
@@ -12,7 +12,6 @@ from app.domain.meta.metabase import MetaBase
from app.domain.scraper import MediaScraperHelper from app.domain.scraper import MediaScraperHelper
from app.modules import _ModuleBase from app.modules import _ModuleBase
from app.modules.bangumi.bangumi import BangumiApi from app.modules.bangumi.bangumi import BangumiApi
from app.modules._base.media_auxiliary import MediaAuxiliaryProviderMixin
from app.runtime.log import logger from app.runtime.log import logger
from app.schemas.types import ( from app.schemas.types import (
MediaRecognizeType, MediaRecognizeType,
@@ -45,7 +44,7 @@ class BangumiModule(MediaAuxiliaryProviderMixin, _ModuleBase):
""" """
初始化Bangumi客户端 初始化Bangumi客户端
""" """
self._config = BangumiConfigSnapshot(proxy=settings.PROXY) self._config = BangumiConfigSnapshot(proxy=get_runtime_setting("PROXY"))
self.bangumiapi = BangumiApi() self.bangumiapi = BangumiApi()
self.scraper = MediaScraperHelper() self.scraper = MediaScraperHelper()
@@ -127,7 +126,7 @@ class BangumiModule(MediaAuxiliaryProviderMixin, _ModuleBase):
return None return None
bangumiid = int(media_id) if media_id is not None else None bangumiid = int(media_id) if media_id is not None else None
if not bangumiid and ( if not bangumiid and (
not meta or (media_source or settings.RECOGNIZE_SOURCE) != MediaSource.Bangumi not meta or (media_source or get_runtime_setting("RECOGNIZE_SOURCE")) != MediaSource.Bangumi
): ):
return None return None
@@ -176,7 +175,7 @@ class BangumiModule(MediaAuxiliaryProviderMixin, _ModuleBase):
return None return None
bangumiid = int(media_id) if media_id is not None else None bangumiid = int(media_id) if media_id is not None else None
if not bangumiid and ( if not bangumiid and (
not meta or (media_source or settings.RECOGNIZE_SOURCE) != MediaSource.Bangumi not meta or (media_source or get_runtime_setting("RECOGNIZE_SOURCE")) != MediaSource.Bangumi
): ):
return None return None
@@ -317,7 +316,7 @@ class BangumiModule(MediaAuxiliaryProviderMixin, _ModuleBase):
:param episode: 集号 :param episode: 集号
:return: NFO XML文本 :return: NFO XML文本
""" """
scrape_source = mediainfo.scrape_source or settings.SCRAP_SOURCE scrape_source = mediainfo.scrape_source or get_runtime_setting("SCRAP_SOURCE")
if scrape_source != "bangumi": if scrape_source != "bangumi":
return None return None
return self.scraper.get_metadata_nfo(mediainfo, season=season, episode=episode) return self.scraper.get_metadata_nfo(mediainfo, season=season, episode=episode)
@@ -336,7 +335,7 @@ class BangumiModule(MediaAuxiliaryProviderMixin, _ModuleBase):
:param episode: 集号 :param episode: 集号
:return: 图片文件名与下载地址映射 :return: 图片文件名与下载地址映射
""" """
scrape_source = mediainfo.scrape_source or settings.SCRAP_SOURCE scrape_source = mediainfo.scrape_source or get_runtime_setting("SCRAP_SOURCE")
if scrape_source != "bangumi": if scrape_source != "bangumi":
return None return None
return self.scraper.get_metadata_img(mediainfo, season=season, episode=episode) return self.scraper.get_metadata_img(mediainfo, season=season, episode=episode)
+7 -8
View File
@@ -3,10 +3,10 @@ from typing import Any, List, Optional, Tuple, Union
import cn2an import cn2an
from app.runtime.settings import RuntimeSettingsCompat from app.modules._base.media_auxiliary import MediaAuxiliaryProviderMixin
from app.runtime.settings import get_runtime_setting
from app.schemas.context import MediaPerson as _SchemaMediaPerson from app.schemas.context import MediaPerson as _SchemaMediaPerson
settings = RuntimeSettingsCompat()
from app.adapters.network.http import RequestUtils from app.adapters.network.http import RequestUtils
from app.domain.context import ( from app.domain.context import (
MediaInfo, MediaInfo,
@@ -21,7 +21,6 @@ from app.foundation.text import convert as zhconv_convert
from app.modules import _ModuleBase from app.modules import _ModuleBase
from app.modules.douban.apiv2 import DoubanApi from app.modules.douban.apiv2 import DoubanApi
from app.modules.douban.scraper import DoubanScraper from app.modules.douban.scraper import DoubanScraper
from app.modules._base.media_auxiliary import MediaAuxiliaryProviderMixin
from app.runtime.execution import retry from app.runtime.execution import retry
from app.runtime.log import logger from app.runtime.log import logger
from app.runtime.rate import rate_limit_exponential from app.runtime.rate import rate_limit_exponential
@@ -707,7 +706,7 @@ class DoubanModule(MediaAuxiliaryProviderMixin, _ModuleBase):
if ( if (
meta meta
and not doubanid and not doubanid
and (kwargs.get("media_source") or settings.RECOGNIZE_SOURCE) != "douban" and (kwargs.get("media_source") or get_runtime_setting("RECOGNIZE_SOURCE")) != "douban"
): ):
return None return None
@@ -778,7 +777,7 @@ class DoubanModule(MediaAuxiliaryProviderMixin, _ModuleBase):
if ( if (
meta meta
and not doubanid and not doubanid
and (kwargs.get("media_source") or settings.RECOGNIZE_SOURCE) != "douban" and (kwargs.get("media_source") or get_runtime_setting("RECOGNIZE_SOURCE")) != "douban"
): ):
return None return None
@@ -1685,7 +1684,7 @@ class DoubanModule(MediaAuxiliaryProviderMixin, _ModuleBase):
:param mediainfo: 媒体信息 :param mediainfo: 媒体信息
:param season: 季号 :param season: 季号
""" """
if (mediainfo.scrape_source or settings.SCRAP_SOURCE) != "douban": if (mediainfo.scrape_source or get_runtime_setting("SCRAP_SOURCE")) != "douban":
return None return None
return self.scraper.get_metadata_nfo(mediainfo=mediainfo, season=season) return self.scraper.get_metadata_nfo(mediainfo=mediainfo, season=season)
@@ -1696,7 +1695,7 @@ class DoubanModule(MediaAuxiliaryProviderMixin, _ModuleBase):
:param season: 季号 :param season: 季号
:param episode: 集号 :param episode: 集号
""" """
if (mediainfo.scrape_source or settings.SCRAP_SOURCE) != "douban": if (mediainfo.scrape_source or get_runtime_setting("SCRAP_SOURCE")) != "douban":
return None return None
return self.scraper.get_metadata_img(mediainfo=mediainfo, season=season, episode=episode) return self.scraper.get_metadata_img(mediainfo=mediainfo, season=season, episode=episode)
@@ -1707,7 +1706,7 @@ class DoubanModule(MediaAuxiliaryProviderMixin, _ModuleBase):
:param mediainfo: 媒体信息 :param mediainfo: 媒体信息
:return: None 表示不处理,MediaInfo 表示继续处理 :return: None 表示不处理,MediaInfo 表示继续处理
""" """
if mediainfo.media_source != MediaSource.Douban and settings.RECOGNIZE_SOURCE != "douban": if mediainfo.media_source != MediaSource.Douban and get_runtime_setting("RECOGNIZE_SOURCE") != "douban":
return None return None
if not mediainfo.douban_id: if not mediainfo.douban_id:
return None return None
+14 -15
View File
@@ -3,19 +3,18 @@ from typing import Dict, List, Optional, Tuple, Union
import cn2an import cn2an
from app.runtime.settings import RuntimeSettingsCompat from app.modules._base.media_auxiliary import MediaAuxiliaryProviderMixin
from app.runtime.settings import get_runtime_setting
from app.schemas.context import MediaPerson as _SchemaMediaPerson from app.schemas.context import MediaPerson as _SchemaMediaPerson
from app.schemas.tmdb import TmdbEpisode as _SchemaTmdbEpisode from app.schemas.tmdb import TmdbEpisode as _SchemaTmdbEpisode
from app.schemas.tmdb import TmdbSeason as _SchemaTmdbSeason from app.schemas.tmdb import TmdbSeason as _SchemaTmdbSeason
settings = RuntimeSettingsCompat()
from app.adapters.network.http import RequestUtils from app.adapters.network.http import RequestUtils
from app.domain.context import MediaInfo from app.domain.context import MediaInfo
from app.domain.media import is_media_source_enabled, is_media_source_selected from app.domain.media import is_media_source_enabled, is_media_source_selected
from app.domain.meta.metabase import MetaBase from app.domain.meta.metabase import MetaBase
from app.foundation.text import convert as zhconv_convert from app.foundation.text import convert as zhconv_convert
from app.modules import _ModuleBase from app.modules import _ModuleBase
from app.modules._base.media_auxiliary import MediaAuxiliaryProviderMixin
from app.modules.themoviedb.category import CategoryHelper from app.modules.themoviedb.category import CategoryHelper
from app.modules.themoviedb.scraper import TmdbScraper from app.modules.themoviedb.scraper import TmdbScraper
from app.modules.themoviedb.tmdb_cache import TmdbCache from app.modules.themoviedb.tmdb_cache import TmdbCache
@@ -95,13 +94,13 @@ class TheMovieDbModule(MediaAuxiliaryProviderMixin, _ModuleBase):
""" """
测试模块连接性 测试模块连接性
""" """
ret = RequestUtils(ua=settings.NORMAL_USER_AGENT, proxies=settings.PROXY).get_res( ret = RequestUtils(ua=get_runtime_setting("NORMAL_USER_AGENT"), proxies=get_runtime_setting("PROXY")).get_res(
f"https://{settings.TMDB_API_DOMAIN}/3/movie/550?api_key={settings.TMDB_API_KEY}") f"https://{get_runtime_setting("TMDB_API_DOMAIN")}/3/movie/550?api_key={get_runtime_setting("TMDB_API_KEY")}")
if ret and ret.status_code == 200: if ret and ret.status_code == 200:
return True, "" return True, ""
elif ret: elif ret:
return False, f"无法连接 {settings.TMDB_API_DOMAIN},错误码:{ret.status_code}" return False, f"无法连接 {get_runtime_setting("TMDB_API_DOMAIN")},错误码:{ret.status_code}"
return False, f"{settings.TMDB_API_DOMAIN} 网络连接失败" return False, f"{get_runtime_setting("TMDB_API_DOMAIN")} 网络连接失败"
def init_setting(self) -> Tuple[str, Union[str, bool]]: def init_setting(self) -> Tuple[str, Union[str, bool]]:
pass pass
@@ -123,7 +122,7 @@ class TheMovieDbModule(MediaAuxiliaryProviderMixin, _ModuleBase):
if not tmdbid and not meta: if not tmdbid and not meta:
return False return False
selected_source = normalize_media_source(media_source or settings.RECOGNIZE_SOURCE) selected_source = normalize_media_source(media_source or get_runtime_setting("RECOGNIZE_SOURCE"))
if meta and not tmdbid and selected_source != MediaSource.TMDB: if meta and not tmdbid and selected_source != MediaSource.TMDB:
return False return False
@@ -974,7 +973,7 @@ class TheMovieDbModule(MediaAuxiliaryProviderMixin, _ModuleBase):
:param season: 季号 :param season: 季号
:param episode: 集号 :param episode: 集号
""" """
if (mediainfo.scrape_source or settings.SCRAP_SOURCE) != "themoviedb": if (mediainfo.scrape_source or get_runtime_setting("SCRAP_SOURCE")) != "themoviedb":
return None return None
return self.scraper.get_metadata_nfo(meta=meta, mediainfo=mediainfo, season=season, episode=episode) return self.scraper.get_metadata_nfo(meta=meta, mediainfo=mediainfo, season=season, episode=episode)
@@ -986,7 +985,7 @@ class TheMovieDbModule(MediaAuxiliaryProviderMixin, _ModuleBase):
:param season: 季号 :param season: 季号
:param episode: 集号 :param episode: 集号
""" """
if (mediainfo.scrape_source or settings.SCRAP_SOURCE) != "themoviedb": if (mediainfo.scrape_source or get_runtime_setting("SCRAP_SOURCE")) != "themoviedb":
return None return None
return self.scraper.get_metadata_img(mediainfo=mediainfo, season=season, episode=episode) return self.scraper.get_metadata_img(mediainfo=mediainfo, season=season, episode=episode)
@@ -1107,7 +1106,7 @@ class TheMovieDbModule(MediaAuxiliaryProviderMixin, _ModuleBase):
:param mediainfo: 媒体信息 :param mediainfo: 媒体信息
:return: None 表示不处理,MediaInfo 表示继续处理 :return: None 表示不处理,MediaInfo 表示继续处理
""" """
if mediainfo.media_source != "themoviedb" and settings.RECOGNIZE_SOURCE != "themoviedb": if mediainfo.media_source != "themoviedb" and get_runtime_setting("RECOGNIZE_SOURCE") != "themoviedb":
return None return None
if not mediainfo.tmdb_id: if not mediainfo.tmdb_id:
return mediainfo return mediainfo
@@ -1148,15 +1147,15 @@ class TheMovieDbModule(MediaAuxiliaryProviderMixin, _ModuleBase):
# 背景图 # 背景图
if not mediainfo.backdrop_path: if not mediainfo.backdrop_path:
if image_path := cls._pick_best_tmdb_image(images.get("backdrops")): if image_path := cls._pick_best_tmdb_image(images.get("backdrops")):
mediainfo.backdrop_path = settings.TMDB_IMAGE_URL(image_path) mediainfo.backdrop_path = get_runtime_setting("TMDB_IMAGE_URL")(image_path)
# 标志 # 标志
if not mediainfo.logo_path: if not mediainfo.logo_path:
if image_path := cls._pick_best_tmdb_image(images.get("logos")): if image_path := cls._pick_best_tmdb_image(images.get("logos")):
mediainfo.logo_path = settings.TMDB_IMAGE_URL(image_path) mediainfo.logo_path = get_runtime_setting("TMDB_IMAGE_URL")(image_path)
# 海报 # 海报
if not mediainfo.poster_path: if not mediainfo.poster_path:
if image_path := cls._pick_best_tmdb_image(images.get("posters")): if image_path := cls._pick_best_tmdb_image(images.get("posters")):
mediainfo.poster_path = settings.TMDB_IMAGE_URL(image_path) mediainfo.poster_path = get_runtime_setting("TMDB_IMAGE_URL")(image_path)
return mediainfo return mediainfo
def obtain_images(self, mediainfo: MediaInfo) -> Optional[MediaInfo]: def obtain_images(self, mediainfo: MediaInfo) -> Optional[MediaInfo]:
@@ -1246,7 +1245,7 @@ class TheMovieDbModule(MediaAuxiliaryProviderMixin, _ModuleBase):
image_path = seasoninfo.get(image_type.value) image_path = seasoninfo.get(image_type.value)
if image_path: if image_path:
return settings.TMDB_IMAGE_URL(image_path, image_prefix) return get_runtime_setting("TMDB_IMAGE_URL")(image_path, image_prefix)
return None return None
def tmdb_movie_similar(self, tmdbid: int) -> List[MediaInfo]: def tmdb_movie_similar(self, tmdbid: int) -> List[MediaInfo]:
+7 -8
View File
@@ -1,15 +1,14 @@
from threading import Lock from threading import Lock
from typing import Optional, Tuple, Union, cast from typing import Optional, Tuple, Union, cast
from app.runtime.settings import RuntimeSettingsCompat
settings = RuntimeSettingsCompat()
from app.domain.context import MediaInfo from app.domain.context import MediaInfo
from app.domain.media import is_media_source_enabled from app.domain.media import is_media_source_enabled
from app.domain.meta.metabase import MetaBase from app.domain.meta.metabase import MetaBase
from app.runtime.execution import run_in_threadpool
from app.runtime.settings import get_runtime_setting
from app.modules import _ModuleBase from app.modules import _ModuleBase
from app.modules.thetvdb import tvdb_v4_official from app.modules.thetvdb import tvdb_v4_official
from app.runtime.execution import run_in_threadpool
from app.runtime.log import logger from app.runtime.log import logger
from app.schemas.types import ( from app.schemas.types import (
MediaRecognizeType, MediaRecognizeType,
@@ -39,11 +38,11 @@ class TheTvDbModule(_ModuleBase):
action = "刷新" if is_retry else "创建" action = "刷新" if is_retry else "创建"
logger.info(f"开始{action}TVDB登录会话...") logger.info(f"开始{action}TVDB登录会话...")
try: try:
if not settings.TVDB_V4_API_KEY: if not get_runtime_setting("TVDB_V4_API_KEY"):
raise ConnectionError("TVDB API Key 未配置,无法初始化会话。") raise ConnectionError("TVDB API Key 未配置,无法初始化会话。")
self.tvdb = tvdb_v4_official.TVDB(apikey=settings.TVDB_V4_API_KEY, self.tvdb = tvdb_v4_official.TVDB(apikey=get_runtime_setting("TVDB_V4_API_KEY"),
pin=settings.TVDB_V4_API_PIN, pin=get_runtime_setting("TVDB_V4_API_PIN"),
proxy=settings.PROXY, proxy=get_runtime_setting("PROXY"),
timeout=self.__timeout) timeout=self.__timeout)
if self.tvdb: if self.tvdb:
logger.info(f"TVDB登录会话{action}成功。") logger.info(f"TVDB登录会话{action}成功。")