fix: clean typing issues and refresh runtime dependencies

Align endpoint/module type hints and config reload handling while updating base Python image and package pins to improve build/runtime compatibility.

Made-with: Cursor
This commit is contained in:
DDSRem
2026-03-24 19:21:04 +08:00
parent aae50004b1
commit 517300afe9
14 changed files with 34 additions and 33 deletions

View File

@@ -5,15 +5,13 @@ from fastapi import APIRouter, Depends, Body
from app import schemas
from app.chain.download import DownloadChain
from app.chain.media import MediaChain
from app.core.config import settings
from app.core.context import MediaInfo, Context, TorrentInfo
from app.core.event import eventmanager
from app.core.metainfo import MetaInfo
from app.core.security import verify_token
from app.db.models.user import User
from app.db.systemconfig_oper import SystemConfigOper
from app.db.user_oper import get_current_active_user
from app.schemas.types import ChainEventType, SystemConfigKey
from app.schemas.types import SystemConfigKey
router = APIRouter()

View File

@@ -12,7 +12,6 @@ from app.db.models.user import User
from app.db.user_oper import get_current_active_superuser_async, \
get_current_active_user_async, get_current_active_user
from app.db.userconfig_oper import UserConfigOper
from app.utils.otp import OtpUtils
router = APIRouter()

View File

@@ -253,7 +253,6 @@ class MediaChain(ChainBase, ConfigReloadMixin, metaclass=Singleton):
"""
流式下载图片并保存到文件
:param storagechain: StorageChain实例
:param fileitem: 关联的媒体文件项
:param path: 图片文件路径
:param url: 图片下载URL

View File

@@ -22,7 +22,6 @@ from webauthn.helpers.structs import (
PublicKeyCredentialDescriptor,
AuthenticatorTransport,
UserVerificationRequirement,
AuthenticatorAttachment,
ResidentKeyRequirement,
AuthenticatorSelectionCriteria
)

View File

@@ -714,7 +714,7 @@ class Emby:
logger.error(f"连接Users/Items出错" + str(e))
return None
def get_webhook_message(self, form: any, args: dict) -> Optional[schemas.WebhookEventInfo]:
def get_webhook_message(self, form: Any, args: dict) -> Optional[schemas.WebhookEventInfo]:
"""
解析Emby Webhook报文
电影:

View File

@@ -111,7 +111,7 @@ class BitptSiteUserInfo(SiteParserBase):
def _parse_message_content(self, html_text) -> Tuple[Optional[str], Optional[str], Optional[str]]:
pass
def _parse_user_torrent_seeding_info(self, html_text: str):
def _parse_user_torrent_seeding_info(self, html_text: str, **kwargs):
pass
def parse(self):

View File

@@ -117,7 +117,7 @@ class ZhixingSiteUserInfo(SiteParserBase):
def _parse_message_content(self, html_text) -> Tuple[Optional[str], Optional[str], Optional[str]]:
pass
def _parse_user_torrent_seeding_info(self, html_text: str):
def _parse_user_torrent_seeding_info(self, html_text: str, multi_page: bool = False):
"""
占位,避免抽象类报错
"""

View File

@@ -569,7 +569,7 @@ class Jellyfin:
logger.error(f"连接Library/Refresh出错" + str(e))
return False
def get_webhook_message(self, body: any) -> Optional[schemas.WebhookEventInfo]:
def get_webhook_message(self, body: Any) -> Optional[schemas.WebhookEventInfo]:
"""
解析Jellyfin报文
{

View File

@@ -549,7 +549,7 @@ class Plex:
logger.error(f"获取媒体库列表出错:{str(err)}")
return None
def get_webhook_message(self, form: any) -> Optional[schemas.WebhookEventInfo]:
def get_webhook_message(self, form: Any) -> Optional[schemas.WebhookEventInfo]:
"""
解析Plex报文
eventItem 字段的含义

View File

@@ -409,7 +409,7 @@ class TrimeMedia:
return lib
return None
def get_webhook_message(self, body: any) -> Optional[schemas.WebhookEventInfo]:
def get_webhook_message(self, body: Any) -> Optional[schemas.WebhookEventInfo]:
pass
def get_iteminfo(self, itemid: str) -> Optional[schemas.MediaServerItem]:

View File

@@ -17,34 +17,44 @@ class ConfigReloadMixin:
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
config_watch = getattr(cls, 'CONFIG_WATCH', None)
config_watch = getattr(cls, "CONFIG_WATCH", None)
if not config_watch:
return
# 检查 on_config_changed 方法是否为异步
is_async = inspect.iscoroutinefunction(cls.on_config_changed)
method_name = 'handle_config_changed'
method_name = "handle_config_changed"
# 创建事件处理函数
def create_handler(is_async):
if is_async:
async def wrapper(self: ConfigReloadMixin, event: Event):
if not event:
return
changed_keys = getattr(event.event_data, "key", set()) & config_watch
changed_keys = (
getattr(event.event_data, "key", set()) & config_watch
)
if not changed_keys:
return
logger.info(f"配置 {', '.join(changed_keys)} 变更,重载 {self.get_reload_name()}...")
await self.on_config_changed()
logger.info(
f"配置 {', '.join(changed_keys)} 变更,重载 {self.get_reload_name()}..."
)
self.on_config_changed()
else:
def wrapper(self: ConfigReloadMixin, event: Event):
if not event:
return
changed_keys = getattr(event.event_data, "key", set()) & config_watch
changed_keys = (
getattr(event.event_data, "key", set()) & config_watch
)
if not changed_keys:
return
logger.info(f"配置 {', '.join(changed_keys)} 变更,重载 {self.get_reload_name()}...")
logger.info(
f"配置 {', '.join(changed_keys)} 变更,重载 {self.get_reload_name()}..."
)
self.on_config_changed()
return wrapper
@@ -52,7 +62,7 @@ class ConfigReloadMixin:
# 创建并设置处理函数
handler = create_handler(is_async)
handler.__module__ = cls.__module__
handler.__qualname__ = f'{cls.__name__}.{method_name}'
handler.__qualname__ = f"{cls.__name__}.{method_name}"
setattr(cls, method_name, handler)
# 添加为事件处理器
eventmanager.add_event_listener(EventType.ConfigChanged, handler)

View File

@@ -1,9 +1,11 @@
from typing import Tuple
import pyotp
class OtpUtils:
@staticmethod
def generate_secret_key(username: str) -> (str, str):
def generate_secret_key(username: str) -> Tuple[str, str]:
try:
secret = pyotp.random_base32()
uri = pyotp.totp.TOTP(secret).provisioning_uri(name='MoviePilot',

View File

@@ -1,4 +1,4 @@
FROM python:3.12.8-slim-bookworm AS base
FROM python:3.12.13-slim-bookworm AS base
# 准备软件包
@@ -68,7 +68,7 @@ WORKDIR /app
COPY requirements.in requirements.in
RUN python3 -m venv ${VENV_PATH} \
&& pip install --upgrade "pip<25.0" \
&& pip install "Cython" "pip-tools<7.5" \
&& pip install "Cython~=3.1.2" "pip-tools<7.5" \
&& pip-compile requirements.in \
&& pip install -r requirements.txt

View File

@@ -10,6 +10,7 @@ python-multipart~=0.0.9
aiofiles~=24.1.0
aioshutil~=1.5
alembic~=1.16.2
anyio~=4.10.0
bcrypt~=4.0.1
regex~=2024.11.6
cn2an~=0.5.19
@@ -22,6 +23,7 @@ urllib3~=2.5.0
lxml~=6.0.0
pyquery~=2.0.1
ruamel.yaml~=0.18.14
PyYAML~=6.0.2
APScheduler~=3.11.0
cryptography~=45.0.4
pytz~=2025.2
@@ -31,10 +33,8 @@ plexapi~=4.17.0
transmission-rpc~=4.3.0
Jinja2~=3.1.6
pyparsing~=3.2.3
func_timeout==4.3.5
bs4~=0.0.2
beautifulsoup4~=4.13.4
pillow~=11.2.1
pillow~=12.1.1
pillow-avif-plugin~=1.5.2
pyTelegramBotAPI~=4.27.0
telegramify-markdown~=0.5.2
@@ -49,24 +49,18 @@ starlette~=0.46.2
PyVirtualDisplay~=3.0
psutil~=7.0.0
python-dotenv~=1.1.1
python-hosts~=1.1.2
watchdog~=6.0.0
watchfiles~=1.1.0
cacheout~=0.16.0
click~=8.2.1
requests-cache~=1.2.1
parse~=1.20.2
docker~=7.1.0
pywin32==310; platform_system == "Windows"
cachetools~=6.1.0
fast-bencode~=1.1.7
pystray~=0.19.5
pyotp~=2.9.0
webauthn~=2.7.0
Pinyin2Hanzi~=0.1.1
pywebpush~=2.0.3
aiopathlib~=0.6.0
asynctempfile~=0.5.0
aiosqlite~=0.21.0
psycopg2-binary~=2.9.10
asyncpg~=0.30.0
@@ -88,8 +82,8 @@ langchain-community~=0.4.1
langchain-openai~=1.1.11
langchain-google-genai~=4.2.1
langchain-deepseek~=1.0.1
langchain-experimental~=0.4.1
langgraph~=1.1.3
openai~=2.29.0
google-genai~=1.68.0
ddgs~=9.10.0
websocket-client~=1.8.0