Exemplo n.º 1
0
    def __setattr__(self, key, value):
        """Add a new attribute to the header.

        Parameters
        ----------
        key : str
            Attribute to set.
        value : any
            Value to assign to the attribute.
            Could be an immutable object (scalar, tuple, dict, str),
            or a vector-like CArray. Lists are automatically converted
            to vector-like CArrays.

        """
        # We store lists as CArrays to facilitate indexing
        value = CArray(value) if is_list(value) else value

        # Make sure we store arrays as vector-like
        value = value.ravel() if isinstance(value, CArray) else value

        super(CDatasetHeader, self).__setattr__(key, value)

        # Make sure that input writable attributes are consistent
        if is_writable(self, key):
            self._validate_params()
Exemplo n.º 2
0
    def set_state(self, state_dict, copy=False):
        """Sets the object state using input dictionary.

        Only readable attributes of the class,
        i.e. PUBLIC or READ/WRITE or READ ONLY, can be set.

        If possible, a reference to the attribute to set is assigned.
        Use `copy=True` to always make a deepcopy before set.

        Parameters
        ----------
        state_dict : dict
            Dictionary containing the state of the object.
        copy : bool, optional
            By default (False) a reference to the attribute to
            assign is set. If True or a reference cannot be
            extracted, a deepcopy of the attribute is done first.

        """
        def copy_attr(attr_tocopy):
            from copy import deepcopy
            return deepcopy(attr_tocopy)

        for param_name in state_dict:

            # Extract the value of the attribute to set
            param_value = state_dict[param_name]

            # Support for recursive setting, e.g. -> kernel.gamma
            param_name = param_name.split('.', 1)

            # Attributes to set in this function must be readable
            # PUBLIC, READ/WRITE and READ ONLY accessibility is checked
            if not is_readable(self, param_name[0]):
                raise AttributeError(
                    "can't set `{:}`, must be readable.".format(param_name[0]))

            attr0 = param_name[0]
            if hasattr(self, attr0):
                # 1 level set or multiple sublevels set?
                if len(param_name) == 1:  # Set attribute directly
                    # If writable (public or property with setter)
                    if is_writable(self, attr0):  # Use main `.set`
                        self.set(attr0, param_value, copy=copy)
                        continue  # Attribute set, go to next one
                    else:  # Maybe is read-only (property with only getter)?
                        # If exists, set the protected attribute
                        if has_protected(self, attr0):
                            attr0 = as_protected(attr0)
                        setattr(self, attr0, copy_attr(param_value)
                                if copy is True else param_value)
                        continue  # Attribute set, go to next one
                else:  # Start recursion on sublevels
                    # Call `.set_state` for the next level of current attribute
                    getattr(self, attr0).set_state(
                        {param_name[1]: param_value}, copy)
                    continue  # Attribute set, go to next one

            # Attribute not found, raise AttributeError
            raise AttributeError(
                "'{:}', or any of its attributes, has attribute '{:}'"
                "".format(self.__class__.__name__, attr0))
Exemplo n.º 3
0
    def set(self, param_name, param_value, copy=False):
        """Set a parameter of the class.

        Only writable attributes of the class,
        i.e. PUBLIC or READ/WRITE, can be set.

        The following checks are performed before setting:
         - if `param_name` is an attribute of current class, set directly;
         - else, iterate over __dict__ and look for a class attribute
            having the desired parameter as an attribute;
         - else, if attribute is not found on the 2nd level,
            raise AttributeError.

        If possible, a reference to the attribute to set is assigned.
        Use `copy=True` to always make a deepcopy before set.

        Parameters
        ----------
        param_name : str
            Name of the parameter to set.
        param_value : any
            Value to set for the parameter.
        copy : bool
            By default (False) a reference to the parameter to
            assign is set. If True or a reference cannot be
            extracted, a deepcopy of the parameter value is done first.

        """
        def copy_attr(attr_tocopy):
            from copy import deepcopy
            return deepcopy(attr_tocopy)

        # Support for recursive setting, e.g. -> kernel.gamma
        param_name = param_name.split('.')

        attr0 = param_name[0]
        if hasattr(self, attr0):
            # Level 0 set or multiple sublevels set?
            if len(param_name) == 1:  # Set attribute directly
                # Level 0 attribute must be writable
                # PUBLIC and READ/WRITE accessibility is checked
                if not is_writable(self, attr0):
                    raise AttributeError(
                        "can't set `{:}`, must be writable.".format(attr0))
                setattr(self, attr0, copy_attr(param_value)
                        if copy is True else param_value)
                return
            else:  # Start recursion on sublevels
                # Level 0 attribute must be accessible (readable)
                # PUBLIC, READ/WRITE and READ ONLY accessibility is checked
                if not is_readable(self, attr0):
                    raise AttributeError(
                        "can't set `{:}`, must be accessible.".format(attr0))
                sub_param_name = '.'.join(param_name[1:])
                # Calling `.set` method of the next sublevel
                getattr(self, attr0).set(sub_param_name, param_value, copy)
                return

        # OLD STYLE SET: recursion on 2 levels only to set a subattribute
        # The first subattribute found is set...
        else:
            # Look for the attribute inside all class attributes
            for attr_name in self.__dict__:
                # Extract the current attribute
                attr = getattr(self, attr_name)
                # If parameter is an attribute of current attribute set it
                if hasattr(attr, attr0):
                    # Attributes to set must be writable
                    # PUBLIC and READ/WRITE accessibility is checked
                    if not is_writable(attr, attr0):
                        raise AttributeError(
                            "can't set `{:}`, must be writable.".format(attr0))
                    setattr(attr, attr0, copy_attr(param_value)
                            if copy is True else param_value)
                    return

        # Attribute not found, raise AttributeError
        raise AttributeError(
            "'{:}', or any of its attributes, has attribute '{:}'"
            "".format(self.__class__.__name__, attr0))