class UserEXT(db.Model): """Represent a UserEXT record.""" __tablename__ = 'userEXT' id = db.Column(db.VARBINARY(255), primary_key=True, nullable=False) method = db.Column(db.String(50), primary_key=True, nullable=False) id_user = db.Column(db.Integer(15, unsigned=True), db.ForeignKey(User.id), nullable=False) user = db.relationship(User, backref="external_identifiers") __table_args__ = (db.Index('id_user', id_user, method, unique=True), db.Model.__table_args__)
class CollectionPortalbox(db.Model): """Represent a CollectionPortalbox record.""" __tablename__ = 'collection_portalbox' id_collection = db.Column(db.MediumInteger(9, unsigned=True), db.ForeignKey(Collection.id), primary_key=True) id_portalbox = db.Column(db.MediumInteger(9, unsigned=True), db.ForeignKey(Portalbox.id), primary_key=True) ln = db.Column(db.Char(5), primary_key=True, server_default='', nullable=False) position = db.Column(db.Char(3), nullable=False, server_default='top') score = db.Column(db.TinyInteger(4, unsigned=True), nullable=False, server_default='0') collection = db.relationship(Collection, backref='portalboxes', order_by=score) portalbox = db.relationship(Portalbox, backref='collections', order_by=score)
class BsrMETHODNAME(db.Model): """Represent a BsrMETHODNAME record.""" __tablename__ = 'bsrMETHODNAME' id_bsrMETHOD = db.Column(db.MediumInteger(9, unsigned=True), db.ForeignKey(BsrMETHOD.id), primary_key=True, nullable=False, autoincrement=False) ln = db.Column(db.String(5), primary_key=True, nullable=False) type = db.Column(db.String(3), primary_key=True, nullable=False) value = db.Column(db.String(255), nullable=False) method = db.relationship(BsrMETHOD, backref=db.backref('names', lazy='dynamic'))
class CrcLOANREQUEST(db.Model): """Represents a CrcLOANREQUEST record.""" def __init__(self): pass __tablename__ = 'crcLOANREQUEST' id = db.Column(db.Integer(15, unsigned=True), nullable=False, primary_key=True, autoincrement=True) id_crcBORROWER = db.Column(db.Integer(15, unsigned=True), db.ForeignKey(CrcBORROWER.id), nullable=False, server_default='0') id_bibrec = db.Column(db.MediumInteger(8, unsigned=True), db.ForeignKey(Bibrec.id), nullable=False, server_default='0') barcode = db.Column(db.String(30), db.ForeignKey(CrcITEM.barcode), nullable=False, server_default='') period_of_interest_from = db.Column(db.DateTime, nullable=False, server_default='1900-01-01 00:00:00') period_of_interest_to = db.Column(db.DateTime, nullable=False, server_default='1900-01-01 00:00:00') status = db.Column(db.String(20), nullable=False, server_default='') notes = db.Column(db.Text, nullable=True) request_date = db.Column(db.DateTime, nullable=False, server_default='1900-01-01 00:00:00') borrower = db.relationship(CrcBORROWER, backref='loanrequests') bibrec = db.relationship(Bibrec, backref='loanrequests') item = db.relationship(CrcITEM, backref='loanrequests')
class CollectionCollection(db.Model): """Represent a CollectionCollection record.""" __tablename__ = 'collection_collection' id_dad = db.Column(db.MediumInteger(9, unsigned=True), db.ForeignKey(Collection.id), primary_key=True) id_son = db.Column(db.MediumInteger(9, unsigned=True), db.ForeignKey(Collection.id), primary_key=True) type = db.Column(db.Char(1), nullable=False, server_default='r') score = db.Column(db.TinyInteger(4, unsigned=True), nullable=False, server_default='0') son = db.relationship( Collection, primaryjoin=id_son == Collection.id, backref='dads', # FIX # collection_class=db.attribute_mapped_collection('score'), order_by=db.asc(score)) dad = db.relationship(Collection, primaryjoin=id_dad == Collection.id, backref='sons', order_by=db.asc(score))
class CmtACTIONHISTORY(db.Model): """Represents a CmtACTIONHISTORY record.""" __tablename__ = 'cmtACTIONHISTORY' id_cmtRECORDCOMMENT = db.Column(db.Integer(15, unsigned=True), db.ForeignKey(CmtRECORDCOMMENT.id), nullable=True, primary_key=True) id_bibrec = db.Column(db.MediumInteger(8, unsigned=True), db.ForeignKey(Bibrec.id), nullable=True, primary_key=True) id_user = db.Column(db.Integer(15, unsigned=True), db.ForeignKey(User.id), nullable=True, primary_key=True) client_host = db.Column(db.Integer(10, unsigned=True), nullable=True) action_time = db.Column(db.DateTime, nullable=False, server_default='1900-01-01 00:00:00') action_code = db.Column(db.Char(1), nullable=False, index=True) recordcomment = db.relationship(CmtRECORDCOMMENT, backref='actionhistory') bibrec = db.relationship(Bibrec) user = db.relationship(User)
class BskEXTREC(db.Model): """Represents a BskEXTREC record.""" __tablename__ = 'bskEXTREC' id = db.Column(db.Integer(15, unsigned=True), nullable=False, primary_key=True) external_id = db.Column(db.Integer(15), nullable=False, server_default='0') collection_id = db.Column(db.MediumInteger(9, unsigned=True), db.ForeignKey(Collection.id), nullable=False, server_default='0') original_url = db.Column(db.Text, nullable=True) creation_date = db.Column(db.DateTime, nullable=False, server_default='1900-01-01 00:00:00') modification_date = db.Column(db.DateTime, nullable=False, server_default='1900-01-01 00:00:00') collection = db.relationship(Collection, backref='EXTRECs')
class ExpQUERYRESULT(db.Model): """Represents a ExpQUERYRESULT record.""" __tablename__ = 'expQUERYRESULT' id = db.Column(db.Integer(15, unsigned=True), nullable=False, primary_key=True, autoincrement=True) id_expQUERY = db.Column(db.Integer(15, unsigned=True), db.ForeignKey(ExpQUERY.id), nullable=False) result = db.Column(db.Text, nullable=False) status = db.Column(db.MediumInteger(12), nullable=False, server_default='0') status_message = db.Column(db.Text, nullable=False) query = db.relationship(ExpQUERY, backref='queryresults')
class NwsTAG(db.Model): """Represents a nwsTAG record.""" __tablename__ = 'nwsTAG' id = db.Column(db.Integer(15, unsigned=True), nullable=False, primary_key=True,autoincrement=True) id_story = db.Column(db.Integer(15, unsigned=True), db.ForeignKey('nwsSTORY.id')) tag = db.Column(db.String(64), nullable=False, default='') @property def serialize_tag(self): """Return object data in easily serializeable format""" return { 'id_story': self.id_story }
class RnkWORD01R(db.Model): """Represent a RnkWORD01R record.""" __tablename__ = 'rnkWORD01R' id_bibrec = db.Column(db.MediumInteger(8, unsigned=True), db.ForeignKey(Bibrec.id), nullable=False, primary_key=True) termlist = db.Column(db.LargeBinary, nullable=True) type = db.Column(db.Enum('CURRENT', 'FUTURE', 'TEMPORARY', name='rnkword_type'), nullable=False, server_default='CURRENT', primary_key=True) bibrec = db.relationship(Bibrec, backref='word01rs')
class BsrMETHODDATABUCKET(db.Model): """Represents a BsrMETHODDATABUCKET record.""" __tablename__ = 'bsrMETHODDATABUCKET' id_bsrMETHOD = db.Column(db.MediumInteger(9, unsigned=True), db.ForeignKey(BsrMETHOD.id), autoincrement=False, primary_key=True, nullable=False) bucket_no = db.Column(db.TinyInteger(2), primary_key=True, nullable=False, autoincrement=False) bucket_data = db.Column(db.LargeBinary) bucket_last_value = db.Column(db.String(255)) last_updated = db.Column(db.DateTime)
class RecordMetadata(db.Model): """Represent a json record inside the SQL database.""" __tablename__ = 'record_json' id = db.Column( db.MediumInteger(8, unsigned=True), db.ForeignKey(Record.id), primary_key=True, nullable=False, autoincrement=True ) json = db.Column(db.JSON, nullable=False) record = db.relationship(Record, backref='record_json')
class Bibdocmoreinfo(db.Model): """Represents a Bibdocmoreinfo record.""" __tablename__ = 'bibdocmoreinfo' id = db.Column(db.MediumInteger(9, unsigned=True), primary_key=True) id_bibdoc = db.Column(db.MediumInteger(9, unsigned=True), db.ForeignKey(Bibdoc.id), nullable=True) version = db.Column(db.TinyInteger(4, unsigned=True), nullable=True) format = db.Column(db.String(50), nullable=True) id_rel = db.Column(db.MediumInteger(9, unsigned=True), nullable=True) namespace = db.Column(db.Char(25), nullable=True) data_key = db.Column(db.Char(25)) data_value = db.Column(db.LargeBinary) __table_args__ = (db.Index('bibdocmoreinfo_key', id_bibdoc, version, format, id_rel, namespace, data_key), db.Model.__table_args__)
class ExpJOBRESULT(db.Model): """Represents a ExpJOBRESULT record.""" __tablename__ = 'expJOBRESULT' id = db.Column(db.Integer(15, unsigned=True), nullable=False, primary_key=True, autoincrement=True) id_expJOB = db.Column(db.Integer(15, unsigned=True), db.ForeignKey(ExpJOB.id), nullable=False) execution_time = db.Column(db.DateTime, nullable=False, server_default='1900-01-01 00:00:00') status = db.Column(db.MediumInteger(12), nullable=False, server_default='0') status_message = db.Column(db.Text, nullable=False) job = db.relationship(ExpJOB, backref='jobresults')
class HstRECORD(db.Model): """Represent a HstRECORD record.""" __tablename__ = 'hstRECORD' id = db.Column(db.Integer(15, unsigned=True), primary_key=True, nullable=False, autoincrement=True) id_bibrec = db.Column(db.MediumInteger(8, unsigned=True), db.ForeignKey(Bibrec.id), autoincrement=False, nullable=False, primary_key=True) marcxml = db.Column(db.iBinary, nullable=False) job_id = db.Column(db.MediumInteger(15, unsigned=True), nullable=False, index=True) job_name = db.Column(db.String(255), nullable=False, index=True) job_person = db.Column(db.String(255), nullable=False, index=True) job_date = db.Column(db.DateTime, nullable=False, index=True) job_details = db.Column(db.iBinary, nullable=False) affected_fields = db.Column(db.Text, nullable=True)
class BibHOLDINGPEN(db.Model): """Represent a BibHOLDINGPEN record.""" __tablename__ = 'bibHOLDINGPEN' changeset_id = db.Column(db.Integer(11), primary_key=True, autoincrement=True) changeset_date = db.Column(db.DateTime, nullable=False, server_default='1900-01-01 00:00:00', index=True) changeset_xml = db.Column(db.Text, nullable=False) oai_id = db.Column(db.String(40), nullable=False, server_default='') id_bibrec = db.Column(db.MediumInteger(8, unsigned=True), db.ForeignKey(Bibrec.id), nullable=False, server_default='0') bibrec = db.relationship(Bibrec, backref='holdingpen')
class BibEDITCACHE(db.Model): """Represent a BibEDITCACHE record.""" __tablename__ = 'bibEDITCACHE' id_bibrec = db.Column(db.MediumInteger(8, unsigned=True), db.ForeignKey(Bibrec.id), autoincrement=False, nullable=False, primary_key=True) uid = db.Column(db.Integer(15, unsigned=True), primary_key=True, nullable=False, autoincrement=False) data = db.Column(db.iBinary, nullable=False) post_date = db.Column(db.DateTime, nullable=False, index=True) is_active = db.Column(db.TinyInteger(1, unsigned=True), server_default='1', nullable=False)
class BskEXTFMT(db.Model): """Represents a BskEXTFMT record.""" __tablename__ = 'bskEXTFMT' id = db.Column(db.Integer(15, unsigned=True), nullable=False, primary_key=True) id_bskEXTREC = db.Column(db.Integer(15, unsigned=True), db.ForeignKey(BskEXTREC.id), nullable=False, server_default='0') format = db.Column(db.String(10), nullable=False, index=True, server_default='') last_updated = db.Column(db.DateTime, nullable=False, server_default='1900-01-01 00:00:00') value = db.Column(db.iLargeBinary, nullable=True) EXTREC = db.relationship(BskEXTREC, backref='EXTFMTs')
class BskBASKET(db.Model): """Represents a BskBASKET record.""" __tablename__ = 'bskBASKET' id = db.Column(db.Integer(15, unsigned=True), nullable=False, primary_key=True) id_owner = db.Column(db.Integer(15, unsigned=True), db.ForeignKey(User.id), nullable=False, server_default='0') name = db.Column(db.String(50), nullable=False, server_default='', index=True) date_modification = db.Column(db.DateTime, nullable=False, server_default='1900-01-01 00:00:00') nb_views = db.Column(db.Integer(15), nullable=False, server_default='0') owner = db.relationship(User, backref='baskets')
class FacetCollection(db.Model): """Facet configuration for collection.""" __tablename__ = 'facet_collection' id = db.Column(db.Integer, primary_key=True) id_collection = db.Column(db.MediumInteger(9, unsigned=True), db.ForeignKey(Collection.id)) order = db.Column(db.Integer) facet_name = db.Column(db.String(80)) collection = db.relationship(Collection, backref='facets') def __repr__(self): """Return class representation.""" return ('FacetCollection <id: {0.id}, id_collection: ' '{0.id_collection}, order: {0.order}, ' 'facet_name: {0.facet_name}>'.format(self)) @classmethod def is_place_taken(cls, id_collection, order): """Check if there is already a facet on the given position. .. note:: This works well as a pre-check, however saving can still fail if somebody else creates the same record in other session (phantom reads). """ return bool(cls.query.filter( cls.id_collection == id_collection, cls.order == order).count()) @classmethod def is_duplicated(cls, id_collection, facet_name): """Check if the given facet is already assigned to this collection. .. note:: This works well as a pre-check, however saving can still fail if somebody else creates the same record in other session (phantom reads). """ return bool(cls.query.filter( cls.id_collection == id_collection, cls.facet_name == facet_name).count())
class CollectionFormat(db.Model): """Represent a CollectionFormat record.""" __tablename__ = 'collection_format' id_collection = db.Column(db.MediumInteger(9, unsigned=True), db.ForeignKey(Collection.id), primary_key=True) format_code = db.Column('format', db.String(10), primary_key=True) score = db.Column(db.TinyInteger(4, unsigned=True), nullable=False, server_default='0') collection = db.relationship( Collection, backref=db.backref( 'formats', order_by=db.desc(score) ), order_by=db.desc(score)) @property def format(self): """Return output format definition.""" return output_formats[self.format_code]
class BsrMETHODDATA(db.Model): """Represent a BsrMETHODDATA record.""" __tablename__ = 'bsrMETHODDATA' id_bsrMETHOD = db.Column(db.MediumInteger(9, unsigned=True), db.ForeignKey(BsrMETHOD.id), primary_key=True, nullable=False, autoincrement=False) data_dict = db.Column(db.LargeBinary) data_dict_ordered = db.Column(db.LargeBinary) data_list_sorted = db.Column(db.LargeBinary) last_updated = db.Column(db.DateTime) @property def ordered(self): """Return deserialized orderd dict.""" return deserialize_via_marshal(self.data_dict_ordered) method = db.relationship(BsrMETHOD, backref='methoddata')
class Formatname(db.Model): """Represents a Formatname record.""" __tablename__ = 'formatname' id_format = db.Column( db.MediumInteger(9, unsigned=True), db.ForeignKey(Format.id), primary_key=True) ln = db.Column( db.Char(5), primary_key=True, server_default='') type = db.Column( db.Char(3), primary_key=True, server_default='sn') value = db.Column(db.String(255), nullable=False) format = db.relationship(Format, backref='names')
class HstTASK(db.Model): """Represents a HstTASK record.""" __tablename__ = 'hstTASK' id = db.Column(db.Integer(15, unsigned=True), nullable=False, primary_key=True, autoincrement=False) proc = db.Column(db.String(255), nullable=False) host = db.Column(db.String(255), nullable=False, server_default='') user = db.Column(db.String(50), nullable=False) runtime = db.Column(db.DateTime, nullable=False, index=True) sleeptime = db.Column(db.String(20), nullable=True) arguments = db.Column(db.iMediumBinary, nullable=True) status = db.Column(db.String(50), nullable=True, index=True) progress = db.Column(db.String(255), nullable=True) priority = db.Column(db.TinyInteger(4), nullable=False, server_default='0', index=True) sequenceid = db.Column(db.Integer(15, unsigned=True), db.ForeignKey(SeqSTORE.id))
class Bibfmt(db.Model): """Represents a Bibfmt record.""" __tablename__ = 'bibfmt' id_bibrec = db.Column( db.MediumInteger(8, unsigned=True), db.ForeignKey(Bibrec.id), nullable=False, server_default='0', primary_key=True, autoincrement=False) format = db.Column( db.String(10), nullable=False, server_default='', primary_key=True, index=True) kind = db.Column( db.String(10), nullable=False, server_default='', index=True ) last_updated = db.Column( db.DateTime, nullable=False, server_default='1900-01-01 00:00:00', index=True) value = db.Column(db.iLargeBinary) needs_2nd_pass = db.Column(db.TinyInteger(1), server_default='0') bibrec = db.relationship(Bibrec, backref='bibfmt')
class Collectionname(db.Model): """Represent a Collectionname record.""" __tablename__ = 'collectionname' id_collection = db.Column(db.MediumInteger(9, unsigned=True), db.ForeignKey(Collection.id), nullable=False, primary_key=True) ln = db.Column(db.Char(5), nullable=False, primary_key=True, server_default='') type = db.Column(db.Char(3), nullable=False, primary_key=True, server_default='sn') value = db.Column(db.String(255), nullable=False) @db.hybrid_property def ln_type(self): return (self.ln, self.type) @ln_type.setter def set_ln_type(self, value): (self.ln, self.type) = value
class BibWorkflowObject(db.Model): """Data model for wrapping data being run in the workflows. Main object being passed around in the workflows module when using the workflows API. It can be instantiated like this: .. code-block:: python obj = BibWorkflowObject() obj.save() Or, like this: .. code-block:: python obj = BibWorkflowObject.create_object() BibWorkflowObject provides some handy functions such as: .. code-block:: python obj.set_data("<xml ..... />") obj.get_data() == "<xml ..... />" obj.set_extra_data({"param": value}) obj.get_extra_data() == {"param": value} obj.add_task_result("myresult", {"result": 1}) Then to finally save the object .. code-block:: python obj.save() Now you can for example run it in a workflow: .. code-block:: python obj.start_workflow("sample_workflow") """ # db table definition __tablename__ = "bwlOBJECT" id = db.Column(db.Integer, primary_key=True) # Our internal data column. Default is encoded dict. _data = db.Column(db.LargeBinary, nullable=False, default=get_default_data()) _extra_data = db.Column(db.LargeBinary, nullable=False, default=get_default_extra_data()) id_workflow = db.Column(db.String(36), db.ForeignKey("bwlWORKFLOW.uuid"), nullable=True) version = db.Column(db.Integer(3), default=ObjectVersion.INITIAL, nullable=False) id_parent = db.Column(db.Integer, db.ForeignKey("bwlOBJECT.id"), default=None) child_objects = db.relationship("BibWorkflowObject", remote_side=[id_parent]) created = db.Column(db.DateTime, default=datetime.now, nullable=False) modified = db.Column(db.DateTime, default=datetime.now, onupdate=datetime.now, nullable=False) status = db.Column(db.String(255), default="", nullable=False) data_type = db.Column(db.String(150), default="", nullable=True) uri = db.Column(db.String(500), default="") id_user = db.Column(db.Integer, default=0, nullable=False) child_logs = db.relationship("BibWorkflowObjectLog", backref='bibworkflowobject', cascade="all, delete, delete-orphan") workflow = db.relationship( Workflow, foreign_keys=[id_workflow], remote_side=Workflow.uuid, ) _log = None @property def log(self): """Access logger object for this instance.""" if not self._log: db_handler_obj = BibWorkflowLogHandler(BibWorkflowObjectLog, "id") self._log = get_logger(logger_name="object.%s" % (self.id, ), db_handler_obj=db_handler_obj, loglevel=logging.DEBUG, obj=self) return self._log def get_data(self): """Get data saved in the object.""" return cPickle.loads(base64.b64decode(self._data)) def set_data(self, value): """Save data to the object.""" self._data = base64.b64encode(cPickle.dumps(value)) def get_extra_data(self): """Get extra data saved to the object.""" return cPickle.loads(base64.b64decode(self._extra_data)) def set_extra_data(self, value): """Save extra data to the object. :param value: what you want to replace extra_data with. :type value: dict """ self._extra_data = base64.b64encode(cPickle.dumps(value)) def get_workflow_name(self): """Return the workflow name for this object.""" try: if self.id_workflow: return Workflow.query.get(self.id_workflow).name except AttributeError: # Workflow non-existent pass return def get_formatted_data(self, of="hd"): """Get the formatted representation for this object.""" from .registry import workflows try: name = self.get_workflow_name() if not name: return "" workflow_definition = workflows[name] formatted_data = workflow_definition.formatter(self, of=of) except (KeyError, AttributeError): # Somehow the workflow or formatter does not exist from invenio.ext.logging import register_exception register_exception(alert_admin=True) formatted_data = "" return formatted_data def __repr__(self): """Represent a BibWorkflowObject.""" return "<BibWorkflowObject(id = %s, data = %s, id_workflow = %s, " \ "version = %s, id_parent = %s, created = %s, extra_data = %s)" \ % (str(self.id), str(self.get_data()), str(self.id_workflow), str(self.version), str(self.id_parent), str(self.created), str(self.get_extra_data())) def __eq__(self, other): """Enable equal operators on BibWorkflowObjects.""" if isinstance(other, BibWorkflowObject): if self._data == other._data and \ self._extra_data == other._extra_data and \ self.id_workflow == other.id_workflow and \ self.version == other.version and \ self.id_parent == other.id_parent and \ isinstance(self.created, datetime) and \ isinstance(self.modified, datetime): return True else: return False return NotImplemented def __ne__(self, other): """Enable equal operators on BibWorkflowObjects.""" return not self.__eq__(other) def add_task_result(self, name, result, template="workflows/results/default.html"): """Add a new task result defined by name. The name is the dictionary key used to group similar types of results as well as a possible label for the result. The result is a dictionary given as context to the template when rendered. The result given here is added to a list of results for this name. .. code-block:: python obj = BibWorkflowObject() # or BibWorkflowObject.query.get(id) obj.add_task_result("foo", my_result, "path/to/template") :param name: The name of the task in human friendly way. It is used as a key and label for the result rendering. :type name: string :param result: The result to store - passed to render_template(). :type result: dict :param template: The location of the template to render the result. :type template: string """ extra_data = getattr(self, "extra_data", self.get_extra_data()) task_result = {"name": name, "result": result, "template": template} if name in extra_data["_tasks_results"]: extra_data["_tasks_results"][name].append(task_result) else: extra_data["_tasks_results"][name] = [task_result] self.set_extra_data(extra_data) def update_task_results(self, name, results): """Update tasks results by name. The name is the dictionary key used to group similar types of results as well as a possible label for the result. This functions allows you to update (replace) the list of results associated with a name where each result is structured like this: .. code-block:: python task_result = { "name": "foo", "result": result, "template": template } obj = BibWorkflowObject() # or BibWorkflowObject.query.get(id) obj.update_task_results("foo", [task_result]) :param name: The name of the task in human friendly way. It is used as a key and label for the result rendering. :type name: string :param results: List of results to store - passed to render_template(). :type results: list :param template: The location of the template to render the result. :type template: string """ extra_data = getattr(self, "extra_data", self.get_extra_data()) extra_data["_tasks_results"][name] = results self.set_extra_data(extra_data) def get_tasks_results(self): """Return the complete set of tasks results. The result is given as a dictionary where each result is structured like: .. code-block:: python task_result = { "name": name, "result": result, "template": template } :return: dictionary of results as {name: [result, ..], ..} """ return self.get_extra_data()["_tasks_results"] def set_action(self, action, message): """Set the action to be taken for this object. Assign an special "action" to this object to be taken in consideration in Holding Pen. The widget is referred to by a string with the filename minus extension. A message is also needed to tell the user the action required in a textual way. :param action: name of the action to add (i.e. "approval") :type action: string :param message: message to show to the user :type message: string """ extra_data = self.get_extra_data() extra_data["_action"] = action extra_data["_message"] = message self.set_extra_data(extra_data) def get_action(self): """Retrieve the currently assigned action, if any. :return: name of action assigned as string, or None """ try: return self.get_extra_data()["_action"] except KeyError: # No widget, try old _widget extra_data = self.get_extra_data() if "_widget" in extra_data: import warnings warnings.warn("Widget's are now stored in '_action'", DeprecationWarning) # Migrate to new naming extra_data["_action"] = extra_data['_widget'] del extra_data["_widget"] self.set_extra_data(extra_data) return extra_data["_action"] return None def get_action_message(self): """Retrieve the currently assigned widget, if any.""" try: return unicodifier(self.get_extra_data()["_message"]) except KeyError: # No widget return "" def set_error_message(self, msg): """Set an error message.""" extra_data = self.get_extra_data() extra_data["_error_msg"] = msg self.set_extra_data(extra_data) def reset_error_message(self): """Reset the error message.""" extra_data = self.get_extra_data() if "_error_msg" in extra_data: del extra_data["_error_msg"] self.set_extra_data(extra_data) def get_error_message(self): """Retrieve the error message, if any.""" if "error_msg" in self.get_extra_data(): # Backwards compatibility extra_data = self.get_extra_data() msg = extra_data["error_msg"] del extra_data["error_msg"] self.set_extra_data(extra_data) self.set_error_message(msg) try: return self.get_extra_data()["_error_msg"] except KeyError: # No message return "" def remove_action(self): """Remove the currently assigned action.""" extra_data = self.get_extra_data() extra_data["_action"] = None extra_data["_message"] = "" if "_widget" in extra_data: del extra_data["_widget"] self.set_extra_data(extra_data) def start_workflow(self, workflow_name, delayed=False, **kwargs): """Run the workflow specified on the object. Will start workflows execution for the object using :py:func:`.api.start` (or :py:func:`.api.start_delayed` if `delayed=True`). :param workflow_name: name of workflow to run :type workflow_name: str :param delayed: should the workflow run asynchronously? :type delayed: bool :return: BibWorkflowEngine (or AsynchronousResultWrapper). """ if delayed: from .api import start_delayed as start_func else: from .api import start as start_func self.save() return start_func(workflow_name, data=[self], **kwargs) def continue_workflow(self, start_point="continue_next", delayed=False, **kwargs): """Continue the workflow for this object. Will continue a previous execution for the object using :py:func:`.api.continue_oid` (or :py:func:`.api.continue_oid_delayed` if `delayed=True`). The parameter `start_point` allows you to specify the point of where the workflow shall continue: * restart_prev: will restart from the previous task * continue_next: will continue to the next task * restart_task: will restart the current task :param start_point: where should the workflow start from? :type start_point: str :param delayed: should the workflow run asynchronously? :type delayed: bool :return: BibWorkflowEngine (or AsynchronousResultWrapper). """ from .errors import WorkflowAPIError self.save() if not self.id_workflow: raise WorkflowAPIError("No workflow associated with object: %r" % (repr(self), )) if delayed: from .api import continue_oid_delayed as continue_func else: from .api import continue_oid as continue_func return continue_func(self.id, start_point, **kwargs) def change_status(self, message): """Change the status.""" self.status = message def get_current_task(self): """Return the current task from the workflow engine for this object.""" extra_data = self.get_extra_data() try: return extra_data["_task_counter"] except KeyError: # Assume old version "task_counter" return extra_data["task_counter"] def get_current_task_info(self): """Return a dictionary of current task function info for this object.""" from .utils import get_workflow_definition, get_func_info task_pointer = self.get_current_task() name = self.get_workflow_name() if not name: return "" current_task = get_workflow_definition(name) for step in task_pointer: current_task = current_task[step] if callable(current_task): return get_func_info(current_task) def save_to_file(self, directory=None, prefix="workflow_object_data_", suffix=".obj"): """Save the contents of self.data['data'] to file. Returns path to saved file. Warning: Currently assumes non-binary content. """ if directory is None: directory = cfg['CFG_TMPSHAREDDIR'] tmp_fd, filename = tempfile.mkstemp(dir=directory, prefix=prefix, suffix=suffix) os.write(tmp_fd, self.get_data()) os.close(tmp_fd) return filename def get_log(self, *criteria, **filters): """Return a list of log entries from BibWorkflowObjectLog. You can specify additional filters following the SQLAlchemy syntax. Get all the logs for the object: .. code-block:: python b = BibWorkflowObject.query.get(1) b.get_log() Get all the logs for the object labeled as ERROR. .. code-block:: python b = BibWorkflowObject.query.get(1) b.get_log(BibWorkflowObjectLog.log_type == logging.ERROR) :return: list of BibWorkflowObjectLog """ criterions = [BibWorkflowObjectLog.id_object == self.id ] + list(criteria) res = BibWorkflowObjectLog.query.filter(*criterions).filter_by( **filters) return res.all() def __getstate__(self): """Return internal dict.""" return self.__dict__ def __setstate__(self, state): """Update interal dict with given state.""" self.__dict__ = state def copy(self, other): """Copy data and metadata except id and id_workflow.""" self._data = other._data self._extra_data = other._extra_data self.version = other.version self.id_parent = other.id_parent self.created = other.created self.modified = other.modified self.status = other.status self.data_type = other.data_type self.uri = other.uri @session_manager def save(self, version=None, task_counter=None, id_workflow=None): """Save object to persistent storage.""" if task_counter is not None: if isinstance(task_counter, list): self.log.debug("Saving task counter: %s" % (task_counter, )) extra_data = self.get_extra_data() extra_data["_task_counter"] = task_counter self.set_extra_data(extra_data) else: raise ValueError("Task counter must be a list!") if version is not None: if version != self.version: self.modified = datetime.now() self.version = version if id_workflow is not None: self.id_workflow = id_workflow db.session.add(self) if self.id is not None: self.log.debug("Saving object: %s" % (self.id or "new", )) @classmethod def get(cls, *criteria, **filters): """Wrapper of SQLAlchemy to get a BibWorkflowObject. A wrapper for the filter and filter_by functions of SQLAlchemy. Define a dict with which columns should be filtered by which values. .. code-block:: python Workflow.get(uuid=uuid) Workflow.get(Workflow.uuid != uuid) The function supports also "hybrid" arguments. .. code-block:: python Workflow.get(Workflow.module_name != 'i_hate_this_module', user_id=user_id) See also SQLAlchemy BaseQuery's filter and filter_by documentation. """ return cls.query.filter(*criteria).filter_by(**filters) @classmethod @session_manager def delete(cls, oid): """Delete a BibWorkflowObject.""" cls.get(BibWorkflowObject.id == oid).delete() @classmethod @session_manager def create_object(cls, **kwargs): """Create a new Workflow Object with given content.""" obj = BibWorkflowObject(**kwargs) db.session.add(obj) return obj @classmethod @session_manager def create_object_revision(cls, old_obj, version, **kwargs): """Create a Workflow Object copy with customized values.""" # Create new object and copy it obj = BibWorkflowObject(**kwargs) obj.copy(old_obj) # Overwrite some changes obj.version = version obj.created = datetime.now() obj.modified = datetime.now() for key, value in iteritems(kwargs): setattr(obj, key, value) db.session.add(obj) return obj
class MsgMESSAGE(db.Model): """Represents a MsgMESSAGE record.""" def __str__(self): return "From: %s<%s>, Subject: <%s> %s" % \ (self.user_from.nickname or _('None'), self.user_from.email or _('unknown'), self.subject, self.body) __tablename__ = 'msgMESSAGE' id = db.Column(db.Integer(15, unsigned=True), nullable=False, primary_key=True, autoincrement=True) id_user_from = db.Column(db.Integer(15, unsigned=True), db.ForeignKey(User.id), nullable=True, server_default='0') _sent_to_user_nicks = db.Column(db.Text, name='sent_to_user_nicks', nullable=False) _sent_to_group_names = db.Column(db.Text, name='sent_to_group_names', nullable=False) subject = db.Column(db.Text, nullable=False) body = db.Column(db.Text, nullable=True) sent_date = db.Column( db.DateTime, nullable=False, server_default='1900-01-01 00:00:00') # db.func.now() -> 'NOW()' received_date = db.Column(db.DateTime, server_default='1900-01-01 00:00:00') user_from = db.relationship(User, backref='sent_messages') #recipients = db.relationship(User, # secondary=lambda: UserMsgMESSAGE.__table__, # collection_class=set) recipients = association_proxy('sent_to_users', 'user_to', creator=lambda u: UserMsgMESSAGE(user_to=u)) @db.hybrid_property def sent_to_user_nicks(self): """ Alias for column 'sent_to_user_nicks'. """ return self._sent_to_user_nicks @db.hybrid_property def sent_to_group_names(self): """ Alias for column 'sent_to_group_names'. """ return self._sent_to_group_names @db.validates('_sent_to_user_nicks') def validate_sent_to_user_nicks(self, key, value): user_nicks = filter( len, map(strip, value.split(cfg['CFG_WEBMESSAGE_SEPARATOR']))) assert len(user_nicks) == len(set(user_nicks)) if len(user_nicks) > 0: assert len(user_nicks) == \ User.query.filter(User.nickname.in_(user_nicks)).count() return cfg['CFG_WEBMESSAGE_SEPARATOR'].join(user_nicks) @db.validates('_sent_to_group_names') def validate_sent_to_group_names(self, key, value): group_names = filter( len, map(strip, value.split(cfg['CFG_WEBMESSAGE_SEPARATOR']))) assert len(group_names) == len(set(group_names)) if len(group_names) > 0: assert len(group_names) == \ Usergroup.query.filter(Usergroup.name.in_(group_names)).count() return cfg['CFG_WEBMESSAGE_SEPARATOR'].join(group_names) @sent_to_user_nicks.setter def sent_to_user_nicks(self, value): old_user_nicks = self.user_nicks self._sent_to_user_nicks = value to_add = set(self.user_nicks) - set(old_user_nicks) to_del = set(old_user_nicks) - set(self.user_nicks) if len(self.group_names): to_del = to_del-set([u.nickname for u in User.query.\ join(User.usergroups).filter( Usergroup.name.in_(self.group_names)).\ all()]) if len(to_del): is_to_del = lambda u: u.nickname in to_del remove_old = filter(is_to_del, self.recipients) for u in remove_old: self.recipients.remove(u) if len(to_add): for u in User.query.filter(User.nickname.\ in_(to_add)).all(): if u not in self.recipients: self.recipients.append(u) @sent_to_group_names.setter def sent_to_group_names(self, value): old_group_names = self.group_names self._sent_to_group_names = value groups_to_add = set(self.group_names) - set(old_group_names) groups_to_del = set(old_group_names) - set(self.group_names) if len(groups_to_del): to_del = set([u.nickname for u in User.query.\ join(User.usergroups).filter( Usergroup.name.in_(groups_to_del)).\ all()])-set(self.user_nicks) is_to_del = lambda u: u.nickname in to_del remove_old = filter(is_to_del, self.recipients) for u in remove_old: self.recipients.remove(u) if len(groups_to_add): for u in User.query.join(User.usergroups).filter( db.and_(Usergroup.name.in_(groups_to_add), db.not_(User.nickname.in_( self.user_nicks)))).all(): if u not in self.recipients: self.recipients.append(u) @property def user_nicks(self): if not self._sent_to_user_nicks: return [] return filter( len, map( strip, self._sent_to_user_nicks.split( cfg['CFG_WEBMESSAGE_SEPARATOR']))) @property def group_names(self): if not self._sent_to_group_names: return [] return filter( len, map( strip, self.sent_to_group_names.split( cfg['CFG_WEBMESSAGE_SEPARATOR'])))
class CmtRECORDCOMMENT(db.Model): """Represents a CmtRECORDCOMMENT record.""" __tablename__ = 'cmtRECORDCOMMENT' id = db.Column(db.Integer(15, unsigned=True), nullable=False, primary_key=True, autoincrement=True) id_bibrec = db.Column(db.MediumInteger(8, unsigned=True), db.ForeignKey(Bibrec.id), nullable=False, server_default='0') id_user = db.Column(db.Integer(15, unsigned=True), db.ForeignKey(User.id), nullable=False, server_default='0') title = db.Column(db.String(255), nullable=False, server_default='') body = db.Column(db.Text, nullable=False) date_creation = db.Column(db.DateTime, nullable=False, server_default='1900-01-01 00:00:00') star_score = db.Column(db.TinyInteger(5, unsigned=True), nullable=False, server_default='0') nb_votes_yes = db.Column(db.Integer(10), nullable=False, server_default='0') nb_votes_total = db.Column(db.Integer(10, unsigned=True), nullable=False, server_default='0') nb_abuse_reports = db.Column(db.Integer(10), nullable=False, server_default='0') status = db.Column(db.Char(2), nullable=False, index=True, server_default='ok') round_name = db.Column(db.String(255), nullable=False, server_default='') restriction = db.Column(db.String(50), nullable=False, server_default='') in_reply_to_id_cmtRECORDCOMMENT = db.Column(db.Integer(15, unsigned=True), db.ForeignKey(id), nullable=False, server_default='0') reply_order_cached_data = db.Column(db.Binary, nullable=True) bibrec = db.relationship(Bibrec, backref='recordcomments') user = db.relationship(User, backref='recordcomments') replies = db.relationship('CmtRECORDCOMMENT', backref=db.backref('parent', remote_side=[id], order_by=date_creation)) @property def is_deleted(self): """Check if is deleted.""" return self.status != 'ok' def is_collapsed(self, id_user): """Return true if the comment is collapsed by user.""" return CmtCOLLAPSED.query.filter( db.and_(CmtCOLLAPSED.id_bibrec == self.id_bibrec, CmtCOLLAPSED.id_cmtRECORDCOMMENT == self.id, CmtCOLLAPSED.id_user == id_user)).count() > 0 @session_manager def collapse(self, id_user): """Collapse comment beloging to user.""" c = CmtCOLLAPSED(id_bibrec=self.id_bibrec, id_cmtRECORDCOMMENT=self.id, id_user=id_user) db.session.add(c) db.session.commit() def expand(self, id_user): """Expand comment beloging to user.""" CmtCOLLAPSED.query.filter( db.and_(CmtCOLLAPSED.id_bibrec == self.id_bibrec, CmtCOLLAPSED.id_cmtRECORDCOMMENT == self.id, CmtCOLLAPSED.id_user == id_user)).delete( synchronize_session=False) __table_args__ = (db.Index('cmtRECORDCOMMENT_reply_order_cached_data', reply_order_cached_data, mysql_length=40), db.Model.__table_args__) @classmethod def count(cls, *criteria, **filters): """Count how many comments.""" return cls.query.filter(*criteria).filter_by(**filters).count()
class BibWorkflowEngineLog(db.Model): """Represents a log entry for BibWorkflowEngine. This class represent a record of a log emit by an object into the database. The object must be saved before using this class as it requires the object id. """ __tablename__ = "bwlWORKFLOWLOGGING" id = db.Column(db.Integer, primary_key=True) id_object = db.Column(db.String(255), db.ForeignKey('bwlWORKFLOW.uuid'), nullable=False) log_type = db.Column(db.Integer, default=0, nullable=False) created = db.Column(db.DateTime, default=datetime.now) message = db.Column(db.TEXT, default="", nullable=False) def __str__(self): """Print a log.""" return "%(severity)s: %(created)s - %(message)s" % { "severity": self.log_type, "created": self.created, "message": self.message } def __repr__(self): """Represent a log message.""" return "BibWorkflowEngineLog(%s)" % (", ".join([ "log_type='%s'" % self.log_type, "created='%s'" % self.created, "message='%s'" % self.message, "id_object='%s'" % self.id_object ])) @classmethod def get(cls, *criteria, **filters): """Sqlalchemy wrapper to get BibWorkflowEngineLog. A wrapper for the filter and filter_by functions of sqlalchemy. Define a dict with which columns should be filtered by which values. look up also sqalchemy BaseQuery's filter and filter_by documentation """ return cls.query.filter(*criteria).filter_by(**filters) @classmethod def get_most_recent(cls, *criteria, **filters): """Return the most recently created log.""" most_recent = cls.get(*criteria, **filters).order_by( desc(BibWorkflowEngineLog.created)).first() if most_recent is None: raise NoResultFound else: return most_recent @classmethod def delete(cls, uuid=None): """Delete an instance in database.""" cls.get(BibWorkflowEngineLog.id == uuid).delete() db.session.commit()