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
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
1"""Additional regular expression utilities, to make it easier to sync up
2with Java regular expression code.
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
27if sys.version_info >= (3, 4): # pragma no cover
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."""
33 return pattern.fullmatch(string)
35else: # pragma no cover
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
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
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 = {}
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
82if __name__ == '__main__': # pragma no cover
83 import doctest
84 doctest.testmod()