class CouchbaseClientTest(Base): def setUp(self): super(CouchbaseClientTest, self).setUp() self.client = CouchbaseClient(self.url, self.bucket_name, "", True) def tearDown(self): self.client.done() @nottest def setup_memcached_bucket(self): self.memcached_bucket = 'testing-memcached' self.rest_client = RestConnection({'ip': self.host, 'port': self.port, 'username': self.username, 'password': self.password}) self.rest_client.create_bucket(self.memcached_bucket, bucketType='memcached', authType='sasl', ramQuotaMB=64) self.client_for_memcached_bucket = \ CouchbaseClient(self.url, self.memcached_bucket, verbose=True) @nottest def teardown_memcached_bucket(self): self.rest_client.delete_bucket(self.memcached_bucket) @attr(cbv="1.0.0") def test_set_integer_value(self): self.client.set('int', 0, 0, 10) self.assertEqual(self.client.get('int')[2], 10, 'value should be the integer 10') self.client.incr('int') self.assertEqual(self.client.get('int')[2], 11, 'value should be the integer 11') self.client.delete('int') def test_two_client_incr(self): """http://www.couchbase.com/issues/browse/PYCBC-16""" key = 'test_two_client_incr' client_one = self.client client_two = CouchbaseClient(self.url, self.bucket_name, "", True) # Client one sets a numeric key client_one.set(key, 0, 0, 20) # Client two tries to increment this numeric key (i, cas) = client_two.incr(key) self.assertEqual(i, 21) # Client two should be able to keep incrementing this key (i, cas) = client_two.incr(key) self.assertEqual(i, 22) (_, cas, i) = client_two.get(key) self.assertEqual(i, 22) (i, cas) = client_two.incr(key) self.assertEqual(i, 23) def test_bucket_of_type_memcached(self): self.setup_memcached_bucket() self.assertIsInstance(self.client_for_memcached_bucket, CouchbaseClient) self.teardown_memcached_bucket()
def test_two_client_incr(self): """http://www.couchbase.com/issues/browse/PYCBC-16""" key = 'test_two_client_incr' client_one = self.client client_two = CouchbaseClient(self.url, self.bucket_name, "", True) # Client one sets a numeric key client_one.set(key, 0, 0, 20) # Client two tries to increment this numeric key (i, cas) = client_two.incr(key) self.assertEqual(i, 21) # Client two should be able to keep incrementing this key (i, cas) = client_two.incr(key) self.assertEqual(i, 22) (_, cas, i) = client_two.get(key) self.assertEqual(i, 22) (i, cas) = client_two.incr(key) self.assertEqual(i, 23)
class CouchbaseClientTest(Base): def setUp(self): super(CouchbaseClientTest, self).setUp() self.client = CouchbaseClient(self.url, self.bucket_name, "", True) def tearDown(self): self.client.flush() self.client.done() @nottest def setup_memcached_bucket(self): self.memcached_bucket = 'testing-memcached' self.rest_client = RestConnection({'ip': self.host, 'port': self.port, 'username': self.username, 'password': self.password}) self.rest_client.create_bucket(self.memcached_bucket, bucketType='memcached', authType='sasl', ramQuotaMB=64) self.client_for_memcached_bucket = \ CouchbaseClient(self.url, self.memcached_bucket, verbose=True) @nottest def teardown_memcached_bucket(self): self.rest_client.delete_bucket(self.memcached_bucket) @attr(cbv="1.0.0") def test_set_integer_value(self): self.client.set('int', 0, 0, 10) self.assertEqual(self.client.get('int')[2], 10, 'value should be the integer 10') self.client.incr('int') self.assertEqual(self.client.get('int')[2], 11, 'value should be the integer 11') @attr(cbv="1.0.0") def test_bucket_of_type_memcached(self): self.setup_memcached_bucket() self.assertIsInstance(self.client_for_memcached_bucket, CouchbaseClient) self.teardown_memcached_bucket()
class Bucket(object): """Handles Bucket management as well as key/value access for a specific bucket.""" def __init__(self, name, server): self.server = server self.name = name rest = server._rest() self.password = rest.get_bucket(self.name).saslPassword ip, port, rest_username, rest_password = server._rest_info() formatter_uri = "http://%s:%s/pools/default" self.mc_client = CouchbaseClient(formatter_uri % (ip, port), self.name, self.password) def append(self, key, value, cas=0): return self.mc_client.append(key, value, cas) def prepend(self, key, value, cas=0): return self.mc_client.prepend(key, value, cas) def incr(self, key, amt=1, init=0, exp=0): return self.mc_client.incr(key, amt, init, exp) def decr(self, key, amt=1, init=0, exp=0): return self.mc_client.decr(key, amt, init, exp) def set(self, key, expiration, flags, value): return self.mc_client.set(key, expiration, flags, value) def add(self, key, exp, flags, val): return self.mc_client.add(key, exp, flags, val) def replace(self, key, exp, flags, val): return self.mc_client.replace(key, exp, flags, val) def get(self, key): return self.mc_client.get(key) def getl(self, key, exp=15): return self.mc_client.getl(key, exp) def cas(self, key, exp, flags, oldVal, val): return self.mc_client.cas(key, exp, flags, oldVal, val) def touch(self, key, exp): return self.mc_client.touch(key, exp) def gat(self, key, exp): return self.mc_client.gat(key, exp) def stats(self, sub=''): return self.mc_client.stats(sub) def delete(self, key, cas=0): if key.startswith('_design/'): # this is a design doc, we need to handle it differently view = key.split('/')[1] rest = self.server._rest() rest.delete_view(self.name, view) else: return self.mc_client.delete(key, cas) def save(self, document): value = deepcopy(document) if '_id' in value: key = value['_id'] del value['_id'] else: key = str(uuid.uuid4()) if '$flags' in value: flags = value['$flags'] del value['$flags'] else: flags = 0 if '$expiration' in value: expiration = value['$expiration'] del value['$expiration'] else: expiration = 0 if key.startswith('_design/'): # this is a design doc, we need to handle it differently view = key.split('/')[1] rest = self.server._rest() rest.create_design_doc(self.name, view, json.dumps(value)) else: if '_rev' in value: # couchbase works in clobber mode so for "set" _rev is useless del value['_rev'] self.set(key, expiration, flags, json.dumps(value)) return key def __setitem__(self, key, value): if isinstance(value, dict): self.set(key, value['expiration'], value['flags'], value['value']) else: self.set(key, 0, 0, value) def __getitem__(self, key): return self.get(key) def view(self, view, **options): params = deepcopy(options) limit = None if 'limit' in params: limit = params['limit'] del params['limit'] if view.startswith("_design/"): view_s = view.split('/') view_doc = view_s[1] view_map = view_s[3] else: view_doc = view view_map = None rest = self.server._rest() results = rest.view_results(self.name, view_doc, view_map, params, limit) if 'rows' in results: return results['rows'] else: return None
class Bucket(object): """Handles Bucket management as well as key/value access for a specific bucket.""" def __init__(self, name, server): self.server = server self.name = name rest = server._rest() self.info = rest.get_bucket(self.name) self.password = self.info.saslPassword ip, port, rest_username, rest_password = server._rest_info() formatter_uri = "http://%s:%s/pools/default" self.mc_client = CouchbaseClient(formatter_uri % (ip, port), self.name, self.password) def __del__(self): self.mc_client.done() def append(self, key, value, cas=0): return self.mc_client.append(key, value, cas) def prepend(self, key, value, cas=0): return self.mc_client.prepend(key, value, cas) def incr(self, key, amt=1, init=0, exp=0): return self.mc_client.incr(key, amt, init, exp) def decr(self, key, amt=1, init=0, exp=0): return self.mc_client.decr(key, amt, init, exp) def set(self, key, expiration, flags, value): if isinstance(value, dict): value = json.dumps(value) return self.mc_client.set(key, expiration, flags, value) def add(self, key, exp, flags, val): return self.mc_client.add(key, exp, flags, val) def replace(self, key, exp, flags, val): return self.mc_client.replace(key, exp, flags, val) def get(self, key): return self.mc_client.get(key) def getl(self, key, exp=15): return self.mc_client.getl(key, exp) def cas(self, key, exp, flags, oldVal, val): return self.mc_client.cas(key, exp, flags, oldVal, val) def touch(self, key, exp): return self.mc_client.touch(key, exp) def gat(self, key, exp): return self.mc_client.gat(key, exp) def stats(self, sub=''): return self.mc_client.stats(sub) def delete(self, key, cas=0): if key.startswith('_design/'): # this is a design doc, we need to handle it differently view = key.split('/')[1] rest = self.server._rest() rest.delete_view(self.name, view) else: return self.mc_client.delete(key, cas) def save(self, document): warnings.warn("save is deprecated; use set instead", DeprecationWarning) value = deepcopy(document) if '_id' in value: key = value['_id'] del value['_id'] else: key = str(uuid.uuid4()) if '$flags' in value: flags = value['$flags'] del value['$flags'] else: flags = 0 if '$expiration' in value: expiration = value['$expiration'] del value['$expiration'] else: expiration = 0 if key.startswith('_design/'): self[key] = value else: if '_rev' in value: # couchbase works in clobber mode so for "set" _rev is useless del value['_rev'] self.set(key, expiration, flags, json.dumps(value)) return key def __setitem__(self, key, value): if isinstance(value, dict): if 'expiration' in value or 'flags' in value: assert 'value' in value if isinstance(value['value'], dict): v = json.dumps(value['value']) else: v = value['value'] self.set(key, value.get('expiration', 0), value.get('flags', 0), v) elif key.startswith('_design/'): rest = self.server._rest() rest.create_design_doc(self.name, key[8:], json.dumps(value)) else: self.set(key, 0, 0, json.dumps(value)) else: self.set(key, 0, 0, value) def __getitem__(self, key): if key.startswith("_design/"): rest = self.server._rest() doc = rest.get_design_doc(self.name, key[8:]) return DesignDoc(key[8:], doc, self) else: return self.get(key) def view(self, view, **options): params = deepcopy(options) limit = None if 'limit' in params: limit = params['limit'] del params['limit'] if view.startswith("_design/"): view_s = view.split('/') view_doc = view_s[1] view_map = view_s[3] else: view_doc = view view_map = None rest = self.server._rest() results = rest.view_results(self.name, view_doc, view_map, params, limit) if 'rows' in results: return results['rows'] else: return None def design_docs(self): """List all design documents and return DesignDoc objects for each""" (ip, port, _, _) = self.server._rest_info() api = ''.join(['http://{0}:{1}'.format(ip, port), self.info.ddocs['uri']]) r = requests.get(api, auth=(self.server.rest_username, self.server.rest_password)) ddocs = [] for ddoc in r.json().get('rows'): ddocs.append(DesignDoc(ddoc['doc']['meta']['id'], ddoc['doc']['json'], bucket=self)) return ddocs def flush(self): """RESTful Bucket flushing - will destory all the data in a bucket.""" ip, port, rest_username, rest_password = self.server._rest_info() api = ''.join(["http://{0}:{1}".format(ip, port), self.info.controllers['flush']]) response = requests.post(api, auth=(rest_username, rest_password)) if response.status_code is 503: raise Exception("Only buckets of type 'memcached' support flush.") elif response.status_code is 404: raise BucketUnavailableException elif response.status_code is 200: return True
class CouchbaseClientTest(Base): def setUp(self): super(CouchbaseClientTest, self).setUp() self.client = CouchbaseClient(self.url, self.bucket_name, "", True) def tearDown(self): self.client.done() @nottest def setup_memcached_bucket(self): self.memcached_bucket = 'testing-memcached' self.rest_client = RestConnection({ 'ip': self.host, 'port': self.port, 'username': self.username, 'password': self.password }) self.rest_client.create_bucket(self.memcached_bucket, bucketType='memcached', authType='sasl', ramQuotaMB=64) self.client_for_memcached_bucket = \ CouchbaseClient(self.url, self.memcached_bucket, verbose=True) @nottest def teardown_memcached_bucket(self): self.rest_client.delete_bucket(self.memcached_bucket) @attr(cbv="1.0.0") def test_set_integer_value(self): self.client.set('int', 0, 0, 10) self.assertEqual( self.client.get('int')[2], 10, 'value should be the integer 10') self.client.incr('int') self.assertEqual( self.client.get('int')[2], 11, 'value should be the integer 11') self.client.delete('int') def test_two_client_incr(self): """http://www.couchbase.com/issues/browse/PYCBC-16""" key = 'test_two_client_incr' client_one = self.client client_two = CouchbaseClient(self.url, self.bucket_name, "", True) # Client one sets a numeric key client_one.set(key, 0, 0, 20) # Client two tries to increment this numeric key (i, cas) = client_two.incr(key) self.assertEqual(i, 21) # Client two should be able to keep incrementing this key (i, cas) = client_two.incr(key) self.assertEqual(i, 22) (_, cas, i) = client_two.get(key) self.assertEqual(i, 22) (i, cas) = client_two.incr(key) self.assertEqual(i, 23) def test_bucket_of_type_memcached(self): self.setup_memcached_bucket() self.assertIsInstance(self.client_for_memcached_bucket, CouchbaseClient) self.teardown_memcached_bucket()
class Bucket(object): """Handles Bucket management as well as key/value access for a specific bucket.""" def __init__(self, name, server): self.server = server self.name = name rest = server._rest() self.info = rest.get_bucket(self.name) self.password = self.info.saslPassword ip, port, rest_username, rest_password = server._rest_info() formatter_uri = "http://%s:%s/pools/default" self.mc_client = CouchbaseClient(formatter_uri % (ip, port), self.name, self.password) def __del__(self): self.mc_client.done() def append(self, key, value, cas=0): return self.mc_client.append(key, value, cas) def prepend(self, key, value, cas=0): return self.mc_client.prepend(key, value, cas) def incr(self, key, amt=1, init=0, exp=0): return self.mc_client.incr(key, amt, init, exp) def decr(self, key, amt=1, init=0, exp=0): return self.mc_client.decr(key, amt, init, exp) def set(self, key, expiration, flags, value): if isinstance(value, dict): value = json.dumps(value) return self.mc_client.set(key, expiration, flags, value) def add(self, key, exp, flags, val): return self.mc_client.add(key, exp, flags, val) def replace(self, key, exp, flags, val): return self.mc_client.replace(key, exp, flags, val) def get(self, key): return self.mc_client.get(key) def getl(self, key, exp=15): return self.mc_client.getl(key, exp) def cas(self, key, exp, flags, oldVal, val): return self.mc_client.cas(key, exp, flags, oldVal, val) def touch(self, key, exp): return self.mc_client.touch(key, exp) def gat(self, key, exp): return self.mc_client.gat(key, exp) def stats(self, sub=''): return self.mc_client.stats(sub) def delete(self, key, cas=0): if key.startswith('_design/'): # this is a design doc, we need to handle it differently view = key.split('/')[1] rest = self.server._rest() rest.delete_view(self.name, view) else: return self.mc_client.delete(key, cas) def save(self, document): warnings.warn("save is deprecated; use set instead", DeprecationWarning) value = deepcopy(document) if '_id' in value: key = value['_id'] del value['_id'] else: key = str(uuid.uuid4()) if '$flags' in value: flags = value['$flags'] del value['$flags'] else: flags = 0 if '$expiration' in value: expiration = value['$expiration'] del value['$expiration'] else: expiration = 0 if key.startswith('_design/'): self[key] = value else: if '_rev' in value: # couchbase works in clobber mode so for "set" _rev is useless del value['_rev'] self.set(key, expiration, flags, json.dumps(value)) return key def __setitem__(self, key, value): if isinstance(value, dict): if 'expiration' in value or 'flags' in value: assert 'value' in value if isinstance(value['value'], dict): v = json.dumps(value['value']) else: v = value['value'] self.set(key, value.get('expiration', 0), value.get('flags', 0), v) elif key.startswith('_design/'): rest = self.server._rest() rest.create_design_doc(self.name, key[8:], json.dumps(value)) else: self.set(key, 0, 0, json.dumps(value)) else: self.set(key, 0, 0, value) def __getitem__(self, key): if key.startswith("_design/"): rest = self.server._rest() doc = rest.get_design_doc(self.name, key[8:]) return DesignDoc(key[8:], doc, self) else: return self.get(key) def view(self, view, **options): params = deepcopy(options) limit = None if 'limit' in params: limit = params['limit'] del params['limit'] if view.startswith("_design/"): view_s = view.split('/') view_doc = view_s[1] view_map = view_s[3] else: view_doc = view view_map = None rest = self.server._rest() results = rest.view_results(self.name, view_doc, view_map, params, limit) if 'rows' in results: return results['rows'] else: return None def design_docs(self): """List all design documents and return DesignDoc objects for each""" (ip, port, _, _) = self.server._rest_info() api = ''.join( ['http://{0}:{1}'.format(ip, port), self.info.ddocs['uri']]) r = requests.get(api, auth=(self.server.rest_username, self.server.rest_password)) ddocs = [] for ddoc in r.json().get('rows'): ddocs.append( DesignDoc(ddoc['doc']['meta']['id'], ddoc['doc']['json'], bucket=self)) return ddocs def flush(self): """RESTful Bucket flushing - will destory all the data in a bucket.""" ip, port, rest_username, rest_password = self.server._rest_info() api = ''.join([ "http://{0}:{1}".format(ip, port), self.info.controllers['flush'] ]) response = requests.post(api, auth=(rest_username, rest_password)) if response.status_code is 503: raise Exception("Only buckets of type 'memcached' support flush.") elif response.status_code is 404: raise BucketUnavailableException elif response.status_code is 200: return True