From bc22e34fc36298009fb9daf856f3fbb9dc8783be Mon Sep 17 00:00:00 2001
From: G Johansson <goran.johansson@shiftit.se>
Date: Mon, 6 Jan 2025 04:22:54 +0100
Subject: [PATCH] Add python_script to strict typing (#134822)

---
 .strict-typing                                |  1 +
 .../components/python_script/__init__.py      | 29 +++++++++++++------
 mypy.ini                                      | 10 +++++++
 3 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/.strict-typing b/.strict-typing
index f0f4e34c505..98fbb16ff45 100644
--- a/.strict-typing
+++ b/.strict-typing
@@ -383,6 +383,7 @@ homeassistant.components.pure_energie.*
 homeassistant.components.purpleair.*
 homeassistant.components.pushbullet.*
 homeassistant.components.pvoutput.*
+homeassistant.components.python_script.*
 homeassistant.components.qnap_qsw.*
 homeassistant.components.rabbitair.*
 homeassistant.components.radarr.*
diff --git a/homeassistant/components/python_script/__init__.py b/homeassistant/components/python_script/__init__.py
index af773278029..1e41c81b010 100644
--- a/homeassistant/components/python_script/__init__.py
+++ b/homeassistant/components/python_script/__init__.py
@@ -1,6 +1,6 @@
 """Component to allow running Python scripts."""
 
-from collections.abc import Mapping, Sequence
+from collections.abc import Callable, Mapping, Sequence
 import datetime
 import glob
 import logging
@@ -197,7 +197,12 @@ def guarded_inplacevar(op: str, target: Any, operand: Any) -> Any:
 
 
 @bind_hass
-def execute_script(hass, name, data=None, return_response=False):
+def execute_script(
+    hass: HomeAssistant,
+    name: str,
+    data: dict[str, Any] | None = None,
+    return_response: bool = False,
+) -> dict | None:
     """Execute a script."""
     filename = f"{name}.py"
     raise_if_invalid_filename(filename)
@@ -207,7 +212,13 @@ def execute_script(hass, name, data=None, return_response=False):
 
 
 @bind_hass
-def execute(hass, filename, source, data=None, return_response=False):
+def execute(
+    hass: HomeAssistant,
+    filename: str,
+    source: Any,
+    data: dict[str, Any] | None = None,
+    return_response: bool = False,
+) -> dict | None:
     """Execute Python source."""
 
     compiled = compile_restricted_exec(source, filename=filename)
@@ -223,7 +234,7 @@ def execute(hass, filename, source, data=None, return_response=False):
             "Warning loading script %s: %s", filename, ", ".join(compiled.warnings)
         )
 
-    def protected_getattr(obj, name, default=None):
+    def protected_getattr(obj: object, name: str, default: Any = None) -> Any:
         """Restricted method to get attributes."""
         if name.startswith("async_"):
             raise ScriptError("Not allowed to access async methods")
@@ -316,10 +327,10 @@ def execute(hass, filename, source, data=None, return_response=False):
 class StubPrinter:
     """Class to handle printing inside scripts."""
 
-    def __init__(self, _getattr_):
+    def __init__(self, _getattr_: Callable) -> None:
         """Initialize our printer."""
 
-    def _call_print(self, *objects, **kwargs):
+    def _call_print(self, *objects: object, **kwargs: Any) -> None:
         """Print text."""
         _LOGGER.warning("Don't use print() inside scripts. Use logger.info() instead")
 
@@ -330,7 +341,7 @@ class TimeWrapper:
     # Class variable, only going to warn once per Home Assistant run
     warned = False
 
-    def sleep(self, *args, **kwargs):
+    def sleep(self, *args: Any, **kwargs: Any) -> None:
         """Sleep method that warns once."""
         if not TimeWrapper.warned:
             TimeWrapper.warned = True
@@ -340,12 +351,12 @@ class TimeWrapper:
 
         time.sleep(*args, **kwargs)
 
-    def __getattr__(self, attr):
+    def __getattr__(self, attr: str) -> Any:
         """Fetch an attribute from Time module."""
         attribute = getattr(time, attr)
         if callable(attribute):
 
-            def wrapper(*args, **kw):
+            def wrapper(*args: Any, **kw: Any) -> Any:
                 """Wrap to return callable method if callable."""
                 return attribute(*args, **kw)
 
diff --git a/mypy.ini b/mypy.ini
index e393b32f9fd..55fd0b3cd65 100644
--- a/mypy.ini
+++ b/mypy.ini
@@ -3586,6 +3586,16 @@ disallow_untyped_defs = true
 warn_return_any = true
 warn_unreachable = true
 
+[mypy-homeassistant.components.python_script.*]
+check_untyped_defs = true
+disallow_incomplete_defs = true
+disallow_subclassing_any = true
+disallow_untyped_calls = true
+disallow_untyped_decorators = true
+disallow_untyped_defs = true
+warn_return_any = true
+warn_unreachable = true
+
 [mypy-homeassistant.components.qnap_qsw.*]
 check_untyped_defs = true
 disallow_incomplete_defs = true
-- 
GitLab