Exemple #1
0
    def save_doc(self, doc, encode=False, force_update=False, **params):
        """ Save a document. It will use the `_id` member of the document
        or request a new uuid from CouchDB. IDs are attached to
        documents on the client side because POST has the curious property of
        being automatically retried by proxies in the event of network
        segmentation and lost responses. 

        @param doc: dict.  doc is updated
        with doc '_id' and '_rev' properties returned
        by CouchDB server when you save.
        @param force_update: boolean, if there is conlict, try to update
        with latest revision
        @param encode: Encode attachments if needed (depends on couchdb version)

        @return: new doc with updated revision an id
        """  
        if '_attachments' in doc and encode:
            doc['_attachments'] = encode_attachments(doc['_attachments'])
            
        headers = params.get('headers', {})
        headers.setdefault('Content-Type', 'application/json')
        params['headers'] = headers
        
        if '_id' in doc:
            docid = escape_docid(doc['_id'])
            try:
                resp = self.put(docid, payload=json.dumps(doc), **params)
            except ResourceConflict:
                if not force_update:
                    raise
                rev = self.last_rev(doc['_id'])
                doc['_rev'] = rev
                resp = self.put(docid, payload=json.dumps(doc), **params)
        else:
            json_doc = json.dumps(doc)
            try:
                doc['_id'] = self.uuids.next()
                resp = self.put(doc['_id'], payload=json_doc, **params)
            except ResourceConflict:
                resp = self.post(payload=json_doc, **params)
            
        json_res = resp.json_body
        doc1 = {}
        for a, n in aliases.items():
            if a in json_res:
                doc1[n] = json_res[a]
        doc.update(doc1)
        return doc
Exemple #2
0
def encode_params(params):
    """ encode parameters in json if needed """
    _params = {}
    if params:
        for name, value in params.items():
            if value is None:
                continue
            if name in ("key", "startkey", "endkey") or not isinstance(value, basestring):
                value = json.dumps(value).encode("utf-8")
            _params[name] = value
    return _params
Exemple #3
0
    def view(self, view_name, **params):
        try:
            dname, vname = view_name.split("/")
            path = "/_design/%s/_view/%s" % (dname, vname)
        except ValueError:
            path = view_name

        if "keys" in params:
            keys = params.pop("keys")
            return self.post(path, json.dumps({"keys": keys}, **params)).json_body

        return self.get(path, **params).json_body
Exemple #4
0
    def save_docs(self, docs, all_or_nothing=False, use_uuids=True):
        """ Bulk save. Modify Multiple Documents With a Single Request

        @param docs: list of docs
        @param use_uuids: add _id in doc who don't have it already set.
        @param all_or_nothing: In the case of a power failure, when the database 
        restarts either all the changes will have been saved or none of them.
        However, it does not do conflict checking, so the documents will


        @return doc lists updated with new revision or raise BulkSaveError 
        exception. You can access to doc created and docs in error as properties
        of this exception.
        """
            
        def is_id(doc):
            return '_id' in doc
            
        if use_uuids:
            noids = []
            for k, g in itertools.groupby(docs, is_id):
                if not k:
                    noids = list(g)
                    
            for doc in noids:
                nextid = self.uuids.next()
                if nextid:
                    doc['_id'] = nextid
                    
        payload = { "docs": docs }
        if all_or_nothing:
            payload["all-or-nothing"] = True
            
        # update docs
        res = self.post('/_bulk_docs', payload=json.dumps(payload),
                    headers={'Content-Type': 'application/json'})
            
        json_res = res.json_body
        errors = []
        for i, r in enumerate(json_res):
            if 'error' in r:
                doc1 = docs[i]
                doc1.update({'_id': r['id'], 
                                '_rev': r['rev']})
                errors.append(doc1)
            else:
                docs[i].update({'_id': r['id'], 
                                '_rev': r['rev']})
                                
        if errors:
            raise BulkSaveError(docs, errors)