3
(h;                 @   sf  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	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mZ d dlmZ d dlm Z  d dl!m"Z"m#Z#m$Z$m%Z% G dd deZ&G dd de'Z(G dd de(Z)G dd de'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 )    )unicode_literalsN)OrderedDict)settings)check_settingsmatches_patterns)InvalidCacheBackendErrorcachecaches)ImproperlyConfigured)ContentFile)FileSystemStorageget_storage_class)force_bytes
force_text)
LazyObject)	iteritems)unquote	urldefragurlsplit
urlunsplitc                   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                sR   |d krt j}|d krt j}t| tt| j||f|| |sNd | _d | _d S )N)	r   ZSTATIC_ROOT
STATIC_URLr   superr   __init__Zbase_locationlocation)selfr   base_urlargskwargs)	__class__ F/tmp/pip-install-q3hcpn_q/Django/django/contrib/staticfiles/storage.pyr   !   s    
zStaticFilesStorage.__init__c                s   | j stdtt| j|S )NzaYou're using the staticfiles app without having set the STATIC_ROOT setting to a filesystem path.)r   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                   sr   e 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 Zdd Zdd Z  ZS )#HashedFilesMixinz	url("%s")*.css#(url\(['"]{0,1}\s*(.*?)["']{0,1}\))(@import\s*["']\s*(.*?)["'])@import url("%s")c                s   t t| j|| t | _i | _xd| jD ]Z\}}xP|D ]H}t|tt	frR|\}}n| j
}tj|tj}| jj|g j||f q6W q(W d S )N)r   r)   r   r   	_patternshashed_filespatterns
isinstancetuplelistdefault_templaterecompile
IGNORECASE
setdefaultappend)r   r   r   	extensionr0   patterntemplateZcompiled)r   r    r!   r   @   s    

zHashedFilesMixin.__init__Nc             C   s@   |dkrdS t j }x|j D ]}|j| qW |j 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#   contentr?   chunkr    r    r!   	file_hashM   s    zHashedFilesMixin.file_hashc             C   s  t t|}|jj }d}|d krd| j|s<td|| f y| j|}W n tk
r^   |S X d}z| j||}W d |r|j	  X t
jj|\}}t
jj|\}	}
|d k	rd| }t
jj|d|	||
f }t|}||d< d|ko|d  r |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IOErrorrE   closeossplitsplitextjoinr3   r   )r   r#   rC   Zparsed_name
clean_nameZopenedrE   r"   filenamerootexthashed_nameZunparsed_namer    r    r!   rW   X   s6    



zHashedFilesMixin.hashed_nameFc       	         s   t jr| r|d }}n,t|\}}t|jjdr:|}n
| j|}tt| j	|}d|k}|sd|rt
t|}|r|d  r||d< |r|d  r|d  d7  < t|}t|S )z4
        Return the real URL in DEBUG mode.
         /z?#   rG   rF   rH   )r   DEBUGr   r   r"   endswithstored_namer   r)   urlr3   r   r   )	r   r#   forcerW   fragmentrS   Z	final_urlZquery_fragmenturlparts)r   r    r!   r^   y   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  | j  \}}|jdr|S |jdr6|jtj r6|S t|\}}|jdrp|jtjs\t|ttjd }n.tjdkr~ n j	tjd}t
jt
j||}jt|dd	}dj|jddd |j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.
            http:https://#data:rY   NT)r_      z?#)rb   rc   rd   re   rf   rh   )groups
startswithr   r   r   AssertionErrorlenrO   sepreplace	posixpathrR   dirnamer^   r   rP   )	Zmatchobjmatchedr^   Zurl_pathr`   Ztarget_nameZsource_nameZ
hashed_urlZtransformed_url)r#   r   r<   r    r!   	converter   s     

*z1HashedFilesMixin.url_converter.<locals>.converter)r4   )r   r#   r<   rr   r    )r#   r   r<   r!   url_converter   s    *zHashedFilesMixin.url_converterc             +   s  |rdS t  } fdd|D }dd }xt|j |ddD ]n}|| \}}	|j|	L}
 j||
}t|
dr~|
jd	  j|}d
}||krf|
j j	t
j}xt jD ]t\}}t|	|frx^|D ]V\}} j||}y|j||}W q tk
r  } z|d|fV  W Y dd}~X qX qW qW |r: j| tt|} j||}t j|}d}n$|sd} j||
}t j|}|| j|< |||fV  W dQ R X q>W  j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j r|qS r    )r   r.   keys).0r"   )r   r    r!   
<listcomp>   s    z1HashedFilesMixin.post_process.<locals>.<listcomp>c             S   s   t | jtjS )N)rl   rP   rO   rm   )r#   r    r    r!   
path_level   s    z1HashedFilesMixin.post_process.<locals>.path_levelT)keyreverseseekr   F)r   sortedrt   rL   rW   hasattrrz   rJ   readdecoder   ZFILE_CHARSETr   r.   r   rs   subrK   deleter   r   _saver   rS   hash_keyr/   rA   )r   pathsdry_runoptionsr/   Zadjustable_pathsrw   r#   Zstorager"   Zoriginal_filerW   Zhashed_file_exists	processedrC   r:   r0   r;   r<   rr   exccontent_fileZ
saved_namer    )r   r!   post_process   sH    



&
zHashedFilesMixin.post_processc             C   s   |j ddS )N\rY   )rn   )r   r#   r    r    r!   rS     s    zHashedFilesMixin.clean_namec             C   s   |S )Nr    )r   r#   r    r    r!   r     s    zHashedFilesMixin.hash_keyc             C   s<   | j |}| jj|}|d kr8| j| j|}|| j|< |S )N)r   r/   getrS   rW   )r   r#   r   Z
cache_namer    r    r!   r]      s    

zHashedFilesMixin.stored_namer,   r-   r+   r   r*   r   )r   )N)N)F)N)F)r$   r%   r&   r4   r0   r   rE   rW   r^   rs   r   rS   r   r]   r(   r    r    )r   r!   r)   7   s     

!
3
Rr)   c                   sH   e Zd ZdZdZ fddZdd Zdd Z fd	d
Zdd Z	  Z
S )ManifestFilesMixinz1.0zstaticfiles.jsonc                s    t t| j|| | j | _d S )N)r   r   r   load_manifestr/   )r   r   r   )r   r    r!   r   /  s    zManifestFilesMixin.__init__c             C   s@   y&| j | j}|j jdS Q R X W n tk
r:   d S X d S )Nzutf-8)rL   manifest_namer}   r~   rM   )r   manifestr    r    r!   read_manifest3  s
    z ManifestFilesMixin.read_manifestc             C   sv   | j  }|d krt S ytj|td}W n tk
r<   Y n"X |jd}|dkr^|jdt S td| j| jf d S )N)object_pairs_hookversionz1.0r   z(Couldn't load manifest '%s' (version %s))r   r   jsonloadsrK   r   r   manifest_version)r   rC   Zstoredr   r    r    r!   r   :  s    
z ManifestFilesMixin.load_manifestc             /   s:   t  | _tt| j||}x|D ]
}|V  q W | j  d S )N)r   r/   r   r   r   save_manifest)r   r   r   Zall_post_processedZpost_processed)r   r    r!   r   I  s    

zManifestFilesMixin.post_processc             C   sL   | j | jd}| j| jr&| j| j tj|jd}| j| jt	| d S )N)r   r   zutf-8)
r/   r   rJ   r   r   r   dumpsencoder   r   )r   payloadcontentsr    r    r!   r   Q  s
    z ManifestFilesMixin.save_manifest)r$   r%   r&   r   r   r   r   r   r   r   r(   r    r    )r   r!   r   +  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 j|| d S )N)r   set)r   rx   valuer    r    r!   __setitem__`  s    z_MappingCache.__setitem__c             C   s$   | j j|}|d kr td| |S )NzCouldn't find a file name '%s')r   r   KeyError)r   rx   r   r    r    r!   __getitem__c  s    z_MappingCache.__getitem__c             C   s   | j j  d S )N)r   clear)r   r    r    r!   r   i  s    z_MappingCache.clearc             C   s   | j j| d S )N)r   Zset_many)r   datar    r    r!   rA   l  s    z_MappingCache.updateNc             C   s"   y| | S  t k
r   |S X d S )N)r   )r   rx   defaultr    r    r!   r   o  s    z_MappingCache.get)N)
r$   r%   r&   r'   r   r   r   r   rA   r   r    r    r    r!   r   Y  s   r   c                   s$   e Zd Z fddZdd Z  ZS )CachedFilesMixinc                sH   t t| j|| yttd | _W n tk
rB   tt| _Y nX d S )NZstaticfiles)r   r   r   r   r	   r/   r   default_cache)r   r   r   )r   r    r!   r   w  s
    zCachedFilesMixin.__init__c             C   s    t jt| j|j }d| S )Nzstaticfiles:%s)r>   r?   r   rS   rB   )r   r#   rx   r    r    r!   r     s    zCachedFilesMixin.hash_key)r$   r%   r&   r   r   r(   r    r    )r   r!   r   v  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   )0
__future__r   r>   r   rO   ro   r5   collectionsr   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   r   Zdjango.utils.functionalr   Zdjango.utils.sixr   Z#django.utils.six.moves.urllib.parser   r   r   r   r   objectr)   r   r   r   r   r   r   Zstaticfiles_storager    r    r    r!   <module>   s4    u.