refactor: normalize capability module paths

This commit is contained in:
jxxghp
2026-08-27 22:20:38 +08:00
parent ea58c245dd
commit f134e068e7
85 changed files with 749 additions and 691 deletions
+39 -41
View File
@@ -23,7 +23,6 @@ prepare_backend()
# 复用共享 autouse 网络守卫;同一实现亦供各插件仓 conftest import 复用,避免逐仓维护
from app.testing.network_guard import block_real_network # noqa: E402,F401
TResult = TypeVar("TResult")
@@ -104,31 +103,29 @@ def pytest_runtest_call(item):
def configure_plugin_system_services():
"""为绕过完整启动流程的单元测试装配真实插件系统适配器。"""
from app.adapters.web.security.access import configure_token_codec
from app.application.security.token import (
create_access_token,
decode_access_token,
)
from app.api.data import configure_api_data_ports
from app.application.configuration import (
RuntimeConfiguration,
RuntimeSettingsService,
SystemConfigService,
TransferRetryConfig,
configure_token_runtime_config,
configure_runtime_configuration,
configure_runtime_settings,
configure_system_config,
configure_token_runtime_config,
configure_transfer_retry_config,
)
from app.runtime.config import settings
from app.runtime.settings import configure_runtime_setting_provider
from app.startup.composition.configuration import (
build_api_runtime_config,
build_chain_runtime_config,
build_scheduler_runtime_config,
build_token_runtime_config,
from app.application.security.token import (
create_access_token,
decode_access_token,
)
from app.application.security.userconfig import (
UserConfigurationService,
configure_user_configuration,
)
from app.application.service import configure_service_directory
from app.db.oper.systemconfig import SystemConfigOper
from app.db.oper.userconfig import UserConfigOper
from app.db.session import (
SessionFactory,
async_session_scope,
@@ -140,11 +137,13 @@ def configure_plugin_system_services():
SqlAlchemyUnitOfWork,
configure_transaction_runners,
)
from app.db.oper.systemconfig import SystemConfigOper
from app.db.oper.userconfig import UserConfigOper
from app.application.security.userconfig import (
UserConfigurationService,
configure_user_configuration,
from app.runtime.config import settings
from app.runtime.settings import configure_runtime_setting_provider
from app.startup.composition.configuration import (
build_api_runtime_config,
build_chain_runtime_config,
build_scheduler_runtime_config,
build_token_runtime_config,
)
configure_token_codec(create_access_token, decode_access_token)
@@ -181,25 +180,25 @@ def configure_plugin_system_services():
max_failed_retries=settings.TRANSFER_MAX_FAILED_RETRIES,
)
)
from app.application.chain.data import configure_chain_data_ports
from app.application.subscription.write import configure_subscribe_writer
from app.application.plugin.runtime import configure_plugin_runtime
from app.application.module import configure_module_runtime
from app.application.chain.context import (
ChainRuntimeContext,
configure_chain_runtime_context_provider,
)
from app.application.messaging.message import MessageHelper, MessageQueueManager
from app.application.chain.data import configure_chain_data_ports
from app.application.messaging.chat import (
AgentChatService,
AgentChatPersistenceService,
configure_agent_chat_service,
AgentChatService,
configure_agent_chat_persistence,
configure_agent_chat_service,
)
from app.application.messaging.message import MessageHelper, MessageQueueManager
from app.application.module import configure_module_runtime
from app.application.plugin.runtime import configure_plugin_runtime
from app.application.subscription.write import configure_subscribe_writer
from app.runtime.cache import AsyncFileCache, FileCache
from app.runtime.events import EventManager
from app.runtime.extensions.module_manager import ModuleManager
from app.runtime.extensions.module.dispatcher import ModuleInvocationDispatcher
from app.runtime.extensions.module_manager import ModuleManager
from app.runtime.extensions.plugin_manager import PluginManager
from app.runtime.extensions.service_config import ServiceConfigHelper
configure_service_directory(
@@ -208,8 +207,8 @@ def configure_plugin_system_services():
)
configure_plugin_runtime(lambda: PluginManager())
configure_module_runtime(lambda: ModuleManager())
from app.application.site.query import SiteQueryService, configure_site_query_service
from app.application.site.health import SiteHealthService, configure_site_health_service
from app.application.site.query import SiteQueryService, configure_site_query_service
from app.application.workflow import (
WorkflowQueryService,
configure_workflow_query,
@@ -222,27 +221,26 @@ def configure_plugin_system_services():
AgentTaskExecutionService,
configure_agent_task_execution,
)
from app.db.adapters.download import TransactionalDownloadFailureRepository
from app.db.adapters.site import TransactionalSiteRepository
from app.db.adapters.subscription import TransactionalSubscribeWriter
from app.db.adapters.transaction import TransactionalWriteRunner
from app.db.adapters.transfer.admission import TransactionalTransferAdmissionRepository
from app.db.adapters.transfer.execution import (
TransactionalTransferExecutionRepository,
)
from app.db.adapters.workflow import TransactionalWorkflowExecutionService
from app.db.oper.agentchat import AgentChatOper
from app.db.oper.downloadfailure import DownloadFailureOper
from app.db.oper.downloadhistory import DownloadHistoryOper
from app.db.oper.mediaserver import MediaServerOper
from app.db.oper.message import MessageOper
from app.db.oper.passkey import PassKeyOper
from app.db.oper.site import SiteOper
from app.db.oper.subscribe import SubscribeOper
from app.db.oper.subscribehistory import SubscribeHistoryOper
from app.db.oper.transferhistory import TransferHistoryOper
from app.db.adapters.transfer import TransactionalTransferAdmissionRepository
from app.db.adapters.transfer_execution import (
TransactionalTransferExecutionRepository,
)
from app.db.oper.user import UserOper
from app.db.oper.workflow import WorkflowOper, configure_workflow_legacy_writer
from app.db.oper.message import MessageOper
from app.db.oper.passkey import PassKeyOper
from app.db.adapters.subscription import TransactionalSubscribeWriter
from app.db.adapters.download import TransactionalDownloadFailureRepository
from app.db.adapters.site import TransactionalSiteRepository
from app.db.adapters.workflow import TransactionalWorkflowExecutionService
from app.db.adapters.transaction import TransactionalWriteRunner
def create_sync_session() -> Session:
"""为无显式会话的 Oper 测试入口创建独占同步 Session。"""
@@ -363,8 +361,8 @@ def configure_plugin_system_services():
)
configure_agent_chat_service(AgentChatService(repository=AgentChatOper()))
from app.adapters.external.market import (
PluginHelper,
VERSION_BACKWARD_COMPATIBLE_FLAGS,
PluginHelper,
)
from app.adapters.external.plugin.client import PluginMarketClient
from app.adapters.system.plugin.dependency import PluginDependencyInstaller
@@ -389,9 +387,9 @@ def configure_plugin_system_services():
frozen=lambda: False,
install=lambda **_kwargs: (False, "测试环境未装配插件安装 Gateway"),
))
from app.agent.skills.registry import SkillHelper
from app.agent.llm.gateway import register_llm_provider_runtime
from app.agent.llm.provider import LLMProviderManager
from app.agent.skills.registry import SkillHelper
from app.application.messaging.skill import register_skill_catalog_provider
register_skill_catalog_provider(lambda: SkillHelper())
+3 -3
View File
@@ -1,8 +1,8 @@
{
"application": {
"covered_lines": 9966,
"percent": 78.61,
"statements": 12678
"covered_lines": 9992,
"percent": 78.63,
"statements": 12707
},
"domain": {
"covered_lines": 3392,
+115 -97
View File
@@ -77,7 +77,7 @@
"target": "app.adapters.network.http"
},
{
"source": "app.application.transfer",
"source": "app.application.transfer.workflow",
"target": "app.adapters.system.host"
},
{
@@ -154,7 +154,7 @@
"app.application.security.cookie",
"app.application.security.passkey",
"app.application.torrent",
"app.application.transfer",
"app.application.transfer.workflow",
"app.chain._recognition",
"app.chain._transfer",
"app.chain.download",
@@ -1441,8 +1441,8 @@
"runtime_only": true
}
},
"edge_count": 6882,
"edge_sha256": "602a73df30503fec4f4f01e28020222497cdadcad731dfedca40a3e4b1133c0d",
"edge_count": 6898,
"edge_sha256": "c73faf7e29ee12a862cf2332f1803fd4eb8a3f4d2994ed81075ff198e896f8df",
"edges": [
"app -> app.runtime",
"app -> app.runtime.compat",
@@ -1532,7 +1532,7 @@
"app.adapters.network.browser -> app.adapters.network.http",
"app.adapters.network.browser -> app.runtime",
"app.adapters.network.browser -> app.runtime.log",
"app.adapters.network.browser -> app.runtime.managed_resources",
"app.adapters.network.browser -> app.runtime.resources",
"app.adapters.network.browser -> app.runtime.settings",
"app.adapters.network.cloudflare -> app.runtime",
"app.adapters.network.cloudflare -> app.runtime.log",
@@ -1553,7 +1553,7 @@
"app.adapters.system.display -> app.foundation.singleton",
"app.adapters.system.display -> app.runtime",
"app.adapters.system.display -> app.runtime.log",
"app.adapters.system.display -> app.runtime.managed_resources",
"app.adapters.system.display -> app.runtime.resources",
"app.adapters.system.display.resource -> app.adapters",
"app.adapters.system.display.resource -> app.adapters.system",
"app.adapters.system.display.resource -> app.adapters.system.host",
@@ -2219,7 +2219,8 @@
"app.agent.tools.impl.delete_transfer_history -> app.application.agentdata",
"app.agent.tools.impl.delete_transfer_history -> app.application.chain",
"app.agent.tools.impl.delete_transfer_history -> app.application.chain.data",
"app.agent.tools.impl.delete_transfer_history -> app.application.transfer_execution",
"app.agent.tools.impl.delete_transfer_history -> app.application.transfer",
"app.agent.tools.impl.delete_transfer_history -> app.application.transfer.execution",
"app.agent.tools.impl.delete_transfer_history -> app.chain",
"app.agent.tools.impl.delete_transfer_history -> app.chain.storage",
"app.agent.tools.impl.delete_transfer_history -> app.runtime",
@@ -3313,7 +3314,8 @@
"app.api.endpoints.history -> app.application.chain.data",
"app.api.endpoints.history -> app.application.configuration",
"app.api.endpoints.history -> app.application.history",
"app.api.endpoints.history -> app.application.transfer_execution",
"app.api.endpoints.history -> app.application.transfer",
"app.api.endpoints.history -> app.application.transfer.execution",
"app.api.endpoints.history -> app.runtime",
"app.api.endpoints.history -> app.runtime.config",
"app.api.endpoints.history -> app.runtime.log",
@@ -3824,7 +3826,8 @@
"app.api.endpoints.transfer -> app.application.configuration",
"app.api.endpoints.transfer -> app.application.directory",
"app.api.endpoints.transfer -> app.application.history",
"app.api.endpoints.transfer -> app.application.transfer_execution",
"app.api.endpoints.transfer -> app.application.transfer",
"app.api.endpoints.transfer -> app.application.transfer.execution",
"app.api.endpoints.transfer -> app.chain",
"app.api.endpoints.transfer -> app.chain.media",
"app.api.endpoints.transfer -> app.chain.transfer",
@@ -3977,26 +3980,28 @@
"app.application.chain.context -> app.application",
"app.application.chain.context -> app.application.chain",
"app.application.chain.context -> app.application.chain.data",
"app.application.chain.context -> app.application.chain.durable_events",
"app.application.chain.context -> app.application.chain.events",
"app.application.chain.context -> app.application.configuration",
"app.application.chain.context -> app.runtime",
"app.application.chain.context -> app.runtime.stop",
"app.application.chain.data -> app.application",
"app.application.chain.data -> app.application.transfer",
"app.application.chain.data -> app.application.transfer_execution",
"app.application.chain.durable_events -> app.application",
"app.application.chain.durable_events -> app.application.history",
"app.application.chain.durable_events -> app.application.transfer_execution",
"app.application.chain.durable_events -> app.domain",
"app.application.chain.durable_events -> app.domain.context",
"app.application.chain.durable_events -> app.domain.meta",
"app.application.chain.durable_events -> app.domain.meta.metabase",
"app.application.chain.durable_events -> app.domain.meta.metamusic",
"app.application.chain.durable_events -> app.domain.metainfo",
"app.application.chain.durable_events -> app.schemas",
"app.application.chain.durable_events -> app.schemas.file",
"app.application.chain.durable_events -> app.schemas.transfer",
"app.application.chain.durable_events -> app.schemas.types",
"app.application.chain.data -> app.application.transfer.execution",
"app.application.chain.data -> app.application.transfer.workflow",
"app.application.chain.events -> app.application",
"app.application.chain.events -> app.application.history",
"app.application.chain.events -> app.application.transfer",
"app.application.chain.events -> app.application.transfer.execution",
"app.application.chain.events -> app.domain",
"app.application.chain.events -> app.domain.context",
"app.application.chain.events -> app.domain.meta",
"app.application.chain.events -> app.domain.meta.metabase",
"app.application.chain.events -> app.domain.meta.metamusic",
"app.application.chain.events -> app.domain.metainfo",
"app.application.chain.events -> app.schemas",
"app.application.chain.events -> app.schemas.file",
"app.application.chain.events -> app.schemas.transfer",
"app.application.chain.events -> app.schemas.types",
"app.application.configuration -> app.application",
"app.application.configuration -> app.application.database",
"app.application.configuration -> app.schemas",
@@ -4441,31 +4446,33 @@
"app.application.torrent_cache -> app.foundation.crypto",
"app.application.torrent_cache -> app.schemas",
"app.application.torrent_cache -> app.schemas.types",
"app.application.transfer -> app.adapters",
"app.application.transfer -> app.adapters.system",
"app.application.transfer -> app.adapters.system.host",
"app.application.transfer -> app.application",
"app.application.transfer -> app.application.agent",
"app.application.transfer -> app.application.transfer_execution",
"app.application.transfer -> app.domain",
"app.application.transfer -> app.domain.context",
"app.application.transfer -> app.domain.media",
"app.application.transfer -> app.domain.meta",
"app.application.transfer -> app.domain.meta.metabase",
"app.application.transfer -> app.domain.meta.metamusic",
"app.application.transfer -> app.foundation",
"app.application.transfer -> app.foundation.text",
"app.application.transfer -> app.runtime",
"app.application.transfer -> app.runtime.log",
"app.application.transfer -> app.schemas",
"app.application.transfer -> app.schemas.file",
"app.application.transfer -> app.schemas.history",
"app.application.transfer -> app.schemas.media",
"app.application.transfer -> app.schemas.system",
"app.application.transfer -> app.schemas.tmdb",
"app.application.transfer -> app.schemas.transfer",
"app.application.transfer -> app.schemas.types",
"app.application.transfer -> app.schemas.workflow",
"app.application.transfer.workflow -> app.adapters",
"app.application.transfer.workflow -> app.adapters.system",
"app.application.transfer.workflow -> app.adapters.system.host",
"app.application.transfer.workflow -> app.application",
"app.application.transfer.workflow -> app.application.agent",
"app.application.transfer.workflow -> app.application.transfer",
"app.application.transfer.workflow -> app.application.transfer.execution",
"app.application.transfer.workflow -> app.domain",
"app.application.transfer.workflow -> app.domain.context",
"app.application.transfer.workflow -> app.domain.media",
"app.application.transfer.workflow -> app.domain.meta",
"app.application.transfer.workflow -> app.domain.meta.metabase",
"app.application.transfer.workflow -> app.domain.meta.metamusic",
"app.application.transfer.workflow -> app.foundation",
"app.application.transfer.workflow -> app.foundation.text",
"app.application.transfer.workflow -> app.runtime",
"app.application.transfer.workflow -> app.runtime.log",
"app.application.transfer.workflow -> app.schemas",
"app.application.transfer.workflow -> app.schemas.context",
"app.application.transfer.workflow -> app.schemas.file",
"app.application.transfer.workflow -> app.schemas.history",
"app.application.transfer.workflow -> app.schemas.media",
"app.application.transfer.workflow -> app.schemas.music",
"app.application.transfer.workflow -> app.schemas.system",
"app.application.transfer.workflow -> app.schemas.tmdb",
"app.application.transfer.workflow -> app.schemas.transfer",
"app.application.transfer.workflow -> app.schemas.types",
"app.chain -> app.application",
"app.chain -> app.application.chain",
"app.chain -> app.application.chain.context",
@@ -4568,7 +4575,8 @@
"app.chain._transfer -> app.application.formatting",
"app.chain._transfer -> app.application.history",
"app.chain._transfer -> app.application.transfer",
"app.chain._transfer -> app.application.transfer_execution",
"app.chain._transfer -> app.application.transfer.execution",
"app.chain._transfer -> app.application.transfer.workflow",
"app.chain._transfer -> app.chain",
"app.chain._transfer -> app.chain._contracts",
"app.chain._transfer -> app.chain.media",
@@ -4994,14 +5002,15 @@
"app.chain.transfer -> app.application",
"app.chain.transfer -> app.application.chain",
"app.chain.transfer -> app.application.chain.data",
"app.chain.transfer -> app.application.chain.durable_events",
"app.chain.transfer -> app.application.chain.events",
"app.chain.transfer -> app.application.configuration",
"app.chain.transfer -> app.application.directory",
"app.chain.transfer -> app.application.formatting",
"app.chain.transfer -> app.application.history",
"app.chain.transfer -> app.application.outbox",
"app.chain.transfer -> app.application.transfer",
"app.chain.transfer -> app.application.transfer_execution",
"app.chain.transfer -> app.application.transfer.execution",
"app.chain.transfer -> app.application.transfer.workflow",
"app.chain.transfer -> app.chain",
"app.chain.transfer -> app.chain._transfer",
"app.chain.transfer -> app.chain.media",
@@ -5105,10 +5114,11 @@
"app.command -> app.schemas.types",
"app.db.adapters.chain -> app.application",
"app.db.adapters.chain -> app.application.chain",
"app.db.adapters.chain -> app.application.chain.durable_events",
"app.db.adapters.chain -> app.application.chain.events",
"app.db.adapters.chain -> app.application.history",
"app.db.adapters.chain -> app.application.outbox",
"app.db.adapters.chain -> app.application.transfer_execution",
"app.db.adapters.chain -> app.application.transfer",
"app.db.adapters.chain -> app.application.transfer.execution",
"app.db.adapters.chain -> app.db",
"app.db.adapters.chain -> app.db.adapters",
"app.db.adapters.chain -> app.db.adapters.outbox",
@@ -5165,24 +5175,26 @@
"app.db.adapters.subscription -> app.db.uow",
"app.db.adapters.transaction -> app.db",
"app.db.adapters.transaction -> app.db.uow",
"app.db.adapters.transfer -> app.application",
"app.db.adapters.transfer -> app.application.transfer",
"app.db.adapters.transfer -> app.db",
"app.db.adapters.transfer -> app.db.models",
"app.db.adapters.transfer -> app.db.models.transferpending",
"app.db.adapters.transfer -> app.db.oper",
"app.db.adapters.transfer -> app.db.oper.transferpending",
"app.db.adapters.transfer -> app.db.uow",
"app.db.adapters.transfer_execution -> app.application",
"app.db.adapters.transfer_execution -> app.application.transfer_execution",
"app.db.adapters.transfer_execution -> app.db",
"app.db.adapters.transfer_execution -> app.db.models",
"app.db.adapters.transfer_execution -> app.db.models.transferexecutionstep",
"app.db.adapters.transfer_execution -> app.db.models.transferpending",
"app.db.adapters.transfer_execution -> app.db.oper",
"app.db.adapters.transfer_execution -> app.db.oper.transferexecutionstep",
"app.db.adapters.transfer_execution -> app.db.oper.transferpending",
"app.db.adapters.transfer_execution -> app.db.uow",
"app.db.adapters.transfer.admission -> app.application",
"app.db.adapters.transfer.admission -> app.application.transfer",
"app.db.adapters.transfer.admission -> app.application.transfer.workflow",
"app.db.adapters.transfer.admission -> app.db",
"app.db.adapters.transfer.admission -> app.db.models",
"app.db.adapters.transfer.admission -> app.db.models.transferpending",
"app.db.adapters.transfer.admission -> app.db.oper",
"app.db.adapters.transfer.admission -> app.db.oper.transferpending",
"app.db.adapters.transfer.admission -> app.db.uow",
"app.db.adapters.transfer.execution -> app.application",
"app.db.adapters.transfer.execution -> app.application.transfer",
"app.db.adapters.transfer.execution -> app.application.transfer.execution",
"app.db.adapters.transfer.execution -> app.db",
"app.db.adapters.transfer.execution -> app.db.models",
"app.db.adapters.transfer.execution -> app.db.models.transferexecutionstep",
"app.db.adapters.transfer.execution -> app.db.models.transferpending",
"app.db.adapters.transfer.execution -> app.db.oper",
"app.db.adapters.transfer.execution -> app.db.oper.transferexecutionstep",
"app.db.adapters.transfer.execution -> app.db.oper.transferpending",
"app.db.adapters.transfer.execution -> app.db.uow",
"app.db.adapters.workflow -> app.application",
"app.db.adapters.workflow -> app.application.workflow",
"app.db.adapters.workflow -> app.db",
@@ -5852,7 +5864,8 @@
"app.modules.filemanager.module -> app.application.messaging",
"app.modules.filemanager.module -> app.application.messaging.message",
"app.modules.filemanager.module -> app.application.transfer",
"app.modules.filemanager.module -> app.application.transfer_execution",
"app.modules.filemanager.module -> app.application.transfer.execution",
"app.modules.filemanager.module -> app.application.transfer.workflow",
"app.modules.filemanager.module -> app.domain",
"app.modules.filemanager.module -> app.domain.context",
"app.modules.filemanager.module -> app.domain.meta",
@@ -6005,7 +6018,8 @@
"app.modules.filemanager.transhandler -> app.application.messaging",
"app.modules.filemanager.transhandler -> app.application.messaging.message",
"app.modules.filemanager.transhandler -> app.application.transfer",
"app.modules.filemanager.transhandler -> app.application.transfer_execution",
"app.modules.filemanager.transhandler -> app.application.transfer.execution",
"app.modules.filemanager.transhandler -> app.application.transfer.workflow",
"app.modules.filemanager.transhandler -> app.domain",
"app.modules.filemanager.transhandler -> app.domain.context",
"app.modules.filemanager.transhandler -> app.domain.meta",
@@ -7351,12 +7365,6 @@
"app.runtime.extensions.host_module_adapter -> app.runtime.settings",
"app.runtime.extensions.host_module_adapter -> app.schemas",
"app.runtime.extensions.host_module_adapter -> app.schemas.types",
"app.runtime.extensions.managed_resource_adapter -> app.runtime",
"app.runtime.extensions.managed_resource_adapter -> app.runtime.capabilities",
"app.runtime.extensions.managed_resource_adapter -> app.runtime.capabilities.errors",
"app.runtime.extensions.managed_resource_adapter -> app.runtime.capabilities.model",
"app.runtime.extensions.managed_resource_adapter -> app.runtime.capabilities.registry",
"app.runtime.extensions.managed_resource_adapter -> app.runtime.managed_resources",
"app.runtime.extensions.module.dispatcher -> app.foundation",
"app.runtime.extensions.module.dispatcher -> app.foundation.reflection",
"app.runtime.extensions.module.dispatcher -> app.runtime",
@@ -7479,6 +7487,12 @@
"app.runtime.extensions.plugin_manager -> app.schemas.exception",
"app.runtime.extensions.plugin_manager -> app.schemas.plugin",
"app.runtime.extensions.plugin_manager -> app.schemas.types",
"app.runtime.extensions.resource -> app.runtime",
"app.runtime.extensions.resource -> app.runtime.capabilities",
"app.runtime.extensions.resource -> app.runtime.capabilities.errors",
"app.runtime.extensions.resource -> app.runtime.capabilities.model",
"app.runtime.extensions.resource -> app.runtime.capabilities.registry",
"app.runtime.extensions.resource -> app.runtime.resources",
"app.runtime.extensions.service_config -> app.runtime",
"app.runtime.extensions.service_config -> app.runtime.log",
"app.runtime.extensions.service_config -> app.schemas",
@@ -7670,6 +7684,7 @@
"app.sdk._legacy.subscribe -> app.domain.context",
"app.sdk._legacy.transfer -> app.application",
"app.sdk._legacy.transfer -> app.application.transfer",
"app.sdk._legacy.transfer -> app.application.transfer.workflow",
"app.sdk._legacy.transferpending -> app.db",
"app.sdk._legacy.transferpending -> app.db.base",
"app.sdk._legacy.transferpending -> app.db.models",
@@ -7890,12 +7905,6 @@
"app.startup.initializers.domain -> app.domain.metainfo",
"app.startup.initializers.domain -> app.runtime",
"app.startup.initializers.domain -> app.runtime.settings",
"app.startup.initializers.managed_resources -> app.runtime",
"app.startup.initializers.managed_resources -> app.runtime.capabilities",
"app.startup.initializers.managed_resources -> app.runtime.capabilities.runtime",
"app.startup.initializers.managed_resources -> app.runtime.extensions",
"app.startup.initializers.managed_resources -> app.runtime.extensions.managed_resource_adapter",
"app.startup.initializers.managed_resources -> app.runtime.managed_resources",
"app.startup.initializers.modules -> app.adapters",
"app.startup.initializers.modules -> app.adapters.cache",
"app.startup.initializers.modules -> app.adapters.cache.redis",
@@ -7918,7 +7927,7 @@
"app.startup.initializers.modules -> app.application.chain",
"app.startup.initializers.modules -> app.application.chain.context",
"app.startup.initializers.modules -> app.application.chain.data",
"app.startup.initializers.modules -> app.application.chain.durable_events",
"app.startup.initializers.modules -> app.application.chain.events",
"app.startup.initializers.modules -> app.application.configuration",
"app.startup.initializers.modules -> app.application.database",
"app.startup.initializers.modules -> app.application.history",
@@ -7970,7 +7979,8 @@
"app.startup.initializers.modules -> app.db.adapters.subscription",
"app.startup.initializers.modules -> app.db.adapters.transaction",
"app.startup.initializers.modules -> app.db.adapters.transfer",
"app.startup.initializers.modules -> app.db.adapters.transfer_execution",
"app.startup.initializers.modules -> app.db.adapters.transfer.admission",
"app.startup.initializers.modules -> app.db.adapters.transfer.execution",
"app.startup.initializers.modules -> app.db.adapters.workflow",
"app.startup.initializers.modules -> app.db.oper",
"app.startup.initializers.modules -> app.db.oper.agentchat",
@@ -8021,7 +8031,7 @@
"app.startup.initializers.modules -> app.startup.composition.subscription",
"app.startup.initializers.modules -> app.startup.initializers",
"app.startup.initializers.modules -> app.startup.initializers.agent",
"app.startup.initializers.modules -> app.startup.initializers.managed_resources",
"app.startup.initializers.modules -> app.startup.initializers.resources",
"app.startup.initializers.monitor -> app.monitor",
"app.startup.initializers.monitor -> app.runtime",
"app.startup.initializers.monitor -> app.runtime.execution",
@@ -8075,12 +8085,18 @@
"app.startup.initializers.plugins -> app.runtime.extensions.plugin.system",
"app.startup.initializers.plugins -> app.runtime.extensions.plugin_manager",
"app.startup.initializers.plugins -> app.runtime.log",
"app.startup.initializers.plugins -> app.runtime.managed_resources",
"app.startup.initializers.plugins -> app.runtime.resources",
"app.startup.initializers.plugins -> app.runtime.settings",
"app.startup.initializers.plugins -> app.schemas",
"app.startup.initializers.plugins -> app.schemas.exception",
"app.startup.initializers.plugins -> app.schemas.plugin",
"app.startup.initializers.plugins -> app.schemas.types",
"app.startup.initializers.resources -> app.runtime",
"app.startup.initializers.resources -> app.runtime.capabilities",
"app.startup.initializers.resources -> app.runtime.capabilities.runtime",
"app.startup.initializers.resources -> app.runtime.extensions",
"app.startup.initializers.resources -> app.runtime.extensions.resource",
"app.startup.initializers.resources -> app.runtime.resources",
"app.startup.initializers.routers -> app.api",
"app.startup.initializers.routers -> app.api.router_specs",
"app.startup.initializers.routers -> app.api.servarr",
@@ -8327,7 +8343,7 @@
"app.workflow.actions.transfer_file -> app.workflow",
"app.workflow.actions.transfer_file -> app.workflow.actions"
],
"module_count": 842,
"module_count": 844,
"modules": [
"app",
"app.adapters",
@@ -8583,7 +8599,7 @@
"app.application.chain",
"app.application.chain.context",
"app.application.chain.data",
"app.application.chain.durable_events",
"app.application.chain.events",
"app.application.commands",
"app.application.configuration",
"app.application.dashboard",
@@ -8674,7 +8690,8 @@
"app.application.torrent",
"app.application.torrent_cache",
"app.application.transfer",
"app.application.transfer_execution",
"app.application.transfer.execution",
"app.application.transfer.workflow",
"app.application.workflow",
"app.chain",
"app.chain._contracts",
@@ -8726,7 +8743,8 @@
"app.db.adapters.subscription",
"app.db.adapters.transaction",
"app.db.adapters.transfer",
"app.db.adapters.transfer_execution",
"app.db.adapters.transfer.admission",
"app.db.adapters.transfer.execution",
"app.db.adapters.workflow",
"app.db.base",
"app.db.decorators",
@@ -9025,7 +9043,6 @@
"app.runtime.execution",
"app.runtime.extensions",
"app.runtime.extensions.host_module_adapter",
"app.runtime.extensions.managed_resource_adapter",
"app.runtime.extensions.module",
"app.runtime.extensions.module.contracts",
"app.runtime.extensions.module.dispatcher",
@@ -9050,16 +9067,17 @@
"app.runtime.extensions.plugin.system",
"app.runtime.extensions.plugin.tools",
"app.runtime.extensions.plugin_manager",
"app.runtime.extensions.resource",
"app.runtime.extensions.service_config",
"app.runtime.gc",
"app.runtime.health",
"app.runtime.localization",
"app.runtime.log",
"app.runtime.managed_resources",
"app.runtime.observability",
"app.runtime.progress",
"app.runtime.rate",
"app.runtime.reload",
"app.runtime.resources",
"app.runtime.scheduling",
"app.runtime.settings",
"app.runtime.state",
@@ -9140,10 +9158,10 @@
"app.startup.initializers.command",
"app.startup.initializers.database",
"app.startup.initializers.domain",
"app.startup.initializers.managed_resources",
"app.startup.initializers.modules",
"app.startup.initializers.monitor",
"app.startup.initializers.plugins",
"app.startup.initializers.resources",
"app.startup.initializers.routers",
"app.startup.initializers.scheduler",
"app.startup.initializers.transfer",
+1 -1
View File
@@ -142,7 +142,7 @@
"tracking": "S2-L6"
},
{
"source": "app.application.transfer",
"source": "app.application.transfer.workflow",
"target": "app.adapters.system.host",
"tracking": "S2-L6"
},
-20
View File
@@ -1112,10 +1112,6 @@
"app/application/agenttask.py": {
"type-arg": 1
},
"app/application/chain/durable_events.py": {
"arg-type": 1,
"no-untyped-call": 1
},
"app/application/commands.py": {
"no-any-return": 1
},
@@ -1356,18 +1352,6 @@
"app/application/torrent_cache.py": {
"type-arg": 1
},
"app/application/transfer.py": {
"arg-type": 16,
"assignment": 3,
"attr-defined": 4,
"misc": 6,
"no-any-return": 1,
"no-untyped-call": 2,
"no-untyped-def": 10,
"return-value": 1,
"type-arg": 14,
"union-attr": 47
},
"app/chain/__init__.py": {
"assignment": 13,
"attr-defined": 1,
@@ -3210,10 +3194,6 @@
"app/runtime/localization.py": {
"no-any-return": 1
},
"app/runtime/managed_resources.py": {
"arg-type": 2,
"union-attr": 3
},
"app/runtime/progress.py": {
"no-any-return": 4,
"type-arg": 6
-53
View File
@@ -15,9 +15,6 @@
"F841": 2,
"I001": 1
},
"app/adapters/system/display/__init__.py": {
"I001": 1
},
"app/adapters/system/host.py": {
"I001": 2
},
@@ -300,9 +297,6 @@
"app/application/agenttask.py": {
"I001": 1
},
"app/application/chain/data.py": {
"I001": 1
},
"app/application/directory.py": {
"I001": 1
},
@@ -392,10 +386,6 @@
"app/chain/_music.py": {
"E402": 5
},
"app/chain/_transfer.py": {
"E402": 15,
"F401": 1
},
"app/chain/media.py": {
"E731": 2
},
@@ -962,9 +952,6 @@
"app/runtime/extensions/host_module_adapter.py": {
"I001": 1
},
"app/runtime/extensions/managed_resource_adapter.py": {
"I001": 1
},
"app/runtime/extensions/module_manager.py": {
"I001": 1
},
@@ -990,9 +977,6 @@
"E731": 1,
"I001": 1
},
"app/runtime/managed_resources.py": {
"I001": 1
},
"app/runtime/observability/__init__.py": {
"I001": 1
},
@@ -1038,18 +1022,12 @@
"app/schemas/system.py": {
"I001": 1
},
"app/schemas/transfer.py": {
"I001": 1
},
"app/schemas/types.py": {
"I001": 1
},
"app/schemas/user.py": {
"I001": 1
},
"app/sdk/_legacy/transfer.py": {
"I001": 1
},
"app/sdk/_legacy/user.py": {
"I001": 1
},
@@ -1125,9 +1103,6 @@
"scripts/perf/task_registry_ab.py": {
"E402": 1
},
"scripts/perf/test_scenarios.py": {
"I001": 1
},
"scripts/schema/exports.py": {
"I001": 1
},
@@ -1137,10 +1112,6 @@
"scripts/startup/performance.py": {
"I001": 1
},
"tests/conftest.py": {
"F401": 1,
"I001": 7
},
"tests/test_acoustid_module.py": {
"I001": 1
},
@@ -1440,12 +1411,6 @@
"tests/test_main_direct_execution.py": {
"I001": 1
},
"tests/test_managed_resources.py": {
"I001": 1
},
"tests/test_manual_transfer_history.py": {
"I001": 1
},
"tests/test_mcp_plugin_tools.py": {
"I001": 1
},
@@ -1797,9 +1762,6 @@
"E402": 6,
"I001": 2
},
"tests/test_transfer_failure_notification_aggregation.py": {
"I001": 1
},
"tests/test_transfer_history_gate.py": {
"I001": 1
},
@@ -1809,27 +1771,12 @@
"tests/test_transfer_history_write_path.py": {
"I001": 1
},
"tests/test_transfer_mark_torrent_completed.py": {
"I001": 1
},
"tests/test_transfer_mounted_disk_cleanup.py": {
"I001": 1
},
"tests/test_transfer_movie_collection.py": {
"I001": 1
},
"tests/test_transfer_queue_count.py": {
"I001": 1
},
"tests/test_transfer_rename_build_event.py": {
"I001": 1
},
"tests/test_transfer_stale_tasks.py": {
"I001": 1
},
"tests/test_transfer_tmdb_category.py": {
"I001": 1
},
"tests/test_transferhistory_media_source_migration.py": {
"I001": 1
},
+38 -5
View File
@@ -1,6 +1,13 @@
{
"compat_manifest": {
"module_aliases": {
"app.application.chain.durable_events": {
"introduced": "v3.0.0",
"is_package": false,
"owner": "application",
"replacement": "app.application.chain.events",
"target": "app.application.chain.events"
},
"app.application.filter": {
"introduced": "v3.0.0",
"is_package": false,
@@ -15,6 +22,13 @@
"replacement": "app.application.rules",
"target": "app.application.rules"
},
"app.application.transfer_execution": {
"introduced": "v3.0.0",
"is_package": false,
"owner": "application",
"replacement": "app.application.transfer.execution",
"target": "app.application.transfer.execution"
},
"app.chain.media_interaction": {
"introduced": "v3.0.0",
"is_package": false,
@@ -250,7 +264,7 @@
"introduced": "v3.0.0",
"is_package": false,
"owner": "sdk",
"replacement": "app.application.transfer",
"replacement": "app.application.transfer.workflow",
"target": "app.sdk._legacy.transferpending"
},
"app.db.user_oper": {
@@ -596,6 +610,13 @@
"replacement": "app.sdk.services",
"target": "app.sdk.services"
},
"app.runtime.managed_resources": {
"introduced": "v3.0.0",
"is_package": false,
"owner": "runtime",
"replacement": "app.runtime.resources",
"target": "app.runtime.resources"
},
"app.utils.coalesce": {
"introduced": "v3.0.0",
"is_package": false,
@@ -869,6 +890,18 @@
"target_name": "ReplyMode"
}
},
"app.application.transfer": {
"TransferQueue": {
"replacement": "app.application.transfer.workflow.TransferQueue",
"target_module": "app.sdk._legacy.transfer",
"target_name": "TransferQueue"
},
"TransferTask": {
"replacement": "app.application.transfer.workflow.TransferTask",
"target_module": "app.sdk._legacy.transfer",
"target_name": "TransferTask"
}
},
"app.chain.media": {
"ScrapingChain": {
"replacement": "app.chain.scraping.ScrapingChain",
@@ -987,12 +1020,12 @@
"target_name": "MessageType"
},
"TransferQueue": {
"replacement": "app.application.transfer.TransferQueue",
"replacement": "app.application.transfer.workflow.TransferQueue",
"target_module": "app.sdk._legacy.transfer",
"target_name": "TransferQueue"
},
"TransferTask": {
"replacement": "app.application.transfer.TransferTask",
"replacement": "app.application.transfer.workflow.TransferTask",
"target_module": "app.sdk._legacy.transfer",
"target_name": "TransferTask"
}
@@ -1083,12 +1116,12 @@
"target_name": "TransferDirectoryConf"
},
"TransferQueue": {
"replacement": "app.application.transfer.TransferQueue",
"replacement": "app.application.transfer.workflow.TransferQueue",
"target_module": "app.sdk._legacy.transfer",
"target_name": "TransferQueue"
},
"TransferTask": {
"replacement": "app.application.transfer.TransferTask",
"replacement": "app.application.transfer.workflow.TransferTask",
"target_module": "app.sdk._legacy.transfer",
"target_name": "TransferTask"
}
+113 -113
View File
@@ -1,41 +1,41 @@
{
"schema_version": 2,
"generated_at": "2026-08-27T12:39:02.223653+00:00",
"generated_at": "2026-08-27T13:33:52.081319+00:00",
"platform": "macOS-26.5.2-arm64-arm-64bit-Mach-O",
"python": "3.14.3",
"repeat": 3,
"targets": {
"app.startup.lifecycle": {
"loaded_app_module_count": 386,
"max_ms": 943.849,
"median_ms": 933.725,
"min_ms": 933.213,
"loaded_app_module_count": 388,
"max_ms": 1035.341,
"median_ms": 993.245,
"min_ms": 991.998,
"samples_ms": [
943.849,
933.213,
933.725
1035.341,
991.998,
993.245
]
},
"app.factory": {
"loaded_app_module_count": 398,
"max_ms": 959.917,
"median_ms": 955.782,
"min_ms": 950.477,
"loaded_app_module_count": 400,
"max_ms": 1006.172,
"median_ms": 1005.88,
"min_ms": 1003.841,
"samples_ms": [
950.477,
955.782,
959.917
1005.88,
1006.172,
1003.841
]
},
"app.main": {
"loaded_app_module_count": 400,
"max_ms": 1027.215,
"median_ms": 1012.512,
"min_ms": 996.609,
"loaded_app_module_count": 402,
"max_ms": 1085.652,
"median_ms": 1055.994,
"min_ms": 1043.212,
"samples_ms": [
1027.215,
1012.512,
996.609
1055.994,
1043.212,
1085.652
]
}
},
@@ -47,24 +47,24 @@
{
"mode": "normal",
"enabled_component_count": 25,
"startup_ms": 0.668,
"full_lifespan_ms": 1.475,
"startup_ms": 0.702,
"full_lifespan_ms": 1.54,
"stage_ms": {
"后台任务登记器": 0.081,
"数据库准备": 0.039,
"HTTP 基础能力": 0.032,
"领域依赖装配": 0.029,
"数据库引擎预热": 0.026,
"数据库连接预算": 0.025,
"路由": 0.023,
"模块服务": 0.026,
"插件备份恢复": 0.023,
"后台任务登记器": 0.09,
"数据库准备": 0.048,
"HTTP 基础能力": 0.03,
"领域依赖装配": 0.033,
"数据库引擎预热": 0.031,
"数据库连接预算": 0.031,
"路由": 0.028,
"模块服务": 0.022,
"插件备份恢复": 0.021,
"插件": 0.025,
"定时器": 0.022,
"定时器": 0.023,
"监控器": 0.021,
"待处理整理回放": 0.024,
"命令服务": 0.022,
"工作流": 0.02,
"待处理整理回放": 0.025,
"命令服务": 0.021,
"工作流": 0.023,
"插件同步与启动收尾": 0.024
},
"threads_before": 2,
@@ -78,25 +78,25 @@
{
"mode": "normal",
"enabled_component_count": 25,
"startup_ms": 0.644,
"full_lifespan_ms": 1.465,
"startup_ms": 0.667,
"full_lifespan_ms": 1.559,
"stage_ms": {
"后台任务登记器": 0.073,
"数据库准备": 0.035,
"HTTP 基础能力": 0.032,
"领域依赖装配": 0.029,
"数据库引擎预热": 0.025,
"数据库连接预算": 0.025,
"路由": 0.025,
"模块服务": 0.024,
"插件备份恢复": 0.023,
"插件": 0.021,
"定时器": 0.023,
"监控器": 0.025,
"待处理整理回放": 0.024,
"命令服务": 0.023,
"后台任务登记器": 0.078,
"数据库准备": 0.037,
"HTTP 基础能力": 0.027,
"领域依赖装配": 0.03,
"数据库引擎预热": 0.027,
"数据库连接预算": 0.024,
"路由": 0.026,
"模块服务": 0.026,
"插件备份恢复": 0.026,
"插件": 0.025,
"定时器": 0.024,
"监控器": 0.024,
"待处理整理回放": 0.027,
"命令服务": 0.026,
"工作流": 0.023,
"插件同步与启动收尾": 0.02
"插件同步与启动收尾": 0.021
},
"threads_before": 2,
"threads_started": 2,
@@ -109,25 +109,25 @@
{
"mode": "normal",
"enabled_component_count": 25,
"startup_ms": 0.661,
"full_lifespan_ms": 1.501,
"startup_ms": 0.735,
"full_lifespan_ms": 1.57,
"stage_ms": {
"后台任务登记器": 0.073,
"数据库准备": 0.049,
"HTTP 基础能力": 0.032,
"领域依赖装配": 0.029,
"数据库引擎预热": 0.025,
"后台任务登记器": 0.103,
"数据库准备": 0.041,
"HTTP 基础能力": 0.031,
"领域依赖装配": 0.032,
"数据库引擎预热": 0.028,
"数据库连接预算": 0.026,
"路由": 0.025,
"模块服务": 0.025,
"插件备份恢复": 0.023,
"路由": 0.027,
"模块服务": 0.026,
"插件备份恢复": 0.026,
"插件": 0.025,
"定时器": 0.026,
"定时器": 0.024,
"监控器": 0.025,
"待处理整理回放": 0.021,
"命令服务": 0.022,
"待处理整理回放": 0.024,
"命令服务": 0.024,
"工作流": 0.024,
"插件同步与启动收尾": 0.021
"插件同步与启动收尾": 0.024
},
"threads_before": 2,
"threads_started": 2,
@@ -138,8 +138,8 @@
"database_connections_started": 0
}
],
"median_startup_ms": 0.661,
"median_full_lifespan_ms": 1.475,
"median_startup_ms": 0.702,
"median_full_lifespan_ms": 1.559,
"enabled_component_count": 25,
"enabled_components": [
"后台任务登记器",
@@ -174,41 +174,17 @@
{
"mode": "safe",
"enabled_component_count": 13,
"startup_ms": 0.48,
"full_lifespan_ms": 0.905,
"startup_ms": 0.527,
"full_lifespan_ms": 0.956,
"stage_ms": {
"后台任务登记器": 0.073,
"数据库准备": 0.043,
"后台任务登记器": 0.091,
"数据库准备": 0.042,
"HTTP 基础能力": 0.03,
"领域依赖装配": 0.027,
"数据库引擎预热": 0.026,
"数据库连接预算": 0.025,
"路由": 0.025,
"模块服务": 0.025,
"插件同步与启动收尾": 0.022
},
"threads_before": 2,
"threads_started": 2,
"threads_after": 2,
"tasks_before": 1,
"tasks_started": 1,
"tasks_after": 1,
"database_connections_started": 0
},
{
"mode": "safe",
"enabled_component_count": 13,
"startup_ms": 0.51,
"full_lifespan_ms": 0.935,
"stage_ms": {
"后台任务登记器": 0.082,
"数据库准备": 0.039,
"HTTP 基础能力": 0.036,
"领域依赖装配": 0.032,
"数据库引擎预热": 0.024,
"数据库连接预算": 0.026,
"领域依赖装配": 0.03,
"数据库引擎预热": 0.028,
"数据库连接预算": 0.027,
"路由": 0.026,
"模块服务": 0.025,
"模块服务": 0.026,
"插件同步与启动收尾": 0.025
},
"threads_before": 2,
@@ -222,17 +198,41 @@
{
"mode": "safe",
"enabled_component_count": 13,
"startup_ms": 0.564,
"full_lifespan_ms": 0.97,
"startup_ms": 0.523,
"full_lifespan_ms": 0.954,
"stage_ms": {
"后台任务登记器": 0.092,
"数据库准备": 0.039,
"后台任务登记器": 0.082,
"数据库准备": 0.045,
"HTTP 基础能力": 0.036,
"领域依赖装配": 0.031,
"数据库引擎预热": 0.03,
"数据库连接预算": 0.026,
"路由": 0.027,
"模块服务": 0.027,
"领域依赖装配": 0.033,
"数据库引擎预热": 0.026,
"数据库连接预算": 0.024,
"路由": 0.023,
"模块服务": 0.024,
"插件同步与启动收尾": 0.023
},
"threads_before": 2,
"threads_started": 2,
"threads_after": 2,
"tasks_before": 1,
"tasks_started": 1,
"tasks_after": 1,
"database_connections_started": 0
},
{
"mode": "safe",
"enabled_component_count": 13,
"startup_ms": 0.515,
"full_lifespan_ms": 0.934,
"stage_ms": {
"后台任务登记器": 0.084,
"数据库准备": 0.044,
"HTTP 基础能力": 0.029,
"领域依赖装配": 0.027,
"数据库引擎预热": 0.031,
"数据库连接预算": 0.028,
"路由": 0.023,
"模块服务": 0.022,
"插件同步与启动收尾": 0.025
},
"threads_before": 2,
@@ -244,8 +244,8 @@
"database_connections_started": 0
}
],
"median_startup_ms": 0.51,
"median_full_lifespan_ms": 0.935,
"median_startup_ms": 0.523,
"median_full_lifespan_ms": 0.954,
"enabled_component_count": 13,
"enabled_components": [
"后台任务登记器",
+1 -1
View File
@@ -37,7 +37,7 @@ FROZEN_DIRECT_ADAPTER_IMPORTS = {
("app.application.security.cookie", "app.adapters.network.http"): "S2-L6",
("app.application.security.passkey", "app.adapters.cache.redis"): "S2-L4",
("app.application.torrent", "app.adapters.network.http"): "S2-L6",
("app.application.transfer", "app.adapters.system.host"): "S2-L6",
("app.application.transfer.workflow", "app.adapters.system.host"): "S2-L6",
("app.chain._recognition", "app.adapters.external.server"): "S2-L7",
("app.chain._transfer", "app.adapters.system.host"): "S2-L7",
("app.chain.download", "app.adapters.network.http"): "S2-L7",
+11 -3
View File
@@ -82,6 +82,13 @@ RETIRED_CANONICAL_FILES = (
"app/adapters/network/sites.pyi",
"app/application/plugins.py",
"app/application/subscribe.py",
"app/application/chain/durable_events.py",
"app/application/transfer.py",
"app/application/transfer_execution.py",
"app/db/adapters/transfer.py",
"app/db/adapters/transfer_execution.py",
"app/runtime/extensions/managed_resource_adapter.py",
"app/runtime/managed_resources.py",
"app/startup/agent_initializer.py",
"app/startup/cache_initializer.py",
"app/startup/chain_events.py",
@@ -93,6 +100,7 @@ RETIRED_CANONICAL_FILES = (
"app/startup/domain_initializer.py",
"app/startup/download_failure.py",
"app/startup/managed_resources_initializer.py",
"app/startup/initializers/managed_resources.py",
"app/startup/modules_initializer.py",
"app/startup/monitor_initializer.py",
"app/startup/outbox.py",
@@ -481,9 +489,9 @@ def test_transfer_chains_use_explicit_data_port_getters():
def test_transfer_pending_oper_import_is_confined_to_database_boundary():
"""宿主仅允许事务适配器和兼容导出直接导入整理待处理 Oper。"""
allowed_paths = {
"app/db/adapters/transfer.py",
"app/db/adapters/transfer/admission.py",
"app/db/adapters/chain.py",
"app/db/adapters/transfer_execution.py",
"app/db/adapters/transfer/execution.py",
"app/db/oper/__init__.py",
}
violations: list[str] = []
@@ -520,7 +528,7 @@ def test_startup_injects_transactional_transfer_admission_repository():
tree = ast.parse(path.read_text(encoding="utf-8-sig"), filename=str(path))
imports_repository = any(
isinstance(node, ast.ImportFrom)
and node.module == "app.db.adapters.transfer"
and node.module == "app.db.adapters.transfer.admission"
and any(
alias.name == "TransactionalTransferAdmissionRepository"
for alias in node.names
+2 -2
View File
@@ -11,7 +11,7 @@ from sqlalchemy import create_engine, delete, select
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import sessionmaker
from app.application.chain.durable_events import (
from app.application.chain.events import (
TransferResultSettlement,
download_added_event_key,
restore_download_added,
@@ -21,7 +21,7 @@ from app.application.chain.durable_events import (
transfer_result_event_key,
)
from app.application.history import TransferHistoryMutationCommand
from app.application.transfer_execution import (
from app.application.transfer.execution import (
TransferExecutionLeaseLostError,
TransferSettlementResult,
)
+1 -1
View File
@@ -12,7 +12,7 @@ from sqlalchemy import create_engine, select
from sqlalchemy.orm import sessionmaker
from app.db import base as db_base
from app.db.adapters.transfer import TransactionalTransferAdmissionRepository
from app.db.adapters.transfer.admission import TransactionalTransferAdmissionRepository
from app.db.models.transferhistory import TransferHistory
from app.db.models.transferpending import TransferPending
from app.db.oper.transferpending import TransferPendingOper
+1 -1
View File
@@ -3,7 +3,7 @@ from pathlib import Path
import pytest
from app.application.transfer import TransferPlanCheckpoint, TransferPlanningInput
from app.application.transfer.workflow import TransferPlanCheckpoint, TransferPlanningInput
from app.domain.context import MediaInfo
from app.domain.meta.metabase import MetaBase
from app.modules.filemanager import transhandler as transhandler_module
+1 -1
View File
@@ -8,7 +8,7 @@ from types import SimpleNamespace
from app.agent.tools.impl.delete_transfer_history import DeleteTransferHistoryTool
from app.api.endpoints import history as history_endpoint
from app.application.configuration import ApiRuntimeConfig
from app.application.transfer_execution import (
from app.application.transfer.execution import (
TransferExecutionState,
TransferRetryRequestResult,
)
+1 -1
View File
@@ -2,7 +2,7 @@ import importlib
import pytest
from app.application.transfer import TransferTask as CanonicalTransferTask
from app.application.transfer.workflow import TransferTask as CanonicalTransferTask
from app.db.models.transferhistory import TransferHistory
from app.schemas.file import FileItem
+31
View File
@@ -189,6 +189,37 @@ for legacy_name, alias in MODULE_ALIASES.items():
)
def test_renamed_modules_use_exact_compat_routes() -> None:
"""旧模块路径只经 manifest 复用新的 canonical 模块。"""
expected = {
"app.application.chain.durable_events": "app.application.chain.events",
"app.application.transfer_execution": "app.application.transfer.execution",
"app.runtime.managed_resources": "app.runtime.resources",
}
configure_legacy_import_diagnostics(enabled=False, emitter=lambda _: None)
try:
for legacy_name, target_name in expected.items():
assert MODULE_ALIASES[legacy_name].target == target_name
assert importlib.import_module(legacy_name) is importlib.import_module(target_name)
finally:
reset_legacy_import_diagnostics()
def test_transfer_package_exposes_plugin_symbols_only_through_overlay() -> None:
"""整理包不重导出宿主实现,只按兼容清单惰性提供插件旧符号。"""
configure_legacy_import_diagnostics(enabled=False, emitter=lambda _: None)
try:
package = importlib.import_module("app.application.transfer")
legacy = importlib.import_module("app.sdk._legacy.transfer")
assert package.TransferTask is legacy.TransferTask
assert package.TransferQueue is legacy.TransferQueue
assert "TransferTask" not in package.__all__
assert "TransferQueue" not in package.__all__
finally:
reset_legacy_import_diagnostics()
def test_virtual_package_exports_resolve_exact_manifest_symbols():
"""合成旧包仅公开 manifest 声明的符号,并记录 DEBUG 兼容警告。"""
legacy_package = "app.core.meta"
+5 -6
View File
@@ -13,18 +13,18 @@ from unittest.mock import MagicMock
import pytest
from app.runtime import resources as managed_resource_facade
from app.runtime.capabilities.errors import (
CapabilityOperationError,
CapabilityRuntimeClosedError,
)
from app.runtime.capabilities.runtime import CapabilityRuntime
from app.runtime.extensions.managed_resource_adapter import (
from app.runtime.extensions.resource import (
AsyncManagedResourceAdapter,
SyncManagedResourceAdapter,
build_managed_resource_registry,
)
from app.runtime import managed_resources as managed_resource_facade
from app.runtime.managed_resources import (
from app.runtime.resources import (
MANAGED_RESOURCE_ASYNC_KIND,
MANAGED_RESOURCE_SYNC_KIND,
acquire_managed_resource,
@@ -35,7 +35,6 @@ from app.runtime.managed_resources import (
shutdown_managed_resource_runtime,
)
PROJECT_ROOT = Path(__file__).parents[1]
@@ -346,7 +345,7 @@ def test_startup_initializer_discovers_manifest_without_importing_resource() ->
script = """
import asyncio
import sys
from app.startup.initializers.managed_resources import (
from app.startup.initializers.resources import (
init_managed_resources,
stop_managed_resources,
)
@@ -372,7 +371,7 @@ assert "pyvirtualdisplay" not in sys.modules
def test_startup_shutdown_without_init_does_not_build_registry(monkeypatch) -> None:
"""未执行启动装配时,关闭入口不得通过发现声明反向初始化 Runtime。"""
from app.startup.initializers import managed_resources as managed_resources_initializer
from app.startup.initializers import resources as managed_resources_initializer
build_registry = MagicMock(side_effect=AssertionError("must not discover"))
monkeypatch.setattr(
+6 -10
View File
@@ -2,18 +2,20 @@ from types import SimpleNamespace
from app.api.endpoints.transfer import (
manual_transfer as manual_transfer_endpoint,
)
from app.api.endpoints.transfer import (
query_manual_transfer_history,
)
from app.chain.transfer import TransferChain
from app.runtime.config import settings
from app.db.oper.transferhistory import TransferHistoryOper
from app.application.history import (
clear_transfer_failures,
failed_retry_count,
max_failed_retries,
record_transfer_failure,
)
from app.schemas import ManualTransferItem
from app.chain.transfer import TransferChain
from app.db.oper.transferhistory import TransferHistoryOper
from app.runtime.config import settings
from app.schemas.transfer import ManualTransferItem
from tests.test_transfer_sync_extra_files import (
FakeMeta,
make_fileitem,
@@ -72,12 +74,6 @@ def _patch_transfer_planning(monkeypatch, chain, fileitem, history, planned, del
get_by_path=lambda path: None,
),
)
monkeypatch.setattr("app.chain._transfer.get_chain_download_history_port", lambda: SimpleNamespace(
get_by_hash=lambda download_hash: None,
get_file_by_fullpath=lambda fullpath: None,
get_files_by_savepath=lambda savepath: [],
get_by_path=lambda path: None,
))
monkeypatch.setattr(
"app.chain.transfer.get_configured_system_config",
lambda: SimpleNamespace(get=lambda key: None),
+1 -1
View File
@@ -5,7 +5,7 @@ from unittest.mock import Mock
from jinja2 import Template
from app.application.messaging.message import TemplateHelper
from app.application.transfer import TransferTask
from app.application.transfer.workflow import TransferTask
from app.chain.media import MediaChain
from app.chain.transfer import JobManager, TransferChain
from app.domain.context import MusicInfo
+1 -1
View File
@@ -2,7 +2,7 @@
from types import SimpleNamespace
from app.application.transfer_execution import (
from app.application.transfer.execution import (
TransferExecutionState,
TransferRetryRequestResult,
)
+2 -2
View File
@@ -11,7 +11,7 @@ from alembic.migration import MigrationContext
from alembic.operations import Operations
from sqlalchemy.orm import sessionmaker
from app.application.transfer_execution import (
from app.application.transfer.execution import (
TransferExecutionCommand,
TransferExecutionConflictError,
TransferExecutionState,
@@ -20,7 +20,7 @@ from app.application.transfer_execution import (
TransferStepIntent,
TransferStepResult,
)
from app.db.adapters.transfer_execution import (
from app.db.adapters.transfer.execution import (
TransactionalTransferExecutionRepository,
)
from app.db.models.transferpending import TransferPending
+2 -2
View File
@@ -6,7 +6,7 @@ import pytest
from sqlalchemy import create_engine, select
from sqlalchemy.orm import sessionmaker
from app.application.transfer_execution import (
from app.application.transfer.execution import (
TransferExecutionCheckpoint,
TransferExecutionCommand,
TransferExecutionConflictError,
@@ -20,7 +20,7 @@ from app.application.transfer_execution import (
build_transfer_checkpoint_fingerprint,
build_transfer_operation_id,
)
from app.db.adapters.transfer_execution import (
from app.db.adapters.transfer.execution import (
TransactionalTransferExecutionRepository,
)
from app.db.base import Base
+2 -2
View File
@@ -8,7 +8,7 @@ import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from app.application.transfer_execution import (
from app.application.transfer.execution import (
TransferExecutionCommand,
TransferExecutionState,
TransferOperationObservation,
@@ -17,7 +17,7 @@ from app.application.transfer_execution import (
TransferStepResult,
)
from app.chain import transfer as transfer_chain_module
from app.db.adapters.transfer_execution import (
from app.db.adapters.transfer.execution import (
TransactionalTransferExecutionRepository,
)
from app.db.base import Base
@@ -5,7 +5,7 @@ from unittest.mock import Mock, patch
import pytest
from app.application.transfer import FailedRetryScheduler
from app.application.transfer.workflow import FailedRetryScheduler
def test_retry_scheduler_close_cancels_buffered_timer_and_rejects_new_work():
@@ -76,7 +76,7 @@ def test_retry_scheduler_observes_unexpected_background_task_error():
raise RuntimeError("flush failed")
scheduler._flush_retry_transfer = failing_flush
with patch("app.application.transfer.logger.error", Mock()) as log_error:
with patch("app.application.transfer.workflow.logger.error", Mock()) as log_error:
await scheduler.schedule_retry(11, group_key="media:test")
for _ in range(5):
await asyncio.sleep(0)
@@ -1,16 +1,16 @@
from unittest.mock import Mock, patch
from types import SimpleNamespace
from unittest.mock import Mock, patch
import pytest
from app.chain import transfer as transfer_module
from app.chain.transfer import TransferChain
from app.application.transfer import (
from app.application.transfer.workflow import (
TransferFailureNotification,
TransferFailureNotificationAggregator,
TransferTask,
build_transfer_failure_group_key,
)
from app.chain import transfer as transfer_module
from app.chain.transfer import TransferChain
from app.domain.context import MediaInfo
from app.domain.metainfo import MetaInfo
from app.runtime.config import ConfigModel
@@ -247,7 +247,7 @@ def test_aggregator_close_observes_flush_callback_error():
loop=loop,
)
with patch("app.application.transfer.logger.error") as log_error:
with patch("app.application.transfer.workflow.logger.error") as log_error:
aggregator.close()
callback.assert_called_once_with([notice])
+1 -1
View File
@@ -9,7 +9,7 @@ from app.application.history import (
failed_retry_count,
record_transfer_failure,
)
from app.application.transfer import (
from app.application.transfer.workflow import (
TransferAdmission,
TransferPlanningInput,
TransferTask,
+6 -6
View File
@@ -9,7 +9,7 @@ import pytest
from sqlalchemy import create_engine, select, text
from sqlalchemy.orm import sessionmaker
from app.application.transfer import (
from app.application.transfer.workflow import (
TRANSFER_ADMISSION_PLANNED,
TransferAdmission,
TransferAdmissionProjectionError,
@@ -19,7 +19,7 @@ from app.application.transfer import (
TransferProviderInvocationSnapshot,
TransferProviderReference,
)
from app.db.adapters.transfer import TransactionalTransferAdmissionRepository
from app.db.adapters.transfer.admission import TransactionalTransferAdmissionRepository
from app.db.models.transferhistory import TransferHistory
from app.db.models.transferpending import TransferPending
from app.db.oper.transferpending import TransferPendingOper
@@ -321,7 +321,7 @@ def test_claim_recoverable_skips_corrupt_projection_and_claims_later_tasks(
repository = repository_factory()
messages: list[str] = []
monkeypatch.setattr(
"app.db.adapters.transfer._diagnostic_logger.error",
"app.db.adapters.transfer.admission._diagnostic_logger.error",
messages.append,
)
corrupt = _admit(repository, "/downloads/a-corrupt.mkv")
@@ -389,7 +389,7 @@ def test_projection_diagnostic_changes_are_recorded_once_each(
repository = repository_factory()
messages: list[str] = []
monkeypatch.setattr(
"app.db.adapters.transfer._diagnostic_logger.error",
"app.db.adapters.transfer.admission._diagnostic_logger.error",
messages.append,
)
admitted = _admit(repository, "/downloads/changing-corrupt.mkv")
@@ -459,7 +459,7 @@ def test_projection_diagnostic_cas_is_concurrency_safe(
messages.append(message)
monkeypatch.setattr(
"app.db.adapters.transfer._diagnostic_logger.error",
"app.db.adapters.transfer.admission._diagnostic_logger.error",
capture,
)
barrier = Barrier(2)
@@ -498,7 +498,7 @@ def test_projection_diagnostic_does_not_overwrite_active_lease(
before = _pending_snapshot(repository, admitted.task_id)
messages: list[str] = []
monkeypatch.setattr(
"app.db.adapters.transfer._diagnostic_logger.error",
"app.db.adapters.transfer.admission._diagnostic_logger.error",
messages.append,
)
@@ -4,7 +4,7 @@ import threading
from types import SimpleNamespace
from unittest.mock import Mock, patch
from app.application.transfer_execution import (
from app.application.transfer.execution import (
TransferExecutionCheckpoint,
TransferSettlementResult,
)
+1 -1
View File
@@ -11,7 +11,7 @@ from pydantic import ValidationError
from app.api.dependencies.auth import get_current_active_manage_user
from app.api.endpoints import transfer as transfer_endpoint
from app.application.transfer_execution import (
from app.application.transfer.execution import (
TransferExecutionConflictError,
TransferExecutionState,
TransferManualReviewDecision,
@@ -8,14 +8,14 @@ from sqlalchemy import create_engine, select
from sqlalchemy.orm import sessionmaker
from app.api.endpoints import transfer as transfer_endpoint
from app.application.transfer_execution import (
from app.application.transfer.execution import (
TransferExecutionCommand,
TransferExecutionState,
TransferManualReviewQuery,
TransferStepIntent,
TransferStepResult,
)
from app.db.adapters.transfer_execution import (
from app.db.adapters.transfer.execution import (
TransactionalTransferExecutionRepository,
)
from app.db.base import Base
@@ -1,11 +1,11 @@
# -*- coding: utf-8 -*-
from types import SimpleNamespace
from app.application.transfer.workflow import TransferTask
from app.chain.transfer import JobManager, TransferChain
from app.domain.meta.metabase import MetaBase
from app.runtime.config import settings
from app.schemas import FileItem
from app.application.transfer import TransferTask
from app.schemas.file import FileItem
from app.schemas.types import MediaType
+4 -3
View File
@@ -2,10 +2,11 @@ from pathlib import Path
from types import SimpleNamespace
from unittest.mock import patch
from app.chain.transfer import TransferChain
from app.schemas import FileItem, TransferDirectoryConf
from app.application.transfer import TransferTask
from app.adapters.system.host import SystemUtils
from app.application.transfer.workflow import TransferTask
from app.chain.transfer import TransferChain
from app.schemas.file import FileItem
from app.schemas.system import TransferDirectoryConf
def _make_task(
+4 -4
View File
@@ -2,12 +2,13 @@ from types import SimpleNamespace
import pytest
from app.application.transfer.workflow import TransferTask
from app.chain.transfer import TransferChain
from app.runtime.config import settings
from app.domain.context import MediaInfo
from app.domain.meta.metabase import MetaBase
from app.schemas import DownloadHistory, FileItem
from app.application.transfer import TransferTask
from app.runtime.config import settings
from app.schemas.file import FileItem
from app.schemas.history import DownloadHistory
from app.schemas.types import MediaType
@@ -192,7 +193,6 @@ def test_movie_collection_conflict_only_drops_automatic_media(
)
monkeypatch.setattr("app.chain._transfer.get_chain_transfer_history_port", lambda: SimpleNamespace(get_by_src=lambda src, storage=None: None))
monkeypatch.setattr("app.chain.transfer.get_chain_download_history_port", lambda: history_oper)
monkeypatch.setattr("app.chain._transfer.get_chain_download_history_port", lambda: history_oper)
monkeypatch.setattr(
"app.chain.transfer.get_configured_system_config",
lambda: SimpleNamespace(get=lambda key: None),
+2 -2
View File
@@ -1,8 +1,8 @@
from app import schemas
from app.application.transfer import TransferTask
from app.application.transfer.workflow import TransferTask
from app.chain.transfer import JobManager
from app.domain.meta.metamusic import MetaMusic
from app.schemas import FileItem
from app.schemas.file import FileItem
def _music_task() -> TransferTask:
+1 -1
View File
@@ -11,7 +11,7 @@ from unittest.mock import MagicMock, patch
import pytest
from app.application.transfer_execution import (
from app.application.transfer.execution import (
TransferExecutionCheckpoint,
TransferSettlementResult,
)
+1 -1
View File
@@ -50,7 +50,7 @@ def test_legacy_import_targets_private_sdk_facade() -> None:
assert alias.target == "app.sdk._legacy.transferpending"
assert alias.owner == "sdk"
assert alias.replacement == "app.application.transfer"
assert alias.replacement == "app.application.transfer.workflow"
assert legacy is importlib.import_module(alias.target)
assert legacy.__all__ == ["TransferPendingOper"]
assert not hasattr(legacy, "TransferPending")
+1 -1
View File
@@ -13,7 +13,7 @@ from dataclasses import replace
from pathlib import Path
from unittest.mock import MagicMock
from app.application.transfer import TransferAdmission, TransferPlanningInput, TransferTask
from app.application.transfer.workflow import TransferAdmission, TransferPlanningInput, TransferTask
from app.chain.transfer import TransferChain
from app.schemas.file import FileItem
+4 -4
View File
@@ -12,14 +12,14 @@ import pytest
from sqlalchemy import create_engine, select
from sqlalchemy.orm import sessionmaker
from app.application import transfer as transfer_application
from app.application.transfer import TransferTask
from app.application.transfer_execution import (
from app.application.transfer import workflow as transfer_application
from app.application.transfer.execution import (
TransferExecutionCheckpoint,
TransferSettlementResult,
)
from app.application.transfer.workflow import TransferTask
from app.chain.transfer import TransferChain
from app.db.adapters.transfer import TransactionalTransferAdmissionRepository
from app.db.adapters.transfer.admission import TransactionalTransferAdmissionRepository
from app.db.models.transferhistory import TransferHistory
from app.db.models.transferpending import TransferPending
from app.domain.context import MediaInfo
+1 -1
View File
@@ -6,7 +6,7 @@ from unittest.mock import Mock
import pytest
from app.application.transfer import TransferTask
from app.application.transfer.workflow import TransferTask
from app.chain import ChainBase
from app.chain.transfer import TransferChain
from app.modules.filemanager.module import FileManagerModule
+1 -1
View File
@@ -10,7 +10,7 @@ import sqlalchemy as sa
from alembic.migration import MigrationContext
from alembic.operations import Operations
from app.application.transfer import TransferPlanningInput
from app.application.transfer.workflow import TransferPlanningInput
from app.db.models.transferpending import TransferPending
try:
+2 -2
View File
@@ -6,7 +6,7 @@ import pytest
from sqlalchemy import create_engine, select
from sqlalchemy.orm import sessionmaker
from app.application.transfer import (
from app.application.transfer.workflow import (
TRANSFER_ADMISSION_ACCEPTED,
TRANSFER_ADMISSION_PLANNED,
TRANSFER_ADMISSION_PROVIDER_PENDING,
@@ -19,7 +19,7 @@ from app.application.transfer import (
TransferProviderInvocationSnapshot,
TransferProviderReference,
)
from app.db.adapters.transfer import TransactionalTransferAdmissionRepository
from app.db.adapters.transfer.admission import TransactionalTransferAdmissionRepository
from app.db.models.transferhistory import TransferHistory
from app.db.models.transferpending import TransferPending
+2 -2
View File
@@ -5,8 +5,8 @@ import pytest
from sqlalchemy import create_engine, select
from sqlalchemy.orm import sessionmaker
from app.application.transfer import TransferAdmission, TransferQueueService
from app.db.adapters.transfer import TransactionalTransferAdmissionRepository
from app.application.transfer.workflow import TransferAdmission, TransferQueueService
from app.db.adapters.transfer.admission import TransactionalTransferAdmissionRepository
from app.db.models.transferhistory import TransferHistory
from app.db.models.transferpending import TransferPending
from app.schemas.file import FileItem
+7 -7
View File
@@ -9,19 +9,19 @@ import pytest
from sqlalchemy import create_engine, select
from sqlalchemy.orm import sessionmaker
from app.application.transfer import (
from app.application.transfer.execution import (
TransferExecutionCheckpoint,
TransferExecutionSnapshot,
TransferExecutionState,
)
from app.application.transfer.workflow import (
TransferAdmission,
TransferPlanCheckpoint,
TransferPlanningInput,
TransferTask,
)
from app.application.transfer_execution import (
TransferExecutionCheckpoint,
TransferExecutionSnapshot,
TransferExecutionState,
)
from app.chain.transfer import TransferChain
from app.db.adapters.transfer import TransactionalTransferAdmissionRepository
from app.db.adapters.transfer.admission import TransactionalTransferAdmissionRepository
from app.db.models.transferhistory import TransferHistory
from app.db.models.transferpending import TransferPending
from app.schemas.file import FileItem
+3 -3
View File
@@ -1,10 +1,10 @@
"""整理任务失活收敛行为测试。"""
from app.application.transfer import workflow as app_transfer
from app.application.transfer.workflow import TransferTask
from app.chain.transfer import JobManager
from app.domain.meta.metabase import MetaBase
from app.schemas import FileItem
from app.application.transfer import TransferTask
from app.application import transfer as app_transfer
from app.schemas.file import FileItem
from app.schemas.types import MediaType
-42
View File
@@ -148,12 +148,6 @@ def test_sync_extra_subtitle_inherits_matching_video_episode(monkeypatch):
get_by_path=lambda path: None,
),
)
monkeypatch.setattr("app.chain._transfer.get_chain_download_history_port", lambda: SimpleNamespace(
get_by_hash=lambda download_hash: None,
get_file_by_fullpath=lambda fullpath: None,
get_files_by_savepath=lambda savepath: [],
get_by_path=lambda path: None,
))
monkeypatch.setattr(
"app.chain.transfer.get_configured_system_config",
lambda: SimpleNamespace(get=lambda key: None),
@@ -245,12 +239,6 @@ def test_single_subtitle_transfer_reuses_same_name_video_episode(monkeypatch):
get_by_path=lambda path: None,
),
)
monkeypatch.setattr("app.chain._transfer.get_chain_download_history_port", lambda: SimpleNamespace(
get_by_hash=lambda download_hash: None,
get_file_by_fullpath=lambda fullpath: None,
get_files_by_savepath=lambda savepath: [],
get_by_path=lambda path: None,
))
monkeypatch.setattr(
"app.chain.transfer.get_configured_system_config",
lambda: SimpleNamespace(get=lambda key: None),
@@ -360,12 +348,6 @@ def test_single_video_transfer_lists_parent_once_for_same_name_extra(monkeypatch
get_by_path=lambda path: None,
),
)
monkeypatch.setattr("app.chain._transfer.get_chain_download_history_port", lambda: SimpleNamespace(
get_by_hash=lambda download_hash: None,
get_file_by_fullpath=lambda fullpath: None,
get_files_by_savepath=lambda savepath: [],
get_by_path=lambda path: None,
))
monkeypatch.setattr(
"app.chain.transfer.get_configured_system_config",
lambda: SimpleNamespace(get=lambda key: None),
@@ -458,12 +440,6 @@ def test_episode_format_filters_extra_files_before_sync_planning(monkeypatch):
get_by_path=lambda path: None,
),
)
monkeypatch.setattr("app.chain._transfer.get_chain_download_history_port", lambda: SimpleNamespace(
get_by_hash=lambda download_hash: None,
get_file_by_fullpath=lambda fullpath: None,
get_files_by_savepath=lambda savepath: [],
get_by_path=lambda path: None,
))
monkeypatch.setattr(
"app.chain.transfer.get_configured_system_config",
lambda: SimpleNamespace(get=lambda key: None),
@@ -545,12 +521,6 @@ def test_episode_format_keeps_matching_extra_files_following_main(monkeypatch):
get_by_path=lambda path: None,
),
)
monkeypatch.setattr("app.chain._transfer.get_chain_download_history_port", lambda: SimpleNamespace(
get_by_hash=lambda download_hash: None,
get_file_by_fullpath=lambda fullpath: None,
get_files_by_savepath=lambda savepath: [],
get_by_path=lambda path: None,
))
monkeypatch.setattr(
"app.chain.transfer.get_configured_system_config",
lambda: SimpleNamespace(get=lambda key: None),
@@ -641,12 +611,6 @@ def test_single_matching_subtitle_uses_unmatched_video_only_as_context(monkeypat
get_by_path=lambda path: None,
),
)
monkeypatch.setattr("app.chain._transfer.get_chain_download_history_port", lambda: SimpleNamespace(
get_by_hash=lambda download_hash: None,
get_file_by_fullpath=lambda fullpath: None,
get_files_by_savepath=lambda savepath: [],
get_by_path=lambda path: None,
))
monkeypatch.setattr(
"app.chain.transfer.get_configured_system_config",
lambda: SimpleNamespace(get=lambda key: None),
@@ -741,12 +705,6 @@ def test_cleanup_dest_fileitem_is_checkpointed_only_after_allowed_items_exist(mo
get_by_path=lambda path: None,
),
)
monkeypatch.setattr("app.chain._transfer.get_chain_download_history_port", lambda: SimpleNamespace(
get_by_hash=lambda download_hash: None,
get_file_by_fullpath=lambda fullpath: None,
get_files_by_savepath=lambda savepath: [],
get_by_path=lambda path: None,
))
monkeypatch.setattr(
"app.chain.transfer.get_configured_system_config",
lambda: SimpleNamespace(get=lambda key: None),
+3 -2
View File
@@ -1,10 +1,11 @@
from types import SimpleNamespace
from app.application.transfer.workflow import TransferTask
from app.chain.transfer import TransferChain
from app.domain.context import MediaInfo
from app.domain.metainfo import MetaInfo
from app.schemas import FileItem, TransferDirectoryConf
from app.application.transfer import TransferTask
from app.schemas.file import FileItem
from app.schemas.system import TransferDirectoryConf
from app.schemas.types import MediaSource, MediaType
+1 -1
View File
@@ -10,7 +10,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from app.application.transfer import TransferAdmission, TransferQueue, TransferTask
from app.application.transfer.workflow import TransferAdmission, TransferQueue, TransferTask
from app.chain.transfer import TransferChain
from app.foundation.singleton import Singleton
from app.runtime.config import global_vars
+1 -1
View File
@@ -3,7 +3,7 @@ from unittest.mock import MagicMock
import pytest
from app.application.transfer import TransferPlanningInput
from app.application.transfer.workflow import TransferPlanningInput
from app.domain.context import MediaInfo
from app.domain.meta.metavideo import MetaVideo
from app.modules.filemanager.transhandler import TransHandler