mirror of
https://github.com/home-assistant/core.git
synced 2026-08-24 10:13:52 -05:00
Refactor pylint plugins to use match statements (#168894)
This commit is contained in:
@@ -124,34 +124,18 @@ def _check_subscript_or_call_ip(node: nodes.NodeNG) -> str | None:
|
||||
avoiding false positives from local variables named ``host`` used in
|
||||
attribute chains like ``host.api.mac_address``.
|
||||
"""
|
||||
# Subscript: data[CONF_HOST] or data["host"]
|
||||
if isinstance(node, nodes.Subscript):
|
||||
key = node.slice
|
||||
if isinstance(key, nodes.Name) and key.name in _IP_HOST_NAMES:
|
||||
return str(key.name)
|
||||
if (
|
||||
isinstance(key, nodes.Const)
|
||||
and isinstance(key.value, str)
|
||||
and key.value in _IP_HOST_NAMES
|
||||
):
|
||||
return key.value
|
||||
|
||||
# Call: data.get(CONF_HOST) or data.get("host")
|
||||
if (
|
||||
isinstance(node, nodes.Call)
|
||||
and isinstance(node.func, nodes.Attribute)
|
||||
and node.func.attrname == "get"
|
||||
and node.args
|
||||
):
|
||||
first_arg = node.args[0]
|
||||
if isinstance(first_arg, nodes.Name) and first_arg.name in _IP_HOST_NAMES:
|
||||
return str(first_arg.name)
|
||||
if (
|
||||
isinstance(first_arg, nodes.Const)
|
||||
and isinstance(first_arg.value, str)
|
||||
and first_arg.value in _IP_HOST_NAMES
|
||||
):
|
||||
return first_arg.value
|
||||
match node:
|
||||
# Subscript: data[CONF_HOST] or data["host"]
|
||||
case nodes.Subscript(
|
||||
slice=nodes.Name(name=val) | nodes.Const(value=str(val))
|
||||
) if val in _IP_HOST_NAMES:
|
||||
return str(val)
|
||||
# Call: data.get(CONF_HOST) or data.get("host")
|
||||
case nodes.Call(
|
||||
func=nodes.Attribute(attrname="get"),
|
||||
args=[nodes.Name(name=val) | nodes.Const(value=str(val)), *_],
|
||||
) if val in _IP_HOST_NAMES:
|
||||
return str(val)
|
||||
|
||||
# Recurse into child nodes to catch embedded references (e.g. f-strings),
|
||||
# but skip function call arguments -- a call like get_unique_id(host)
|
||||
|
||||
@@ -83,19 +83,14 @@ class HassEnforceConfigFlowNoPollingChecker(BaseChecker):
|
||||
|
||||
def _get_schema_field_name(node: nodes.Call) -> str | None:
|
||||
"""Extract the field name from vol.Required(...) or vol.Optional(...)."""
|
||||
if not isinstance(node.func, nodes.Attribute):
|
||||
return None
|
||||
if node.func.attrname not in {"Required", "Optional"}:
|
||||
return None
|
||||
if not node.args:
|
||||
return None
|
||||
|
||||
first_arg = node.args[0]
|
||||
if isinstance(first_arg, nodes.Const) and isinstance(first_arg.value, str):
|
||||
return first_arg.value
|
||||
if isinstance(first_arg, nodes.Name):
|
||||
return str(first_arg.name)
|
||||
return None
|
||||
match node:
|
||||
case nodes.Call(
|
||||
func=nodes.Attribute(attrname="Required" | "Optional"),
|
||||
args=[nodes.Name(name=val) | nodes.Const(value=str(val)), *_],
|
||||
):
|
||||
return str(val)
|
||||
case _:
|
||||
return None
|
||||
|
||||
|
||||
def register(linter: PyLinter) -> None:
|
||||
|
||||
@@ -81,39 +81,31 @@ class HassEnforceRuntimeDataChecker(BaseChecker):
|
||||
return
|
||||
|
||||
# Don't flag deletion: del hass.data[DOMAIN] or hass.data[DOMAIN].pop(...)
|
||||
parent = node.parent
|
||||
if isinstance(parent, nodes.Delete):
|
||||
return
|
||||
if (
|
||||
isinstance(parent, nodes.Attribute)
|
||||
and parent.attrname == "pop"
|
||||
and isinstance(parent.parent, nodes.Call)
|
||||
):
|
||||
return
|
||||
match node.parent:
|
||||
case nodes.Delete():
|
||||
return
|
||||
case nodes.Attribute(attrname="pop", parent=nodes.Call()):
|
||||
return
|
||||
|
||||
self.add_message("hass-use-runtime-data", node=node)
|
||||
|
||||
|
||||
def _is_hass_data_domain_access(node: nodes.Subscript) -> bool:
|
||||
"""Return True if node is hass.data[DOMAIN] or self.hass.data[DOMAIN]."""
|
||||
if not isinstance(node.value, nodes.Attribute):
|
||||
return False
|
||||
if node.value.attrname != "data":
|
||||
return False
|
||||
|
||||
slice_node = node.slice
|
||||
if not isinstance(slice_node, nodes.Name) or slice_node.name != "DOMAIN":
|
||||
return False
|
||||
|
||||
expr = node.value.expr
|
||||
if isinstance(expr, nodes.Name) and expr.name == "hass":
|
||||
return True
|
||||
return (
|
||||
isinstance(expr, nodes.Attribute)
|
||||
and expr.attrname == "hass"
|
||||
and isinstance(expr.expr, nodes.Name)
|
||||
and expr.expr.name == "self"
|
||||
)
|
||||
match node:
|
||||
case nodes.Subscript(
|
||||
value=nodes.Attribute(
|
||||
expr=(
|
||||
nodes.Name(name="hass")
|
||||
| nodes.Attribute(expr=nodes.Name(name="self"), attrname="hass")
|
||||
),
|
||||
attrname="data",
|
||||
),
|
||||
slice=nodes.Name(name="DOMAIN"),
|
||||
):
|
||||
return True
|
||||
case _:
|
||||
return False
|
||||
|
||||
|
||||
def _has_config_flow(integration: str, module: nodes.Module) -> bool:
|
||||
|
||||
Reference in New Issue
Block a user