mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Merge pull request #44297 from home-assistant/rc
This commit is contained in:
commit
4ec81d4b67
@ -29,3 +29,8 @@ async def async_setup_entry(hass, entry: config_entries.ConfigEntry):
|
||||
hass.config_entries.async_forward_entry_setup(entry, "media_player")
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
async def async_remove_entry(hass, entry):
|
||||
"""Remove Home Assistant Cast user."""
|
||||
await home_assistant_cast.async_remove_user(hass, entry)
|
||||
|
@ -72,3 +72,14 @@ async def async_setup_ha_cast(
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def async_remove_user(
|
||||
hass: core.HomeAssistant, entry: config_entries.ConfigEntry
|
||||
):
|
||||
"""Remove Home Assistant Cast user."""
|
||||
user_id: Optional[str] = entry.data.get("user_id")
|
||||
|
||||
if user_id is not None:
|
||||
user = await hass.auth.async_get_user(user_id)
|
||||
await hass.auth.async_remove_user(user)
|
||||
|
@ -2,7 +2,7 @@
|
||||
"domain": "dsmr",
|
||||
"name": "DSMR Slimme Meter",
|
||||
"documentation": "https://www.home-assistant.io/integrations/dsmr",
|
||||
"requirements": ["dsmr_parser==0.23"],
|
||||
"requirements": ["dsmr_parser==0.25"],
|
||||
"codeowners": ["@Robbie1221"],
|
||||
"config_flow": false
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
"domain": "enphase_envoy",
|
||||
"name": "Enphase Envoy",
|
||||
"documentation": "https://www.home-assistant.io/integrations/enphase_envoy",
|
||||
"requirements": ["envoy_reader==0.17.0"],
|
||||
"requirements": ["envoy_reader==0.17.3"],
|
||||
"codeowners": [
|
||||
"@gtdiehl"
|
||||
]
|
||||
|
@ -365,9 +365,7 @@ class InputDatetime(RestoreEntity):
|
||||
def async_set_datetime(self, date=None, time=None, datetime=None, timestamp=None):
|
||||
"""Set a new date / time."""
|
||||
if timestamp:
|
||||
datetime = dt_util.as_local(dt_util.utc_from_timestamp(timestamp)).replace(
|
||||
tzinfo=None
|
||||
)
|
||||
datetime = dt_util.as_local(dt_util.utc_from_timestamp(timestamp))
|
||||
|
||||
if datetime:
|
||||
date = datetime.date()
|
||||
@ -388,8 +386,8 @@ class InputDatetime(RestoreEntity):
|
||||
if not time:
|
||||
time = self._current_datetime.time()
|
||||
|
||||
self._current_datetime = py_datetime.datetime.combine(date, time).replace(
|
||||
tzinfo=dt_util.DEFAULT_TIME_ZONE
|
||||
self._current_datetime = dt_util.DEFAULT_TIME_ZONE.localize(
|
||||
py_datetime.datetime.combine(date, time)
|
||||
)
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/recollect_waste",
|
||||
"requirements": [
|
||||
"aiorecollect==0.2.2"
|
||||
"aiorecollect==1.0.1"
|
||||
],
|
||||
"codeowners": [
|
||||
"@bachya"
|
||||
|
@ -120,9 +120,11 @@ class RecollectWasteSensor(CoordinatorEntity):
|
||||
self._state = pickup_event.date
|
||||
self._attributes.update(
|
||||
{
|
||||
ATTR_PICKUP_TYPES: pickup_event.pickup_types,
|
||||
ATTR_PICKUP_TYPES: [t.name for t in pickup_event.pickup_types],
|
||||
ATTR_AREA_NAME: pickup_event.area_name,
|
||||
ATTR_NEXT_PICKUP_TYPES: next_pickup_event.pickup_types,
|
||||
ATTR_NEXT_PICKUP_TYPES: [
|
||||
t.name for t in next_pickup_event.pickup_types
|
||||
],
|
||||
ATTR_NEXT_PICKUP_DATE: next_date,
|
||||
}
|
||||
)
|
||||
|
@ -27,12 +27,6 @@ HOST_SCHEMA = vol.Schema({vol.Required(CONF_HOST): str})
|
||||
HTTP_CONNECT_ERRORS = (asyncio.TimeoutError, aiohttp.ClientError)
|
||||
|
||||
|
||||
def _remove_prefix(shelly_str):
|
||||
if shelly_str.startswith("shellyswitch"):
|
||||
return shelly_str[6:]
|
||||
return shelly_str
|
||||
|
||||
|
||||
async def validate_input(hass: core.HomeAssistant, host, data):
|
||||
"""Validate the user input allows us to connect.
|
||||
|
||||
@ -159,7 +153,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
self.host = zeroconf_info["host"]
|
||||
# pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167
|
||||
self.context["title_placeholders"] = {
|
||||
"name": _remove_prefix(zeroconf_info["properties"]["id"])
|
||||
"name": zeroconf_info.get("name", "").split(".")[0]
|
||||
}
|
||||
return await self.async_step_confirm_discovery()
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "Tasmota (beta)",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/tasmota",
|
||||
"requirements": ["hatasmota==0.1.4"],
|
||||
"requirements": ["hatasmota==0.1.6"],
|
||||
"dependencies": ["mqtt"],
|
||||
"mqtt": ["tasmota/discovery/#"],
|
||||
"codeowners": ["@emontnemery"]
|
||||
|
@ -89,12 +89,12 @@ class Metering(ZigbeeChannel):
|
||||
@property
|
||||
def divisor(self) -> int:
|
||||
"""Return divisor for the value."""
|
||||
return self.cluster.get("divisor")
|
||||
return self.cluster.get("divisor") or 1
|
||||
|
||||
@property
|
||||
def multiplier(self) -> int:
|
||||
"""Return multiplier for the value."""
|
||||
return self.cluster.get("multiplier")
|
||||
return self.cluster.get("multiplier") or 1
|
||||
|
||||
async def async_configure(self) -> None:
|
||||
"""Configure channel."""
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""Constants used by Home Assistant components."""
|
||||
MAJOR_VERSION = 2020
|
||||
MINOR_VERSION = 12
|
||||
PATCH_VERSION = "0"
|
||||
PATCH_VERSION = "1"
|
||||
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||
__version__ = f"{__short_version__}.{PATCH_VERSION}"
|
||||
REQUIRED_PYTHON_VER = (3, 7, 1)
|
||||
|
@ -215,7 +215,7 @@ aiopvpc==2.0.2
|
||||
aiopylgtv==0.3.3
|
||||
|
||||
# homeassistant.components.recollect_waste
|
||||
aiorecollect==0.2.2
|
||||
aiorecollect==1.0.1
|
||||
|
||||
# homeassistant.components.shelly
|
||||
aioshelly==0.5.1
|
||||
@ -508,7 +508,7 @@ doorbirdpy==2.1.0
|
||||
dovado==0.4.1
|
||||
|
||||
# homeassistant.components.dsmr
|
||||
dsmr_parser==0.23
|
||||
dsmr_parser==0.25
|
||||
|
||||
# homeassistant.components.dwd_weather_warnings
|
||||
dwdwfsapi==1.0.3
|
||||
@ -559,7 +559,7 @@ env_canada==0.2.4
|
||||
# envirophat==0.0.6
|
||||
|
||||
# homeassistant.components.enphase_envoy
|
||||
envoy_reader==0.17.0
|
||||
envoy_reader==0.17.3
|
||||
|
||||
# homeassistant.components.season
|
||||
ephem==3.7.7.0
|
||||
@ -738,7 +738,7 @@ hass-nabucasa==0.39.0
|
||||
hass_splunk==0.1.1
|
||||
|
||||
# homeassistant.components.tasmota
|
||||
hatasmota==0.1.4
|
||||
hatasmota==0.1.6
|
||||
|
||||
# homeassistant.components.jewish_calendar
|
||||
hdate==0.9.12
|
||||
|
@ -131,7 +131,7 @@ aiopvpc==2.0.2
|
||||
aiopylgtv==0.3.3
|
||||
|
||||
# homeassistant.components.recollect_waste
|
||||
aiorecollect==0.2.2
|
||||
aiorecollect==1.0.1
|
||||
|
||||
# homeassistant.components.shelly
|
||||
aioshelly==0.5.1
|
||||
@ -269,7 +269,7 @@ distro==1.5.0
|
||||
doorbirdpy==2.1.0
|
||||
|
||||
# homeassistant.components.dsmr
|
||||
dsmr_parser==0.23
|
||||
dsmr_parser==0.25
|
||||
|
||||
# homeassistant.components.dynalite
|
||||
dynalite_devices==0.1.46
|
||||
@ -376,7 +376,7 @@ hangups==0.4.11
|
||||
hass-nabucasa==0.39.0
|
||||
|
||||
# homeassistant.components.tasmota
|
||||
hatasmota==0.1.4
|
||||
hatasmota==0.1.6
|
||||
|
||||
# homeassistant.components.jewish_calendar
|
||||
hdate==0.9.12
|
||||
|
@ -1,5 +1,6 @@
|
||||
"""Test Home Assistant Cast."""
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.cast import home_assistant_cast
|
||||
from homeassistant.config import async_process_ha_core_config
|
||||
|
||||
@ -86,3 +87,32 @@ async def test_use_cloud_url(hass, mock_zeroconf):
|
||||
assert len(calls) == 1
|
||||
controller = calls[0][0]
|
||||
assert controller.hass_url == "https://something.nabu.casa"
|
||||
|
||||
|
||||
async def test_remove_entry(hass, mock_zeroconf):
|
||||
"""Test removing config entry removes user."""
|
||||
entry = MockConfigEntry(
|
||||
connection_class=config_entries.CONN_CLASS_LOCAL_PUSH,
|
||||
data={},
|
||||
domain="cast",
|
||||
title="Google Cast",
|
||||
)
|
||||
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.cast.media_player._async_setup_platform"
|
||||
), patch(
|
||||
"pychromecast.discovery.discover_chromecasts", return_value=(True, None)
|
||||
), patch(
|
||||
"pychromecast.discovery.stop_discovery"
|
||||
):
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert "cast" in hass.config.components
|
||||
|
||||
user_id = entry.data.get("user_id")
|
||||
assert await hass.auth.async_get_user(user_id)
|
||||
|
||||
assert await hass.config_entries.async_remove(entry.entry_id)
|
||||
assert not await hass.auth.async_get_user(user_id)
|
||||
|
@ -44,7 +44,7 @@ async def test_setup_provide_implementation(hass):
|
||||
"homeassistant.components.cloud.account_link._get_services",
|
||||
return_value=[
|
||||
{"service": "test", "min_version": "0.1.0"},
|
||||
{"service": "too_new", "min_version": "100.0.0"},
|
||||
{"service": "too_new", "min_version": "1000000.0.0"},
|
||||
],
|
||||
):
|
||||
assert (
|
||||
|
@ -697,6 +697,15 @@ async def test_timestamp(hass):
|
||||
).strftime(FMT_DATETIME)
|
||||
== "2020-12-13 10:00:00"
|
||||
)
|
||||
# Use datetime.datetime.fromtimestamp
|
||||
assert (
|
||||
dt_util.as_local(
|
||||
datetime.datetime.fromtimestamp(
|
||||
state_without_tz.attributes[ATTR_TIMESTAMP]
|
||||
)
|
||||
).strftime(FMT_DATETIME)
|
||||
== "2020-12-13 10:00:00"
|
||||
)
|
||||
|
||||
# Test initial time sets timestamp correctly.
|
||||
state_time = hass.states.get("input_datetime.test_time_initial")
|
||||
@ -704,5 +713,24 @@ async def test_timestamp(hass):
|
||||
assert state_time.state == "10:00:00"
|
||||
assert state_time.attributes[ATTR_TIMESTAMP] == 10 * 60 * 60
|
||||
|
||||
# Test that setting the timestamp of an entity works.
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
"set_datetime",
|
||||
{
|
||||
ATTR_ENTITY_ID: "input_datetime.test_datetime_initial_with_tz",
|
||||
ATTR_TIMESTAMP: state_without_tz.attributes[ATTR_TIMESTAMP],
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
state_with_tz_updated = hass.states.get(
|
||||
"input_datetime.test_datetime_initial_with_tz"
|
||||
)
|
||||
assert state_with_tz_updated.state == "2020-12-13 10:00:00"
|
||||
assert (
|
||||
state_with_tz_updated.attributes[ATTR_TIMESTAMP]
|
||||
== state_without_tz.attributes[ATTR_TIMESTAMP]
|
||||
)
|
||||
|
||||
finally:
|
||||
dt_util.set_default_time_zone(ORIG_TIMEZONE)
|
||||
|
@ -20,11 +20,6 @@ DISCOVERY_INFO = {
|
||||
"name": "shelly1pm-12345",
|
||||
"properties": {"id": "shelly1pm-12345"},
|
||||
}
|
||||
SWITCH25_DISCOVERY_INFO = {
|
||||
"host": "1.1.1.1",
|
||||
"name": "shellyswitch25-12345",
|
||||
"properties": {"id": "shellyswitch25-12345"},
|
||||
}
|
||||
|
||||
|
||||
async def test_form(hass):
|
||||
@ -67,7 +62,7 @@ async def test_form(hass):
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_title_without_name_and_prefix(hass):
|
||||
async def test_title_without_name(hass):
|
||||
"""Test we set the title to the hostname when the device doesn't have a name."""
|
||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
@ -330,29 +325,6 @@ async def test_zeroconf(hass):
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_zeroconf_with_switch_prefix(hass):
|
||||
"""Test we get remove shelly from the prefix."""
|
||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||
|
||||
with patch(
|
||||
"aioshelly.get_info",
|
||||
return_value={"mac": "test-mac", "type": "SHSW-1", "auth": False},
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
data=SWITCH25_DISCOVERY_INFO,
|
||||
context={"source": config_entries.SOURCE_ZEROCONF},
|
||||
)
|
||||
assert result["type"] == "form"
|
||||
assert result["errors"] == {}
|
||||
context = next(
|
||||
flow["context"]
|
||||
for flow in hass.config_entries.flow.async_progress()
|
||||
if flow["flow_id"] == result["flow_id"]
|
||||
)
|
||||
assert context["title_placeholders"]["name"] == "switch25-12345"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"error", [(asyncio.TimeoutError, "cannot_connect"), (ValueError, "unknown")]
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user