mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +00:00
Sort DMS results using only criteria supported by the device (#67475)
This commit is contained in:
parent
c5dd5e18c0
commit
797a9c3de5
@ -547,7 +547,7 @@ class DmsDeviceSource:
|
||||
children = await self._device.async_browse_direct_children(
|
||||
object_id,
|
||||
metadata_filter=DLNA_BROWSE_FILTER,
|
||||
sort_criteria=DLNA_SORT_CRITERIA,
|
||||
sort_criteria=self._sort_criteria,
|
||||
)
|
||||
|
||||
return self._didl_to_media_source(base_object, children)
|
||||
@ -680,6 +680,27 @@ class DmsDeviceSource:
|
||||
"""Make an identifier for BrowseMediaSource."""
|
||||
return f"{self.source_id}/{action}{object_id}"
|
||||
|
||||
@property # type: ignore
|
||||
@functools.cache
|
||||
def _sort_criteria(self) -> list[str]:
|
||||
"""Return criteria to be used for sorting results.
|
||||
|
||||
The device must be connected before reading this property.
|
||||
"""
|
||||
assert self._device
|
||||
|
||||
if self._device.sort_capabilities == ["*"]:
|
||||
return DLNA_SORT_CRITERIA
|
||||
|
||||
# Filter criteria based on what the device supports. Strings in
|
||||
# DLNA_SORT_CRITERIA are prefixed with a sign, while those in
|
||||
# the device's sort_capabilities are not.
|
||||
return [
|
||||
criterion
|
||||
for criterion in DLNA_SORT_CRITERIA
|
||||
if criterion[1:] in self._device.sort_capabilities
|
||||
]
|
||||
|
||||
|
||||
class Action(StrEnum):
|
||||
"""Actions that can be specified in a DMS media-source identifier."""
|
||||
|
@ -8,7 +8,7 @@ from async_upnp_client.profiles.dlna import ContentDirectoryErrorCode, DmsDevice
|
||||
from didl_lite import didl_lite
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.dlna_dms.const import DOMAIN
|
||||
from homeassistant.components.dlna_dms.const import DLNA_SORT_CRITERIA, DOMAIN
|
||||
from homeassistant.components.dlna_dms.dms import (
|
||||
ActionError,
|
||||
DeviceConnectionError,
|
||||
@ -686,6 +686,81 @@ async def test_browse_media_object(
|
||||
assert not child.children
|
||||
|
||||
|
||||
async def test_browse_object_sort_anything(
|
||||
device_source_mock: DmsDeviceSource, dms_device_mock: Mock
|
||||
) -> None:
|
||||
"""Test sort criteria for children where device allows anything."""
|
||||
dms_device_mock.sort_capabilities = ["*"]
|
||||
|
||||
object_id = "0"
|
||||
dms_device_mock.async_browse_metadata.return_value = didl_lite.Container(
|
||||
id="0", restricted="false", title="root"
|
||||
)
|
||||
dms_device_mock.async_browse_direct_children.return_value = DmsDevice.BrowseResult(
|
||||
[], 0, 0, 0
|
||||
)
|
||||
await device_source_mock.async_browse_object("0")
|
||||
|
||||
# Sort criteria should be dlna_dms's default
|
||||
dms_device_mock.async_browse_direct_children.assert_awaited_once_with(
|
||||
object_id, metadata_filter=ANY, sort_criteria=DLNA_SORT_CRITERIA
|
||||
)
|
||||
|
||||
|
||||
async def test_browse_object_sort_superset(
|
||||
device_source_mock: DmsDeviceSource, dms_device_mock: Mock
|
||||
) -> None:
|
||||
"""Test sorting where device allows superset of integration's criteria."""
|
||||
dms_device_mock.sort_capabilities = [
|
||||
"dc:title",
|
||||
"upnp:originalTrackNumber",
|
||||
"upnp:class",
|
||||
"upnp:artist",
|
||||
"dc:creator",
|
||||
"upnp:genre",
|
||||
]
|
||||
|
||||
object_id = "0"
|
||||
dms_device_mock.async_browse_metadata.return_value = didl_lite.Container(
|
||||
id="0", restricted="false", title="root"
|
||||
)
|
||||
dms_device_mock.async_browse_direct_children.return_value = DmsDevice.BrowseResult(
|
||||
[], 0, 0, 0
|
||||
)
|
||||
await device_source_mock.async_browse_object("0")
|
||||
|
||||
# Sort criteria should be dlna_dms's default
|
||||
dms_device_mock.async_browse_direct_children.assert_awaited_once_with(
|
||||
object_id, metadata_filter=ANY, sort_criteria=DLNA_SORT_CRITERIA
|
||||
)
|
||||
|
||||
|
||||
async def test_browse_object_sort_subset(
|
||||
device_source_mock: DmsDeviceSource, dms_device_mock: Mock
|
||||
) -> None:
|
||||
"""Test sorting where device allows subset of integration's criteria."""
|
||||
dms_device_mock.sort_capabilities = [
|
||||
"dc:title",
|
||||
"upnp:class",
|
||||
]
|
||||
|
||||
object_id = "0"
|
||||
dms_device_mock.async_browse_metadata.return_value = didl_lite.Container(
|
||||
id="0", restricted="false", title="root"
|
||||
)
|
||||
dms_device_mock.async_browse_direct_children.return_value = DmsDevice.BrowseResult(
|
||||
[], 0, 0, 0
|
||||
)
|
||||
await device_source_mock.async_browse_object("0")
|
||||
|
||||
# Sort criteria should be reduced to only those allowed,
|
||||
# and in the order specified by DLNA_SORT_CRITERIA
|
||||
expected_criteria = ["+upnp:class", "+dc:title"]
|
||||
dms_device_mock.async_browse_direct_children.assert_awaited_once_with(
|
||||
object_id, metadata_filter=ANY, sort_criteria=expected_criteria
|
||||
)
|
||||
|
||||
|
||||
async def test_browse_media_path(
|
||||
device_source_mock: DmsDeviceSource, dms_device_mock: Mock
|
||||
) -> None:
|
||||
|
Loading…
x
Reference in New Issue
Block a user