o
    iP                  	   @   s>  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 zddl2m3Z3 W n' e4y   ddl5Z5ddl6Z6e5j78e6j9d dv rede6j:d i Z3n Y nw dd Z;edZ<edZ=ede< e= ed Z>e;dd Z?e@ed!e< ed" ed# e> ed$ ed% e= ed" e> ed$ ed! e< ed e> ed& e= ed' e? e> ed( ZAe;dd)ZBe;dd*ZCee ZDe;deDZEed%e ed eC ZFed+e;deD ZGe<e ZHed%eH ed ZIe@eIZJe@ed#eI eF ed, eB eG ed# eF eG ed, eE ed# e ed- eZKe@ed.ZLe@ed/ZMe@ed0ZNe@ed1ZOe@ed2e@ed3e@ed4e@ed5e@ed6e@ed7fZPG d8d9 d9eQZRd:d; ZSd<d= ZTd>d? ZUd@dA ZVdBdC ZWdDdE ZXdFdG ZYdHdI ZZdJdK Z[dLdM Z\G dNdO dOeQZ]G dPdQ dQeZ^dS )Rz7Functionality 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                 C   s0   | dk s|dks|| k rt dtd| |f S )zFReturns a regular expression quantifier with an upper and lower limit.r   zIllegal argument to _limitz{%d,%d})	Exceptionr   )lowerupper r2   /var/www/snowflake_co_dev_github/snow_flake_back_end_deploy/env/lib/python3.10/site-packages/phonenumbers/phonenumbermatcher.py_limit9   s   r4   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                   @   s    e Zd ZdZdZdZdZdZdS )LeniencyzzLeniency when finding potential phone numbers in text segments.

    The levels here are ordered in increasing strictness.r   r   r:   r6   N)__name__
__module____qualname____doc__POSSIBLEVALIDSTRICT_GROUPINGEXACT_GROUPINGr2   r2   r2   r3   r=      s    
r=   c                 C   sr   | t jkr	t|S | t jkrt|rt||sdS t|S | t jkr(t|||S | t j	kr3t
|||S td|  )zJReturns True if number is a verified number according to the
    leniency.Fz$Error: unsupported Leniency value %s)r=   rB   r   rC   r   _contains_only_valid_x_chars'_is_national_prefix_present_if_requiredrD   _verify_strict_groupingrE   _verify_exact_groupingr/   )leniencynumobj	candidatematcherr2   r2   r3   _verify   s   



rN   c                 C   6   t | rt| |rt| |st| sdS || |tS NF)r   rF   0_contains_more_than_one_slash_in_national_numberrG   _check_number_grouping_is_valid!_all_number_groups_remain_groupedrK   rL   rM   r2   r2   r3   rH         rH   c           	      C   s   d}| j tjkrt| j}||t| }t|D ]F\}}|||}|dk r+ dS |t|7 }|dkr`|t|k r`t| j}t	|ddur`|| 
 r`t| }||t| d |  S q||d | jpktdk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   )	rK   normalized_candidateformatted_number_groups
from_indexr[   iiformatted_number_groupregionnsnr2   r2   r3   rS      s$   


rS   c                 C   rO   rP   )r   rF   rQ   rG   rR   &_all_number_groups_are_exactly_presentrT   r2   r2   r3   rI     rU   rI   c                 C   s   t t|}| jdurt|d }nt|d }t|dks)|| t| dkr+dS t|d }|dkrS|dkrS|| || krCdS |d8 }|d8 }|dkrS|dks9|dko_|| |d S )rV   Nr:   r   rW   Tr   F)resplitr   ra   r]   r\   r"   endswith)rK   rb   rc   candidate_groupscandidate_number_group_indexformatted_number_group_indexr2   r2   r3   ri   )  s&   
ri   c                 C   sF   t | tj}|t}|dk rt|}|td }||| 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   RFC3966r\   r
   r]   r	   rk   )rK   rfc3966_format	end_indexstart_indexr2   r2   r3   +_get_national_number_groups_without_patternQ  s   
rt   c                 C   s   t | }t||t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   rp   rk   r	   )rK   formatting_patternrh   r2   r2   r3   _get_national_number_groupsc  s   rv   c                 C   s   | t}|dk rdS | t|d }|dk rdS | jtjkp$| jtjk}|rAt|d | t| jkrA||d d   tdkS dS )Nr   Fr   rW   T)	r\   r   rX   r+   FROM_NUMBER_WITH_PLUS_SIGNFROM_NUMBER_WITHOUT_PLUS_SIGNr!   r   r[   )rK   rL   first_slash_in_body_indexsecond_slash_in_body_indexcandidate_has_country_coder2   r2   r3   rQ   m  s   

rQ   c                 C   s   d}|t |d k rP|| tks|| tkrD||d  }|tks$|tkr7|d7 }t| ||d  tjkr6dS nt||d  | jkrDdS |d7 }|t |d k s
dS )Nr   r   FT)r]   r   r   r&   r   	NSN_MATCHr!   ra   )rK   rL   re   	next_charr2   r2   r3   rF     s   rF   c                 C   s   | j tjkrdS t| j}t|d }|d u rdS t| }t|j	|}|d urB|j
rB|jr/dS t|j
r6dS t| j}t||d S dS )NTr:   )rX   r+   rY   r'   r[   r,   metadata_for_regionr"   r)   number_formatnational_prefix_formatting_rule(national_prefix_optional_when_formattingr*   r!   	raw_inputr(   )rK   phone_number_regionmetadatanational_numberformat_ruler   r2   r2   r3   rG     s(   


rG   c                   @   s   e Zd ZdZdZdZdZejdfddZ	dd	 Z
d
d Zedd Zedd Zdd Zdd Zdd Zdd Zdd Zdd Zdd ZdS )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                 C   sh   |du rt dt|dk rt d|| _| jdu rt| _|| _|| _t|| _tj| _	d| _
d| _dS )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_regionrJ   
_max_triesr   
_NOT_READY_state_last_match_search_index)selfr   rg   rJ   	max_triesr2   r2   r3   __init__  s   


zPhoneNumberMatcher.__init__c                 C   s   t | j|}| jdkrL|durL| }| j||  }| t|}| ||}|dur/|S |t	| }|  jd8  _t | j|}| jdkrL|dusdS )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_matchr]   )r   indexmatchr   rL   r2   r2   r3   _find  s   zPhoneNumberMatcher._findc                 C   s"   | |}|r|d|  }|S )zoTrims away any characters after the first match of pattern in
        candidate, returning the trimmed version.N)r   r   )r   patternrL   trailing_chars_matchr2   r2   r3   r     s   
z*PhoneNumberMatcher._trim_after_first_matchc                 C   sb   t |st|tjkrdS t|}|tjkp0|tjkp0|tjkp0|tjkp0|tj	kp0|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blockr2   r2   r3   _is_latin_letter  s   

z#PhoneNumberMatcher._is_latin_letterc                 C   s   |t kpt|tjkS N)r   r   r   CURRENCY_SYMBOL)r   	characterr2   r2   r3   _is_invalid_punctuation_symbol'  s   z1PhoneNumberMatcher._is_invalid_punctuation_symbolc                 C   s`   t |rdS t|r| j|t| d }t|rdS | ||}|dur*|S | ||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   r]   _TIME_STAMPS_SUFFIXr   _parse_and_verify_extract_inner_match)r   rL   offsetfollowing_textr   r2   r2   r3   r   ,  s   



z!PhoneNumberMatcher._extract_matchc                 C   s   t D ]i}||}d}|rk| jdkrk|r7| t|d|  }| ||}|dur.|  S |  jd8  _d}| t|d}| |||d }|durS|  S |  jd8  _||| d }|rk| jdksqdS )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   rL   r   possible_inner_matchgroup_matchis_first_matchr   r   r2   r2   r3   r   H  s0   	
z'PhoneNumberMatcher._extract_inner_matchc                 C   s   zst t|rt|rW dS | jtjkrP|dkr1t|s1| j	|d  }| 
|s.| |r1W dS |t| }|t| j	k rP| j	| }| 
|sM| |rPW dS t|| jdd}t| j||| rqtj|_d|_d|_t|||W S W dS  ty}   Y dS 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   rJ   r=   rC   _LEAD_PATTERNr   r   r   r   r]   r    r   rN   r+   UNSPECIFIEDrX   r   preferred_domestic_carrier_codePhoneNumberMatchr   )r   rL   r   previous_charlast_char_indexr}   rK   r2   r2   r3   r   g  s>   



z$PhoneNumberMatcher._parse_and_verifyc           
      C   s   t |d}t|}||||rdS t|jd }t|}|d urH|D ]%}t|jdkr9t	|jd }	|	
|s9q"t||}||||rG dS q"dS )NTr   F)r!   rt   r-   r   r[   r"   r]   leading_digits_patternrj   compiler   rv   )
r   rK   rL   checkerrb   rc   alternate_formatsrh   alternate_formatr   r2   r2   r3   rR     s"   


z2PhoneNumberMatcher._check_number_grouping_is_validc                 C   sL   | j tjkr | | j| _| jdu rtj| _ n	| jj| _tj| _ | j tjkS )z2Indicates whether there is another match availableN)	r   r   r   r   r   r   _DONEr   _READYr   r2   r2   r3   has_next  s   


zPhoneNumberMatcher.has_nextc                 C   s(   |   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   resultr2   r2   r3   next  s   zPhoneNumberMatcher.nextc                 c   s$    |   r|  V  |   sd S d S r   )r   r   r   r2   r2   r3   __iter__  s   
zPhoneNumberMatcher.__iter__N)r>   r?   r@   rA   r   r   r   r=   rC   r   r   r   classmethodr   r   r   r   r   rR   r   r   r   r2   r2   r2   r3   r     s(    
'

6r   c                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )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                 C   sN   |dk rt d|d u s|d u rt d|| _|| _| jt| | _|| _d S )Nr   zStart index not >= 0zInvalid argument)r/   r   
raw_stringr]   r   number)r   r   r   rK   r2   r2   r3   r     s   
zPhoneNumberMatch.__init__c                 C   s>   t |tsdS | j|jko| j|jko| j|jko| j|jkS rP   )
isinstancer   r   r   r   r   r   otherr2   r2   r3   __eq__  s   



zPhoneNumberMatch.__eq__c                 C   s   |  | S r   )r   r   r2   r2   r3   __ne__  s   zPhoneNumberMatch.__ne__c                 C      t d| j| j| jf S )Nz4PhoneNumberMatch(start=%r, raw_string=%r, numobj=%r))r   r   r   r   r   r2   r2   r3   __repr__  s   zPhoneNumberMatch.__repr__c                 C   r   )NzPhoneNumberMatch [%s,%s) %s)r   r   r   r   r   r2   r2   r3   __unicode__  s   zPhoneNumberMatch.__unicode__N)	r>   r?   r@   rA   r   r   r   r   r   r2   r2   r2   r3   r     s    r   )_rA   rj   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stderrr4   _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=   rN   rH   rS   rI   ri   rt   rv   rQ   rF   rG   r   r   r2   r2   r2   r3   <module>   s    $	
*





%
2
(
   