#! /usr/bin/env python
"""Utility functions for loading components for The Landlab."""
import os
from landlab.framework.interfaces import BmiBase
_COMPONENT_PATH = [os.path.join(os.path.dirname(__file__), "..", "components")]
try:
paths = os.environ["LANDLAB_PATH"].split(os.pathsep)
except KeyError:
pass
else:
_COMPONENT_PATH = paths + _COMPONENT_PATH
[docs]
def iscomponent(value, cls):
"""Check if *value* is a component for The Landlab. *value* is a component
if it implements the *cls* or it is an instance of *cls*.
Returns ``True`` if *value* is a component, otherwise ``False``.
"""
try:
return (
cls in value.__implements__
or cls.__name__ in value.__implements__
or isinstance(value, cls)
)
except AttributeError:
return False
[docs]
def load_components_from_dir(path, cls):
"""Look for components for Landlab in *path*.
Identify components as being an instance of *cls*. Returns a
dictionary of discovered component names as keys and component
classes as values.
"""
import imp
import sys
components = {}
sys.path.insert(0, path)
cwd = os.getcwd()
os.chdir(path)
for file_name in os.listdir("."):
if os.path.isfile(file_name) and file_name.endswith(".py"):
(mod_name, _) = os.path.splitext(file_name)
mod = imp.load_module(mod_name, *imp.find_module(mod_name))
for name, value in mod.__dict__.items():
if iscomponent(value, cls):
components[name] = value
os.chdir(cwd)
sys.path.pop(0)
return components
[docs]
def load_components(cls, paths=None):
"""Load components from a series of directories.
Components found earlier in the search path order override those
discovered later. Use the *paths* keyword to specify a list of paths to
search for components.
.. seealso::
:func:`load_components_from_dir`
"""
if not paths:
paths = _COMPONENT_PATH
components = {}
for path in paths[::-1]:
components.update(load_components_from_dir(path, cls))
return components
[docs]
def load_landlab_components(paths=None):
"""Load components for The Landlab. These are classes that implement
BmiBase. See :func:`load_components_from_dir` for the meaning of *paths*
keyword.
.. seealso::
:func:`load_components_from_dir`
"""
return load_components(BmiBase, paths=paths)