Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pip/_vendor/rich/highlighter.py: 53%

53 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:48 +0000

1import re 

2from abc import ABC, abstractmethod 

3from typing import List, Union 

4 

5from .text import Span, Text 

6 

7 

8def _combine_regex(*regexes: str) -> str: 

9 """Combine a number of regexes in to a single regex. 

10 

11 Returns: 

12 str: New regex with all regexes ORed together. 

13 """ 

14 return "|".join(regexes) 

15 

16 

17class Highlighter(ABC): 

18 """Abstract base class for highlighters.""" 

19 

20 def __call__(self, text: Union[str, Text]) -> Text: 

21 """Highlight a str or Text instance. 

22 

23 Args: 

24 text (Union[str, ~Text]): Text to highlight. 

25 

26 Raises: 

27 TypeError: If not called with text or str. 

28 

29 Returns: 

30 Text: A test instance with highlighting applied. 

31 """ 

32 if isinstance(text, str): 

33 highlight_text = Text(text) 

34 elif isinstance(text, Text): 

35 highlight_text = text.copy() 

36 else: 

37 raise TypeError(f"str or Text instance required, not {text!r}") 

38 self.highlight(highlight_text) 

39 return highlight_text 

40 

41 @abstractmethod 

42 def highlight(self, text: Text) -> None: 

43 """Apply highlighting in place to text. 

44 

45 Args: 

46 text (~Text): A text object highlight. 

47 """ 

48 

49 

50class NullHighlighter(Highlighter): 

51 """A highlighter object that doesn't highlight. 

52 

53 May be used to disable highlighting entirely. 

54 

55 """ 

56 

57 def highlight(self, text: Text) -> None: 

58 """Nothing to do""" 

59 

60 

61class RegexHighlighter(Highlighter): 

62 """Applies highlighting from a list of regular expressions.""" 

63 

64 highlights: List[str] = [] 

65 base_style: str = "" 

66 

67 def highlight(self, text: Text) -> None: 

68 """Highlight :class:`rich.text.Text` using regular expressions. 

69 

70 Args: 

71 text (~Text): Text to highlighted. 

72 

73 """ 

74 

75 highlight_regex = text.highlight_regex 

76 for re_highlight in self.highlights: 

77 highlight_regex(re_highlight, style_prefix=self.base_style) 

78 

79 

80class ReprHighlighter(RegexHighlighter): 

81 """Highlights the text typically produced from ``__repr__`` methods.""" 

82 

83 base_style = "repr." 

84 highlights = [ 

85 r"(?P<tag_start><)(?P<tag_name>[-\w.:|]*)(?P<tag_contents>[\w\W]*)(?P<tag_end>>)", 

86 r'(?P<attrib_name>[\w_]{1,50})=(?P<attrib_value>"?[\w_]+"?)?', 

87 r"(?P<brace>[][{}()])", 

88 _combine_regex( 

89 r"(?P<ipv4>[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})", 

90 r"(?P<ipv6>([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4})", 

91 r"(?P<eui64>(?:[0-9A-Fa-f]{1,2}-){7}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{1,2}:){7}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{4}\.){3}[0-9A-Fa-f]{4})", 

92 r"(?P<eui48>(?:[0-9A-Fa-f]{1,2}-){5}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{1,2}:){5}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{4}\.){2}[0-9A-Fa-f]{4})", 

93 r"(?P<uuid>[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12})", 

94 r"(?P<call>[\w.]*?)\(", 

95 r"\b(?P<bool_true>True)\b|\b(?P<bool_false>False)\b|\b(?P<none>None)\b", 

96 r"(?P<ellipsis>\.\.\.)", 

97 r"(?P<number_complex>(?<!\w)(?:\-?[0-9]+\.?[0-9]*(?:e[-+]?\d+?)?)(?:[-+](?:[0-9]+\.?[0-9]*(?:e[-+]?\d+)?))?j)", 

98 r"(?P<number>(?<!\w)\-?[0-9]+\.?[0-9]*(e[-+]?\d+?)?\b|0x[0-9a-fA-F]*)", 

99 r"(?P<path>\B(/[-\w._+]+)*\/)(?P<filename>[-\w._+]*)?", 

100 r"(?<![\\\w])(?P<str>b?'''.*?(?<!\\)'''|b?'.*?(?<!\\)'|b?\"\"\".*?(?<!\\)\"\"\"|b?\".*?(?<!\\)\")", 

101 r"(?P<url>(file|https|http|ws|wss)://[-0-9a-zA-Z$_+!`(),.?/;:&=%#]*)", 

102 ), 

103 ] 

104 

105 

106class JSONHighlighter(RegexHighlighter): 

107 """Highlights JSON""" 

108 

109 # Captures the start and end of JSON strings, handling escaped quotes 

110 JSON_STR = r"(?<![\\\w])(?P<str>b?\".*?(?<!\\)\")" 

111 JSON_WHITESPACE = {" ", "\n", "\r", "\t"} 

112 

113 base_style = "json." 

114 highlights = [ 

115 _combine_regex( 

116 r"(?P<brace>[\{\[\(\)\]\}])", 

117 r"\b(?P<bool_true>true)\b|\b(?P<bool_false>false)\b|\b(?P<null>null)\b", 

118 r"(?P<number>(?<!\w)\-?[0-9]+\.?[0-9]*(e[\-\+]?\d+?)?\b|0x[0-9a-fA-F]*)", 

119 JSON_STR, 

120 ), 

121 ] 

122 

123 def highlight(self, text: Text) -> None: 

124 super().highlight(text) 

125 

126 # Additional work to handle highlighting JSON keys 

127 plain = text.plain 

128 append = text.spans.append 

129 whitespace = self.JSON_WHITESPACE 

130 for match in re.finditer(self.JSON_STR, plain): 

131 start, end = match.span() 

132 cursor = end 

133 while cursor < len(plain): 

134 char = plain[cursor] 

135 cursor += 1 

136 if char == ":": 

137 append(Span(start, end, "json.key")) 

138 elif char in whitespace: 

139 continue 

140 break 

141 

142 

143class ISO8601Highlighter(RegexHighlighter): 

144 """Highlights the ISO8601 date time strings. 

145 Regex reference: https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch04s07.html 

146 """ 

147 

148 base_style = "iso8601." 

149 highlights = [ 

150 # 

151 # Dates 

152 # 

153 # Calendar month (e.g. 2008-08). The hyphen is required 

154 r"^(?P<year>[0-9]{4})-(?P<month>1[0-2]|0[1-9])$", 

155 # Calendar date w/o hyphens (e.g. 20080830) 

156 r"^(?P<date>(?P<year>[0-9]{4})(?P<month>1[0-2]|0[1-9])(?P<day>3[01]|0[1-9]|[12][0-9]))$", 

157 # Ordinal date (e.g. 2008-243). The hyphen is optional 

158 r"^(?P<date>(?P<year>[0-9]{4})-?(?P<day>36[0-6]|3[0-5][0-9]|[12][0-9]{2}|0[1-9][0-9]|00[1-9]))$", 

159 # 

160 # Weeks 

161 # 

162 # Week of the year (e.g., 2008-W35). The hyphen is optional 

163 r"^(?P<date>(?P<year>[0-9]{4})-?W(?P<week>5[0-3]|[1-4][0-9]|0[1-9]))$", 

164 # Week date (e.g., 2008-W35-6). The hyphens are optional 

165 r"^(?P<date>(?P<year>[0-9]{4})-?W(?P<week>5[0-3]|[1-4][0-9]|0[1-9])-?(?P<day>[1-7]))$", 

166 # 

167 # Times 

168 # 

169 # Hours and minutes (e.g., 17:21). The colon is optional 

170 r"^(?P<time>(?P<hour>2[0-3]|[01][0-9]):?(?P<minute>[0-5][0-9]))$", 

171 # Hours, minutes, and seconds w/o colons (e.g., 172159) 

172 r"^(?P<time>(?P<hour>2[0-3]|[01][0-9])(?P<minute>[0-5][0-9])(?P<second>[0-5][0-9]))$", 

173 # Time zone designator (e.g., Z, +07 or +07:00). The colons and the minutes are optional 

174 r"^(?P<timezone>(Z|[+-](?:2[0-3]|[01][0-9])(?::?(?:[0-5][0-9]))?))$", 

175 # Hours, minutes, and seconds with time zone designator (e.g., 17:21:59+07:00). 

176 # All the colons are optional. The minutes in the time zone designator are also optional 

177 r"^(?P<time>(?P<hour>2[0-3]|[01][0-9])(?P<minute>[0-5][0-9])(?P<second>[0-5][0-9]))(?P<timezone>Z|[+-](?:2[0-3]|[01][0-9])(?::?(?:[0-5][0-9]))?)$", 

178 # 

179 # Date and Time 

180 # 

181 # Calendar date with hours, minutes, and seconds (e.g., 2008-08-30 17:21:59 or 20080830 172159). 

182 # A space is required between the date and the time. The hyphens and colons are optional. 

183 # This regex matches dates and times that specify some hyphens or colons but omit others. 

184 # This does not follow ISO 8601 

185 r"^(?P<date>(?P<year>[0-9]{4})(?P<hyphen>-)?(?P<month>1[0-2]|0[1-9])(?(hyphen)-)(?P<day>3[01]|0[1-9]|[12][0-9])) (?P<time>(?P<hour>2[0-3]|[01][0-9])(?(hyphen):)(?P<minute>[0-5][0-9])(?(hyphen):)(?P<second>[0-5][0-9]))$", 

186 # 

187 # XML Schema dates and times 

188 # 

189 # Date, with optional time zone (e.g., 2008-08-30 or 2008-08-30+07:00). 

190 # Hyphens are required. This is the XML Schema 'date' type 

191 r"^(?P<date>(?P<year>-?(?:[1-9][0-9]*)?[0-9]{4})-(?P<month>1[0-2]|0[1-9])-(?P<day>3[01]|0[1-9]|[12][0-9]))(?P<timezone>Z|[+-](?:2[0-3]|[01][0-9]):[0-5][0-9])?$", 

192 # Time, with optional fractional seconds and time zone (e.g., 01:45:36 or 01:45:36.123+07:00). 

193 # There is no limit on the number of digits for the fractional seconds. This is the XML Schema 'time' type 

194 r"^(?P<time>(?P<hour>2[0-3]|[01][0-9]):(?P<minute>[0-5][0-9]):(?P<second>[0-5][0-9])(?P<frac>\.[0-9]+)?)(?P<timezone>Z|[+-](?:2[0-3]|[01][0-9]):[0-5][0-9])?$", 

195 # Date and time, with optional fractional seconds and time zone (e.g., 2008-08-30T01:45:36 or 2008-08-30T01:45:36.123Z). 

196 # This is the XML Schema 'dateTime' type 

197 r"^(?P<date>(?P<year>-?(?:[1-9][0-9]*)?[0-9]{4})-(?P<month>1[0-2]|0[1-9])-(?P<day>3[01]|0[1-9]|[12][0-9]))T(?P<time>(?P<hour>2[0-3]|[01][0-9]):(?P<minute>[0-5][0-9]):(?P<second>[0-5][0-9])(?P<ms>\.[0-9]+)?)(?P<timezone>Z|[+-](?:2[0-3]|[01][0-9]):[0-5][0-9])?$", 

198 ] 

199 

200 

201if __name__ == "__main__": # pragma: no cover 

202 from .console import Console 

203 

204 console = Console() 

205 console.print("[bold green]hello world![/bold green]") 

206 console.print("'[bold green]hello world![/bold green]'") 

207 

208 console.print(" /foo") 

209 console.print("/foo/") 

210 console.print("/foo/bar") 

211 console.print("foo/bar/baz") 

212 

213 console.print("/foo/bar/baz?foo=bar+egg&egg=baz") 

214 console.print("/foo/bar/baz/") 

215 console.print("/foo/bar/baz/egg") 

216 console.print("/foo/bar/baz/egg.py") 

217 console.print("/foo/bar/baz/egg.py word") 

218 console.print(" /foo/bar/baz/egg.py word") 

219 console.print("foo /foo/bar/baz/egg.py word") 

220 console.print("foo /foo/bar/ba._++z/egg+.py word") 

221 console.print("https://example.org?foo=bar#header") 

222 

223 console.print(1234567.34) 

224 console.print(1 / 2) 

225 console.print(-1 / 123123123123) 

226 

227 console.print( 

228 "127.0.1.1 bar 192.168.1.4 2001:0db8:85a3:0000:0000:8a2e:0370:7334 foo" 

229 ) 

230 import json 

231 

232 console.print_json(json.dumps(obj={"name": "apple", "count": 1}), indent=None)