Esempio n. 1
0
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
Esempio n. 2
0
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