Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/mistune/_inline/delimiters.py: 100%

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

55 statements  

1"""Indexes of closing delimiters for one inline source. 

2 

3Each delimiter family scans its source once. These are lexical positions, not 

4memoized parse failures, and are never shared with copied or sliced sources. 

5""" 

6 

7import re 

8from bisect import bisect_left, bisect_right 

9from typing import Dict, List, Optional, Tuple 

10 

11_BACKTICKS = re.compile(r"`+") 

12 

13 

14class DelimiterScanner: 

15 def __init__(self, src: str) -> None: 

16 self.src = src 

17 self._code: Optional[Dict[int, List[int]]] = None 

18 self._ends: Dict[Tuple[str, bool], List[int]] = {} 

19 

20 def code_end(self, marker: str, pos: int) -> Optional[int]: 

21 size = len(marker) 

22 if self._code is None: 

23 end = self.src.find(marker, pos) 

24 if end >= 0 and (end == 0 or self.src[end - 1] != "`"): 

25 after = end + size 

26 if after == len(self.src) or self.src[after] != "`": 

27 return end 

28 self._code = {} 

29 for match in _BACKTICKS.finditer(self.src): 

30 self._code.setdefault(match.end() - match.start(), []).append(match.start()) 

31 positions = self._code.get(size, []) 

32 index = bisect_left(positions, pos) 

33 return positions[index] if index < len(positions) else None 

34 

35 def find(self, marker: str, pos: int, *, formatting: bool = False) -> Optional[int]: 

36 key = (marker, formatting) 

37 positions = self._ends.get(key) 

38 if positions is None: 

39 positions = [] 

40 start = self.src.find(marker) 

41 while start >= 0: 

42 if not formatting or _formatting_closer(self.src, start, marker): 

43 positions.append(start) 

44 start = self.src.find(marker, start + 1) 

45 self._ends[key] = positions 

46 index = bisect_right(positions, pos) if formatting else bisect_left(positions, pos) 

47 return positions[index] if index < len(positions) else None 

48 

49 

50def _formatting_closer(src: str, start: int, marker: str) -> bool: 

51 char = marker[0] 

52 end = start + len(marker) 

53 if end < len(src) and src[end] == char and not src.startswith(marker, end): 

54 return False 

55 if not start: 

56 return False 

57 previous = src[start - 1] 

58 if previous != char: 

59 return not previous.isspace() 

60 # A literal escaped first character can precede a closing pair in a run. 

61 if start < 2 or src[start - 2] != "\\": 

62 return False 

63 backslashes = 0 

64 pos = start - 2 

65 while pos >= 0 and src[pos] == "\\": 

66 backslashes += 1 

67 pos -= 1 

68 return backslashes % 2 == 1