U
    Rh                      @  s   d dl m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	 d dl
Z
d dlZ
d dlmZ d dlmZmZ d dlmZ d dlmZmZmZ d dlmZmZmZ ejed	f ZG d
d deZG dd dZdS )    )annotationsN)	parsedate)get_route_path)URLHeaders)HTTPException)FileResponseRedirectResponseResponse)ReceiveScopeSendzos.PathLike[str]c                      s&   e Zd ZdZdd fddZ  ZS )NotModifiedResponse)zcache-controlzcontent-locationdateetagZexpiresZvaryr   )headersc                   s&   t  jd fdd| D d d S )Ni0  c                   s    i | ]\}}| j kr||qS  )NOT_MODIFIED_HEADERS).0namevalueselfr   ;./venv/lib/python3.8/site-packages/starlette/staticfiles.py
<dictcomp>#   s     
  z0NotModifiedResponse.__init__.<locals>.<dictcomp>)status_coder   )super__init__items)r   r   	__class__r   r   r       s    zNotModifiedResponse.__init__)__name__
__module____qualname__r   r   __classcell__r   r   r   r   r      s   	r   c                   @  s   e Zd Zddddddddddddd	d
dZd0ddddddZdddddddZdddddZddddddZdddd d!Zd1d#d$dd%dd&d'd(Z	dd)d*d+Z
d,d,dd-d.d/ZdS )2StaticFilesNFT)	directorypackageshtml	check_dirfollow_symlinkzPathLike | Nonez"list[str | tuple[str, str]] | NoneboolNone)r&   r'   r(   r)   r*   returnc                C  sX   || _ || _| ||| _|| _d| _|| _|rT|d k	rTtj	|sTt
d| dd S )NFDirectory 'z' does not exist)r&   r'   get_directoriesall_directoriesr(   config_checkedr*   ospathisdirRuntimeError)r   r&   r'   r(   r)   r*   r   r   r   r   (   s    	zStaticFiles.__init__zlist[PathLike])r&   r'   r-   c                 C  s   g }|dk	r| | |pg D ]}t|tr6|\}}nd}tj|}|dk	s^td|d|jdk	sxtd|dtj	
tj	|jd|}tj	|std|d|d| | q|S )z
        Given `directory` and `packages` arguments, return a list of all the
        directories that should be used for serving static files from.
        NZstaticszPackage z could not be found.z..r.   z' in package )append
isinstancetuple	importlibutil	find_specAssertionErrororiginr2   r3   normpathjoinr4   )r   r&   r'   ZdirectoriespackageZstatics_dirspecZpackage_directoryr   r   r   r/   :   s$    	


zStaticFiles.get_directoriesr   r   r   )scopereceivesendr-   c                   s\   |d dkst | js*|  I dH  d| _| |}| ||I dH }||||I dH  dS )z'
        The ASGI entry point.
        typeZhttpNT)r<   r1   check_configget_pathget_response)r   rB   rC   rD   r3   responser   r   r   __call__W   s    
zStaticFiles.__call__str)rB   r-   c                 C  s"   t |}tjtjj|d S )z
        Given the ASGI scope, return the `path` string to serve up,
        with OS specific path separators, and any '..', '.' components removed.
        /)r   r2   r3   r>   r?   split)r   rB   Z
route_pathr   r   r   rG   e   s    zStaticFiles.get_pathr
   )r3   rB   r-   c              
     s  |d dkrt ddztj| j|I dH \}}W nX tk
rR   t ddY n< tk
r } z|jtjkrxt dd|W 5 d}~X Y nX |rt	
|jr| |||S |rLt	|jrL| jrLtj|d}tj| j|I dH \}}|dk	rLt	
|jrL|d	 d
s>t|d}|j|jd
 d}t|dS | |||S | jrtj| jdI dH \}}|rt	
|jrt||ddS t dddS )z`
        Returns an HTTP response, given the incoming path, method and request headers.
        method)ZGETZHEADi  )r   Ni  i  z
index.htmlr3   rL   rB   )r3   )urlz404.html)stat_resultr   )r   anyio	to_threadrun_synclookup_pathPermissionErrorOSErrorerrnoZENAMETOOLONGstatS_ISREGst_modefile_responseS_ISDIRr(   r2   r3   r?   endswithr   replacer	   r   )r   r3   rB   	full_pathrQ   excZ
index_pathrP   r   r   r   rH   m   s4    



zStaticFiles.get_responsez!tuple[str, os.stat_result | None])r3   r-   c              
   C  s   | j D ]}tj||}| jr,tj|}ntj|}tj|}tj||g|krZqz|t|fW   S  t	t
fk
r   Y qY qX qdS )N) N)r0   r2   r3   r?   r*   abspathrealpath
commonpathrY   FileNotFoundErrorNotADirectoryError)r   r3   r&   Zjoined_pathr`   r   r   r   rU      s    
zStaticFiles.lookup_path   PathLikezos.stat_resultint)r`   rQ   rB   r   r-   c                 C  s4   t |d}t|||d}| |j|r0t|jS |S )NrO   )r   rQ   )r   r   is_not_modifiedr   r   )r   r`   rQ   rB   r   request_headersrI   r   r   r   r\      s
    

zStaticFiles.file_response)r-   c                   s   | j dkrdS ztjtj| j I dH }W n& tk
rP   td| j  dY nX t|j	s|t
|j	s|td| j  ddS )z
        Perform a one-off configuration check that StaticFiles is actually
        pointed at a directory, so that we can raise loud errors rather than
        just returning 404 responses.
        NzStaticFiles directory 'z' does not exist.zStaticFiles path 'z' is not a directory.)r&   rR   rS   rT   r2   rY   rf   r5   r]   r[   S_ISLNK)r   rQ   r   r   r   rF      s    
zStaticFiles.check_configr   )response_headersrl   r-   c                 C  s   z2|d }|d }|dd | dD kr0W dS W n tk
rF   Y nX z:t|d }t|d }|d	k	r|d	k	r||krW dS W n tk
r   Y nX d
S )z
        Given the request and response headers, return `True` if an HTTP
        "Not Modified" response could be returned instead.
        zif-none-matchr   c                 S  s   g | ]}| d qS )z W/)strip)r   tagr   r   r   
<listcomp>   s     z/StaticFiles.is_not_modified.<locals>.<listcomp>,Tzif-modified-sincezlast-modifiedNF)rM   KeyErrorr   )r   rn   rl   Zif_none_matchr   Zif_modified_sinceZlast_modifiedr   r   r   rk      s    

zStaticFiles.is_not_modified)NN)rh   )r!   r"   r#   r   r/   rJ   rG   rH   rU   r\   rF   rk   r   r   r   r   r%   '   s"     * r%   ) Z
__future__r   rX   importlib.utilr9   r2   rY   typingZemail.utilsr   rR   Zanyio.to_threadZstarlette._utilsr   Zstarlette.datastructuresr   r   Zstarlette.exceptionsr   Zstarlette.responsesr   r	   r
   Zstarlette.typesr   r   r   ZUnionrK   ri   r   r%   r   r   r   r   <module>   s    