mirror of
https://github.com/home-assistant/core.git
synced 2025-07-12 07:47:08 +00:00
Add media-player checks to pylint plugin (#76675)
* Add media-player checks to pylint plugin * Fix invalid hints * Add tests * Adjust tests * Add extra test * Adjust regex * Cleanup comment * Move media player tests up
This commit is contained in:
parent
c9feda1562
commit
6243f24b05
@ -59,7 +59,7 @@ _TYPE_HINT_MATCHERS: dict[str, re.Pattern[str]] = {
|
|||||||
# a_or_b matches items such as "DiscoveryInfoType | None"
|
# a_or_b matches items such as "DiscoveryInfoType | None"
|
||||||
"a_or_b": re.compile(r"^(\w+) \| (\w+)$"),
|
"a_or_b": re.compile(r"^(\w+) \| (\w+)$"),
|
||||||
}
|
}
|
||||||
_INNER_MATCH = r"((?:\w+)|(?:\.{3})|(?:\w+\[.+\]))"
|
_INNER_MATCH = r"((?:[\w\| ]+)|(?:\.{3})|(?:\w+\[.+\]))"
|
||||||
_INNER_MATCH_POSSIBILITIES = [i + 1 for i in range(5)]
|
_INNER_MATCH_POSSIBILITIES = [i + 1 for i in range(5)]
|
||||||
_TYPE_HINT_MATCHERS.update(
|
_TYPE_HINT_MATCHERS.update(
|
||||||
{
|
{
|
||||||
@ -1465,6 +1465,322 @@ _INHERITANCE_MATCH: dict[str, list[ClassTypeHintMatch]] = {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
"media_player": [
|
||||||
|
ClassTypeHintMatch(
|
||||||
|
base_class="Entity",
|
||||||
|
matches=_ENTITY_MATCH,
|
||||||
|
),
|
||||||
|
ClassTypeHintMatch(
|
||||||
|
base_class="MediaPlayerEntity",
|
||||||
|
matches=[
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="device_class",
|
||||||
|
return_type=["MediaPlayerDeviceClass", "str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="state",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="access_token",
|
||||||
|
return_type="str",
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="volume_level",
|
||||||
|
return_type=["float", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="is_volume_muted",
|
||||||
|
return_type=["bool", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_content_id",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_content_type",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_duration",
|
||||||
|
return_type=["int", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_position",
|
||||||
|
return_type=["int", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_position_updated_at",
|
||||||
|
return_type=["datetime", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_image_url",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_image_remotely_accessible",
|
||||||
|
return_type="bool",
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_image_hash",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="async_get_media_image",
|
||||||
|
return_type="tuple[bytes | None, str | None]",
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="async_get_browse_image",
|
||||||
|
arg_types={
|
||||||
|
1: "str",
|
||||||
|
2: "str",
|
||||||
|
3: "str | None",
|
||||||
|
},
|
||||||
|
return_type="tuple[bytes | None, str | None]",
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_title",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_artist",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_album_name",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_album_artist",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_track",
|
||||||
|
return_type=["int", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_series_title",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_season",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_episode",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_channel",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_playlist",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="app_id",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="app_name",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="source",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="source_list",
|
||||||
|
return_type=["list[str]", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="sound_mode",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="sound_mode_list",
|
||||||
|
return_type=["list[str]", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="shuffle",
|
||||||
|
return_type=["bool", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="repeat",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="group_members",
|
||||||
|
return_type=["list[str]", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="turn_on",
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="turn_off",
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="mute_volume",
|
||||||
|
arg_types={
|
||||||
|
1: "bool",
|
||||||
|
},
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="set_volume_level",
|
||||||
|
arg_types={
|
||||||
|
1: "float",
|
||||||
|
},
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_play",
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_pause",
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_stop",
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_previous_track",
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_next_track",
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_seek",
|
||||||
|
arg_types={
|
||||||
|
1: "float",
|
||||||
|
},
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="play_media",
|
||||||
|
arg_types={
|
||||||
|
1: "str",
|
||||||
|
2: "str",
|
||||||
|
},
|
||||||
|
kwargs_type="Any",
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="select_source",
|
||||||
|
arg_types={
|
||||||
|
1: "str",
|
||||||
|
},
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="select_sound_mode",
|
||||||
|
arg_types={
|
||||||
|
1: "str",
|
||||||
|
},
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="clear_playlist",
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="set_shuffle",
|
||||||
|
arg_types={
|
||||||
|
1: "bool",
|
||||||
|
},
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="set_repeat",
|
||||||
|
arg_types={
|
||||||
|
1: "str",
|
||||||
|
},
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="toggle",
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="volume_up",
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="volume_down",
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_play_pause",
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="media_image_local",
|
||||||
|
return_type=["str", None],
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="capability_attributes",
|
||||||
|
return_type="dict[str, Any]",
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="async_browse_media",
|
||||||
|
arg_types={
|
||||||
|
1: "str | None",
|
||||||
|
2: "str | None",
|
||||||
|
},
|
||||||
|
return_type="BrowseMedia",
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="join_players",
|
||||||
|
arg_types={
|
||||||
|
1: "list[str]",
|
||||||
|
},
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="unjoin_player",
|
||||||
|
return_type=None,
|
||||||
|
has_async_counterpart=True,
|
||||||
|
),
|
||||||
|
TypeHintMatch(
|
||||||
|
function_name="get_browse_image_url",
|
||||||
|
arg_types={
|
||||||
|
1: "str",
|
||||||
|
2: "str",
|
||||||
|
3: "str | None",
|
||||||
|
},
|
||||||
|
return_type="str",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
"number": [
|
"number": [
|
||||||
ClassTypeHintMatch(
|
ClassTypeHintMatch(
|
||||||
base_class="Entity",
|
base_class="Entity",
|
||||||
|
@ -53,6 +53,7 @@ def test_regex_get_module_platform(
|
|||||||
("Awaitable[None]", 1, ("Awaitable", "None")),
|
("Awaitable[None]", 1, ("Awaitable", "None")),
|
||||||
("list[dict[str, str]]", 1, ("list", "dict[str, str]")),
|
("list[dict[str, str]]", 1, ("list", "dict[str, str]")),
|
||||||
("list[dict[str, Any]]", 1, ("list", "dict[str, Any]")),
|
("list[dict[str, Any]]", 1, ("list", "dict[str, Any]")),
|
||||||
|
("tuple[bytes | None, str | None]", 2, ("tuple", "bytes | None", "str | None")),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_regex_x_of_y_i(
|
def test_regex_x_of_y_i(
|
||||||
@ -902,6 +903,35 @@ def test_invalid_device_class(
|
|||||||
type_hint_checker.visit_classdef(class_node)
|
type_hint_checker.visit_classdef(class_node)
|
||||||
|
|
||||||
|
|
||||||
|
def test_media_player_entity(
|
||||||
|
linter: UnittestLinter, type_hint_checker: BaseChecker
|
||||||
|
) -> None:
|
||||||
|
"""Ensure valid hints are accepted for media_player entity."""
|
||||||
|
# Set bypass option
|
||||||
|
type_hint_checker.config.ignore_missing_annotations = False
|
||||||
|
|
||||||
|
class_node = astroid.extract_node(
|
||||||
|
"""
|
||||||
|
class Entity():
|
||||||
|
pass
|
||||||
|
|
||||||
|
class MediaPlayerEntity(Entity):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class MyMediaPlayer( #@
|
||||||
|
MediaPlayerEntity
|
||||||
|
):
|
||||||
|
async def async_get_media_image(self) -> tuple[bytes | None, str | None]:
|
||||||
|
pass
|
||||||
|
""",
|
||||||
|
"homeassistant.components.pylint_test.media_player",
|
||||||
|
)
|
||||||
|
type_hint_checker.visit_module(class_node.parent)
|
||||||
|
|
||||||
|
with assert_no_messages(linter):
|
||||||
|
type_hint_checker.visit_classdef(class_node)
|
||||||
|
|
||||||
|
|
||||||
def test_number_entity(linter: UnittestLinter, type_hint_checker: BaseChecker) -> None:
|
def test_number_entity(linter: UnittestLinter, type_hint_checker: BaseChecker) -> None:
|
||||||
"""Ensure valid hints are accepted for number entity."""
|
"""Ensure valid hints are accepted for number entity."""
|
||||||
# Set bypass option
|
# Set bypass option
|
||||||
|
Loading…
x
Reference in New Issue
Block a user