U
    i7g1]                     @  s>  d Z ddlmZ ddlZddlZddlmZmZ ddlm	Z	 ddl
mZ ddlmZ ddlmZ ed	ZG d
d deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG d d! d!eZG d"d# d#eZdS )$z-Validation classes for various types of data.    )annotationsN)ABCabstractmethod)zip_longest)
attrgetter)types)ValidationError_Tc                   @  sD   e Zd ZdZdZddddZddddZed	d	d
ddZdS )	ValidatorzAbstract base class for validators.

    .. note::
        This class does not provide any validation behavior. It is only used to
        add a useful `__repr__` implementation for validators.
    Nstrreturnc                 C  s8   |   }|r| dnd}d| jj d| d| jdS )N,  <(zerror=z)>)
_repr_args	__class____name__error)selfargs r   8/tmp/pip-unpacked-wheel-o_a6af_p/marshmallow/validate.py__repr__   s    zValidator.__repr__c                 C  s   dS )zbA string representation of the args passed to this validator. Used by
        `__repr__`.
        r   r   r   r   r   r   r   !   s    zValidator._repr_args
typing.Anyvaluer   c                 C  s   d S Nr   r   r   r   r   r   __call__'   s    zValidator.__call__)	r   
__module____qualname____doc__r   r   r   r   r!   r   r   r   r   r
      s   r
   c                   @  sH   e Zd ZdZdZddddddd	Zd
dddZdddddZdS )Anda3  Compose multiple validators and combine their error messages.

    Example: ::

        from marshmallow import validate, ValidationError


        def is_even(value):
            if value % 2 != 0:
                raise ValidationError("Not an even value.")


        validator = validate.And(validate.Range(min=0), is_even)
        validator(-1)
        # ValidationError: ['Must be greater than or equal to 0.', 'Not an even value.']

    :param validators: Validators to combine.
    :param error: Error message to use when a validator returns ``False``.
    zInvalid value.Nr   ztypes.Validator
str | None)
validatorsr   c                G  s   t || _|p| j| _d S r   )tupler(   default_error_messager   )r   r   r(   r   r   r   __init__B   s    
zAnd.__init__r   r   c                 C  s   d| j S )Nzvalidators=)r(   r   r   r   r   r   F   s    zAnd._repr_argsr   r   c                 C  s   g }i }| j D ]}z(||}t|ts8|dkr8t| jW q tk
r } z>||j t|jtrr|	|j n|
tt|j W 5 d }~X Y qX q|rt|f||S )NF)r(   
isinstancer
   r   r   updatekwargsmessagesdictappendextendtypingcastlist)r   r   errorsr.   Z	validatorrerrr   r   r   r!   I   s    
(zAnd.__call__)r   r"   r#   r$   r*   r+   r   r!   r   r   r   r   r%   +   s
   r%   c                   @  s   e Zd ZdZG dd dZe ZdZddddhZd	d
dd
ddddddddddZddddZ	ddddZ
dddddZdS )URLa  Validate a URL.

    :param relative: Whether to allow relative URLs.
    :param absolute: Whether to allow absolute URLs.
    :param error: Error message to raise in case of a validation error.
        Can be interpolated with `{input}`.
    :param schemes: Valid schemes. By default, ``http``, ``https``,
        ``ftp``, and ``ftps`` are allowed.
    :param require_tld: Whether to reject non-FQDN hostnames.
    c                   @  s<   e Zd Zdd ZdddddddZddddddd	Zd
S )zURL.RegexMemoizerc                 C  s
   i | _ d S r   )	_memoizedr   r   r   r   r+   j   s    zURL.RegexMemoizer.__init__boolztyping.Pattern)relativeabsoluterequire_tldr   c                 C  sx   ddddg}|s| d dddd	d
|ddf}d}|rZ|rPd|d|f}qdd|f}n
d||f}td|tjS )NzM(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)	localhostz"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}z\[[A-F0-9]*:[A-F0-9:]+\]z+(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.?)r   z(?:[a-z0-9\.\-\+]*)://z1(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?z(?:|)z	(?::\d+)?z(?:/?|[/?]\S+)\Zz^(z)?^)r1   joinrecompile
IGNORECASE)r   r<   r=   r>   Zhostname_variantsZabsolute_partZrelative_partpartsr   r   r   _regex_generatorm   s6    


z"URL.RegexMemoizer._regex_generatorc                 C  s2   |||f}|| j kr(| |||| j |< | j | S r   )r:   rH   )r   r<   r=   r>   keyr   r   r   r!      s    

  
zURL.RegexMemoizer.__call__N)r   r"   r#   r+   rH   r!   r   r   r   r   RegexMemoizeri   s   6rJ   zNot a valid URL.httphttpsftpZftpsFTN)r<   r=   schemesr>   r   r;   ztypes.StrSequenceOrSet | Noner'   c                C  s>   |s|st d|| _|| _|p$| j| _|p0| j| _|| _d S )Nz>URL validation cannot set both relative and absolute to False.)
ValueErrorr<   r=   default_messager   default_schemesrN   r>   )r   r<   r=   rN   r>   r   r   r   r   r+      s    	zURL.__init__r   r   c                 C  s   d| j d| jS )Nz	relative=z, absolute=)r<   r=   r   r   r   r   r      s    zURL._repr_argsc                 C  s   | j j|dS N)inputr   formatr    r   r   r   _format_error   s    zURL._format_errorr   c                 C  sl   |  |}|st|d|krB|dd  }|| jkrBt|| | j| j| j}|	|sht||S )Nz://r   )
rV   r   splitlowerrN   _regexr<   r=   r>   search)r   r   messageschemeregexr   r   r   r!      s    


zURL.__call__)r   r"   r#   r$   rJ   rY   rP   rQ   r+   r   rV   r!   r   r   r   r   r9   ]   s   Er9   c                   @  st   e Zd ZdZedejejB ZedejejB Z	dZ
dZddddd	d
ZdddddZdddddZdS )EmailzValidate an email address.

    :param error: Error message to raise in case of a validation error. Can be
        interpolated with `{input}`.
    z(^[-!#$%&'*+/=?^`{}|~\w]+(\.[-!#$%&'*+/=?^`{}|~\w]+)*\Z|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"\Z)z(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}|[A-Z0-9-]{2,})\Z|^\[(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\]\Z)r?   zNot a valid email address.Nr&   r'   c                C  s   |p| j | _d S r   )rP   r   )r   r   r   r   r   r+      s    zEmail.__init__r   r   c                 C  s   | j j|dS rR   rT   r    r   r   r   rV      s    zEmail._format_errorc                 C  s   |  |}|rd|krt||dd\}}| j|sBt||| jkr| j|sz|dd}W n t	k
r   Y nX | j|r|S t||S )N@   idnaascii)
rV   r   rsplit
USER_REGEXmatchDOMAIN_WHITELISTDOMAIN_REGEXencodedecodeUnicodeError)r   r   r[   Z	user_partZdomain_partr   r   r   r!     s     

zEmail.__call__)r   r"   r#   r$   rD   rE   rF   UNICODErd   rg   rf   rP   r+   rV   r!   r   r   r   r   r^      s   


r^   c                   @  sz   e Zd ZdZdZdZdZdZdZdZ	dZ
dd
d
d	dddddddZddddZddddddZdddddZd	S )Rangea-  Validator which succeeds if the value passed to it is within the specified
    range. If ``min`` is not specified, or is specified as `None`,
    no lower bound exists. If ``max`` is not specified, or is specified as `None`,
    no upper bound exists. The inclusivity of the bounds (if they exist) is configurable.
    If ``min_inclusive`` is not specified, or is specified as `True`, then
    the ``min`` bound is included in the range. If ``max_inclusive`` is not specified,
    or is specified as `True`, then the ``max`` bound is included in the range.

    :param min: The minimum value (lower bound). If not provided, minimum
        value will not be checked.
    :param max: The maximum value (upper bound). If not provided, maximum
        value will not be checked.
    :param min_inclusive: Whether the `min` bound is included in the range.
    :param max_inclusive: Whether the `max` bound is included in the range.
    :param error: Error message to raise in case of a validation error.
        Can be interpolated with `{input}`, `{min}` and `{max}`.
    zMust be {min_op} {{min}}.zMust be {max_op} {{max}}.z.Must be {min_op} {{min}} and {max_op} {{max}}.zgreater than or equal tozgreater thanzless than or equal toz	less thanNT)min_inclusivemax_inclusiver   r;   r'   c                C  s   || _ || _|| _|| _|| _| jj| jr0| jn| jd| _| j	j| jrN| j
n| jd| _	| jj| jrl| jn| j| jr|| j
n| jd| _d S )N)min_op)max_op)ro   rp   )minmaxr   rm   rn   message_minrU   message_gte
message_gtmessage_maxmessage_lte
message_ltmessage_all)r   rq   rr   rm   rn   r   r   r   r   r+   7  s    	zRange.__init__r   r   c                 C  s$   d| j d| jd| jd| jS )Nmin=, max=z, min_inclusive=z, max_inclusive=)rq   rr   rm   rn   r   r   r   r   r   R  s    zRange._repr_argsr	   r   r[   r   c                 C  s   | j p|j|| j| jdS )N)rS   rq   rr   )r   rU   rq   rr   r   r   r[   r   r   r   rV   U  s    zRange._format_errorr   c                 C  s   | j d k	rL| jr|| j k rLn
|| j krL| jd kr6| jn| j}t| ||| jd k	r| jrh|| jkrn
|| jkr| j d kr| jn| j}t| |||S r   )	rq   rm   rr   rs   ry   r   rV   rn   rv   r}   r   r   r   r!   X  s&    

zRange.__call__)NN)r   r"   r#   r$   rs   rv   ry   rt   ru   rw   rx   r+   r   rV   r!   r   r   r   r   rl     s$     rl   c                   @  sn   e Zd ZdZdZdZdZdZdddddddd	d
ddZddddZ	ddddddZ
dddddZdS )Lengthah  Validator which succeeds if the value passed to it has a
    length between a minimum and maximum. Uses len(), so it
    can work for strings, lists, or anything with length.

    :param min: The minimum length. If not provided, minimum length
        will not be checked.
    :param max: The maximum length. If not provided, maximum length
        will not be checked.
    :param equal: The exact length. If provided, maximum and minimum
        length will not be checked.
    :param error: Error message to raise in case of a validation error.
        Can be interpolated with `{input}`, `{min}` and `{max}`.
    z"Shorter than minimum length {min}.z!Longer than maximum length {max}.z'Length must be between {min} and {max}.zLength must be {equal}.N)equalr   z
int | Noner'   )rq   rr   r   r   c                C  s8   |d k	rt ||grtd|| _|| _|| _|| _d S )NzVThe `equal` parameter was provided, maximum or minimum parameter must not be provided.)anyrO   rq   rr   r   r   )r   rq   rr   r   r   r   r   r   r+   |  s    zLength.__init__r   r   c                 C  s   d| j d| jd| jS )Nrz   r{   z, equal=)rq   rr   r   r   r   r   r   r     s    zLength._repr_argsztyping.Sizedr|   c                 C  s   | j p|j|| j| j| jdS )N)rS   rq   rr   r   )r   rU   rq   rr   r   r}   r   r   r   rV     s    
   zLength._format_errorr   c                 C  s   t |}| jd k	r2|| jkr.t| || j|S | jd k	rl|| jk rl| jd krV| jn| j}t| ||| jd k	r|| jkr| jd kr| j	n| j}t| |||S r   )
lenr   r   rV   message_equalrq   rr   rs   ry   rv   )r   r   lengthr[   r   r   r   r!     s    

zLength.__call__)NN)r   r"   r#   r$   rs   rv   ry   r   r+   r   rV   r!   r   r   r   r   r~   h  s     r~   c                   @  sV   e Zd ZdZdZddddddZdd	d
dZdddddZdddddZdS )Equala  Validator which succeeds if the ``value`` passed to it is
    equal to ``comparable``.

    :param comparable: The object to compare to.
    :param error: Error message to raise in case of a validation error.
        Can be interpolated with `{input}` and `{other}`.
    zMust be equal to {other}.Nr&   r'   c                C  s   || _ |p| j| _d S r   )
comparablerP   r   )r   r   r   r   r   r   r+     s    zEqual.__init__r   r   c                 C  s   d| j S )Nzcomparable=)r   r   r   r   r   r     s    zEqual._repr_argsr	   r   c                 C  s   | j j|| jdS )N)rS   other)r   rU   r   r    r   r   r   rV     s    zEqual._format_errorc                 C  s   || j krt| ||S r   )r   r   rV   r    r   r   r   r!     s    
zEqual.__call__	r   r"   r#   r$   rP   r+   r   rV   r!   r   r   r   r   r     s   r   c                   @  s   e Zd ZdZdZddddddd	d
dZddddZdddddZej	dddddZ
ej	dddddZ
dd Z
dS )Regexpa  Validator which succeeds if the ``value`` matches ``regex``.

    .. note::

        Uses `re.match`, which searches for a match at the beginning of a string.

    :param regex: The regular expression string to use. Can also be a compiled
        regular expression pattern.
    :param flags: The regexp flags to use, for example re.IGNORECASE. Ignored
        if ``regex`` is not a string.
    :param error: Error message to raise in case of a validation error.
        Can be interpolated with `{input}` and `{regex}`.
    z'String does not match expected pattern.r   Nr&   zstr | bytes | typing.Patternintr'   )r]   flagsr   c                C  s0   t |ttfrt||n|| _|p(| j| _d S r   )r,   r   bytesrD   rE   r]   rP   r   )r   r]   r   r   r   r   r   r+     s    zRegexp.__init__r   r   c                 C  s   d| j S )Nzregex=)r]   r   r   r   r   r     s    zRegexp._repr_argszstr | bytesr   c                 C  s   | j j|| jjdS )N)rS   r]   )r   rU   r]   patternr    r   r   r   rV     s    zRegexp._format_errorc                 C  s   d S r   r   r    r   r   r   r!     s    zRegexp.__call__r   c                 C  s   d S r   r   r    r   r   r   r!     s    c                 C  s"   | j |d krt| ||S r   )r]   re   r   rV   r    r   r   r   r!     s    )r   )r   r"   r#   r$   rP   r+   r   rV   r3   overloadr!   r   r   r   r   r     s    r   c                   @  sX   e Zd ZdZdZddddddd	Zdd
ddZdddddZdddddZdS )	Predicatea  Call the specified ``method`` of the ``value`` object. The
    validator succeeds if the invoked method returns an object that
    evaluates to True in a Boolean context. Any additional keyword
    argument will be passed to the method.

    :param method: The name of the method to invoke.
    :param error: Error message to raise in case of a validation error.
        Can be interpolated with `{input}` and `{method}`.
    :param kwargs: Additional keyword arguments to pass to the method.
    Invalid input.Nr&   r   r'   )methodr   c                K  s   || _ |p| j| _|| _d S r   )r   rP   r   r.   )r   r   r   r.   r   r   r   r+     s    zPredicate.__init__r   c                 C  s   d| j d| jS )Nzmethod=z	, kwargs=)r   r.   r   r   r   r   r     s    zPredicate._repr_argsr   r   c                 C  s   | j j|| jdS )N)rS   r   )r   rU   r   r    r   r   r   rV     s    zPredicate._format_errorc                 C  s*   t || j}|f | js&t| ||S r   )getattrr   r.   r   rV   )r   r   r   r   r   r   r!     s    zPredicate.__call__r   r   r   r   r   r     s   r   c                   @  sV   e Zd ZdZdZddddddd	Zd
dddZd
dddZdddddZdS )NoneOfzValidator which fails if ``value`` is a member of ``iterable``.

    :param iterable: A sequence of invalid values.
    :param error: Error message to raise in case of a validation error. Can be
        interpolated using `{input}` and `{values}`.
    r   Nr&   typing.Iterabler'   )iterabler   c                C  s.   || _ ddd | j D | _|p&| j| _d S )Nr   c                 s  s   | ]}t |V  qd S r   r   ).0Zeachr   r   r   	<genexpr>#  s     z"NoneOf.__init__.<locals>.<genexpr>)r   rC   values_textrP   r   )r   r   r   r   r   r   r+   !  s    zNoneOf.__init__r   r   c                 C  s   d| j S )Nz	iterable=)r   r   r   r   r   r   &  s    zNoneOf._repr_argsc                 C  s   | j j|| jdS )N)rS   values)r   rU   r   r    r   r   r   rV   )  s    zNoneOf._format_errorr   r   c                 C  s6   z|| j krt| |W n tk
r0   Y nX |S r   )r   r   rV   	TypeErrorr    r   r   r   r!   ,  s    
zNoneOf.__call__r   r   r   r   r   r     s   r   c                   @  sn   e Zd ZdZdZdddddddd	d
ZddddZddddZdddddZe	fdddddZ
dS )OneOfaP  Validator which succeeds if ``value`` is a member of ``choices``.

    :param choices: A sequence of valid values.
    :param labels: Optional sequence of labels to pair with the choices.
    :param error: Error message to raise in case of a validation error. Can be
        interpolated with `{input}`, `{choices}` and `{labels}`.
    zMust be one of: {choices}.Nr&   r   ztyping.Iterable[str] | Noner'   )choiceslabelsr   c                C  sX   || _ ddd | j D | _|d k	r*|ng | _ddd | jD | _|pP| j| _d S )Nr   c                 s  s   | ]}t |V  qd S r   r   )r   choicer   r   r   r   I  s     z!OneOf.__init__.<locals>.<genexpr>c                 s  s   | ]}t |V  qd S r   r   )r   labelr   r   r   r   K  s     )r   rC   choices_textr   labels_textrP   r   )r   r   r   r   r   r   r   r+   A  s
    zOneOf.__init__r   r   c                 C  s   d| j d| jS )Nzchoices=z	, labels=)r   r   r   r   r   r   r   N  s    zOneOf._repr_argsc                 C  s   | j j|| j| jdS )N)rS   r   r   )r   rU   r   r   r    r   r   r   rV   Q  s
      zOneOf._format_errorr   r   c              
   C  sT   z|| j krt| |W n2 tk
rN } zt| ||W 5 d }~X Y nX |S r   )r   r   rV   r   )r   r   r   r   r   r   r!   V  s    
"zOneOf.__call__z/str | typing.Callable[[typing.Any], typing.Any]z'typing.Iterable[tuple[typing.Any, str]])valuegetterr   c                   s8   t  r nt  t| j| jdd} fdd|D S )a  Return a generator over the (value, label) pairs, where value
        is a string associated with each choice. This convenience method
        is useful to populate, for instance, a form select field.

        :param valuegetter: Can be a callable or a string. In the former case, it must
            be a one-argument callable which returns the value of a
            choice. In the latter case, the string specifies the name
            of an attribute of the choice objects. Defaults to `str()`
            or `str()`.
        r   )	fillvaluec                 3  s   | ]\}} ||fV  qd S r   r   )r   r   r   r   r   r   r   p  s     z OneOf.options.<locals>.<genexpr>)callabler   r   r   r   )r   r   pairsr   r   r   options_  s    zOneOf.options)N)r   r"   r#   r$   rP   r+   r   rV   r!   r   r   r   r   r   r   r   6  s    r   c                      s:   e Zd ZdZdZdd fddZdddd	d
Z  ZS )ContainsOnlyaG  Validator which succeeds if ``value`` is a sequence and each element
    in the sequence is also in the sequence passed as ``choices``. Empty input
    is considered valid.

    :param iterable choices: Same as :class:`OneOf`.
    :param iterable labels: Same as :class:`OneOf`.
    :param str error: Same as :class:`OneOf`.

    .. versionchanged:: 3.0.0b2
        Duplicate values are considered valid.
    .. versionchanged:: 3.0.0b2
        Empty input is considered valid. Use `validate.Length(min=1) <marshmallow.validate.Length>`
        to validate against empty inputs.
    z:One or more of the choices you made was not in: {choices}.r   r   c                   s    d dd |D }t |S )Nr   c                 s  s   | ]}t |V  qd S r   r   r   valr   r   r   r     s     z-ContainsOnly._format_error.<locals>.<genexpr>rC   superrV   r   r   Z
value_textr   r   r   rV     s    zContainsOnly._format_errortyping.Sequence[_T]r   c                 C  s&   |D ]}|| j krt| |q|S r   )r   r   rV   r   r   r   r   r   r   r!     s    
zContainsOnly.__call__r   r"   r#   r$   rP   rV   r!   __classcell__r   r   r   r   r   s  s   r   c                      s:   e Zd ZdZdZdd fddZdddd	d
Z  ZS )ContainsNoneOfa6  Validator which fails if ``value`` is a sequence and any element
    in the sequence is a member of the sequence passed as ``iterable``. Empty input
    is considered valid.

    :param iterable iterable: Same as :class:`NoneOf`.
    :param str error: Same as :class:`NoneOf`.

    .. versionadded:: 3.6.0
    z5One or more of the choices you made was in: {values}.r   r   c                   s    d dd |D }t |S )Nr   c                 s  s   | ]}t |V  qd S r   r   r   r   r   r   r     s     z/ContainsNoneOf._format_error.<locals>.<genexpr>r   r   r   r   r   rV     s    zContainsNoneOf._format_errorr   r   c                 C  s&   |D ]}|| j krt| |q|S r   )r   r   rV   r   r   r   r   r!     s    
zContainsNoneOf.__call__r   r   r   r   r   r     s   
r   )r$   
__future__r   rD   r3   abcr   r   	itertoolsr   operatorr   Zmarshmallowr   Zmarshmallow.exceptionsr   TypeVarr	   r
   r%   r9   r^   rl   r~   r   r   r   r   r   r   r   r   r   r   r   <module>   s.   
2 <MB0"=