mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-08-28 19:47:41 +08:00
refactor: type media server contracts
This commit is contained in:
@@ -87,10 +87,19 @@ _METHOD_CONTRACTS = {
|
||||
),
|
||||
"obtain_images": ModuleMethodContract(family="media-recognition", input_contract="MediaInfo", result_contract="MediaInfo | None", aggregation=ModuleResultAggregation.PIPELINE_RELAY, required_parameters=("mediainfo",)),
|
||||
"media_category": ModuleMethodContract(family="media-recognition", input_contract="MediaCategoryRequest", result_contract="CategoryConfig | None"),
|
||||
"mediaserver_items": ModuleMethodContract(family="media-server", input_contract="MediaServerItemsRequest", result_contract="list[MediaServerItem]", aggregation=ModuleResultAggregation.ORDERED_LIST_MERGE, required_parameters=("server", "library_id", "start_index", "limit")),
|
||||
"mediaserver_items": ModuleMethodContract(family="media-server", input_contract="MediaServerItemsRequest", result_contract="Iterable[MediaServerItem] | None", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("server", "library_id", "start_index", "limit")),
|
||||
"mediaserver_iteminfo": ModuleMethodContract(family="media-server", input_contract="MediaServerItemRequest", result_contract="MediaServerItem | None", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("server", "item_id")),
|
||||
"mediaserver_play_url": ModuleMethodContract(family="media-server", input_contract="MediaServerPlayRequest", result_contract="str | None", result_shape=ModuleResultShape.STRING, aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("server", "item_id")),
|
||||
"mediaserver_tv_episodes": ModuleMethodContract(family="media-server", input_contract="MediaServerEpisodesRequest", result_contract="list[MediaServerPlayItem]", aggregation=ModuleResultAggregation.ORDERED_LIST_MERGE, required_parameters=("server", "item_id")),
|
||||
"media_exists": ModuleMethodContract(family="media-server", input_contract="MediaExistsRequest", result_contract="ExistMediaInfo | None", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("mediainfo", "itemid", "server")),
|
||||
"media_statistic": ModuleMethodContract(family="media-server", input_contract="MediaStatisticRequest", result_contract="list[Statistic]", result_shape=ModuleResultShape.LIST, aggregation=ModuleResultAggregation.ORDERED_LIST_MERGE, required_parameters=("server",)),
|
||||
"mediaserver_image_cookies": ModuleMethodContract(family="media-server", input_contract="MediaServerImageCookiesRequest", result_contract="str | dict | None", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("server", "image_url")),
|
||||
"mediaserver_items_count": ModuleMethodContract(family="media-server", input_contract="MediaServerItemsCountRequest", result_contract="int | None", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("server", "library_id")),
|
||||
"mediaserver_latest": ModuleMethodContract(family="media-server", input_contract="MediaServerRecentRequest", result_contract="list[MediaServerPlayItem]", result_shape=ModuleResultShape.LIST, aggregation=ModuleResultAggregation.ORDERED_LIST_MERGE, required_parameters=("server", "count", "username")),
|
||||
"mediaserver_latest_images": ModuleMethodContract(family="media-server", input_contract="MediaServerRecentImagesRequest", result_contract="list[str]", result_shape=ModuleResultShape.LIST, aggregation=ModuleResultAggregation.ORDERED_LIST_MERGE, required_parameters=("server", "count", "remote", "username")),
|
||||
"mediaserver_librarys": ModuleMethodContract(family="media-server", input_contract="MediaServerLibrariesRequest", result_contract="list[MediaServerLibrary]", result_shape=ModuleResultShape.LIST, aggregation=ModuleResultAggregation.ORDERED_LIST_MERGE, required_parameters=("server", "username", "hidden")),
|
||||
"mediaserver_playing": ModuleMethodContract(family="media-server", input_contract="MediaServerRecentRequest", result_contract="list[MediaServerPlayItem]", result_shape=ModuleResultShape.LIST, aggregation=ModuleResultAggregation.ORDERED_LIST_MERGE, required_parameters=("server", "count", "username")),
|
||||
"mediaserver_season_episode_ids": ModuleMethodContract(family="media-server", input_contract="MediaServerSeasonEpisodesRequest", result_contract="dict[int, str] | None", result_shape=ModuleResultShape.MAPPING, aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("server", "item_id", "season")),
|
||||
"download_file": ModuleMethodContract(family="storage", input_contract="StorageDownloadRequest", result_contract="FileItem | None", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("fileitem", "path")),
|
||||
"upload_file": ModuleMethodContract(family="storage", input_contract="StorageUploadRequest", result_contract="FileItem | None", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("fileitem", "path", "new_name")),
|
||||
"list_files": ModuleMethodContract(family="storage", input_contract="StorageListRequest", result_contract="list[FileItem]", result_shape=ModuleResultShape.LIST, aggregation=ModuleResultAggregation.ORDERED_LIST_MERGE, required_parameters=("fileitem", "recursion")),
|
||||
|
||||
+77
-44
@@ -4385,15 +4385,19 @@
|
||||
"version": 1
|
||||
},
|
||||
"media_exists": {
|
||||
"aggregation": "legacy",
|
||||
"aggregation": "first_non_empty",
|
||||
"error_policy": "isolate_provider",
|
||||
"execution": "sync_or_async",
|
||||
"family": "media-server",
|
||||
"input_contract": "MediaServerKeywordArguments",
|
||||
"input_contract": "MediaExistsRequest",
|
||||
"plugin_short_circuit": true,
|
||||
"public_to_plugins": true,
|
||||
"required_parameters": [],
|
||||
"result_contract": "MediaServerProviderResult",
|
||||
"required_parameters": [
|
||||
"itemid",
|
||||
"mediainfo",
|
||||
"server"
|
||||
],
|
||||
"result_contract": "ExistMediaInfo | None",
|
||||
"result_shape": "any",
|
||||
"supports_async": true,
|
||||
"supports_sync": true,
|
||||
@@ -4417,31 +4421,36 @@
|
||||
"version": 1
|
||||
},
|
||||
"media_statistic": {
|
||||
"aggregation": "legacy",
|
||||
"aggregation": "ordered_list_merge",
|
||||
"error_policy": "isolate_provider",
|
||||
"execution": "sync_or_async",
|
||||
"family": "media-server",
|
||||
"input_contract": "MediaServerKeywordArguments",
|
||||
"input_contract": "MediaStatisticRequest",
|
||||
"plugin_short_circuit": true,
|
||||
"public_to_plugins": true,
|
||||
"required_parameters": [],
|
||||
"result_contract": "MediaServerProviderResult",
|
||||
"result_shape": "any",
|
||||
"required_parameters": [
|
||||
"server"
|
||||
],
|
||||
"result_contract": "list[Statistic]",
|
||||
"result_shape": "list",
|
||||
"supports_async": true,
|
||||
"supports_sync": true,
|
||||
"timeout_policy": "caller_budget",
|
||||
"version": 1
|
||||
},
|
||||
"mediaserver_image_cookies": {
|
||||
"aggregation": "legacy",
|
||||
"aggregation": "first_non_empty",
|
||||
"error_policy": "isolate_provider",
|
||||
"execution": "sync_or_async",
|
||||
"family": "media-server",
|
||||
"input_contract": "MediaServerKeywordArguments",
|
||||
"input_contract": "MediaServerImageCookiesRequest",
|
||||
"plugin_short_circuit": true,
|
||||
"public_to_plugins": true,
|
||||
"required_parameters": [],
|
||||
"result_contract": "MediaServerProviderResult",
|
||||
"required_parameters": [
|
||||
"image_url",
|
||||
"server"
|
||||
],
|
||||
"result_contract": "str | dict | None",
|
||||
"result_shape": "any",
|
||||
"supports_async": true,
|
||||
"supports_sync": true,
|
||||
@@ -4468,7 +4477,7 @@
|
||||
"version": 1
|
||||
},
|
||||
"mediaserver_items": {
|
||||
"aggregation": "ordered_list_merge",
|
||||
"aggregation": "first_non_empty",
|
||||
"error_policy": "isolate_provider",
|
||||
"execution": "sync_or_async",
|
||||
"family": "media-server",
|
||||
@@ -4481,7 +4490,7 @@
|
||||
"server",
|
||||
"start_index"
|
||||
],
|
||||
"result_contract": "list[MediaServerItem]",
|
||||
"result_contract": "Iterable[MediaServerItem] | None",
|
||||
"result_shape": "any",
|
||||
"supports_async": true,
|
||||
"supports_sync": true,
|
||||
@@ -4489,15 +4498,18 @@
|
||||
"version": 1
|
||||
},
|
||||
"mediaserver_items_count": {
|
||||
"aggregation": "legacy",
|
||||
"aggregation": "first_non_empty",
|
||||
"error_policy": "isolate_provider",
|
||||
"execution": "sync_or_async",
|
||||
"family": "media-server",
|
||||
"input_contract": "MediaServerKeywordArguments",
|
||||
"input_contract": "MediaServerItemsCountRequest",
|
||||
"plugin_short_circuit": true,
|
||||
"public_to_plugins": true,
|
||||
"required_parameters": [],
|
||||
"result_contract": "MediaServerProviderResult",
|
||||
"required_parameters": [
|
||||
"library_id",
|
||||
"server"
|
||||
],
|
||||
"result_contract": "int | None",
|
||||
"result_shape": "any",
|
||||
"supports_async": true,
|
||||
"supports_sync": true,
|
||||
@@ -4505,48 +4517,61 @@
|
||||
"version": 1
|
||||
},
|
||||
"mediaserver_latest": {
|
||||
"aggregation": "legacy",
|
||||
"aggregation": "ordered_list_merge",
|
||||
"error_policy": "isolate_provider",
|
||||
"execution": "sync_or_async",
|
||||
"family": "media-server",
|
||||
"input_contract": "MediaServerKeywordArguments",
|
||||
"input_contract": "MediaServerRecentRequest",
|
||||
"plugin_short_circuit": true,
|
||||
"public_to_plugins": true,
|
||||
"required_parameters": [],
|
||||
"result_contract": "MediaServerProviderResult",
|
||||
"result_shape": "any",
|
||||
"required_parameters": [
|
||||
"count",
|
||||
"server",
|
||||
"username"
|
||||
],
|
||||
"result_contract": "list[MediaServerPlayItem]",
|
||||
"result_shape": "list",
|
||||
"supports_async": true,
|
||||
"supports_sync": true,
|
||||
"timeout_policy": "caller_budget",
|
||||
"version": 1
|
||||
},
|
||||
"mediaserver_latest_images": {
|
||||
"aggregation": "legacy",
|
||||
"aggregation": "ordered_list_merge",
|
||||
"error_policy": "isolate_provider",
|
||||
"execution": "sync_or_async",
|
||||
"family": "media-server",
|
||||
"input_contract": "MediaServerKeywordArguments",
|
||||
"input_contract": "MediaServerRecentImagesRequest",
|
||||
"plugin_short_circuit": true,
|
||||
"public_to_plugins": true,
|
||||
"required_parameters": [],
|
||||
"result_contract": "MediaServerProviderResult",
|
||||
"result_shape": "any",
|
||||
"required_parameters": [
|
||||
"count",
|
||||
"remote",
|
||||
"server",
|
||||
"username"
|
||||
],
|
||||
"result_contract": "list[str]",
|
||||
"result_shape": "list",
|
||||
"supports_async": true,
|
||||
"supports_sync": true,
|
||||
"timeout_policy": "caller_budget",
|
||||
"version": 1
|
||||
},
|
||||
"mediaserver_librarys": {
|
||||
"aggregation": "legacy",
|
||||
"aggregation": "ordered_list_merge",
|
||||
"error_policy": "isolate_provider",
|
||||
"execution": "sync_or_async",
|
||||
"family": "media-server",
|
||||
"input_contract": "MediaServerKeywordArguments",
|
||||
"input_contract": "MediaServerLibrariesRequest",
|
||||
"plugin_short_circuit": true,
|
||||
"public_to_plugins": true,
|
||||
"required_parameters": [],
|
||||
"result_contract": "MediaServerProviderResult",
|
||||
"result_shape": "any",
|
||||
"required_parameters": [
|
||||
"hidden",
|
||||
"server",
|
||||
"username"
|
||||
],
|
||||
"result_contract": "list[MediaServerLibrary]",
|
||||
"result_shape": "list",
|
||||
"supports_async": true,
|
||||
"supports_sync": true,
|
||||
"timeout_policy": "caller_budget",
|
||||
@@ -4572,32 +4597,40 @@
|
||||
"version": 1
|
||||
},
|
||||
"mediaserver_playing": {
|
||||
"aggregation": "legacy",
|
||||
"aggregation": "ordered_list_merge",
|
||||
"error_policy": "isolate_provider",
|
||||
"execution": "sync_or_async",
|
||||
"family": "media-server",
|
||||
"input_contract": "MediaServerKeywordArguments",
|
||||
"input_contract": "MediaServerRecentRequest",
|
||||
"plugin_short_circuit": true,
|
||||
"public_to_plugins": true,
|
||||
"required_parameters": [],
|
||||
"result_contract": "MediaServerProviderResult",
|
||||
"result_shape": "any",
|
||||
"required_parameters": [
|
||||
"count",
|
||||
"server",
|
||||
"username"
|
||||
],
|
||||
"result_contract": "list[MediaServerPlayItem]",
|
||||
"result_shape": "list",
|
||||
"supports_async": true,
|
||||
"supports_sync": true,
|
||||
"timeout_policy": "caller_budget",
|
||||
"version": 1
|
||||
},
|
||||
"mediaserver_season_episode_ids": {
|
||||
"aggregation": "legacy",
|
||||
"aggregation": "first_non_empty",
|
||||
"error_policy": "isolate_provider",
|
||||
"execution": "sync_or_async",
|
||||
"family": "media-server",
|
||||
"input_contract": "MediaServerKeywordArguments",
|
||||
"input_contract": "MediaServerSeasonEpisodesRequest",
|
||||
"plugin_short_circuit": true,
|
||||
"public_to_plugins": true,
|
||||
"required_parameters": [],
|
||||
"result_contract": "MediaServerProviderResult",
|
||||
"result_shape": "any",
|
||||
"required_parameters": [
|
||||
"item_id",
|
||||
"season",
|
||||
"server"
|
||||
],
|
||||
"result_contract": "dict[int, str] | None",
|
||||
"result_shape": "mapping",
|
||||
"supports_async": true,
|
||||
"supports_sync": true,
|
||||
"timeout_policy": "caller_budget",
|
||||
|
||||
@@ -159,6 +159,36 @@ def test_downloader_query_contracts_merge_provider_lists() -> None:
|
||||
assert contract.result_shape is ModuleResultShape.LIST
|
||||
|
||||
|
||||
def test_media_server_contracts_distinguish_streams_lists_and_scalar_routes() -> None:
|
||||
"""媒体服务器能力应按真实返回形状选择合并或目标路由语义。"""
|
||||
list_methods = {
|
||||
"media_statistic",
|
||||
"mediaserver_latest",
|
||||
"mediaserver_latest_images",
|
||||
"mediaserver_librarys",
|
||||
"mediaserver_playing",
|
||||
}
|
||||
scalar_methods = {
|
||||
"media_exists",
|
||||
"mediaserver_image_cookies",
|
||||
"mediaserver_items_count",
|
||||
"mediaserver_season_episode_ids",
|
||||
}
|
||||
|
||||
for method in list_methods:
|
||||
contract = get_module_method_contract(method)
|
||||
assert contract.aggregation is ModuleResultAggregation.ORDERED_LIST_MERGE
|
||||
assert contract.result_shape is ModuleResultShape.LIST
|
||||
for method in scalar_methods:
|
||||
contract = get_module_method_contract(method)
|
||||
assert contract.aggregation is ModuleResultAggregation.FIRST_NON_EMPTY
|
||||
|
||||
items = get_module_method_contract("mediaserver_items")
|
||||
assert items.result_contract == "Iterable[MediaServerItem] | None"
|
||||
assert items.aggregation is ModuleResultAggregation.FIRST_NON_EMPTY
|
||||
assert items.result_shape is ModuleResultShape.ANY
|
||||
|
||||
|
||||
def test_heterogeneous_torrent_files_result_remains_legacy_compatible() -> None:
|
||||
"""下载器文件集合尚未归一前不得声明虚假的列表聚合语义。"""
|
||||
contract = get_module_method_contract("torrent_files")
|
||||
|
||||
Reference in New Issue
Block a user