TokyoTyrantをモデルっぽく使う TokyoTyrantStorage

投稿者: ytyng 12年, 10ヶ月 前
# -*- coding: utf-8 -*-

"""
TokyoTyrantをモデルっぽく使う

class Soldier(TokyoTyrantStorage):
    
    hp = TokyoTyrantStorage.Field(default=0)
    mp = TokyoTyrantStorage.Field(default=0)

cain = Soldier('Cain')
cain.hp = 100
cain.mp = 50
cain.save()

abel = Soldier('Abel')
abel.hp = 50
abel.mp = 100
abel.save()

cain = Soldier('Cain')
cain.hp -= 80
cain.save()

abel = Soldier('Abel')
abel.mp -= 20
abel.save()

cain = Soldier('Cain')
cain.hp = min(cain.hp + 50, 100)
cain.save()

cain = Soldier('Cain')
cain.hp

Out: 70

"""

import logging
from tokyotyrant import get_client
import msgpack

class TokyoTyrantStorage(object):
    """
    TokyoTyrantをディクショナリとして使う基底クラス
    継承して使ってください
    """
    packer = msgpack.Packer()
    tt_client = get_client()

    def __new__(cls, *args, **kwargs):
        for k, v in vars(cls).iteritems():
            if isinstance(v, TokyoTyrantStorage.Field):
                v.set_field_name(k)
        return object.__new__(cls)

    def __init__(self, key_object):
        """
        @param key_object djangoのモデルインスタンスなど。player や osuser
        オーバーライドして、superの__init__を呼びたくないときは
        そのまま self.after_init(key_part) する
        """
        self.key_object = key_object
        key_part = getattr(key_object, 'pk', str(key_object))
        self.after_init(key_part)

    def after_init(self, key_part):
        """
        初期化処理の後半
        @param (str)key_part キー生成の元となるユニークな文字列
        """
        self.kvs_key = '%s::%s' % (self.__class__.__name__, key_part)
        bulk_storage = self.tt_client.get(self.kvs_key, None)
        if bulk_storage:
            self.storage = msgpack.unpackb(bulk_storage)
        else:
            self.storage = {}

    def get(self, k, default=None):
        return self.storage.get(k,default)

    def set(self, k, value):
        self.storage[k] = value

    def save(self):
        """
        storageを保存
        """
        self.tt_client.set(self.kvs_key, self.packer.pack(self.storage))

    def delete(self):
        """
        storageを削除
        """
        self.tt_client.out(self.kvs_key)
        self.storage = {}

    def dump(self):
        logging.debug("[TokyoTyrantStorage] dump: kvs_key=%s, storage=%r" % (self.kvs_key, self.storage))


    class Field(object):
        """
        TokyoTyrantStorage に使えるフィールド
        score = TokyoTyrantStorage.Field(default=0) みたいに使う。
        """

        def __init__(self, key_name=None, default=None):
            self._key_name = key_name 
            self.default = default

        def __get__(self, inst, type=None):
            assert isinstance(inst, TokyoTyrantStorage), '%s use only TokyoTyrantStorage class.' % self.__class__.__name__
            return inst.get(self.key_name, self.default)

        def __set__(self, inst, value):
            assert isinstance(inst, TokyoTyrantStorage), '%s use only TokyoTyrantStorage class.' % self.__class__.__name__
            inst.set(self.key_name, value)

        def set_field_name(self, field_name):
            #TokyoTyrantStorage.__new__ から呼ばれる
            self.field_name = field_name

        @property
        def key_name(self):
            return self._key_name or self.field_name
現在未評価

コメント

アーカイブ

2024
2023
2022
2021
2020
2019
2018
2017
2016
2015
2014
2013
2012
2011