U
    HaD                     @   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-unpacked-wheel-3jxiddxt/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 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 | _| jD ]V\}}|D ]H}t|ttfrH|\}}n| j}t	
|t	j}| j|g ||f q,q d S r   )r   r   	_patternshashed_filespatterns
isinstancetuplelistdefault_templaterecompile
IGNORECASE
setdefaultappend)r   r   r   	extensionr(   patterntemplateZcompiledr   r   r   r   7   s    
zHashedFilesMixin.__init__Nc                 C   s<   |dkrdS t  }| D ]}|| q| 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   contentr7   chunkr   r   r   	file_hashD   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joinr+   r   )r   r   r;   filenameparsed_name
clean_nameZopenedr=   r   rootexthashed_nameunparsed_namer   r   r   rR   O   s4    




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|
rtt|	}|r|d s||d< |
r|d s|d  d7  < t	|}	t
|	S )	:
        Return the non-hashed URL in DEBUG mode.
        r>   /Nr@      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urlpartsr   r   r   _urlp   s&    

zHashedFilesMixin._urlc                 C   s   |  | j||S )rT   )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rd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'   r@   #)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   r4   r   r   	converter   s*    
  *z1HashedFilesMixin.url_converter.<locals>.converter)r,   )r   r   r'   r4   rm   r   rl   r   url_converter   s    -zHashedFilesMixin.url_converterc                 +   s   |rdS i }fdd D }  ||D ]\}}}}	|||fV  q, fdd|D  tjD ]@}
d}  ||D ] \}}}}|||fV  |p|}qx|sb qqb|rd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   ro   )pathsr   r   
<dictcomp>   s      z1HashedFilesMixin.post_process.<locals>.<dictcomp>FZAllz!Max post-process passes exceeded.)_post_processrangemax_post_process_passesRuntimeErrorr'   r9   )r   rs   dry_runoptionsr'   adjustable_pathsr   rR   	processed_isubstitutionsZsubstr   )rs   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   )re   rJ   rI   rf   )r   r   r   r   
path_level   s    z2HashedFilesMixin._post_process.<locals>.path_levelT)keyreverseseekr   Fzutf-8)sortedrF   rO   hash_keyrR   hasattrr   rD   readdecoder&   itemsr   rn   subrE   deleter
   encodekeep_intermediate_files_save)r   rs   r{   r'   r   r   r   Zstorager   Zoriginal_filecleaned_namer   rR   Zhashed_file_existsr|   Zold_hashed_namer;   r2   r(   r3   r4   rm   exccontent_fileZ
saved_namer   r   r   ru      sZ    





$




zHashedFilesMixin._post_processc                 C   s   | ddS )N\rU   )rg   r   r   r   r   rO   C  s    zHashedFilesMixin.clean_namec                 C   s   |S r   r   r   r   r   r   r   F  s    zHashedFilesMixin.hash_keyc                 C   sD   t |}| |}| |}||}|d kr@| | |}|S r   )rh   normpathrO   r   getrR   )r   r   r'   r   r   
cache_namer   r   r   rj   I  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;   rM   z*The name '%s' could not be hashed with %r.)rO   r   r'   r   rv   rw   rR   rE   )r   r   r   r   r   Zintermediate_namer~   r   r   r   r^   U  s    


zHashedFilesMixin.stored_name)N)NN)FN)F)N)F)r   r    r!   r,   rw   r(   r   r   r=   rR   r]   rY   rn   r   ru   rO   r   rj   r^   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 )ManifestFilesMixin1.0zstaticfiles.jsonTFc                    s   t  j|| |  | _d S r   )r   r   load_manifestr'   r   r   r   r   r   r   r   s  s    zManifestFilesMixin.__init__c              
   C   sN   z2|  | j}|  W  5 Q R  W S Q R X W n tk
rH   Y d S X d S r   )rF   manifest_namer   r   FileNotFoundError)r   manifestr   r   r   read_manifestw  s
    $z ManifestFilesMixin.read_manifestc                 C   sp   |   }|d kri S z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versionr   rs   z(Couldn't load manifest '%s' (version %s))r   jsonloadsJSONDecodeErrorr   rE   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 )Nry   )r'   r   r   r   save_manifestr   r   r   r   r     s    
zManifestFilesMixin.post_processc                 C   sJ   | j | jd}| | jr&| | j t| }| | jt	| d S )N)rs   r   )
r'   r   rD   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?   r@   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   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 r   )r   r   ZSTATICFILES_STORAGEZ_wrappedrq   r   r   r   _setup  s    zConfiguredStorage._setupN)r   r    r!   r   r   r   r   r   r     s   r   )r6   r   rI   rh   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?