Esempio n. 1
0
    def get_dbcomputer(cls, computer):
        """
        Return a DbComputer from its name (or from another Computer or DbComputer instance)
        """

        from aiida.orm.computer import Computer
        if isinstance(computer, basestring):
            try:
                dbcomputer = cls.session.query(cls).filter(cls.name==computer).one()
            except NoResultFound:
                raise NotExistent("No computer found in the table of computers with "
                                  "the given name '{}'".format(computer))
            except MultipleResultsFound:
                raise DbContentError("There is more than one computer with name '{}', "
                                     "pass a Computer instance".format(computer))
        elif isinstance(computer, int):
            try:
                dbcomputer = cls.session.query(cls).filter(cls.id==computer).one()
            except NoResultFound:
                raise NotExistent("No computer found in the table of computers with "
                                  "the given id '{}'".format(computer))
        elif isinstance(computer, DbComputer):
            if computer.id is None:
                raise ValueError("The computer instance you are passing has not been stored yet")
            dbcomputer = computer
        elif isinstance(computer, Computer):
            if computer.dbcomputer.id is None:
                raise ValueError("The computer instance you are passing has not been stored yet")
            dbcomputer = computer.dbcomputer
        else:
            raise TypeError("Pass either a computer name, a DbComputer SQLAlchemy instance, a Computer id or a Computer object")
        return dbcomputer
Esempio n. 2
0
 def get_transport_params(self):
     try:
         return json.loads(self.dbcomputer.transport_params)
     except ValueError:
         raise DbContentError(
             "Error while reading transport_params for computer {}".format(
                 self.hostname))
Esempio n. 3
0
def get_query_type_string(plugin_type_string):
    """
    Receives a plugin_type_string, an attribute of subclasses of Node.
    Checks whether it is a valid type_string and manipulates the string
    to return a string that in a query returns all instances of a class and
    all instances of subclasses.

    :param plugin_type_string: The plugin_type_string

    :returns: the query_type_string
    """
    from aiida.common.exceptions import DbContentError, InputValidationError
    if not isinstance(plugin_type_string, basestring):
        raise InputValidationError("You have to pass as argument")
    # First case, an empty string for Node:
    if plugin_type_string == '':
        query_type_string = ''
    # Anything else should have baseclass.Class., so at least 2 dots
    # and end with a dot:
    elif not (plugin_type_string.endswith('.')) or plugin_type_string.count(
            '.') == 1:
        raise DbContentError(
            "The type name '{}' is not valid!".format(plugin_type_string))
    else:
        query_type_string = '{}.'.format('.'.join(
            plugin_type_string.split('.')[:-2]))
    return query_type_string
Esempio n. 4
0
    def getvalue(self, attr):
        """This can be called on a given row and will get the corresponding value, casting it correctly. """
        try:
            if attr.datatype == 'list' or attr.datatype == 'dict':
                prefix = '{}{}'.format(attr.key, self._sep)
                prefix_len = len(prefix)
                dballsubvalues = self._model_class.objects.filter(
                    key__startswith=prefix,
                    **self.subspecifiers_dict(attr)).values_list('key',
                                                           'datatype', 'tval', 'fval',
                                                           'ival', 'bval', 'dval')
                # Strip the FULL prefix and replace it with the simple
                # "attr" prefix
                data = {'attr.{}'.format(_[0][prefix_len:]): {
                    'datatype': _[1],
                    'tval': _[2],
                    'fval': _[3],
                    'ival': _[4],
                    'bval': _[5],
                    'dval': _[6],
                } for _ in dballsubvalues
                }
                # for _ in dballsubvalues}
                # Append also the item itself
                data['attr'] = {
                    # Replace the key (which may contain the separator) with the
                    # simple "attr" key. In any case I do not need to return it!
                    'key': 'attr',
                    'datatype': attr.datatype,
                    'tval': attr.tval,
                    'fval': attr.fval,
                    'ival': attr.ival,
                    'bval': attr.bval,
                    'dval': attr.dval}
                return deserialize_attributes(data, sep=self._sep,
                                              original_class=self._model_class,
                                              original_pk=self.subspecifier_pk(attr))['attr']
            else:
                data = {'attr': {
                    # Replace the key (which may contain the separator) with the
                    # simple "attr" key. In any case I do not need to return it!
                    'key': 'attr',
                    'datatype': attr.datatype,
                    'tval': attr.tval,
                    'fval': attr.fval,
                    'ival': attr.ival,
                    'bval': attr.bval,
                    'dval': attr.dval}}

                return deserialize_attributes(data, sep=self._sep,
                                              original_class=self._model_class,
                                              original_pk=self.subspecifier_pk(attr))['attr']
        except DeserializationException as exc:
            exc = DbContentError(exc)
            exc.original_exception = exc
            raise exc
Esempio n. 5
0
def get_class_typestring(type_string):
    """
    Given the type string, return three strings: the first one is
    one of the first-level classes that the Node can be:
    "node", "calculation", "code", "data".
    The second string is the one that can be passed to the DataFactory or
    CalculationFactory (or an empty string for nodes and codes);
    the third one is the name of the python class that would be loaded.
    """
    from aiida.common.exceptions import DbContentError

    if type_string == "":
        return ("node", "")
    else:
        pieces = type_string.split('.')
        if pieces[-1]:
            raise DbContentError("The type string does not end with a dot")
        if len(pieces) < 3:
            raise DbContentError("Not enough parts in the type string")
        return pieces[0], ".".join(pieces[1:-2]), pieces[-2]
Esempio n. 6
0
def from_type_to_pluginclassname(typestr):
    """
    Return the string to pass to the load_plugin function, starting from
    the 'type' field of a Node.
    """
    # Fix for base class
    from aiida.common.exceptions import DbContentError
    if typestr == "":
        typestr = "node.Node."
    if not typestr.endswith("."):
        raise DbContentError(
            "The type name '{}' is not valid!".format(typestr))
    return typestr[:-1]  # Strip final dot
Esempio n. 7
0
def get_plugin_type_from_type_string(type_string):
    """
    Take the type string of a Node and create the loadable plugin type string

    :param type_string: the value from the 'type' column of the Node table
    :return: the type string that can be used to load the plugin
    """
    if type_string == '':
        type_string = 'node.Node.'

    if not type_string.endswith('.'):
        raise DbContentError(
            "The type string '{}' is invalid".format(type_string))

    # Return the type string minus the trailing period
    return type_string[:-1]
Esempio n. 8
0
    def get_aiida_class(self):
        """
        Return the corresponding aiida instance of class aiida.orm.Node or a
        appropriate subclass.
        """
        from aiida.orm.node import Node
        from aiida.plugins.loader import get_plugin_type_from_type_string, load_plugin

        try:
            plugin_type = get_plugin_type_from_type_string(self.type)
        except DbContentError:
            raise DbContentError("The type name of node with pk= {} is "
                                 "not valid: '{}'".format(self.pk, self.type))

        PluginClass = load_plugin(plugin_type, safe=True)

        return PluginClass(dbnode=self)
Esempio n. 9
0
def get_query_type_from_type_string(type_string):
    """
    Take the type string of a Node and create the queryable type string

    :param type_string: the plugin_type_string attribute of a Node
    :return: the type string that can be used to query for
    """
    if type_string == '':
        return ''

    if not type_string.endswith('.') or type_string.count('.') == 1:
        raise DbContentError(
            "The type string '{}' is invalid".format(type_string))

    type_path, type_class, sep = type_string.rsplit('.', 2)
    type_string = type_path + '.'

    return type_string
Esempio n. 10
0
    def get_aiida_class(self):
        """
        Return the corresponding aiida instance of class aiida.orm.Node or a
        appropriate subclass.
        """
        from aiida.common.old_pluginloader import from_type_to_pluginclassname
        from aiida.orm.node import Node
        from aiida.common.pluginloader import load_plugin_safe

        try:
            pluginclassname = from_type_to_pluginclassname(self.type)
        except DbContentError:
            raise DbContentError("The type name of node with pk= {} is "
                                 "not valid: '{}'".format(self.pk, self.type))

        PluginClass = load_plugin_safe(Node, 'aiida.orm', pluginclassname,
                                       self.type, self.pk)

        return PluginClass(dbnode=self)
Esempio n. 11
0
    def get_state(self, from_attribute=False):
        """
        Get the state of the calculation.

        .. note:: this method returns the NOTFOUND state if no state
          is found in the DB.

        .. note:: the 'most recent' state is obtained using the logic in the
          ``aiida.common.datastructures.sort_states`` function.

        .. todo:: Understand if the state returned when no state entry is found
          in the DB is the best choice.

        :param from_attribute: if set to True, read it from the attributes
          (the attribute is also set with set_state, unless the state is set
          to IMPORTED; in this way we can also see the state before storing).

        :return: a string. If from_attribute is True and no attribute is found,
          return None. If from_attribute is False and no entry is found in the
          DB, return the "NOTFOUND" state.
        """
        from aiida.backends.djsite.db.models import DbCalcState
        if from_attribute:
            return self.get_attr('state', None)
        else:
            if not self.is_stored:
                return calc_states.NEW
            else:
                this_calc_states = DbCalcState.objects.filter(
                    dbnode=self).values_list('state', flat=True)
                if not this_calc_states:
                    return None
                else:
                    try:
                        most_recent_state = sort_states(this_calc_states)[0]
                    except ValueError as e:
                        raise DbContentError("Error in the content of the "
                                             "DbCalcState table ({})".format(
                            e.message))

                    return most_recent_state
Esempio n. 12
0
    def get_aiida_class(self):
        """
        Return the corresponding aiida instance of class aiida.orm.Node or a
        appropriate subclass.
        """
        from aiida.common.pluginloader import from_type_to_pluginclassname
        from aiida.orm.node import Node

        try:
            pluginclassname = from_type_to_pluginclassname(self.type)
        except DbContentError:
            raise DbContentError("The type name of node with pk= {} is "
                                 "not valid: '{}'".format(self.pk, self.type))

        try:
            PluginClass = load_plugin(Node, 'aiida.orm', pluginclassname)
        except MissingPluginError:
            aiidalogger.error("Unable to find plugin for type '{}' (node= {}), "
                              "will use base Node class".format(self.type, self.pk))
            PluginClass = Node

        return PluginClass(dbnode=self)
Esempio n. 13
0
def get_db_columns(db_class):
    """
    This function returns a dictionary where the keys are the columns of
    the table corresponding to the db_class and the values are the column
    properties such as type, is_foreign_key and if so, the related table
    and column.
    :param db_class: the database model whose schema has to be returned
    :return: a dictionary
    """

    import datetime

    django2python_map = {
        'AutoField': int,
        'BooleanField': bool,
        'CharField': str,
        'DateTimeField': datetime.datetime,
        'EmailField': str,
        'FloatField': float,
        'IntegerField': int,
        'TextField': str,
        'UUIDField': str,
    }

    ## Retrieve the columns of the table corresponding to the present class
    columns = db_class._meta.fields

    column_names = []
    column_types = []
    column_python_types = []
    foreign_keys = []

    ## retrieve names, types, and convert types in python types.
    for column in columns:

        name = column.get_attname()
        type = column.get_internal_type()

        column_names.append(name)

        # Check for foreignkeys and compile a dictionary with the required
        # informations
        if type is 'ForeignKey':
            # relation is a tuple with the related table and the related field
            relation = column.resolve_related_fields()
            if len(relation) == 0:
                raise DbContentError(' "{}" field has no foreign '
                                     'relationship')
            elif len(relation) > 1:
                raise DbContentError(' "{}" field has not a unique foreign '
                                     'relationship')
            else:
                #Collect infos of the foreing key
                foreign_keys.append((name, relation[0][0], relation[0][1]))
                #Change the type according to the type of the related column
                type = relation[0][1].get_internal_type()

        column_types.append(type)

    column_python_types = map(lambda x: django2python_map[x], column_types)

    ## Fill in the returned dictionary
    schema = {}

    # Fill in the keys based on the column names and the types. By default we
    #  assume that columns are no foreign keys
    for k, v in iter(zip(column_names, column_python_types)):
        schema[k] = {'type': v, 'is_foreign_key': False}

    # Add infos about the foreign relationships
    for k, related_class, related_field in foreign_keys:
        schema[k].update({
            'is_foreign_key': True,
            'related_table': related_class.rel.to.__name__,
            'related_column': related_field.get_attname()
        })

    return schema