Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/phonenumbers/re_util.py: 53%

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

15 statements  

1"""Additional regular expression utilities, to make it easier to sync up 

2with Java regular expression code. 

3 

4>>> import re 

5>>> from .re_util import fullmatch 

6>>> from .util import u 

7>>> string = 'abcd' 

8>>> r1 = re.compile('abcd') 

9>>> r2 = re.compile('bc') 

10>>> r3 = re.compile('abc') 

11>>> fullmatch(r1, string) # doctest: +ELLIPSIS 

12<...Match object...> 

13>>> fullmatch(r2, string) 

14>>> fullmatch(r3, string) 

15>>> r = re.compile(r'\\d{8}|\\d{10,11}') 

16>>> m = fullmatch(r, '1234567890') 

17>>> m.end() 

1810 

19>>> r = re.compile(u(r'[+\uff0b\\d]'), re.UNICODE) 

20>>> m = fullmatch(r, u('\uff10')) 

21>>> m.end() 

221 

23""" 

24import re 

25import sys 

26 

27if sys.version_info >= (3, 4): # pragma no cover 

28 

29 def fullmatch(pattern, string): 

30 """Try to apply the pattern at the start of the string, returning a match 

31 object if the whole string matches, or None if no match was found.""" 

32 

33 return pattern.fullmatch(string) 

34 

35else: # pragma no cover 

36 

37 def fullmatch(pattern, string): 

38 """Try to apply the pattern at the start of the string, returning a match 

39 object if the whole string matches, or None if no match was found.""" 

40 # Build a version of the pattern with a non-capturing group around it. 

41 # This is needed to get m.end() to correctly report the size of the 

42 # matched expression (as per the final doctest above). 

43 grouped_pattern = re.compile("^(?:%s)$" % pattern.pattern, pattern.flags) 

44 m = grouped_pattern.match(string) 

45 if m and m.end() < len(string): 

46 # Incomplete match (which should never happen because of the $ at the 

47 # end of the regexp), treat as failure. 

48 m = None # pragma no cover 

49 return m 

50 

51 

52# Compiled regular expressions, keyed by pattern string, or None while the 

53# cache is off (the default). The patterns used come from the (fixed) metadata, 

54# so the number of entries is bounded; holding on to them means that 

55# applications which work with numbers from many regions don't keep recompiling 

56# patterns that have dropped out of the re module's own, smaller, cache. 

57_COMPILED_PATTERNS = None 

58 

59 

60def enable_pattern_cache(): 

61 """Keep every compiled metadata regular expression from now on, rather than 

62 relying on the re module's own (bounded) cache.""" 

63 global _COMPILED_PATTERNS 

64 if _COMPILED_PATTERNS is None: 

65 _COMPILED_PATTERNS = {} 

66 

67 

68def re_compile(regex): 

69 """Return a compiled version of the given regular expression string. Once 

70 enable_pattern_cache() has been called, an earlier compilation of the same 

71 string is re-used (as the RegexCache class in the Java code does); 

72 otherwise this is just re.compile.""" 

73 if _COMPILED_PATTERNS is None: 

74 return re.compile(regex) 

75 pattern = _COMPILED_PATTERNS.get(regex, None) 

76 if pattern is None: 

77 pattern = re.compile(regex) 

78 _COMPILED_PATTERNS[regex] = pattern 

79 return pattern 

80 

81 

82if __name__ == '__main__': # pragma no cover 

83 import doctest 

84 doctest.testmod()