135 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""
 | 
						|
Useful testing utilities.
 | 
						|
 | 
						|
This module is considered public API.
 | 
						|
 | 
						|
"""
 | 
						|
 | 
						|
import time
 | 
						|
 | 
						|
import six
 | 
						|
 | 
						|
from pymemcache.client import MemcacheIllegalInputError
 | 
						|
 | 
						|
 | 
						|
class MockMemcacheClient(object):
 | 
						|
    """
 | 
						|
    A (partial) in-memory mock for Clients.
 | 
						|
 | 
						|
    """
 | 
						|
 | 
						|
    def __init__(self,
 | 
						|
                 server=None,
 | 
						|
                 serializer=None,
 | 
						|
                 deserializer=None,
 | 
						|
                 connect_timeout=None,
 | 
						|
                 timeout=None,
 | 
						|
                 no_delay=False,
 | 
						|
                 ignore_exc=False):
 | 
						|
 | 
						|
        self._contents = {}
 | 
						|
 | 
						|
        self.serializer = serializer
 | 
						|
        self.deserializer = deserializer
 | 
						|
 | 
						|
        # Unused, but present for interface compatibility
 | 
						|
        self.server = server
 | 
						|
        self.connect_timeout = connect_timeout
 | 
						|
        self.timeout = timeout
 | 
						|
        self.no_delay = no_delay
 | 
						|
        self.ignore_exc = ignore_exc
 | 
						|
 | 
						|
    def get(self, key):
 | 
						|
        if isinstance(key, six.text_type):
 | 
						|
            raise MemcacheIllegalInputError(key)
 | 
						|
 | 
						|
        if key not in self._contents:
 | 
						|
            return None
 | 
						|
 | 
						|
        expire, value, was_serialized = self._contents[key]
 | 
						|
        if expire and expire < time.time():
 | 
						|
            del self._contents[key]
 | 
						|
            return None
 | 
						|
 | 
						|
        if self.deserializer:
 | 
						|
            return self.deserializer(key, value, 2 if was_serialized else 1)
 | 
						|
        return value
 | 
						|
 | 
						|
    def get_many(self, keys):
 | 
						|
        out = {}
 | 
						|
        for key in keys:
 | 
						|
            value = self.get(key)
 | 
						|
            if value is not None:
 | 
						|
                out[key] = value
 | 
						|
        return out
 | 
						|
 | 
						|
    def set(self, key, value, expire=0, noreply=True):
 | 
						|
        if isinstance(key, six.text_type):
 | 
						|
            raise MemcacheIllegalInputError(key)
 | 
						|
        if isinstance(value, six.text_type):
 | 
						|
            raise MemcacheIllegalInputError(value)
 | 
						|
 | 
						|
        was_serialized = False
 | 
						|
        if self.serializer:
 | 
						|
            value = self.serializer(key, value)
 | 
						|
 | 
						|
        if expire:
 | 
						|
            expire += time.time()
 | 
						|
 | 
						|
        self._contents[key] = expire, value, was_serialized
 | 
						|
        return True
 | 
						|
 | 
						|
    def set_many(self, values, expire=None, noreply=True):
 | 
						|
        for key, value in six.iteritems(values):
 | 
						|
            self.set(key, value, expire, noreply)
 | 
						|
        return True
 | 
						|
 | 
						|
    def incr(self, key, value, noreply=False):
 | 
						|
        current = self.get(key)
 | 
						|
        present = current is not None
 | 
						|
        if present:
 | 
						|
            self.set(key, current + value, noreply=noreply)
 | 
						|
        return None if noreply or not present else current + value
 | 
						|
 | 
						|
    def decr(self, key, value, noreply=False):
 | 
						|
        current = self.get(key)
 | 
						|
        if current is None:
 | 
						|
            return
 | 
						|
 | 
						|
        self.set(key, current - value, noreply=noreply)
 | 
						|
        return current - value
 | 
						|
 | 
						|
    def add(self, key, value, expire=None, noreply=True):
 | 
						|
        current = self.get(key)
 | 
						|
        present = current is not None
 | 
						|
        if not present:
 | 
						|
            self.set(key, value, expire, noreply)
 | 
						|
        return not present
 | 
						|
 | 
						|
    def delete(self, key, noreply=True):
 | 
						|
        current = self._contents.pop(key, None)
 | 
						|
        present = current is not None
 | 
						|
        return noreply or present
 | 
						|
 | 
						|
    def stats(self):
 | 
						|
        # I make no claim that these values make any sense, but the format
 | 
						|
        # of the output is the same as for pymemcache.client.Client.stats()
 | 
						|
        return {
 | 
						|
            "version": "MockMemcacheClient",
 | 
						|
            "rusage_user": 1.0,
 | 
						|
            "rusage_system": 1.0,
 | 
						|
            "hash_is_expanding": False,
 | 
						|
            "slab_reassign_running": False,
 | 
						|
            "inter": "in-memory",
 | 
						|
            "evictions": False,
 | 
						|
            "growth_factor": 1.0,
 | 
						|
            "stat_key_prefix": "",
 | 
						|
            "umask": 0o644,
 | 
						|
            "detail_enabled": False,
 | 
						|
            "cas_enabled": False,
 | 
						|
            "auth_enabled_sasl": False,
 | 
						|
            "maxconns_fast": False,
 | 
						|
            "slab_reassign": False,
 | 
						|
            "slab_automove": False,
 | 
						|
        }
 |