Esempio n. 1
0
    def put_attachment(self, doc, content, name=None, content_type=None, 
        content_length=None):
        """ Add attachement to a document. All attachments are streamed.

        @param doc: dict, document object
        @param content: string or :obj:`File` object.
        @param name: name or attachment (file name).
        @param content_type: string, mimetype of attachment.
        If you don't set it, it will be autodetected.
        @param content_lenght: int, size of attachment.

        @return: bool, True if everything was ok.


        Example:
            
            >>> from simplecouchdb import server
            >>> server = server()
            >>> db = server.create_db('couchapp_test')
            >>> doc = { 'string': 'test', 'number': 4 }
            >>> db.save(doc)
            >>> text_attachment = u'un texte attaché'
            >>> db.put_attachment(doc, text_attachment, "test", "text/plain")
            True
            >>> file = db.fetch_attachment(doc, 'test')
            >>> result = db.delete_attachment(doc, 'test')
            >>> result['ok']
            True
            >>> db.fetch_attachment(doc, 'test')
            >>> del server['couchapp_test']
            {u'ok': True}
        """
        headers = {}
        
        if not content:
            content = ""
            content_length = 0
        if name is None:
            if hasattr(content, "name"):
                name = content.name
            else:
                raise InvalidAttachment('You should provid a valid attachment name')
        name = resource.url_quote(name, safe="")
        if content_type is None:
            content_type = ';'.join(filter(None, mimetypes.guess_type(name)))

        if content_type:
            headers['Content-Type'] = content_type
            
        # add appropriate headers    
        if content_length and content_length is not None:
            headers['Content-Length'] = content_length

        result = self.res(resource.escape_docid(doc['_id'])).put(name, payload=content, 
                headers=headers, rev=doc['_rev'])

        if result['ok']:
            doc.update({ '_rev': result['rev']})
        return result['ok']
Esempio n. 2
0
 def compact(self, dname=None, _raw_json=False):
     """ compact database
     @param dname: string, name of design doc. Usefull to 
     compact a view.
     """
     path = "/_compact"
     if dname is not None:
         path = "%s/%s" % (path, resource.escape_docid(dname))
     res = self.res.post(path, _raw_json=_raw_json)
     return res
Esempio n. 3
0
    def doc_exist(self, docid):
        """Test if document exists in a database

        @param docid: str, document id
        @return: boolean, True if document exist
        """

        try:
            data = self.res.head(resource.escape_docid(docid))
        except ResourceNotFound:
            return False
        return True
Esempio n. 4
0
    def delete_attachment(self, doc, name):
        """ delete attachement to the document

        @param doc: dict, document object in python
        @param name: name of attachement
    
        @return: dict, with member ok set to True if delete was ok.
        """
        name = resource.url_quote(name, safe="")
        
        res = self.res(resource.escape_docid(doc['_id'])).delete(name, rev=doc['_rev'])
        if res['ok']:
            doc.update({ '_rev': res['rev']})
        return res['ok']
Esempio n. 5
0
    def delete_doc(self, doc, _raw_json=False):
        """ delete a document or a list of documents
        @param doc: str or dict,  document id or full doc.
        @param _raw_json: return raw json instead deserializing it
        @return: dict like:
       
        .. code-block:: python

            {"ok":true,"rev":"2839830636"}
        """
        result = { 'ok': False }
        if isinstance(doc, dict):
            if not '_id' or not '_rev' in doc:
                raise KeyError('_id and _rev are required to delete a doc')
                
            docid = resource.escape_docid(doc['_id'])
            result = self.res.delete(docid, _raw_json=_raw_json, rev=doc['_rev'])
        elif isinstance(doc, basestring): # we get a docid
            docid = resource.escape_docid(doc)
            data = self.res.head(docid)
            response = self.res.response
            result = self.res.delete(docid, raw_json=_raw_json, 
                                    rev=response['etag'].strip('"'))
        return result
Esempio n. 6
0
    def fetch_attachment(self, id_or_doc, name, stream=False):
        """ get attachment in a document
        
        @param id_or_doc: str or dict, doc id or document dict
        @param name: name of attachment default: default result
        @param stream: boolean, response return a ResponseStream object
        @param stream_size: int, size in bytes of response stream block
        
        @return: str, attachment
        """

        if isinstance(id_or_doc, basestring):
            docid = id_or_doc
        else:
            docid = id_or_doc['_id']
      
        name = resource.url_quote(name, safe="")
        return self.res(resource.escape_docid(docid)).get(name, _stream=stream)
Esempio n. 7
0
    def save_doc(self, doc, encode_attachments=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. (Idee from `Couchrest <http://github.com/jchris/couchrest/>`)

        @param doc: dict.  doc is updated 
        with doc '_id' and '_rev' properties returned 
        by CouchDB server when you save.
        @param _raw_json: return raw json instead deserializing it
        @param params, list of optionnal params, like batch="ok"
        
        with `_raw_json=True` It return raw response. If False it update 
        doc instance with new revision (if batch=False).
        """
        if doc is None:
            doc = {}
            
        _raw_json = params.get('_raw_json', False)
            
        if '_attachments' in doc and encode_attachments:
            doc['_attachments'] = resource.encode_attachments(doc['_attachments'])
            
        if '_id' in doc:
            docid = resource.escape_docid(doc['_id'])
            res = self.res.put(docid, payload=doc, _raw_json=_raw_json, **params)
        else:
            try:
                doc['_id'] = self.server.next_uuid()
                res = self.res.put(doc['_id'], payload=doc, **params)
            except:
                res = self.res.post(payload=doc, **params)
                
        if _raw_json:    
            return res
                
        if 'batch' in params and 'id' in res:
            doc.update({ '_id': res['id']})
        else:
            doc.update({ '_id': res['id'], '_rev': res['rev']})
Esempio n. 8
0
    def get_doc(self, docid, wrapper=None, **params):
        """Get document from database
        
        Args:
        @param docid: str, document id to retrieve 
        @param rev: if specified, allows you to retrieve
        a specific revision of document
        @param wrapper: callable. function that takes dict as a param. 
        Used to wrap an object.
        @param _raw_json: return raw json instead deserializing it
        
        @return: dict, representation of CouchDB document as
         a dict.
        """
        docid = resource.escape_docid(docid)
        doc = self.res.get(docid, **params)

        if wrapper is not None:
            if not callable(wrapper):
                raise TypeError("wrapper isn't a callable")
            return wrapper(doc)
        
        return doc
Esempio n. 9
0
    def doc_revisions(self, docid, with_doc=True, _raw_json=False):
        """ retrieve revisions of a doc
            
        @param docid: str, id of document
        @param with_doc: bool, if True return document
        dict with revisions as member, if false return 
        only revisions
        @param _raw_json: return raw json instead deserializing it
        
        @return: dict: '_rev_infos' member if you have set with_doc
        to True :
        

                {
                    "_revs_info": [
                        {"rev": "123456", "status": "disk"},
                            {"rev": "234567", "status": "missing"},
                            {"rev": "345678", "status": "deleted"},
                    ]
                }
            
        If False, return current revision of the document, but with
        an additional field, _revs, the value being a list of 
        the available revision IDs. 
        """
        docid = resource.escape_docid(docid)
        try:
            if with_doc:
                doc_with_rev = self.res.get(docid, _raw_json=_raw_json, revs=True)
            else:
                doc_with_revs = self.res.get(docid, _raw_json=_raw_json, revs_info=True)
        except ResourceNotFound:
            if self.ui.verbose >=2:
                self.ui.logger.info("document %s not found" % docid)
            return None
        return doc_with_revs