U
    eQ                     @   s   d dl Z d dlZd dlZd dlZd dlmZmZmZmZ d dl	m
Z
mZ d dlmZmZ d dlmZ d dlmZ d dlmZmZ d dlmZ d d	lmZ G d
d deZG dd dZG dd deZG dd deeZG dd deZe ZdS )    N)unquote	urldefragurlsplit
urlunsplit)STATICFILES_STORAGE_ALIASsettings)check_settingsmatches_patterns)ImproperlyConfigured)ContentFile)FileSystemStoragestorages)md5)
LazyObjectc                       s.   e Zd ZdZd fdd	Z fddZ  ZS )StaticFilesStoragez
    Standard file system storage for static files.

    The defaults for ``location`` and ``base_url`` are
    ``STATIC_ROOT`` and ``STATIC_URL``.
    Nc                    sN   |d krt j}|d krt j}t| t j||f|| |sJd | _d | _d S N)r   ZSTATIC_ROOT
STATIC_URLr   super__init__Zbase_locationlocation)selfr   base_urlargskwargs	__class__ F/tmp/pip-unpacked-wheel-lctamlir/django/contrib/staticfiles/storage.pyr      s    zStaticFilesStorage.__init__c                    s   | j stdt |S )NzaYou're using the staticfiles app without having set the STATIC_ROOT setting to a filesystem path.)r   r
   r   pathr   namer   r   r   r   %   s
    zStaticFilesStorage.path)NN)__name__
__module____qualname____doc__r   r   __classcell__r   r   r   r   r      s   r   c                       s   e Zd ZdZdZdZdZdZdZ fddZ	d d
dZ
d!ddZd" fdd	Zd#ddZd$ddZd%ddZdd Zdd Zdd Zdd Zdd Z  ZS )&HashedFilesMixinzurl("%(url)s")   F)*.js))zU(?P<matched>import(?s:(?P<import>[\s\{].*?))\s*from\s*['"](?P<url>[\.\/].*?)["']\s*;)z import%(import)s from "%(url)s";)zV(?P<matched>export(?s:(?P<exports>[\s\{].*?))\s*from\s*["'](?P<url>[\.\/].*?)["']\s*;)z!export%(exports)s from "%(url)s";)z4(?P<matched>import\s*['"](?P<url>[\.\/].*?)["']\s*;)zimport"%(url)s";)z+(?P<matched>import\(["'](?P<url>.*?)["']\))zimport("%(url)s")))z*.css)z5(?P<matched>url\(['"]{0,1}\s*(?P<url>.*?)["']{0,1}\)))z.(?P<matched>@import\s*["']\s*(?P<url>.*?)["'])z@import url("%(url)s"))zI(?m)(?P<matched>)^(/\*#[ \t](?-i:sourceMappingURL)=(?P<url>.*)[ \t]*\*/)$z/*# sourceMappingURL=%(url)s */)r(   ))z;(?m)(?P<matched>)^(//# (?-i:sourceMappingURL)=(?P<url>.*))$z//# sourceMappingURL=%(url)sTc                    s   | j r|  j| jf7  _t j|| i | _i | _| jD ]V\}}|D ]H}t|tt	fr`|\}}n| j
}t|tj}| j|g ||f qDq8d S r   )$support_js_module_import_aggregationpatterns&_js_module_import_aggregation_patternsr   r   	_patternshashed_files
isinstancetuplelistdefault_templaterecompile
IGNORECASE
setdefaultappend)r   r   r   	extensionr*   patterntemplateZcompiledr   r   r   r   l   s    
zHashedFilesMixin.__init__Nc                 C   s>   |dkrdS t dd}| D ]}|| q| dd S )zU
        Return a hash of the file with the given name and optional content.
        NF)Zusedforsecurity   )r   chunksupdate	hexdigest)r   r    contentZhasherchunkr   r   r   	file_hash{   s    
zHashedFilesMixin.file_hashc                 C   s"  t t|}|j }|r,t t|j p.|}|d k}|r~| |sVtd|| f z| |}W n tk
r|   | Y S X z| 	||}W 5 |r|  X t
j|\}}t
j|\}	}
|rd| nd}t
j|d|	||
f }t|}||d< d|kr|d s|d  d7  < t|S )	Nz)The file '%s' could not be found with %r.z.%s z%s%s%s   ?#   ?)r   r   r   stripexists
ValueErroropenOSErrorcloser@   ossplitsplitextjoinr0   r   )r   r    r>   filenameparsed_name
clean_nameZopenedr@   r   rootexthashed_nameunparsed_namer   r   r   rU      s4    




zHashedFilesMixin.hashed_namec                    s   t jr|s|d }}nBt|\}}t|jdr8|}n |f}|dk	rP||f7 }|| }t |}	d|k}
|st|
rtt|	}|r|d s||d< |
r|d s|d  d7  < t	|}	t
|	S )	:
        Return the non-hashed URL in DEBUG mode.
        rA   /NrC      rD   rB   rE   )r   DEBUGr   r   r   endswithr   urlr0   r   r   )r   Zhashed_name_funcr    forcer-   rU   fragmentrR   r   Z	final_urlZquery_fragmenturlpartsr   r   r   _url   s&    

zHashedFilesMixin._urlc                 C   s   |  | j||S )rW   )r`   stored_name)r   r    r]   r   r   r   r\      s    zHashedFilesMixin.urlc                    s$   dkrj  fdd}|S )zJ
        Return the custom URL converter for the given file name.
        Nc           
         s(  |   }|d }|d }td|r(|S |drB|tjsB|S t|\}}|sV|S |dr|tjspt|ttjd }n.t	j
dkrnt	j
d}tt||}jjt|d d}d|ddd |ddd  }	|r|	d	|kr
d	nd
| 7 }	t|	|d< | S )z
            Convert the matched URL to a normalized and hashed URL.

            This requires figuring out which files the matched URL resolves
            to and calling the url() method of the storage.
            matchedr\   z^[a-z]+:rX   NT)r]   r-   rC   #)	groupdictr2   match
startswithr   r   r   AssertionErrorlenrL   sepreplace	posixpathrO   dirnamer`   _stored_namer   rM   )
Zmatchobjmatchesrb   r\   Zurl_pathr^   Ztarget_nameZsource_nameZ
hashed_urlZtransformed_urlr-   r    r   r9   r   r   	converter   s8    
"z1HashedFilesMixin.url_converter.<locals>.converter)r1   )r   r    r-   r9   rq   r   rp   r   url_converter   s    8zHashedFilesMixin.url_converterc                 +   s  |rdS i }fdd D }i }  ||D ]:\}}}	}
||ksNt|	tr\|||	fV  q0|||	f||< q0 fdd|D  d}tjD ]B}d}  ||D ]"\}}}	}|||	f||< |p|}q|s qq|rddtdfV  j| | E dH  dS )	a  
        Post process the given dictionary of files (called from collectstatic).

        Processing is actually two separate operations:

        1. renaming files to include a hash of their content for cache-busting,
           and copying those files to the target storage.
        2. adjusting files which contain references to other files so they
           refer to the cache-busting filenames.

        If either of these are performed on a file, then that file is considered
        post-processed.
        Nc                    s   g | ]}t | jr|qS r   )r	   r,   .0r   r   r   r   
<listcomp>$  s     z1HashedFilesMixin.post_process.<locals>.<listcomp>c                    s   i | ]}| | qS r   r   rs   )pathsr   r   
<dictcomp>5  s      z1HashedFilesMixin.post_process.<locals>.<dictcomp>FZAllz!Max post-process passes exceeded.)	_post_processr.   	Exceptionrangemax_post_process_passesRuntimeErrorr-   r<   values)r   rw   dry_runoptionsr-   adjustable_pathsZprocessed_adjustable_pathsr    rU   	processed_substitutionsiZsubstr   )rw   r   r   post_process  s@    
    
zHashedFilesMixin.post_processc                 c   s  dd }t ||ddD ]}d}|| \}}||}	| |}
| |
}||krd| ||	}n|| }t|	dr|	d | |}d}||kr|}|	 	d}| j
 D ]t\}}t||fr|D ]Z\}}| |||}z|||}W q tk
r$ } z|d |dfV  W 5 d }~X Y qX qq|r:| | t| }| jrZ| || | ||}| |r|| | | ||}| |}||krd}d}|s|sd}| ||	}| |}|||< ||||fV  W 5 Q R X qd S )	Nc                 S   s   t | tjS r   )ri   rM   rL   rj   )r    r   r   r   
path_levelO  s    z2HashedFilesMixin._post_process.<locals>.path_levelT)keyreverseseekr   Fzutf-8)sortedrI   rR   hash_keyrU   hasattrr   rG   readdecoder,   itemsr	   rr   subrH   deleter   encodekeep_intermediate_files_save)r   rw   r   r-   r   r    r   Zstorager   Zoriginal_filecleaned_namer   rU   Zhashed_file_existsr   Zold_hashed_namer>   r7   r*   r8   r9   rq   exccontent_fileZ
saved_namer   r   r   ry   M  sb    





  $




zHashedFilesMixin._post_processc                 C   s   | ddS )N\rX   )rk   r   r   r   r   rR     s    zHashedFilesMixin.clean_namec                 C   s   |S r   r   r   r   r   r   r     s    zHashedFilesMixin.hash_keyc                 C   sD   t |}| |}| |}||}|d kr@| | |}|S r   )rl   normpathrR   r   getrU   )r   r    r-   r   r   
cache_namer   r   r   rn     s    



zHashedFilesMixin._stored_namec                 C   s   |  |}| |}| j|}|r(|S |}t| jd D ]8}|  | j|d |d}||krn|| j|< |  S |}q:td|| f d S )N   )r>   rP   z*The name '%s' could not be hashed with %r.)rR   r   r-   r   r{   r|   rU   rH   )r   r    r   r   r   Zintermediate_namer   r   r   r   ra     s    


zHashedFilesMixin.stored_name)N)NN)FN)F)N)F)r!   r"   r#   r1   r|   r)   r+   r*   r   r   r@   rU   r`   r\   rr   r   ry   rR   r   rn   ra   r%   r   r   r   r   r&   /   s$   

"

A
?Jr&   c                       s^   e Zd ZdZdZdZdZdd fdd
Zd	d
 Zdd Z	 fddZ
dd Zdd Z  ZS )ManifestFilesMixin1.1zstaticfiles.jsonTFN)manifest_storagec                   s4   t  j|| |d kr| }|| _|  \| _| _d S r   )r   r   r   load_manifestr-   manifest_hash)r   r   r   r   r   r   r   r     s
    zManifestFilesMixin.__init__c              
   C   sP   z4| j | j}|  W  5 Q R  W S Q R X W n tk
rJ   Y d S X d S r   )r   rI   manifest_namer   r   FileNotFoundError)r   manifestr   r   r   read_manifest  s
    $z ManifestFilesMixin.read_manifestc                 C   s   |   }|d kri dfS zt|}W n tjk
r<   Y n,X |d}|dkrh|di |ddfS td| j| jf d S )NrA   version)z1.0r   rw   hashz(Couldn't load manifest '%s' (version %s))r   jsonloadsJSONDecodeErrorr   rH   r   manifest_version)r   r>   Zstoredr   r   r   r   r     s    

z ManifestFilesMixin.load_manifestc                 /   s0   i | _ t j||E d H  |ds,|   d S )Nr   )r-   r   r   r   save_manifest)r   r   r   r   r   r   r     s    
zManifestFilesMixin.post_processc              	   C   sz   |  d ttt| j  | _| j| j	| jd}| j
| jrT| j
| j t| }| j
| jt| d S )N)rw   r   r   )r@   r   r   dumpsr   r-   r   r   r   r   r   rG   r   r   r   )r   payloadcontentsr   r   r   r     s     z ManifestFilesMixin.save_manifestc                 C   s   t t|}|j }| |}| j|}|d krV| jrFtd| | 	| 
|}t|}||d< d|kr|d s|d  d7  < t|S )Nz+Missing staticfiles manifest entry for '%s'rB   rC   rD   rE   )r   r   r   rF   r   r-   r   manifest_strictrH   rR   rU   r0   r   )r   r    rQ   rR   r   r   rV   r   r   r   ra     s    

zManifestFilesMixin.stored_name)r!   r"   r#   r   r   r   r   r   r   r   r   r   ra   r%   r   r   r   r   r     s   r   c                   @   s   e Zd ZdZdS )ManifestStaticFilesStoragezh
    A static file system storage backend which also saves
    hashed copies of the files it saves.
    N)r!   r"   r#   r$   r   r   r   r   r     s   r   c                   @   s   e Zd Zdd ZdS )ConfiguredStoragec                 C   s   t t | _d S r   )r   r   Z_wrappedru   r   r   r   _setup  s    zConfiguredStorage._setupN)r!   r"   r#   r   r   r   r   r   r     s   r   ) r   rL   rl   r2   urllib.parser   r   r   r   Zdjango.confr   r   Z django.contrib.staticfiles.utilsr   r	   Zdjango.core.exceptionsr
   Zdjango.core.files.baser   Zdjango.core.files.storager   r   Zdjango.utils.cryptor   Zdjango.utils.functionalr   r   r&   r   r   r   Zstaticfiles_storager   r   r   r   <module>   s(      M	