def test_rewrite_rule(self):
     """
     Test that design document URL is rewritten to the expected test document.
     """
     ddoc = DesignDocument(self.db, '_design/ddoc001')
     ddoc['rewrites'] = [
         {"from": "",
          "to": "/../../rewrite_doc",
          "method": "GET",
          "query": {}
          }
     ]
     self.assertIsInstance(ddoc.rewrites, list)
     self.assertIsInstance(ddoc.rewrites[0], dict)
     ddoc.save()
     doc = Document(self.db, 'rewrite_doc')
     doc.save()
     resp = self.client.r_session.get('/'.join([ddoc.document_url, '_rewrite']))
     self.assertEquals(
         resp.json(),
         {
             '_id': 'rewrite_doc',
             '_rev': doc['_rev']
         }
     )
Пример #2
0
 def test_appended_error_message_using_save_with_invalid_key(self):
     """
     Test that saving a document with an invalid remote key will
     throw an HTTPError with additional error details from util
     method append_response_error_content.
     """
     # First create the document
     doc = Document(self.db, 'julia006')
     # Add an invalid key and try to save document
     doc['_invalid_key'] = 'jules'
     with self.assertRaises(requests.HTTPError) as cm:
         doc.save()
     err = cm.exception
     # Should be a 400 error code, but CouchDB 1.6 issues a 500
     if err.response.status_code == 500:
         # Check this is CouchDB 1.x
         self.assertTrue(self.client.r_session.head(self.url).headers['Server'].find('CouchDB/1.') >= 0,
                         '500 returned but was not CouchDB 1.x')
         self.assertEqual(
             str(err.response.reason),
             'Internal Server Error doc_validation Bad special document member: _invalid_key'
         )
     else:
         self.assertEqual(
             str(err.response.reason),
             'Bad Request doc_validation Bad special document member: _invalid_key'
         )
         self.assertEqual(
             err.response.status_code,
             400
         )
Пример #3
0
 def test_appended_error_message_using_save_with_invalid_key(self):
     """
     Test that saving a document with an invalid remote key will
     throw an HTTPError with additional error details from util
     method append_response_error_content.
     """
     # First create the document
     doc = Document(self.db, 'julia006')
     # Add an invalid key and try to save document
     doc['_invalid_key'] = 'jules'
     with self.assertRaises(requests.HTTPError) as cm:
         doc.save()
     err = cm.exception
     # Should be a 400 error code, but CouchDB 1.6 issues a 500
     if err.response.status_code == 500:
         #Check this is CouchDB 1.6
         self.assertTrue(self.client.r_session.head(self.url).headers['Server'].find('CouchDB/1.6.') >= 0,
                         '500 returned but was not CouchDB 1.6.x')
         self.assertEqual(
             str(err.response.reason),
             'Internal Server Error doc_validation Bad special document member: _invalid_key'
         )
     else:
         self.assertEqual(
             str(err.response.reason),
             'Bad Request doc_validation Bad special document member: _invalid_key'
         )
         self.assertEqual(
             err.response.status_code,
             400
         )
Пример #4
0
 def new_transaction_doc(self, symbol, quantity, price, fee, action):
     xactiondoc = Document(self.db)
     xactiondoc['type'] = 'transaction'
     xactiondoc['action'] = action
     xactiondoc['quantity'] = quantity
     xactiondoc['date'] = strftime("%Y-%m-%d %H:%M:%S")
     xactiondoc['fee'] = fee
     xactiondoc['price'] = price
     if action == 'deposit' or action == 'withdrawl':
         xactiondoc['symbol'] = 'Cash'
         xactiondoc['price'] = 1
     else:  #otherwise use symbol passed and check to see if updating cash is needed
         xactiondoc['symbol'] = symbol
     xactiondoc.save()
Пример #5
0
 def test_create_document_using_save(self):
     """
     Test that save functionality works.  If a document does
     not exist remotely then create it.
     """
     doc = Document(self.db, 'julia006')
     doc['name'] = 'julia'
     doc['age'] = 6
     self.assertIsNone(doc.get('_rev'))
     doc.save()
     self.assertTrue(doc.exists())
     self.assertTrue(doc['_rev'].startswith('1-'))
     remote_doc = Document(self.db, 'julia006')
     remote_doc.fetch()
     self.assertEqual(remote_doc, doc)
Пример #6
0
 def test_create_document_using_save(self):
     """
     Test that save functionality works.  If a document does
     not exist remotely then create it.
     """
     doc = Document(self.db, 'julia006')
     doc['name'] = 'julia'
     doc['age'] = 6
     self.assertIsNone(doc.get('_rev'))
     doc.save()
     self.assertTrue(doc.exists())
     self.assertTrue(doc['_rev'].startswith('1-'))
     remote_doc = Document(self.db, 'julia006')
     remote_doc.fetch()
     self.assertEqual(remote_doc, doc)
Пример #7
0
    def test_update_field_success_on_retry(self):
        """
        Test that conflict retries work for updating a single field.
        """
        # Create a doc
        doc = Document(self.db, 'julia006')
        doc['name'] = 'julia'
        doc['age'] = 6
        doc.create()
        self.assertTrue(doc['_rev'].startswith('1-'))
        self.assertEqual(doc['age'], 6)

        # Mock when saving the document
        # 1st call throw a 409
        # 2nd call delegate to the real doc.save()
        with mock.patch('cloudant.document.Document.save',
                        side_effect=[
                            requests.HTTPError(response=mock.Mock(
                                status_code=409, reason='conflict')),
                            doc.save()
                        ]) as m_save:
            # A list of side effects containing only 1 element
            doc.update_field(doc.field_set, 'age', 7, max_tries=1)
        # Two calls to save, one with a 409 and one that succeeds
        self.assertEqual(m_save.call_count, 2)
        # Check that the _rev and age field were updated
        self.assertTrue(doc['_rev'].startswith('2-'))
        self.assertEqual(doc['age'], 7)
Пример #8
0
    def test_document_request_fails_after_client_disconnects(self):
        """
        Test that after disconnecting from a client any objects created based
        on that client are not able to make requests.
        """
        self.client.connect()
        doc = Document(self.db, 'julia001')
        doc.save()
        self.client.disconnect()

        try:
            with self.assertRaises(AttributeError):
                doc.fetch()
            self.assertIsNone(doc.r_session)
        finally:
            self.client.connect()
Пример #9
0
    def test_document_request_fails_after_client_disconnects(self):
        """
        Test that after disconnecting from a client any objects created based
        on that client are not able to make requests.
        """
        self.client.connect()
        doc = Document(self.db, 'julia001')
        doc.save()
        self.client.disconnect()

        try:
            with self.assertRaises(AttributeError):
                doc.fetch()
            self.assertIsNone(doc.r_session)
        finally:
            self.client.connect()
Пример #10
0
 def test_update_document_with_encoded_url(self):
     """
     Test that updating a document where the document id requires that the
     document url be encoded is successful.
     """
     # First create the document
     doc = Document(self.db, 'http://example.com')
     doc['name'] = 'julia'
     doc['age'] = 6
     doc.save()
     # Now test that the document gets updated
     doc['name'] = 'jules'
     doc.save()
     self.assertTrue(doc['_rev'].startswith('2-'))
     remote_doc = Document(self.db, 'http://example.com')
     remote_doc.fetch()
     self.assertEqual(remote_doc, doc)
     self.assertEqual(remote_doc['name'], 'jules')
Пример #11
0
 def test_update_document_using_save(self):
     """
     Test that save functionality works.  If a document exists
     remotely then update it.
     """
     # First create the document
     doc = Document(self.db, 'julia006')
     doc['name'] = 'julia'
     doc['age'] = 6
     doc.save()
     # Now test that the document gets updated
     doc['name'] = 'jules'
     doc.save()
     self.assertTrue(doc['_rev'].startswith('2-'))
     remote_doc = Document(self.db, 'julia006')
     remote_doc.fetch()
     self.assertEqual(remote_doc, doc)
     self.assertEqual(remote_doc['name'], 'jules')
Пример #12
0
def checkToken(token):
    if token == 'test':
        return 'test'
    if token == None:
        return None
    tokendb = crecli()['token']
    tokendoc = Document(tokendb, token)
    if not tokendoc.exists():
        return None
    if tokendb[token]['time'] > str(datetime.datetime.now() -
                                    datetime.timedelta(
                                        seconds=7)).split('.')[0]:
        tokendoc = tokendb[token]
        tokendoc['time'] = str(datetime.datetime.now()).split('.')[0]
        tokendoc.save()
        return tokendoc['name']
    else:
        return None
 def test_appended_error_message_using_save_with_invalid_key(self):
     """
     Test that saving a document with an invalid remote key will
     throw an HTTPError with additional error details from util
     method append_response_error_content.
     """
     # First create the document
     doc = Document(self.db, 'julia006')
     # Add an invalid key and try to save document
     doc['_invalid_key'] = 'jules'
     with self.assertRaises(requests.HTTPError) as cm:
         doc.save()
     err = cm.exception
     self.assertEqual(
         str(err.response.reason),
         'Internal Server Error doc_validation Bad special document member: _invalid_key'
     )
     self.assertEqual(err.response.status_code, 500)
Пример #14
0
 def test_update_document_using_save(self):
     """
     Test that save functionality works.  If a document exists
     remotely then update it.
     """
     # First create the document
     doc = Document(self.db, 'julia006')
     doc['name'] = 'julia'
     doc['age'] = 6
     doc.save()
     # Now test that the document gets updated
     doc['name'] = 'jules'
     doc.save()
     self.assertTrue(doc['_rev'].startswith('2-'))
     remote_doc = Document(self.db, 'julia006')
     remote_doc.fetch()
     self.assertEqual(remote_doc, doc)
     self.assertEqual(remote_doc['name'], 'jules')
Пример #15
0
 def test_update_document_with_encoded_url(self):
     """
     Test that updating a document where the document id requires that the
     document url be encoded is successful.
     """
     # First create the document
     doc = Document(self.db, 'http://example.com')
     doc['name'] = 'julia'
     doc['age'] = 6
     doc.save()
     # Now test that the document gets updated
     doc['name'] = 'jules'
     doc.save()
     self.assertTrue(doc['_rev'].startswith('2-'))
     remote_doc = Document(self.db, 'http://example.com')
     remote_doc.fetch()
     self.assertEqual(remote_doc, doc)
     self.assertEqual(remote_doc['name'], 'jules')
Пример #16
0
    def test_save_non_exists(self):
        """cover save case where doc doesnt exist"""
        mock_resp = mock.Mock()
        mock_resp.status_code = 404
        self.mock_session.get.return_value = mock_resp

        mock_post = mock.Mock()
        mock_post.raise_for_status = mock.Mock()
        mock_post.json = mock.Mock()
        mock_post.json.return_value = {'id': "created", "rev": "created"}
        mock_put = mock.Mock()
        mock_put.raise_for_status = mock.Mock()
        self.mock_session.post.return_value = mock_post
        self.mock_session.put.return_value = mock_put

        doc = Document(self.database, "DUCKUMENT")
        doc.save()

        self.assertEqual(doc['_id'], "created")
        self.assertEqual(doc['_rev'], "created")
Пример #17
0
    def test_document_custom_json_encoder_and_decoder(self):
        dt_format = '%Y-%m-%dT%H:%M:%S'

        class DTEncoder(json.JSONEncoder):
            def default(self, obj):
                if isinstance(obj, datetime):
                    return {
                        '_type': 'datetime',
                        'value': obj.strftime(dt_format)
                    }
                return super(DTEncoder, self).default(obj)

        class DTDecoder(json.JSONDecoder):
            def __init__(self, *args, **kwargs):
                json.JSONDecoder.__init__(self,
                                          object_hook=self.object_hook,
                                          *args,
                                          **kwargs)

            def object_hook(self, obj):
                if '_type' not in obj:
                    return obj
                if obj['_type'] == 'datetime':
                    return datetime.strptime(obj['value'], dt_format)
                return obj

        doc = Document(self.db, encoder=DTEncoder)
        doc['name'] = 'julia'
        doc['dt'] = datetime(2018, 7, 9, 15, 11, 10, 0)
        doc.save()

        raw_doc = self.db.all_docs(include_docs=True)['rows'][0]['doc']

        self.assertEqual(raw_doc['name'], 'julia')
        self.assertEqual(raw_doc['dt']['_type'], 'datetime')
        self.assertEqual(raw_doc['dt']['value'], '2018-07-09T15:11:10')

        doc2 = Document(self.db, doc['_id'], decoder=DTDecoder)
        doc2.fetch()

        self.assertEqual(doc2['dt'], doc['dt'])
Пример #18
0
    def test_document_context_manager_update_failure_on_error(self):
        """
        Test that the document context manager skips document update if there
        is an error.
        """
        # Create the document.
        doc = Document(self.db, 'julia006')
        doc['name'] = 'julia'
        doc['age'] = 6
        doc.save()

        # Make a document update and then raise an error.
        with self.assertRaises(ZeroDivisionError), Document(
                self.db, 'julia006') as doc:
            doc['age'] = 7
            raise ZeroDivisionError()

        # Assert the change persists locally.
        self.assertEqual(doc['age'], 7)

        # Assert the document has not been saved to remote server.
        self.assertTrue(doc['_rev'].startswith('1-'))
        self.assertEqual(self.db['julia006']['age'], 6)
Пример #19
0
#     print(row)
#     db.create_document(row)

# data  = pd.read_csv('./resources/years.csv', encoding='windows-1255')
#
# data_json = json.loads(data.to_json(orient='records'))
#
# for row in data_json:
#     for key, value in row.items():
#         if key=='plot' or value is None:
#             continue
#         newRow = {}
#         newRow['plot']=row['plot']
#         newRow['year']=int(key)
#         newRow['crop']=value
#         newRow['type']='years'
#         #print (newRow)
#         db.create_document(newRow)

species = getSpecies(db)['docs']
# Retrieve documents where the name field is 'foo'
selector = {'type': {'$eq': 'species'}}
docs = db.get_query_result(selector)
for doc in docs:
    # Create Document object from dict
    updated_doc = Document(db, doc['_id'])
    print(updated_doc)
    updated_doc['_id'] = doc['Variety']
    updated_doc.save()
    print(updated_doc)
Пример #20
0
 def save_doc(self, doc: Document, key, value):
     doc.fetch()
     doc['key'] = key
     doc['value'] = value
     doc.save()
Пример #21
0
    def save_doc(self, doc, encode_attachments=True, 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. (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 params, list of optionnal params, like batch="ok"

        @return res: result of save. doc is updated in the mean time
        """
        if doc is None:
            doc1 = {}
        else:
            doc1, schema = _maybe_serialize(doc)

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

        if '_id' in doc1:
            docid = doc1['_id'] if six.PY3 else doc1['_id'].encode('utf-8')
            couch_doc = Document(self.cloudant_database, docid)
            couch_doc.update(doc1)
            try:
                # Copied from Document.save to ensure that a deleted doc cannot be saved.
                headers = {}
                headers.setdefault('Content-Type', 'application/json')
                put_resp = couch_doc.r_session.put(
                    couch_doc.document_url,
                    data=couch_doc.json(),
                    headers=headers
                )
                put_resp.raise_for_status()
                data = put_resp.json()
                super(Document, couch_doc).__setitem__('_rev', data['rev'])
            except HTTPError as e:
                if e.response.status_code != 409:
                    raise

                if force_update:
                    couch_doc['_rev'] = self.get_rev(docid)
                    couch_doc.save()
                else:
                    raise ResourceConflict
            res = couch_doc
        else:
            res = self.cloudant_database.create_document(doc1)

        if 'batch' in params and ('id' in res or '_id' in res):
            doc1.update({ '_id': res.get('_id')})
        else:
            doc1.update({'_id': res.get('_id'), '_rev': res.get('_rev')})

        if schema:
            for key, value in six.iteritems(doc.__class__.wrap(doc1)):
                doc[key] = value
        else:
            doc.update(doc1)
        return {
            'id': res['_id'],
            'rev': res['_rev'],
            'ok': True,
        }
Пример #22
0
    def save_doc(self,
                 doc,
                 encode_attachments=True,
                 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. (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 params, list of optionnal params, like batch="ok"

        @return res: result of save. doc is updated in the mean time
        """
        if doc is None:
            doc1 = {}
        else:
            doc1, schema = _maybe_serialize(doc)

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

        if '_id' in doc1:
            docid = doc1['_id'] if six.PY3 else doc1['_id'].encode('utf-8')
            couch_doc = Document(self.cloudant_database, docid)
            couch_doc.update(doc1)
            try:
                # Copied from Document.save to ensure that a deleted doc cannot be saved.
                headers = {}
                headers.setdefault('Content-Type', 'application/json')
                put_resp = couch_doc.r_session.put(couch_doc.document_url,
                                                   data=couch_doc.json(),
                                                   headers=headers)
                put_resp.raise_for_status()
                data = put_resp.json()
                super(Document, couch_doc).__setitem__('_rev', data['rev'])
            except HTTPError as e:
                if e.response.status_code != 409:
                    raise

                if force_update:
                    couch_doc['_rev'] = self.get_rev(docid)
                    couch_doc.save()
                else:
                    raise ResourceConflict
            res = couch_doc
        else:
            res = self.cloudant_database.create_document(doc1)

        if 'batch' in params and ('id' in res or '_id' in res):
            doc1.update({'_id': res.get('_id')})
        else:
            doc1.update({'_id': res.get('_id'), '_rev': res.get('_rev')})

        if schema:
            for key, value in six.iteritems(doc.__class__.wrap(doc1)):
                doc[key] = value
        else:
            doc.update(doc1)
        return {
            'id': res['_id'],
            'rev': res['_rev'],
            'ok': True,
        }
Пример #23
0
    def test_document_crud(self):
        """test basic crud operations with mocked backend"""
        doc = Document(self.database, "DUCKUMENT")
        # exists
        mock_resp = mock.Mock()
        mock_resp.status_code = 200
        self.mock_session.get.return_value = mock_resp
        self.assertTrue(doc.exists())
        self.assertTrue(self.mock_session.get.called)
        self.mock_session.get.assert_has_calls(
            [ mock.call('https://bob.cloudant.com/unittest/DUCKUMENT') ]
        )
        self.mock_session.get.reset_mock()

        # create
        mock_resp = mock.Mock()
        mock_resp.raise_for_status = mock.Mock()
        mock_resp.status_code = 200
        mock_resp.json = mock.Mock()
        mock_resp.json.return_value = {'id': 'DUCKUMENT', 'rev': 'DUCK2'}
        self.mock_session.post.return_value = mock_resp

        doc.create()
        self.assertEqual(doc['_rev'], 'DUCK2')
        self.assertEqual(doc['_id'], 'DUCKUMENT')
        self.assertTrue(self.mock_session.post.called)
        self.mock_session.post.reset_mock()

        # fetch
        mock_resp = mock.Mock()
        mock_resp.status_code = 200
        mock_resp.raise_for_status = mock.Mock()
        mock_resp.json = mock.Mock()
        mock_resp.json.return_value = {
            '_id': 'DUCKUMENT', '_rev': 'DUCK2',
            'herp': 'HERP', 'derp': 'DERP'
        }
        self.mock_session.get.return_value = mock_resp
        doc.fetch()
        self.assertTrue('herp' in doc)
        self.assertTrue('derp' in doc)
        self.assertEqual(doc['herp'], 'HERP')
        self.assertEqual(doc['derp'], 'DERP')

        self.assertTrue(self.mock_session.get.called)
        self.mock_session.get.assert_has_calls(
            [ mock.call('https://bob.cloudant.com/unittest/DUCKUMENT') ]
        )
        self.mock_session.get.reset_mock()

        # save
        mock_put_resp = mock.Mock()
        mock_put_resp.status_code = 200
        mock_put_resp.raise_for_status = mock.Mock()
        mock_put_resp.json = mock.Mock()
        mock_put_resp.json.return_value = {'id': 'DUCKUMENT', 'rev': 'DUCK3'}
        self.mock_session.put.return_value = mock_put_resp
        mock_get_resp = mock.Mock()
        mock_get_resp.status_code = 200
        self.mock_session.get.return_value = mock_get_resp

        doc.save()
        self.assertEqual(doc['_rev'], 'DUCK3')
        self.assertEqual(doc['_id'], 'DUCKUMENT')
        self.assertTrue(self.mock_session.get.called)
        self.assertTrue(self.mock_session.put.called)

        self.mock_session.get.assert_has_calls(
            [ mock.call('https://bob.cloudant.com/unittest/DUCKUMENT') ]
        )
        self.mock_session.put.assert_has_calls(
            [ mock.call(
                  'https://bob.cloudant.com/unittest/DUCKUMENT',
                  headers={'Content-Type': 'application/json'},
                  data=mock.ANY
            ) ]
        )
        self.mock_session.get.reset_mock()
        self.mock_session.put.reset_mock()

        # delete
        mock_resp = mock.Mock()
        mock_resp.status_code = 200
        mock_resp.raise_for_status = mock.Mock()
        self.mock_session.delete.return_value = mock_resp
        doc.delete()

        self.assertTrue(self.mock_session.delete.called)
        self.mock_session.delete.assert_has_calls(
            [ mock.call(
                  'https://bob.cloudant.com/unittest/DUCKUMENT',
                  params={'rev': 'DUCK3'}
            ) ]
        )
        self.mock_session.delete.reset_mock()
        # test delete with no rev explodes as expected
        self.assertRaises(CloudantException, doc.delete)