def store_revision(self, meta, data, overwrite=False, trusted=False, # True for loading a serialized representation or other trusted sources name=None, # TODO name we decoded from URL path action=ACTION_SAVE, remote_addr=None, userid=None, wikiname=None, contenttype_current=None, contenttype_guessed=None, acl_parent=None, return_rev=False, fqname=None, ): """ Store a revision into the backend, write metadata and data to it. Usually this will be a new revision, either of an existing item or a new item. With overwrite mode, we can also store over existing revisions. :type meta: dict :type data: open file (file must be closed by caller) :param overwrite: if True, allow overwriting of existing revs. :param return_rev: if True, return a Revision instance of the just created revision :returns: a Revision instance or None """ if remote_addr is None: try: # if we get here outside a request, this won't work: remote_addr = unicode(request.remote_addr) except: pass if userid is None: try: # if we get here outside a request, this won't work: userid = flaskg.user.valid and flaskg.user.itemid or None except: pass if wikiname is None: wikiname = app.cfg.interwikiname state = {'trusted': trusted, NAME: [name], ACTION: action, ADDRESS: remote_addr, USERID: userid, WIKINAME: wikiname, NAMESPACE: None, ITEMID: self.itemid, # real itemid or None 'contenttype_current': contenttype_current, 'contenttype_guessed': contenttype_guessed, 'acl_parent': acl_parent, FQNAME: fqname, } ct = meta.get(CONTENTTYPE) if ct == CONTENTTYPE_USER: Schema = UserMetaSchema else: Schema = ContentMetaSchema m = Schema(meta) valid = m.validate(state) if not valid: logging.warning("metadata validation failed, see below") for e in m.children: logging.warning("{0}, {1}".format(e.valid, e)) logging.warning("data validation skipped as we have no valid metadata") if VALIDATION_HANDLING == VALIDATION_HANDLING_STRICT: raise ValueError('metadata validation failed and strict handling requested, see the log for details') # we do not have anything in m that is not defined in the schema, # e.g. userdefined meta keys or stuff we do not validate. thus, we # just update the meta dict with the validated stuff: meta.update(dict(m.value.items())) # we do not want None / empty values: # XXX do not kick out empty lists before fixing NAME processing: meta = dict([(k, v) for k, v in meta.items() if v not in [None, ]]) if valid and not validate_data(meta, data): # need valid metadata to validate data logging.warning("data validation failed") if VALIDATION_HANDLING == VALIDATION_HANDLING_STRICT: raise ValueError('data validation failed and strict handling requested, see the log for details') if self.itemid is None: self.itemid = meta[ITEMID] backend = self.backend if not overwrite: revid = meta.get(REVID) if revid is not None and revid in backend: raise ValueError('need overwrite=True to overwrite existing revisions') meta, data, content = self.preprocess(meta, data) data.seek(0) # rewind file backend_name, revid = backend.store(meta, data) meta[REVID] = revid self.indexer.index_revision(meta, content, backend_name) if not overwrite: self._current = self.indexer._document(revid=revid) if return_rev: return Revision(self, revid)
def store_revision(self, meta, data, overwrite=False, trusted=False, # True for loading a serialized representation or other trusted sources name=None, # TODO name we decoded from URL path action=u'SAVE', remote_addr=None, userid=None, wikiname=None, contenttype_current=None, contenttype_guessed=None, acl_parent=None, ): """ Store a revision into the backend, write metadata and data to it. Usually this will be a new revision, either of an existing item or a new item. With overwrite mode, we can also store over existing revisions. :type meta: dict :type data: open file (file must be closed by caller) :param overwrite: if True, allow overwriting of existing revs. :returns: a Revision instance of the just created revision """ if remote_addr is None: try: # if we get here outside a request, this won't work: remote_addr = unicode(request.remote_addr) except: pass if userid is None: try: # if we get here outside a request, this won't work: userid = flaskg.user.valid and flaskg.user.itemid or None except: pass if wikiname is None: wikiname = app.cfg.interwikiname state = {'trusted': trusted, keys.NAME: name, keys.ACTION: action, keys.ADDRESS: remote_addr, keys.USERID: userid, keys.WIKINAME: wikiname, keys.ITEMID: self.itemid, # real itemid or None 'contenttype_current': contenttype_current, 'contenttype_guessed': contenttype_guessed, 'acl_parent': acl_parent, } ct = meta.get(keys.CONTENTTYPE) if ct == CONTENTTYPE_USER: Schema = UserMetaSchema else: Schema = ContentMetaSchema m = Schema(meta) valid = m.validate(state) # TODO: currently we just log validation results. in the end we should # reject invalid stuff in some comfortable way. if not valid: logging.warning("metadata validation failed, see below") for e in m.children: logging.warning("{0}, {1}".format(e.valid, e)) # we do not have anything in m that is not defined in the schema, # e.g. userdefined meta keys or stuff we do not validate. thus, we # just update the meta dict with the validated stuff: meta.update(dict(m.value.items())) # we do not want None / empty values: meta = dict([(k, v) for k, v in meta.items() if v not in [None, []]]) if self.itemid is None: self.itemid = meta[ITEMID] backend = self.backend if not overwrite: revid = meta.get(REVID) if revid is not None and revid in backend: raise ValueError('need overwrite=True to overwrite existing revisions') meta, data, content = self.preprocess(meta, data) data.seek(0) # rewind file revid = backend.store(meta, data) meta[REVID] = revid self.indexer.index_revision(meta, content) if not overwrite: self._current = self.indexer._document(revid=revid) return Revision(self, revid)