
    ͆h/                       S r SSKJr  SSKrSSKrSSKrSSKrSSKrSSKrSSK	r	SSK
r
SSKJr  SSKJrJr  SSKJr  SSKJrJrJrJrJr  SSKJr  \	R2                  S	:  a	  SS
KJrJr  OSS
KJrJr  SSKJr  SSK J!r!J"r"  \(       a  SSK#J$r$  \" S5      r%\RL                  " \'5      r(Sr)SS.S6S jjr*S7S jr+S8S jr,\	R2                  S:  a  \-R\                  r/OS9S jr/S:S jr0\	R2                  S	:  a  SSK1J2r2  O
S S.S;S jjr2S<S jr3S=S jr4S>S jr5S?S jr6\Rn                  " S5      r8S?S  jr9\Rt                  " SS!9S@S" j5       r;SAS# jr<SBSCS$ jjr=\Rt                  " SS!9SDS% j5       r> SB       SES& jjr?S' r@SFS( jrA\Rt                  " SS!9SGS) j5       rBSHS* jrCSIS+ jrDSJS, jrES- rFS. rG " S/ S05      rH " S1 S2\R                  5      rJ " S3 S45      rKSKS5 jrLg)Lz
Standalone file utils.

Nothing in this module should have an knowledge of config or the layout
and structure of the site and pages in the site.
    )annotationsN)defaultdict)datetimetimezone)PurePath)TYPE_CHECKING
CollectionIterableMutableSequenceTypeVar)urlsplit)   
   )
EntryPointentry_points)
exceptions)get_yaml_loader	yaml_load)PageT)z	.markdownz.mdownz.mkdnz.mkdz.md)pagesc                    U (       aD  [        S U  5       5      n[        R                  " U5      R                  [        R
                  S9nO
[        5       n[        UR                  5       5      $ )z
Returns the number of seconds since the epoch for the latest updated page.

In reality this is just today's date because that's how pages' update time is populated.
c              3  8   #    U  H  oR                   v   M     g 7fN)update_date).0ps     M/opt/services/DDDS/venv/lib/python3.13/site-packages/mkdocs/utils/__init__.py	<genexpr>&get_build_timestamp.<locals>.<genexpr>7   s     7A--s   )tzinfo)	maxr   fromisoformatreplacer   utcget_build_datetimeint	timestamp)r   date_stringdts      r   get_build_timestampr+   /   sR     777##K0888M!r||~    c                     [         R                  R                  S5      n U c$  [        R                  " [
        R                  5      $ [        R                  " [        U 5      [
        R                  5      $ )z
Returns an aware datetime object.

Support SOURCE_DATE_EPOCH environment variable for reproducible builds.
See https://reproducible-builds.org/specs/source-date-epoch/
SOURCE_DATE_EPOCH)	osenvirongetr   nowr   r%   fromtimestampr'   )source_date_epochs    r   r&   r&   >   sN     

':; ||HLL))!!#&7"8(,,GGr,   c                 4    [        5       R                  S5      $ )z
Returns the displayable date string.

Support SOURCE_DATE_EPOCH environment variable for reproducible builds.
See https://reproducible-builds.org/specs/source-date-epoch/
z%Y-%m-%d)r&   strftime r,   r   get_build_dater8   L   s     ((44r,   )r   	   c                ^    U(       a%  U R                  U5      (       a  U S [        U5      *  $ U $ r   )endswithlen)ssuffixs     r   _removesuffixr?   Z   s+    ajj((^F|$$r,   c                >    [        [        R                  U 5      5      $ )z4Reduce duplicate items in a list and preserve order.)listdictfromkeys)data_sets    r   reduce_listrE   `   s    h'((r,   )insortc                    U $ r   r7   )vs    r   <lambda>rI   i   s    Qr,   )keyc                   U" U5      n[        U 5      nUS:  a-  X2" XS-
     5      :  a  US-  nUS:  a  X2" XS-
     5      :  a  M  U R                  XA5        g )Nr      )r<   insert)axrJ   kxis        r   rF   rF   i   sZ    VF!eSq5]*FA !eSq5]*	r,   c                Z   [         R                  R                  U5      n[         R                  " USS9  [         R                  R	                  U5      (       a=  [         R                  R                  U[         R                  R                  U 5      5      n[        R                  " X5        g)zq
Copy source_path to output_path, making sure any parent directories exist.

The output_path may be a directory.
Texist_okN)	r/   pathdirnamemakedirsisdirjoinbasenameshutilcopyfile)source_pathoutput_path
output_dirs      r   	copy_filer`   q   sf     -JKK
T*	ww}}[!!ggll;0@0@0MN
OOK-r,   c                    [         R                  R                  U5      n[         R                  " USS9  [	        US5       nUR                  U 5        SSS5        g! , (       d  f       g= f)zGWrite content to output_path, making sure any parent directories exist.TrS   wbN)r/   rU   rV   rW   openwrite)contentr^   r_   fs       r   
write_filerg   ~   sF    -JKK
T*	k4	 A	 
!	 	 s   A
A*c                   [         R                  R                  U 5      (       d  g[         R                  " U 5       H  nUR	                  S5      (       a  M  [         R                  R                  X5      n[         R                  R                  U5      (       a  [        R                  " US5        Mw  [         R                  " U5        M     g)zKRemove the content of a directory recursively but not the directory itself.N.T)
r/   rU   existslistdir
startswithrY   rX   r[   rmtreeunlink)	directoryentryrU   s      r   clean_directoryrq      s    77>>)$$I& C  ww||I-77==MM$%IIdO 'r,   c                ,    U R                  [        5      $ )z
Return True if the given file path is a Markdown file.

https://superuser.com/questions/249436/file-extension-for-markdown-files
)r;   markdown_extensionsrU   s    r   is_markdown_fileru      s     ==,--r,   z^\d{3}\.html?$c                >    [        [        R                  U 5      5      $ )z=Return True if the given file path is an HTTP error template.)bool_ERROR_TEMPLATE_REmatchrt   s    r   is_error_templaterz      s    "((.//r,   )maxsizec                    U R                  S5      (       d  SU -   n [        R                  " U 5      SS  n U (       a  U R                  S5      $ / $ )N/rL   )rl   	posixpathnormpathsplitrt   s    r   _norm_partsr      sF    ??3Tzd#AB'D"4::c?**r,   c                F   UR                  S5      u  p#nSU;   a  Un[        U5      n[        U 5      nSn[        XV5       H  u  pX:w  a    O	US-  nM     S/[        U5      U-
  -  XgS -   n
SR	                  U
5      =(       d    SnU R                  S5      (       a  US-   $ U$ )a  
Return given url relative to other.

Both are operated as slash-separated paths, similarly to the 'path' part of a URL.
The last component of `other` is skipped if it contains a dot (considered a file).
Actual URLs (with schemas etc.) aren't supported. The leading slash is ignored.
Paths are normalized ('..' works as parent directory), but going higher than the
root has no effect ('foo/../../bar' ends up just as 'bar').
r}   ri   r   rL   z..N)
rpartitionr   zipr<   rY   r;   )urlotherrV   _rZ   other_parts
dest_partscommonrN   b	rel_partsrelurls               r   get_relative_urlr      s     !++C0G
he$KS!JFK,6! -
 #k*V34z'7JJIXXi 'CF<<,,6C<8&8r,   c                    [        U 5      u  pUS:X  a  U $ Ub%  [        XR                  5      nUS:  a  SU-  U-   nU$ [        R                  " X 5      $ )z:Return a URL relative to the given page or using the base.r   ../)_get_norm_urlr   r   r~   rY   )rU   pagebaserelative_levelresults        r   normalize_urlr      s[    (.D!$1A^+f4F>>$%%r,   c                   U (       d  Sn O1SU ;   a+  [         R                  SU  S35        U R                  SS5      n [        U 5      nUR                  (       d'  UR
                  (       d  U R                  S5      (       a  U S4$ [        R                  " U 5      S-   nSnUR                  S	US
-  5      (       a!  US-  nUR                  S	US
-  5      (       a  M!  X4$ )Nri   \zPath 'zh' uses OS-specific separator '\'. That will be unsupported in a future release. Please change it to '/'.r}   )r}   #r   r   r   r   rL   )	logwarningr$   r   schemenetlocrl   r~   r   )rU   parsednormr   s       r   r   r      s    	TF U V	
 ||D#&d^F}})D)DRx d#c)DN
//%!!3
4
4! //%!!3
4
4r,   c                F    U  Vs/ s H  n[        X1U5      PM     sn$ s  snf )Soft-deprecated, do not use.)r   )	path_listr   r   rU   s       r   create_media_urlsr      s$     9BB	M$d+	BBBs   c                \    [         R                  " S[        5        U R                  SS5      $ )Nz=path_to_url is never used in MkDocs and will be removed soon.r   r}   )warningswarnDeprecationWarningr$   rt   s    r   path_to_urlr      s'    MMGI[ <<c""r,   c                    [        5       U    n[        R                  R                  [        R                  R	                  UR                  5       R                  5      5      $ )z3Return the directory of an installed theme by name.)
get_themesr/   rU   rV   abspathload__file__)namethemes     r   get_theme_dirr      s:    LE77??277??5::<+@+@ABBr,   c                    0 n [         R                  [        SS95      nU Vs1 s H9  o"R                  c  M  UR                  R                  S:X  d  M-  UR                  iM;     nnU GH  nUR                  c   eUR                  U;   aU  UR                  R                  S:w  a;  [
        R                  " SUR                   SUR                  R                   S35      eUR                  U ;   a{  XR                     R                  nUc   e[        R                  SUR                   SUR                  R                   S	UR                   S
UR                  R                   S3	5        X@UR                  '   GM     U $ s  snf )z<Return a dict of all installed themes as {name: EntryPoint}.zmkdocs.themes)groupmkdocszThe theme 'z&' is a builtin theme but the package 'z1' attempts to provide a theme with the same name.zA theme named 'z&' is provided by the Python packages 'z' and 'z'. The one in 'z' will be used.)	rB   rC   r   distr   r   ConfigurationErrorr   r   )themesepsepbuiltinsr   
other_dists         r   r   r     s[    %'F"&--?0S"TC"%Z#BQYAY#HZzz%%%::!ejjoo&A//ejj\)OPUPZPZP_P_O` aB B  ZZ6!

+00J)))KK!%**-STYT^T^TcTcSd e"(

7HY
 #uzz! $ M) [s   E?E?E?c                 2    [        5       R                  5       $ )z.Return a list of all installed themes by name.)r   keysr7   r,   r   get_theme_namesr   "  s    <r,   c                    U nUR                  SS5      R                  SS5      nUR                  5       U:X  a  UR                  5       nU$ )z2Return a page tile obtained from a directory name.- r   )r$   lower
capitalize)rV   titles     r   dirname_to_titler   '  sE    EMM#s#++C5E{{}  "Lr,   c                0   U R                  SS5      R                  SS5      R                  S5      nU(       a^  UR                  S5      R                  5       nUR                  5       (       d  M=  UR	                  S5      (       d  gUR                  S5      $ g)r   z

r   z# N)r$   r   popstriprl   lstrip)markdown_srclineslines      r   get_markdown_titler   2  sw      .66tTBHHNE
yy|!!#zz||t$${{4  r,   c                    U  H%  n[        U[        5      (       d  M  X;   d  M!  X!   s  $    / nX0nU R                  U5        U$ )z
Given a list, look for dictionary with a key matching key and return it's
value. If it doesn't exist, create it with the value of an empty list and
return that.
)
isinstancerB   append)branchrJ   node
new_branchs       r   find_or_create_noder   ?  sL     $%%;9  JD
MM$r,   c                    / nU  HT  n[        U5      R                  R                  nUnU H  n[        U5      n[	        XE5      nM     UR                  U5        MV     U$ )z_
Given a list of paths, convert them into a nested structure that will match
the pages config.
)r   parentpartsr   r   r   )pathsnestedrU   r   r   parts         r   
nest_pathsr   R  s`    
 F%%++D#D)D(6F  	d  Mr,   c                  ,    \ rS rSrSrSS jrSS jrSrg)	DuplicateFilterif  z!Avoid logging duplicate messages.c                "    [        5       U l        g r   )setmsgs)selfs    r   __init__DuplicateFilter.__init__i  s    !e	r,   c                    UR                   U R                  ;  nU R                  R                  UR                   5        U$ r   )msgr   addr   recordrvs      r   __call__DuplicateFilter.__call__l  s-    ZZtyy(		fjj!	r,   )r   NreturnNone)r   zlogging.LogRecordr   rw   )__name__
__module____qualname____firstlineno____doc__r   r   __static_attributes__r7   r,   r   r   r   f  s    +$r,   r   c                  @   ^  \ rS rSrSrSU 4S jjrS rSS jrSrU =r	$ )	CountHandlerir  z$Counts all logged messages >= level.c                N   > [        [        5      U l        [        TU ]  " S0 UD6  g )Nr7   )r   r'   countssuperr   )r   kwargs	__class__s     r   r   CountHandler.__init__u  s    &1#&6"6"r,   c                x    U R                  U5      nU(       a!  U R                  UR                  ==   S-  ss'   U$ )NrL   )filterr   levelnor   s      r   handleCountHandler.handley  s0    [[ KK'1,'	r,   c                    [        U R                  R                  5       SS9 VVs/ s H  u  p[        R                  " U5      U4PM     snn$ s  snnf )NT)reverse)sortedr   itemslogginggetLevelName)r   krH   s      r   
get_countsCountHandler.get_counts  sC    9?@Q@Q@S]a9bc9b%%a(!,9bcccs   $A)r   r   )r   zlist[tuple[str, int]])
r   r   r   r   r   r   r  r  r   __classcell__)r   s   @r   r   r   r  s    .#d dr,   r   c                  (    \ rS rSrSrS rSS jrSrg)weak_propertyi  zHSame as a read-only property, but allows overwriting the field for good.c                2    Xl         UR                  U l        g r   )funcr   )r   r  s     r   r   weak_property.__init__  s    	||r,   Nc                .    Uc  U $ U R                  U5      $ r   )r  )r   instanceowners      r   __get__weak_property.__get__  s    Kyy""r,   )r   r  r   )r   r   r   r   r   r   r  r   r7   r,   r   r  r    s    R$#r,   r  c                    U S:X  a0  [         R                  " S[        5        [        R                  " 5       $ [        S[        < SU < 35      e)Nwarning_filterzwarning_filter doesn't do anything since MkDocs 1.2 and will be removed soon. All messages on the `mkdocs` logger get counted automatically.zmodule z has no attribute )r   r   r   r  FilterAttributeErrorr   )r   s    r   __getattr__r    sH    M	

 ~~
78,.@I
JJr,   )r   zCollection[Page] | Noner   r'   )r   r   )r   str)r=   r  r>   r  r   r  )rD   zIterable[T]r   zlist[T])rN   zMutableSequence[T]rO   r   r   r   )r]   r  r^   r  r   r   )re   bytesr^   r  r   r   )ro   r  r   r   )rU   r  r   rw   )rU   r  r   	list[str])r   r  r   r  r   r  )N )rU   r  r   Page | Noner   r  r   r  )rU   r  r   ztuple[str, int])r   zIterable[str]r   r!  r   r  r   r  )r   r  r   r  )r   zdict[str, EntryPoint])r   zCollection[str])rV   r  r   r  )r   r  r   z
str | None)r   r  )Mr   
__future__r   	functoolsr  r/   r~   rer[   sysr   collectionsr   r   r   pathlibr   typingr   r	   r
   r   r   urllib.parser   version_infoimportlib.metadatar   r   importlib_metadatar   r   mkdocs.utils.yamlr   r   mkdocs.structure.pagesr   r   	getLoggerr   r   rs   r+   r&   r8   r  removesuffixr?   rE   bisectrF   r`   rg   rq   ru   compilerx   rz   	lru_cacher   r   r   r   r   r   r   r   r   r   r   r   r   r   NullHandlerr   r  r  r7   r,   r   <module>r5     s   #   	  	  
  # '  P P !w;;;  8+CL!  =A H5 v$$M)
 w 4? 
.$. ZZ 12 0
 T"+ #+98& T"  # . EGCC$/C>ACC#C T" #6

&(	 	d7&& d$
# 
#	Kr,   