Ejemplo n.º 1
0
    def _is_attribute_in_config_arguments(self, attr_space: AttributeSpace,
                                          builder_space: BuilderSpace):
        """Checks if an attribute is in the configuration file or keyword arguments dictionary

        Will recurse spock classes as dependencies might be defined in the configs class

        Args:
            attr_space: holds information about a single attribute that is mapped to a ConfigSpace
            builder_space: map of the read/cmd-line parameter dictionary to general or class level arguments

        Returns:
            boolean if in dictionary

        """
        # Instances might have other instances that might be defined in the configs
        # Recurse to try and catch all config defs
        # Only map if default is not None -- do so by evolving the attribute
        if (_is_spock_instance(attr_space.attribute.type)
                and attr_space.attribute.default is not None):
            attr_space.field, special_keys = RegisterSpockCls(
            ).recurse_generate(attr_space.attribute.type, builder_space)
            attr_space.attribute = attr_space.attribute.evolve(
                default=attr_space.field)
            builder_space.spock_space[
                attr_space.attribute.type.__name__] = attr_space.field
            self.special_keys.update(special_keys)
        return (attr_space.config_space.name in builder_space.arguments
                and attr_space.attribute.name
                in builder_space.arguments[attr_space.config_space.name])
Ejemplo n.º 2
0
    def handle_attribute_from_config(self, attr_space: AttributeSpace,
                                     builder_space: BuilderSpace):
        """Handles setting a simple attribute when it is a spock class type

        Args:
            attr_space: holds information about a single attribute that is mapped to a ConfigSpace
            builder_space: named_tuple containing the arguments and spock_space

        Returns:
        """
        typed = attr_space.attribute.metadata["type"]
        out = None
        # Handle List Types
        if (_get_name_py_version(typed) == "List"
                or _get_name_py_version(typed) == "Tuple"):
            out = []
            for v in builder_space.arguments[attr_space.config_space.name][
                    attr_space.attribute.name]:
                out.append(_recurse_callables(v, _str_2_callable))
        # Handle Dict Types
        elif _get_name_py_version(typed) == "Dict":
            out = {}
            for k, v in builder_space.arguments[attr_space.config_space.name][
                    attr_space.attribute.name].items():
                out.update({k: _recurse_callables(v, _str_2_callable)})
        attr_space.field = out
Ejemplo n.º 3
0
    def handle_optional_attribute_value(self, attr_space: AttributeSpace,
                                        builder_space: BuilderSpace):
        """Handles setting an optional value with its default

        Args:
            attr_space: holds information about a single attribute that is mapped to a ConfigSpace
            builder_space: named_tuple containing the arguments and spock_space

        Returns:
        """
        attr_space.field = attr_space.attribute.default
Ejemplo n.º 4
0
    def handle_attribute_from_config(self, attr_space: AttributeSpace,
                                     builder_space: BuilderSpace):
        """Handles when the spock tune class is made up of spock classes

        Args:
            attr_space: holds information about a single attribute that is mapped to a ConfigSpace
            builder_space: named_tuple containing the arguments and spock_space

        Returns:
        """
        attr_type = self._attr_type(attr_space)
        attr_space.field = attr_type(**builder_space.arguments[
            attr_space.config_space.name][attr_space.attribute.name])
Ejemplo n.º 5
0
    def handle_attribute_from_config(self, attr_space: AttributeSpace,
                                     builder_space: BuilderSpace):
        """Handles setting a simple attribute when it is a spock class type

        Args:
            attr_space: holds information about a single attribute that is mapped to a ConfigSpace
            builder_space: named_tuple containing the arguments and spock_space

        Returns:
        """
        attr_space.field = builder_space.arguments[
            attr_space.config_space.name][attr_space.attribute.name]
        self.register_special_key(attr_space)
Ejemplo n.º 6
0
    def handle_attribute_from_config(self, attr_space: AttributeSpace,
                                     builder_space: BuilderSpace):
        """Handles setting a simple attribute when it is a spock class type

        Args:
            attr_space: holds information about a single attribute that is mapped to a ConfigSpace
            builder_space: named_tuple containing the arguments and spock_space

        Returns:
        """
        # These should always be strings
        str_field = builder_space.arguments[attr_space.config_space.name][
            attr_space.attribute.name]
        call_ref = _str_2_callable(str_field)
        attr_space.field = call_ref
Ejemplo n.º 7
0
    def _handle_and_register_enum(self, enum_cls, attr_space: AttributeSpace,
                                  builder_space: BuilderSpace):
        """Recurses the enum in case there are nested type definitions

        Args:
            enum_cls: current enum class
            attr_space: holds information about a single attribute that is mapped to a ConfigSpace
            builder_space: named_tuple containing the arguments and spock_space

        Returns:
        """
        attr_space.field, special_keys = RegisterSpockCls.recurse_generate(
            enum_cls, builder_space)
        self.special_keys.update(special_keys)
        builder_space.spock_space[enum_cls.__name__] = attr_space.field
Ejemplo n.º 8
0
    def handle_optional_attribute_value(self, attr_space: AttributeSpace,
                                        builder_space: BuilderSpace):
        """Handles setting the value for an optional basic attribute

        Args:
            attr_space: holds information about a single attribute that is mapped to a ConfigSpace
            builder_space: named_tuple containing the arguments and spock_space

        Returns:
        """
        super().handle_optional_attribute_value(attr_space, builder_space)
        if attr_space.field is not None:
            list_item_spock_class = attr_space.field
            # Here we need to catch the possibility of repeated lists via coded defaults
            if _is_spock_instance(
                    attr_space.attribute.metadata["type"].__args__[0]):
                spock_cls = attr_space.attribute.metadata["type"].__args__[0]
                # Fall back to configs if present
                if spock_cls.__name__ in builder_space.arguments:
                    attr_space.field = self._process_list(
                        spock_cls, builder_space)
                # Here we need to attempt to instantiate any class references that still exist
                try:
                    attr_space.field = [
                        val() if type(val) is type else val
                        for val in attr_space.field
                    ]
                except Exception as e:
                    raise _SpockInstantiationError(
                        f"Spock class `{spock_cls.__name__}` could not be instantiated -- attrs message: {e}"
                    )
                builder_space.spock_space[
                    spock_cls.__name__] = attr_space.field
            else:
                builder_space.spock_space[
                    list_item_spock_class.__name__] = attr_space.field
Ejemplo n.º 9
0
    def handle_optional_attribute_type(self, attr_space: AttributeSpace,
                                       builder_space: BuilderSpace):
        """Handles a list of spock config classes (aka repeated classes) if it is optional

        Args:
            attr_space: holds information about a single attribute that is mapped to a ConfigSpace
            builder_space: named_tuple containing the arguments and spock_space

        Returns:
        """
        list_item_spock_class = attr_space.attribute.default
        attr_space.field = self._process_list(list_item_spock_class,
                                              builder_space)
        builder_space.spock_space[
            list_item_spock_class.__name__] = attr_space.field
Ejemplo n.º 10
0
    def handle_attribute_from_config(self, attr_space: AttributeSpace,
                                     builder_space: BuilderSpace):
        """Handles when the attribute is made up of a spock class or classes

        Calls the recurse_generate function which handles nesting of spock classes

        Args:
            attr_space: holds information about a single attribute that is mapped to a ConfigSpace
            builder_space: named_tuple containing the arguments and spock_space

        Returns:
        """
        attr_type = self._attr_type(attr_space)
        attr_space.field, special_keys = self.recurse_generate(
            attr_type, builder_space)
        builder_space.spock_space[attr_type.__name__] = attr_space.field
        self.special_keys.update(special_keys)
Ejemplo n.º 11
0
    def handle_optional_attribute_type(self, attr_space: AttributeSpace,
                                       builder_space: BuilderSpace):
        """Handles when the falling back onto the default for the attribute of spock class type

        Calls the recurse_generate function which handles nesting of spock classes -- to make sure the attr_space.field
        value is defined

        Args:
            attr_space: holds information about a single attribute that is mapped to a ConfigSpace
            builder_space: named_tuple containing the arguments and spock_space

        Returns:
        """
        attr_space.field, special_keys = RegisterSpockCls.recurse_generate(
            self._attr_type(attr_space), builder_space)
        self.special_keys.update(special_keys)

        builder_space.spock_space[self._attr_type(
            attr_space).__name__] = attr_space.field
Ejemplo n.º 12
0
    def recurse_generate(cls, spock_cls: _C, builder_space: BuilderSpace):
        """Call on a spock classes to iterate through the attrs attributes and handle each based on type and optionality

        Triggers a recursive call when an attribute refers to another spock classes

        Args:
            spock_cls: current spock class that is being handled
            builder_space: named_tuple containing the arguments and spock_space

        Returns:
            tuple of the instantiated spock class and the dictionary of special keys

        """
        # Empty dits for storing info
        special_keys = {}
        fields = {}
        # Init the ConfigSpace for this spock class
        config_space = ConfigSpace(spock_cls, fields)
        # Iterate through the attrs within the spock class
        for attribute in spock_cls.__attrs_attrs__:
            attr_space = AttributeSpace(attribute, config_space)
            # Logic to handle the underlying type to call the correct Register* class
            # Lists of repeated values
            if ((attribute.type is list) or
                (attribute.type is List)) and _is_spock_instance(
                    attribute.metadata["type"].__args__[0]):
                handler = RegisterList()
            # Dict/List of Callables
            elif ((attribute.type is list) or (attribute.type is List) or
                  (attribute.type is dict) or (attribute.type is Dict) or
                  (attribute.type is tuple) or
                  (attribute.type is Tuple)) and cls._find_callables(
                      attribute.metadata["type"]):
                # handler = RegisterListCallableField()
                handler = RegisterGenericAliasCallableField()
            # Enums
            elif isinstance(attribute.type, EnumMeta) and _check_iterable(
                    attribute.type):
                handler = RegisterEnum()
            # References to other spock classes
            elif _is_spock_instance(attribute.type):
                handler = RegisterSpockCls()
            # References to tuner classes
            elif _is_spock_tune_instance(attribute.type):
                handler = RegisterTuneCls()
            # References to callables
            elif isinstance(attribute.type, _SpockVariadicGenericAlias):
                handler = RegisterCallableField()
            # Basic field
            else:
                handler = RegisterSimpleField()

            handler(attr_space, builder_space)
            special_keys.update(handler.special_keys)

        # Try except on the class since it might not be successful -- throw the attrs message as it will know the
        # error on instantiation
        try:
            spock_instance = spock_cls(**fields)
        except Exception as e:
            raise _SpockInstantiationError(
                f"Spock class `{spock_cls.__name__}` could not be instantiated -- attrs message: {e}"
            )
        return spock_instance, special_keys