o
    Ì^½^9-  ã                   @   s€  d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	m	Z	m
Z
 ddlmZ ddlmZ e e¡Zg d¢Zejfdd„Zd	d
„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd@dd„Zdd„ Zd d!„ Z d"d#„ Z!e "d$¡Z#d%d&„ Z$d'd(„ Z%dAd*d+„Z&dAd,d-„Z'd.d/„ Z(d0d1„ Z)d2d3„ Z*d4d5„ Z+d6d7„ Z,d8d9„ Z-d:d;„ Z.d<d=„ Z/G d>d?„ d?ej0ƒZ1e1ƒ Z2dS )Bz’
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.
é    N)ÚdatetimeÚtimezone)Úurlparse)Ú
exceptions)z	.markdownz.mdownz.mkdnz.mkdz.mdc              	   C   s^   dd„ }G dd„ d|ƒ}|  d|¡ zt | |¡W t| dƒr#|  ¡  S S t| dƒr.|  ¡  w w )z—
    Wrap PyYaml's loader so we can extend it to suit our needs.

    Load all strings as unicode.
    https://stackoverflow.com/a/2967461/3609487
    c                 S   s
   |   |¡S )zi
        Override the default string handling function to always return
        unicode objects.
        )Úconstruct_scalar)ÚselfÚnode© r	   ú7/usr/lib/python3/dist-packages/mkdocs/utils/__init__.pyÚconstruct_yaml_str)   s   
z%yaml_load.<locals>.construct_yaml_strc                   @   s   e Zd ZdZdS )zyaml_load.<locals>.Loaderzu
        Define a custom loader derived from the global loader to leave the
        global loader unaltered.
        N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r	   r	   r	   r
   ÚLoader0   s    r   ztag:yaml.org,2002:strÚclose)Úadd_constructorÚyamlÚloadÚhasattrr   )ÚsourceÚloaderr   r   r	   r	   r
   Ú	yaml_load!   s   
	
ÿ
ÿr   c                 C   s   t j | ¡rt j | ¡S dS )zƒ
    Return the modified time of the supplied file. If the file does not exists zero is returned.
    see build_pages for use.
    g        )ÚosÚpathÚexistsÚgetmtime)Ú	file_pathr	   r	   r
   Úmodified_timeH   s   r   c                  C   s0   t j d¡} | du rtt tj¡ ¡ ƒS t| ƒS )zÆ
    Returns the number of seconds since the epoch.

    Support SOURCE_DATE_EPOCH environment variable for reproducible builds.
    See https://reproducible-builds.org/specs/source-date-epoch/
    ÚSOURCE_DATE_EPOCHN)	r   ÚenvironÚgetÚintr   Únowr   ÚutcÚ	timestamp©Úsource_date_epochr	   r	   r
   Úget_build_timestampS   s   r(   c                  C   s2   t j d¡} | du rt tj¡S t t| ƒtj¡S )z¹
    Returns an aware datetime object.

    Support SOURCE_DATE_EPOCH environment variable for reproducible builds.
    See https://reproducible-builds.org/specs/source-date-epoch/
    r   N)	r   r    r!   r   r#   r   r$   Úfromtimestampr"   r&   r	   r	   r
   Úget_build_datetimea   s   r*   c                   C   s   t ƒ  d¡S )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*   Ústrftimer	   r	   r	   r
   Úget_build_dateo   s   r,   c                    s   t ƒ ‰ ‡ fdd„| D ƒS )z5 Reduce duplicate items in a list and preserve order c                    s"   g | ]}|ˆ vrˆ   |¡s|‘qS r	   )Úadd)Ú.0Úitem©Úseenr	   r
   Ú
<listcomp>|   s    ÿzreduce_list.<locals>.<listcomp>)Úset)Údata_setr	   r0   r
   Úreduce_listy   s   r5   c                 C   sT   t j |¡}t j |¡st  |¡ t j |¡r"t j |t j | ¡¡}t 	| |¡ dS )z}
    Copy source_path to output_path, making sure any parent directories exist.

    The output_path may be a directory.
    N)
r   r   Údirnamer   ÚmakedirsÚisdirÚjoinÚbasenameÚshutilÚcopyfile)Úsource_pathÚoutput_pathÚ
output_dirr	   r	   r
   Ú	copy_file€   s   
r@   c                 C   s\   t j |¡}t j |¡st  |¡ t|dƒ�}| | ¡ W d  ƒ dS 1 s'w   Y  dS )zQ
    Write content to output_path, making sure any parent directories exist.
    ÚwbN)r   r   r6   r   r7   ÚopenÚwrite)Úcontentr>   r?   Úfr	   r	   r
   Ú
write_fileŽ   s   
"ÿrF   c                 C   sb   t j | ¡sdS t  | ¡D ]!}| d¡rqt j | |¡}t j |¡r)t |d¡ qt  	|¡ qdS )zU
    Remove the content of a directory recursively but not the directory itself.
    NÚ.T)
r   r   r   ÚlistdirÚ
startswithr9   r8   r;   ÚrmtreeÚunlink)Ú	directoryÚentryr   r	   r	   r
   Úclean_directory™   s   
õrN   c                 C   s6   t j | ¡d } t j | ¡dkr| d S d | df¡S )a  
    Map a source file path to an output html path.

    Paths like 'index.md' will be converted to 'index.html'
    Paths like 'about.md' will be converted to 'about/index.html'
    Paths like 'api-guide/core.md' will be converted to 'api-guide/core/index.html'
    r   Úindexú.htmlú/ú
index.html)r   r   Úsplitextr:   r9   ©r   r	   r	   r
   Úget_html_path®   s   rU   Tc                 C   s6   t | ƒ} d|  tjjd¡ }|r|dtdƒ … S |S )aƒ  
    Map a source file path to an output html path.

    Paths like 'index.md' will be converted to '/'
    Paths like 'about.md' will be converted to '/about/'
    Paths like 'api-guide/core.md' will be converted to '/api-guide/core/'

    If `use_directory_urls` is `False`, returned URLs will include the a trailing
    `index.html` rather than just returning the directory path.
    rQ   NrR   )rU   Úreplacer   r   ÚsepÚlen)r   Úuse_directory_urlsÚurlr	   r	   r
   Úget_url_path¼   s
   r[   c                    s   t ‡ fdd„tD ƒƒS )zŽ
    Return True if the given file path is a Markdown file.

    https://superuser.com/questions/249436/file-extension-for-markdown-files
    c                 3   s&   � | ]}t   ˆ  ¡ d  |¡¡V  qdS )z*{}N)ÚfnmatchÚlowerÚformat)r.   ÚxrT   r	   r
   Ú	<genexpr>Ô   s   €$ z#is_markdown_file.<locals>.<genexpr>)ÚanyÚmarkdown_extensionsrT   r	   rT   r
   Úis_markdown_fileÎ   s   rc   c                 C   ó   t j | ¡d  ¡ }|dv S )ú=
    Return True if the given file path is an HTML file.
    é   )rP   ú.htm©r   r   rS   r]   ©r   Úextr	   r	   r
   Úis_html_file×   ó   rk   c                 C   rd   )re   rf   )rP   rg   z.xmlrh   ri   r	   r	   r
   Úis_template_fileâ   rl   rm   z^\d{3}\.html?$c                 C   s   t t | ¡ƒS )zG
    Return True if the given file path is an HTTP error template.
    )ÚboolÚ_ERROR_TEMPLATE_REÚmatchrT   r	   r	   r
   Úis_error_templateñ   s   rq   c                 C   sL   |dkrt  |¡}d|d v r|d n|}t  | |¡}|  d¡r$|d S |S )z-
    Return given url relative to other.
    rG   rf   r   rQ   )Ú	posixpathÚsplitÚrelpathÚendswith)rZ   ÚotherÚpartsÚrelurlr	   r	   r
   Úget_relative_urlø   s
   
ry   Ú c                 C   sN   t | pdƒ} t| ƒ}|js|js|  d¡r| S |dur!t| |jƒS t || ¡S )z< Return a URL relative to the given page or using the base. rG   )rQ   ú#N)	Úpath_to_urlr   ÚschemeÚnetlocrI   ry   rZ   rr   r9   )r   ÚpageÚbaseÚparsedr	   r	   r
   Únormalize_url  s   r‚   c                 C   s$   g }| D ]}|  t|||ƒ¡ q|S )zM
    Return a list of URLs relative to the given page or using the base.
    )Úappendr‚   )Ú	path_listr   r€   Úurlsr   r	   r	   r
   Úcreate_media_urls  s   r†   c                 C   s   d  |  d¡¡S )zConvert a system path to a URL.rQ   ú\)r9   rs   rT   r	   r	   r
   r|     s   r|   c                 C   s$   t ƒ |  }tj tj | ¡ j¡¡S )z5 Return the directory of an installed theme by name. )Ú
get_themesr   r   r6   Úabspathr   Ú__file__)ÚnameÚthemer	   r	   r
   Úget_theme_dir%  s   
r�   c                  C   sœ   i } t jddd�}t jdd�D ]<}|j|v r(|jjdkr(t d |j|jj¡¡‚|j| v rF| |j jj|jjg}t	 
d|jd |¡|jj¡ || |j< q| S )zE Return a dict of all installed themes as (name, entry point) pairs. Úmkdocszmkdocs.themes)ÚdistÚgroup)r�   zJThe theme {} is a builtin theme but {} provides a theme with the same namezQThe theme %s is provided by the Python packages '%s'. The one in %s will be used.ú,)Úpkg_resourcesÚget_entry_mapÚiter_entry_pointsr‹   r�   Úkeyr   ÚConfigurationErrorr^   ÚlogÚwarningr9   )ÚthemesÚbuiltinsrŒ   Úmultiple_packagesr	   r	   r
   rˆ   ,  s   þ
þrˆ   c                   C   s
   t ƒ  ¡ S )z.Return a list of all installed themes by name.)rˆ   Úkeysr	   r	   r	   r
   Úget_theme_namesD  s   
r�   c                 C   s0   | }|  dd¡  dd¡}| ¡ |kr| ¡ }|S )z4 Return a page tile obtained from a directory name. ú-ú Ú_)rV   r]   Ú
capitalize)r6   Útitler	   r	   r
   Údirname_to_titleJ  s
   r£   c                 C   sR   |   dd¡  dd¡ d¡}|r'| d¡ ¡ }| ¡ sq| d¡s"dS | d¡S dS )a=  
    Get the title of a Markdown document. The title in this case is considered
    to be a H1 that occurs before any other content in the document.
    The procedure is then to iterate through the lines, stopping at the first
    non-whitespace content. If it is a title, return that, otherwise return
    None.
    z
Ú
úr   z# N)rV   rs   ÚpopÚstriprI   Úlstrip)Úmarkdown_srcÚlinesÚliner	   r	   r
   Úget_markdown_titleU  s   	

úr¬   c                 C   sD   | D ]}t |tƒs
q||v r||   S qg }||i}|  |¡ |S )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.
    )Ú
isinstanceÚdictrƒ   )Úbranchr•   r   Ú
new_branchr	   r	   r
   Úfind_or_create_nodeh  s   
ÿ
r±   c                 C   sr   g }| D ]2}t jj|vr| |¡ qt j |¡\}}| t jj¡}|}|D ]}t|ƒ}t||ƒ}q%| |¡ q|S )zk
    Given a list of paths, convert them into a nested structure that will match
    the pages config.
    )r   r   rW   rƒ   rs   r£   r±   )ÚpathsÚnestedr   rL   r    rw   r¯   Úpartr	   r	   r
   Ú
nest_paths|  s   
rµ   c                   @   s   e Zd ZdZdZdd„ ZdS )ÚWarningFilterz( Counts all WARNING level log messages. r   c                 C   s   |j tjkr|  jd7  _dS )Nrf   T)ÚlevelnoÚloggingÚWARNINGÚcount)r   Úrecordr	   r	   r
   Úfilterš  s   zWarningFilter.filterN)r   r   r   r   rº   r¼   r	   r	   r	   r
   r¶   –  s    r¶   )T)Nrz   )3r   r¸   r   r’   r;   Úrer   r\   rr   r   r   Úurllib.parser   rŽ   r   Ú	getLoggerr   r—   rb   r   r   r   r(   r*   r,   r5   r@   rF   rN   rU   r[   rc   rk   rm   Úcompilero   rq   ry   r‚   r†   r|   r�   rˆ   r�   r£   r¬   r±   rµ   ÚFilterr¶   Úwarning_filterr	   r	   r	   r
   Ú<module>   sV    
	'

	



