Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. from urllib.parse import unquote, urlsplit, urlunsplit
  2. from asgiref.local import Local
  3. from django.utils.functional import lazy
  4. from django.utils.translation import override
  5. from .exceptions import NoReverseMatch, Resolver404
  6. from .resolvers import _get_cached_resolver, get_ns_resolver, get_resolver
  7. from .utils import get_callable
  8. # SCRIPT_NAME prefixes for each thread are stored here. If there's no entry for
  9. # the current thread (which is the only one we ever access), it is assumed to
  10. # be empty.
  11. _prefixes = Local()
  12. # Overridden URLconfs for each thread are stored here.
  13. _urlconfs = Local()
  14. def resolve(path, urlconf=None):
  15. if urlconf is None:
  16. urlconf = get_urlconf()
  17. return get_resolver(urlconf).resolve(path)
  18. def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None):
  19. if urlconf is None:
  20. urlconf = get_urlconf()
  21. resolver = get_resolver(urlconf)
  22. args = args or []
  23. kwargs = kwargs or {}
  24. prefix = get_script_prefix()
  25. if not isinstance(viewname, str):
  26. view = viewname
  27. else:
  28. *path, view = viewname.split(":")
  29. if current_app:
  30. current_path = current_app.split(":")
  31. current_path.reverse()
  32. else:
  33. current_path = None
  34. resolved_path = []
  35. ns_pattern = ""
  36. ns_converters = {}
  37. for ns in path:
  38. current_ns = current_path.pop() if current_path else None
  39. # Lookup the name to see if it could be an app identifier.
  40. try:
  41. app_list = resolver.app_dict[ns]
  42. # Yes! Path part matches an app in the current Resolver.
  43. if current_ns and current_ns in app_list:
  44. # If we are reversing for a particular app, use that
  45. # namespace.
  46. ns = current_ns
  47. elif ns not in app_list:
  48. # The name isn't shared by one of the instances (i.e.,
  49. # the default) so pick the first instance as the default.
  50. ns = app_list[0]
  51. except KeyError:
  52. pass
  53. if ns != current_ns:
  54. current_path = None
  55. try:
  56. extra, resolver = resolver.namespace_dict[ns]
  57. resolved_path.append(ns)
  58. ns_pattern = ns_pattern + extra
  59. ns_converters.update(resolver.pattern.converters)
  60. except KeyError as key:
  61. if resolved_path:
  62. raise NoReverseMatch(
  63. "%s is not a registered namespace inside '%s'"
  64. % (key, ":".join(resolved_path))
  65. )
  66. else:
  67. raise NoReverseMatch("%s is not a registered namespace" % key)
  68. if ns_pattern:
  69. resolver = get_ns_resolver(
  70. ns_pattern, resolver, tuple(ns_converters.items())
  71. )
  72. return resolver._reverse_with_prefix(view, prefix, *args, **kwargs)
  73. reverse_lazy = lazy(reverse, str)
  74. def clear_url_caches():
  75. get_callable.cache_clear()
  76. _get_cached_resolver.cache_clear()
  77. get_ns_resolver.cache_clear()
  78. def set_script_prefix(prefix):
  79. """
  80. Set the script prefix for the current thread.
  81. """
  82. if not prefix.endswith("/"):
  83. prefix += "/"
  84. _prefixes.value = prefix
  85. def get_script_prefix():
  86. """
  87. Return the currently active script prefix. Useful for client code that
  88. wishes to construct their own URLs manually (although accessing the request
  89. instance is normally going to be a lot cleaner).
  90. """
  91. return getattr(_prefixes, "value", "/")
  92. def clear_script_prefix():
  93. """
  94. Unset the script prefix for the current thread.
  95. """
  96. try:
  97. del _prefixes.value
  98. except AttributeError:
  99. pass
  100. def set_urlconf(urlconf_name):
  101. """
  102. Set the URLconf for the current thread (overriding the default one in
  103. settings). If urlconf_name is None, revert back to the default.
  104. """
  105. if urlconf_name:
  106. _urlconfs.value = urlconf_name
  107. else:
  108. if hasattr(_urlconfs, "value"):
  109. del _urlconfs.value
  110. def get_urlconf(default=None):
  111. """
  112. Return the root URLconf to use for the current thread if it has been
  113. changed from the default one.
  114. """
  115. return getattr(_urlconfs, "value", default)
  116. def is_valid_path(path, urlconf=None):
  117. """
  118. Return the ResolverMatch if the given path resolves against the default URL
  119. resolver, False otherwise. This is a convenience method to make working
  120. with "is this a match?" cases easier, avoiding try...except blocks.
  121. """
  122. try:
  123. return resolve(path, urlconf)
  124. except Resolver404:
  125. return False
  126. def translate_url(url, lang_code):
  127. """
  128. Given a URL (absolute or relative), try to get its translated version in
  129. the `lang_code` language (either by i18n_patterns or by translated regex).
  130. Return the original URL if no translated version is found.
  131. """
  132. parsed = urlsplit(url)
  133. try:
  134. # URL may be encoded.
  135. match = resolve(unquote(parsed.path))
  136. except Resolver404:
  137. pass
  138. else:
  139. to_be_reversed = (
  140. "%s:%s" % (match.namespace, match.url_name)
  141. if match.namespace
  142. else match.url_name
  143. )
  144. with override(lang_code):
  145. try:
  146. url = reverse(to_be_reversed, args=match.args, kwargs=match.kwargs)
  147. except NoReverseMatch:
  148. pass
  149. else:
  150. url = urlunsplit(
  151. (parsed.scheme, parsed.netloc, url, parsed.query, parsed.fragment)
  152. )
  153. return url