Example #1
0
    def delete_doc(self, doc):
        """ delete a document or a list of documents
        @param doc: str or dict,  document id or full doc.
        @return: dict like:

        .. code-block:: python

            {"ok":true,"rev":"2839830636"}
        """
        result = { 'ok': False }

        doc1, schema = _maybe_serialize(doc)
        if isinstance(doc1, dict):
            if not '_id' or not '_rev' in doc1:
                raise KeyError('_id and _rev are required to delete a doc')

            docid = resource.escape_docid(doc1['_id'])
            result = self.res.delete(docid, rev=doc1['_rev']).json_body
        elif isinstance(doc1, basestring): # we get a docid
            rev = self.get_rev(doc1)
            docid = resource.escape_docid(doc1)
            result = self.res.delete(docid, rev=rev).json_body

        if schema:
            doc._doc.update({
                "_rev": result['rev'],
                "_deleted": True
            })
        elif isinstance(doc, dict):
            doc.update({
                "_rev": result['rev'],
                "_deleted": True
            })
        return result
Example #2
0
    def get(self, docid, rev=None, wrapper=None, _raw_json=False):
        """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)
        if rev is not None:
            doc = maybe_raw(self.res.get(docid, rev=rev), raw=_raw_json)
        else:
            doc = maybe_raw(self.res.get(docid), raw=_raw_json)

        if wrapper is not None:
            if not callable(wrapper):
                raise TypeError("wrapper isn't a callable")
            return wrapper(doc)

        return doc
Example #3
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_revs = maybe_raw(self.res.get(docid, revs=True), raw=_raw_json)
            else:
                doc_with_revs = maybe_raw(self.res.get(docid, revs_info=True), raw=_raw_json)
        except resource.ResourceNotFound:
            return None
        return doc_with_revs
Example #4
0
    def open_doc(self, docid, **params):
        """Get document from database

        Args:
        @param docid: str, document id to retrieve
        @param wrapper: callable. function that takes dict as a param.
        Used to wrap an object.
        @param _raw_json: return raw json instead deserializing it
        @param **params: See doc api for parameters to use:
        http://wiki.apache.org/couchdb/HTTP_Document_API

        @return: dict, representation of CouchDB document as
         a dict.
        """
        wrapper = None
        raw_json = False
        if "wrapper" in params:
            wrapper = params.pop("wrapper")
            
        if "_raw_json" in params:
            raw_json = params.pop("_raw_json")
        
        docid = resource.escape_docid(docid)
        
        doc = maybe_raw(self.res.get(docid, **params), raw=raw_json)        
        if wrapper is not None:
            if not callable(wrapper):
                raise TypeError("wrapper isn't a callable")
            return wrapper(doc)

        return doc
Example #5
0
    def open_doc(self, docid, **params):
        """Get document from database

        Args:
        @param docid: str, document id to retrieve
        @param wrapper: callable. function that takes dict as a param.
        Used to wrap an object.
        @param **params: See doc api for parameters to use:
        http://wiki.apache.org/couchdb/HTTP_Document_API

        @return: dict, representation of CouchDB document as
         a dict.
        """
        wrapper = None
        if "wrapper" in params:
            wrapper = params.pop("wrapper")
        elif "schema" in params:
            schema = params.pop("schema")
            if not hasattr(schema, "wrap"):
                raise TypeError("invalid schema")
            wrapper = schema.wrap

        docid = resource.escape_docid(docid)
        doc = self.res.get(docid, **params).json_body        
        if wrapper is not None:
            if not callable(wrapper):
                raise TypeError("wrapper isn't a callable")

            return wrapper(doc)

        return doc
    def debug_open_doc(self, docid, **params):
        """Get document from database

        Args:
        @param docid: str, document id to retrieve
        @param wrapper: callable. function that takes dict as a param.
        Used to wrap an object.
        @param **params: See doc api for parameters to use:
        http://wiki.apache.org/couchdb/HTTP_Document_API

        @return: dict, representation of CouchDB document as
         a dict.
        """
        start = datetime.utcnow()

        ############################
        #Start Database.open_doc
        wrapper = None
        if "wrapper" in params:
            wrapper = params.pop("wrapper")
        elif "schema" in params:
            schema = params.pop("schema")
            if not hasattr(schema, "wrap"):
                raise TypeError("invalid schema")
            wrapper = schema.wrap

        docid = resource.escape_docid(docid)
        error = None
        try:
            doc = self.res.get(docid, **params).json_body
        except ResourceNotFound, ex:
            error = ex
            doc = {}
    def debug_open_doc(self, docid, **params):
        """Get document from database

        Args:
        @param docid: str, document id to retrieve
        @param wrapper: callable. function that takes dict as a param.
        Used to wrap an object.
        @param **params: See doc api for parameters to use:
        http://wiki.apache.org/couchdb/HTTP_Document_API

        @return: dict, representation of CouchDB document as
         a dict.
        """
        start = datetime.utcnow()

        ############################
        #Start Database.open_doc
        wrapper = None
        if "wrapper" in params:
            wrapper = params.pop("wrapper")
        elif "schema" in params:
            schema = params.pop("schema")
            if not hasattr(schema, "wrap"):
                raise TypeError("invalid schema")
            wrapper = schema.wrap

        docid = resource.escape_docid(docid)
        error = None
        try:
            doc = self.res.get(docid, **params).json_body
        except ResourceNotFound, ex:
            error = ex
            doc = {}
Example #8
0
    def get_rev(self, docid):
        """ Get last revision from docid (the '_rev' member)
        @param docid: str, undecoded document id.

        @return rev: str, the last revision of document.
        """
        response = self.res.head(resource.escape_docid(docid))
        return response.headers['etag'].strip('"')
Example #9
0
    def save_doc(self, doc, encode_attachments=True, force_update=False,
            _raw_json=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 force_update: boolean, if there is conlict, try to update
        with latest revision
        @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).

        @return res: result of save. doc is updated in the mean time
        """
        if doc is None:
            doc = {}

        if '_attachments' in doc and encode_attachments:
            doc['_attachments'] = resource.encode_attachments(doc['_attachments'])

        if '_id' in doc:
            docid = doc['_id']
            docid1 = resource.escape_docid(doc['_id'])
            try:
                res = maybe_raw(self.res.put(docid1, payload=doc,
                            **params), raw=_raw_json)
            except resource.ResourceConflict:
                if force_update:
                    doc['_rev'] = self.get_rev(docid)
                    res = maybe_raw(self.res.put(docid1, payload=doc,
                                **params), raw=_raw_json)
                else:
                    raise
        else:
            try:
                doc['_id'] = self.server.next_uuid()
                res =  maybe_raw(self.res.put(doc['_id'], payload=doc, **params),
                            raw=_raw_json)
            except:
                res = maybe_raw(self.res.post(payload=doc, **params), raw=_raw_json)

        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']})

        return res
Example #10
0
 def compact(self, dname=None):
     """ 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)
     return res.json_body
Example #11
0
 def compact(self, dname=None):
     """ 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, headers={"Content-Type": 
         "application/json"})
     return res.json_body
Example #12
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:
            self.res.head(resource.escape_docid(docid))
        except resource.ResourceNotFound:
            return False
        return True
Example #13
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 = maybe_raw(self.res.delete(docid, rev=doc["_rev"]), raw=_raw_json)
        elif isinstance(doc, basestring):  # we get a docid
            rev = self.get_rev(doc)
            docid = resource.escape_docid(doc)
            result = maybe_raw(self.res.delete(docid, rev=rev), raw=_raw_json)
        return result
Example #14
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.
        """
        docid = resource.escape_docid(doc["_id"])
        name = url_quote(name, safe="")

        res = self.res(docid).delete(name, rev=doc["_rev"]).json_body
        if res["ok"]:
            doc.update({"_rev": res["rev"]})
        return res["ok"]
Example #15
0
 def _get(self, docid, **params):
     try:
         doc_model = SQLDocModel.objects.get(doc_id=docid)
     except SQLDocModel.DoesNotExist:
         docid = resource.escape_docid(docid)
         return self.res.get(docid, **params).json_body
     else:
         doc = doc_model.doc
         assert doc['doc_type'] == doc_model.doc_type
         assert doc['_id'] == doc_model.doc_id
         doc['_rev'] = doc_model.sql_rev
         doc['_attachments'] = dict(
             att.format_stub() for att in
             doc_model.sqldocattachment_set.defer('payload')
         )
         return doc
Example #16
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.
        """
        docid = resource.escape_docid(doc['_id'])
        name = url_quote(name, safe="")

        res = self.res(docid).delete(name, rev=doc['_rev']).json_body
        if res['ok']:
            new_doc = self.get(doc['_id'], rev=res['rev'])
            doc.update(new_doc)
        return res['ok']
Example #17
0
def open_doc(self, docid, **params):
    """Get document from database

    Args:
    @param docid: str, document id to retrieve
    @param wrapper: callable. function that takes dict as a param.
    Used to wrap an object.
    @param **params: See doc api for parameters to use:
    http://wiki.apache.org/couchdb/HTTP_Document_API

    @return: dict, representation of CouchDB document as
     a dict.
    """
    wrapper = None
    if 'wrapper' in params:
        wrapper = params.pop('wrapper')
    elif 'schema' in params:
        schema = params.pop('schema')
        if not hasattr(schema, 'wrap'):
            raise TypeError("invalid schema")
        wrapper = schema.wrap

    docid = resource.escape_docid(docid)
    doc = self.res.get(docid, **params).json_body

    # Lookup to see if doc_type is registered in schema
    try:
        schema = couchdbkit_handler.get_schema(*doc['doc_type'])
    except TypeError:
        pass
    else:
        if schema:
            wrapper = schema.wrap

    if wrapper is not None:
        if not callable(wrapper):
            raise TypeError("wrapper isn't a callable")
        doc = wrapper(doc)
        doc._db = self
        return doc
    return doc
Example #18
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, if True return a file object
        @return: `restkit.httpc.Response` object
        """

        if isinstance(id_or_doc, basestring):
            docid = id_or_doc
        else:
            docid = id_or_doc['_id']

        docid = resource.escape_docid(docid)
        name = url_quote(name, safe="")

        resp = self.res(docid).get(name)
        if stream:
            return resp.body_file
        return resp.body_string(charset="utf-8")
Example #19
0
    def debug_open_doc(self, docid, **params):
        """Get document from database

        Args:
        @param docid: str, document id to retrieve
        @param wrapper: callable. function that takes dict as a param.
        Used to wrap an object.
        @param **params: See doc api for parameters to use:
        http://wiki.apache.org/couchdb/HTTP_Document_API

        @return: dict, representation of CouchDB document as
         a dict.
        """
        start = datetime.utcnow()

        ############################
        #Start Database.open_doc
        wrapper = None
        if "wrapper" in params:
            wrapper = params.pop("wrapper")
        elif "schema" in params:
            schema = params.pop("schema")
            if not hasattr(schema, "wrap"):
                raise TypeError("invalid schema")
            wrapper = schema.wrap

        docid = resource.escape_docid(docid)
        error = None
        try:
            doc = self.res.get(docid, **params).json_body
        except ResourceNotFound as ex:
            error = ex
            doc = {}
        #############################

        #############################
        #Debug Panel data collection
        stop = datetime.utcnow()
        duration = ms_from_timedelta(stop - start)
        stacktrace = tidy_stacktrace(traceback.extract_stack())

        if wrapper is not None:
            view_path_display = "GET %s" % wrapper.__self__._doc_type
        else:
            view_path_display = "Raw GET"

        q = {
                'view_path': view_path_display,
                'duration': duration,
                'params': params,
                'stacktrace': stacktrace,
                'start_time': start,
                'stop_time': stop,
                'is_slow': (duration > SQL_WARNING_THRESHOLD),
                'total_rows': 1,
                'response': 200 if error is None else 404,
                'doc_type': doc.get('doc_type', '[unknown]'),
                'doc_id': docid,
            }
        self._queries.append(q)

        #end debug panel data collection
        ################################


        ##################################
        #Resume original Database.open_doc
        if error is not None:
            raise error

        if wrapper is not None:
            if not callable(wrapper):
                raise TypeError("wrapper isn't a callable")
            return wrapper(doc)

        return doc
Example #20
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('couchdbkit_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['couchdbkit_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 provide a valid attachment name')
        name = url_quote(name, safe="")
        if content_type is None:
            content_type = ';'.join(filter(None, 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

        if hasattr(doc, 'to_json'):
            doc1 = doc.to_json()
        else:
            doc1 = doc

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

        if res['ok']:
            new_doc = self.get(doc1['_id'], rev=res['rev'])
            doc.update(new_doc)
        return res['ok']
    def debug_open_doc(self, docid, **params):
        """Get document from database

        Args:
        @param docid: str, document id to retrieve
        @param wrapper: callable. function that takes dict as a param.
        Used to wrap an object.
        @param **params: See doc api for parameters to use:
        http://wiki.apache.org/couchdb/HTTP_Document_API

        @return: dict, representation of CouchDB document as
         a dict.
        """
        # debug panel
        start = datetime.now()
        newparams = params.copy()
        # end debug panel

        ############################
        # Start Database.open_doc
        wrapper = None
        if "wrapper" in params:
            wrapper = params.pop("wrapper")
        elif "schema" in params:
            schema = params.pop("schema")
            if not hasattr(schema, "wrap"):
                raise TypeError("invalid schema")
            wrapper = schema.wrap

        docid = resource.escape_docid(docid)
        doc = self.res.get(docid, **params).json_body
        # End Database.open_doc
        #############################

        #############################
        # Debug Panel data collection
        stop = datetime.now()
        duration = ms_from_timedelta(stop - start)
        stacktrace = tidy_stacktrace(traceback.extract_stack())

        if wrapper is not None:
            view_path_display = "GET %s" % wrapper.im_self._doc_type
        else:
            view_path_display = "Raw GET"

        self._queries.append(
            {
                "view_path": "get",
                "view_path_safe": "get",
                "view_path_display": view_path_display,
                "duration": duration,
                "params": {"docid": docid},
                "hash": sha1(settings.SECRET_KEY + str(newparams) + docid).hexdigest(),
                "stacktrace": stacktrace,
                "start_time": start,
                "stop_time": stop,
                "is_slow": (duration > SQL_WARNING_THRESHOLD),
                "total_rows": 1,
                #'is_cached': is_cached,
                #'is_reduce': sql.lower().strip().startswith('select'),
                #'template_info': template_info,
            }
        )

        # end debug panel data collection
        ################################

        ##################################
        # Resume original Database.open_doc
        if wrapper is not None:
            if not callable(wrapper):
                raise TypeError("wrapper isn't a callable")

            return wrapper(doc)

        return doc
Example #22
0
    def debug_open_doc(self, docid, **params):
        """Get document from database

        Args:
        @param docid: str, document id to retrieve
        @param wrapper: callable. function that takes dict as a param.
        Used to wrap an object.
        @param **params: See doc api for parameters to use:
        http://wiki.apache.org/couchdb/HTTP_Document_API

        @return: dict, representation of CouchDB document as
         a dict.
        """
        start = datetime.utcnow()

        ############################
        #Start Database.open_doc
        wrapper = None
        if "wrapper" in params:
            wrapper = params.pop("wrapper")
        elif "schema" in params:
            schema = params.pop("schema")
            if not hasattr(schema, "wrap"):
                raise TypeError("invalid schema")
            wrapper = schema.wrap

        docid = resource.escape_docid(docid)
        error = None
        try:
            doc = self.res.get(docid, **params).json_body
        except ResourceNotFound as ex:
            error = ex
            doc = {}
        #############################

        #############################
        #Debug Panel data collection
        stop = datetime.utcnow()
        duration = ms_from_timedelta(stop - start)
        stacktrace = tidy_stacktrace(traceback.extract_stack())

        if wrapper is not None:
            view_path_display = "GET %s" % wrapper.__self__._doc_type
        else:
            view_path_display = "Raw GET"

        q = {
                'view_path': view_path_display,
                'duration': duration,
                'params': params,
                'stacktrace': stacktrace,
                'start_time': start,
                'stop_time': stop,
                'is_slow': (duration > SQL_WARNING_THRESHOLD),
                'total_rows': 1,
                'response': 200 if error is None else 404,
                'doc_type': doc.get('doc_type', '[unknown]'),
                'doc_id': docid,
            }
        self._queries.append(q)

        #end debug panel data collection
        ################################


        ##################################
        #Resume original Database.open_doc
        if error is not None:
            raise error

        if wrapper is not None:
            if not callable(wrapper):
                raise TypeError("wrapper isn't a callable")
            return wrapper(doc)

        return doc
Example #23
0
    def debug_open_doc(self, docid, **params):
        """Get document from database

        Args:
        @param docid: str, document id to retrieve
        @param wrapper: callable. function that takes dict as a param.
        Used to wrap an object.
        @param **params: See doc api for parameters to use:
        http://wiki.apache.org/couchdb/HTTP_Document_API

        @return: dict, representation of CouchDB document as
         a dict.
        """
        #debug panel
        start = datetime.now()
        newparams = params.copy()
        #end debug panel

        ############################
        #Start Database.open_doc
        wrapper = None
        if "wrapper" in params:
            wrapper = params.pop("wrapper")
        elif "schema" in params:
            schema = params.pop("schema")
            if not hasattr(schema, "wrap"):
                raise TypeError("invalid schema")
            wrapper = schema.wrap

        docid = resource.escape_docid(docid)
        doc = self.res.get(docid, **params).json_body
        #End Database.open_doc
        #############################

        #############################
        #Debug Panel data collection
        stop = datetime.now()
        duration = ms_from_timedelta(stop - start)
        stacktrace = tidy_stacktrace(traceback.extract_stack())

        if wrapper is not None:
            view_path_display = "GET %s" % wrapper.im_self._doc_type
        else:
            view_path_display = "Raw GET"

        self._queries.append({
            'view_path':
            'get',
            'view_path_safe':
            'get',
            'view_path_display':
            view_path_display,
            'duration':
            duration,
            'params': {
                'docid': docid
            },
            'hash':
            sha1(settings.SECRET_KEY + str(newparams) + docid).hexdigest(),
            'stacktrace':
            stacktrace,
            'start_time':
            start,
            'stop_time':
            stop,
            'is_slow': (duration > SQL_WARNING_THRESHOLD),
            'total_rows':
            1,
            #'is_cached': is_cached,
            #'is_reduce': sql.lower().strip().startswith('select'),
            #'template_info': template_info,
        })

        #end debug panel data collection
        ################################

        ##################################
        #Resume original Database.open_doc
        if wrapper is not None:
            if not callable(wrapper):
                raise TypeError("wrapper isn't a callable")

            return wrapper(doc)

        return doc