B
    CVvgÒD  ã               @   sê   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mZm	Z	 d dl
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 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)Úsettings)Úcheck_settingsÚmatches_patterns)ÚImproperlyConfigured)ÚContentFile)ÚFileSystemStorageÚget_storage_class)Ú
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-install-o3oxmrkh/Django/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   Úname)r   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‡ 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("%s")é   ))z*.css)z#(url\(['"]{0,1}\s*(.*?)["']{0,1}\)))z(@import\s*["']\s*(.*?)["'])z@import url("%s")Tc                s„   t ƒ j||Ž i | _i | _xd| jD ]Z\}}xP|D ]H}t|ttfƒrL|\}}n| j}t	 
|t	j¡}| j |g ¡ ||f¡ q0W q"W d S )N)r   r   Ú	_patternsÚhashed_filesÚpatternsÚ
isinstanceÚtupleÚlistÚdefault_templateÚreÚcompileÚ
IGNORECASEÚ
setdefaultÚappend)r   r   r   Ú	extensionr%   ÚpatternÚtemplateZcompiled)r   r   r   r   7   s    

zHashedFilesMixin.__init__Nc             C   s@   |dkrdS t  ¡ }x| ¡ D ]}| |¡ qW | ¡ dd… S )zU
        Return a hash of the file with the given name and optional content.
        Né   )ÚhashlibÚmd5ÚchunksÚupdateÚ	hexdigest)r   r   Úcontentr4   Úchunkr   r   r   Ú	file_hashD   s    zHashedFilesMixin.file_hashc             C   s  t t|ƒƒ}|j ¡ }|r,t t|ƒƒj ¡ p.|}|d k}|rz|  |¡sVtd|| f ƒ‚y|  |¡}W n tk
rx   |S X z|  ||¡}W d |r˜| 	¡  X t
j |¡\}}t
j |¡\}	}
|rÆd| 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é   z?#é   ú?)r   r   r   ÚstripÚexistsÚ
ValueErrorÚopenÚOSErrorr:   ÚcloseÚosÚsplitÚsplitextÚjoinr(   r   )r   r   r8   ÚfilenameÚparsed_nameÚ
clean_nameZopenedr:   r   ÚrootÚextÚhashed_nameÚunparsed_namer   r   r   rN   O   s2    



zHashedFilesMixin.hashed_nameFc                sÀ   t jr|s|d }}nBt|ƒ\}}t|ƒj d¡r8|}n |f}|dk	rP||f7 }||Ž }tƒ  |¡}	d|k}
|st|
r¸tt|	ƒƒ}|r”|d s”||d< |
r°|d s°|d  d7  < t	|ƒ}	t
|	ƒS )	z:
        Return the non-hashed URL in DEBUG mode.
        r;   ú/Nz?#é   r=   r<   r>   )r   ÚDEBUGr   r   r   Úendswithr   Úurlr(   r   r   )r   Zhashed_name_funcr   Úforcer$   rN   ÚfragmentrK   r   Z	final_urlZquery_fragmentÚurlparts)r   r   r   Ú_urlp   s&    

zHashedFilesMixin._urlc             C   s   |   | j||¡S )z:
        Return the non-hashed URL in DEBUG mode.
        )rX   Ústored_name)r   r   rU   r   r   r   rT   �   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  |   ¡ \}}t d|¡r|S | d¡r6| tj¡s6|S t|ƒ\}}| d¡rp| tj¡s\t‚|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|ƒ 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.
            z^[a-z]+:rP   NT)rU   r$   éÿÿÿÿz?#ú#)Úgroupsr*   ÚmatchÚ
startswithr   r   r   ÚAssertionErrorÚlenrE   ÚsepÚreplaceÚ	posixpathrH   ÚdirnamerX   Ú_stored_namer   rF   )	ZmatchobjÚmatchedrT   Zurl_pathrV   Ztarget_nameZsource_nameZ
hashed_urlZtransformed_url)r$   r   r   r1   r   r   Ú	converterœ   s$    


*z1HashedFilesMixin.url_converter.<locals>.converter)r)   )r   r   r$   r1   rg   r   )r$   r   r   r1   r   Úurl_converter•   s    -zHashedFilesMixin.url_converterc             +   sÒ   |rdS i }‡fdd„ˆ D ƒ}x*ˆ  ˆ ||¡D ]\}}}}	|||fV  q.W ‡ fdd„|D ƒ‰ xPtˆjƒD ]B}
d}x2ˆ  ˆ ||¡D ] \}}}}|||fV  |pž|}q€W |shP qhW |rÂddtdƒfV  ˆj |¡ 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   )ri   r   )Úpathsr   r   ú
<dictcomp>ê   s    z1HashedFilesMixin.post_process.<locals>.<dictcomp>FZAllz!Max post-process passes exceeded.)Ú_post_processÚrangeÚmax_post_process_passesÚRuntimeErrorr$   r6   )r   rk   Údry_runÚoptionsr$   Úadjustable_pathsr   rN   Ú	processedÚ_ÚiÚsubstitutionsZsubstr   )rk   r   r   Úpost_processË   s"    zHashedFilesMixin.post_processc             c   sþ  dd„ }�xît ||dd�D �]Ú}d}|| \}}| |¡��´}	|  |¡}
|  |
¡}||krh|  ||	¡}n|| }t|	dƒr„|	 d¡ |  |¡}d}||k�r°|}|	 ¡  	d¡}x†| j
 ¡ D ]x\}}t||fƒrºxb|D ]Z\}}|  |||¡}y| ||¡}W qÔ tk
�r, } z|d |dfV  W d d }~X Y qÔX qÔW qºW |�rF|  |¡ t| ¡ ƒ}| j�rf|  ||¡ |  ||¡}|  |¡�rˆ|  |¡ |  ||¡}|  |¡}||k�r¬d}d}|�sÖ|�sÖd}|  ||	¡}|  |¡}|||< ||||fV  W d Q R X qW d S )	Nc             S   s   t |  tj¡ƒS )N)r`   rF   rE   ra   )r   r   r   r   Ú
path_levelý   s    z2HashedFilesMixin._post_process.<locals>.path_levelT)ÚkeyÚreverseÚseekr   Fzutf-8)ÚsortedrB   rK   Úhash_keyrN   Úhasattrr|   r@   ÚreadÚdecoder#   Úitemsr   rh   ÚsubrA   Údeleter
   ÚencodeÚkeep_intermediate_filesÚ_save)r   rk   rs   r$   ry   r   rw   Zstorager   Zoriginal_fileÚcleaned_namer~   rN   Zhashed_file_existsrt   Zold_hashed_namer8   r/   r%   r0   r1   rg   ÚexcÚcontent_fileZ
saved_namer   r   r   rm   û   sZ    





(




zHashedFilesMixin._post_processc             C   s   |  dd¡S )Nú\rP   )rb   )r   r   r   r   r   rK   C  s    zHashedFilesMixin.clean_namec             C   s   |S )Nr   )r   r   r   r   r   r~   F  s    zHashedFilesMixin.hash_keyc             C   sD   t  |¡}|  |¡}|  |¡}| |¡}|d kr@|  |  |¡¡}|S )N)rc   ÚnormpathrK   r~   ÚgetrN   )r   r   r$   rˆ   r~   Ú
cache_namer   r   r   re   I  s    



zHashedFilesMixin._stored_namec             C   sˆ   |   |¡}|  |¡}| j |¡}|r(|S |}xFt| jd ƒD ]4}|   | j|d |d�¡}||krl|| j|< |S |}q<W td|| f ƒ‚d S )Né   )r8   rI   z*The name '%s' could not be hashed with %r.)rK   r~   r$   r�   rn   ro   rN   rA   )r   r   rˆ   r~   rŽ   Zintermediate_namerv   r   r   r   rY   U  s    


zHashedFilesMixin.stored_name)N)NN)FN)F)N)F)r   r   r   r)   ro   r%   r†   r   r:   rN   rX   rT   rh   rx   rm   rK   r~   re   rY   r    r   r   )r   r   r!   ,   s    

!

6
0Hr!   c                   sX   e Zd ZdZdZdZdZ‡ fdd„Zdd„ Zd	d
„ Z	‡ fdd„Z
dd„ Zdd„ Z‡  ZS )ÚManifestFilesMixinz1.0zstaticfiles.jsonTFc                s   t ƒ j||Ž |  ¡ | _d S )N)r   r   Úload_manifestr$   )r   r   r   )r   r   r   r   s  s    zManifestFilesMixin.__init__c          	   C   s>   y$|   | j¡�}| ¡  ¡ S Q R X W n tk
r8   d S X d S )N)rB   Úmanifest_namer€   r�   ÚFileNotFoundError)r   Úmanifestr   r   r   Úread_manifestw  s
    z ManifestFilesMixin.read_manifestc             C   sp   |   ¡ }|d kri S yt |¡}W n tjk
r8   Y n X | d¡}|dkrX| di ¡S td| j| jf ƒ‚d S )NÚversionz1.0rk   z(Couldn't load manifest '%s' (version %s))r•   ÚjsonÚloadsÚJSONDecodeErrorr�   rA   r’   Úmanifest_version)r   r8   Zstoredr–   r   r   r   r‘   ~  s    
z ManifestFilesMixin.load_manifestc             /   s0   i | _ tƒ j||ŽE d H  | d¡s,|  ¡  d S )Nrq   )r$   r   rx   r�   Úsave_manifest)r   r   r   )r   r   r   rx   �  s    
zManifestFilesMixin.post_processc             C   sJ   | j | jdœ}|  | j¡r&|  | j¡ t |¡ ¡ }|  | jt	|ƒ¡ d S )N)rk   r–   )
r$   rš   r@   r’   r„   r—   Údumpsr…   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'r<   z?#r=   r>   )r   r   r   r?   r~   r$   r�   Úmanifest_strictrA   rK   rN   r(   r   )r   r   rJ   rK   r~   rŽ   rO   r   r   r   rY   š  s    

zManifestFilesMixin.stored_name)r   r   r   rš   r’   rŸ   r†   r   r•   r‘   rx   r›   rY   r    r   r   )r   r   r�   m  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jƒƒ | _d S )N)r   r   ZSTATICFILES_STORAGEZ_wrapped)r   r   r   r   Ú_setupµ  s    zConfiguredStorage._setupN)r   r   r   r¢   r   r   r   r   r¡   ´  s   r¡   )r3   r—   rE   rc   r*   Úurllib.parser   r   r   r   Zdjango.confr   Z django.contrib.staticfiles.utilsr   r   Zdjango.core.exceptionsr	   Zdjango.core.files.baser
   Zdjango.core.files.storager   r   Zdjango.utils.functionalr   r   r!   r�   r    r¡   Zstaticfiles_storager   r   r   r   Ú<module>   s&     C?