def proxy_from_registry(self, path, db_name=None, *args, **kwargs): """Check if an existing proxy already exists in the registry, if not create a new one with the supplied path. This function is thread-safe. :param path: (tuple) The tuple representation of a dotted path. :param db_name: (str) What redis db to use. :param rconn: (redis.Redis) The redis connection to use. :returns Proxy: A new or existing """ path_elems = [] if isinstance(path, six.string_types): util.validate_key(path) path_elems = path.split(".") else: # Assume it is iterable or None. for elem in path or []: util.validate_path_element(elem) path_elems.append(elem) # Convert to tuple, so path elements stay hashable. path_elems_tuple = tuple(path_elems) kwargs["db_name"] = db_name with self._lock: # Prefer the one passed directly. return self._proxies[db_name].setdefault( path_elems_tuple, _Proxy(path_elems_tuple, *args, **kwargs))
def set(self, key, value, expire=None): """Set a new value to this key. :param key: (str) A dotted path. :param value: (object) Any value that can be passed to json.dumps. :param expire: (int) Time in seconds when to expire this key or None. """ util.validate_key(key) full_key = self._get_full_key(key) conn = self._conn() # Delete any previous keys since we're overwriting this key. # We don't want to have those old keys lying around above. util.clear_parents(conn, full_key) if isinstance(value, dict): # We overwrite all children, clear any leftover keys. self.get(key).clear() items = util.extract_keys(value, full_key) else: items = ((full_key, value), ) # Allow floats as expire time: if expire is not None: expire = int(expire) for full_key, value in items: conn.set(full_key, json.dumps(value), ex=expire) return self
def delete(self, key): """Delete an existing key. :param key: (str) A dotted path. """ util.validate_key(key) self.get(key).clear()
def __init__(self, redis_conn, key, expire_timeout=30, acquire_timeout=10): # Note: This object may not have any state (counter, etc.) # in order to stay thread-safe. The redis connection is thread-safe. util.validate_key(key) self._key = key self._redis_conn = redis_conn self._expire_seconds = max(1, expire_timeout) self._acquire_seconds = max(1, acquire_timeout)
def get(self, key): """Return a lazy value for this key. :param key: (str) A dotted path or simple :return: A child Proxy. """ util.validate_key(key) child_path = self._path + tuple(key.split('.')) return _REGISTRY.proxy_from_registry(child_path, db_name=self._db_name)
def test_validate_key(): """Try some invalid keys""" with pytest.raises(ValueError): validate_key("") with pytest.raises(ValueError): validate_key(".a") with pytest.raises(ValueError): validate_key("a.") with pytest.raises(ValueError): validate_key("a..b") validate_key("a.b")