+
    THim                    r  a  0 t $ R t^ RIHt ^ RIt^ RIHt ^ RIHt ^ RIH	t	H
t
HtHtHtHtHt ^ RIHt ^ RIHt ]	'       d   ^ RIHtHt ^ R	IHt ^ R
IHtHt ^ RIHt ^ RIHt ^ RI H!t! ^ RI"H#t#H$t$H%t% ^ RI&H't' RR.t(])! 4       t*Rt+Rt,Rt-Rt.R]/R&   Rt0R]/R&   ]! R4      t1]	'       d-   ]]2]R,          ]33,          ]2]R,          ]13,          3,          t4MRt4 ! R R]]1,          4      t5]6! 4       t7R]/R&   R  t8]8! 4       t9R! t:]:! 4       t; ! R" R]5]3,          4      t< ! R# R]5]2]3]33,          ,          4      t=R# )$zApache password support)annotationsN)BytesIO)PathLike)TYPE_CHECKINGAnyGenericLiteralTypeVarUnioncast)warn)logger)IterableIterator)Self)excregistry)CryptContext)ExpectedStringError)htdigest)is_ascii_codecrender_bytesto_bytes)
join_bytesHtpasswdFileHtdigestFile   :   #s   :
	 skippedzLiteral['skipped']_SKIPPEDrecordzLiteral['record']_RECORD_TRecordKeyc                  r   ] tR t^6tRtR/R R llt]R R l4       t]R R l4       tR	 R
 lt	]
R R l4       t]P                  R R l4       t]
R R l4       tR R ltR0R R lltR R ltR R ltR R ltR R ltR R ltR0R R  lltR! R" ltR# R$ ltR% tR& R' ltR( R) ltR1R* R+ lltR, R- ltR.tR# )2_CommonFilez0Common framework for HtpasswdFile & HtdigestFileNc               0    V ^8  d   QhRRRRRRRRRRR	R
/# )   pathPathLike | Nonenewboolautosaveencodingstrreturn_unicodereturnNone )formats   "0/usr/lib/python3/dist-packages/passlib/apache.py__annotate___CommonFile.__annotate__9   sF     " "" " 	"
 " " 
"    c                	   V'       g   \        R 4      h\        V4      '       g   \        R4      hW@n        WPn        W0n        Wn        ^ V n        / V n        . V n	        V'       d   V'       g   V P                  4        R# R# R# )z'encoding' is requiredz'encoding must be 7-bit ascii compatibleN)	TypeErrorr   
ValueErrorr,   r.   r+   _path_mtime_records_sourceload)selfr'   r)   r+   r,   r.   s   &&&&&&r3   __init___CommonFile.__init__9   ss     455h'' FGG !, 
 13 ,. IIK 4r6   c               $    V ^8  d   QhRRRRRR/# )r&   datastr | byteskwargsr   r/   r   r1   )r2   s   "r3   r4   r5   ^   s!      { c d r6   c                \    RV9   d   \        R4      hV ! R/ VB pVP                  V4       V# )zcreate new object from raw string.

:type data: str or bytes
:arg data:
    database to load, as single string.

:param \*\*kwds:
    all other keywords are the same as in the class constructor
r'   z$'path' not accepted by from_string()r1   )r8   load_string)clsrC   rE   instances   &&, r3   from_string_CommonFile.from_string]   s6     VBCC==T"r6   c               $    V ^8  d   QhRRRRRR/# )r&   r'   r   kwdsr   r/   r   r1   )r2   s   "r3   r4   r5   o   s!      X s t r6   c                8    V ! R/ VB pVP                  V4       V# )zcreate new object from file, without binding object to file.

:type path: str
:arg path:
    local filepath to load from

:param \*\*kwds:
    all other keywords are the same as in the class constructor
r1   )r>   )rH   r'   rM   r?   s   &&, r3   	from_path_CommonFile.from_pathn   s     {T{		$r6   c                   V ^8  d   QhRR/# )r&   r/   r-   r1   )r2   s   "r3   r4   r5      s     D D# Dr6   c                	0   R pV P                   '       d
   VR,          pV P                  '       d   VRV P                  : 2,          pV P                  R8w  d   VRV P                  : 2,          pRV P                  P                   R\        V 4      R V R2# )	 z autosave=Truez path=utf-8z
 encoding=<z 0x0x>)r+   r:   r,   	__class____name__id)r?   tails   & r3   __repr___CommonFile.__repr__   s    ===$$D:::fTZZN++D==G#j 122D4>>**+3r$xmD6CCr6   c                   V ^8  d   QhRR/# )r&   r/   r(   r1   )r2   s   "r3   r4   r5      s      o r6   c                	    V P                   # N)r:   r?   s   &r3   r'   _CommonFile.path   s    zzr6   c                    V ^8  d   QhRRRR/# )r&   valuer(   r/   r0   r1   )r2   s   "r3   r4   r5      s      / d r6   c                	@    WP                   8w  d   ^ V n        Wn         R# )    N)r:   r;   r?   rd   s   &&r3   r'   rb      s    JJDK
r6   c                   V ^8  d   QhRR/# )r&   r/   floatr1   )r2   s   "r3   r4   r5      s      u r6   c                    V P                   # )z7modify time when last loaded (if bound to a local file))r;   ra   s   &r3   mtime_CommonFile.mtime   s     {{r6   c                   V ^8  d   QhRR/# )r&   r/   r*   r1   )r2   s   "r3   r4   r5      s       r6   c                    V P                   '       g   \        V : R24      hV P                  '       d;   V P                  \        P                  P                  V P                   4      8X  d   R# V P                  4        R# )zBReload from ``self.path`` only if file has changed since last loadz is not bound to a local fileFT)r:   RuntimeErrorr;   osr'   getmtimer>   ra   s   &r3   load_if_changed_CommonFile.load_if_changed   sT    zzz$)FGHH;;;4;;"''*:*:4::*FF		r6   c                    V ^8  d   QhRRRR/# )r&   r'   r(   r/   r*   r1   )r2   s   "r3   r4   r5      s       D r6   c                    Ve8   \        VR4      ;_uu_ 4       p^ V n        V P                  V4       RRR4       R# V P                  '       di   \        V P                  R4      ;_uu_ 4       p\        P
                  P                  V P                  4      V n        V P                  V4       RRR4       R# \        V P                  P                   R24      h  + '       g   i     R# ; i  + '       g   i     R# ; i)zLoad state from local file.
If no path is specified, attempts to load from ``self.path``.

:type path: str
:arg path: local file to load from
Nrbz0().path is not set, an explicit path is requiredT)
openr;   _load_linesr:   rp   r'   rq   ro   rX   rY   r?   r'   fhs   && r3   r>   _CommonFile.load   s     dD!!R  $ "  ZZZdjj$''2 gg..tzz:  $ (  >>**++[\  "!  (' s   C,A C,C)	,C=	c                    V ^8  d   QhRRRR/# )r&   rC   rD   r/   r0   r1   )r2   s   "r3   r4   r5      s     I I I Ir6   c           	     p    ^ V n         V P                  \        \        WP                  R4      4      4       R# )z@Load state from unicode or bytes string, replacing current staterC   N)r;   rx   r   r   r,   )r?   rC   s   &&r3   rG   _CommonFile.load_string   s'    $v!FGHr6   c                    V ^8  d   QhRRRR/# )r&   lineszIterable[bytes]r/   r0   r1   )r2   s   "r3   r4   r5      s     * * *T *r6   c                    / p. pRp\        V4       F  w  rVVP                  4       pV'       d   VP                  \        4      '       d   WF,          pKB  V P	                  We^,           4      w  rW9   d"   \
        P                  ! RV4       WF,          pK  V'       d   VP                  \        V34       RpWV&   VP                  \        V34       K  	  VP                  4       '       d   VP                  \        V34       W n        W0n        R# )zload from sequence of listsr6   z1username occurs multiple times in source file: %rN)	enumeratelstrip
startswith_BHASH_parse_recordr   warningappendr   r!   rstripr<   r=   )
r?   r   recordssourcer   idxlinetmpkeyrd   s
   &&        r3   rx   _CommonFile._load_lines   s    %'"5)IC ++-C#..00 ++D':JC ~G  x12 !CLMM7C.); *@ >>MM8W-.  r6   c               $    V ^8  d   QhRRRRRR/# )r&   r    byteslinenointr/   ztuple[_TRecordKey, Any]r1   )r2   s   "r3   r4   r5      s)     G GG%(G	 Gr6   c                    \        R4      h)z)parse line of file into (key, value) pair!should be implemented in subclassNotImplementedError)r?   r    r   s   &&&r3   r   _CommonFile._parse_record   s     ""EFFr6   c               $    V ^8  d   QhRRRRRR/# )r&   r   r"   rd   r   r/   r*   r1   )r2   s   "r3   r4   r5      s!      { 3 4 r6   c                    WP                   9   pW P                   V&   V'       g"   V P                  P                  \        V34       V# )z{
helper for setting record which takes care of inserting source line if needed;

:returns:
    bool if key already present
)r<   r=   r   r!   )r?   r   rd   existings   &&& r3   _set_record_CommonFile._set_record   s:     --'"cLL#/r6   c                   V ^8  d   QhRR/# )r&   r/   r0   r1   )r2   s   "r3   r4   r5      s      4 r6   c                v    V P                   '       d'   V P                  '       d   V P                  4        R# R# R# )z0subclass helper to call save() after any changesN)r+   r:   savera   s   &r3   	_autosave_CommonFile._autosave   s#    ===TZZZIIK (=r6   c                    V ^8  d   QhRRRR/# )r&   r'   r(   r/   r0   r1   )r2   s   "r3   r4   r5     s       D r6   c                   Ve?   \        VR4      ;_uu_ 4       pVP                  V P                  4       4       RRR4       R# V P                  '       dL   V P	                  V P                  4       \
        P                  P                  V P                  4      V n        R# \        V P                  P                   R24      h  + '       g   i     R# ; i)zXSave current state to file.
If no path is specified, attempts to save to ``self.path``.
Nwbz#().path is not set, cannot autosave)rw   
writelines_iter_linesr:   r   rp   r'   rq   r;   ro   rX   rY   ry   s   && r3   r   _CommonFile.save  s     dD!!Rd..01 "!ZZZIIdjj!''**4::6DK>>**++NO  "!!s    CC	c                   V ^8  d   QhRR/# )r&   r/   r   r1   )r2   s   "r3   r4   r5     s     . .5 .r6   c                4    \        V P                  4       4      # )z)Export current state as a string of bytes)r   r   ra   s   &r3   	to_string_CommonFile.to_string  s    $**,--r6   c                   V ^8  d   QhRR/# )r&   r/   zIterator[Any]r1   )r2   s   "r3   r4   r5     s     T T] Tr6   c              #  L  "   V P                   p \        V4      pV P                   Fc  w  r4V\        8X  d   Vx  K  V\        8X  g   Q h\        RV4      pWA9  d   K7  V P                  WAV,          4      x   VP                  V4       Ke  	   V'       d   Q RV: 24       hR# 5i)z#iterator yielding lines of databaser"   z%failed to write all records: missing=N)r<   setr=   r   r!   r   _render_recordremove)r?   r   pendingactioncontents   &    r3   r   _CommonFile._iter_lines  s      --'lG#||OF!(((!7
 ) ))'73CDDNN7+%  ,&  S"G{ SS;ws   BB$B$c                    \        R4      h)z,given key/value pair, encode as line of filer   r   )r?   r   rd   s   &&&r3   r   _CommonFile._render_record;  s    !"EFFr6   c                    V ^8  d   QhRRRR/# )r&   userrD   r/   r   r1   )r2   s   "r3   r4   r5   ?  s     0 0 0 0r6   c                &    V P                  VR4      # )z)user-specific wrapper for _encode_field()r   _encode_fieldr?   r   s   &&r3   _encode_user_CommonFile._encode_user?  s    !!$//r6   c                    V ^8  d   QhRRRR/# )r&   realmrD   r/   r   r1   )r2   s   "r3   r4   r5   C  s     2 2 2	2r6   c                &    V P                  VR4      # )z*realm-specific wrapper for _encode_field()r   r   r?   r   s   &&r3   _encode_realm_CommonFile._encode_realmC  s     !!%11r6   c                    V ^8  d   QhRRRR/# )r&   rd   rD   r/   r   r1   )r2   s   "r3   r4   r5   I  s      ; % r6   c                   \        V\        4      '       d   VP                  V P                  4      pM!\        V\        4      '       g   \        W4      h\        V4      ^8  d   \        V RV: 24      h\        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      '       d   \        V RV: 24      hV# )a  convert field to internal representation.

internal representation is always bytes. byte strings are left as-is,
unicode strings encoding using file's default encoding (or ``utf-8``
if no encoding has been specified).

:raises UnicodeEncodeError:
    if unicode value cannot be encoded using default encoding.

:raises ValueError:
    if resulting byte string contains a forbidden character,
    or is too long (>255 bytes).

:returns:
    encoded identifer as bytes
z! must be at most 255 characters: c              3  2   "   T F  q\         9   x  K  	  R # 5ir`   )_INVALID_FIELD_CHARS).0cs   & r3   	<genexpr>,_CommonFile._encode_field.<locals>.<genexpr>a  s     8%Q((%   TFz contains invalid characters: )	
isinstancer-   encoder,   r   r   lenr9   any)r?   rd   params   &&&r3   r   _CommonFile._encode_fieldI  s    " eS!!LL/EE5))%e33u:w&GyQRR38%83338%888w&DUINOOr6   c                    V ^8  d   QhRRRR/# )r&   rd   r   r/   zbytes | strr1   )r2   s   "r3   r4   r5   e  s      5 [ r6   c                    \        V\        4      '       g   Q R4       hV P                  '       d   VP                  V P                  4      # V# )a  decode field from internal representation to format
returns by users() method, etc.

:raises UnicodeDecodeError:
    if unicode value cannot be decoded using default encoding.
    (usually indicates wrong encoding set for file).

:returns:
    field as str or bytes, as appropriate.
zexpected value to be bytes)r   r   r.   decoder,   rg   s   &&r3   _decode_field_CommonFile._decode_fielde  sA     %''E)EE'<<..r6   )r;   r:   r<   r=   r+   r,   r.   )NFFrT   Tr`   )field)rY   
__module____qualname____firstlineno____doc__r@   classmethodrJ   rO   r\   propertyr'   setterrk   rr   r>   rG   rx   r   r   r   r   r   r   r   r   r   r   r   __static_attributes__r1   r6   r3   r$   r$   6   s    :"H      D   
[[ 
  *I
*XG
.T>G028 r6   r$   zset[str]_warn_no_bcryptc            	        R p R F#  p\         P                  ! V4      '       g   K!  Tp  M	  \         P                  ! R4      '       d   RMR p\        P	                  4        V'       g   \        P                  . R	O4       \        T;'       g    RRT;'       g    T ;'       g    RT ;'       g    RT;'       g    RRR7      pVP                  VR,          VR,          R7       V# )
Nbcryptsha256_cryptportable_apache_24host_apache_24apr_md5_crypt)r   portable_apache_22r   host_apache_22linux_apache_24linux_apache_22)portablehost)r   r   )r   r   r   r   r   )r   has_os_crypt_supporthas_backendr   clearupdatedict)	host_bestnamer   defaultss       r3   _init_default_schemesr     s    I*((..I + "--h77XTF	
 !44_*====o 33O00.&
H OO./&'   Or6   c                     . ROp V P                  \        P                  ! 4       4       V R,          R.,           V ,           p\        \	        V 4      VP
                  R7      p \        V \        R,          RR7      # )r   r   :N   N)r   r   2y)schemesdefaultbcrypt__ident)r   r   sha512_crypt	des_cryptr   	ldap_sha1	plaintext)extendr   get_supported_os_crypt_schemessortedr   indexr   htpasswd_defaults)r   	preferreds     r3   _init_htpasswd_contextr
    sj    G( NN8::<= //'9IS\y7G !"67 r6   c                  l   a  ] tR tRtRtRR]3V 3R lltR tR tR R lt	R	 t
R
 tR tR tR tRtV ;t# )r   i  a]  class for reading & writing Htpasswd files.

The class constructor accepts the following arguments:

:type path: filepath
:param path:

    Specifies path to htpasswd file, use to implicitly load from and save to.

    This class has two modes of operation:

    1. It can be "bound" to a local file by passing a ``path`` to the class
       constructor. In this case it will load the contents of the file when
       created, and the :meth:`load` and :meth:`save` methods will automatically
       load from and save to that file if they are called without arguments.

    2. Alternately, it can exist as an independant object, in which case
       :meth:`load` and :meth:`save` will require an explicit path to be
       provided whenever they are called. As well, ``autosave`` behavior
       will not be available.

       This feature is new in Passlib 1.6, and is the default if no
       ``path`` value is provided to the constructor.

    This is also exposed as a readonly instance attribute.

:type new: bool
:param new:

    Normally, if *path* is specified, :class:`HtpasswdFile` will
    immediately load the contents of the file. However, when creating
    a new htpasswd file, applications can set ``new=True`` so that
    the existing file (if any) will not be loaded.

    .. versionadded:: 1.6
        This feature was previously enabled by setting ``autoload=False``.
        That alias was removed in Passlib 1.8

:type autosave: bool
:param autosave:

    Normally, any changes made to an :class:`HtpasswdFile` instance
    will not be saved until :meth:`save` is explicitly called. However,
    if ``autosave=True`` is specified, any changes made will be
    saved to disk immediately (assuming *path* has been set).

    This is also exposed as a writeable instance attribute.

:type encoding: str
:param encoding:

    Optionally specify character encoding used to read/write file
    and hash passwords. Defaults to ``utf-8``, though ``latin-1``
    is the only other commonly encountered encoding.

    This is also exposed as a readonly instance attribute.

:type default_scheme: str
:param default_scheme:
    Optionally specify default scheme to use when encoding new passwords.

    This can be any of the schemes with builtin Apache support,
    OR natively supported by the host OS's :func:`crypt.crypt` function.

    * Builtin schemes include ``"bcrypt"`` (apache 2.4+), ``"apr_md5_crypt"`,
      and ``"des_crypt"``.

    * Schemes commonly supported by Unix hosts
      include ``"bcrypt"``, ``"sha256_crypt"``, and ``"des_crypt"``.

    In order to not have to sort out what you should use,
    passlib offers a number of aliases, that will resolve
    to the most appropriate scheme based on your needs:

    * ``"portable"``, ``"portable_apache_24"`` -- pick scheme that's portable across hosts
      running apache >= 2.4. **This will be the default as of Passlib 2.0**.

    * ``"portable_apache_22"`` -- pick scheme that's portable across hosts
      running apache >= 2.4. **This is the default up to Passlib 1.9**.

    * ``"host"``, ``"host_apache_24"`` -- pick strongest scheme supported by
       apache >= 2.4 and/or host OS.

    * ``"host_apache_22"`` -- pick strongest scheme supported by
       apache >= 2.2 and/or host OS.

    .. versionadded:: 1.6
        This keyword was previously named ``default``. That alias
        was removed in Passlib 1.8.

    .. versionchanged:: 1.6.3

        Added support for ``"bcrypt"``, ``"sha256_crypt"``, and ``"portable"`` alias.

    .. versionchanged:: 1.7

        Added apache 2.4 semantics, and additional aliases.

:type context: :class:`~passlib.context.CryptContext`
:param context:
    :class:`!CryptContext` instance used to create
    and verify the hashes found in the htpasswd file.
    The default value is a pre-built context which supports all
    of the hashes officially allowed in an htpasswd file.

    This is also exposed as a readonly instance attribute.

    .. warning::

        This option may be used to add support for non-standard hash
        formats to an htpasswd file. However, the resulting file
        will probably not be usable by another application,
        and particularly not by Apache.

Loading & Saving
================
.. automethod:: load
.. automethod:: load_if_changed
.. automethod:: load_string
.. automethod:: save
.. automethod:: to_string

Inspection
================
.. automethod:: users
.. automethod:: check_password
.. automethod:: get_hash

Modification
================
.. automethod:: set_password
.. automethod:: delete

Alternate Constructors
======================
.. automethod:: from_string

Attributes
==========
.. attribute:: path

    Path to local file that will be used as the default
    for all :meth:`load` and :meth:`save` operations.
    May be written to, initialized by the *path* constructor keyword.

.. attribute:: autosave

    Writeable flag indicating whether changes will be automatically
    written to *path*.

Errors
======
:raises ValueError:
    All of the methods in this class will raise a :exc:`ValueError` if
    any user name contains a forbidden character (one of ``:\r\n\t\x00``),
    or is longer than 255 characters.
Nc                	   < V'       dQ   V\         9   d   \        R V: 2\        P                  4       \        P                  W"4      pVP                  VR7      pW0n        \        SV `$  ! V3/ VB  R# )zNHtpasswdFile: no bcrypt backends available, using fallback for default scheme )r   N)
r   r   r   PasslibSecurityWarningr  getcopycontextsuperr@   )r?   r'   default_schemer  rM   rX   s   &&&&,r3   r@   HtpasswdFile.__init__  sk     099G8JL..
 /22>RNll>l:G&&r6   c                	    VP                  4       P                  \        4      p\        V4      ^8w  d   \	        RV,          4      hV# )r&   z/malformed htpasswd file (error reading line %d)r   split_BCOLONr   r9   )r?   r    r   results   &&& r3   r   HtpasswdFile._parse_record  s;    &&w/v;!NQWWXXr6   c                	    \        R W4      # )z%s:%s
r   )r?   r   hashs   &&&r3   r   HtpasswdFile._render_record  s    It22r6   c                   V ^8  d   QhRR/# )r&   r/   zlist[bytes | str]r1   )r2   s   "r3   r4   HtpasswdFile.__annotate__  s     D D( Dr6   c                `    V P                    Uu. uF  qP                  V4      NK  	  up# u upi )z&
Return list of all users in database
)r<   r   r   s   & r3   usersHtpasswdFile.users  s)     6:]]C]T""4(]CCCs   +c                Z    V P                   P                  V4      pV P                  W4      # )aL  Set password for user; adds user if needed.

:returns:
    * ``True`` if existing user was updated.
    * ``False`` if user account was added.

.. versionchanged:: 1.6
    This method was previously called ``update``, it was renamed
    to prevent ambiguity with the dictionary method.
    The old alias was removed in Passlib 1.8.
)r  r  set_hash)r?   r   passwordr  s   &&& r3   set_passwordHtpasswdFile.set_password  s'     ||  *}}T((r6   c                l     V P                   V P                  V4      ,          #   \         d     R# i ; i)zReturn hash stored for user, or ``None`` if user not found.

.. versionchanged:: 1.6
    This method was previously named ``find``, it was renamed
    for clarity. The old name was removed in Passlib 1.8.
N)r<   r   KeyErrorr   s   &&r3   get_hashHtpasswdFile.get_hash  s3    	==!2!24!899 		s   !$ 33c                    \        V\        4      '       d   VP                  V P                  4      pV P	                  V4      pV P                  W4      pV P                  4        V# )z
semi-private helper which allows writing a hash directly;
adds user if needed.

.. warning::
    does not (currently) do any validation of the hash string

.. versionadded:: 1.7
)r   r-   r   r,   r   r   r   )r?   r   r  r   s   &&& r3   r$  HtpasswdFile.set_hash  sR     dC  ;;t}}-D  &##D/r6   c                     V P                   V P                  V4       T P                  4        R#   \         d     R# i ; i)zcDelete user's entry.

:returns:
    * ``True`` if user deleted.
    * ``False`` if user not found.
FT)r<   r   r)  r   r   s   &&r3   deleteHtpasswdFile.delete  sA    	d//56 	  		s   0 ??c                ~   V P                  V4      pV P                  P                  V4      pVf   R# \        V\        4      '       d   VP                  V P                  4      pV P                  P                  W#4      w  rEV'       d5   Ve1   WP                  9   g   Q hWPP                  V&   V P                  4        V# )a  
Verify password for specified user.
If algorithm marked as deprecated by CryptContext, will automatically be re-hashed.

:returns:
    * ``None`` if user not found.
    * ``False`` if user found, but password does not match.
    * ``True`` if user found and password matches.

.. versionchanged:: 1.6
    This method was previously called ``verify``, it was renamed
    to prevent ambiguity with the :class:`!CryptContext` method.
    The old alias was removed in Passlib 1.8.
N)
r   r<   r  r   r-   r   r,   r  verify_and_updater   )r?   r   r%  r  oknew_hashs   &&&   r3   check_passwordHtpasswdFile.check_password  s       &}}  &<h$$  t}}5H||55hE(&==((("*MM$NN	r6   )r  )rY   r   r   r   r   htpasswd_contextr@   r   r   r!  r&  r*  r$  r/  r5  r   __classcell__rX   s   @r3   r   r     sG    \B 6F'3D$)
& r6   c                     a  ] tR tRtRtRtRV 3R lltR tR tR t	R t
R	 tR
 tRR ltR]3R ltRR ltR]3R ltRR ltR tR]3R ltRtV ;t# )r   i  a  class for reading & writing Htdigest files.

The class constructor accepts the following arguments:

:type path: filepath
:param path:

    Specifies path to htdigest file, use to implicitly load from and save to.

    This class has two modes of operation:

    1. It can be "bound" to a local file by passing a ``path`` to the class
       constructor. In this case it will load the contents of the file when
       created, and the :meth:`load` and :meth:`save` methods will automatically
       load from and save to that file if they are called without arguments.

    2. Alternately, it can exist as an independant object, in which case
       :meth:`load` and :meth:`save` will require an explicit path to be
       provided whenever they are called. As well, ``autosave`` behavior
       will not be available.

       This feature is new in Passlib 1.6, and is the default if no
       ``path`` value is provided to the constructor.

    This is also exposed as a readonly instance attribute.

:type default_realm: str
:param default_realm:

    If ``default_realm`` is set, all the :class:`HtdigestFile`
    methods that require a realm will use this value if one is not
    provided explicitly. If unset, they will raise an error stating
    that an explicit realm is required.

    This is also exposed as a writeable instance attribute.

    .. versionadded:: 1.6

:type new: bool
:param new:

    Normally, if *path* is specified, :class:`HtdigestFile` will
    immediately load the contents of the file. However, when creating
    a new htpasswd file, applications can set ``new=True`` so that
    the existing file (if any) will not be loaded.

    .. versionadded:: 1.6
        This feature was previously enabled by setting ``autoload=False``.
        That alias was removed in Passlib 1.8

:type autosave: bool
:param autosave:

    Normally, any changes made to an :class:`HtdigestFile` instance
    will not be saved until :meth:`save` is explicitly called. However,
    if ``autosave=True`` is specified, any changes made will be
    saved to disk immediately (assuming *path* has been set).

    This is also exposed as a writeable instance attribute.

:type encoding: str
:param encoding:

    Optionally specify character encoding used to read/write file
    and hash passwords. Defaults to ``utf-8``, though ``latin-1``
    is the only other commonly encountered encoding.

    This is also exposed as a readonly instance attribute.

Loading & Saving
================
.. automethod:: load
.. automethod:: load_if_changed
.. automethod:: load_string
.. automethod:: save
.. automethod:: to_string

Inspection
==========
.. automethod:: realms
.. automethod:: users
.. automethod:: check_password(user[, realm], password)
.. automethod:: get_hash

Modification
============
.. automethod:: set_password(user[, realm], password)
.. automethod:: delete
.. automethod:: delete_realm

Alternate Constructors
======================
.. automethod:: from_string

Attributes
==========
.. attribute:: default_realm

    The default realm that will be used if one is not provided
    to methods that require it. By default this is ``None``,
    in which case an explicit realm must be provided for every
    method call. Can be written to.

.. attribute:: path

    Path to local file that will be used as the default
    for all :meth:`load` and :meth:`save` operations.
    May be written to, initialized by the *path* constructor keyword.

.. attribute:: autosave

    Writeable flag indicating whether changes will be automatically
    written to *path*.

Errors
======
:raises ValueError:
    All of the methods in this class will raise a :exc:`ValueError` if
    any user name or realm contains a forbidden character (one of ``:\r\n\t\x00``),
    or is longer than 255 characters.
Nc                	6   < W n         \        SV `  ! V3/ VB  R # r`   )default_realmr  r@   )r?   r'   r<  rM   rX   s   &&&,r3   r@   HtdigestFile.__init__  s    *&&r6   c                	    VP                  4       P                  \        4      p\        V4      ^8w  d   \	        RV,          4      hVw  rEpWE3V3# )r   z/malformed htdigest file (error reading line %d)r  )r?   r    r   r  r   r   r  s   &&&    r3   r   HtdigestFile._parse_record  sM    &&w/v;!NQWWXX"T}d""r6   c                	$    Vw  r4\        R W4V4      # )z	%s:%s:%s
r  )r?   r   r  r   r   s   &&&  r3   r   HtdigestFile._render_record  s    L$t<<r6   c                	D    Vf   V P                   pVf   \        R4      hV# )NzGyou must specify a realm explicitly, or set the default_realm attribute)r<  r8   r   s   &&r3   _require_realmHtdigestFile._require_realm  s0    =&&E}9  r6   c                	H    V P                  V4      pV P                  VR 4      # )r   )rC  r   r   s   &&r3   r   HtdigestFile._encode_realm  s%    ##E*!!%11r6   c                	F    V P                  V4      V P                  V4      3# r`   )r   r   )r?   r   r   s   &&&r3   _encode_keyHtdigestFile._encode_key  s#      &(:(:5(AAAr6   c                    \        R V P                   4       4      pV Uu. uF  q P                  V4      NK  	  up# u upi )z%Return list of all realms in databasec              3  2   "   T F  q^,          x  K  	  R# 5i)   Nr1   )r   r   s   & r3   r   &HtdigestFile.realms.<locals>.<genexpr>  s     5}VV}r   )r   r<   r   )r?   realmsr   s   &  r3   rN  HtdigestFile.realms  s7    5t}}557=>ve""5)v>>>s   =c                    V P                  V4      pV P                   Uu. uF*  q"^,          V8X  g   K  V P                  V^ ,          4      NK,  	  up# u upi )zReturn list of all users in specified realm.

* uses ``self.default_realm`` if no realm explicitly provided.
* returns empty list if realm not found.
)r   r<   r   )r?   r   r   s   && r3   r!  HtdigestFile.users  sK     ""5)6:mmWms1vQV*""3q6*mWWWs
   AAc                    V\         J d   RTr2V P                  V4      p\        P                  ! W1W P                  R7      pV P                  WV4      # )a_  Set password for user; adds user & realm if needed.

If ``self.default_realm`` has been set, this may be called
with the syntax ``set_password(user, password)``,
otherwise it must be called with all three arguments:
``set_password(user, realm, password)``.

:returns:
    * ``True`` if existing user was updated
    * ``False`` if user account added.
Nr,   )_UNSETrC  r   r  r,   r$  r?   r   r   r%  r  s   &&&& r3   r&  HtdigestFile.set_password  sH     v"E8##E*}}XU]]K}}T$//r6   c                    V P                  W4      pV P                  P                  V4      pVf   R# VP                  V P                  4      # )a=  Return :class:`~passlib.hash.htdigest` hash stored for user.

* uses ``self.default_realm`` if no realm explicitly provided.
* returns ``None`` if user or realm not found.

.. versionchanged:: 1.6
    This method was previously named ``find``, it was renamed
    for clarity. The old name is was removed Passlib 1.8.
N)rH  r<   r  r   r,   )r?   r   r   r   r  s   &&&  r3   r*  HtdigestFile.get_hash  sC     t+}}  %<{{4==))r6   c                    V\         J d   RTr2\        V\        4      '       d   VP                  V P                  4      pV P                  W4      pV P                  WC4      pV P                  4        V# )ax  
semi-private helper which allows writing a hash directly;
adds user & realm if needed.

If ``self.default_realm`` has been set, this may be called
with the syntax ``set_hash(user, hash)``,
otherwise it must be called with all three arguments:
``set_hash(user, realm, hash)``.

.. warning::
    does not (currently) do any validation of the hash string

.. versionadded:: 1.7
N)rT  r   r-   r   r,   rH  r   r   )r?   r   r   r  r   r   s   &&&&  r3   r$  HtdigestFile.set_hash  s`     6>4dC  ;;t}}-Dt+##C.r6   c                    V P                  W4      p V P                  V T P                  4        R#   \         d     R# i ; i)zDelete user's entry for specified realm.

if realm is not specified, uses ``self.default_realm``.

:returns:
    * ``True`` if user deleted,
    * ``False`` if user not found in realm.
FT)rH  r<   r)  r   )r?   r   r   r   s   &&& r3   r/  HtdigestFile.delete  sH     t+	c" 	  		s   2 A Ac                    V P                  V4      pV P                  pV Uu. uF  q3^,          V8X  g   K  VNK  	  ppV F  pW# K  	  V P                  4        \        V4      # u upi )zDelete all users for specified realm.

if realm is not specified, uses ``self.default_realm``.

:returns: number of users deleted (0 if realm not found)
)r   r<   r   r   )r?   r   r   r   keyss   &&   r3   delete_realmHtdigestFile.delete_realm+  sc     ""5)--&:wa&E/w:C 4y	 ;s
   A$A$c                    V\         J d   RTr2V P                  V4      pV P                  V4      pV P                  P	                  W34      pVf   R# \
        P                  ! W4WV P                  R7      # )ak  Verify password for specified user + realm.

If ``self.default_realm`` has been set, this may be called
with the syntax ``check_password(user, password)``,
otherwise it must be called with all three arguments:
``check_password(user, realm, password)``.

:returns:
    * ``None`` if user or realm not found.
    * ``False`` if user found, but password does not match.
    * ``True`` if user found and password matches.

.. versionchanged:: 1.6
    This method was previously called ``verify``, it was renamed
    to prevent ambiguity with the :class:`!CryptContext` method.
    The old alias was removed in Passlib 1.8.
NrS  )rT  r   r   r<   r  r   verifyr,   rU  s   &&&& r3   r5  HtdigestFile.check_password:  sh    $ v"E8  &""5)}}  $/<xtT]]SSr6   )r<  )NNr`   )rY   r   r   r   r   r<  r@   r   r   rC  r   rH  rN  r!  rT  r&  r*  r$  r/  r_  r5  r   r8  r9  s   @r3   r   r     sv    xD M'#=2B?
XB (,f 0&*  $(f 6" *. T Tr6   )>__conditional_annotations__r   
__future__r   rp   ior   r   typingr   r   r   r   r	   r
   r   warningsr   passlib._loggingr   collections.abcr   r   typing_extensionsr   passlibr   r   passlib.contextr   passlib.excr   passlib.hashr   passlib.utilsr   r   r   passlib.utils.compatr   __all__objectrT  r  r   r   r   __annotations__r!   r"   tupler   _SourceTypesr$   r   r   r   r  r
  r7  r   r   )rd  s   @r3   <module>rw     sC    # 	   M M M  #2& ! ( + ! @ @ + 
 

	 &   )
 (%	 %m$gi %'(gh,-	/L
 L}'+& }j
  E !*\ *+ #N *+ e;u% eP	CT;uUE\23 CTr6   