Added cache_utils to the distribution because it includes a patch and is not packaged...
[plcapi.git] / cache_utils / utils.py
diff --git a/cache_utils/utils.py b/cache_utils/utils.py
new file mode 100644 (file)
index 0000000..ed7474d
--- /dev/null
@@ -0,0 +1,60 @@
+from hashlib import md5
+
+CONTROL_CHARACTERS = set([chr(i) for i in range(0,33)])
+CONTROL_CHARACTERS.add(chr(127))
+
+def sanitize_memcached_key(key, max_length=250):
+    """ Removes control characters and ensures that key will
+        not hit the memcached key length limit by replacing
+        the key tail with md5 hash if key is too long.
+    """
+    key = ''.join([c for c in key if c not in CONTROL_CHARACTERS])
+    if len(key) > max_length:
+        hash = md5(key).hexdigest()
+        key = key[:max_length-33]+'-'+hash
+    return key
+
+def _args_to_unicode(args, kwargs):
+    key = ""
+    if args:
+        key += unicode(args)
+    if kwargs:
+        key += unicode(kwargs)
+    return key
+
+
+def _func_type(func):
+    """ returns if callable is a function, method or a classmethod """
+    argnames = func.func_code.co_varnames[:func.func_code.co_argcount]
+    if len(argnames) > 0:
+        if argnames[0] == 'self':
+            return 'method'
+        if argnames[0] == 'cls':
+            return 'classmethod'
+    return 'function'
+
+
+def _func_info(func, args):
+    ''' introspect function's or method's full name.
+    Returns a tuple (name, normalized_args,) with
+    'cls' and 'self' removed from normalized_args '''
+
+    func_type = _func_type(func)
+
+    if func_type == 'function':
+        return ".".join([func.__module__, func.__name__]), args
+
+    class_name = args[0].__class__.__name__
+    if func_type == 'classmethod':
+        class_name = args[0].__name__
+
+    return ".".join([func.__module__, class_name, func.__name__]), args[1:]
+
+
+def _cache_key(func_name, func_type, args, kwargs):
+    """ Construct readable cache key """
+    if func_type == 'function':
+        args_string = _args_to_unicode(args, kwargs)
+    else:
+        args_string = _args_to_unicode(args[1:], kwargs)
+    return sanitize_memcached_key('[cached]%s(%s)' % (func_name, args_string,))