|  | 
| 5 | 5 | import json | 
| 6 | 6 | import logging | 
| 7 | 7 | import os | 
|  | 8 | +import shutil | 
| 8 | 9 | import time | 
| 9 | 10 | import traceback | 
| 10 | 11 | from typing import Any, Callable, Dict, List, Set, Union | 
|  | 
| 37 | 38 |     FOLDER, | 
| 38 | 39 |     LOGGER_PATH, | 
| 39 | 40 |     REQUIREMENTS_FILE, | 
|  | 41 | +    SERVICE_GENERATE_STUBS, | 
| 40 | 42 |     SERVICE_JUPYTER_KERNEL_START, | 
|  | 43 | +    SERVICE_RESPONSE_ONLY, | 
| 41 | 44 |     UNSUB_LISTENERS, | 
| 42 | 45 |     WATCHDOG_TASK, | 
| 43 | 46 | ) | 
|  | 
| 49 | 52 | from .mqtt import Mqtt | 
| 50 | 53 | from .requirements import install_requirements | 
| 51 | 54 | from .state import State, StateVal | 
|  | 55 | +from .stubs.generator import StubsGenerator | 
| 52 | 56 | from .trigger import TrigTime | 
| 53 | 57 | from .webhook import Webhook | 
| 54 | 58 | 
 | 
| @@ -300,6 +304,47 @@ async def reload_scripts_handler(call: ServiceCall) -> None: | 
| 300 | 304 | 
 | 
| 301 | 305 |     hass.services.async_register(DOMAIN, SERVICE_RELOAD, reload_scripts_handler) | 
| 302 | 306 | 
 | 
|  | 307 | +    async def generate_stubs_service(call: ServiceCall) -> Dict[str, Any]: | 
|  | 308 | +        """Generate pyscript IDE stub files.""" | 
|  | 309 | + | 
|  | 310 | +        generator = StubsGenerator(hass) | 
|  | 311 | +        generated_body = await generator.build() | 
|  | 312 | +        stubs_path = os.path.join(hass.config.path(FOLDER), "modules", "stubs") | 
|  | 313 | + | 
|  | 314 | +        def write_stubs(path) -> dict[str, Any]: | 
|  | 315 | +            res: dict[str, Any] = {} | 
|  | 316 | +            try: | 
|  | 317 | +                os.makedirs(path, exist_ok=True) | 
|  | 318 | + | 
|  | 319 | +                builtins_path = os.path.join(os.path.dirname(__file__), "stubs", "pyscript_builtins.py") | 
|  | 320 | +                shutil.copy2(builtins_path, path) | 
|  | 321 | + | 
|  | 322 | +                gen_path = os.path.join(path, "pyscript_generated.py") | 
|  | 323 | +                with open(gen_path, "w", encoding="utf-8") as f: | 
|  | 324 | +                    f.write(generated_body) | 
|  | 325 | +                res["status"] = "OK" | 
|  | 326 | +                return res | 
|  | 327 | +            except Exception as e: | 
|  | 328 | +                _LOGGER.exception("Stubs generation failed: %s", e) | 
|  | 329 | +                res["status"] = "Error" | 
|  | 330 | +                res["exception"] = str(e) | 
|  | 331 | +                res["message"] = "Check pyscript logs" | 
|  | 332 | +                return res | 
|  | 333 | + | 
|  | 334 | +        result = await hass.async_add_executor_job(write_stubs, stubs_path) | 
|  | 335 | + | 
|  | 336 | +        if generator.ignored_identifiers: | 
|  | 337 | +            result["ignored_identifiers"] = sorted(generator.ignored_identifiers) | 
|  | 338 | + | 
|  | 339 | +        if result["status"] == "OK": | 
|  | 340 | +            _LOGGER.info("Pyscript stubs generated to %s", stubs_path) | 
|  | 341 | + | 
|  | 342 | +        return result | 
|  | 343 | + | 
|  | 344 | +    hass.services.async_register( | 
|  | 345 | +        DOMAIN, SERVICE_GENERATE_STUBS, generate_stubs_service, supports_response=SERVICE_RESPONSE_ONLY | 
|  | 346 | +    ) | 
|  | 347 | + | 
| 303 | 348 |     async def jupyter_kernel_start(call: ServiceCall) -> None: | 
| 304 | 349 |         """Handle Jupyter kernel start call.""" | 
| 305 | 350 |         _LOGGER.debug("service call to jupyter_kernel_start: %s", call.data) | 
|  | 
0 commit comments