From e487a09190df1f1325ca583896d4b785ed92c623 Mon Sep 17 00:00:00 2001 From: Johann Kellerman Date: Wed, 2 Nov 2016 06:51:31 +0200 Subject: [PATCH] Remove None value before writing known_devices (#4098) * Remove None * Replace null --- .../components/device_tracker/__init__.py | 7 +++--- homeassistant/util/yaml.py | 6 +++++ tests/util/test_yaml.py | 23 ++++++++++++------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/device_tracker/__init__.py b/homeassistant/components/device_tracker/__init__.py index b7f4e839d7b..c87af93eeb5 100644 --- a/homeassistant/components/device_tracker/__init__.py +++ b/homeassistant/components/device_tracker/__init__.py @@ -12,7 +12,6 @@ import threading from typing import Any, Sequence, Callable import voluptuous as vol -import yaml from homeassistant.bootstrap import ( prepare_setup_platform, log_exception) @@ -27,6 +26,7 @@ import homeassistant.helpers.config_validation as cv import homeassistant.util as util from homeassistant.util.async import run_coroutine_threadsafe import homeassistant.util.dt as dt_util +from homeassistant.util.yaml import dump from homeassistant.helpers.event import track_utc_time_change from homeassistant.const import ( @@ -464,8 +464,6 @@ def setup_scanner_platform(hass: HomeAssistantType, config: ConfigType, def update_config(path: str, dev_id: str, device: Device): """Add device to YAML configuration file.""" with open(path, 'a') as out: - out.write('\n') - device = {device.dev_id: { 'name': device.name, 'mac': device.mac, @@ -473,7 +471,8 @@ def update_config(path: str, dev_id: str, device: Device): 'track': device.track, CONF_AWAY_HIDE: device.away_hide }} - yaml.dump(device, out, default_flow_style=False) + out.write('\n') + out.write(dump(device)) def get_gravatar_for_email(email: str): diff --git a/homeassistant/util/yaml.py b/homeassistant/util/yaml.py index 4a73ac7c8dd..a91130338f5 100644 --- a/homeassistant/util/yaml.py +++ b/homeassistant/util/yaml.py @@ -48,6 +48,12 @@ def load_yaml(fname: str) -> Union[List, Dict]: raise HomeAssistantError(exc) +def dump(_dict: dict) -> str: + """Dump yaml to a string and remove null.""" + return yaml.safe_dump(_dict, default_flow_style=False) \ + .replace(': null\n', ':\n') + + def clear_secret_cache() -> None: """Clear the secret cache. diff --git a/tests/util/test_yaml.py b/tests/util/test_yaml.py index 11a006524a9..3305fbea6c9 100644 --- a/tests/util/test_yaml.py +++ b/tests/util/test_yaml.py @@ -1,7 +1,7 @@ """Test Home Assistant yaml loader.""" import io -import unittest import os +import unittest from unittest.mock import patch from homeassistant.exceptions import HomeAssistantError @@ -12,6 +12,7 @@ from tests.common import get_test_config_dir, patch_yaml_files class TestYaml(unittest.TestCase): """Test util.yaml loader.""" + # pylint: disable=no-self-use, invalid-name def test_simple_list(self): @@ -196,10 +197,12 @@ class TestYaml(unittest.TestCase): """Test include dir merge named yaml.""" mock_walk.return_value = [['/tmp', [], ['first.yaml', 'second.yaml']]] - with patch_yaml_files({ - '/tmp/first.yaml': 'key1: one', - '/tmp/second.yaml': 'key2: two\nkey3: three' - }): + files = { + '/tmp/first.yaml': 'key1: one', + '/tmp/second.yaml': 'key2: two\nkey3: three', + } + + with patch_yaml_files(files): conf = "key: !include_dir_merge_named /tmp" with io.StringIO(conf) as file: doc = yaml.yaml.safe_load(file) @@ -243,6 +246,10 @@ class TestYaml(unittest.TestCase): mock_open.side_effect = UnicodeDecodeError('', b'', 1, 0, '') self.assertRaises(HomeAssistantError, yaml.load_yaml, 'test') + def test_dump(self): + """The that the dump method returns empty None values.""" + assert yaml.dump({'a': None, 'b': 'b'}) == 'a:\nb: b\n' + FILES = {} @@ -270,9 +277,10 @@ class FakeKeyring(): class TestSecrets(unittest.TestCase): """Test the secrets parameter in the yaml utility.""" - # pylint: disable=protected-access, invalid-name - def setUp(self): # pylint: disable=invalid-name + # pylint: disable=protected-access,invalid-name + + def setUp(self): """Create & load secrets file.""" config_dir = get_test_config_dir() yaml.clear_secret_cache() @@ -295,7 +303,6 @@ class TestSecrets(unittest.TestCase): ' password: !secret comp1_pw\n' '') - # pylint: disable=invalid-name def tearDown(self): """Clean up secrets.""" yaml.clear_secret_cache()