
    E6iG                        d Z ddlZddlZddlmZmZmZ ddlmZmZ ddl	m
Z
 ddlZddlZ edddej                        Z edddd	ej                        Z ej                   d
ej"                        Z ej                   dej"                        Z ej                   d      Zd Zddde_        d Zddde_        d Zddde_         G d de      Z eddddd      Z G d de      Z G d de      Zd Zd Zd  Z d4d!Z!dd"de!_        d# Z"dd$de"_        d% Z#d4d&Z$d'dd(e$_        d4d)Z%d'ddd*e%_         G d+ d,e      Z&d- Z'd.d/ie'_        d0 Z(d1 Z)dd2de)_        d3 Z*dd$de*_        y)5a  
This module provide some helpers for advanced types parsing.

You can define you own parser using the same pattern:

.. code-block:: python

    def my_type(value):
        if not condition:
            raise ValueError('This is not my type')
        return parse(value)

    # Swagger documentation
    my_type.__schema__ = {'type': 'string', 'format': 'my-custom-format'}

The last line allows you to document properly the type in the Swagger documentation.
    N)datetimetime	timedelta)parsedate_tz	mktime_tz)urlparsetzinfo   ;   i?B a  (?:(?P<auth>[^:@]+?(?::[^:@]*?)?)@)?(?:(?P<localhost>localhost)|(?P<ipv4>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|(?:\[?(?P<ipv6>[A-F0-9]*:[A-F0-9:]+)\]?)|(?P<domain>(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)))(?::(?P<port>\d+))?$z9^(?P<local>[^@]*[^@.])@(?P<server>[^@\.]+(?:\.[^@\.]+)*)$z\d{2}:\d{2}c                     	 t        j                  |        | j                  d      dk(  r| S 	 t	        dj                  |             # t         j                  $ r Y /w xY w)zValidate an IPv4 address.   {0} is not a valid ipv4 address)socket	inet_atoncounterror
ValueErrorformatvalues    U/home/azureuser/techstart-app/venv/lib/python3.12/site-packages/flask_restx/inputs.pyipv4r   8   sa    ;;sq L ! 6==eD
EE << s   *A AAstringr   typer   c                     	 t        j                  t         j                  |        | S # t         j                  $ r t	        dj                  |             w xY w)zValidate an IPv6 addressr   )r   	inet_ptonAF_INET6r   r   r   r   s    r   ipv6r!   F   sM    J%0<< J:AA%HIIJs	   %( .Ar!   c                     	 t        |       S # t        $ r Y nw xY w	 t        |       S # t        $ r t        dj                  |             w xY w)z+Validate an IP address (both IPv4 and IPv6)z{0} is not a valid ip)r   r   r!   r   r   s    r   ipr#   R   s[    E{ @E{ @077>??@s   
 	
( $Ar#   c                   F    e Zd ZdZ	 	 	 	 	 	 	 	 ddZddZd Zed        Zy)	URLaP  
    Validate an URL.

    Example::

        parser = reqparse.RequestParser()
        parser.add_argument('url', type=inputs.URL(schemes=['http', 'https']))

    Input to the ``URL`` argument will be rejected
    if it does not match an URL with specified constraints.
    If ``check`` is True it will also be rejected if the domain does not exists.

    :param bool check: Check the domain exists (perform a DNS resolution)
    :param bool ip: Allow IP (both ipv4/ipv6) as domain
    :param bool local: Allow localhost (both string or ip) as domain
    :param bool port: Allow a port to be present
    :param bool auth: Allow authentication to be present
    :param list|tuple schemes: Restrict valid schemes to this list
    :param list|tuple domains: Restrict valid domains to this list
    :param list|tuple exclude: Exclude some domains
    Nc	                 t    || _         || _        || _        || _        || _        || _        || _        || _        y N)checkr#   localportauthschemesdomainsexclude)	selfr(   r#   r)   r*   r+   r,   r-   r.   s	            r   __init__zURL.__init__x   s<     

		    c                 d    d}|rdj                  ||f      }t        |j                  |            )Nz{0} is not a valid URLz. )joinr   r   )r/   r   detailsmsgs       r   r   z	URL.error   s0    &))S'N+CE*++r1   c                    t        |      }t        j                  |j                        }t	        |j
                  |j                  f      svt        j                  |j                  xs2 |j                  j                  dd      d   j                  dd      d         r| j                  |d       | j                  |       |j
                  r6| j                  r*|j
                  | j                  vr| j                  |d       |s| j                  |       |j                         }|d   s|d   r| j                  s| j                  |d	       n	 t        |d   xs |d          | j                  sF|d   r'|d   j                  d
      r| j                  |d       n|d   dk(  r| j                  |d       | j                   r	 |d   r| j"                  s| j                  |d       |d   r| j                  s| j                  |d       |d   rL| j$                  s| j                  |d       n-t'        |d         }d|cxk  rdk  sn | j                  |d       |d   r| j(                  r$|d   | j(                  vr| j                  |d       n/| j*                  r#|d   | j*                  v r| j                  |d       | j                   r	 t-        j.                  |d   d        |S |S # t        $ r&}| j                  |t        |             Y d }~d }~ww xY w# t,        j                  $ r | j                  |d       Y |S w xY w)N/   r   ?zDid you mean: http://{0}zProtocol is not allowedr   r!   zIP is not allowed127.zLocalhost is not allowed::1r+   zAuthentication is not allowed	localhostr*   zCustom port is not allowedi  zPort is out of rangedomainzDomain is not allowedzDomain does not exists)r   netloc_regexmatchnetlocallschemepathsplitr   r,   	groupdictr#   r   strr)   
startswithr(   r+   r*   intr-   r.   r   getaddrinfo)r/   r   parsednetloc_matchdataer*   s          r   __call__zURL.__call__   s   %#))&--8FMM6==12!!N!2!23!:1!=!C!CC!KA!N 

5"<=JJu==T\\fmm4<<.OJJu78JJu%%'<4<77

5"56.tF|3tF|4 ::<DL$;$;F$CJJu&@A&\U*JJu&@Azz<		JJu=>TZZJJu89<99

5">?4<(4'%'JJu&<=>||Xdll B

5"9:$x.DLL"@

5"9:zz@&&tH~t< u= " .JJuc!f--.8 || @JJu&>?@s*   K* L *	L3LL%MMc                     dddS )Nr   urlr    r/   s    r   
__schema__zURL.__schema__   s     
 	
r1   )FFFFFNNNr'   )	__name__
__module____qualname____doc__r0   r   rN   propertyrS   rQ   r1   r   r%   r%   a   sE    0 (,2h 
 
r1   r%   T)httphttpsftpftps)r#   r+   r*   r)   r,   c                   <    e Zd ZdZddZd	dZd Zd Zed        Z	y)
emailaN  
    Validate an email.

    Example::

        parser = reqparse.RequestParser()
        parser.add_argument('email', type=inputs.email(dns=True))

    Input to the ``email`` argument will be rejected if it does not match an email
    and if domain does not exists.

    :param bool check: Check the domain exists (perform a DNS resolution)
    :param bool ip: Allow IP (both ipv4/ipv6) as domain
    :param bool local: Allow localhost (both string or ip) as domain
    :param list|tuple domains: Restrict valid domains to this list
    :param list|tuple exclude: Exclude some domains
    Nc                 J    || _         || _        || _        || _        || _        y r'   )r(   r#   r)   r-   r.   )r/   r(   r#   r)   r-   r.   s         r   r0   zemail.__init__   s%    

r1   c                 B    |xs d}t        |j                  |            )Nz{0} is not a valid email)r   r   r/   r   r5   s      r   r   zemail.error   s!    //E*++r1   c                 :    	 t        |       y# t        $ r Y yw xY w)NTF)r#   r   )r/   r   s     r   is_ipzemail.is_ip   s#    	uI 		s    	c                    t         j                  |      }|rd|v r| j                  |       |j                  d      }| j                  r	 t        j                  |d        | j                  r || j                  vr| j                  |d       | j                  r || j                  v r| j                  |d       | j                  s&|dv s|j                  d      r| j                  |       | j                  |      r| j                  s| j                  |       |S # t
        j                  $ r | j                  |       Y w xY w)Nz..serverz-{0} does not belong to the authorized domainsz!{0} belongs to a forbidden domain)r<   r;   r:   )email_regexr?   r   groupr(   r   rI   r-   r.   r)   rG   rc   r#   )r/   r   r?   re   s       r   rN   zemail.__call__   s   !!%(JJuX&::"""640 <<F$,,6JJuMN<<Fdll2JJuABzz**f.?.?.GJJu::fdggJJu << "

5!"s   D $EEc                     dddS )Nr   r^   r   rQ   rR   s    r   rS   zemail.__schema__  s     
 	
r1   )FFFNNr'   )
rT   rU   rV   rW   r0   r   rc   rN   rX   rS   rQ   r1   r   r^   r^      s/    $,, 
 
r1   r^   c                   2    e Zd ZdZd Zd Zd Zed        Zy)regexa`  
    Validate a string based on a regular expression.

    Example::

        parser = reqparse.RequestParser()
        parser.add_argument('example', type=inputs.regex('^[0-9]+$'))

    Input to the ``example`` argument will be rejected if it contains anything
    but numbers.

    :param str pattern: The regular expression the input must match
    c                 F    || _         t        j                  |      | _        y r'   )patternrecompile)r/   rl   s     r   r0   zregex.__init__)  s    **W%r1   c                     | j                   j                  |      s&dj                  | j                        }t	        |      |S )Nz#Value does not match pattern: "{0}")rm   searchr   rl   r   )r/   r   messages      r   rN   zregex.__call__-  s6    ww~~e$;BB4<<PGW%%r1   c                 ,    t        | j                        S r'   )rj   rl   )r/   memos     r   __deepcopy__zregex.__deepcopy__3  s    T\\""r1   c                      d| j                   dS )Nr   )r   rl   )rl   rR   s    r   rS   zregex.__schema__6  s     ||
 	
r1   N)	rT   rU   rV   rW   r0   rN   rt   rX   rS   rQ   r1   r   rj   rj     s*    &# 
 
r1   rj   c                    t        | t              s4t        j                  | t              } t        j                  |t              }| j                  Bt
        j                  j                  |       } t
        j                  j                  |      }| |fS | j                  t
        j                        } |j                  t
        j                        }| |fS )a  
    Normalize datetime intervals.

    Given a pair of datetime.date or datetime.datetime objects,
    returns a 2-tuple of tz-aware UTC datetimes spanning the same interval.

    For datetime.date objects, the returned interval starts at 00:00:00.0
    on the first date and ends at 00:00:00.0 on the second.

    Naive datetimes are upgraded to UTC.

    Timezone-aware datetimes are normalized to the UTC tzdata.

    Params:
        - start: A date or datetime
        - end: A date or datetime
    )	
isinstancer   combineSTART_OF_DAYr
   pytzUTClocalize
astimezone)startendr   s      r   _normalize_intervalr   >  s    $ eX&  5sL1||!!%(hh$
 #:   *nnTXX&#:r1   c                 6   t        | t              s| t        d      z   }|S |j                  d      d   }t	        j
                  dd|      }|j                  d      }|dk(  r| t        d      z   }|S |dk(  r| t        d	      z   }|S | t        d
      z   }|S )Nr8   )daysTz[+-].+ :r   )hours)minutes)seconds)rw   r   r   rD   rm   subr   )r~   r   r   r   time_without_offsetnum_separatorss         r   _expand_datetimer   ^  s    eX& iQ''" J {{3" ffXr48,2237Q)!,,C J q )A..C
 J )A..CJr1   c                     	 t        t        j                  |             S # t        $ rC 	 t        j                  |       dfcY S # t        $ r t        j
                  |       dfcY cY S w xY ww xY w)zg
    Do some nasty try/except voodoo to get some sort of datetime
    object(s) out of the string.
    N)sorted	aniso8601parse_intervalr   parse_datetime
parse_dater   s    r   _parse_intervalr   v  sl    
5i..u566 5	5++E2D88 	5''.44	55s,     	A,A A, A(#A,'A((A,c                     | st        d      	 t        |       \  }}|t        ||       }t        |||       \  }}||fS # t         $ r d}t        |j	                  ||             w xY w)aG  
    Parses ISO 8601-formatted datetime intervals into tuples of datetimes.

    Accepts both a single date(time) or a full interval using either start/end
    or start/duration notation, with the following behavior:

    - Intervals are defined as inclusive start, exclusive end
    - Single datetimes are translated into the interval spanning the
      largest resolution not specified in the input value, up to the day.
    - The smallest accepted resolution is 1 second.
    - All timezones are accepted as values; returned datetimes are
      localized to UTC. Naive inputs and date inputs will are assumed UTC.

    Examples::

        "2013-01-01" -> datetime(2013, 1, 1), datetime(2013, 1, 2)
        "2013-01-01T12" -> datetime(2013, 1, 1, 12), datetime(2013, 1, 1, 13)
        "2013-01-01/2013-02-28" -> datetime(2013, 1, 1), datetime(2013, 2, 28)
        "2013-01-01/P3D" -> datetime(2013, 1, 1), datetime(2013, 1, 4)
        "2013-01-01T12:00/PT30M" -> datetime(2013, 1, 1, 12), datetime(2013, 1, 1, 12, 30)
        "2013-01-01T06:00/2013-01-01T12:00" -> datetime(2013, 1, 1, 6), datetime(2013, 1, 1, 12)

    :param str value: The ISO8601 date time as a string
    :return: Two UTC datetimes, the start and the end of the specified interval
    :rtype: A tuple (datetime, datetime)
    :raises ValueError: if the interval is invalid.
    z,Expected a valid ISO8601 date/time interval.zIInvalid {arg}: {value}. {arg} must be a valid ISO8601 date/time interval.argr   )r   r   r   r   r   )r   argumentr~   r   r5   s        r   iso8601intervalr     s    8 GHH@$U+
s;"5%0C(U;
s #:  @W 	 >??	@s	   ,? (A'ziso8601-intervalc                 2    t        j                  | d      }|S )z3Parse a valid looking date in the format YYYY-mm-ddz%Y-%m-%d)r   strptimer   dates     r   r   r     s    UJ/DKr1   r   c                 t    	 t        |       S # t        t        f$ r t        dj                  |             w xY w)Nz{0} is not a valid integer)rH   	TypeErrorr   r   r   s    r   _get_integerr     s?    E5zz" E5<<UCDDEs   
 *7c                 b    t        |       } | dk  rd}t        |j                  ||             | S )z:Restrict input type to the natural numbers (0, 1, 2, 3...)r   z<Invalid {arg}: {value}. {arg} must be a non-negative integerr   r   r   r   r   r   r5   s      r   naturalr     s5    EqyL>??Lr1   integer)r   minimumc                 b    t        |       } | dk  rd}t        |j                  ||             | S )z9Restrict input type to the positive integers (1, 2, 3...)r8   z8Invalid {arg}: {value}. {arg} must be a positive integerr   r   r   s      r   positiver     s5    EqyH>??Lr1   )r   r   exclusiveMinimumc                   .    e Zd ZdZddZd Zed        Zy)	int_rangez3Restrict input to an integer in a range (inclusive)c                 .    || _         || _        || _        y r'   )lowhighr   )r/   r   r   r   s       r   r0   zint_range.__init__  s    	 r1   c                     t        |      }|| j                  k  s|| j                  kD  r>d}t        |j	                  | j
                  || j                  | j                              |S )Nz@Invalid {arg}: {val}. {arg} must be within the range {lo} - {hi})r   vallohi)r   r   r   r   r   r   ra   s      r   rN   zint_range.__call__  s\    U#488utyy0TC

t}}%DHH
S  r1   c                 6    d| j                   | j                  dS )Nr   )r   r   maximum)r   r   rR   s    r   rS   zint_range.__schema__  s     xxyy
 	
r1   Nr   )rT   rU   rV   rW   r0   rN   rX   rS   rQ   r1   r   r   r     s#    =!
 
 
r1   r   c                     t        | t              r| S | t        d      | syt        |       j	                         } | dv ry| dv ryt        dj                  |             )ap  
    Parse the string ``"true"`` or ``"false"`` as a boolean (case insensitive).

    Also accepts ``"1"`` and ``"0"`` as ``True``/``False`` (respectively).

    If the input is from the request JSON body, the type is already a native python boolean,
    and will be passed through without further parsing.

    :raises ValueError: if the boolean value is invalid
    zboolean type must be non-nullF)true1onT)false0z"Invalid literal for boolean(): {0})rw   boolr   rF   lowerr   r   s    r   booleanr     sw     %}899JE  
    
9@@G
HHr1   r   r   c                    | }t         j                  |       sdj                  | df      } 	 t        |       }t	        |      }|d   3t        j                  |      j                  t        j                        S t        j                  |t        j                        S # t        $ r t        dj                  |            w xY w)aH  
    Turns an RFC822 formatted date into a datetime object.

    Example::

        inputs.datetime_from_rfc822('Wed, 02 Oct 2002 08:00:00 EST')

    :param str value: The RFC822-complying string to transform
    :return: The parsed datetime
    :rtype: datetime
    :raises ValueError: if value is an invalid date literal

     z00:00:00r	   Invalid date literal "{0}")
time_regexrp   r3   r   r   r   fromtimestampreplacerz   utc	Exceptionr   r   )r   raw	timetuple	timestamps       r   datetime_from_rfc822r     s     CU#%,-C '	i(	R= )))4<<DHH<MM)))TXX>> C5<<SABBCs   AB :#B $Cc                    	 	 t        j                  |       S # t        $ rC t        j                  |       }t	        |j
                  |j                  |j                        cY S w xY w# t        $ r t        dj                  |             w xY w)a>  
    Turns an ISO8601 formatted date into a datetime object.

    Example::

        inputs.datetime_from_iso8601("2012-01-01T23:30:00+02:00")

    :param str value: The ISO8601-complying string to transform
    :return: A datetime
    :rtype: datetime
    :raises ValueError: if value is an invalid date literal

    r   )
r   r   r   r   r   yearmonthdayr   r   r   s     r   datetime_from_iso8601r   9  s    E	=++E22 	=''.DDIItzz488<<	=  E5<<UCDDEs"    A	A$!A' #A$$A' '$Bz	date-timec                 4    t        |       j                         S )a!  
    Turns an ISO8601 formatted date into a date object.

    Example::

        inputs.date_from_iso8601("2012-01-01")



    :param str value: The ISO8601-complying string to transform
    :return: A date
    :rtype: date
    :raises ValueError: if value is an invalid date literal

    )r   r   r   s    r   date_from_iso8601r   T  s      !',,..r1   r   )+rW   rm   r   r   r   r   email.utilsr   r   urllib.parser   r   rz   r{   ry   
END_OF_DAYrn   
IGNORECASEr>   rf   r   r   rS   r!   r#   objectr%   rP   r^   rj   r   r   r   r   r   r   r   r   r   r   r   r   r   rQ   r1   r   <module>r      s  $ 
  . . / !   Aq!DHH-"b"fTXX6
 rzz	 MM bjjOMM
 RZZ'
F $v6J $v6	@ "T2j
& j
b 
$T7W
@
F @
F!
F !
H@05-` '/:LM  $v6E (A6   )QDQ 
 
4IB i( C8E0 -5#L   /& )1FC  r1   