Source code for BondGraphTools.component_manager

"""Component Libraries.

This module takes care of the loading and management of component libraries.
This library will automatically load all factory libraries upon import.
Additionally libraries can be added via :func:`load_library`.

Component Libraries are expected to be in json format.
The structure must be::

    {
        "id": The unique library id (str),
        "description": The description of this library
        "components": {
            "component_id": component dictionary,
            ...
        }
    }

Each Component dictionary must be of the form::

    {

    }
"""
import copy
import json
import pathlib
import os
import logging

logger = logging.getLogger(__name__)

__dir, _ = os.path.split(__file__)
__LIB_DIR = os.path.join(__dir, "components")
__libraries = dict()
base_id = "base"


[docs]def load_library(filename): """Load the library specified by the filename. Args: filename: The (absolute) filename of the library to be loaded. Returns: bool: True if the library was successfully loaded. """ with open(filename) as file: try: lib = json.load(file) lib_id = lib["id"] del lib["id"] if lib_id in __libraries: raise KeyError("Invalid Library ID") elif set(lib.keys()) != {"description", "components"}: raise KeyError("Invalid Library") __libraries[lib_id] = lib except json.JSONDecodeError as ex: logger.critical("Error loading library %s; %s", filename, ex.args) return False except KeyError as ex: logger.critical("Error loading library %s: %s", filename, ex.args[0]) return False return True
[docs]def get_library_list(): """Fetch a list of the libraries available for use. Returns: list of (library id, description) tuples """ return [(lib, __libraries[lib]["description"]) for lib in __libraries]
[docs]def get_components_list(library): """Fetch a list of components available in the given library. Args: library: The library id of the library to query Returns: list of (component id, description) tuples """ components = __libraries[library]["components"] return [(comp_id, components[comp_id]["description"]) for comp_id in components]
[docs]def get_component(component, library=base_id): """Fetch the component data for the specified component. Args: component: The id of the specific component library: The id of the library to which the component belongs Returns: dict - the component dictionary """ return copy.deepcopy(__libraries[library]["components"][component])
[docs]def find(component, restrict_to=None, find_all=False, ensure_unique=False): """Find the specified component. Args: component: The component id to find. restrict_to: `list` or `set` of library id's to be that the search should be restricted to. find_all: `False` if the function should return only the first instance of the component, `True` if the function should return all such instances ensure_unique: If true, this assumes that the component id must be unique across libraries, and hence will raise an exception if this is assumption is violated. Returns: the library id, or a list of library_id in which this component can be found. Raises: NotImplementedError - if the component is not found. ValueError - if the component is assume to be unique, but is not """ if restrict_to: keys = {k for k in __libraries if k in restrict_to} else: keys = __libraries results = {lib for lib in keys if component in __libraries[lib]["components"]} if find_all: return results elif (ensure_unique and len(results) == 1) or not ensure_unique: return list(results)[0] elif ensure_unique: raise KeyError("Component is not unique") else: raise NotImplementedError("Component not found", component)
# On Import actions for lib_file in pathlib.Path(__LIB_DIR).glob("**/*.json"): load_library(lib_file)