Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1from hashlib import sha1 

2 

3from ..util import compat 

4from ..util import langhelpers 

5 

6 

7def 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 = compat.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 ) 

40 if has_self: 

41 args = args[1:] 

42 

43 return namespace + "|" + " ".join(map(to_str, args)) 

44 

45 return generate_key 

46 

47 

48def function_multi_key_generator(namespace, fn, to_str=compat.string_type): 

49 

50 if namespace is None: 

51 namespace = "%s:%s" % (fn.__module__, fn.__name__) 

52 else: 

53 namespace = "%s:%s|%s" % (fn.__module__, fn.__name__, namespace) 

54 

55 args = compat.inspect_getargspec(fn) 

56 has_self = args[0] and args[0][0] in ("self", "cls") 

57 

58 def generate_keys(*args, **kw): 

59 if kw: 

60 raise ValueError( 

61 "dogpile.cache's default key creation " 

62 "function does not accept keyword arguments." 

63 ) 

64 if has_self: 

65 args = args[1:] 

66 return [namespace + "|" + key for key in map(to_str, args)] 

67 

68 return generate_keys 

69 

70 

71def kwarg_function_key_generator(namespace, fn, to_str=compat.string_type): 

72 """Return a function that generates a string 

73 key, based on a given function as well as 

74 arguments to the returned function itself. 

75 

76 For kwargs passed in, we will build a dict of 

77 all argname (key) argvalue (values) including 

78 default args from the argspec and then 

79 alphabetize the list before generating the 

80 key. 

81 

82 .. versionadded:: 0.6.2 

83 

84 .. seealso:: 

85 

86 :func:`.function_key_generator` - default key generation function 

87 

88 """ 

89 

90 if namespace is None: 

91 namespace = "%s:%s" % (fn.__module__, fn.__name__) 

92 else: 

93 namespace = "%s:%s|%s" % (fn.__module__, fn.__name__, namespace) 

94 

95 argspec = compat.inspect_getargspec(fn) 

96 default_list = list(argspec.defaults or []) 

97 # Reverse the list, as we want to compare the argspec by negative index, 

98 # meaning default_list[0] should be args[-1], which works well with 

99 # enumerate() 

100 default_list.reverse() 

101 # use idx*-1 to create the correct right-lookup index. 

102 args_with_defaults = dict( 

103 (argspec.args[(idx * -1)], default) 

104 for idx, default in enumerate(default_list, 1) 

105 ) 

106 if argspec.args and argspec.args[0] in ("self", "cls"): 

107 arg_index_start = 1 

108 else: 

109 arg_index_start = 0 

110 

111 def generate_key(*args, **kwargs): 

112 as_kwargs = dict( 

113 [ 

114 (argspec.args[idx], arg) 

115 for idx, arg in enumerate( 

116 args[arg_index_start:], arg_index_start 

117 ) 

118 ] 

119 ) 

120 as_kwargs.update(kwargs) 

121 for arg, val in args_with_defaults.items(): 

122 if arg not in as_kwargs: 

123 as_kwargs[arg] = val 

124 

125 argument_values = [as_kwargs[key] for key in sorted(as_kwargs.keys())] 

126 return namespace + "|" + " ".join(map(to_str, argument_values)) 

127 

128 return generate_key 

129 

130 

131def sha1_mangle_key(key): 

132 """a SHA1 key mangler.""" 

133 

134 if isinstance(key, compat.text_type): 

135 key = key.encode("utf-8") 

136 

137 return sha1(key).hexdigest() 

138 

139 

140def length_conditional_mangler(length, mangler): 

141 """a key mangler that mangles if the length of the key is 

142 past a certain threshold. 

143 

144 """ 

145 

146 def mangle(key): 

147 if len(key) >= length: 

148 return mangler(key) 

149 else: 

150 return key 

151 

152 return mangle 

153 

154 

155# in the 0.6 release these functions were moved to the dogpile.util namespace. 

156# They are linked here to maintain compatibility with older versions. 

157 

158coerce_string_conf = langhelpers.coerce_string_conf 

159KeyReentrantMutex = langhelpers.KeyReentrantMutex 

160memoized_property = langhelpers.memoized_property 

161PluginLoader = langhelpers.PluginLoader 

162to_list = langhelpers.to_list 

163 

164 

165class repr_obj(object): 

166 

167 __slots__ = ("value", "max_chars") 

168 

169 def __init__(self, value, max_chars=300): 

170 self.value = value 

171 self.max_chars = max_chars 

172 

173 def __eq__(self, other): 

174 return other.value == self.value 

175 

176 def __repr__(self): 

177 rep = repr(self.value) 

178 lenrep = len(rep) 

179 if lenrep > self.max_chars: 

180 segment_length = self.max_chars // 2 

181 rep = ( 

182 rep[0:segment_length] 

183 + ( 

184 " ... (%d characters truncated) ... " 

185 % (lenrep - self.max_chars) 

186 ) 

187 + rep[-segment_length:] 

188 ) 

189 return rep