示例#1
0
文件: code.py 项目: asle85/aiida-core
    def _folder_with_code_validator(self, folder_with_code):
        """
        Validates the folder_with_code.
        """
        import os.path
        from aiida.common.exceptions import ValidationError

        if not os.path.isdir(folder_with_code):
            raise ValidationError("'{}' is not a valid directory".format(
                folder_with_code))
示例#2
0
    def setup(cls, **kwargs):
        # raise NotImplementedError
        from aiida.cmdline.commands.code import CodeInputValidationClass
        code = CodeInputValidationClass().set_and_validate_from_code(kwargs)

        try:
            code.store()
        except ValidationError as exc:
            raise ValidationError(
                'Unable to store the computer: {}.'.format(exc))
        return code
示例#3
0
    def validate_key(key):
        """
        Validate the key string to check if it is valid (e.g., if it does not
        contain the separator symbol.).

        :return: None if the key is valid
        :raise aiida.common.ValidationError: if the key is not valid
        """
        from aiida.backends.utils import AIIDA_ATTRIBUTE_SEP
        from aiida.common.exceptions import ValidationError

        if not isinstance(key, str):
            raise ValidationError('The key must be a string.')
        if not key:
            raise ValidationError('The key cannot be an empty string.')
        if AIIDA_ATTRIBUTE_SEP in key:
            raise ValidationError(
                "The separator symbol '{}' cannot be present "
                'in the key of attributes, extras, etc.'.format(
                    AIIDA_ATTRIBUTE_SEP))
示例#4
0
文件: code.py 项目: asle85/aiida-core
    def _local_rel_path_validator(self, local_rel_path):
        """
        Validates the local_rel_path.
        """
        import os.path
        from aiida.common.exceptions import ValidationError

        if not os.path.isfile(os.path.join(self.folder_with_code,
                                           local_rel_path)):
            raise ValidationError("'{}' is not a valid file within '{}'".format(
                local_rel_path, self.folder_with_code))
示例#5
0
 def set_exclude(self, exclude):
     """
     Return the list of classes to exclude from autogrouping.
     """
     the_exclude_classes = self._validate(exclude)
     if self.get_include() is not None:
         if 'all.' in self.get_include():
             if 'all.' in the_exclude_classes:
                 raise ValidationError(
                     "Cannot exclude and include all classes")
     self.exclude = the_exclude_classes
示例#6
0
def validate_m(value):
    """
    Validate the value of the magnetic number
    """
    if not isinstance(value, int):
        raise ValidationError('magnetic number (m) must be integer')

    # without knowing l we cannot validate the value of m. We will call an additional function
    # in the validate function

    return value
示例#7
0
def validate_len3_list(value):
    """
    Validate that the value is a list of three floats
    """
    try:
        conv_value = list(float(i) for i in value)
        if len(conv_value) != 3:
            raise ValueError
    except (ValueError, TypeError):
        raise ValidationError('must be a list of three float number')
    return conv_value
示例#8
0
    def set_include(self, include):
        """
        Set the list of classes to include in the autogrouping.
        """
        the_include_classes = self._validate(include)
        if self.get_exclude() is not None:
            if 'all.' in self.get_exclude():
                if 'all.' in the_include_classes:
                    raise ValidationError("Cannot exclude and include all classes")

        self.include = the_include_classes
    def _validate(self):
        from aiida.common.exceptions import ValidationError, ParsingError
        from aiida.common.files import md5_from_filelike
        import aiida.common.utils

        super(PsmlData, self)._validate()

        # Yet another parsing ???
        with self.open(mode='r') as handle:
            parsed_data = parse_psml(handle.name)

        # Open in binary mode which is required for generating the md5 checksum
        with self.open(mode='rb') as handle:
            md5 = md5_from_filelike(handle)

        # TODO: This is erroneous exception,
        # as it is in the `upf` module oin `aiida_core`
        try:
            element = parsed_data['element']
        except KeyError:
            raise ValidationError("No 'element' could be parsed in the PSML "
                                  "file {}".format(psml_abspath))

        try:
            attr_element = self.get_attribute('element')
        except AttributeError:
            raise ValidationError("attribute 'element' not set.")

        try:
            attr_md5 = self.get_attribute('md5')
        except AttributeError:
            raise ValidationError("attribute 'md5' not set.")

        if attr_element != element:
            raise ValidationError("Attribute 'element' says '{}' but '{}' was "
                                  "parsed instead.".format(
                                      attr_element, element))

        if attr_md5 != md5:
            raise ValidationError("Attribute 'md5' says '{}' but '{}' was "
                                  "parsed instead.".format(attr_md5, md5))
示例#10
0
 def par_validate(params):
     the_params = {}
     for k, v in params.iteritems():
         if any([isinstance(v, int),
                 isinstance(v, bool),
                 isinstance(v, float),
                 isinstance(v, str)]):
             the_params[k] = v
         else:
             raise ValidationError("Cannot store in the DB a parameter "
                                   "which is not of type int, bool, float or str.")
     return the_params
示例#11
0
    def generate_md5(self):
        """
        Computes and returns MD5 hash of the CIF file.
        """
        import aiida.common.utils
        from aiida.common.exceptions import ValidationError

        abspath = self.get_file_abs_path()
        if not abspath:
            raise ValidationError("No valid CIF was passed!")

        return aiida.common.utils.md5_file(abspath)
示例#12
0
文件: node.py 项目: asle85/aiida-core
    def set_query(self,
                  filters=None,
                  orders=None,
                  projections=None,
                  query_type=None,
                  pk=None,
                  alist=None,
                  nalist=None,
                  elist=None,
                  nelist=None):
        """
        Adds filters, default projections, order specs to the query_help,
        and initializes the qb object

        :param filters: dictionary with the filters
        :param orders: dictionary with the order for each tag
        :param projections: dictionary with the projection. It is discarded
        if query_type=='attributes'/'extras'
        :param query_type: (string) specify the result or the content (
        "attr")
        :param pk: (integer) pk of a specific node
        """

        ## Check the compatibility of query_type and pk
        if query_type is not "default" and pk is None:
            raise ValidationError("non default result/content can only be "
                                  "applied to a specific pk")

        ## Set the type of query
        self.set_query_type(query_type,
                            alist=alist,
                            nalist=nalist,
                            elist=elist,
                            nelist=nelist)

        ## Define projections
        if self._content_type is not None:
            # Use '*' so that the object itself will be returned.
            # In get_results() we access attributes/extras by
            # calling the get_attrs()/get_extras().
            projections = ['*']
        else:
            pass  #i.e. use the input parameter projection

        ## TODO this actually works, but the logic is a little bit obscure.
        # Make it clearer
        if self._result_type is not self.__label__:
            projections = self._default_projections

        super(NodeTranslator, self).set_query(filters=filters,
                                              orders=orders,
                                              projections=projections,
                                              pk=pk)
示例#13
0
    def generate_md5(self):
        """
        Generate MD5 hash of the file's contents on-the-fly.
        """
        import aiida.common.utils
        from aiida.common.exceptions import ValidationError

        abspath = self.get_file_abs_path()
        if not abspath:
            raise ValidationError("No valid CIF was passed!")

        return aiida.common.utils.md5_file(abspath)
示例#14
0
    def _get_orbital_class_from_orbital_dict(self, orbital_dict):
        """
        Gets the orbital class from the orbital dictionary stored in DB

        :param orbital_dict: orbital dictionary associated with the orbital
        :return: an Orbital produced using the module_name
        """
        try:
            module_name = orbital_dict['module_name']
        except KeyError:
            raise ValidationError("No valid module name found in orbital")
        return OrbitalFactory(module_name)
示例#15
0
    def _prepare_for_submission(self, tempfolder, inputdict):
        """
        This is the routine to be called when you want to create
        the input files and related stuff with a plugin.
        
        :param tempfolder: a aiida.common.folders.Folder subclass where
                           the plugin should put all its files.
        :param inputdict: a dictionary with the input nodes, as they would
                be returned by get_inputs_dict (with the Code!)
        """
        try:
            parameters = inputdict.pop(self.get_linkname('parameters'))
        except KeyError:
            raise InputValidationError("No parameters specified for this "
                                       "calculation")
        if not isinstance(parameters, ParameterData):
            raise InputValidationError("parameters is not of type "
                                       "ParameterData")
        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError("No code specified for this "
                                       "calculation")
        if inputdict:
            raise ValidationError("Cannot add other nodes beside parameters")

        ##############################
        # END OF INITIAL INPUT CHECK #
        ##############################

        input_json = parameters.get_dict()

        # write all the input to a file
        input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME)
        with open(input_filename, 'w') as infile:
            json.dump(input_json, infile)

        # ============================ calcinfo ================================

        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.local_copy_list = []
        calcinfo.remote_copy_list = []
        calcinfo.retrieve_list = [self._OUTPUT_FILE_NAME]

        codeinfo = CodeInfo()
        codeinfo.cmdline_params = [
            self._INPUT_FILE_NAME, self._OUTPUT_FILE_NAME
        ]
        codeinfo.code_uuid = code.uuid
        calcinfo.codes_info = [codeinfo]

        return calcinfo
示例#16
0
    def _validate(self):

        super(AbstractCode, self)._validate()

        if self.is_local() is None:
            raise ValidationError("You did not set whether the code is local "
                                  "or remote")

        if self.is_local():
            if not self.get_local_executable():
                raise ValidationError(
                    "You have to set which file is the local executable "
                    "using the set_exec_filename() method")
                # c[1] is True if the element is a file
            if self.get_local_executable() not in self.get_folder_list():
                raise ValidationError(
                    "The local executable '{}' is not in the list of "
                    "files of this code".format(self.get_local_executable()))
        else:
            if self.get_folder_list():
                raise ValidationError(
                    "The code is remote but it has files inside")
            if not self.get_remote_computer():
                raise ValidationError("You did not specify a remote computer")
            if not self.get_remote_exec_path():
                raise ValidationError(
                    "You did not specify a remote executable")
示例#17
0
    def _validate(self):
        super()._validate()

        if self.is_local() is None:
            raise ValidationError(
                'You did not set whether the code is local or remote')

        if self.is_local():
            if not self.get_local_executable():
                raise ValidationError(
                    'You have to set which file is the local executable '
                    'using the set_exec_filename() method')
            if self.get_local_executable() not in self.list_object_names():
                raise ValidationError(
                    "The local executable '{}' is not in the list of "
                    'files of this code'.format(self.get_local_executable()))
        else:
            if self.list_object_names():
                raise ValidationError(
                    'The code is remote but it has files inside')
            if not self.get_remote_computer():
                raise ValidationError('You did not specify a remote computer')
            if not self.get_remote_exec_path():
                raise ValidationError(
                    'You did not specify a remote executable')
示例#18
0
    def _validate(self):
        """Validate the UPF potential file stored for this node."""
        from aiida.common.exceptions import ValidationError
        from aiida.common.files import md5_from_filelike

        super(UpfData, self)._validate()

        with self.open(mode='r') as handle:
            parsed_data = parse_upf(handle)

        # Open in binary mode which is required for generating the md5 checksum
        with self.open(mode='rb') as handle:
            md5 = md5_from_filelike(handle)

        try:
            element = parsed_data['element']
        except KeyError:
            raise ValidationError(
                "No 'element' could be parsed in the UPF {}".format(
                    self.filename))

        try:
            attr_element = self.get_attribute('element')
        except AttributeError:
            raise ValidationError("attribute 'element' not set.")

        try:
            attr_md5 = self.get_attribute('md5')
        except AttributeError:
            raise ValidationError("attribute 'md5' not set.")

        if attr_element != element:
            raise ValidationError(
                "Attribute 'element' says '{}' but '{}' was parsed instead.".
                format(attr_element, element))

        if attr_md5 != md5:
            raise ValidationError(
                "Attribute 'md5' says '{}' but '{}' was parsed instead.".
                format(attr_md5, md5))
示例#19
0
    def _default_mpiprocs_per_machine_validator(self, def_cpus_per_machine):
        """
        Validates the default number of CPUs per machine (node)
        """
        if def_cpus_per_machine is None:
            return

        if not isinstance(def_cpus_per_machine, (
                int, long)) or def_cpus_per_machine <= 0:
            raise ValidationError("Invalid value for default_mpiprocs_per_machine, "
                                  "must be a positive integer, or an empty "
                                  "string if you do not want to provide a "
                                  "default value.")
示例#20
0
    def _validate_inputs(self, inputdict):
        """ Validate input links.
        """
        # Check inputdict
        try:
            parameters = inputdict.pop(self.get_linkname('parameters'))
        except KeyError:
            raise InputValidationError("No parameters specified for this "
                                       "calculation")
        if not isinstance(parameters, RipsDistanceMatrixParameters):
            raise InputValidationError("parameters not of type "
                                       "RipsDistanceMatrixParameters")
        # Check code
        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError("No code specified for this "
                                       "calculation")

        # Check input files
        try:
            distance_matrix = inputdict.pop(
                self.get_linkname('distance_matrix'))
            if not isinstance(distance_matrix, SinglefileData):
                raise InputValidationError(
                    "distance_matrix not of type SinglefileData")
            symlink = None

        except KeyError:
            distance_matrix = None

            try:
                remote_folder = inputdict.pop(
                    self.get_linkname('remote_folder'))
                if not isinstance(remote_folder, RemoteData):
                    raise InputValidationError(
                        "remote_folder is not of type RemoteData")

                comp_uuid = remote_folder.get_computer().uuid
                remote_path = remote_folder.get_remote_path()
                symlink = (comp_uuid, remote_path, self._REMOTE_FOLDER_LINK)

            except KeyError:
                raise InputValidationError(
                    "Need to provide either distance_matrix or remote_folder")

        # Check that nothing is left unparsed
        if inputdict:
            raise ValidationError("Unrecognized inputs: {}".format(inputdict))

        return parameters, code, distance_matrix, symlink
    def _prepare_for_submission(self, tempfolder, inputdict):
        """
        Create input files.

            :param tempfolder: aiida.common.folders.Folder subclass where
                the plugin should put all its files.
            :param inputdict: dictionary of the input nodes as they would
                be returned by get_inputs_dict
        """
        # Check inputdict
        try:
            parameters = inputdict.pop(self.get_linkname('parameters'))
        except KeyError:
            raise InputValidationError("No parameters specified for this "
                                       "calculation")
        if not isinstance(parameters, MultiplyParameters):
            raise InputValidationError("parameters not of type "
                                       "MultiplyParameters")
        try:
            code = inputdict.pop(self.get_linkname('code'))
        except KeyError:
            raise InputValidationError("No code specified for this "
                                       "calculation")
        if inputdict:
            raise ValidationError("Unknown inputs besides MultiplyParameters")

        # In this example, the input file is simply a json dict.
        # Adapt for your particular code!
        input_dict = parameters.get_dict()

        # Write input to file
        input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME)
        with open(input_filename, 'w') as infile:
            json.dump(input_dict, infile)

        # Prepare CalcInfo to be returned to aiida
        calcinfo = CalcInfo()
        calcinfo.uuid = self.uuid
        calcinfo.local_copy_list = []
        calcinfo.remote_copy_list = []
        calcinfo.retrieve_list = [self._OUTPUT_FILE_NAME]

        codeinfo = CodeInfo()
        # will call ./code.py in.json out.json
        codeinfo.cmdline_params = [
            self._INPUT_FILE_NAME, self._OUTPUT_FILE_NAME
        ]
        codeinfo.code_uuid = code.uuid
        calcinfo.codes_info = [codeinfo]

        return calcinfo
示例#22
0
    def set_data(self, data):
        """
        Replace the current data with another one.

        :param data: The dictionary to set.
        """
        from aiida.common.exceptions import ModificationNotAllowed

        # first validate the inputs
        try:
            jsonschema.validate(data, self.data_schema)
        except SchemeError as err:
            raise ValidationError(err)

        kinds = data["kind_names"]
        for key, value in data.items():
            if len(value) != len(kinds):
                raise ValidationError(
                    "'{}' array not the same length as 'kind_names'"
                    "".format(key))

        # store all but the symmetry operations as attributes
        old_dict = copy.deepcopy(dict(self.iterattrs()))
        attributes_set = False
        try:
            # Delete existing attributes
            self._del_all_attrs()
            # I set the keys
            self._update_attrs(data)
            attributes_set = True
        finally:
            if not attributes_set:
                try:
                    # Try to restore the old data
                    self._del_all_attrs()
                    self._update_attrs(old_dict)
                except ModificationNotAllowed:
                    pass
示例#23
0
    def __init__(self, time, loggername="", levelname="", objname="", objpk=None,
                 message=None, metadata=None):

        if not loggername or not levelname:
            raise ValidationError(
                "The loggername and levelname can't be empty")

        self.time = time
        self.loggername = loggername
        self.levelname = levelname
        self.objname = objname
        self.objpk = objpk
        self.message = message
        self._metadata = metadata or {}
示例#24
0
    def _set_parent_remotedata(self,remotedata):
        """
        Used to set a parent remotefolder in the restart of ph.
        """
        if not isinstance(remotedata,RemoteData):
            raise ValueError('remotedata must be a RemoteData')
        
        # complain if another remotedata is already found
        input_remote = self.get_inputs(node_type=RemoteData)
        if input_remote:
            raise ValidationError("Cannot set several parent calculation to a "
                                  "ph calculation")

        self.use_parent_folder(remotedata)
示例#25
0
    def _validate_keys(self, input_dict):
        """
        Validates the keys otherwise raise ValidationError. Does basic
        validation from the parent followed by validations for the
        quantum numbers. Raises exceptions should the input_dict fail the
        valiation or if it contains any unsupported keywords.

        :param input_dict: the dictionary of keys to be validated
        :return validated_dict: a validated dictionary
        """
        validated_dict = super()._validate_keys(input_dict)

        # Validate m knowing the value of l
        angular_momentum = validated_dict[
            'angular_momentum']  # l quantum number, must be there
        magnetic_number = validated_dict[
            'magnetic_number']  # m quantum number, must be there
        if angular_momentum >= 0:
            accepted_range = [0, 2 * angular_momentum]
        else:
            accepted_range = [0, -angular_momentum]
        if magnetic_number < min(accepted_range) or magnetic_number > max(
                accepted_range):
            raise ValidationError(
                f'the magnetic number must be in the range [{min(accepted_range)}, {max(accepted_range)}]'
            )

        # Check if it is a known combination
        try:
            self.get_name_from_quantum_numbers(
                validated_dict['angular_momentum'],
                magnetic_number=validated_dict['magnetic_number'])
        except ValidationError:
            raise ValidationError(
                'Invalid angular momentum magnetic number combination')

        return validated_dict
示例#26
0
    def _validate(self, param, is_exact=True):
        """
        Used internally to verify the sanity of exclude, include lists
        """
        from aiida.orm import DataFactory, CalculationFactory

        for i in param:
            if not any([
                    i.startswith('calculation'),
                    i.startswith('code'),
                    i.startswith('data'),
                    i == 'all',
            ]):
                raise ValidationError("Module not recognized, allow prefixes "
                                      " are: calculation, code or data")
        the_param = [i + '.' for i in param]

        factorydict = {
            'calculation': locals()['CalculationFactory'],
            'data': locals()['DataFactory']
        }

        for i in the_param:
            base, module = i.split('.', 1)
            if base == 'code':
                if module:
                    raise ValidationError("Cannot have subclasses for codes")
            elif base == 'all':
                continue
            else:
                if is_exact:
                    try:
                        factorydict[base](module.rstrip('.'))
                    except MissingPluginError:
                        raise ValidationError(
                            "Cannot find the class to be excluded")
        return the_param
示例#27
0
    def _validate(self):
        """
        A validation method. Checks if an ``inp.xml`` file is in the FleurinpData.
        """
        #from aiida.common.exceptions import ValidationError
        # check if schema file path exists.
        super()._validate()

        if 'inp.xml' in self.files:
            # has_inpxml = True # does nothing so far
            pass
        else:
            raise ValidationError(
                'inp.xml file not in attribute "files". '
                'FleurinpData needs to have and inp.xml file!')
示例#28
0
    def _set_computer_string(self, string):
        """
        Set the computer starting from a string.
        """
        from aiida.common.exceptions import ValidationError, NotExistent
        from aiida.orm import Computer as AiidaOrmComputer

        try:
            computer = AiidaOrmComputer.get(string)
        except NotExistent:
            raise ValidationError("Computer with name '{}' not found in "
                                  "DB".format(string))

        self._computer_validator(computer)
        self.computer = computer
示例#29
0
    def strip_api_prefix(self, path):
        """
        Removes the PREFIX from an URL path. PREFIX must be defined in the
        config.py file::

            PREFIX = "/api/v2"
            path = "/api/v2/calculations/page/2"
            strip_api_prefix(path) ==> "/calculations/page/2"

        :param path: the URL path string
        :return: the same URL without the prefix
        """
        if path.startswith(self.prefix):
            return path[len(self.prefix):]

        raise ValidationError(f'path has to start with {self.prefix}')
示例#30
0
def strip_prefix(path):
    """
    Removes the PREFIX from an URL path. PREFIX must be defined in the
    config.py file.
    Ex. PREFIX = "/api/v2"
        path = "/api/v2/calculations/page/2"
        strip_prefix(path) ==> "/calculations/page/2"

    :param path: the URL path string
    :return: the same URL without the prefix
    """

    if path.startswith(PREFIX):
        return path[len(PREFIX):]
    else:
        raise ValidationError('path has to start with {}'.format(PREFIX))