OLD | NEW |
(Empty) | |
| 1 from hashlib import sha1 |
| 2 import inspect |
| 3 from ..util import compat |
| 4 from ..util import langhelpers |
| 5 |
| 6 |
| 7 def function_key_generator(namespace, fn, to_str=compat.string_type): |
| 8 """Return a function that generates a string |
| 9 key, based on a given function as well as |
| 10 arguments to the returned function itself. |
| 11 |
| 12 This is used by :meth:`.CacheRegion.cache_on_arguments` |
| 13 to generate a cache key from a decorated function. |
| 14 |
| 15 An alternate function may be used by specifying |
| 16 the :paramref:`.CacheRegion.function_key_generator` argument |
| 17 for :class:`.CacheRegion`. |
| 18 |
| 19 .. seealso:: |
| 20 |
| 21 :func:`.kwarg_function_key_generator` - similar function that also |
| 22 takes keyword arguments into account |
| 23 |
| 24 """ |
| 25 |
| 26 if namespace is None: |
| 27 namespace = '%s:%s' % (fn.__module__, fn.__name__) |
| 28 else: |
| 29 namespace = '%s:%s|%s' % (fn.__module__, fn.__name__, namespace) |
| 30 |
| 31 args = inspect.getargspec(fn) |
| 32 has_self = args[0] and args[0][0] in ('self', 'cls') |
| 33 |
| 34 def generate_key(*args, **kw): |
| 35 if kw: |
| 36 raise ValueError( |
| 37 "dogpile.cache's default key creation " |
| 38 "function does not accept keyword arguments.") |
| 39 if has_self: |
| 40 args = args[1:] |
| 41 |
| 42 return namespace + "|" + " ".join(map(to_str, args)) |
| 43 return generate_key |
| 44 |
| 45 |
| 46 def function_multi_key_generator(namespace, fn, to_str=compat.string_type): |
| 47 |
| 48 if namespace is None: |
| 49 namespace = '%s:%s' % (fn.__module__, fn.__name__) |
| 50 else: |
| 51 namespace = '%s:%s|%s' % (fn.__module__, fn.__name__, namespace) |
| 52 |
| 53 args = inspect.getargspec(fn) |
| 54 has_self = args[0] and args[0][0] in ('self', 'cls') |
| 55 |
| 56 def generate_keys(*args, **kw): |
| 57 if kw: |
| 58 raise ValueError( |
| 59 "dogpile.cache's default key creation " |
| 60 "function does not accept keyword arguments.") |
| 61 if has_self: |
| 62 args = args[1:] |
| 63 return [namespace + "|" + key for key in map(to_str, args)] |
| 64 return generate_keys |
| 65 |
| 66 |
| 67 def kwarg_function_key_generator(namespace, fn, to_str=compat.string_type): |
| 68 """Return a function that generates a string |
| 69 key, based on a given function as well as |
| 70 arguments to the returned function itself. |
| 71 |
| 72 For kwargs passed in, we will build a dict of |
| 73 all argname (key) argvalue (values) including |
| 74 default args from the argspec and then |
| 75 alphabetize the list before generating the |
| 76 key. |
| 77 |
| 78 .. versionadded:: 0.6.2 |
| 79 |
| 80 .. seealso:: |
| 81 |
| 82 :func:`.function_key_generator` - default key generation function |
| 83 |
| 84 """ |
| 85 |
| 86 if namespace is None: |
| 87 namespace = '%s:%s' % (fn.__module__, fn.__name__) |
| 88 else: |
| 89 namespace = '%s:%s|%s' % (fn.__module__, fn.__name__, namespace) |
| 90 |
| 91 argspec = inspect.getargspec(fn) |
| 92 default_list = list(argspec.defaults or []) |
| 93 # Reverse the list, as we want to compare the argspec by negative index, |
| 94 # meaning default_list[0] should be args[-1], which works well with |
| 95 # enumerate() |
| 96 default_list.reverse() |
| 97 # use idx*-1 to create the correct right-lookup index. |
| 98 args_with_defaults = dict((argspec.args[(idx*-1)], default) |
| 99 for idx, default in enumerate(default_list, 1)) |
| 100 if argspec.args and argspec.args[0] in ('self', 'cls'): |
| 101 arg_index_start = 1 |
| 102 else: |
| 103 arg_index_start = 0 |
| 104 |
| 105 def generate_key(*args, **kwargs): |
| 106 as_kwargs = dict( |
| 107 [(argspec.args[idx], arg) |
| 108 for idx, arg in enumerate(args[arg_index_start:], |
| 109 arg_index_start)]) |
| 110 as_kwargs.update(kwargs) |
| 111 for arg, val in args_with_defaults.items(): |
| 112 if arg not in as_kwargs: |
| 113 as_kwargs[arg] = val |
| 114 |
| 115 argument_values = [as_kwargs[key] |
| 116 for key in sorted(as_kwargs.keys())] |
| 117 return namespace + '|' + " ".join(map(to_str, argument_values)) |
| 118 return generate_key |
| 119 |
| 120 |
| 121 def sha1_mangle_key(key): |
| 122 """a SHA1 key mangler.""" |
| 123 |
| 124 return sha1(key).hexdigest() |
| 125 |
| 126 |
| 127 def length_conditional_mangler(length, mangler): |
| 128 """a key mangler that mangles if the length of the key is |
| 129 past a certain threshold. |
| 130 |
| 131 """ |
| 132 def mangle(key): |
| 133 if len(key) >= length: |
| 134 return mangler(key) |
| 135 else: |
| 136 return key |
| 137 return mangle |
| 138 |
| 139 # in the 0.6 release these functions were moved to the dogpile.util namespace. |
| 140 # They are linked here to maintain compatibility with older versions. |
| 141 |
| 142 coerce_string_conf = langhelpers.coerce_string_conf |
| 143 KeyReentrantMutex = langhelpers.KeyReentrantMutex |
| 144 memoized_property = langhelpers.memoized_property |
| 145 PluginLoader = langhelpers.PluginLoader |
| 146 to_list = langhelpers.to_list |
OLD | NEW |