Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.10/site-packages/django/urls/base.py: 20%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

106 statements  

1from urllib.parse import unquote, urlencode, urlsplit, urlunsplit 

2 

3from asgiref.local import Local 

4 

5from django.http import QueryDict 

6from django.utils.functional import lazy 

7from django.utils.translation import override 

8 

9from .exceptions import NoReverseMatch, Resolver404 

10from .resolvers import _get_cached_resolver, get_ns_resolver, get_resolver 

11from .utils import get_callable 

12 

13# SCRIPT_NAME prefixes for each thread are stored here. If there's no entry for 

14# the current thread (which is the only one we ever access), it is assumed to 

15# be empty. 

16_prefixes = Local() 

17 

18# Overridden URLconfs for each thread are stored here. 

19_urlconfs = Local() 

20 

21 

22def resolve(path, urlconf=None): 

23 if urlconf is None: 

24 urlconf = get_urlconf() 

25 return get_resolver(urlconf).resolve(path) 

26 

27 

28def reverse( 

29 viewname, 

30 urlconf=None, 

31 args=None, 

32 kwargs=None, 

33 current_app=None, 

34 *, 

35 query=None, 

36 fragment=None, 

37): 

38 if urlconf is None: 

39 urlconf = get_urlconf() 

40 resolver = get_resolver(urlconf) 

41 args = args or [] 

42 kwargs = kwargs or {} 

43 

44 prefix = get_script_prefix() 

45 

46 if not isinstance(viewname, str): 

47 view = viewname 

48 else: 

49 *path, view = viewname.split(":") 

50 

51 if current_app: 

52 current_path = current_app.split(":") 

53 current_path.reverse() 

54 else: 

55 current_path = None 

56 

57 resolved_path = [] 

58 ns_pattern = "" 

59 ns_converters = {} 

60 for ns in path: 

61 current_ns = current_path.pop() if current_path else None 

62 # Lookup the name to see if it could be an app identifier. 

63 try: 

64 app_list = resolver.app_dict[ns] 

65 # Yes! Path part matches an app in the current Resolver. 

66 if current_ns and current_ns in app_list: 

67 # If we are reversing for a particular app, use that 

68 # namespace. 

69 ns = current_ns 

70 elif ns not in app_list: 

71 # The name isn't shared by one of the instances (i.e., 

72 # the default) so pick the first instance as the default. 

73 ns = app_list[0] 

74 except KeyError: 

75 pass 

76 

77 if ns != current_ns: 

78 current_path = None 

79 

80 try: 

81 extra, resolver = resolver.namespace_dict[ns] 

82 resolved_path.append(ns) 

83 ns_pattern += extra 

84 ns_converters.update(resolver.pattern.converters) 

85 except KeyError as key: 

86 if resolved_path: 

87 raise NoReverseMatch( 

88 "%s is not a registered namespace inside '%s'" 

89 % (key, ":".join(resolved_path)) 

90 ) 

91 else: 

92 raise NoReverseMatch("%s is not a registered namespace" % key) 

93 if ns_pattern: 

94 resolver = get_ns_resolver( 

95 ns_pattern, resolver, tuple(ns_converters.items()) 

96 ) 

97 

98 resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) 

99 if query is not None: 

100 if isinstance(query, QueryDict): 

101 query_string = query.urlencode() 

102 else: 

103 query_string = urlencode(query, doseq=True) 

104 if query_string: 

105 resolved_url += "?" + query_string 

106 if fragment is not None: 

107 resolved_url += "#" + fragment 

108 return resolved_url 

109 

110 

111reverse_lazy = lazy(reverse, str) 

112 

113 

114def clear_url_caches(): 

115 get_callable.cache_clear() 

116 _get_cached_resolver.cache_clear() 

117 get_ns_resolver.cache_clear() 

118 

119 

120def set_script_prefix(prefix): 

121 """ 

122 Set the script prefix for the current thread. 

123 """ 

124 if not prefix.endswith("/"): 

125 prefix += "/" 

126 _prefixes.value = prefix 

127 

128 

129def get_script_prefix(): 

130 """ 

131 Return the currently active script prefix. Useful for client code that 

132 wishes to construct their own URLs manually (although accessing the request 

133 instance is normally going to be a lot cleaner). 

134 """ 

135 return getattr(_prefixes, "value", "/") 

136 

137 

138def clear_script_prefix(): 

139 """ 

140 Unset the script prefix for the current thread. 

141 """ 

142 try: 

143 del _prefixes.value 

144 except AttributeError: 

145 pass 

146 

147 

148def set_urlconf(urlconf_name): 

149 """ 

150 Set the URLconf for the current thread or asyncio task (overriding the 

151 default one in settings). If urlconf_name is None, revert back to the 

152 default. 

153 """ 

154 if urlconf_name: 

155 _urlconfs.value = urlconf_name 

156 else: 

157 if hasattr(_urlconfs, "value"): 

158 del _urlconfs.value 

159 

160 

161def get_urlconf(default=None): 

162 """ 

163 Return the root URLconf to use for the current thread or asyncio task if it 

164 has been changed from the default one. 

165 """ 

166 return getattr(_urlconfs, "value", default) 

167 

168 

169def is_valid_path(path, urlconf=None): 

170 """ 

171 Return the ResolverMatch if the given path resolves against the default URL 

172 resolver, False otherwise. This is a convenience method to make working 

173 with "is this a match?" cases easier, avoiding try...except blocks. 

174 """ 

175 try: 

176 return resolve(path, urlconf) 

177 except Resolver404: 

178 return False 

179 

180 

181def translate_url(url, lang_code): 

182 """ 

183 Given a URL (absolute or relative), try to get its translated version in 

184 the `lang_code` language (either by i18n_patterns or by translated regex). 

185 Return the original URL if no translated version is found. 

186 """ 

187 parsed = urlsplit(url) 

188 try: 

189 # URL may be encoded. 

190 match = resolve(unquote(parsed.path)) 

191 except Resolver404: 

192 pass 

193 else: 

194 to_be_reversed = ( 

195 "%s:%s" % (match.namespace, match.url_name) 

196 if match.namespace 

197 else match.url_name 

198 ) 

199 with override(lang_code): 

200 try: 

201 url = reverse(to_be_reversed, args=match.args, kwargs=match.kwargs) 

202 except NoReverseMatch: 

203 pass 

204 else: 

205 url = urlunsplit( 

206 (parsed.scheme, parsed.netloc, url, parsed.query, parsed.fragment) 

207 ) 

208 return url