B
    ©0H[ÐJ  ã               @   sF  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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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ƒZ$G dd„ de"ƒZ%G dd„ de%e!ƒZ&G dd„ de#e!ƒZ'G dd„ de ƒZ(e(ƒ Z)dS )é    N)ÚOrderedDict)ÚunquoteÚ	urldefragÚurlsplitÚ
urlunsplit)Úsettings)Úcheck_settingsÚmatches_patterns)ÚInvalidCacheBackendErrorÚcacheÚcaches)ÚImproperlyConfigured)ÚContentFile)ÚFileSystemStorageÚget_storage_class)Úforce_bytes)Ú
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__© úfC:\Users\HIRONO~1\AppData\Local\Temp\pip-install-6bm3nxem\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‡ 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")c                s†   t ƒ j||Ž tƒ | _i | _xd| jD ]Z\}}xP|D ]H}t|ttfƒrN|\}}n| j	}t
 |t
j¡}| j |g ¡ ||f¡ q2W q$W d S )N)r   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   ;   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    Úcontentr9   Úchunkr   r   r   Ú	file_hashH   s    zHashedFilesMixin.file_hashc             C   s&  t t|ƒƒ}|j ¡ }|r,t t|ƒƒj ¡ }|p2|}d}|d kr‚|  |¡sZtd|| f ƒ‚y|  |¡}W n tk
r|   |S X d}z|  ||¡}W d |r | 	¡  X t
j |¡\}}t
j |¡\}	}
|d k	rÒd| }t
j |d|	||
f ¡}t|ƒ}||d< d|k�r|d �s|d  d	7  < t|ƒS )
NFz)The file '%s' could not be found with %r.Tz.%sz%s%s%sé   z?#é   ú?)r   r   r   ÚstripÚexistsÚ
ValueErrorÚopenÚIOErrorr?   ÚcloseÚosÚsplitÚsplitextÚjoinr-   r   )r   r    r=   ÚfilenameÚparsed_nameÚ
clean_nameZopenedr?   r   ÚrootÚextÚhashed_nameÚunparsed_namer   r   r   rR   S   s:    



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.
        Ú ú/Nz?#é   rA   r@   rB   )r   ÚDEBUGr   r   r   Úendswithr   Úurlr-   r   r   )r   Zhashed_name_funcr    Úforcer)   rR   ÚfragmentrO   r   Z	final_urlZquery_fragmentÚurlparts)r   r   r   Ú_urlx   s&    

zHashedFilesMixin._urlc             C   s   |   | j||¡S )z:
        Return the non-hashed URL in DEBUG mode.
        )r]   Ústored_name)r   r    rZ   r   r   r   rY   —   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]+:rU   NT)rZ   r)   éÿÿÿÿz?#ú#)Úgroupsr/   ÚmatchÚ
startswithr   r   r   ÚAssertionErrorÚlenrI   ÚsepÚreplaceÚ	posixpathrL   Údirnamer]   Ú_stored_namer   rJ   )	ZmatchobjÚmatchedrY   Zurl_pathr[   Ztarget_nameZsource_nameZ
hashed_urlZtransformed_url)r)   r    r   r6   r   r   Ú	converter¤   s$    


*z1HashedFilesMixin.url_converter.<locals>.converter)r.   )r   r    r)   r6   rl   r   )r)   r    r   r6   r   Úurl_converter�   s    -zHashedFilesMixin.url_converterc             +   sÔ   |rdS t ƒ }‡fdd„ˆ D ƒ}x*ˆ ˆ ||¡D ]\}}}}	|||fV  q0W ‡ fdd„|D ƒ‰ xPtˆjƒD ]B}
d}x2ˆ ˆ ||¡D ] \}}}}|||fV  |p |}q‚W |sjP qjW |rÄddtdƒfV  ˆj |¡ dS )	a  
        Post process the given OrderedDict 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   )rn   r   )Úpathsr   r   ú
<dictcomp>ò   s    z1HashedFilesMixin.post_process.<locals>.<dictcomp>FZAllz!Max post-process passes exceeded.)r   Ú_post_processÚrangeÚmax_post_process_passesÚRuntimeErrorr)   r;   )r   rp   Údry_runÚoptionsr)   Úadjustable_pathsr    rR   Ú	processedÚ_ÚiÚsubstitutionsZsubstr   )rp   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ª|}|	 ¡  	t
j¡}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 |�rH|  |¡ tt|ƒƒ}|  ||¡}|  ||¡}|  |¡�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)re   rJ   rI   rf   )r    r   r   r   Ú
path_level  s    z2HashedFilesMixin._post_process.<locals>.path_levelT)ÚkeyÚreverseÚseekr   F)ÚsortedrF   rO   Úhash_keyrR   Úhasattrr�   rD   ÚreadÚdecoder   ZFILE_CHARSETr(   Úitemsr	   rm   ÚsubrE   Údeleter   r   Ú_save)r   rp   rx   r)   r~   r    r|   Zstorager   Zoriginal_fileÚcleaned_namerƒ   rR   Zhashed_file_existsry   Zold_hashed_namer=   r4   r*   r5   r6   rl   ÚexcÚcontent_fileZ
saved_namer   r   r   rr     sX    





(




zHashedFilesMixin._post_processc             C   s   |  dd¡S )Nú\rU   )rg   )r   r    r   r   r   rO   J  s    zHashedFilesMixin.clean_namec             C   s   |S )Nr   )r   r    r   r   r   rƒ   M  s    zHashedFilesMixin.hash_keyc             C   sD   t  |¡}|  |¡}|  |¡}| |¡}|d kr@|  |  |¡¡}|S )N)rh   ÚnormpathrO   rƒ   ÚgetrR   )r   r    r)   r‹   rƒ   Ú
cache_namer   r   r   rj   P  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é   )r=   rM   z*The name '%s' could not be hashed with %r.)rO   rƒ   r)   r�   rs   rt   rR   rE   )r   r    r‹   rƒ   r‘   Zintermediate_namer{   r   r   r   r^   \  s    


zHashedFilesMixin.stored_name)N)NN)FN)F)N)F)r!   r"   r#   r.   rt   r*   r   r?   rR   r]   rY   rm   r}   rr   rO   rƒ   rj   r^   r%   r   r   )r   r   r&   1   s   

%

6
0Gr&   c                   sT   e 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.jsonTc                s   t ƒ j||Ž |  ¡ | _d S )N)r   r   Úload_manifestr)   )r   r   r   )r   r   r   r   y  s    zManifestFilesMixin.__init__c          	   C   s>   y$|   | j¡�}| ¡  ¡ S Q R X W n tk
r8   d S X d S )N)rF   Úmanifest_namer…   r†   rG   )r   Úmanifestr   r   r   Úread_manifest}  s
    z ManifestFilesMixin.read_manifestc             C   sv   |   ¡ }|d krtƒ S ytj|td�}W n tk
r<   Y n"X | d¡}|dkr^| dtƒ ¡S td| j| jf ƒ‚d S )N)Úobject_pairs_hookÚversionz1.0rp   z(Couldn't load manifest '%s' (version %s))r—   r   ÚjsonÚloadsrE   r�   r•   Úmanifest_version)r   r=   Zstoredr™   r   r   r   r”   „  s    
z ManifestFilesMixin.load_manifestc             /   s(   t ƒ | _tƒ j||ŽE d H  |  ¡  d S )N)r   r)   r   r}   Úsave_manifest)r   r   r   )r   r   r   r}   “  s    zManifestFilesMixin.post_processc             C   sJ   | j | jdœ}|  | j¡r&|  | j¡ t |¡ ¡ }|  | jt	|ƒ¡ d S )N)rp   r™   )
r)   rœ   rD   r•   r‰   rš   ÚdumpsÚencoderŠ   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?#rA   rB   )r   r   r   rC   rƒ   r)   r�   Úmanifest_strictrE   rO   rR   r-   r   )r   r    rN   rO   rƒ   r‘   rS   r   r   r   r^   Ÿ  s    

zManifestFilesMixin.stored_name)r!   r"   r#   rœ   r•   r¢   r   r—   r”   r}   r�   r^   r%   r   r   )r   r   r“   t  s   r“   c               @   sB   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zddd„Z	dS )Ú_MappingCachezG
    A small dict-like wrapper for a given cache backend instance.
    c             C   s
   || _ d S )N)r   )r   r   r   r   r   r   µ  s    z_MappingCache.__init__c             C   s   | j  ||¡ d S )N)r   Úset)r   r   Úvaluer   r   r   Ú__setitem__¸  s    z_MappingCache.__setitem__c             C   s$   | j  |¡}|d kr td| ƒ‚|S )NzCouldn't find a file name '%s')r   r�   ÚKeyError)r   r   r¥   r   r   r   Ú__getitem__»  s    z_MappingCache.__getitem__c             C   s   | j  ¡  d S )N)r   Úclear)r   r   r   r   r©   Á  s    z_MappingCache.clearc             C   s   | j  |¡ d S )N)r   Zset_many)r   Údatar   r   r   r;   Ä  s    z_MappingCache.updateNc             C   s"   y| | S  t k
r   |S X d S )N)r§   )r   r   Údefaultr   r   r   r�   Ç  s    z_MappingCache.get)N)
r!   r"   r#   r$   r   r¦   r¨   r©   r;   r�   r   r   r   r   r£   ±  s   r£   c                   s$   e Zd Z‡ fdd„Zdd„ Z‡  ZS )ÚCachedFilesMixinc                sD   t ƒ j||Ž yttd ƒ| _W n tk
r>   ttƒ| _Y nX d S )NZstaticfiles)r   r   r£   r   r)   r
   Údefault_cache)r   r   r   )r   r   r   r   Ï  s
    zCachedFilesMixin.__init__c             C   s    t  t|  |¡ƒ¡ ¡ }d| S )Nzstaticfiles:%s)r8   r9   r   rO   r<   )r   r    r   r   r   r   rƒ   ×  s    zCachedFilesMixin.hash_key)r!   r"   r#   r   rƒ   r%   r   r   )r   r   r¬   Î  s   r¬   c               @   s   e Zd ZdZdS )ÚCachedStaticFilesStoragezh
    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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°   )*r8   rš   rI   rh   r/   Úcollectionsr   Úurllib.parser   r   r   r   Zdjango.confr   Z django.contrib.staticfiles.utilsr   r	   Zdjango.core.cacher
   r   r­   r   Zdjango.core.exceptionsr   Zdjango.core.files.baser   Zdjango.core.files.storager   r   Zdjango.utils.encodingr   Zdjango.utils.functionalr   r   r&   r“   r£   r¬   r®   r¯   r°   Zstaticfiles_storager   r   r   r   Ú<module>   s2     E=