Beispiel #1
0
def _check_valid_instance(*args, raise_error=True):
    for instance in args:
        valid = True
        try:
            object_mapper(instance)
        except UnmappedInstanceError:
            valid = False

        if raise_error and not valid:
            raise TypeError(f"Expected a mapped object instance; received: {instance}")
Beispiel #2
0
def saClone(o):
    '''
    "Clone" a SQLAlchemy object.  This function makes a copy of all basic SQLAlchemy attributes of an object.  It does
    not include relation properties or backrefs, only the column attributes.  Use this function to make duplicates of
    objects that will be copied but will have different primary keys.  The primary key(s) of the copied object will be
    set to None.
    
    @param o:  object to clone
    @type o: SQLAlchemy object
    @return: cloned object
    @rtype: SQLAlchemy object 
    '''
    log.debug('class to clone:' + str(o))
    r=o.__class__()
    pk_keys = set([c.key for c in object_mapper(o).primary_key])
    for prop in [p for p in object_mapper(o).iterate_properties]:
        # Exclude any relation properties
        if not hasattr(prop, 'uselist'):
            key = prop.key
            if key not in pk_keys:
                setattr(r, prop.key, getattr(o, prop.key, None))
    return r
Beispiel #3
0
def object_to_defaults(object, prefix):
    defaults = {}

    for key in object_mapper(object).columns.keys():
        value = getattr(object, key)
        if type(value) == list:
            for code in value:
                defaults['.'.join((prefix, key, code))] = 1
            defaults['.'.join((prefix, key))] = ','.join(value)
        elif value == True:
            defaults['.'.join((prefix, key))] = 1
        else:
            defaults['.'.join((prefix, key))] = value

    return defaults
Beispiel #4
0
def object_to_defaults(object, prefix):
    defaults = {}

    for key in object_mapper(object).columns.keys():
        value = getattr(object, key)
        if type(value) == list:
            for code in value:
                defaults['.'.join((prefix, key, code))] = 1
            defaults['.'.join((prefix, key))] = ','.join(value)
        elif value == True:
            defaults['.'.join((prefix, key))] = 1
        else:
            defaults['.'.join((prefix, key))] = value

    return defaults
Beispiel #5
0
 def default(self, obj):
     if hasattr(obj, '__json__'):
         return obj.__json__()
     elif isinstance(obj, (datetime.date, datetime.datetime)):
         return str(obj)
     elif isinstance(obj, decimal.Decimal):
         return float(obj)
     elif is_saobject(obj):
         props = {}
         for prop in object_mapper(obj).iterate_properties:
             if not hasattr(prop, 'uselist'):
                 props[prop.key] = getattr(obj, prop.key)
         return props
     elif isinstance(obj, ResultProxy):
         return list(obj)
     elif isinstance(obj, RowProxy):
         return dict(obj)
     else:
         return JSONEncoder.default(self, obj)
Beispiel #6
0
    def to_dict(self, fields=None):
        propdict = {}
        for prop in object_mapper(self).iterate_properties:
            if isinstance(prop, (ColumnProperty)):# or isinstance(prop, RelationProperty) and prop.secondary:
                if fields and prop.key not in fields: continue
                val = getattr(self, prop.key)
                if val:
                    if isinstance(val, datetime):
                        val = val.isoformat().split('.')[0].replace('+00:00','')+'Z'
    
                    if prop.key == 'json_attributes':
                        propdict.update(val)
                    else:
                        propdict[prop.key] = val
                else:
                    propdict[prop.key] = val

        for val in self._rd_collection_to_dict('tags', fields):
            propdict.setdefault('tags', []).append(val)

        return propdict
Beispiel #7
0
 def nodeToDict(self, folder):
     name=folder.name
     im0='folderClosed.gif'
     if folder.parentFolder is None:
         name = '/'
     retVal = dict(id=str(folder.folder_id), 
                   text=name, 
                   im0=im0, 
                   userdata=[dict(name='type', content='node')],
                   item=[])
     
     for subFolder in folder.folders:
         retVal['item'].append(self.nodeToDict(subFolder))
         
     # TODO: We should either have separate controllers for the SAR folders and the study folders,
     # or we should unify the primary key names for the study_file_manager and the sar_file tables.
     for file in folder.files + folder.studyFiles:
         m = object_mapper(file)
         pkCol = [c.name for c in m.tables[0].primary_key][0]
         id = getattr(file, pkCol)
         retVal['item'].append(dict(id=id, 
                                    text=file.name, 
                                    userdata=[dict(name='type', content='leaf')]))
     return retVal
Beispiel #8
0
def mergeMol(mol):
    """
    Certain attributes of a molecule (e.g. InChI, CAS number, IUPAC name) are unique.  This method analyzes
    a molecule to see if it might already exist in the database based on those unique attributes.  If the
    molecule is found in the database, this method does a consistency check, ensuring that any non-null, non-empty
    unique attributes match those of the database molecule.
    
    If the molecule is found in the db and the consistency check passes, merge the molecule's attributes into the
    db molecule. "Merge" means overwrite the db attribute if the db attribute is the empty string or null.

    If merging fails this function will raise an exception.  Merging should only fail if the mol passed in to this
    function and the mol in the database have conflicting values for a unique attribute.  For example, a CAS number
    is unique to a structure.  If the mol passed in has a different CAS number from the db mol, there is a problem--we
    don't know which is the correct one.
    
    Return the database molecule if found.  Otherwise add the passed in mol to the session and return it.
    
    At least ONE of the unique attributes must be set--in the case of a corporate compound, for example, you
    must set the structure, or a reg ID, or a CAS number, or the IUPAC name.  Otherwise there is no handle to
    uniquely identify the molecule.
    
    @param mol: molecule to merge with matching database molecule 
    @type mol: _RegMolBase
    @return: the merged molecule
    @rtype: _RegMolBase
    """

    # There should be at most one version of the molecule in the database
    
    #  Get list of indexes for the table storing the molecules
    m = object_mapper(mol)
    indexes=m.tables[0].indexes
    # Get list of attributes that must be unique
    uniqueAttributes = []
    for col in m.tables[0].primary_key:
        uniqueAttributes.append(col.name)
    for i in indexes:
        if i.unique:
            if len(i.columns) == 1:
                attr = i.columns[0].name
                if attr not in uniqueAttributes:
                    uniqueAttributes.append(attr)

    # Sort the unique attributes. This guarantees that we analyze them in the same way each time, improving our
    # ability to properly unit test this method.
    uniqueAttributes.sort()

    # Check each unique attribute.  If the passed in molecule has a non-None, non-empty string value, search
    # the db.  If a db mol is found, move on to the merge.  If no db mol is found, continue checking the unique
    # attributes. 
    query = None
    attr = None
    mols=[]
    validMol = False # a valid molecule must have at least ONE unique attribute set
    for attr in uniqueAttributes:
        attrVal = getattr(mol,attr)
        if attrVal is not None and attrVal is not None:
            query = DBSession().query(type(mol)).filter(type(mol).__dict__[attr] == getattr(mol,attr))
            mols = query.all()
            validMol = True
            if mols:
                break

    if not validMol:
        raise MissingUniqueAttrError('At least one unique attribute must be set for a molecule: check ' + ','. join(uniqueAttributes))

    if len(mols) > 1:
        raise Exception("Unique constraint on " + attr + " violated: check " + ','.join([t.name for t in object_mapper(mol).tables]))
    
    # Check if we were not able to find a molecule in the database
    if len(mols) == 0:
        mol.mol_id = None  # make sure database assigns the primary key
        DBSession().add(mol)
        return mol

    dbMol = mols[0]
    #  The molecule exists in the database.  Make sure that any unique property of the database molecule matches
    #  the one passed in.  For example, CAS number is unique.  The CAS number of the passed in molecule must
    #  be the same as the one in the database, or something is wrong.
    msgs = []
    parameters = { 'molid' : dbMol.molid, 'param' : []}
    for attr in uniqueAttributes:
        molVal = getattr(mol, attr, None)
        dbVal = getattr(dbMol, attr, None)
        if dbVal and molVal and dbVal != molVal:
            msgs.append('%s:  Compound database has value of %s, tried to register new value of  %s' % (attr, dbVal, molVal))
            parameters['param'].append(dict(attr=attr, dbVal=dbVal, molVal=molVal))
        
    if msgs:
        msg = 'Inconsistent values for properties of molecule during registration to database\n' + '\n'.join(msgs)
        raise InconsistentMolError(msg, parameters)

    #  Everything checks out as consistent.  Update the db mol from the passed-in mol (for any cases where the mol
    #  attribute has a value)
    for c in m.tables[0].columns:
        if c.primary_key:
            continue
        attr=c.name
        molVal = getattr(mol, attr, None)
        dbVal = getattr(dbMol, attr, None)
        if molVal:
            setattr(dbMol, attr, molVal)
    
    return dbMol
Beispiel #9
0
 def __iter__(self):
     self._i = iter(object_mapper(self).columns)
     return self