Ejemplo n.º 1
0
    def add_component(self, _component_config):
        """Add the component configuration passed as parameter

        Add it to MonanasDSL configuration, and return a new unique ID
        generated for it.
        The configuration passed as parameter is validated, raising exceptions
        if the module does not exist or the configuration is invalid.

        :type _component_config: dict
        :param _component_config: configuration of the component to be added
        :rtype: str
        :returns: Component ID for the added component
        :raises: MonanasNoSuchClassError -- if the defined class doesn't
                 exist or is not of a valid type
        :raises: SchemaError -- if the configuration is not valid for
                 the class.
        """
        if type(_component_config) == str:
            _component_config = json.loads(_component_config)
        clz = cu.get_class_by_name(_component_config[MODULE])
        clz.validate_config(_component_config)
        comp_type = cu.get_component_type(_component_config[MODULE])
        comp_id = self._generate_id(comp_type)
        self._config[comp_type][comp_id] = _component_config
        self._config[const.CONNECTIONS][comp_id] = []
        return comp_id
def eval_comp(context, comp, expected_type):
    """
    Instantiate the given component, computing
    the required config.
    :type context: ctx.EvaluationContext
    :param context: Evaluation context.
    :type comp: ast.Component
    :param comp: the node to evaluate.
    :type expected_type: type_util.IsType
    :param expected_type: The expected type of this computation.
    :return: Returns the instantiated component.
    """
    arguments = {}
    # Compute arguments
    for arg in comp.args:
        arg_name = ast.DotPath(arg.arg_name.span, arg.arg_name, [])
        arg_value = eval_rhs(context, arg.value, expected_type[arg_name])
        arguments[arg.arg_name.inner_val()] = arg_value
    # Lookup component
    component_type = introspect.get_class_by_name(comp.type_name.val)
    # Get default config for the component
    conf = component_type.get_default_config()
    # Update modified params
    for k, val in arguments.iteritems():
        conf[k] = val
    # Delay evaluation until we do the assign
    return component_type, conf
Ejemplo n.º 3
0
    def add_component(self, _component_config):
        """Add the component configuration passed as parameter

        Add it to MonanasDSL configuration, and return a new unique ID
        generated for it.
        The configuration passed as parameter is validated, raising exceptions
        if the module does not exist or the configuration is invalid.

        :type _component_config: dict
        :param _component_config: configuration of the component to be added
        :rtype: str
        :returns: Component ID for the added component
        :raises: MonanasNoSuchClassError -- if the defined class doesn't
                 exist or is not of a valid type
        :raises: SchemaError -- if the configuration is not valid for
                 the class.
        """
        if type(_component_config) == str:
            _component_config = json.loads(_component_config)
        clz = cu.get_class_by_name(_component_config[MODULE])
        clz.validate_config(_component_config)
        comp_type = cu.get_component_type(_component_config[MODULE])
        comp_id = self._generate_id(comp_type)
        self._config[comp_type][comp_id] = _component_config
        self._config[const.CONNECTIONS][comp_id] = []
        return comp_id
Ejemplo n.º 4
0
def eval_comp(context, comp, expected_type):
    """
    Instantiate the given component, computing
    the required config.
    :type context: ctx.EvaluationContext
    :param context: Evaluation context.
    :type comp: ast.Component
    :param comp: the node to evaluate.
    :type expected_type: type_util.IsType
    :param expected_type: The expected type of this computation.
    :return: Returns the instantiated component.
    """
    arguments = {}
    # Compute arguments
    for arg in comp.args:
        arg_name = ast.DotPath(arg.arg_name.span, arg.arg_name, [])
        arg_value = eval_rhs(context, arg.value, expected_type[arg_name])
        arguments[arg.arg_name.inner_val()] = arg_value
    # Lookup component
    component_type = introspect.get_class_by_name(comp.type_name.val)
    # Get default config for the component
    conf = component_type.get_default_config()
    # Update modified params
    for k, val in six.iteritems(arguments):
        conf[k] = val
    # Delay evaluation until we do the assign
    return component_type, conf
Ejemplo n.º 5
0
    def create(self, varname, modulename):
        """Add a module defined by modulename in the configuration

        :type varname: str
        :param varname: name of the variable representing
                        the new component
        :rtype: str
        :returns: new component ID
        """
        clz = cu.get_class_by_name(modulename)
        conf = copy.deepcopy(clz.get_default_config())
        comp_id = self.dsl.add_component(conf)
        self.mappings[varname] = comp_id
        return comp_id
Ejemplo n.º 6
0
    def create(self, varname, modulename):
        """Add a module defined by modulename in the configuration

        :type varname: str
        :param varname: name of the variable representing
                        the new component
        :rtype: str
        :returns: new component ID
        """
        clz = cu.get_class_by_name(modulename)
        conf = copy.deepcopy(clz.get_default_config())
        comp_id = self.dsl.add_component(conf)
        self.mappings[varname] = comp_id
        return comp_id
Ejemplo n.º 7
0
    def modify_component(self, comp_id, params_path, value):
        """Overrides the value of the configuration path of a component

        Modifies the configuration of the component defined by comp_id,
        following the path in the dictionary defined by params_path, and
        assigning the value value.

        :type comp_id: str
        :param comp_id: ID of the component to be modified
        :type params_path: list
        :param params_path: parameters path to modify in the config
        :type value: str | int | float
        :param value: new value to be assigned, will be parsed
                      according to the expected configuration
        :rtype: bool
        :returns: True if the component was modified (or if the modification
                  result was the same as the existing configuration),
                  False otherwise
        :raises: SchemaError -- if the new configuration would not be valid
        """
        comp_type = self._get_type_by_id(comp_id)
        if not comp_type:
            return False
        new_conf = copy.deepcopy(self._config[comp_type][comp_id])
        logger.debug("Modifying " + comp_id + ", existing config = " +
                     str(new_conf))
        clz = cu.get_class_by_name(new_conf[MODULE])
        for var_type in [str, int, float]:
            try:
                parsed_value = var_type(value)
            except ValueError as e:
                logger.debug(str(e))
                continue
            new_conf = self._modify_dictionary(new_conf, params_path,
                                               parsed_value)
            try:
                clz.validate_config(new_conf)
                logger.debug("New validated config = " + str(new_conf))
                self._config[comp_type][comp_id] = new_conf
                return True
            except voluptuous.Invalid as e:
                logger.debug(str(e))
                continue
        return False
Ejemplo n.º 8
0
    def modify_component(self, comp_id, params_path, value):
        """Overrides the value of the configuration path of a component

        Modifies the configuration of the component defined by comp_id,
        following the path in the dictionary defined by params_path, and
        assigning the value value.

        :type comp_id: str
        :param comp_id: ID of the component to be modified
        :type params_path: list
        :param params_path: parameters path to modify in the config
        :type value: str | int | float
        :param value: new value to be assigned, will be parsed
                      according to the expected configuration
        :rtype: bool
        :returns: True if the component was modified (or if the modification
                  result was the same as the existing configuration),
                  False otherwise
        :raises: SchemaError -- if the new configuration would not be valid
        """
        comp_type = self._get_type_by_id(comp_id)
        if not comp_type:
            return False
        new_conf = copy.deepcopy(self._config[comp_type][comp_id])
        logger.debug("Modifying " + comp_id + ", existing config = " +
                     str(new_conf))
        clz = cu.get_class_by_name(new_conf[MODULE])
        for var_type in [str, int, float]:
            try:
                parsed_value = var_type(value)
            except ValueError as e:
                logger.debug(str(e))
                continue
            new_conf = self._modify_dictionary(new_conf, params_path,
                                               parsed_value)
            try:
                clz.validate_config(new_conf)
                logger.debug("New validated config = " + str(new_conf))
                self._config[comp_type][comp_id] = new_conf
                return True
            except voluptuous.Invalid as e:
                logger.debug(str(e))
                continue
        return False
def _create_component_by_module(comp_id, comp_config, comp_type):
    """Create a single component matching the past configuration.

    The id assigned to that component will be comp_id.

    :type comp_id: str
    :param comp_id: ID of the component to create
    :type comp_config: dict
    :param comp_config: Configuration of the component to create
    :type comp_type: str
    :param comp_type: type of component to create
    :rtype: monasca_analytics.component.base.BaseComponent
    :returns: Instantiated component object
    """
    logger.debug("deploying " + comp_config["module"] + " object")
    clazz = common_util.get_class_by_name(comp_config["module"],
                                          comp_type)
    _comp = clazz(comp_id, comp_config)
    return _comp
Ejemplo n.º 10
0
def typeck_component(component, type_table):
    """
    Type-check the provided component. Returns
    the appropriate subclass of util.Component if
    successful, or raise an exception if there's
    an error.
    :type component: ast.Component
    :param component: The component ast node.
    :type type_table: typetbl.TypeTable
    :param type_table: the type table.
    :rtype: u.Source | u.Sink | u.Voter | u.Ldp | u.Sml | u.Ingestor
    :return: Returns the appropriate type for the component.
    """
    # TODO(Joan): This wont't work for type that are defined
    # TODO(Joan): at the language level. We need a registration service
    # TODO(Joan): to manage the Types of component that we can create
    # TODO(Joan): instead of this hacky function call.
    try:
        component_type = introspect.get_class_by_name(component.type_name.val)
        comp_params = component_type.get_params()
    except exception_monanas.MonanasNoSuchClassError:
        raise exception.BananaUnknown(component)

    # Compute the type of the component
    if issubclass(component_type, source.BaseSource):
        comp_type = u.Source(component_type.__name__, comp_params)
    elif issubclass(component_type, sink.BaseSink):
        comp_type = u.Sink(component_type.__name__, comp_params)
    elif issubclass(component_type, sml.BaseSML):
        comp_type = u.Sml(component_type.__name__, comp_params)
    elif issubclass(component_type, voter.BaseVoter):
        comp_type = u.Voter(component_type.__name__, comp_params)
    elif issubclass(component_type, ldp.BaseLDP):
        comp_type = u.Ldp(component_type.__name__, comp_params)
    elif issubclass(component_type, ingestor.BaseIngestor):
        comp_type = u.Ingestor(component_type.__name__, comp_params)
    else:
        raise exception.BananaTypeCheckerBug(
            "Couldn't find a type for '{}'".format(component.type_name.val))

    # Type check the parameters
    if len(component.args) > len(comp_params):
        raise exception.BananaComponentTooManyParams(component.span)

    # Does saying that parameter should either all have a name
    # or non at all satisfying? -> Yes
    # Are parameter all named?
    all_named = -1
    for arg in component.args:
        if arg.arg_name is not None:
            if all_named == 0:
                raise exception.BananaComponentMixingParams(arg.span, False)
            all_named = 1
        else:
            if all_named == 1:
                raise exception.BananaComponentMixingParams(arg.span, True)
            all_named = 0

    if all_named == 1:
        for arg in component.args:
            param = filter(lambda x: x.param_name == arg.arg_name.inner_val(),
                           comp_params)
            if len(param) != 1:
                raise exception.BananaComponentIncorrectParamName(
                    component=component.type_name, found=arg.arg_name)
            param = param[0]
            expr_type = typeck_rhs(arg.value, type_table)
            if not u.can_be_cast_to(expr_type, param.param_type):
                raise exception.BananaArgumentTypeError(
                    where=arg,
                    expected_type=param.param_type,
                    received_type=expr_type)
    else:
        for arg, param in zip(component.args, comp_params):
            arg.arg_name = ast.Ident(arg.span, param.param_name)
            expr_type = typeck_rhs(arg.value, type_table)
            if not u.can_be_cast_to(expr_type, param.param_type):
                raise exception.BananaArgumentTypeError(
                    where=arg,
                    expected_type=param.param_type,
                    received_type=expr_type)

    return comp_type
Ejemplo n.º 11
0
def typeck_component(component, type_table):
    """
    Type-check the provided component. Returns
    the appropriate subclass of util.Component if
    successful, or raise an exception if there's
    an error.
    :type component: ast.Component
    :param component: The component ast node.
    :type type_table: typetbl.TypeTable
    :param type_table: the type table.
    :rtype: u.Source | u.Sink | u.Voter | u.Ldp | u.Sml | u.Ingestor
    :return: Returns the appropriate type for the component.
    """
    # TODO(Joan): This wont't work for type that are defined
    # TODO(Joan): at the language level. We need a registration service
    # TODO(Joan): to manage the Types of component that we can create
    # TODO(Joan): instead of this hacky function call.
    try:
        component_type = introspect.get_class_by_name(component.type_name.val)
        comp_params = component_type.get_params()
    except exception_monanas.MonanasNoSuchClassError:
        raise exception.BananaUnknown(
            component
        )

    # Compute the type of the component
    if issubclass(component_type, source.BaseSource):
        comp_type = u.Source(component_type.__name__, comp_params)
    elif issubclass(component_type, sink.BaseSink):
        comp_type = u.Sink(component_type.__name__, comp_params)
    elif issubclass(component_type, sml.BaseSML):
        comp_type = u.Sml(component_type.__name__, comp_params)
    elif issubclass(component_type, voter.BaseVoter):
        comp_type = u.Voter(component_type.__name__, comp_params)
    elif issubclass(component_type, ldp.BaseLDP):
        comp_type = u.Ldp(component_type.__name__, comp_params)
    elif issubclass(component_type, ingestor.BaseIngestor):
        comp_type = u.Ingestor(component_type.__name__, comp_params)
    else:
        raise exception.BananaTypeCheckerBug("Couldn't find a type for '{}'"
                                             .format(component.type_name.val))

    # Type check the parameters
    if len(component.args) > len(comp_params):
        raise exception.BananaComponentTooManyParams(component.span)

    # Does saying that parameter should either all have a name
    # or non at all satisfying? -> Yes
    # Are parameter all named?
    all_named = -1
    for arg in component.args:
        if arg.arg_name is not None:
            if all_named == 0:
                raise exception.BananaComponentMixingParams(arg.span, False)
            all_named = 1
        else:
            if all_named == 1:
                raise exception.BananaComponentMixingParams(arg.span, True)
            all_named = 0

    if all_named == 1:
        for arg in component.args:
            param = list(filter(lambda x:
                                x.param_name == arg.arg_name.inner_val(),
                                comp_params))
            if len(param) != 1:
                raise exception.BananaComponentIncorrectParamName(
                    component=component.type_name,
                    found=arg.arg_name
                )
            param = param[0]
            expr_type = typeck_rhs(arg.value, type_table)
            if not u.can_be_cast_to(expr_type, param.param_type):
                raise exception.BananaArgumentTypeError(
                    where=arg,
                    expected_type=param.param_type,
                    received_type=expr_type
                )
    else:
        for arg, param in zip(component.args, comp_params):
            arg.arg_name = ast.Ident(arg.span, param.param_name)
            expr_type = typeck_rhs(arg.value, type_table)
            if not u.can_be_cast_to(expr_type, param.param_type):
                raise exception.BananaArgumentTypeError(
                    where=arg,
                    expected_type=param.param_type,
                    received_type=expr_type
                )

    return comp_type
Ejemplo n.º 12
0
 def test_get_class_by_name(self):
     common_util.get_class_by_name("RandomSource", const.SOURCES)
Ejemplo n.º 13
0
 def test_get_class_by_name(self):
     common_util.get_class_by_name("RandomSource", const.SOURCES)