Example #1
0
def build_config(config_dicts, ignore_names):
    """ Builds the model from the configuration

    Arguments:
        config_dicts: The parsed configuration file
        ignore_names: A set of names that should be ignored during the loading.
    """
    if "main" not in config_dicts:
        raise Exception("Configuration does not contain the main block.")

    existing_objects = dict()

    main_config = config_dicts['main']

    configuration = dict()
    # TODO ensure tf_manager goes last in a better way
    for key, value in sorted(main_config.items(),
                             key=lambda t: t[0]
                             if t[0] != 'tf_manager' else 'zzz'):
        if key not in ignore_names:
            try:
                configuration[key] = build_object(value, config_dicts,
                                                  existing_objects, 0)
            except Exception as exc:
                raise ConfigBuildException(key, exc) from None

    return configuration
Example #2
0
def instantiate_class(name: str,
                      all_dicts: Dict[str, Any],
                      existing_objects: Dict[str, Any],
                      depth: int) -> Any:
    """Instantiate a class from the configuration.

    Arguments: see help(build_object)
    """
    if name not in all_dicts:
        debug(str(all_dicts), "configBuild")
        raise ConfigInvalidValueException(name, "Undefined object")
    this_dict = all_dicts[name]

    if "class" not in this_dict:
        raise ConfigInvalidValueException(name, "Undefined object type")
    clazz = this_dict["class"].create()

    if not isclass(clazz) and not isfunction(clazz):
        raise ConfigInvalidValueException(
            name, "Cannot instantiate object with '{}'".format(clazz))

    # prepare the arguments for the constructor
    arguments = dict()

    for key, value in this_dict.items():
        if key == "class":
            continue

        arguments[key] = build_object(value, all_dicts, existing_objects,
                                      depth + 1)

    # get a signature of the constructing function
    construct_sig = signature(clazz)

    try:
        # try to bound the arguments to the signature
        bounded_params = construct_sig.bind(**arguments)
    except TypeError as exc:
        raise ConfigBuildException(clazz, exc)

    debug("Instantiating class {} with arguments {}".format(clazz, arguments),
          "configBuild")

    # call the function with the arguments
    # NOTE: any exception thrown from the body of the constructor is
    # not worth catching here
    obj = clazz(*bounded_params.args, **bounded_params.kwargs)

    debug("Class {} initialized into object {}".format(clazz, obj),
          "configBuild")

    return obj
Example #3
0
def build_config(
        config_dicts: Dict[str, Any],
        ignore_names: Set[str],
        warn_unused: bool = False) -> Tuple[Dict[str, Any], Dict[str, Any]]:
    """Build the model from the configuration.

    Arguments:
        config_dicts: The parsed configuration file
        ignore_names: A set of names that should be ignored during the loading.
        warn_unused: Emit a warning if there are unused sections.

    Returns:
        A tuple containing a dictionary corresponding to the main section and
        a dictionary mapping section names to objects.
    """
    if "main" not in config_dicts:
        raise Exception("Configuration does not contain the main block.")

    existing_objects = collections.OrderedDict()  # type: Dict[str, Any]

    main_config = config_dicts["main"]
    existing_objects["main"] = Namespace(**main_config)

    configuration = collections.OrderedDict()  # type: Dict[str, Any]
    # TODO ensure tf_manager goes last in a better way
    for key, value in sorted(main_config.items(),
                             key=lambda t: t[0]
                             if t[0] != "tf_manager" else "zzz"):
        if key not in ignore_names:
            try:
                configuration[key] = build_object(value, config_dicts,
                                                  existing_objects, 0)
            except Exception as exc:
                raise ConfigBuildException(key, exc) from None

    if warn_unused:
        existing_names = set(existing_objects.keys()) | {"main"}
        unused = config_dicts.keys() - existing_names
        if unused:
            warn("Configuration contains unused sections: " + str(unused) +
                 ".")

    return configuration, existing_objects
Example #4
0
def build_config(config_dicts: Dict[str, Any],
                 ignore_names: Set[str],
                 warn_unused: bool = False) -> Dict[str, Any]:
    """ Builds the model from the configuration

    Arguments:
        config_dicts: The parsed configuration file
        ignore_names: A set of names that should be ignored during the loading.
        warn_unused: Emit a warning if there are unused sections.
    """
    if "main" not in config_dicts:
        raise Exception("Configuration does not contain the main block.")

    existing_objects = collections.OrderedDict()  # type: Dict[str, Any]

    main_config = config_dicts['main']

    configuration = collections.OrderedDict()  # type: Dict[str, Any]
    # TODO ensure tf_manager goes last in a better way
    for key, value in sorted(main_config.items(),
                             key=lambda t: t[0]
                             if t[0] != 'tf_manager' else 'zzz'):
        if key not in ignore_names:
            try:
                configuration[key] = build_object(value, config_dicts,
                                                  existing_objects, 0)
            except Exception as exc:
                raise ConfigBuildException(key, exc) from None

    if warn_unused:
        existing_names = {x[7:] for x in existing_objects.keys()} | {'main'}
        unused = config_dicts.keys() - existing_names
        if unused:
            warn("Configuration contains unused sections: " + str(unused) +
                 ".")

    return configuration
Example #5
0
def instantiate_class(name: str, all_dicts: Dict[str, Any],
                      existing_objects: Dict[str, Any], depth: int) -> Any:
    """Instantiate a class from the configuration.

    Arguments: see help(build_object)
    """
    if name not in all_dicts:
        debug(str(all_dicts), "configBuild")
        raise ConfigInvalidValueException(name, "Undefined object")
    this_dict = all_dicts[name]

    if "class" not in this_dict:
        raise ConfigInvalidValueException(name, "Undefined object type")
    clazz = this_dict["class"].create()

    if not isclass(clazz) and not isfunction(clazz):
        raise ConfigInvalidValueException(
            name, "Cannot instantiate object with '{}'".format(clazz))

    # prepare the arguments for the constructor
    arguments = dict()

    for key, value in this_dict.items():
        if key == "class":
            continue

        arguments[key] = build_object(value, all_dicts, existing_objects,
                                      depth + 1)

    # get a signature of the constructing function
    construct_sig = signature(clazz)

    # if a signature contains a "name" attribute which is not in arguments,
    # replace it with the name of the section
    if "name" in construct_sig.parameters and "name" not in arguments:
        annotation = construct_sig.parameters["name"].annotation

        if annotation == Parameter.empty:
            debug(
                "No type annotation for the 'name' parameter in "
                "class/function {}. Default value will not be used.".format(
                    this_dict["class"].clazz), "configBuild")
        elif annotation != str:
            debug(
                "Type annotation for the 'name' parameter in class/function "
                "{} is not 'str'. Default value will not be used.".format(
                    this_dict["class"].clazz), "configBuild")
            debug("Annotation is {}".format(str(annotation)))
        else:
            debug(
                "Using default 'name' for object {}".format(
                    this_dict["class"].clazz), "configBuild")
            arguments["name"] = name

    try:
        # try to bound the arguments to the signature
        bounded_params = construct_sig.bind(**arguments)
    except TypeError as exc:
        raise ConfigBuildException(clazz, exc)

    debug("Instantiating class {} with arguments {}".format(clazz, arguments),
          "configBuild")

    # call the function with the arguments
    # NOTE: any exception thrown from the body of the constructor is
    # not worth catching here
    obj = clazz(*bounded_params.args, **bounded_params.kwargs)

    debug("Class {} initialized into object {}".format(clazz, obj),
          "configBuild")

    return obj