Fix module names for custom components (#14317)

* Fix module names for custom components

* Also set __package__ correctly

* bla

* Remove print
pull/14325/head
Paulus Schoutsen 2018-05-06 20:54:56 -04:00 committed by GitHub
parent 107769ab81
commit 34727be5ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 7 deletions

View File

@ -73,13 +73,15 @@ def get_component(hass, comp_or_platform):
# Try custom component
module = _load_module(hass.config.path(PATH_CUSTOM_COMPONENTS),
comp_or_platform)
PATH_CUSTOM_COMPONENTS, comp_or_platform)
if module is None:
try:
module = importlib.import_module(
'{}.{}'.format(PACKAGE_COMPONENTS, comp_or_platform))
_LOGGER.debug('Loaded %s (built-in)', comp_or_platform)
except ImportError:
_LOGGER.warning('Unable to find %s', comp_or_platform)
module = None
cache = hass.data.get(DATA_KEY)
@ -102,18 +104,20 @@ def _find_spec(path, name):
return None
def _load_module(path, name):
def _load_module(path, base_module, name):
"""Load a module based on a folder and a name."""
mod_name = "{}.{}".format(base_module, name)
spec = _find_spec([path], name)
# Special handling if loading platforms and the folder is a namespace
# (namespace is a folder without __init__.py)
if spec is None and '.' in name:
parent_spec = _find_spec([path], name.split('.')[0])
mod_parent_name = name.split('.')[0]
parent_spec = _find_spec([path], mod_parent_name)
if (parent_spec is None or
parent_spec.submodule_search_locations is None):
return None
spec = _find_spec(parent_spec.submodule_search_locations, name)
spec = _find_spec(parent_spec.submodule_search_locations, mod_name)
# Not found
if spec is None:
@ -123,8 +127,19 @@ def _load_module(path, name):
if spec.loader is None:
return None
_LOGGER.debug('Loaded %s (%s)', name, base_module)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# A hack, I know. Don't currently know how to work around it.
if not module.__name__.startswith(base_module):
module.__name__ = "{}.{}".format(base_module, name)
if not module.__package__:
module.__package__ = base_module
elif not module.__package__.startswith(base_module):
module.__package__ = "{}.{}".format(base_module, name)
return module

View File

@ -30,8 +30,7 @@ class TestLoader(unittest.TestCase):
comp = object()
loader.set_component(self.hass, 'switch.test_set', comp)
self.assertEqual(comp,
loader.get_component(self.hass, 'switch.test_set'))
assert loader.get_component(self.hass, 'switch.test_set') is comp
def test_get_component(self):
"""Test if get_component works."""
@ -106,3 +105,18 @@ def test_helpers_wrapper(hass):
yield from hass.async_block_till_done()
assert result == ['hello']
async def test_custom_component_name(hass):
"""Test the name attribte of custom components."""
comp = loader.get_component(hass, 'test_standalone')
assert comp.__name__ == 'custom_components.test_standalone'
assert comp.__package__ == 'custom_components'
comp = loader.get_component(hass, 'test_package')
assert comp.__name__ == 'custom_components.test_package'
assert comp.__package__ == 'custom_components.test_package'
comp = loader.get_component(hass, 'light.test')
assert comp.__name__ == 'custom_components.light.test'
assert comp.__package__ == 'custom_components.light'

View File

@ -2,6 +2,6 @@
DOMAIN = 'test_package'
def setup(hass, config):
async def async_setup(hass, config):
"""Mock a successful setup."""
return True