
    ThP              
          d Z ddlZddlmZ ddlmZmZmZmZ ddlm	Z	m
Z
mZmZmZmZmZ ddlmZmZmZ ddlmZmZ dd	lmZmZmZ dd
lmZmZ ddlmZmZ ddlmZmZm Z  ddlm!Z!m"Z"m#Z# ddlm$Z$m%Z% ddlm&Z&m'Z' ddlm(Z(m)Z)m*Z* ddlm+Z+ ddlm,Z, ddlm-Z- ddl.m/Z/ ddl0m1Z1 	 ddl2m3Z3 d Z; ed      Z< ed      Z= ed      e<z   e=z    ed      z   Z> e;dd      Z? ej                   ed       e<z    ed!      z    ed"      z   e>z    ed#      z    ed$      z   e=z    ed!      z   e>z    ed#      z    ed       z   e<z    ed      z   e>z    ed%      z   e=z    ed&      z   e?z   e>z    ed'      z         ZA e;dd(      ZB e;dd)      ZCeez   ZD e;deD      ZE ed$      ez    ed      z   eCz   ZF ed*       e;deD      z   ZGe<ez   ZH ed$      eHz    ed      z   ZI ej                  eI      ZJ ej                   ed"      eIz   eFz    ed+      z   eBz   eGz    ed"      z   eFz   eGz    ed+      z   eEz    ed"      z   ez    ed,      z   e      ZK ej                   ed-            ZL ej                   ed.            ZM ej                   ed/            ZN ej                   ed0            ZO ej                   ed1             ej                   ed2             ej                   ed3             ej                   ed4             ej                   ed5             ej                   ed6            fZP G d7 d8eQ      ZRd9 ZSd: ZTd; ZUd< ZVd= ZWd> ZXd? ZYd@ ZZdA Z[dB Z\ G dC dDeQ      Z] G dE dFe      Z^y# e4$ rN ddl5Z5ddl6Z6e5jn                  jq                  e6jr                  d         dv r ede6jt                         i Z3n Y w xY w)Gz7Functionality to match phone numbers in a piece of text    N   )	fullmatch)UnicodeMixinuunicodprnt)U_EMPTY_STRINGU_DASHU_SEMICOLONU_SLASH	U_X_LOWER	U_X_UPPER	U_PERCENT)CategoryBlock	is_letter)_MAX_LENGTH_FOR_NSN_MAX_LENGTH_COUNTRY_CODE)_VALID_PUNCTUATION_PLUS_CHARSNON_DIGITS_PATTERN)_EXTN_PATTERNS_FOR_MATCHING_REGEX_FLAGS)_SECOND_NUMBER_START_PATTERN_UNWANTED_END_CHAR_PATTERN)	MatchTypeNumberParseExceptionPhoneNumberFormat)is_possible_numberis_valid_numberparse)normalize_digits_onlynational_significant_number)_format_nsn_using_patternndd_prefix_for_region)format_numberis_number_matchregion_code_for_country_code))_maybe_strip_national_prefix_carrier_code)%_choose_formatting_pattern_for_number)%_formatting_rule_has_first_group_only)CountryCodeSource)PhoneMetadata)_ALT_NUMBER_FORMATS)zbuildmetadatafromxml.pyzbuildprefixdata.pyzAFailed to import generated data (but OK as during autogeneration))filec                 V    | dk  s
|dk  s|| k  rt        d      t        d      | |fz  S )zFReturns a regular expression quantifier with an upper and lower limit.r   zIllegal argument to _limitz{%d,%d})	Exceptionr   )loweruppers     _/opt/server/standalone/crm/venv/lib/python3.12/site-packages/phonenumbers/phonenumbermatcher.py_limitr5   9   s5    	
455)u~--    u	   (\[（［u	   )\]）］z[^]   z(?:[z])?z(?:+[z+[z])*      z\d)z)?z \d{1,5}-+\d{1,5}\s{0,4}\(\d{1,4}z>(?:(?:[0-3]?\d/[01]?\d)|(?:[01]?\d/[0-3]?\d))/(?:[12]\d)?\d{2}z*[12]\d{3}[-/]?[01]\d[-/]?[0-3]\d +[0-2]\d$z:[0-5]\dz/+(.*)z	(\([^(]*)z(?u)(?:\s-|-\s)\s*(.+)u   (?u)[‒-―－]\s*(.+)z(?u)\.+\s*([^.]+)z(?u)\s+(\S+)c                        e Zd ZdZdZdZdZdZy)LeniencyzzLeniency when finding potential phone numbers in text segments.

    The levels here are ordered in increasing strictness.r   r   r<   r8   N)__name__
__module____qualname____doc__POSSIBLEVALIDSTRICT_GROUPINGEXACT_GROUPING r6   r4   r@   r@      s#    =
 H
 E O Nr6   r@   c                 F   | t         j                  k(  rt        |      S | t         j                  k(  r#t	        |      rt        ||      syt        |      S | t         j                  k(  rt        |||      S | t         j                  k(  rt        |||      S t        d| z        )zJReturns True if number is a verified number according to the
    leniency.Fz$Error: unsupported Leniency value %s)r@   rE   r   rF   r    _contains_only_valid_x_chars'_is_national_prefix_present_if_requiredrG   _verify_strict_groupingrH   _verify_exact_groupingr1   )leniencynumobj	candidatematchers       r4   _verifyrS      s     8$$$!&))	X^^	#',VY?6v>>	X--	-&vy'BB	X,,	,%fiAA>IJJr6   c                     t        |       r#t        | |      rt        | |      st        |       sy|j	                  | |t
              S NF)r    rK   0_contains_more_than_one_slash_in_national_numberrL   _check_number_grouping_is_valid!_all_number_groups_remain_groupedrP   rQ   rR   s      r4   rM   rM      sE    F#(;8K3F;22693TV Vr6   c                 X   d}| j                   t        j                  k7  r2t        | j                        }|j                  |      t        |      z   }t        |      D ]  \  }}|j                  ||      }|dk  r y|t        |      z  }|dk(  s3|t        |      k  sBt        | j                        }t        |d      d||   j                         sxt        |       }||t        |      z
  d j                  |      c S  ||d j                  | j                  xs t              dk7  S )  Returns True if the groups of digits found in our candidate phone number match our
    expectations.

    Arguments:
    numobj -- the original number we found when parsing
    normalized_candidate -- the candidate number, normalized to only contain ASCII digits,
          but with non-digits (spaces etc) retained
    expected_number_groups -- the groups of digits that we would expect to see if we
          formatted this number
    Returns True if expectations matched.
    r   FTN)country_code_sourcer,   FROM_DEFAULT_COUNTRYstrcountry_codefindlen	enumerater(   r%   isdigitr#   
startswith	extensionr	   )	rP   normalized_candidateformatted_number_groups
from_indexr`   iiformatted_number_groupregionnsns	            r4   rX   rX      s6    J!!%6%K%KK6../)..|<s<?PP
 '00G&H i"" *../EzR
>c011
!G
S)=%>> 2&2E2EFF%fd3?$Z088: 2&9+Z#>T:U-U,WXccdghh1i8 !-2263C3C3U~VZ\\]r6   c                     t        |       r#t        | |      rt        | |      st        |       sy|j	                  | |t
              S rU   )r    rK   rV   rL   rW   &_all_number_groups_are_exactly_presentrY   s      r4   rN   rN     sE    F#(;8K3F;22693Y[ [r6   c                    t        j                  t        |      }| j                  t	        |      dz
  }nt	        |      dz
  }t	        |      dk(  s ||   j                  t        |             dk7  ryt	        |      dz
  }|dkD  r&|dk\  r!||   ||   k7  ry|dz  }|dz  }|dkD  r|dk\  r!|dk\  xr ||   j                  |d         S )r[   r<   r   r\   Tr   F)resplitr   rf   rb   ra   r#   endswith)rP   rg   rh   candidate_groupscandidate_number_group_indexformatted_number_group_indexs         r4   ro   ro   )  s    xx 24HI#'*+;'<q'@$'*+;'<q'@$
 	"56;;<WX^<_`dff $''>#?!#C '!+0LPQ0Q9:#$@AB$)$$)$ (!+0LPQ0Q )A- `9:CCD[\]D^_ar6   c                     t        | t        j                        }|j                  t              }|dk  rt        |      }|j                  t              dz   }||| j                  t              S )zHelper method to get the national-number part of a number, formatted without any national
    prefix, and return it as a set of digit blocks that would be formatted together following
    standard formatting rules.r   r   )r&   r   RFC3966ra   r   rb   r
   rr   )rP   rfc3966_format	end_indexstart_indexs       r4   +_get_national_number_groups_without_patternr|   Q  si     #6+<+D+DEN ##K0I1}'	 !%%f-1K+i066v>>r6   c                 t    t        |       }t        ||t        j                        j	                  t
              S )zHelper method to get the national-number part of a number, formatted without any national
    prefix, and return it as a set of digit blocks that should be formatted together according to
    the formatting pattern passed in.)r#   r$   r   rx   rr   r
   )rP   formatting_patternrm   s      r4   _get_national_number_groupsr   c  s4    
 &f
-C$S*<%6%>%>@@EfNr6   c                 x   |j                  t              }|dk  ry|j                  t        |dz         }|dk  ry| j                  t        j                  k(  xs | j                  t        j
                  k(  }|rBt        |d |       t        | j                        k(  r||dz   d  j                  t              dk7  S y)Nr   Fr   r\   T)	ra   r   r]   r,   FROM_NUMBER_WITH_PLUS_SIGNFROM_NUMBER_WITHOUT_PLUS_SIGNr"   r   r`   )rP   rQ   first_slash_in_body_indexsecond_slash_in_body_indexcandidate_has_country_codes        r4   rV   rV   m  s     )w 7 1$!*9RUV9V!W!A% #)"<"<@Q@l@l"l #p"("<"<@Q@o@o"o "i(B)BCDv""#	$ 59;<AA'JbPQr6   c                 @   d}|t        |      dz
  k  r||   t        k(  s||   t        k(  r\||dz      }|t        k(  s	|t        k(  r&|dz  }t        | ||d        t        j
                  k7  ryt        ||d        | j                  k7  ry|dz  }|t        |      dz
  k  ry)Nr   r   FT)rb   r   r   r'   r   	NSN_MATCHr"   rf   )rP   rQ   rj   	next_chars       r4   rK   rK     s     
B
I"
#bMY&)B-9*D!"q&)IY&)y*@ a"69RS>:i>Q>QQ  'y~6&:J:JJ
a I"
# r6   c                    | j                   t        j                  k7  ryt        | j                        }t        j                  |d       }|yt        |       }t        |j                  |      }|S|j                  rG|j                  ryt        |j                        ryt        | j                        }t        ||      d   S y)NTr<   )r]   r,   r^   r(   r`   r-   metadata_for_regionr#   r*   number_formatnational_prefix_formatting_rule(national_prefix_optional_when_formattingr+   r"   	raw_inputr)   )rP   phone_number_regionmetadatanational_numberformat_ruler   s         r4   rL   rL     s     !!%6%K%KK6v7J7JK001DdKH1&9O78N8N8GIK 	33?? 01\1\])&*:*:;	 9HMaPPr6   c                       e Zd ZdZdZdZdZej                  dfdZ	d Z
d Zed	        Zed
        Zd Zd Zd Zd Zd Zd Zd Zy)PhoneNumberMatcherzA stateful class that finds and extracts telephone numbers from text.

    Vanity numbers (phone numbers using alphabetic digits such as '1-800-SIX-FLAGS' are
    not found.

    This class is not thread-safe.
    r   r   r<   i  c                    |t        d      t        |      dk  rt        d      || _        | j                  t        | _        || _        || _        t        |      | _        t        j                  | _	        d| _
        d| _        y)a  Creates a new instance.

        Arguments:
        text -- The character sequence that we will search, None for no text.
        country -- The country to assume for phone numbers not written in
              international format (with a leading plus, or with the
              international dialing prefix of the specified region). May be
              None or "ZZ" if only numbers with a leading plus should be
              considered.
        leniency -- The leniency to use when evaluating candidate phone
              numbers.
        max_tries -- The maximum number of invalid numbers to try before
              giving up on the text.  This is to cover degenerate cases where
              the text has a lot of false positives in it. Must be >= 0.
        NzNeed a leniency valuer   z!Need max_tries to be positive int)
ValueErrorinttextr	   preferred_regionrO   
_max_triesr   
_NOT_READY_state_last_match_search_index)selfr   rl   rO   	max_triess        r4   __init__zPhoneNumberMatcher.__init__  s    " 455y>A@AA	99&DI !' i.(33r6   c                    t         j                  | j                  |      }| j                  dkD  r||j	                         }| j                  ||j                          }| j                  t        |      }| j                  ||      }||S |t        |      z   }| xj                  dz  c_        t         j                  | j                  |      }| j                  dkD  r|y)aG  Attempts to find the next subsequence in the searched sequence on or after index
        that represents a phone number. Returns the next match, None if none was found.

        Arguments:
        index -- The search index to start searching at.
        Returns the phone number match found, None if none can be found.
        r   Nr   )
_PATTERNsearchr   r   startend_trim_after_first_matchr   _extract_matchrb   )r   indexmatchr   rQ   s        r4   _findzPhoneNumberMatcher._find  s     		51oo!e&7KKME		%		4I 445Q5>@I ''	59E C	N*EOOq OOODIIu5E# oo!e&7$ r6   c                 R    |j                  |      }|r|d|j                          }|S )zoTrims away any characters after the first match of pattern in
        candidate, returning the trimmed version.N)r   r   )r   patternrQ   trailing_chars_matchs       r4   r   z*PhoneNumberMatcher._trim_after_first_match  s3      '~~i8!"?#7#=#=#?@Ir6   c                    t        |      s't        j                  |      t        j                  k7  ryt	        j                  |      }|t        j
                  k(  xsg |t        j                  k(  xsR |t        j                  k(  xs= |t        j                  k(  xs( |t        j                  k(  xs |t        j                  k(  S )zHelper method to determine if a character is a Latin-script letter
        or not. For our purposes, combining marks should also return True
        since we assume they have been added to a preceding Latin character.F)r   r   getNON_SPACING_MARKr   BASIC_LATINLATIN_1_SUPPLEMENTLATIN_EXTENDED_ALATIN_EXTENDED_ADDITIONALLATIN_EXTENDED_BCOMBINING_DIACRITICAL_MARKS)clsletterblocks      r4   _is_latin_letterz#PhoneNumberMatcher._is_latin_letter  s     &!LL H$=$==		&!*** ;111;///; 888; ///	;
 :::	<r6   c                 d    |t         k(  xs& t        j                  |      t        j                  k(  S N)r   r   r   CURRENCY_SYMBOL)r   	characters     r4   _is_invalid_punctuation_symbolz1PhoneNumberMatcher._is_invalid_punctuation_symbol'  s-    Y& DY'8+C+CC	Er6   c                 
   t         j                  |      ryt        j                  |      r1| j                  |t	        |      z   d }t
        j                  |      ry| j                  ||      }||S | j                  ||      S )a  Attempts to extract a match from a candidate string.

        Arguments:
        candidate -- The candidate text that might contain a phone number.
        offset -- The offset of candidate within self.text
        Returns the match found, None if none can be found
        N)	_SLASH_SEPARATED_DATESr   _TIME_STAMPSr   rb   _TIME_STAMPS_SUFFIXr   _parse_and_verify_extract_inner_match)r   rQ   offsetfollowing_textr   s        r4   r   z!PhoneNumberMatcher._extract_match,  s     #)))4 y)!YYvI'>'?@N"((8 &&y&9L ((F;;r6   c                 P   t         D ]  }|j                  |      }d}|s| j                  dkD  s*|rV| j                  t        |d|j                                }| j                  ||      }||c S | xj                  dz  c_        d}| j                  t        |j                  d            }| j                  |||j                  d      z         }||c S | xj                  dz  c_        |j                  ||j                         dz         }|s| j                  dkD  r y)aF  Attempts to extract a match from candidate if the whole candidate
        does not qualify as a match.

        Arguments:
        candidate -- The candidate text that might contain a phone number
        offset -- The current offset of candidate within text
        Returns the match found, None if none can be found
        Tr   Nr   F)_INNER_MATCHESr   r   r   r   r   r   group)r   rQ   r   possible_inner_matchgroup_matchis_first_matchr   r   s           r4   r   z'PhoneNumberMatcher._extract_inner_matchH  s(    %3 	^ .55i@K!N$//A"5! 889S9BCWKDUDUDW9XZE 225&AE($OOq(O%*N445O5@5F5Fq5IK..uf{?P?PQR?S6ST$ L1$299)[EVEVEX[\E\]! $//A"5	^( r6   c                    	 t        t        |      rt        j                  |      ry| j                  t
        j                  k\  r|dkD  rJt        j                  |      s5| j                  |dz
     }| j                  |      s| j                  |      ry|t        |      z   }|t        | j                        k  r2| j                  |   }| j                  |      s| j                  |      ryt        || j                  d      }t        | j                  |||       r0t         j"                  |_        d|_        d|_        t+        |||      S 	 y# t,        $ r Y yw xY w)a  Parses a phone number from the candidate using phonenumberutil.parse and
        verifies it matches the requested leniency. If parsing and verification succeed, a
        corresponding PhoneNumberMatch is returned, otherwise this method returns None.

        Arguments:
        candidate -- The candidate match.
        offset -- The offset of candidate within self.text.
        Returns the parsed and validated phone number match, or None.
        Nr   r   T)keep_raw_input)r   _MATCHING_BRACKETS
_PUB_PAGESr   rO   r@   rF   _LEAD_PATTERNr   r   r   r   rb   r!   r   rS   r,   UNSPECIFIEDr]   r   preferred_domestic_carrier_codePhoneNumberMatchr   )r   rQ   r   previous_charlast_char_indexr   rP   s          r4   r   z$PhoneNumberMatcher._parse_and_verifyg  sB   )	 0)<
@Q@QR[@\
 }}. QJ%++I6$(IIfqj$9M ;;MJ--m<#"(3y>"9"S^3 $		/ :I;;IF--i8#9d&;&;DQFt}}fi> .?-J-J*#' 9=6'	6BB ?  $ 		s%   %E A+E AE ,AE 	EEc                 x   t        |d      }t        |      } ||||      ryt        j                  |j                  d       }t        |      }|k|D ]f  }t        |j                        dkD  r4t        j                  |j                  d         }	|	j                  |      sOt        ||      } ||||      sf y y)NTr   F)r"   r|   r.   r   r`   r#   rb   leading_digits_patternrq   compiler   r   )
r   rP   rQ   checkerrg   rh   alternate_formatsrm   alternate_formatr   s
             r4   rW   z2PhoneNumberMatcher._check_number_grouping_is_valid  s    4YE"Mf"U6/1HI/33F4G4GN)&1($5 	  '>>?!C jj)9)P)PQR)STG"==- *EfN^*_'6#79PQ	  r6   c                 Z   | j                   t        j                  k(  rr| j                  | j                        | _        | j
                  t        j                  | _         n0| j
                  j                  | _        t        j                  | _         | j                   t        j                  k(  S )z2Indicates whether there is another match available)	r   r   r   r   r   r   _DONEr   _READYr   s    r4   has_nextzPhoneNumberMatcher.has_next  s|    ;;,777#zz$*<*<=D'066%)%5%5%9%9"07718889r6   c                     | j                         st        d      | j                  }d| _        t        j                  | _        |S )zBReturn the next match; raises Exception if no next match availablezNo next matchN)r   StopIterationr   r   r   r   )r   results     r4   nextzPhoneNumberMatcher.next  s=     }}00!!(33r6   c              #   t   K   | j                         r$| j                          | j                         r#y y wr   )r   r   r   s    r4   __iter__zPhoneNumberMatcher.__iter__  s&     mmo))+ mmos   388N)rA   rB   rC   rD   r   r   r   r@   rF   r   r   r   classmethodr   r   r   r   r   rW   r   r   r   rI   r6   r4   r   r     s     JFE #..E%N: < <  E E<8>4l*	:	r6   r   c                   .    e Zd ZdZd Zd Zd Zd Zd Zy)r   a7  The immutable match of a phone number within a piece of text.

    Matches may be found using the find() method of PhoneNumberMatcher.

    A match consists of the phone number (in .number) as well as the .start
    and .end offsets of the corresponding subsequence of the searched
    text. Use .raw_string to obtain a copy of the matched subsequence.

    The following annotated example clarifies the relationship between the
    searched text, the match offsets, and the parsed number:

    >>> text = "Call me at +1 425 882-8080 for details."
    >>> country = "US"
    >>> import phonenumbers
    >>> matcher = phonenumbers.PhoneNumberMatcher(text, country)
    >>> matcher.has_next()
    True
    >>> m = matcher.next()  # Find the first phone number match
    >>> m.raw_string # contains the phone number as it appears in the text.
    "+1 425 882-8080"
    >>> (m.start, m.end)  # define the range of the matched subsequence.
    (11, 26)
    >>> text[m.start, m.end]
    "+1 425 882-8080"
    >>> phonenumberutil.parse("+1 425 882-8080", "US") == m.number
    True
    c                     |dk  rt        d      ||t        d      || _        || _        | j                  t        |      z   | _        || _        y )Nr   zStart index not >= 0zInvalid argument)r1   r   
raw_stringrb   r   number)r   r   r   rP   s       r4   r   zPhoneNumberMatch.__init__  sT    19233.//
$::J/r6   c                     t        |t              sy| j                  |j                  k(  xrO | j                  |j                  k(  xr4 | j                  |j                  k(  xr | j
                  |j
                  k(  S rU   )
isinstancer   r   r   r   r   r   others     r4   __eq__zPhoneNumberMatch.__eq__  sh    %!12

ekk) ,5#3#33,EII%, u||+	-r6   c                 &    | j                  |       S r   )r   r   s     r4   __ne__zPhoneNumberMatch.__ne__  s    ;;u%%%r6   c                 `    t        d      | j                  | j                  | j                  fz  S )Nz4PhoneNumberMatch(start=%r, raw_string=%r, numobj=%r))r   r   r   r   r   s    r4   __repr__zPhoneNumberMatch.__repr__  s/    MN 	r6   c                 `    t        d      | j                  | j                  | j                  fz  S )NzPhoneNumberMatch [%s,%s) %s)r   r   r   r   r   s    r4   __unicode__zPhoneNumberMatch.__unicode__  s&    34

DHHdoo7^^^r6   N)	rA   rB   rC   rD   r   r   r   r   r   rI   r6   r4   r   r     s!    6-&_r6   r   )_rD   rq   re_utilr   utilr   r   r   r   r	   r
   r   r   r   r   r   unicode_utilr   r   r   phonenumberutilr   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   phonenumberr,   phonemetadatar-   datar.   ImportErrorossyspathbasenameargvstderrr5   _OPENING_PARENS_CLOSING_PARENS_NON_PARENS_BRACKET_PAIR_LIMITr   r   _LEAD_LIMIT_PUNCTUATION_LIMIT_DIGIT_BLOCK_LIMIT_BLOCK_LIMIT_PUNCTUATION_DIGIT_SEQUENCE_LEAD_CLASS_CHARS_LEAD_CLASSr   r   r   r   r   r   r   objectr@   rS   rM   rX   rN   ro   r|   r   rV   rK   rL   r   r   rI   r6   r4   <module>r     su   =$ 
  / / _ _ _ 4 4 J P P F U O O G G O M Y Y F B B * (). &'&'g'/9AcFBQl   RZZ&	O ;ah F5 QT_ _bcdgbh h !#!')8!9;<U8!D +!,./f!5 !"&	!* -<!< ?@f!E HS!S !"$	!( +:	!: =>dG	!D GZ	!Z
 !,!,
 /0f!5 6  QlAq\  *,DD  a+, v**QsV36HHE(VA'9::#k1 f((1S61

;' 2::ah,|;afD{R%&()%13?@BQRTUVYTZ[]ijh!<=?@wG #$ RZZABC
 $A&l$mn  rzz!LMN bjj;0  BJJq{ BJJq BJJq,-.
 BJJq456BJJq&'(BJJq!"#'%,"v "JK$V/^d[%aP?$N,4@M M`;_| ;_C  
 	ww$(YYPWZWaWab  	
s   $M1 1AOO