Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/sentry_sdk/integrations/django/transactions.py: 79%

69 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1""" 

2Copied from raven-python. Used for 

3`DjangoIntegration(transaction_fron="raven_legacy")`. 

4""" 

5 

6from __future__ import absolute_import 

7 

8import re 

9 

10from sentry_sdk._types import MYPY 

11 

12if MYPY: 12 ↛ 13line 12 didn't jump to line 13, because the condition on line 12 was never true

13 from django.urls.resolvers import URLResolver 

14 from typing import Dict 

15 from typing import List 

16 from typing import Optional 

17 from django.urls.resolvers import URLPattern 

18 from typing import Tuple 

19 from typing import Union 

20 from re import Pattern 

21 

22try: 

23 from django.urls import get_resolver 

24except ImportError: 

25 from django.core.urlresolvers import get_resolver 

26 

27 

28def get_regex(resolver_or_pattern): 

29 # type: (Union[URLPattern, URLResolver]) -> Pattern[str] 

30 """Utility method for django's deprecated resolver.regex""" 

31 try: 

32 regex = resolver_or_pattern.regex 

33 except AttributeError: 

34 regex = resolver_or_pattern.pattern.regex 

35 return regex 

36 

37 

38class RavenResolver(object): 

39 _optional_group_matcher = re.compile(r"\(\?\:([^\)]+)\)") 

40 _named_group_matcher = re.compile(r"\(\?P<(\w+)>[^\)]+\)+") 

41 _non_named_group_matcher = re.compile(r"\([^\)]+\)") 

42 # [foo|bar|baz] 

43 _either_option_matcher = re.compile(r"\[([^\]]+)\|([^\]]+)\]") 

44 _camel_re = re.compile(r"([A-Z]+)([a-z])") 

45 

46 _cache = {} # type: Dict[URLPattern, str] 

47 

48 def _simplify(self, pattern): 

49 # type: (str) -> str 

50 r""" 

51 Clean up urlpattern regexes into something readable by humans: 

52 

53 From: 

54 > "^(?P<sport_slug>\w+)/athletes/(?P<athlete_slug>\w+)/$" 

55 

56 To: 

57 > "{sport_slug}/athletes/{athlete_slug}/" 

58 """ 

59 # remove optional params 

60 # TODO(dcramer): it'd be nice to change these into [%s] but it currently 

61 # conflicts with the other rules because we're doing regexp matches 

62 # rather than parsing tokens 

63 result = self._optional_group_matcher.sub(lambda m: "%s" % m.group(1), pattern) 63 ↛ exitline 63 didn't run the lambda on line 63

64 

65 # handle named groups first 

66 result = self._named_group_matcher.sub(lambda m: "{%s}" % m.group(1), result) 

67 

68 # handle non-named groups 

69 result = self._non_named_group_matcher.sub("{var}", result) 

70 

71 # handle optional params 

72 result = self._either_option_matcher.sub(lambda m: m.group(1), result) 72 ↛ exitline 72 didn't run the lambda on line 72

73 

74 # clean up any outstanding regex-y characters. 

75 result = ( 

76 result.replace("^", "") 

77 .replace("$", "") 

78 .replace("?", "") 

79 .replace("\\A", "") 

80 .replace("\\Z", "") 

81 .replace("//", "/") 

82 .replace("\\", "") 

83 ) 

84 

85 return result 

86 

87 def _resolve(self, resolver, path, parents=None): 

88 # type: (URLResolver, str, Optional[List[URLResolver]]) -> Optional[str] 

89 

90 match = get_regex(resolver).search(path) # Django < 2.0 

91 

92 if not match: 

93 return None 

94 

95 if parents is None: 

96 parents = [resolver] 

97 elif resolver not in parents: 97 ↛ 100line 97 didn't jump to line 100, because the condition on line 97 was never false

98 parents = parents + [resolver] 

99 

100 new_path = path[match.end() :] 

101 for pattern in resolver.url_patterns: 101 ↛ 123line 101 didn't jump to line 123, because the loop on line 101 didn't complete

102 # this is an include() 

103 if not pattern.callback: 

104 match_ = self._resolve(pattern, new_path, parents) 

105 if match_: 105 ↛ 107line 105 didn't jump to line 107, because the condition on line 105 was never false

106 return match_ 

107 continue 

108 elif not get_regex(pattern).search(new_path): 

109 continue 

110 

111 try: 

112 return self._cache[pattern] 

113 except KeyError: 

114 pass 

115 

116 prefix = "".join(self._simplify(get_regex(p).pattern) for p in parents) 

117 result = prefix + self._simplify(get_regex(pattern).pattern) 

118 if not result.startswith("/"): 118 ↛ 119line 118 didn't jump to line 119, because the condition on line 118 was never true

119 result = "/" + result 

120 self._cache[pattern] = result 

121 return result 

122 

123 return None 

124 

125 def resolve( 

126 self, 

127 path, # type: str 

128 urlconf=None, # type: Union[None, Tuple[URLPattern, URLPattern, URLResolver], Tuple[URLPattern]] 

129 ): 

130 # type: (...) -> str 

131 resolver = get_resolver(urlconf) 

132 match = self._resolve(resolver, path) 

133 return match or path 

134 

135 

136LEGACY_RESOLVER = RavenResolver()