def test_fetch(self): # add a database without http auth client = CouchAsyncHTTPClient('http://172.16.200.51:5984/', self.io_loop) resp = yield client.fetch( 'newcmdb', method="PUT", raise_error=False, allow_nonstandard_methods=True ) self.assertEqual(resp.body, '{"error":"unauthorized","reason":"You are not a server admin."}')
def test_fetch_del(self): # delete a database with http auth client = CouchAsyncHTTPClient('http://172.16.200.51:5984/', self.io_loop) resp = yield client.fetch( 'newcmdb', method="DELETE", raise_error=False, auth_username='******', auth_password='******', allow_nonstandard_methods=True ) self.assertEqual(resp.body, '{"ok":true}\n')
class TestHttpClient(AsyncTestCase): @classmethod def setUpClass(cls): cls.database = 'couch-test' def setUp(self): super(TestHttpClient, self).setUp() # setup io_loop self.client = CouchAsyncHTTPClient('http://127.0.0.1:5984/', self.io_loop) @gen_test(timeout=3) def test_get(self): resp = yield self.client.get(self.database, 'not exist', raise_error=False) self.assertEqual(resp.body, '{"error":"not_found","reason":"missing"}') @gen_test(timeout=3) def test_put(self): client = CouchAsyncHTTPClient('http://172.16.200.51:5984/', self.io_loop) resp = yield client.put('cmdb', 'foo_bar', {"foo": "bar"}, raise_error=False) print(resp.body) @gen_test(timeout=3) def test_fetch(self): # add a database without http auth client = CouchAsyncHTTPClient('http://172.16.200.51:5984/', self.io_loop) resp = yield client.fetch( 'newcmdb', method="PUT", raise_error=False, allow_nonstandard_methods=True ) self.assertEqual(resp.body, '{"error":"unauthorized","reason":"You are not a server admin."}') @gen_test(timeout=3) def test_fetch_auth(self): # add a database with http auth client = CouchAsyncHTTPClient('http://172.16.200.51:5984/', self.io_loop) resp = yield client.fetch( 'newcmdb', method="PUT", raise_error=False, auth_username='******', auth_password='******', allow_nonstandard_methods=True ) self.assertEqual(resp.body, '{"ok":true}\n') @gen_test(timeout=3) def test_fetch_del(self): # delete a database with http auth client = CouchAsyncHTTPClient('http://172.16.200.51:5984/', self.io_loop) resp = yield client.fetch( 'newcmdb', method="DELETE", raise_error=False, auth_username='******', auth_password='******', allow_nonstandard_methods=True ) self.assertEqual(resp.body, '{"ok":true}\n')
def test_put(self): client = CouchAsyncHTTPClient('http://172.16.200.51:5984/', self.io_loop) resp = yield client.put('cmdb', 'foo_bar', {"foo": "bar"}, raise_error=False) print(resp.body)
def setUp(self): super(TestHttpClient, self).setUp() # setup io_loop self.client = CouchAsyncHTTPClient('http://127.0.0.1:5984/', self.io_loop)
def __init__(self, url='http://localhost:5984', io_loop=None): self.base_url = url[:-1] if url.endswith('/') else url self.io_loop = io_loop or ioloop.IOLoop.instance() self.client = CouchAsyncHTTPClient(self.base_url, self.io_loop)
class CouchServer(object): """ couchdb database operation """ def __init__(self, url='http://localhost:5984', io_loop=None): self.base_url = url[:-1] if url.endswith('/') else url self.io_loop = io_loop or ioloop.IOLoop.instance() self.client = CouchAsyncHTTPClient(self.base_url, self.io_loop) @gen.coroutine def create(self, database): # if couchdb set a admin must use http auth to create/delete a database # because tornado AsyncHttpclient can not send a empty body with 'PUT' method # so here set allow_nonstandard_methods = True # this option send body with a '0' instead of empty # if couchdb implement on a windows client will get an error: [Errno 10054] # because couchdb send a RST packet , but it works fine on Linux try: resp = yield self.client.fetch( database, method="PUT", auth_username=couch_conf['user'], auth_password=couch_conf['passwd'], allow_nonstandard_methods=True ) raise gen.Return(resp.body) except HTTPError: # HTTP 412: Precondition Failed raise ValueError('Database: {0} Exist'.format(database)) @staticmethod def _get_design(root): design_path = os.path.join(root, 'design') return [os.path.join(design_path, f) for f in os.listdir(design_path)] @gen.coroutine def init(self, database): """ add design document to a new database """ root = os.path.join(os.path.dirname(__file__), '..') designs = self._get_design(root) for design in designs: design_name = os.path.basename(design).split('.')[0] with open(design) as f: doc = json_decode(f.read()) yield self.client.fetch( '{0}/_design/{1}'.format(database, design_name), method="PUT", body=doc, auth_username=couch_conf['user'], auth_password=couch_conf['passwd'] ) @gen.coroutine def delete(self, database): try: resp = yield self.client.fetch( database, method="DELETE", auth_username=couch_conf['user'], auth_password=couch_conf['passwd'] ) raise gen.Return(resp.body) except HTTPError: raise ValueError('Database: {0} not Exist'.format(database)) @gen.coroutine def list_db(self): resp = yield self.client.fetch('_all_dbs', method="GET", allow_nonstandard_methods=True) databases = [db for db in json_decode(resp.body) if not db.startswith('_')] raise gen.Return(databases)
class CouchBase(object): """ couchdb document operation """ def __init__(self, url='http://localhost:5984', io_loop=None): self.url = url[:-1] if url.endswith('/') else url self.io_loop = io_loop or ioloop.IOLoop.instance() self.client = CouchAsyncHTTPClient(self.url, io_loop=self.io_loop) @gen.coroutine def list_ids(self, database): """ only list document id which not starts with '_' """ resp = yield self.get_doc(database, '_all_docs') raise gen.Return([doc['id'] for doc in resp['rows'] if not doc['id'].startswith('_')]) @gen.coroutine def get_doc(self, database, doc_id): """ return Document instance """ resp = yield self.client.get(database, doc_id, raise_error=False) if resp.code == 200: raise gen.Return(Document(json_decode(resp.body))) elif resp.code == 404: # {"error":"not_found","reason":"no_db_file"} for db not exist # {"error":"not_found","reason":"missing"} for doc not exist raise ValueError(json_decode(resp.body)['reason']) @gen.coroutine def has_doc(self, database, doc_id): try: resp = yield self.client.head(database, doc_id) raise gen.Return(resp.code == 200) except HTTPError: raise gen.Return(False) @gen.coroutine def get_doc_rev(self, database, doc_id): try: resp = yield self.client.head(database, doc_id) raise gen.Return(resp.headers['Etag'].strip('"')) except HTTPError: raise ValueError("Document {0} not Exist".format(doc_id)) @gen.coroutine def update_doc(self, database, doc_id, doc): resp = yield self.client.put(database, doc_id, doc) raise gen.Return(resp.body.decode('utf-8')) @gen.coroutine def update_doc_field(self, database, doc_id, **fields): doc = yield self.get_doc(database, doc_id) for field, value in fields.items(): doc[field] = value resp = yield self.client.put(database, doc_id, doc) raise gen.Return(resp.body.decode('utf-8')) @gen.coroutine def del_doc(self, database, doc_id): rev = yield self.get_doc_rev(database, doc_id) resp = yield self.client.delete(database, doc_id, rev) # json_decode can not decode String "True" but "true" # should return lowercase string "true" raise gen.Return("true" if resp.code == 200 else "false")