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}")
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
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
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)
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
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
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
def __iter__(self): self._i = iter(object_mapper(self).columns) return self