
    +h                     f   d Z ddlm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mZ n# e$ r ddlmZ ddlmZ Y nw xY wddlmZ ddlmZ dd	lZdd	lZdd	lZ ej        e          Zdd	lZdd	lZdd	lZdd	lZdd	lZer	 dd	l Z n# e$ r d	Z d
Z!Y nw xY wdd	l Z dd	l"Z"e rdd	l#Z#	 dd	l$Z$n# e$ r d	Z$Y nw xY wdd	l%Z%dd	l&Z&ddl'm(Z( ddl)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6 ddl7m8Z8m9Z9m:Z:m;Z;m<Z< ddl=m>Z>m?Z? ddlm@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZGmHZHmIZImJZJmKZKmLZLmMZMmNZNmOZOmPZP g dZQ eR ej        eFrejS        nejT        d          dz             ZUg dZVddgZWddl=mXZX dZY eGd          ZZ eGd          Z[ eRej\        ]                    d          pd          Z^ G d de_          Z`eFr'eja        jb        Zc edeceja        je        g          Zfd Zgnd Zg	 	 dnd!Zhd" Zid# ZjejZk	 dd$llmmZj n# e$ r Y nw xY wdod&Zndpd(Zoe dpd)Zod* ZpeFrd+ Zqd, Zrndd-lmsZsmtZt d. Zqd/ Zr e@eqd0            e@erd1           d2 Zud3 Zvd4 Zwd5Zx eGd6          Zydqd7Zzd8 Z{d9Z|e|}                    d:          Z~d; Zd< Zd=Z eGd>          Zd? ZdrdAZdsdBZeFrdsdCZndsdDZ e@edE            e8dFdGH          dtdI            Z eddJ                                          Z eddK                                          Z edddLg          ZdudNZdO Z	 ddPlmZ dQZd6Ze$r)ePr'dRej        cxk    rdSk    rn n e$j                    ZdQZnddTlmZ  e            Zd Z eGdU          ZeFr#dQZ	  edVdW           n# e$ r d ZY n Y nxY wdX ZndQZdY Zn# e$ r d	Zd Zd Zd Zd	ZdZ ZY nw xY w e@ed[           d\ Ze%j        ZeZd] Z	  ej        d^           dQZn# e$ r d ZY nw xY wdqd_Zer ej                    Zn ej         e                      Zd` Zda ZdbZ e8dGdcdde          dfefdg            ZdhZdi ZdjZdk Zdl Zdm Zd	S )vz4passlib.utils -- helpers for writing password hashes    )JYTHON)
b2a_base64
a2b_base64Error)	b64encode	b64decode)Sequence)Iterable)lookup)update_wrapperNznot present under Jython)warn)BASE64_CHARS
AB64_CHARSHASH64_CHARSBCRYPT_CHARSBase64EngineLazyBase64Engineh64h64bigbcrypt64ab64_encodeab64_decodeb64s_encodeb64s_decode)deprecated_functiondeprecated_methodmemoized_propertyclasspropertyhybrid_method)ExpectedStringErrorExpectedTypeError)add_doc
join_bytesjoin_byte_valuesjoin_byte_elemsirangeimapPY3ujoin_unicodeunicodebyte_elem_value
nextgetterunicode_or_strunicode_or_bytes_typesget_method_functionsuppress_causePYPY)r   sys_bitsunix_crypt_schemesrounds_cost_valuesconsteqsaslprep	xor_bytesrender_bytesis_same_codecis_ascii_safeto_bytes
to_unicodeto_native_str	has_crypt
test_crypt
safe_crypttickrnggetrandbytes
getrandstrgenerate_passwordis_crypt_handleris_crypt_contexthas_rounds_infohas_salt_info   g      ?)sha512_cryptsha256_crypt
sha1_cryptbcrypt	md5_crypt
bsdi_crypt	des_cryptlinearlog2)MissingBackendError      PASSLIB_MAX_PASSWORD_SIZEi   c                   <    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	S )
SequenceMixinz
    helper which lets result object act like a fixed-length sequence.
    subclass just needs to provide :meth:`_as_tuple()`.
    c                      t          d          )Nzimplement in subclass)NotImplementedErrorselfs    Z/var/www/html/e360mart/e360mart_env/lib/python3.11/site-packages/passlib/utils/__init__.py	_as_tuplezSequenceMixin._as_tuple   s    !"9:::rV   c                 D    t          |                                           S N)reprra   r^   s    r`   __repr__zSequenceMixin.__repr__       DNN$$%%%rV   c                 6    |                                  |         S rc   ra   )r_   idxs     r`   __getitem__zSequenceMixin.__getitem__   s    ~~$$rV   c                 D    t          |                                           S rc   )iterra   r^   s    r`   __iter__zSequenceMixin.__iter__   rf   rV   c                 D    t          |                                           S rc   )lenra   r^   s    r`   __len__zSequenceMixin.__len__   s    4>>##$$$rV   c                 2    |                                  |k    S rc   rh   r_   others     r`   __eq__zSequenceMixin.__eq__   s    ~~5((rV   c                 .    |                      |           S rc   )rt   rr   s     r`   __ne__zSequenceMixin.__ne__   s    ;;u%%%%rV   N)__name__
__module____qualname____doc__ra   re   rj   rm   rp   rt   rv    rV   r`   r[   r[      s         ; ; ;& & &% % %& & &% % %) ) )& & & & &rV   r[   c                     t          j        t          |                     j        }|sdS |                    |          }|r|j        t          vrdS |t          |          d                  j        t          k    S )*test if function accepts specified keywordFT)	inspect	signaturer0   
parametersgetkind_VAR_ANY_SETlist_VAR_KEYWORD)funckeyparamsargs       r`   accepts_keywordr      sq    "#6t#<#<==H 	5jjoo 	38<//4d6ll2&',<<rV   c                 h    t          j        t          |                     }||j        v p|j        duS )r}   N)r   
getargspecr0   argskeywords)r   r   specs      r`   r   r      s4    !"5d";";<<di<4=#<<rV   Fc                    t          |t                    r|g}t          | j                  }|r=t          |t                    r|g}|D ]"|r|v r	|v r|                               #|r|D ]ߊt          fd|D                       r|rKt          |          D ]+\  }}	t          |	          r n$|rt          |	|          r n,t          |          }n^|rZt          t          |                    D ]:\  }
}	t          |	|          r%t          |          |
z
  }||dz
           |	k    sJ  n;d}nd}|
                    |           |st          |          | _        dS dS )a  
    helper to update mixin classes installed in target class.

    :param target:
        target class whose bases will be modified.

    :param add:
        class / classes to install into target's base class list.

    :param remove:
        class / classes to remove from target's base class list.

    :param append:
        by default, prepends mixins to front of list.
        if True, appends to end of list instead.

    :param after:
        optionally make sure all mixins are inserted after
        this class / classes.

    :param before:
        optionally make sure all mixins are inserted before
        this class / classes.

    :param dryrun:
        optionally perform all calculations / raise errors,
        but don't actually modify the class.
    c              3   8   K   | ]}t          |          V  d S rc   )
issubclass).0basemixins     r`   	<genexpr>z'update_mixin_classes.<locals>.<genexpr>   s-      ==t:dE**======rV      r   N)
isinstancetyper   	__bases__removeany	enumerater   ro   reversedinserttuple)targetaddr   appendbeforeafterdryrunbasesri   r   end_idxr   s              @r`   update_mixin_classesr      s   < #t e!""E  $fd## 	XF 	$ 	$E u||~~U###   % 	% 	%E====u=====   !*5!1!1 	% 	%IC!%..  *T6":":  e**C %.x%?%?  MGT!$.. !%jj72$SU|t3333	 C  LLe$$$$  ( <<( (rV   c              #     K   |dk     rt          d          t          | t                    r4t          |           }d}||k     r||z   }| ||         V  |}||k     dS dS t          | t                    r`t          |           }	 t          j        ||          }	 t          |          }n# t          $ r Y dS w xY wt          j
        |f|          V  Pt          d          )z8
    split iterable into chunks of <size> elements.
    r   zsize must be positive integerr   Tzsource must be iterableN)
ValueErrorr   r	   ro   r
   rl   	itertoolsislicenextStopIterationchain	TypeError)sourcesizeendinitr	chunk_itrfirsts           r`   batchr     s      axx8999&(## 3&kk#ggDA1+A #gggggg 
FH	%	% 
36ll	7!(d33IY    /5(I66666	7 1222s   B, ,
B:9B:c                 0   t          | t                    r't          |t                    st          d          d}nPt          | t                    r,t          |t                    st          d          t          }nt          d          t          |           t          |          k    }|r| }d}|s|}d}|rt          ||          D ]\  }}|||z  z  }n8t          ||          D ]'\  }}|t          |          t          |          z  z  }(|dk    S )a  Check two strings/bytes for equality.

    This function uses an approach designed to prevent
    timing analysis, making it appropriate for cryptography.
    a and b must both be of the same type: either str (ASCII only),
    or any type that supports the buffer protocol (e.g. bytes).

    Note: If a and b are of different lengths, or if an error occurs,
    a timing attack could theoretically reveal information about the
    types and lengths of a and b--but not their values.
    z)inputs must be both unicode or both bytesFr   r   )r   r+   r   bytesr(   ro   zipord)leftrightis_py3_bytes	same_sizetmpresultlrs           r`   r6   r6   ;  sE   * $   	E%)) 	IGHHH	D%	 	  E%'' 	IGHHHCDDD Tc%jj(I     &sE?? 	 	CAaa!eOFF	 sE?? 	& 	&CAac!ffs1vvo%FFQ;rV   )compare_digest,c                     |                                  } |                     |          r
| dd         } | sg S d |                     |          D             S )zRsplit comma-separated string into list of elements,
    stripping whitespace.
    Nr~   c                 6    g | ]}|                                 S r{   )stripr   elems     r`   
<listcomp>zsplitcomma.<locals>.<listcomp>  s     999dTZZ\\999rV   )r   endswithsplit)r   seps     r`   
splitcommar     s_     \\^^Fs  	99fll3&7&79999rV   valuec                 2   t          | t                    st          dt          |                     t          j        t          j        t          fd| D                       }t          j	        d|          }|st          S t          j        } ||d                   r0 ||d                   st          d|z             t          j        }n|}t          j        }t          j        }t          j        }t          j        }t          j        }	t          j        }
t          j        }t          j        }t          j        }|D ]O} |          r
J d             |          r
J d             ||          rt          d	|z              ||          rt          d
|z              ||          rt          d|z              ||          rt          d|z              |	|          rt          d|z              |
|          rt          d|z              ||          rt          d|z              ||          rt          d|z              ||          rt          d|z              ||          rt          d|z             Q|S )a  Normalizes unicode strings using SASLPrep stringprep profile.

    The SASLPrep profile is defined in :rfc:`4013`.
    It provides a uniform scheme for normalizing unicode usernames
    and passwords before performing byte-value sensitive operations
    such as hashing. Among other things, it normalizes diacritic
    representations, removes non-printing characters, and forbids
    invalid characters such as ``\n``. Properly internationalized
    applications should run user passwords through this function
    before hashing.

    :arg source:
        unicode string to normalize & validate

    :param param:
        Optional noun identifying source parameter in error messages
        (Defaults to the string ``"value"``). This is mainly useful to make the caller's error
        messages make more sense contextually.

    :raises ValueError:
        if any characters forbidden by the SASLPrep profile are encountered.

    :raises TypeError:
        if input is not :class:`!unicode`

    :returns:
        normalized unicode string

    .. note::

        This function is not available under Jython,
        as the Jython stdlib is missing the :mod:`!stringprep` module
        (`Jython issue 1758320 <http://bugs.jython.org/issue1758320>`_).

    .. versionadded:: 1.6
    z"input must be unicode string, not c              3   V   K   | ]#} |           |          rt           n|V  $d S rc   )_USPACE)r   cin_table_b1in_table_c12s     r`   r   zsaslprep.<locals>.<genexpr>  sV       
 
{1~~
<??)
 
 
 
 
 
rV   NFKCr   r~   zmalformed bidi sequence in z$failed to strip B.1 in mapping stagez(failed to replace C.1.2 in mapping stagez$unassigned code points forbidden in z control characters forbidden in z$private use characters forbidden in z"non-char code points forbidden in zsurrogate codes forbidden in z!non-plaintext chars forbidden in z!non-canonical chars forbidden in z1display-modifying / deprecated chars forbidden inztagged characters forbidden in zforbidden bidi character in )r   r+   r   r   
stringprepr   r   r*   unicodedata	normalize_UEMPTYin_table_d1r   in_table_d2in_table_a1in_table_c21_c22in_table_c3in_table_c4in_table_c5in_table_c6in_table_c7in_table_c8in_table_c9)r   paramdatais_ral_charis_forbidden_bidi_charr   r   r   r   r   r   r   r   r   r   r   r   s                  @@r`   r7   r7     s4   X fg&& )if( ) ) 	) *L(K 
 
 
 
 

 
 
 
 
D  ..D  (K{47 -{48$$ 	D:UBCCC!+!7 "- (K!2(K(K(K(K(K(K(K E E;q>>II#III!<??NN$NNN" ;q>> 	MCeKLLLA 	I?%GHHH;q>> 	MCeKLLL;q>> 	KAEIJJJ;q>> 	F<uDEEE;q>> 	J@5HIII;q>> 	J @5HIII;q>> 	5 ,.34 5 5 5;q>> 	H>FGGG "!!$$ 	E;eCDDD	E KrV   c                 0    t          dt          z             )zstub for saslprep()z>saslprep() support requires the 'stringprep' module, which is )r]   _stringprep_missing_reason)r   r   s     r`   r7   r7     s%    ! #02L#M N N 	NrV   c                     t          | t                    r|                     d          } | t          d |D                       z  }|                    d          S )a  Peform ``%`` formating using bytes in a uniform manner across Python 2/3.

    This function is motivated by the fact that
    :class:`bytes` instances do not support ``%`` or ``{}`` formatting under Python 3.
    This function is an attempt to provide a replacement:
    it converts everything to unicode (decoding bytes instances as ``latin-1``),
    performs the required formatting, then encodes the result to ``latin-1``.

    Calling ``render_bytes(source, *args)`` should function roughly the same as
    ``source % args`` under Python 2.

    .. todo::
        python >= 3.5 added back limited support for bytes %,
        can revisit when 3.3/3.4 is dropped.
    latin-1c              3   n   K   | ]0}t          |t                    r|                    d           n|V  1dS )r   N)r   r   decode)r   r   s     r`   r   zrender_bytes.<locals>.<genexpr>,  sZ       6 6), 6@U5K5K %CJJy111!$6 6 6 6 6 6rV   )r   r   r   r   encode)r   r   r   s      r`   r9   r9     sk      &%   *y))e 6 6046 6 6 6 6 6F==###rV   c                 8    t                               | d          S Nbig)int
from_bytesr   s    r`   bytes_to_intr   2  s    ~~eU+++rV   c                 .    |                      |d          S r   )r<   r   counts     r`   int_to_bytesr   4  s    ~~eU+++rV   )hexlify	unhexlifyc                 <    t          t          |           d          S )N   )r   r  r   s    r`   r   r   9  s    75>>"%%%rV   c                 2    t          d|dz  z  | z            S )Nz%%0%dxr   )r  r   s     r`   r   r   ;  s    (eQh/58999rV   z/decode byte string as single big-endian integerz/encode integer as single big-endian byte stringc                 v    t          t          |           t          |          z  t          |                     S )z;Perform bitwise-xor of two byte strings (must be same size))r   r   ro   r   r   s     r`   r8   r8   A  s-    T**\%-@-@@#d))LLLrV   c                 L    d|dz
  t          |           z  z   }| |z  d|         S )zE
    repeat or truncate <source> string, so it has length <size>
    r   N)ro   r   r   mults      r`   repeat_stringr  E  s0     qS[[((DTM5D5!!rV   c                 X    d|dz
  t          |           z  z   }t          | |z  |          S )zN
    variant of repeat_string() which truncates to nearest UTF8 boundary.
    r   )ro   utf8_truncater	  s      r`   utf8_repeat_stringr  M  s1     qS[[((D$---rV        c                     t          |           }||k    r0|#t          | t                    rt          nt          }| |||z
  z  z   S | d|         S )z>right-pad or truncate <source> string, so it has length <size>N)ro   r   r+   _UNULL_BNULL)r   r   padcurs       r`   right_pad_stringr  X  sT    
f++Cczz;&vw77C&&VCc48n$$ete}rV   c                     t           t                    st           t          d          t                     }|dk     rt	          d||z             }||k    r S t          |dz   |          }||k     r(t           |                   dz  dk    rn|dz  }||k     (||k    sJ  d|          fd} |            sJ S )	a  
    helper to truncate UTF8 byte string to nearest character boundary ON OR AFTER <index>.
    returned prefix will always have length of at least <index>, and will stop on the
    first byte that's not a UTF8 continuation byte (128 - 191 inclusive).
    since utf8 should never take more than 4 bytes to encode known unicode values,
    we can stop after ``index+3`` is reached.

    :param bytes source:
    :param int index:
    :rtype: bytes
    r   r            r   Nc                      	                      d          } n# t          $ r Y dS w xY w|                                          d                    sJ dS )Nutf-8T)r   UnicodeDecodeError
startswith)textr   r   s    r`   sanity_checkz#utf8_truncate.<locals>.sanity_check  sh    	==))DD! 	 	 	44	
 v}}W5566666ts    
'')r   r   r!   ro   maxminr,   )r   indexr   r   r   s   `   @r`   r  r  c  s   2 fe$$ 9x888 f++CqyyAus{##|| eai

C #++6%=))D0D88
 #++ |||| FUF^F
 
 
 
 
 
 <>>>MrV   s	    
 aA:#!asciic                 H    t                               |           t          k    S )zRTest if codec is compatible with 7-bit ascii (e.g. latin-1, utf-8; but not utf-16))_ASCII_TEST_UNICODEr   _ASCII_TEST_BYTES)codecs    r`   is_ascii_codecr)    s    %%e,,0AAArV   c                 r    | |k    rdS | r|sdS t          |           j        t          |          j        k    S )z3Check if two codec names are aliases for same codecTF)_lookup_codecnamer  s     r`   r:   r:     sE    u}}t U u#}U';';'@@@rV   r     c                     t          | t                    rt          nt          t	          fd| D                       S )z<Check if string (bytes or unicode) contains only 7-bit asciic              3   $   K   | ]
}|k     V  d S rc   r{   )r   r   r   s     r`   r   z is_ascii_safe.<locals>.<genexpr>  s'      %%q1u%%%%%%rV   )r   r   _B80_U80all)r   r   s    @r`   r;   r;     s>    65))3tA%%%%f%%%%%%rV   r  c                     |sJ t          | t                    r<|r8t          ||          s(|                     |                              |          S | S t          | t
                    r|                     |          S t          | |          )a  Helper to normalize input to bytes.

    :arg source:
        Source bytes/unicode to process.

    :arg encoding:
        Target encoding (defaults to ``"utf-8"``).

    :param param:
        Optional name of variable/noun to reference when raising errors

    :param source_encoding:
        If this is specified, and the source is bytes,
        the source will be transcoded from *source_encoding* to *encoding*
        (via unicode).

    :raises TypeError: if source is not unicode or bytes.

    :returns:
        * unicode strings will be encoded using *encoding*, and returned.
        * if *source_encoding* is not specified, byte strings will be
          returned unchanged.
        * if *source_encoding* is specified, byte strings will be transcoded
          to *encoding*.
    )r   r   r:   r   r   r+   r    )r   encodingr   source_encodings       r`   r<   r<     s    4 OO8&%   1 	=(#K#K 	==1188BBBM	FG	$	$ 1}}X&&&!&%000rV   c                     |sJ t          | t                    r| S t          | t                    r|                     |          S t	          | |          )a  Helper to normalize input to unicode.

    :arg source:
        source bytes/unicode to process.

    :arg encoding:
        encoding to use when decoding bytes instances.

    :param param:
        optional name of variable/noun to reference when raising errors.

    :raises TypeError: if source is not unicode or bytes.

    :returns:
        * returns unicode strings unchanged.
        * returns bytes strings decoded using *encoding*
    )r   r+   r   r   r    r   r4  r   s      r`   r=   r=     sX    $ OO8&'"" 1	FE	"	" 1}}X&&&!&%000rV   c                     t          | t                    r|                     |          S t          | t                    r| S t	          | |          rc   )r   r   r   r+   r    r7  s      r`   r>   r>     sM    fe$$ 	5==***(( 	5M%fe444rV   c                     t          | t                    r| S t          | t                    r|                     |          S t	          | |          rc   )r   r   r+   r   r    r7  s      r`   r>   r>     sM    fe$$ 	5M(( 	5==***%fe444rV   a>  Take in unicode or bytes, return native string.

    Python 2: encodes unicode using specified encoding, leaves bytes alone.
    Python 3: leaves unicode alone, decodes bytes using specified encoding.

    :raises TypeError: if source is not unicode or bytes.

    :arg source:
        source unicode or bytes string.

    :arg encoding:
        encoding to use when encoding unicode or decoding bytes.
        this defaults to ``"utf-8"``.

    :param param:
        optional name of variable/noun to reference when raising errors.

    :returns: :class:`str` instance
    z1.6z1.7)
deprecatedremovedc                 &    t          | |d          S )z'deprecated, use to_native_str() insteadhash)r   )r>   )r   r4  s     r`   to_hash_strr>  $  s     8888rV   z true t yes y on 1 enable enabledz#false f no n off 0 disable disablednonebooleanc                 D   |dv sJ t          | t                    r\|                                                                 }|t          v rdS |t
          v rdS |t          v r|S t          d|d|           t          | t                    r| S | |S t          |           S )z\
    helper to convert value to boolean.
    recognizes strings such as "true", "false"
    )TFNTFzunrecognized z value: )	r   r/   lowerr   	_true_set
_false_set	_none_setr   bool)r   r?  r   cleans       r`   as_boolrH  -  s    
 &&&&&%/00 ##%%I4J5IKjuuEFFF	E4	 	  	E{{rV   c                     t           st          | t                    sdS 	 |                     d           dS # t          $ r Y dS w xY w)z
    UT helper --
    test if value is safe to pass to crypt.crypt();
    under PY3, can't pass non-UTF8 bytes to crypt.crypt.
    Tr  F)crypt_accepts_bytesr   r   r   r  r   s    r`   is_safe_crypt_inputrK  G  s`      *UE":": tWt   uus   7 
AA)cryptT)   rK   r   )rM  r  r  )nullcontextz*:!   xxc                 4   t           rmt          | t                    r|                     d          } t          | v rt          d          t          |t                    r|                    d          }nt          | t                    rM| }	 |                     d          } n# t          $ r Y d S w xY w|                     d          |k    s
J d            t          | v rt          d          t          |t                    r|                    d          }	 t          5  t          | |          }d d d            n# 1 swxY w Y   n# t          $ r Y d S w xY wt          |t                    r|                    d          }|r|d         t          v rd S |S )Nr  null character in secretr$  z"utf-8 spec says this can't happen!r   )rJ  r   r+   r   r  r   r   r   r  _NULL_safe_crypt_lock_cryptOSError_invalid_prefixes)secretr=  origr   s       r`   rA   rA     s    " 0 fg.. 4#]]733FV##$%?@@@dG,, 0;;w//D
 fe,, 	E!D$!'w!7!7- $ $ $#tt$ "==11T999 D :99F??$%?@@@dE** 0;;w//D% 2 2#FD11F2 2 2 2 2 2 2 2 2 2 2 2 2 2 2    tt	 &%(( 0w// VAY*;;;tMsH   B# #
B10B1E
 !D>2E
 >EE
 EE
 

EEc                    t          | t                    r|                     d          } t          | v rt	          d          t          |t                    r|                    d          }t
          5  t          | |          }d d d            n# 1 swxY w Y   |sd S |                    d          }|d         t          v rd S |S )Nr  rR  r$  r   )	r   r+   r   rS  r   rT  rU  r   rW  )rX  r=  r   s      r`   rA   rA     s   &'** 0w// !;<<<$(( ,{{7++! . .--. . . . . . . . . . . . . . . t]]7++Fay---tMs   4BBBc                     d S rc   r{   rX  r=  s     r`   rA   rA   ]  s    trV   a  Wrapper around stdlib's crypt.

    This is a wrapper around stdlib's :func:`!crypt.crypt`, which attempts
    to provide uniform behavior across Python 2 and 3.

    :arg secret:
        password, as bytes or unicode (unicode will be encoded as ``utf-8``).

    :arg hash:
        hash or config string, as ascii bytes or unicode.

    :returns:
        resulting hash as ascii unicode; or ``None`` if the password
        couldn't be hashed due to one of the issues:

        * :func:`crypt()` not available on platform.

        * Under Python 3, if *secret* is specified as bytes,
          it must be use ``utf-8`` or it can't be passed
          to :func:`crypt()`.

        * Some OSes will return ``None`` if they don't recognize
          the algorithm being used (though most will simply fall
          back to des-crypt).

        * Some OSes will return an error string if the input config
          is recognized but malformed; current code converts these to ``None``
          as well.
    c                     t          |t                    sJ dt          |          z              |s
J d            t          | |          |k    S )zcheck if :func:`crypt.crypt` supports specific hash
    :arg secret: password to test
    :arg hash: known hash of password to use as reference
    :returns: True or False
    z#hash must be unicode_or_str, got %szhash must be non-empty)r   r.   r   rA   r\  s     r`   r@   r@     s_     dN++ ; ;-T

:; ;+)))))4fd##t++rV   c                     t          j        d|           }|r?t          d |                    d                              d          D                       S dS )zhelper to parse version stringz(\d+(?:\.\d+)+)c              3   4   K   | ]}t          |          V  d S rc   )r   r   s     r`   r   z parse_version.<locals>.<genexpr>  s(      AA4SYYAAAAAArV   r   .N)researchr   groupr   )r   ms     r`   parse_versionre    sW    
	$f--A BAA1771::+;+;C+@+@AAAAAA4rV   r   c           	         ddl m} t          | d          rKt          | d          r;	 |                                 } n%# t          $ r |                     d          } Y nw xY wt          d          | t          t          d          rt          j                    ndt          t                                t          j                    t                      t          r't          j        d	                              d
          ndfz  }t!           ||                    d                                                    d          S )z.generate prng seed value from system resourcesr   )sha512getstategetrandbitsi   z%s %s %s %.15f %.15f %sgetpidN    r   r  r  )hashlibrg  hasattrrh  r]   ri  r)   osrj  idobjecttimerB   has_urandomurandomr   r   r   	hexdigest)r   rg  r  s      r`   genseedru    s6   uj!! /ge]&C&C /	/NN$$EE" 	/ 	/ 	/ %%g..EEE	/ &'' r8,,6	$ 	688 		 -8>
2i(((Q#+
 
D( vvdkk'**++5577<<<s   = AAc                 R     st           S  fd}t           |                      S )z]return byte-string containing *count* number of randomly generated bytes, using specified rngc               3   ~   K                        dz            } d}|k     r| dz  V  | dz  } |dz  }|k     d S d S )Nr  r      r   )ri  )r   r   r   rC   s     r`   helperzgetrandbytes.<locals>.helperM  s_      q))%ii$,aKEFA %iiiiiirV   )_BEMPTYr$   )rC   r   ry  s   `` r`   rD   rD   B  sG            FFHH%%%rV   c                 (    dk     rt          d          t                    dk    rt          d          dk    rz  S  fd}t          t                    rt	           |                      S t           |                      S )z|return string containing *count* number of chars/bytes, whose elements are drawn from specified charset, using specified rngr   zcount must be >= 0zalphabet must not be emptyr   c               3      K                        dz            } d}|k     r| z           V  | z  } |dz  }|k     d S d S )Nr   r   )	randrange)r   r   charsetr   lettersrC   s     r`   ry  zgetrandstr.<locals>.helperf  sg      a%00%ii%'/****gEFA %iiiiiirV   )r   ro   r   r+   r*   r%   )rC   r~  r   ry  r  s   ``` @r`   rE   rE   W  s     qyy-...'llG!||5666!||        '7## )FFHH%%%vvxx(((rV   42346789ABCDEFGHJKMNPQRTUVWXYZabcdefghjkmnpqrstuvwxyzz2.0z/passlib.pwd.genword() / passlib.pwd.genphrase())r:  r;  replacement
   c                 .    t          t          ||           S )aw  generate random password using given length & charset

    :param size:
        size of password.

    :param charset:
        optional string specified set of characters to draw from.

        the default charset contains all normal alphanumeric characters,
        except for the characters ``1IiLl0OoS5``, which were omitted
        due to their visual similarity.

    :returns: :class:`!str` containing randomly generated password.

    .. note::

        Using the default character set, on a OS with :class:`!SystemRandom` support,
        this function should generate passwords with 5.7 bits of entropy per character.
    )rE   rC   )r   r~  s     r`   rF   rF   v  s    , c7D)))rV   )r,  setting_kwdscontext_kwdsverifyr=  identifyc                 D     t           fdt          D                       S )z4check if object follows the :ref:`password-hash-api`c              3   8   K   | ]}t          |          V  d S rc   rm  r   r,  objs     r`   r   z#is_crypt_handler.<locals>.<genexpr>  -      ==dwsD!!======rV   )r2  _handler_attrsr  s   `r`   rG   rG     (     ====n======rV   )needs_update	genconfiggenhashr  encryptr  c                 D     t           fdt          D                       S )zOcheck if object appears to be a :class:`~passlib.context.CryptContext` instancec              3   8   K   | ]}t          |          V  d S rc   r  r  s     r`   r   z#is_crypt_context.<locals>.<genexpr>  r  rV   )r2  _context_attrsr  s   `r`   rH   rH     r  rV   c                 :    d| j         v ot          | dd          duS )z_check if handler provides the optional :ref:`rounds information <rounds-attributes>` attributesrounds
min_roundsNr  getattrhandlers    r`   rI   rI     s+    ,, =G\400<>rV   c                 :    d| j         v ot          | dd          duS )z[check if handler provides the optional :ref:`salt information <salt-attributes>` attributessaltmin_salt_sizeNr  r  s    r`   rJ   rJ     s-    g** @G_d334?ArV   )NNFNNF)r   r   rc   )r  r   N)r  r   )r$  )Nr@  )rz   passlib.utils.compatr   binasciir   r   r   _BinAsciiErrorbase64r   r   collections.abcr	   r
   ImportErrorcollectionscodecsr   r+  	functoolsr   r   r   logging	getLoggerrw   logmathrn  sysrandomra  r   r   rq  r   	threadingtimeittypeswarningsr   passlib.utils.binaryr   r   r   r   r   r   r   r   r   r   r   r   r   passlib.utils.decorr   r   r   r   r   passlib.excr    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   __all__r   maxsizemaxintr3   r4   r5   rU   rz  r   r   environr   MAX_PASSWORD_SIZErp  r[   	ParameterVAR_KEYWORDr   setVAR_POSITIONALr   r   r   r   r6   str_consteqhmacr   r   r7   r9   r   r   r  r  r8   r  r  r  r  r  r  r'  r   r&  r)  r:   r0  r1  r;   r<   r=   r>   r>  r   rC  rD  rE  rH  rK  rL  rU  r?   rS  pypy_version_infoLockrT  crypt_needs_lockrN  rW  rJ  r   rA   r@   default_timertimerrB   re  rs  rr  r]   ru  SystemRandomrC   RandomrD   rE   
_52charsetrF   r  rG   r  rH   rI   rJ   r{   rV   r`   <module>r     s   : : ( ' ' ' ' ' D D D D D D D D D D ' ' ' ' ' ' ' '%((((((((((((( % % %$$$$$$$$$$$$$$% + * * * * * $ $ $ $ $ $      'g'11  				 



  					 	@ @ @ @
%?"""@      III                                                   ? > > > > > > >M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M' ' '\ 3xtxs:
A>>DEE     )  , + + + + + 
!B%%
!C&& C
'BCCKtLL & & & & &F & & &4  = $0L3g&7&FGHHL	= 	= 	= 	== = =
 @E9>R( R( R( R(n3 3 3>8 8 8| 	....... 	 	 	D		: 	: 	: 	:} } } }@ N N N N$ $ $,  :, , ,, , , , ,+++++++& & &: : : G H H H G H H HM M M" " ". . . 
	
6   A A AL ( '..w77 B B BA A A qyy& & &
#1 #1 #1 #1J1 1 1 14  55 5 5 5 55 5 5 5 	 	 	* u5559 9 9 659 C288::;;	S6<<>>??
CV	   4  s%%%%%% IE  !T !i3+@MMMMIMMMMM *9>++   	544444&;==  %
 P
 #	F7D!!!! 	( 	( 	("'	 D+	 +	 +	 +	^ #	 	 	 	G    FI    f 
  	 	 	<, , , 	  ,BJqMMMKK   KKK= = = =B  #
&


CC &-		
"
"C
& & &*) ) ): D
u!RT T Tz * * *T T*2
> > >

> > >> > >
A A A A Asx   ) ==?B 	BB"B' 'B10B1G& &G.-G. M= M$ $M0-M0=NN1O OO