def NOtestall(self): t = Tyrant(host='127.0.0.1', port=1978) time1 = time.time() for i in range(1, 10000): key = "key%s" % i t[key] = {"firstname": "Alex", "lastname": "Madon", "age": "34"} time2 = time.time() dt = time2 - time1 print "Tyran tc: %s" % dt
def connect(self): """ Connects to the database. Raises RuntimeError if the connection is not closed yet. Use :meth:`StorageAdapter.reconnect` to explicitly close the connection and open it again. """ # TODO: sockets, etc. host = self._connection_options.get('host', DEFAULT_HOST) port = self._connection_options.get('port', DEFAULT_PORT) self.connection = Tyrant(host=host, port=port)
def setUp(self): assert not os.path.exists(self.TYRANT_FILE), 'Cannot proceed if test database already exists' cmd = 'ttserver -dmn -host %(host)s -port %(port)s -pid %(pid)s -ext %(lua)s %(file)s' cmd = cmd % {'host': self.TYRANT_HOST, 'port': self.TYRANT_PORT, 'pid': self.TYRANT_PID, 'file': self.TYRANT_FILE, 'lua': self.TYRANT_LUA} os.popen(cmd).read() self.t = Tyrant(host=self.TYRANT_HOST, port=self.TYRANT_PORT) self.t.clear() #Clear dirty data self.t.sync() self._set_test_data()
class StorageAdapter(BaseStorageAdapter): supports_nested_data = False converter_manager = converter_manager lookup_manager = lookup_manager #--------------------+ # Magic attributes | #--------------------+ def __contains__(self, key): return key in self.connection def __iter__(self): return iter(self.connection) def __len__(self): return len(self.connection) #----------------------+ # Private attributes | #----------------------+ def _fetch(self, primary_key): """ Returns model instance for given model and primary key. Raises KeyError if there is no item with given key in the database. """ return self.connection[primary_key] or {} #--------------+ # Public API | #--------------+ def clear(self): """ Clears the whole storage from data, resets autoincrement counters. """ self.connection.clear() def connect(self): """ Connects to the database. Raises RuntimeError if the connection is not closed yet. Use :meth:`StorageAdapter.reconnect` to explicitly close the connection and open it again. """ # TODO: sockets, etc. host = self._connection_options.get('host', DEFAULT_HOST) port = self._connection_options.get('port', DEFAULT_PORT) self.connection = Tyrant(host=host, port=port) def delete(self, key): """ Permanently deletes the record with given primary key from the database. """ del self.connection[key] def disconnect(self): self.connection = None def get_query(self, model): return QueryAdapter(storage=self, model=model) def save(self, data, primary_key=None): """ Saves given model instance into the storage. Returns primary key. :param data: dict containing all properties to be saved :param primary_key: the key for given object; if undefined, will be generated Note that you must provide current primary key for a model instance which is already in the database in order to update it instead of copying it. """ primary_key = primary_key or self.connection.generate_key() self.connection[primary_key] = data return primary_key
class TestTyrant(unittest.TestCase): TYRANT_HOST = '127.0.0.1' TYRANT_PORT = 1983 TYRANT_FILE = os.path.abspath('test123.tct') TYRANT_PID = os.path.abspath('test123.pid') TYRANT_LUA = os.path.dirname(__file__) + '/test.lua' def setUp(self): assert not os.path.exists(self.TYRANT_FILE), 'Cannot proceed if test database already exists' cmd = 'ttserver -dmn -host %(host)s -port %(port)s -pid %(pid)s -ext %(lua)s %(file)s#idx=id:lex#idx=store:qgr#idx=color:tok#idx=stock:dec#' cmd = cmd % {'host': self.TYRANT_HOST, 'port': self.TYRANT_PORT, 'pid': self.TYRANT_PID, 'file': self.TYRANT_FILE, 'lua': self.TYRANT_LUA} os.popen(cmd).read() self.t = Tyrant(host=self.TYRANT_HOST, port=self.TYRANT_PORT) self.t.clear() #Clear dirty data self.t.sync() self._set_test_data() self.q = self.t.query def tearDown(self): del self.t cmd = 'ps -e -o pid,command | grep "ttserver" | grep "\-port %s"' % self.TYRANT_PORT line = os.popen(cmd).read() try: pid = int(line.strip().split(' ')[0]) except: 'Expected "pid command" format, got %s' % line #os.popen('kill %s' % pid) os.unlink(self.TYRANT_FILE) try: os.unlink("%s.idx.store.qgr" % self.TYRANT_FILE) os.unlink("%s.idx.stock.dec" % self.TYRANT_FILE) os.unlink("%s.idx.id.lex" % self.TYRANT_FILE) os.unlink("%s.idx.color.tok" % self.TYRANT_FILE) except: pass def __init__(self, methodName="runTest"): unittest.TestCase.__init__(self, methodName) fields = [ ("id", lambda _:_), ("store", lambda _:_), ("color", lambda _:_), ("price", lambda x:x), #TODO: See how to set as double ("stock", lambda _:_), ] raw_data = """ apple\tConvenience Store\tred\t1.20\t120 blueberry\tFarmer's Market\tblue\t1.12\t92 peach\tShopway\tyellow\t2.30\t300 pear\tFarmer's Market\tyellow\t0.80\t58 raspberry\tShopway\tred\t1.50\t12 strawberry\tFarmer's Market\tred\t3.15\t214 """ data = {} for line in raw_data.splitlines(): f = line.split("\t") d = {} if len(f) < len(fields): continue for i in xrange(len(fields)): d[fields[i][0]] = fields[i][1](f[i]) data[d["id"]] = d self.data = data def _set_test_data(self): self.t.update(self.data) def test_slices(self): q = self.q.order_by('id') # we use exclude() with different dummy conditions to make sure that # each query object is "clean", i.e. no cache is shared between it and # its anchestor assert 6 == len(q.exclude(a=123)) assert 6 == len(q.exclude(a=456)[:]) assert 6 == len(list(q.exclude(a=789))) assert q.exclude(a=135).order_by('id')[0][0] == 'apple' keys = 'apple blueberry peach pear raspberry strawberry'.split() def sliced(start=None, stop=None): return [k for k,v in q.exclude(a=246).order_by('id')[start:stop]] assert sliced(None, None) == keys[:] assert sliced(0, None) == keys[0:] assert sliced(None, 1) == keys[:1] assert sliced(0, 2) == keys[0:2] assert sliced(2, 4) == keys[2:4] def test_cache_chunks(self): keys = 'apple blueberry peach pear raspberry strawberry'.split() q = self.q.exclude(a=123).order_by('id') # multiple elems by slice def sliced(q, chunk_size, start=None, stop=None): q.set_chunk_size(chunk_size) # this drops cache return [k for k,v in q.order_by('id')[start:stop]] assert sliced(q, 1, 2, 4) == keys[2:4] assert sliced(q, 2, 2, 4) == keys[2:4] assert sliced(q, 3, 2, 4) == keys[2:4] assert sliced(q, 4, 2, 4) == keys[2:4] assert sliced(q, 5, 2, 4) == keys[2:4] assert sliced(q, 3, 2, None) == keys[2:] assert sliced(q, 3, None, 2) == keys[:2] # single elem by index def get_item(q, chunk_size, index): q.set_chunk_size(chunk_size) # this drops cache key, data = q.order_by('id')[index] return data assert get_item(q, 1, 0) == self.t[ keys[0] ] assert get_item(q, 1, 1) == self.t[ keys[1] ] assert get_item(q, 1, 2) == self.t[ keys[2] ] assert get_item(q, 2, 0) == self.t[ keys[0] ] assert get_item(q, 2, 1) == self.t[ keys[1] ] assert get_item(q, 2, 2) == self.t[ keys[2] ] assert get_item(q, 3, 1) == self.t[ keys[1] ] self.assertRaises(IndexError, lambda: get_item(q, 3, 10) == self.t[ keys[1] ]) def test_exact_match(self): #Test implicit __is operator apple = self.q.filter(id="apple")[:] assert len(apple) == 1 assert apple[0][1] == self.data["apple"] #Test explicit __is lookup pear = self.q.filter(id__is="pear")[:] assert len(pear) == 1 assert pear[0][1] == self.data["pear"] #Test many results shopway = self.q.filter(store="Shopway")[:] assert len(shopway) == 2 for k, v in shopway: assert self.data[k]["store"] == "Shopway" #Test limit keys color = self.q.filter(color="red")[:1] assert len(color) == 1 for k, v in color: assert self.data[k]["color"] == "red" #Test and query shopway_red = self.q.filter(color="red", store="Shopway")[:] assert len(shopway_red) == 1 assert shopway_red[0][0] == "raspberry" #Test chained and filter shopway = self.q.filter(store="Shopway") shopway_red = shopway.filter(color="red")[:] assert len(shopway_red) == 1 assert shopway_red[0][0] == "raspberry" #Test exclude shopway_not_red = shopway.exclude(color="red")[:] assert len(shopway_not_red) == 1 assert shopway_not_red[0][0] == "peach" def test_numeric(self): #Numeric or decimal means integers. Search over floats or doubles are crazy bad_stock = self.q.filter(stock__lt=100) assert len(bad_stock) == 3 for k, v in bad_stock: assert k in "blueberry pear raspberry".split() stock_300 = self.q.filter(stock=300) assert len(stock_300) == 1 assert stock_300[0][0] == "peach" stock_58 = self.q.filter(stock__is=58) assert len(stock_58) == 1 assert stock_58[0][0] == "pear" good_stock = self.q.filter(stock__gt=100) assert len(good_stock) == 3 for k, v in good_stock: assert k in "apple peach strawberry".split() middle_stock = self.q.filter(stock__gte=58, stock__lte=120) assert len(middle_stock) == 3 assert query_equals(middle_stock, "pear blueberry apple") middle_stock_between = self.q.filter(stock__between=[58, 120]) assert list(middle_stock) == list(middle_stock_between) self.assertRaises(ValueError, lambda: list(self.q.filter(stock__between=[1]))) self.assertRaises(ValueError, lambda: list(self.q.filter(stock__between=[1, 2, 3]))) self.assertRaises(ValueError, lambda: list(self.q.filter(stock__between=['a', 'b']))) def test_string_contains(self): with_s = self.q.filter(id__contains="s") assert query_equals(with_s, "raspberry strawberry") def test_string_startswith(self): start = self.q.filter(id__startswith="pe") assert query_equals(start, "peach pear") def test_string_endswith(self): ends = self.q.filter(id__endswith="berry") assert query_equals(ends, "blueberry raspberry strawberry") def test_string_matchregex(self): regex = self.q.filter(id__matches=".ea.*") assert query_equals(regex, "peach pear") def test_token_eq_or(self): #Test string token yellow_blue = self.q.filter(color__in=["blue", "yellow"]) assert query_equals(yellow_blue, "blueberry peach pear") #Test numeric token some_stocks = self.q.filter(stock__in=[12, 120]) assert query_equals(some_stocks, "apple raspberry") def test_token_contains_or(self): market_store = self.q.filter(store__contains_any=["Market", "Store"]) assert query_equals(market_store, "apple blueberry pear strawberry") def test_token_contains_and(self): store_convenience = self.q.filter(store__contains=["Store", "Convenience"]) assert store_convenience[0][0] == "apple" def test_qgr_like(self): market = self.q.filter(store__like="market") assert query_equals(market, "blueberry pear strawberry") #Like is not like any market = self.q.filter(store__like="market store") assert len(market) == 0 def test_qgr_like_all(self): store = self.q.filter(store__like="nience store".split()) assert len(store) == 1 assert store[0][0] == "apple" store = self.q.filter(store__like="market store".split()) assert len(store) == 0 def test_qgr_like_any(self): market_store = self.q.filter(store__like_any="market store".split()) assert query_equals(market_store, "apple blueberry pear strawberry") def test_qgr_search(self): market_store = self.q.filter(store__search="market || store") assert query_equals(market_store, "apple blueberry pear strawberry") market_store = self.q.filter(store__search="market && store") assert len(market_store) == 0 def test_exists(self): self.t['stray_dog'] = {'color': 'brown', 'name': 'Fido'} with_name = self.q.filter(name__exists=True) without_name_outer = self.q.exclude(name__exists=True) without_name_inner = self.q.filter(name__exists=False) with_name_dbl_neg = self.q.exclude(name__exists=False) expected_named = 'stray_dog' expected_unnamed = 'strawberry apple peach raspberry pear blueberry' assert query_equals(with_name, expected_named) assert query_equals(without_name_outer, expected_unnamed) assert query_equals(without_name_inner, expected_unnamed) assert query_equals(with_name_dbl_neg, expected_named) del self.t['stray_dog'] def test_boolean(self): # make sure we can tell an edible missile from other kinds of missiles self.t['pie'] = {'type': 'missile', 'edible': True, 'name': 'Pie'} self.t['icbm'] = {'type': 'missile', 'edible': False, 'name': 'Trident'} assert query_equals(self.t.query.filter(edible=True), 'pie') assert query_equals(self.t.query.filter(edible=False), 'icbm') # boolean semantics are preserved when data is converted back to Python self.assertEquals(bool(self.t['pie']['edible']), True) self.assertEquals(bool(self.t['icbm']['edible']), False) def test_order(self): #Gets some fruits fruits = self.q.filter(id__in=["apple", "blueberry", "peach"]) #Order by name named_fruits = fruits.order_by("id") assert named_fruits[0][0] == "apple" assert named_fruits[1][0] == "blueberry" assert named_fruits[2][0] == "peach" #Order by name desc named_fruits_desc = fruits.order_by("-id") assert named_fruits_desc[0][0] == "peach" assert named_fruits_desc[1][0] == "blueberry" assert named_fruits_desc[2][0] == "apple" #Order by stock stock_fruits = fruits.order_by("stock", numeric=True) assert stock_fruits[0][0] == "blueberry" assert stock_fruits[1][0] == "apple" assert stock_fruits[2][0] == "peach" #Order by stock desc stock_fruits_desc = fruits.order_by("-stock", numeric=True) assert stock_fruits_desc[0][0] == "peach" assert stock_fruits_desc[1][0] == "apple" assert stock_fruits_desc[2][0] == "blueberry" def test_values(self): assert self.q.values("color") == [u'blue', u'yellow', u'red'] assert self.q.values("store") == [u'Shopway', u"Farmer's Market", u'Convenience Store'] def test_stat(self): assert self.q.stat() == {u'color': 6, u'price': 6, u'id': 6, u'store': 6, u'stock': 6} self.t.clear() self.t["prueba"] = dict(color="rojo", precio="3") self.t["test"] = dict(color="red", price="3") assert self.t.query.stat() == {u'color': 2, u'price': 1, u'precio': 1} def test_operator_or(self): #TODO: Q | Q not_blue = self.q.filter(color="red") | self.q.filter(color="yellow") assert len(not_blue) == 5 assert "blueberry" not in not_blue complex_or = self.q.filter(color="blue") | self.q.filter(store="Shopway") print complex_or assert len(complex_or) == 3 def test_columns(self): q = self.q.filter(id="apple") assert q.columns("id", "store")[0] == dict(id="apple", store="Convenience Store") assert q.columns("id", "color")[0] == dict(id="apple", color="red") assert q.columns("price", "stock")[:] == [dict(price="1.20", stock="120")] def test_union(self): q_apple = self.q.filter(id="apple") q_pear = self.q.filter(id="pear") q_red = self.q.filter(color="red") def get_ids(q): res = q.columns("id")[:] return set([d["id"] for d in res]) assert get_ids(q_apple.union(q_pear)) == set("apple pear".split()) assert get_ids(q_apple | q_pear) == set("apple pear".split()) assert get_ids(q_pear | q_red) == set("apple pear raspberry strawberry".split()) def test_intersect(self): q_apple = self.q.filter(id="apple") q_pear = self.q.filter(id="pear") q_red = self.q.filter(color="red") def get_ids(q): res = q.columns("id")[:] return set([d["id"] for d in res]) assert get_ids(q_apple.intersect(q_pear)) == set([]) assert get_ids(q_apple & q_pear) == set([]) assert get_ids(q_apple & q_red) == set(["apple"]) def test_intersect(self): q_apple = self.q.filter(id="apple") q_pear = self.q.filter(id="pear") q_red = self.q.filter(color="red") def get_ids(q): res = q.columns("id")[:] return set([d["id"] for d in res]) assert get_ids(q_apple.minus(q_pear)) == set(["apple"]) assert get_ids(q_apple - q_pear) == set(["apple"]) assert get_ids(q_red - q_apple) == set("raspberry strawberry".split()) def test_delete(self): assert "apple" in self.t deleted = self.q.filter(id="apple").delete() assert "apple" not in self.t def test_count(self): q_red = self.q.filter(color="red") assert q_red.count() == 3 del self.t["apple"] assert q_red.count() == 2 def test_hint(self): q_apple = self.q.filter(id="apple") q_red = self.q.filter(color="red") assert "HINT" in q_red.hint() assert "HINT" in q_apple.hint()
class TestTyrant(unittest.TestCase): TYRANT_HOST = '127.0.0.1' TYRANT_PORT = 1983 TYRANT_FILE = os.path.abspath('test123.tct') TYRANT_PID = os.path.abspath('test123.pid') TYRANT_LUA = os.path.dirname(__file__) + '/test.lua' def setUp(self): assert not os.path.exists(self.TYRANT_FILE), 'Cannot proceed if test database already exists' cmd = 'ttserver -dmn -host %(host)s -port %(port)s -pid %(pid)s -ext %(lua)s %(file)s' cmd = cmd % {'host': self.TYRANT_HOST, 'port': self.TYRANT_PORT, 'pid': self.TYRANT_PID, 'file': self.TYRANT_FILE, 'lua': self.TYRANT_LUA} os.popen(cmd).read() self.t = Tyrant(host=self.TYRANT_HOST, port=self.TYRANT_PORT) self.t.clear() #Clear dirty data self.t.sync() self._set_test_data() def tearDown(self): del self.t cmd = 'ps -e -o pid,command | grep "ttserver" | grep "\-port %s"' % self.TYRANT_PORT line = os.popen(cmd).read() try: pid = int(line.strip().split(' ')[0]) except: 'Expected "pid command" format, got %s' % line #os.popen('kill %s' % pid) os.unlink(self.TYRANT_FILE) def _set_test_data(self): self.t["apple"] = dict(store="Convenience Store", color="red") self.t["blueberry"] = dict(store="Farmer's Market", color="blue") self.t["peach"] = dict(store="Shopway", color="yellow") self.t["pear"] = dict(store="Farmer's Market", color="yellow") self.t["raspberry"] = dict(store="Shopway", color="red") self.t["strawberry"] = dict(store="Farmer's Market", color="red") def test___contains__(self): assert "apple" in self.t assert "melon" not in self.t def test___delitem__(self): assert "apple" in self.t del self.t["apple"] assert "apple" not in self.t def fail(): del self.t["melon"] self.assertRaises(KeyError, fail) def test___getitem__(self): assert self.t["apple"] == dict(store="Convenience Store", color="red") assert self.t["blueberry"] == dict(store="Farmer's Market", color="blue") def fail(): return self.t["melon"] self.assertRaises(KeyError, fail) def test_get(self): assert self.t.get("apple") == dict(store="Convenience Store", color="red") assert self.t.get("blueberry") == dict(store="Farmer's Market", color="blue") assert self.t.get("melon", None) == None def test___len__(self): assert len(self.t) == 6 def test___setitem__(self): assert self.t.get("apple") == dict(store="Convenience Store", color="red") self.t["apple"] = dict(store="Bah", color="yellow") assert self.t.get("apple") == dict(store="Bah", color="yellow") self.t["melon"] = dict(store="VillaConejos", color="green") assert self.t.get("melon") == dict(store="VillaConejos", color="green") def test_call_func(self): assert self.t.call_func("test_ext", "key", "value") == u"test: key=value" fake_func = lambda: self.t.call_func("invented_function", "key", "value") self.assertRaises(exceptions.InvalidOperation, fake_func) def test_clear(self): assert len(self.t) == 6 self.t.clear() assert len(self.t) == 0 def test_concat(self): self.fail("Code and doc revision needed") def test_generate_key(self): # test autoincrement assert '1' == self.t.generate_key() assert '2' == self.t.generate_key() # test UUID on server fail (the fail is faked by monkey-patching) real_genuid = self.t.proto.genuid def fake_genuid(): raise ValueError self.t.proto.genuid = fake_genuid assert isinstance(self.t.generate_key(), uuid.UUID) self.t.proto.genuid = real_genuid def test_get_size(self): self.assertRaises(KeyError, lambda:self.t.get_size("melon")) assert self.t.get_size("apple") == 34 #More usefull in not table dbtype. 34 is magic def test_get_stats(self): stats = self.t.get_stats() assert stats["rnum"] == "6" assert stats["type"] == protocol.DB_TABLE assert self.t.db_type == protocol.DB_TABLE assert self.t.table_enabled == True def test_iterkeys(self): keys = set("apple blueberry peach pear raspberry strawberry".split()) g = self.t.iterkeys() assert hasattr(g, '__iter__') assert not hasattr(g, '__len__') db_keys = set([key for key in g]) assert keys == db_keys def test_keys(self): assert self.t.keys() == "apple blueberry peach pear raspberry strawberry".split() #BTree and Tables are ordered def test_iteritems(self): g = self.t.iteritems() assert hasattr(g, '__iter__') assert not hasattr(g, '__len__') lst = list(g) assert len(lst) == 6 assert 'apple' in dict(lst) def test_items(self): assert dict(self.t.iteritems()) == dict(self.t.items()) def test_itervalues(self): g = self.t.itervalues() assert hasattr(g, '__iter__') assert not hasattr(g, '__len__') lst = list(g) assert len(lst) == 6 assert 'color' in lst[0] assert lst[0]['color'] == 'red' def test_values(self): assert dict(self.t.itervalues()) == dict(self.t.values()) def test_update(self): assert "melon" not in self.t assert "tomatoe" not in self.t #Update from named params self.t.update( melon = dict(store="VillaConejos", color="green"), tomatoe = dict(store="Bah de Perales", color="red") ) assert "melon" in self.t assert "tomatoe" in self.t self.t.clear() #Update from a key and value list self.t.update([ ("melon", dict(store="VillaConejos", color="green")), ("tomatoe", dict(store="Bah de Perales", color="red")) ]) assert "melon" in self.t assert "tomatoe" in self.t self.t.clear() #Update from another dict self.t.update(dict( melon = dict(store="VillaConejos", color="green"), tomatoe = dict(store="Bah de Perales", color="red") )) assert "melon" in self.t assert "tomatoe" in self.t def test_multi_del(self): assert len(self.t) == 6 self.t.multi_del(["apple", "pear"]) assert len(self.t) == 4 assert "apple" not in self.t assert "pear" not in self.t def test_multi_get(self): fruits = self.t.multi_get("apple melon pear".split()) fruits = dict(fruits) assert len(fruits) == 2 assert "apple" in fruits assert "pear" in fruits def test_multi_set(self): self.t.multi_set(dict( melon = dict(store="VillaConejos", color="green"), tomatoe = dict(store="Bah de Perales", color="red") )) assert "melon" in self.t assert "tomatoe" in self.t assert self.t["melon"] == dict(store="VillaConejos", color="green") assert self.t["tomatoe"] == dict(store="Bah de Perales", color="red") def test_prefix_keys(self): fruits_a = self.t.prefix_keys("a") assert len(fruits_a) == 1 fruits_p = self.t.prefix_keys("p") assert len(fruits_p) == 2 fruits_p1 = self.t.prefix_keys("p", 1) assert len(fruits_p1) == 1 fruits_m = self.t.prefix_keys("m") assert len(fruits_m) == 0 def test_sync(self): #I don't know if sync system call is performed, but i can test if the # function call returns an error. self.t.sync() def test_query(self): pass def test_unicode(self): item_with_unicode_value = {'name': u'Андрей'} item_with_unicode_key = {u'имя': 'Andrey'} ascii_pk = 'primary key' unicode_pk = u'первичный ключ' self.t[ascii_pk] = item_with_unicode_value assert self.t[ascii_pk] == item_with_unicode_value self.t[ascii_pk] = item_with_unicode_key assert self.t[ascii_pk] == item_with_unicode_key self.t[unicode_pk] = item_with_unicode_value assert self.t[unicode_pk] == item_with_unicode_value