# Buggy code
def merge_packages_config(hass, config, packages, _log_pkg_error=_log_pkg_error):
    """Merge packages into the top-level configuration. Mutate config."""
    # pylint: disable=too-many-nested-blocks
    PACKAGES_CONFIG_SCHEMA(packages)
    for pack_name, pack_conf in packages.items():
        for comp_name, comp_conf in pack_conf.items():
            if comp_name == CONF_CORE:
                continue
            component = get_component(hass, comp_name)

            if component is None:
                _log_pkg_error(pack_name, comp_name, config, "does not exist")
                continue

            if hasattr(component, "PLATFORM_SCHEMA"):
                if not comp_conf:
                    continue  # Ensure we dont add Falsy items to list
                config[comp_name] = cv.ensure_list(config.get(comp_name))
                config[comp_name].extend(cv.ensure_list(comp_conf))
                continue

            if hasattr(component, "CONFIG_SCHEMA"):
                merge_type, _ = _identify_config_schema(component)

                if merge_type == "list":
                    if not comp_conf:
                        continue  # Ensure we dont add Falsy items to list
                    config[comp_name] = cv.ensure_list(config.get(comp_name))
                    config[comp_name].extend(cv.ensure_list(comp_conf))
                    continue

                if merge_type == "dict":
                    if comp_conf is None:
                        comp_conf = OrderedDict()

                    if not isinstance(comp_conf, dict):
                        _log_pkg_error(
                            pack_name,
                            comp_name,
                            config,
                            "cannot be merged. Expected a dict.",
                        )
                        continue

                    if comp_name not in config:
                        config[comp_name] = OrderedDict()

                    if not isinstance(config[comp_name], dict):
                        _log_pkg_error(
                            pack_name,
                            comp_name,
                            config,
                            "cannot be merged. Dict expected in main config.",
                        )
                        continue

                    for key, val in comp_conf.items():
                        if key in config[comp_name]:
                            _log_pkg_error(
                                pack_name,
                                comp_name,
                                config,
                                "duplicate key '{}'".format(key),
                            )
                            continue
                        config[comp_name][key] = val
                    continue

            # The last merge type are sections that require recursive merging
            if comp_name in config:
                _recursive_merge(
                    pack_name,
                    comp_name,
                    config,
                    conf=config[comp_name],
                    package=comp_conf,
                )
                continue
            config[comp_name] = comp_conf

    return config


# Traceback (AttributeError)
2018-06-10 00:27:15 INFO (SyncWorker_0) [homeassistant.config] Upgrading configuration directory from 0.70.1 to 0.71.0
2018-06-10 00:27:15 INFO (SyncWorker_0) [homeassistant.config] Migrating old system configuration files to new locations
2018-06-10 00:27:15 INFO (MainThread) [homeassistant.loader] Loaded device_tracker from homeassistant.components.device_tracker
2018-06-10 00:27:15 INFO (MainThread) [homeassistant.loader] Loaded sensor from homeassistant.components.sensor
2018-06-10 00:27:15 INFO (MainThread) [homeassistant.loader] Loaded automation from homeassistant.components.automation
2018-06-10 00:27:15 INFO (MainThread) [homeassistant.loader] Loaded map from homeassistant.components.map
Traceback (most recent call last):
File "/usr/local/lib/python3.6/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/local/lib/python3.6/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/usr/src/app/homeassistant/__main__.py", line 377, in <module>
sys.exit(main())
File "/usr/src/app/homeassistant/__main__.py", line 369, in main
exit_code = setup_and_run_hass(config_dir, args)
File "/usr/src/app/homeassistant/__main__.py", line 274, in setup_and_run_hass
log_no_color=args.log_no_color)
File "/usr/src/app/homeassistant/bootstrap.py", line 179, in from_config_file
log_rotate_days, log_file, log_no_color)
File "uvloop/loop.pyx", line 1422, in uvloop.loop.Loop.run_until_complete
File "/usr/src/app/homeassistant/bootstrap.py", line 215, in async_from_config_file
config_dict, hass, enable_log=False, skip_pip=skip_pip)
File "/usr/src/app/homeassistant/bootstrap.py", line 110, in async_from_config_dict
hass, config, core_config.get(conf_util.CONF_PACKAGES, {}))
File "/usr/src/app/homeassistant/config.py", line 638, in merge_packages_config
conf=config[comp_name], package=comp_conf)
File "/usr/src/app/homeassistant/config.py", line 553, in _recursive_merge
for key, pack_conf in package.items():
AttributeError: 'NoneType' object has no attribute 'items'

# Fixed code
def merge_packages_config(hass, config, packages, _log_pkg_error=_log_pkg_error):
    """Merge packages into the top-level configuration. Mutate config."""
    # pylint: disable=too-many-nested-blocks
    PACKAGES_CONFIG_SCHEMA(packages)
    for pack_name, pack_conf in packages.items():
        for comp_name, comp_conf in pack_conf.items():
            if comp_name == CONF_CORE:
                continue
            component = get_component(hass, comp_name)

            if component is None:
                _log_pkg_error(pack_name, comp_name, config, "does not exist")
                continue

            if hasattr(component, "PLATFORM_SCHEMA"):
                if not comp_conf:
                    continue  # Ensure we dont add Falsy items to list
                config[comp_name] = cv.ensure_list(config.get(comp_name))
                config[comp_name].extend(cv.ensure_list(comp_conf))
                continue

            if hasattr(component, "CONFIG_SCHEMA"):
                merge_type, _ = _identify_config_schema(component)

                if merge_type == "list":
                    if not comp_conf:
                        continue  # Ensure we dont add Falsy items to list
                    config[comp_name] = cv.ensure_list(config.get(comp_name))
                    config[comp_name].extend(cv.ensure_list(comp_conf))
                    continue

            if comp_conf is None:
                comp_conf = OrderedDict()

            if not isinstance(comp_conf, dict):
                _log_pkg_error(
                    pack_name, comp_name, config, "cannot be merged. Expected a dict."
                )
                continue

            if comp_name not in config or config[comp_name] is None:
                config[comp_name] = OrderedDict()

            if not isinstance(config[comp_name], dict):
                _log_pkg_error(
                    pack_name,
                    comp_name,
                    config,
                    "cannot be merged. Dict expected in main config.",
                )
                continue
            if not isinstance(comp_conf, dict):
                _log_pkg_error(
                    pack_name,
                    comp_name,
                    config,
                    "cannot be merged. Dict expected in package.",
                )
                continue

            error = _recursive_merge(conf=config[comp_name], package=comp_conf)
            if error:
                _log_pkg_error(
                    pack_name, comp_name, config, "has duplicate key '{}'".format(error)
                )

    return config