mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 00:37:53 +00:00
Add new Remote Python Debugger integration (#36960)
This commit is contained in:
parent
9d40ae96b5
commit
b47be05efc
@ -86,6 +86,7 @@ homeassistant/components/cpuspeed/* @fabaff
|
||||
homeassistant/components/cups/* @fabaff
|
||||
homeassistant/components/daikin/* @fredrike
|
||||
homeassistant/components/darksky/* @fabaff
|
||||
homeassistant/components/debugpy/* @frenck
|
||||
homeassistant/components/deconz/* @Kane610
|
||||
homeassistant/components/delijn/* @bollewolle @Emilv2
|
||||
homeassistant/components/demo/* @home-assistant/core
|
||||
|
@ -40,7 +40,7 @@ DATA_LOGGING = "logging"
|
||||
|
||||
LOG_SLOW_STARTUP_INTERVAL = 60
|
||||
|
||||
DEBUGGER_INTEGRATIONS = {"ptvsd"}
|
||||
DEBUGGER_INTEGRATIONS = {"debugpy", "ptvsd"}
|
||||
CORE_INTEGRATIONS = ("homeassistant", "persistent_notification")
|
||||
LOGGING_INTEGRATIONS = {
|
||||
# Set log levels
|
||||
|
79
homeassistant/components/debugpy/__init__.py
Normal file
79
homeassistant/components/debugpy/__init__.py
Normal file
@ -0,0 +1,79 @@
|
||||
"""The Remote Python Debugger integration."""
|
||||
from asyncio import Event
|
||||
import logging
|
||||
from threading import Thread
|
||||
from typing import Optional
|
||||
|
||||
import debugpy
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.service import async_register_admin_service
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
DOMAIN = "debugpy"
|
||||
CONF_WAIT = "wait"
|
||||
CONF_START = "start"
|
||||
SERVICE_START = "start"
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
DOMAIN: vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_HOST, default="0.0.0.0"): cv.string,
|
||||
vol.Optional(CONF_PORT, default=5678): cv.port,
|
||||
vol.Optional(CONF_START, default=True): cv.boolean,
|
||||
vol.Optional(CONF_WAIT, default=False): cv.boolean,
|
||||
}
|
||||
)
|
||||
},
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"""Set up the Remote Python Debugger component."""
|
||||
conf = config[DOMAIN]
|
||||
|
||||
async def debug_start(
|
||||
call: Optional[ServiceCall] = None, *, wait: bool = True
|
||||
) -> None:
|
||||
"""Start the debugger."""
|
||||
debugpy.listen((conf[CONF_HOST], conf[CONF_PORT]))
|
||||
|
||||
wait = conf[CONF_WAIT]
|
||||
if wait:
|
||||
_LOGGER.warning(
|
||||
"Waiting for remote debug connection on %s:%s",
|
||||
conf[CONF_HOST],
|
||||
conf[CONF_PORT],
|
||||
)
|
||||
ready = Event()
|
||||
|
||||
def waitfor():
|
||||
debugpy.wait_for_client()
|
||||
hass.loop.call_soon_threadsafe(ready.set)
|
||||
|
||||
Thread(target=waitfor).start()
|
||||
|
||||
await ready.wait()
|
||||
else:
|
||||
_LOGGER.warning(
|
||||
"Listening for remote debug connection on %s:%s",
|
||||
conf[CONF_HOST],
|
||||
conf[CONF_PORT],
|
||||
)
|
||||
|
||||
async_register_admin_service(
|
||||
hass, DOMAIN, SERVICE_START, debug_start, schema=vol.Schema({})
|
||||
)
|
||||
|
||||
# If set to start the debugger on startup, do so
|
||||
if conf[CONF_START]:
|
||||
await debug_start(wait=conf[CONF_WAIT])
|
||||
|
||||
return True
|
8
homeassistant/components/debugpy/manifest.json
Normal file
8
homeassistant/components/debugpy/manifest.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"domain": "debugpy",
|
||||
"name": "Remote Python Debugger",
|
||||
"documentation": "https://www.home-assistant.io/integrations/debugpy",
|
||||
"requirements": ["debugpy==1.0.0b11"],
|
||||
"codeowners": ["@frenck"],
|
||||
"quality_scale": "internal"
|
||||
}
|
3
homeassistant/components/debugpy/services.yaml
Normal file
3
homeassistant/components/debugpy/services.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
# Describes the format for available Remote Python Debugger services
|
||||
start:
|
||||
description: Start the Remote Python Debugger.
|
@ -456,6 +456,9 @@ datadog==0.15.0
|
||||
# homeassistant.components.metoffice
|
||||
datapoint==0.9.5
|
||||
|
||||
# homeassistant.components.debugpy
|
||||
debugpy==1.0.0b11
|
||||
|
||||
# homeassistant.components.decora
|
||||
# decora==0.6
|
||||
|
||||
|
@ -211,6 +211,9 @@ datadog==0.15.0
|
||||
# homeassistant.components.metoffice
|
||||
datapoint==0.9.5
|
||||
|
||||
# homeassistant.components.debugpy
|
||||
debugpy==1.0.0b11
|
||||
|
||||
# homeassistant.components.ihc
|
||||
# homeassistant.components.namecheapdns
|
||||
# homeassistant.components.ohmconnect
|
||||
|
1
tests/components/debugpy/__init__.py
Normal file
1
tests/components/debugpy/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""Tests for the Remote Python Debugger integration."""
|
61
tests/components/debugpy/test_init.py
Normal file
61
tests/components/debugpy/test_init.py
Normal file
@ -0,0 +1,61 @@
|
||||
"""Tests for the Remote Python Debugger integration."""
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.debugpy import (
|
||||
CONF_HOST,
|
||||
CONF_PORT,
|
||||
CONF_START,
|
||||
CONF_WAIT,
|
||||
DOMAIN,
|
||||
SERVICE_START,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.async_mock import patch
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_debugpy():
|
||||
"""Mock debugpy lib."""
|
||||
with patch("homeassistant.components.debugpy.debugpy") as mocked_debugpy:
|
||||
yield mocked_debugpy
|
||||
|
||||
|
||||
async def test_default(hass: HomeAssistant, mock_debugpy) -> None:
|
||||
"""Test if the default settings work."""
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
|
||||
|
||||
mock_debugpy.listen.assert_called_once_with(("0.0.0.0", 5678))
|
||||
mock_debugpy.wait_for_client.assert_not_called()
|
||||
assert len(mock_debugpy.method_calls) == 1
|
||||
|
||||
|
||||
async def test_wait_on_startup(hass: HomeAssistant, mock_debugpy) -> None:
|
||||
"""Test if the waiting for client is called."""
|
||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_WAIT: True}})
|
||||
|
||||
mock_debugpy.listen.assert_called_once_with(("0.0.0.0", 5678))
|
||||
mock_debugpy.wait_for_client.assert_called_once()
|
||||
assert len(mock_debugpy.method_calls) == 2
|
||||
|
||||
|
||||
async def test_on_demand(hass: HomeAssistant, mock_debugpy) -> None:
|
||||
"""Test on-demand debugging using a service call."""
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
DOMAIN,
|
||||
{DOMAIN: {CONF_START: False, CONF_HOST: "127.0.0.1", CONF_PORT: 80}},
|
||||
)
|
||||
|
||||
mock_debugpy.listen.assert_not_called()
|
||||
mock_debugpy.wait_for_client.assert_not_called()
|
||||
assert len(mock_debugpy.method_calls) == 0
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_START, blocking=True,
|
||||
)
|
||||
|
||||
mock_debugpy.listen.assert_called_once_with(("127.0.0.1", 80))
|
||||
mock_debugpy.wait_for_client.assert_not_called()
|
||||
assert len(mock_debugpy.method_calls) == 1
|
Loading…
x
Reference in New Issue
Block a user