refactor(torrent): group application capability

This commit is contained in:
jxxghp
2026-08-29 21:28:18 +08:00
parent b4b5f82511
commit fb5d7fc593
31 changed files with 133 additions and 72 deletions

View File

@@ -8,7 +8,7 @@ from app.api.dependencies.auth import (
)
from app.api.response import ResponseAPIRouter
from app.application.configuration import get_api_runtime_config_snapshot
from app.application.torrent_cache import TorrentCacheRecognitionService
from app.application.torrent.cache import TorrentCacheRecognitionService
from app.chain.media import MediaChain
from app.chain.torrents import TorrentsChain
from app.foundation.crypto import HashUtils

View File

@@ -0,0 +1 @@
"""种子下载与缓存应用能力包;宿主直接依赖职责子模块。"""

View File

@@ -3,10 +3,10 @@
from typing import Any, Optional
from app.domain.context import MediaInfo, MusicInfo
from app.domain.media import is_music_media_source, normalize_music_type
from app.domain.meta.metamusic import MetaMusic
from app.domain.metainfo import MetaInfo
from app.foundation.crypto import HashUtils
from app.domain.media import is_music_media_source, normalize_music_type
from app.schemas.types import MUSIC_ENTITY_RECORDING, MediaSource, MediaType, MusicTargetEntityType

View File

@@ -10,7 +10,7 @@ from app.application.subscription.contract import (
subscribe_media_key,
)
from app.application.subscription.mutation import SubscriptionActor
from app.application.torrent import TorrentHelper
from app.application.torrent.download import TorrentHelper
from app.chain._contracts import MusicSubscribeMixinHost
from app.chain.download import DownloadChain
from app.chain.media import MediaChain

View File

@@ -4,7 +4,7 @@ import copy
from typing import Callable, Dict, List, Optional, Set, Tuple, cast
from app.application.download import selection as _selection
from app.application.torrent import TorrentHelper
from app.application.torrent.download import TorrentHelper
from app.chain.download.contract import _DownloadOwnerBase
from app.domain import episode as episode_rules
from app.domain.context import (

View File

@@ -7,7 +7,7 @@ from app.application.configuration import get_chain_runtime_config_snapshot
from app.application.download.failures import (
DownloadFailureSnapshot,
)
from app.application.torrent import TorrentHelper
from app.application.torrent.download import TorrentHelper
from app.chain.download.contract import _DownloadOwnerBase
from app.domain.context import (
Context,

View File

@@ -9,7 +9,7 @@ from urllib.parse import urlencode, urljoin, urlparse
from app.application.configuration import get_chain_runtime_config_snapshot
from app.application.directory import validate_download_save_path
from app.application.torrent import TorrentHelper
from app.application.torrent.download import TorrentHelper
from app.chain.download.contract import _DownloadOwnerBase
from app.chain.download.ports import (
_close_download_response,

View File

@@ -8,7 +8,7 @@ from typing import Any, List, Optional, Tuple, Union, cast
from app.application.configuration import get_chain_runtime_config_snapshot
from app.application.directory import DirectoryHelper, validate_download_save_path
from app.application.torrent import TorrentHelper
from app.application.torrent.download import TorrentHelper
from app.chain.download.contract import _DownloadOwnerBase
from app.chain.download.ports import (
DownloadArchivePort,

View File

@@ -7,7 +7,7 @@ from app.application.messaging.media import (
PendingMediaInteraction,
media_interaction_manager,
)
from app.application.torrent import TorrentHelper
from app.application.torrent.download import TorrentHelper
from app.chain.base import ChainBase
from app.chain.download import DownloadChain
from app.chain.media import MediaChain

View File

@@ -10,7 +10,7 @@ from unicodedata import normalize
from app.application.configuration import (
get_configured_system_config,
)
from app.application.torrent import TorrentHelper
from app.application.torrent.download import TorrentHelper
from app.chain.search.contract import _SearchOwnerBase as _SearchOwnerBase
from app.domain.context import Context, MusicInfo, TorrentInfo
from app.domain.meta.metamusic import MetaMusic

View File

@@ -4,7 +4,7 @@ import copy
from typing import Callable, Dict, List, Optional, Tuple, cast
from app.application.configuration import get_configured_system_config
from app.application.torrent import TorrentHelper
from app.application.torrent.download import TorrentHelper
from app.chain.media import MediaChain
from app.chain.search.contract import _SearchOwnerBase
from app.domain.context import Context, MediaInfo, TorrentInfo

View File

@@ -4,7 +4,7 @@ import asyncio
import random
from typing import Any, AsyncIterator, Dict, List, Optional, cast
from app.application.torrent import TorrentHelper
from app.application.torrent.download import TorrentHelper
from app.chain.media import MediaChain
from app.chain.search.contract import _SearchOwnerBase as _SearchOwnerBase
from app.domain.context import MediaInfo, SubtitleInfo, TorrentInfo

View File

@@ -6,7 +6,7 @@ from typing import Callable, Dict, List, Optional
from app.application.configuration import get_configured_system_config
from app.application.subscription.contract import build_subscribe_meta, subscribe_media_key
from app.application.torrent import TorrentHelper
from app.application.torrent.download import TorrentHelper
from app.chain.media import MediaChain
from app.chain.subscribe.contract import _SubscribeOwnerBase
from app.chain.subscribe.identity import subscribe_recognize_kwargs

View File

@@ -6,7 +6,7 @@ from typing import Callable, Dict, List, Optional, Union
from app.application.configuration import get_configured_system_config
from app.application.rss import RssHelper
from app.application.site.sites import SitesHelper # pylint: disable=import-error,no-name-in-module
from app.application.torrent import TorrentHelper
from app.application.torrent.download import TorrentHelper
from app.chain.base import ChainBase
from app.chain.media import MediaChain
from app.domain import site as site_rules

View File

@@ -619,7 +619,8 @@ MODULE_ALIASES: Dict[str, ModuleAlias] = {
introduced="v3.0.0", owner="runtime",
),
"app.helper.torrent": ModuleAlias(
target="app.application.torrent", replacement="app.application.torrent",
target="app.application.torrent.download",
replacement="app.application.torrent.download",
introduced="v3.0.0", owner="application",
),
"app.helper.transferhistory": ModuleAlias(

View File

@@ -25,7 +25,7 @@ from app.application.security.cookie import (
configure_cookie_ports,
reset_cookie_ports,
)
from app.application.torrent import (
from app.application.torrent.download import (
TorrentHttpPort,
TorrentResponsePort,
configure_torrent_port,

View File

@@ -2,7 +2,7 @@ from typing import List, Optional
from pydantic import Field
from app.application.torrent import TorrentHelper
from app.application.torrent.download import TorrentHelper
from app.runtime.log import logger
from app.runtime.stop import runtime_stop_state
from app.schemas.workflow import ActionContext, ActionParams

View File

@@ -361,7 +361,7 @@ mentions media, site or torrent:
| Media | `context.py` owns canonical `Context`, `MediaInfo` and `TorrentInfo` construction; `projection/` owns the pure, input-immutable TMDB/Douban/Bangumi/AniList field mappings and TMDB image-builder port; `media.py` owns source selection policy; identity representation/normalization stays in `schemas/media.py`; `title.py` owns title-candidate and search-keyword rules; `episode.py` owns episode-range display; `scraper.py` owns Kodi-style NFO reading and metadata document generation |
| Recognition | `metainfo.py`, `meta/` and `tokens.py` parse names, paths, release groups, streaming platforms, anime, video and music metadata |
| Site | `site.py` owns site-domain exceptions and interprets HTML into business states such as logged-in and checked-in; configured catalog/auth/index resources stay in `app/application/site/`, generic URL/DOM parsing stays in foundation and network access stays in adapters |
| Torrent | `torrent.py` owns magnet-link semantics; configured download/cache/file behavior stays in `app/application/torrent.py` |
| Torrent | `domain/torrent.py` owns magnet-link semantics; configured download/file behavior stays in `application/torrent/download.py`, while cache recognition stays in `application/torrent/cache.py` |
`app/domain` may depend only on schemas and foundation. It must not read global
settings, access DB/network/filesystem adapters, import Rust, discover services

View File

@@ -1089,8 +1089,8 @@
"runtime_only": true
}
},
"edge_count": 8301,
"edge_sha256": "a1148b9576004423eb291429dc3e9a0e99282f14fe9d3d416539584a28aec8d0",
"edge_count": 8330,
"edge_sha256": "1a084d7f7953fed5f141f7bc6082442fffd69c0b71ad65a65b64e0454602c617",
"edges": [
"app -> app.foundation",
"app -> app.foundation.environment",
@@ -3536,7 +3536,8 @@
"app.api.endpoints.torrent -> app.api.response",
"app.api.endpoints.torrent -> app.application",
"app.api.endpoints.torrent -> app.application.configuration",
"app.api.endpoints.torrent -> app.application.torrent_cache",
"app.api.endpoints.torrent -> app.application.torrent",
"app.api.endpoints.torrent -> app.application.torrent.cache",
"app.api.endpoints.torrent -> app.chain",
"app.api.endpoints.torrent -> app.chain.media",
"app.api.endpoints.torrent -> app.chain.torrents",
@@ -4222,36 +4223,36 @@
"app.application.subscription.write -> app.schemas.common",
"app.application.subscription.write -> app.schemas.media",
"app.application.subscription.write -> app.schemas.types",
"app.application.torrent -> app.application",
"app.application.torrent -> app.application.configuration",
"app.application.torrent -> app.application.site",
"app.application.torrent -> app.application.site.query",
"app.application.torrent -> app.domain",
"app.application.torrent -> app.domain.context",
"app.application.torrent -> app.domain.meta",
"app.application.torrent -> app.domain.meta.metabase",
"app.application.torrent -> app.domain.meta.metamusic",
"app.application.torrent -> app.domain.metainfo",
"app.application.torrent -> app.domain.torrent",
"app.application.torrent -> app.foundation",
"app.application.torrent -> app.foundation.crypto",
"app.application.torrent -> app.foundation.text",
"app.application.torrent -> app.runtime",
"app.application.torrent -> app.runtime.cache",
"app.application.torrent -> app.runtime.log",
"app.application.torrent -> app.schemas",
"app.application.torrent -> app.schemas.media",
"app.application.torrent -> app.schemas.types",
"app.application.torrent_cache -> app.domain",
"app.application.torrent_cache -> app.domain.context",
"app.application.torrent_cache -> app.domain.media",
"app.application.torrent_cache -> app.domain.meta",
"app.application.torrent_cache -> app.domain.meta.metamusic",
"app.application.torrent_cache -> app.domain.metainfo",
"app.application.torrent_cache -> app.foundation",
"app.application.torrent_cache -> app.foundation.crypto",
"app.application.torrent_cache -> app.schemas",
"app.application.torrent_cache -> app.schemas.types",
"app.application.torrent.cache -> app.domain",
"app.application.torrent.cache -> app.domain.context",
"app.application.torrent.cache -> app.domain.media",
"app.application.torrent.cache -> app.domain.meta",
"app.application.torrent.cache -> app.domain.meta.metamusic",
"app.application.torrent.cache -> app.domain.metainfo",
"app.application.torrent.cache -> app.foundation",
"app.application.torrent.cache -> app.foundation.crypto",
"app.application.torrent.cache -> app.schemas",
"app.application.torrent.cache -> app.schemas.types",
"app.application.torrent.download -> app.application",
"app.application.torrent.download -> app.application.configuration",
"app.application.torrent.download -> app.application.site",
"app.application.torrent.download -> app.application.site.query",
"app.application.torrent.download -> app.domain",
"app.application.torrent.download -> app.domain.context",
"app.application.torrent.download -> app.domain.meta",
"app.application.torrent.download -> app.domain.meta.metabase",
"app.application.torrent.download -> app.domain.meta.metamusic",
"app.application.torrent.download -> app.domain.metainfo",
"app.application.torrent.download -> app.domain.torrent",
"app.application.torrent.download -> app.foundation",
"app.application.torrent.download -> app.foundation.crypto",
"app.application.torrent.download -> app.foundation.text",
"app.application.torrent.download -> app.runtime",
"app.application.torrent.download -> app.runtime.cache",
"app.application.torrent.download -> app.runtime.log",
"app.application.torrent.download -> app.schemas",
"app.application.torrent.download -> app.schemas.media",
"app.application.torrent.download -> app.schemas.types",
"app.application.transfer.workflow -> app.application",
"app.application.transfer.workflow -> app.application.history",
"app.application.transfer.workflow -> app.application.transfer",
@@ -4310,6 +4311,7 @@
"app.chain._music -> app.application.subscription.contract",
"app.chain._music -> app.application.subscription.mutation",
"app.chain._music -> app.application.torrent",
"app.chain._music -> app.application.torrent.download",
"app.chain._music -> app.chain",
"app.chain._music -> app.chain._contracts",
"app.chain._music -> app.chain.download",
@@ -4399,6 +4401,7 @@
"app.chain.download.batch -> app.application.download",
"app.chain.download.batch -> app.application.download.selection",
"app.chain.download.batch -> app.application.torrent",
"app.chain.download.batch -> app.application.torrent.download",
"app.chain.download.batch -> app.chain",
"app.chain.download.batch -> app.chain.download",
"app.chain.download.batch -> app.chain.download.contract",
@@ -4490,6 +4493,7 @@
"app.chain.download.selection -> app.application.download",
"app.chain.download.selection -> app.application.download.failures",
"app.chain.download.selection -> app.application.torrent",
"app.chain.download.selection -> app.application.torrent.download",
"app.chain.download.selection -> app.chain",
"app.chain.download.selection -> app.chain.download",
"app.chain.download.selection -> app.chain.download.contract",
@@ -4510,6 +4514,7 @@
"app.chain.download.submission -> app.application.configuration",
"app.chain.download.submission -> app.application.directory",
"app.chain.download.submission -> app.application.torrent",
"app.chain.download.submission -> app.application.torrent.download",
"app.chain.download.submission -> app.chain",
"app.chain.download.submission -> app.chain.download",
"app.chain.download.submission -> app.chain.download.contract",
@@ -4531,6 +4536,7 @@
"app.chain.download.subtitle -> app.application.configuration",
"app.chain.download.subtitle -> app.application.directory",
"app.chain.download.subtitle -> app.application.torrent",
"app.chain.download.subtitle -> app.application.torrent.download",
"app.chain.download.subtitle -> app.chain",
"app.chain.download.subtitle -> app.chain.download",
"app.chain.download.subtitle -> app.chain.download.contract",
@@ -4566,6 +4572,7 @@
"app.chain.interaction -> app.application.messaging",
"app.chain.interaction -> app.application.messaging.media",
"app.chain.interaction -> app.application.torrent",
"app.chain.interaction -> app.application.torrent.download",
"app.chain.interaction -> app.chain",
"app.chain.interaction -> app.chain.base",
"app.chain.interaction -> app.chain.download",
@@ -4905,6 +4912,7 @@
"app.chain.search.music -> app.application",
"app.chain.search.music -> app.application.configuration",
"app.chain.search.music -> app.application.torrent",
"app.chain.search.music -> app.application.torrent.download",
"app.chain.search.music -> app.chain",
"app.chain.search.music -> app.chain.search",
"app.chain.search.music -> app.chain.search.contract",
@@ -4968,6 +4976,7 @@
"app.chain.search.result -> app.application",
"app.chain.search.result -> app.application.configuration",
"app.chain.search.result -> app.application.torrent",
"app.chain.search.result -> app.application.torrent.download",
"app.chain.search.result -> app.chain",
"app.chain.search.result -> app.chain.media",
"app.chain.search.result -> app.chain.search",
@@ -4995,6 +5004,7 @@
"app.chain.search.site -> app.schemas.types",
"app.chain.search.subtitle -> app.application",
"app.chain.search.subtitle -> app.application.torrent",
"app.chain.search.subtitle -> app.application.torrent.download",
"app.chain.search.subtitle -> app.chain",
"app.chain.search.subtitle -> app.chain.media",
"app.chain.search.subtitle -> app.chain.search",
@@ -5157,6 +5167,7 @@
"app.chain.subscribe.match -> app.application.subscription",
"app.chain.subscribe.match -> app.application.subscription.contract",
"app.chain.subscribe.match -> app.application.torrent",
"app.chain.subscribe.match -> app.application.torrent.download",
"app.chain.subscribe.match -> app.chain",
"app.chain.subscribe.match -> app.chain.media",
"app.chain.subscribe.match -> app.chain.subscribe",
@@ -5317,6 +5328,7 @@
"app.chain.torrents -> app.application.rss",
"app.chain.torrents -> app.application.site",
"app.chain.torrents -> app.application.torrent",
"app.chain.torrents -> app.application.torrent.download",
"app.chain.torrents -> app.chain",
"app.chain.torrents -> app.chain.base",
"app.chain.torrents -> app.chain.media",
@@ -6303,10 +6315,6 @@
"app.modules -> app.schemas.message",
"app.modules -> app.schemas.system",
"app.modules -> app.schemas.types",
"app.modules._base -> app.modules",
"app.modules._base -> app.modules._base.downloader",
"app.modules._base -> app.modules._base.mediaserver",
"app.modules._base -> app.modules._base.notification",
"app.modules._base.downloader -> app.domain",
"app.modules._base.downloader -> app.domain.torrent",
"app.modules._base.downloader -> app.modules",
@@ -6413,6 +6421,7 @@
"app.modules.dingtalk -> app.domain.context",
"app.modules.dingtalk -> app.modules",
"app.modules.dingtalk -> app.modules._base",
"app.modules.dingtalk -> app.modules._base.notification",
"app.modules.dingtalk -> app.modules.dingtalk.dingtalk",
"app.modules.dingtalk -> app.schemas",
"app.modules.dingtalk -> app.schemas.message",
@@ -6432,6 +6441,7 @@
"app.modules.discord -> app.domain.context",
"app.modules.discord -> app.modules",
"app.modules.discord -> app.modules._base",
"app.modules.discord -> app.modules._base.notification",
"app.modules.discord -> app.modules.discord.discord",
"app.modules.discord -> app.runtime",
"app.modules.discord -> app.runtime.log",
@@ -6496,6 +6506,7 @@
"app.modules.douban.scraper -> app.schemas.types",
"app.modules.emby -> app.modules",
"app.modules.emby -> app.modules._base",
"app.modules.emby -> app.modules._base.mediaserver",
"app.modules.emby -> app.modules.emby.emby",
"app.modules.emby -> app.runtime",
"app.modules.emby -> app.runtime.log",
@@ -6537,6 +6548,7 @@
"app.modules.feishu -> app.domain.context",
"app.modules.feishu -> app.modules",
"app.modules.feishu -> app.modules._base",
"app.modules.feishu -> app.modules._base.notification",
"app.modules.feishu -> app.modules.feishu.feishu",
"app.modules.feishu -> app.runtime",
"app.modules.feishu -> app.runtime.log",
@@ -7100,6 +7112,7 @@
"app.modules.indexer.spider.yema -> app.schemas.types",
"app.modules.jellyfin -> app.modules",
"app.modules.jellyfin -> app.modules._base",
"app.modules.jellyfin -> app.modules._base.mediaserver",
"app.modules.jellyfin -> app.modules.jellyfin.jellyfin",
"app.modules.jellyfin -> app.runtime",
"app.modules.jellyfin -> app.runtime.log",
@@ -7222,6 +7235,7 @@
"app.modules.plex -> app.domain.context",
"app.modules.plex -> app.modules",
"app.modules.plex -> app.modules._base",
"app.modules.plex -> app.modules._base.mediaserver",
"app.modules.plex -> app.modules.plex.plex",
"app.modules.plex -> app.runtime",
"app.modules.plex -> app.runtime.events",
@@ -7260,6 +7274,7 @@
"app.modules.qbittorrent -> app.foundation.text",
"app.modules.qbittorrent -> app.modules",
"app.modules.qbittorrent -> app.modules._base",
"app.modules.qbittorrent -> app.modules._base.downloader",
"app.modules.qbittorrent -> app.modules.qbittorrent.qbittorrent",
"app.modules.qbittorrent -> app.runtime",
"app.modules.qbittorrent -> app.runtime.log",
@@ -7291,6 +7306,7 @@
"app.modules.qqbot.module -> app.domain.context",
"app.modules.qqbot.module -> app.modules",
"app.modules.qqbot.module -> app.modules._base",
"app.modules.qqbot.module -> app.modules._base.notification",
"app.modules.qqbot.module -> app.modules.qqbot",
"app.modules.qqbot.module -> app.modules.qqbot.qqbot",
"app.modules.qqbot.module -> app.runtime",
@@ -7334,6 +7350,7 @@
"app.modules.rtorrent -> app.foundation.text",
"app.modules.rtorrent -> app.modules",
"app.modules.rtorrent -> app.modules._base",
"app.modules.rtorrent -> app.modules._base.downloader",
"app.modules.rtorrent -> app.modules.rtorrent.rtorrent",
"app.modules.rtorrent -> app.runtime",
"app.modules.rtorrent -> app.runtime.log",
@@ -7351,6 +7368,7 @@
"app.modules.slack -> app.domain.context",
"app.modules.slack -> app.modules",
"app.modules.slack -> app.modules._base",
"app.modules.slack -> app.modules._base.notification",
"app.modules.slack -> app.modules.slack.slack",
"app.modules.slack -> app.runtime",
"app.modules.slack -> app.runtime.log",
@@ -7397,6 +7415,7 @@
"app.modules.synologychat -> app.domain.context",
"app.modules.synologychat -> app.modules",
"app.modules.synologychat -> app.modules._base",
"app.modules.synologychat -> app.modules._base.notification",
"app.modules.synologychat -> app.modules.synologychat.synologychat",
"app.modules.synologychat -> app.runtime",
"app.modules.synologychat -> app.runtime.log",
@@ -7422,6 +7441,7 @@
"app.modules.telegram.module -> app.domain.context",
"app.modules.telegram.module -> app.modules",
"app.modules.telegram.module -> app.modules._base",
"app.modules.telegram.module -> app.modules._base.notification",
"app.modules.telegram.module -> app.modules.telegram",
"app.modules.telegram.module -> app.modules.telegram.telegram",
"app.modules.telegram.module -> app.runtime",
@@ -7703,6 +7723,7 @@
"app.modules.transmission -> app.foundation.temporal",
"app.modules.transmission -> app.modules",
"app.modules.transmission -> app.modules._base",
"app.modules.transmission -> app.modules._base.downloader",
"app.modules.transmission -> app.modules.transmission.transmission",
"app.modules.transmission -> app.runtime",
"app.modules.transmission -> app.runtime.log",
@@ -7723,6 +7744,7 @@
"app.modules.trimemedia.api -> app.runtime.settings",
"app.modules.trimemedia.module -> app.modules",
"app.modules.trimemedia.module -> app.modules._base",
"app.modules.trimemedia.module -> app.modules._base.mediaserver",
"app.modules.trimemedia.module -> app.modules.trimemedia",
"app.modules.trimemedia.module -> app.modules.trimemedia.trimemedia",
"app.modules.trimemedia.module -> app.runtime",
@@ -7758,6 +7780,7 @@
"app.modules.ugreen.api -> app.runtime.log",
"app.modules.ugreen.module -> app.modules",
"app.modules.ugreen.module -> app.modules._base",
"app.modules.ugreen.module -> app.modules._base.mediaserver",
"app.modules.ugreen.module -> app.modules.ugreen",
"app.modules.ugreen.module -> app.modules.ugreen.ugreen",
"app.modules.ugreen.module -> app.runtime",
@@ -7787,6 +7810,7 @@
"app.modules.vocechat -> app.domain.context",
"app.modules.vocechat -> app.modules",
"app.modules.vocechat -> app.modules._base",
"app.modules.vocechat -> app.modules._base.notification",
"app.modules.vocechat -> app.modules.vocechat.vocechat",
"app.modules.vocechat -> app.runtime",
"app.modules.vocechat -> app.runtime.log",
@@ -7825,6 +7849,7 @@
"app.modules.wechat -> app.foundation.dom",
"app.modules.wechat -> app.modules",
"app.modules.wechat -> app.modules._base",
"app.modules.wechat -> app.modules._base.notification",
"app.modules.wechat -> app.modules.wechat.wechat",
"app.modules.wechat -> app.modules.wechat.wechatbot",
"app.modules.wechat -> app.runtime",
@@ -7871,6 +7896,7 @@
"app.modules.wechatclawbot -> app.domain.context",
"app.modules.wechatclawbot -> app.modules",
"app.modules.wechatclawbot -> app.modules._base",
"app.modules.wechatclawbot -> app.modules._base.notification",
"app.modules.wechatclawbot -> app.modules.wechatclawbot.wechatclawbot",
"app.modules.wechatclawbot -> app.runtime",
"app.modules.wechatclawbot -> app.runtime.cache",
@@ -7895,6 +7921,7 @@
"app.modules.wechatclawbot.wechatclawbot -> app.runtime.settings",
"app.modules.zspace -> app.modules",
"app.modules.zspace -> app.modules._base",
"app.modules.zspace -> app.modules._base.mediaserver",
"app.modules.zspace -> app.modules.zspace.zspace",
"app.modules.zspace -> app.runtime",
"app.modules.zspace -> app.runtime.log",
@@ -9149,6 +9176,7 @@
"app.startup.initializers.site -> app.application.security",
"app.startup.initializers.site -> app.application.security.cookie",
"app.startup.initializers.site -> app.application.torrent",
"app.startup.initializers.site -> app.application.torrent.download",
"app.startup.initializers.site -> app.chain",
"app.startup.initializers.site -> app.chain.site",
"app.startup.initializers.transfer -> app.chain",
@@ -9326,6 +9354,7 @@
"app.workflow.actions.filter_medias -> app.workflow.actions",
"app.workflow.actions.filter_torrents -> app.application",
"app.workflow.actions.filter_torrents -> app.application.torrent",
"app.workflow.actions.filter_torrents -> app.application.torrent.download",
"app.workflow.actions.filter_torrents -> app.runtime",
"app.workflow.actions.filter_torrents -> app.runtime.log",
"app.workflow.actions.filter_torrents -> app.runtime.stop",
@@ -9394,7 +9423,7 @@
"app.workflow.actions.transfer_file -> app.workflow",
"app.workflow.actions.transfer_file -> app.workflow.actions"
],
"module_count": 972,
"module_count": 973,
"modules": [
"app",
"app.adapters",
@@ -9754,7 +9783,8 @@
"app.application.subscription.search",
"app.application.subscription.write",
"app.application.torrent",
"app.application.torrent_cache",
"app.application.torrent.cache",
"app.application.torrent.download",
"app.application.transfer",
"app.application.transfer.execution",
"app.application.transfer.workflow",

View File

@@ -104,7 +104,6 @@
"app/agent/tools/impl/write_file.py",
"app/api/openai_utils.py",
"app/api/router_specs.py",
"app/application/torrent_cache.py",
"app/chain/_contracts.py",
"app/chain/_interaction.py",
"app/chain/_messaging.py",

View File

@@ -1225,7 +1225,7 @@
"app/application/subscription/write.py": {
"arg-type": 2
},
"app/application/torrent.py": {
"app/application/torrent/download.py": {
"arg-type": 2,
"assignment": 3,
"attr-defined": 1,
@@ -1237,7 +1237,7 @@
"union-attr": 4,
"var-annotated": 1
},
"app/application/torrent_cache.py": {
"app/application/torrent/cache.py": {
"type-arg": 1
},
"app/chain/_interaction.py": {

View File

@@ -216,9 +216,6 @@
"app/application/storage.py": {
"I001": 1
},
"app/application/torrent_cache.py": {
"I001": 1
},
"app/db/__init__.py": {
"I001": 1
},

View File

@@ -565,8 +565,8 @@
"introduced": "v3.0.0",
"is_package": false,
"owner": "application",
"replacement": "app.application.torrent",
"target": "app.application.torrent"
"replacement": "app.application.torrent.download",
"target": "app.application.torrent.download"
},
"app.helper.transferhistory": {
"introduced": "v3.0.0",

View File

@@ -35,7 +35,7 @@ FROZEN_DIRECT_ADAPTER_IMPORTS = {
("app.application.security.cookie", "app.adapters.external.ocr"): "S2-L6",
("app.application.security.cookie", "app.adapters.network.browser"): "S2-L6",
("app.application.security.cookie", "app.adapters.network.http"): "S2-L6",
("app.application.torrent", "app.adapters.network.http"): "S2-L6",
("app.application.torrent.download", "app.adapters.network.http"): "S2-L6",
("app.application.transfer.workflow", "app.adapters.system.host"): "S2-L6",
}

View File

@@ -84,6 +84,8 @@ RETIRED_CANONICAL_FILES = (
"app/adapters/network/sites.pyi",
"app/application/plugins.py",
"app/application/subscribe.py",
"app/application/torrent.py",
"app/application/torrent_cache.py",
"app/application/chain/durable_events.py",
"app/application/transfer.py",
"app/application/transfer_execution.py",
@@ -363,6 +365,34 @@ def test_runtime_dependencies_use_same_named_single_word_package() -> None:
assert violations == []
def test_application_torrent_uses_same_named_single_word_package() -> None:
"""种子应用能力必须归入同名包,包根不得重复导出内部实现。"""
package = APP_ROOT / "application" / "torrent"
assert {path.name for path in package.glob("*.py")} == {
"__init__.py",
"cache.py",
"download.py",
}
init_tree = ast.parse(
(package / "__init__.py").read_text(encoding="utf-8"),
filename=str(package / "__init__.py"),
)
assert ast.get_docstring(init_tree)
assert len(init_tree.body) == 1
root_imports: list[str] = []
for path in APP_ROOT.rglob("*.py"):
if path.is_relative_to(APP_ROOT / "plugins"):
continue
tree = ast.parse(path.read_text(encoding="utf-8-sig"), filename=str(path))
for node in ast.walk(tree):
if isinstance(node, ast.ImportFrom) and node.module == "app.application.torrent":
root_imports.append(
f"{path.relative_to(PROJECT_ROOT).as_posix()}:{node.lineno}"
)
assert root_imports == []
def test_host_module_package_roots_only_export_capability_entrypoints() -> None:
"""宿主模块包根只公开 capability entrypoint,内部 owner 必须直达子模块。"""
base_path = APP_ROOT / "modules" / "_base" / "__init__.py"

View File

@@ -16,7 +16,7 @@ from app.domain.meta.runtime import (
get_media_extensions,
get_metainfo_accelerator,
)
from app.application.torrent import TorrentHelper
from app.application.torrent.download import TorrentHelper
from app.schemas.types import MediaSource, MediaType
from tests.cases.meta import meta_cases

View File

@@ -5,12 +5,12 @@ from types import SimpleNamespace
import pytest
import app.application.torrent.download as torrent_module
from app.application import rss as rss_module
from app.application import torrent as torrent_module
from app.application.rss import RssHelper, configure_rss_ports
from app.application.security import cookie as cookie_module
from app.application.security.cookie import CookieHelper, configure_cookie_ports
from app.application.torrent import (
from app.application.torrent.download import (
TorrentHelper,
configure_torrent_port,
)

View File

@@ -9,9 +9,9 @@ from typing import Iterator, Optional
import pytest
import app.application.torrent.download as torrent_module
from app.adapters.external import cookiecloud as cookiecloud_module
from app.application import rss as rss_module
from app.application import torrent as torrent_module
from app.application.security import cookie as cookie_module
from app.application.site.contract import SiteSnapshot
from app.chain import site as site_module

View File

@@ -400,7 +400,10 @@ def _load_subscribe_chain_class():
)
helper_mediaserver_module.MediaServerHelper = type("MediaServerHelper", (), {})
helper_torrent_module = ensure_module("app.application.torrent", types.ModuleType("app.application.torrent"))
helper_torrent_module = ensure_module(
"app.application.torrent.download",
types.ModuleType("app.application.torrent.download"),
)
helper_torrent_module.TorrentHelper = type("TorrentHelper", (), {})
db_model_module = ensure_module("app.db.models.subscribe", types.ModuleType("app.db.models.subscribe"))
@@ -490,8 +493,8 @@ def _load_subscribe_chain_class():
import app.startup.initializers.chain as chain_initializer
from app.application.messaging.subscribe import SubscribeInteractionHandler
from app.application.subscription.contract import SubscriptionSnapshot, build_subscribe_meta
from app.chain.subscribe import SubscribeChain as ProductionSubscribeChain
from app.chain.subscribe.context import _SubscribeCreateContext
from app.chain.subscribe.facade import SubscribeChain as ProductionSubscribeChain
class SubscribeChain(ProductionSubscribeChain):
"""保留存量单元测试按调用时替换 repository 的隔离接缝。"""

View File

@@ -3,7 +3,7 @@ from types import SimpleNamespace
from unittest.mock import patch
from app.domain.context import MediaInfo, TorrentInfo
from app.application.torrent import TorrentHelper
from app.application.torrent.download import TorrentHelper
from app.modules.filter import FilterModule
from app.application.rules import BUILTIN_RULE_SET
from app.adapters.system import rust as rust_accel