Merge pull request #43664 from home-assistant/rc

This commit is contained in:
Paulus Schoutsen 2020-11-26 17:42:21 +01:00 committed by GitHub
commit a15abf8802
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 87 additions and 29 deletions

View File

@ -534,7 +534,7 @@ async def _async_set_up_integrations(
_LOGGER.warning("Setup timed out for stage 1 - moving forward") _LOGGER.warning("Setup timed out for stage 1 - moving forward")
# Enables after dependencies # Enables after dependencies
async_set_domains_to_be_loaded(hass, stage_1_domains | stage_2_domains) async_set_domains_to_be_loaded(hass, stage_2_domains)
if stage_2_domains: if stage_2_domains:
_LOGGER.info("Setting up stage 2: %s", stage_2_domains) _LOGGER.info("Setting up stage 2: %s", stage_2_domains)

View File

@ -3,5 +3,5 @@
"name": "Elgato Avea", "name": "Elgato Avea",
"documentation": "https://www.home-assistant.io/integrations/avea", "documentation": "https://www.home-assistant.io/integrations/avea",
"codeowners": ["@pattyland"], "codeowners": ["@pattyland"],
"requirements": ["avea==1.5"] "requirements": ["avea==1.5.1"]
} }

View File

@ -640,7 +640,7 @@ class MqttClimate(
return self._hold return self._hold
if self._away: if self._away:
return PRESET_AWAY return PRESET_AWAY
return None return PRESET_NONE
@property @property
def preset_modes(self): def preset_modes(self):

View File

@ -56,7 +56,7 @@ def is_duplicate_owserver_entry(hass: HomeAssistantType, user_input):
if ( if (
config_entry.data[CONF_TYPE] == CONF_TYPE_OWSERVER config_entry.data[CONF_TYPE] == CONF_TYPE_OWSERVER
and config_entry.data[CONF_HOST] == user_input[CONF_HOST] and config_entry.data[CONF_HOST] == user_input[CONF_HOST]
and config_entry.data[CONF_PORT] == str(user_input[CONF_PORT]) and config_entry.data[CONF_PORT] == user_input[CONF_PORT]
): ):
return True return True
return False return False

View File

@ -11,7 +11,7 @@
"zigpy-deconz==0.11.0", "zigpy-deconz==0.11.0",
"zigpy==0.27.0", "zigpy==0.27.0",
"zigpy-xbee==0.13.0", "zigpy-xbee==0.13.0",
"zigpy-zigate==0.7.2", "zigpy-zigate==0.7.3",
"zigpy-znp==0.2.2" "zigpy-znp==0.2.2"
], ],
"codeowners": ["@dmulcahey", "@adminiuga"] "codeowners": ["@dmulcahey", "@adminiuga"]

View File

@ -1,7 +1,7 @@
"""Constants used by Home Assistant components.""" """Constants used by Home Assistant components."""
MAJOR_VERSION = 0 MAJOR_VERSION = 0
MINOR_VERSION = 118 MINOR_VERSION = 118
PATCH_VERSION = "3" PATCH_VERSION = "4"
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
__version__ = f"{__short_version__}.{PATCH_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}"
REQUIRED_PYTHON_VER = (3, 7, 1) REQUIRED_PYTHON_VER = (3, 7, 1)

View File

@ -49,6 +49,8 @@ _RENDER_INFO = "template.render_info"
_ENVIRONMENT = "template.environment" _ENVIRONMENT = "template.environment"
_RE_JINJA_DELIMITERS = re.compile(r"\{%|\{\{|\{#") _RE_JINJA_DELIMITERS = re.compile(r"\{%|\{\{|\{#")
# Match "simple" ints and floats. -1.0, 1, +5, 5.0
_IS_NUMERIC = re.compile(r"^[+-]?(?!0\d)\d*(?:\.\d*)?$")
_RESERVED_NAMES = {"contextfunction", "evalcontextfunction", "environmentfunction"} _RESERVED_NAMES = {"contextfunction", "evalcontextfunction", "environmentfunction"}
@ -373,7 +375,19 @@ class Template:
# render, by not returning right here. The evaluation of strings # render, by not returning right here. The evaluation of strings
# resulting in strings impacts quotes, to avoid unexpected # resulting in strings impacts quotes, to avoid unexpected
# output; use the original render instead of the evaluated one. # output; use the original render instead of the evaluated one.
if not isinstance(result, str): # Complex and scientific values are also unexpected. Filter them out.
if (
# Filter out string and complex numbers
not isinstance(result, (str, complex))
and (
# Pass if not numeric and not a boolean
not isinstance(result, (int, float))
# Or it's a boolean (inherit from int)
or isinstance(result, bool)
# Or if it's a digit
or _IS_NUMERIC.match(render_result) is not None
)
):
return result return result
except (ValueError, TypeError, SyntaxError, MemoryError): except (ValueError, TypeError, SyntaxError, MemoryError):
pass pass

View File

@ -303,7 +303,7 @@ aurorapy==0.2.6
av==8.0.2 av==8.0.2
# homeassistant.components.avea # homeassistant.components.avea
# avea==1.5 # avea==1.5.1
# homeassistant.components.avion # homeassistant.components.avion
# avion==0.10 # avion==0.10
@ -2353,7 +2353,7 @@ zigpy-deconz==0.11.0
zigpy-xbee==0.13.0 zigpy-xbee==0.13.0
# homeassistant.components.zha # homeassistant.components.zha
zigpy-zigate==0.7.2 zigpy-zigate==0.7.3
# homeassistant.components.zha # homeassistant.components.zha
zigpy-znp==0.2.2 zigpy-znp==0.2.2

View File

@ -1131,7 +1131,7 @@ zigpy-deconz==0.11.0
zigpy-xbee==0.13.0 zigpy-xbee==0.13.0
# homeassistant.components.zha # homeassistant.components.zha
zigpy-zigate==0.7.2 zigpy-zigate==0.7.3
# homeassistant.components.zha # homeassistant.components.zha
zigpy-znp==0.2.2 zigpy-znp==0.2.2

View File

@ -438,11 +438,11 @@ async def test_set_away_mode_pessimistic(hass, mqtt_mock):
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get(ENTITY_CLIMATE) state = hass.states.get(ENTITY_CLIMATE)
assert state.attributes.get("preset_mode") is None assert state.attributes.get("preset_mode") == "none"
await common.async_set_preset_mode(hass, "away", ENTITY_CLIMATE) await common.async_set_preset_mode(hass, "away", ENTITY_CLIMATE)
state = hass.states.get(ENTITY_CLIMATE) state = hass.states.get(ENTITY_CLIMATE)
assert state.attributes.get("preset_mode") is None assert state.attributes.get("preset_mode") == "none"
async_fire_mqtt_message(hass, "away-state", "ON") async_fire_mqtt_message(hass, "away-state", "ON")
state = hass.states.get(ENTITY_CLIMATE) state = hass.states.get(ENTITY_CLIMATE)
@ -450,11 +450,11 @@ async def test_set_away_mode_pessimistic(hass, mqtt_mock):
async_fire_mqtt_message(hass, "away-state", "OFF") async_fire_mqtt_message(hass, "away-state", "OFF")
state = hass.states.get(ENTITY_CLIMATE) state = hass.states.get(ENTITY_CLIMATE)
assert state.attributes.get("preset_mode") is None assert state.attributes.get("preset_mode") == "none"
async_fire_mqtt_message(hass, "away-state", "nonsense") async_fire_mqtt_message(hass, "away-state", "nonsense")
state = hass.states.get(ENTITY_CLIMATE) state = hass.states.get(ENTITY_CLIMATE)
assert state.attributes.get("preset_mode") is None assert state.attributes.get("preset_mode") == "none"
async def test_set_away_mode(hass, mqtt_mock): async def test_set_away_mode(hass, mqtt_mock):
@ -467,7 +467,7 @@ async def test_set_away_mode(hass, mqtt_mock):
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get(ENTITY_CLIMATE) state = hass.states.get(ENTITY_CLIMATE)
assert state.attributes.get("preset_mode") is None assert state.attributes.get("preset_mode") == "none"
await common.async_set_preset_mode(hass, "away", ENTITY_CLIMATE) await common.async_set_preset_mode(hass, "away", ENTITY_CLIMATE)
mqtt_mock.async_publish.assert_called_once_with("away-mode-topic", "AN", 0, False) mqtt_mock.async_publish.assert_called_once_with("away-mode-topic", "AN", 0, False)
mqtt_mock.async_publish.reset_mock() mqtt_mock.async_publish.reset_mock()
@ -477,7 +477,7 @@ async def test_set_away_mode(hass, mqtt_mock):
await common.async_set_preset_mode(hass, PRESET_NONE, ENTITY_CLIMATE) await common.async_set_preset_mode(hass, PRESET_NONE, ENTITY_CLIMATE)
mqtt_mock.async_publish.assert_called_once_with("away-mode-topic", "AUS", 0, False) mqtt_mock.async_publish.assert_called_once_with("away-mode-topic", "AUS", 0, False)
state = hass.states.get(ENTITY_CLIMATE) state = hass.states.get(ENTITY_CLIMATE)
assert state.attributes.get("preset_mode") is None assert state.attributes.get("preset_mode") == "none"
await common.async_set_preset_mode(hass, "hold-on", ENTITY_CLIMATE) await common.async_set_preset_mode(hass, "hold-on", ENTITY_CLIMATE)
mqtt_mock.async_publish.reset_mock() mqtt_mock.async_publish.reset_mock()
@ -525,7 +525,7 @@ async def test_set_hold_pessimistic(hass, mqtt_mock):
async_fire_mqtt_message(hass, "hold-state", "off") async_fire_mqtt_message(hass, "hold-state", "off")
state = hass.states.get(ENTITY_CLIMATE) state = hass.states.get(ENTITY_CLIMATE)
assert state.attributes.get("preset_mode") is None assert state.attributes.get("preset_mode") == "none"
async def test_set_hold(hass, mqtt_mock): async def test_set_hold(hass, mqtt_mock):
@ -534,7 +534,7 @@ async def test_set_hold(hass, mqtt_mock):
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get(ENTITY_CLIMATE) state = hass.states.get(ENTITY_CLIMATE)
assert state.attributes.get("preset_mode") is None assert state.attributes.get("preset_mode") == "none"
await common.async_set_preset_mode(hass, "hold-on", ENTITY_CLIMATE) await common.async_set_preset_mode(hass, "hold-on", ENTITY_CLIMATE)
mqtt_mock.async_publish.assert_called_once_with("hold-topic", "hold-on", 0, False) mqtt_mock.async_publish.assert_called_once_with("hold-topic", "hold-on", 0, False)
mqtt_mock.async_publish.reset_mock() mqtt_mock.async_publish.reset_mock()
@ -550,7 +550,7 @@ async def test_set_hold(hass, mqtt_mock):
await common.async_set_preset_mode(hass, PRESET_NONE, ENTITY_CLIMATE) await common.async_set_preset_mode(hass, PRESET_NONE, ENTITY_CLIMATE)
mqtt_mock.async_publish.assert_called_once_with("hold-topic", "off", 0, False) mqtt_mock.async_publish.assert_called_once_with("hold-topic", "off", 0, False)
state = hass.states.get(ENTITY_CLIMATE) state = hass.states.get(ENTITY_CLIMATE)
assert state.attributes.get("preset_mode") is None assert state.attributes.get("preset_mode") == "none"
async def test_set_preset_mode_twice(hass, mqtt_mock): async def test_set_preset_mode_twice(hass, mqtt_mock):
@ -559,7 +559,7 @@ async def test_set_preset_mode_twice(hass, mqtt_mock):
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get(ENTITY_CLIMATE) state = hass.states.get(ENTITY_CLIMATE)
assert state.attributes.get("preset_mode") is None assert state.attributes.get("preset_mode") == "none"
await common.async_set_preset_mode(hass, "hold-on", ENTITY_CLIMATE) await common.async_set_preset_mode(hass, "hold-on", ENTITY_CLIMATE)
mqtt_mock.async_publish.assert_called_once_with("hold-topic", "hold-on", 0, False) mqtt_mock.async_publish.assert_called_once_with("hold-topic", "hold-on", 0, False)
mqtt_mock.async_publish.reset_mock() mqtt_mock.async_publish.reset_mock()
@ -735,7 +735,7 @@ async def test_set_with_templates(hass, mqtt_mock, caplog):
assert state.attributes.get("temperature") == 1031 assert state.attributes.get("temperature") == 1031
# Away Mode # Away Mode
assert state.attributes.get("preset_mode") is None assert state.attributes.get("preset_mode") == "none"
async_fire_mqtt_message(hass, "away-state", '"ON"') async_fire_mqtt_message(hass, "away-state", '"ON"')
state = hass.states.get(ENTITY_CLIMATE) state = hass.states.get(ENTITY_CLIMATE)
assert state.attributes.get("preset_mode") == "away" assert state.attributes.get("preset_mode") == "away"
@ -743,7 +743,7 @@ async def test_set_with_templates(hass, mqtt_mock, caplog):
# Away Mode with JSON values # Away Mode with JSON values
async_fire_mqtt_message(hass, "away-state", "false") async_fire_mqtt_message(hass, "away-state", "false")
state = hass.states.get(ENTITY_CLIMATE) state = hass.states.get(ENTITY_CLIMATE)
assert state.attributes.get("preset_mode") is None assert state.attributes.get("preset_mode") == "none"
async_fire_mqtt_message(hass, "away-state", "true") async_fire_mqtt_message(hass, "away-state", "true")
state = hass.states.get(ENTITY_CLIMATE) state = hass.states.get(ENTITY_CLIMATE)

View File

@ -48,9 +48,8 @@ async def setup_onewire_owserver_integration(hass):
data={ data={
CONF_TYPE: CONF_TYPE_OWSERVER, CONF_TYPE: CONF_TYPE_OWSERVER,
CONF_HOST: "1.2.3.4", CONF_HOST: "1.2.3.4",
CONF_PORT: "1234", CONF_PORT: 1234,
}, },
unique_id=f"{CONF_TYPE_OWSERVER}:1.2.3.4:1234",
connection_class=CONN_CLASS_LOCAL_POLL, connection_class=CONN_CLASS_LOCAL_POLL,
options={}, options={},
entry_id="2", entry_id="2",
@ -74,12 +73,11 @@ async def setup_onewire_patched_owserver_integration(hass):
data={ data={
CONF_TYPE: CONF_TYPE_OWSERVER, CONF_TYPE: CONF_TYPE_OWSERVER,
CONF_HOST: "1.2.3.4", CONF_HOST: "1.2.3.4",
CONF_PORT: "1234", CONF_PORT: 1234,
CONF_NAMES: { CONF_NAMES: {
"10.111111111111": "My DS18B20", "10.111111111111": "My DS18B20",
}, },
}, },
unique_id=f"{CONF_TYPE_OWSERVER}:1.2.3.4:1234",
connection_class=CONN_CLASS_LOCAL_POLL, connection_class=CONN_CLASS_LOCAL_POLL,
options={}, options={},
entry_id="2", entry_id="2",

View File

@ -318,7 +318,7 @@ async def test_import_owserver_with_port(hass):
data={ data={
CONF_TYPE: CONF_TYPE_OWSERVER, CONF_TYPE: CONF_TYPE_OWSERVER,
CONF_HOST: "1.2.3.4", CONF_HOST: "1.2.3.4",
CONF_PORT: "1234", CONF_PORT: 1234,
}, },
) )
assert result["type"] == RESULT_TYPE_CREATE_ENTRY assert result["type"] == RESULT_TYPE_CREATE_ENTRY
@ -326,8 +326,37 @@ async def test_import_owserver_with_port(hass):
assert result["data"] == { assert result["data"] == {
CONF_TYPE: CONF_TYPE_OWSERVER, CONF_TYPE: CONF_TYPE_OWSERVER,
CONF_HOST: "1.2.3.4", CONF_HOST: "1.2.3.4",
CONF_PORT: "1234", CONF_PORT: 1234,
} }
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(mock_setup.mock_calls) == 1 assert len(mock_setup.mock_calls) == 1
assert len(mock_setup_entry.mock_calls) == 1 assert len(mock_setup_entry.mock_calls) == 1
async def test_import_owserver_duplicate(hass):
"""Test OWServer flow."""
# Initialise with single entry
with patch(
"homeassistant.components.onewire.async_setup", return_value=True
) as mock_setup, patch(
"homeassistant.components.onewire.async_setup_entry",
return_value=True,
) as mock_setup_entry:
await setup_onewire_owserver_integration(hass)
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
# Import duplicate entry
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_IMPORT},
data={
CONF_TYPE: CONF_TYPE_OWSERVER,
CONF_HOST: "1.2.3.4",
CONF_PORT: 1234,
},
)
assert result["type"] == RESULT_TYPE_ABORT
assert result["reason"] == "already_configured"
await hass.async_block_till_done()
assert len(mock_setup.mock_calls) == 1
assert len(mock_setup_entry.mock_calls) == 1

View File

@ -346,7 +346,7 @@ def test_tan(hass):
(0, 0.0), (0, 0.0),
(math.pi, -0.0), (math.pi, -0.0),
(math.pi / 180 * 45, 1.0), (math.pi / 180 * 45, 1.0),
(math.pi / 180 * 90, 1.633123935319537e16), (math.pi / 180 * 90, "1.633123935319537e+16"),
(math.pi / 180 * 135, -1.0), (math.pi / 180 * 135, -1.0),
("'error'", "error"), ("'error'", "error"),
] ]
@ -2416,5 +2416,22 @@ async def test_parse_result(hass):
('{{ "{{}}" }}', "{{}}"), ('{{ "{{}}" }}', "{{}}"),
("not-something", "not-something"), ("not-something", "not-something"),
("2a", "2a"), ("2a", "2a"),
("123E5", "123E5"),
("1j", "1j"),
("1e+100", "1e+100"),
("0xface", "0xface"),
("123", 123),
("10", 10),
("123.0", 123.0),
(".5", 0.5),
("0.5", 0.5),
("-1", -1),
("-1.0", -1.0),
("+1", 1),
("5.", 5.0),
("123_123_123", "123_123_123"),
# ("+48100200300", "+48100200300"), # phone number
("010", "010"),
("0011101.00100001010001", "0011101.00100001010001"),
): ):
assert template.Template(tpl, hass).async_render() == result assert template.Template(tpl, hass).async_render() == result