
v^K                 @   s  d  d l  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 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 Gd d   d e  Z  Gd d   d  Z! Gd d   d e!  Z" Gd d   d  Z# Gd d   d e!  Z$ Gd d   d e$ e   Z% Gd d   d e" e   Z& Gd d   d e  Z' e'   Z( d S)    N)unquote	urldefragurlsplit
urlunsplit)settings)check_settingsmatches_patterns)InvalidCacheBackendErrorcachecaches)ImproperlyConfigured)ContentFile)FileSystemStorageget_storage_class)RemovedInDjango31Warning)
LazyObjectc                   s@   e  Z d  Z d Z d d   f d d  Z   f d d   Z   S)StaticFilesStoragez
    Standard file system storage for static files.

    The defaults for ``location`` and ``base_url`` are
    ``STATIC_ROOT`` and ``STATIC_URL``.
    Nc                si   | d  k r t  j } | d  k r* t  j } t |  t   j | | | |  | se d  |  _ d  |  _ d  S)N)r   ZSTATIC_ROOT
STATIC_URLr   super__init__Zbase_locationlocation)selfr   base_urlargskwargs)	__class__ D/tmp/pip-build-8lau8j11/django/django/contrib/staticfiles/storage.pyr      s    		
	zStaticFilesStorage.__init__c                s%   |  j  s t d   t   j |  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)__name__
__module____qualname____doc__r   r   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 d  Z	 d 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   S)&HashedFilesMixinz	url("%s")   *.css#(url\(['"]{0,1}\s*(.*?)["']{0,1}\))(@import\s*["']\s*(.*?)["'])@import url("%s")Tc                s   t    j | |   i  |  _ i  |  _ x |  j D] \ } } xr | D]j } t | t t f  rl | \ } } n	 |  j } t	 j
 | t	 j  } |  j j | g   j | | f  qB Wq/ Wd  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   <   s    			zHashedFilesMixin.__init__Nc             C   sT   | d k r d St  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_hashI   s    zHashedFilesMixin.file_hashc             C   s  t  t |   } | j j   } | rB t  t |   j j   pE | } | d  k } | r |  j |  s t d | |  f   y |  j |  } Wn t k
 r | SYn Xz |  j | |  } Wd  | r | j	   Xt
 j j |  \ } } t
 j j |  \ }	 }
 | d  k	 rd | } t
 j j | d |	 | |
 f  } t |  } | | d <d | k rx| d rx| d d 7<t |  S)Nz)The file '%s' could not be found with %r.z.%sz%s%s%s   z?#   ?)r   r   r   stripexists
ValueErroropenOSErrorrA   closeossplitsplitextjoinr/   r   )r   r   r?   filenameparsed_name
clean_nameZopenedrA   r   rootexthashed_nameunparsed_namer   r   r   rT   T   s4    '	

zHashedFilesMixin.hashed_nameFc                s  t  j r  | r  | d } } na t |  \ } } t |  j j d  rS | } n. | f } | d k	 ru | | f 7} | |   } t   j |  }	 d | k }
 | s |
 rt t |	   } | r | d r | | d <|
 r | d r | d d 7<t	 |  }	 t
 |	  S)	z:
        Return the non-hashed URL in DEBUG mode.
         /Nz?#   rC   rB   rD   )r   DEBUGr   r   r   endswithr   urlr/   r   r   )r   Zhashed_name_funcr   forcer+   rT   fragmentrQ   r   Z	final_urlZquery_fragmenturlparts)r   r   r   _urlv   s&    		
zHashedFilesMixin._urlc             C   s   |  j  |  j | |  S)z:
        Return the non-hashed URL in DEBUG mode.
        )r_   stored_name)r   r   r\   r   r   r   r[      s    zHashedFilesMixin.urlc                s4    d k r  j        f d d   } | S)zJ
        Return the custom URL converter for the given file name.
        Nc       	         s|  |  j    \ } } t j d |  r( | S| j d  rN | j t j  rN | St |  \ } } | j d  r | j t j  s t  | t t j  d  } nE t	 j
 d k r  n  j t	 j
 d  } t j t j |  |  }  j  j t |  d d d   } d j | j d  d d
  | j d  d d   } | rn| d | k rc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]+:rW   Nr\   Tr+      z?##rc   )groupsr1   match
startswithr   r   r   AssertionErrorlenrK   sepreplace	posixpathrN   dirnamer_   _stored_namer   rL   )	Zmatchobjmatchedr[   Zurl_pathr]   Ztarget_nameZsource_nameZ
hashed_urlZtransformed_url)r+   r   r   r8   r   r   	converter   s$    "*9 z1HashedFilesMixin.url_converter.<locals>.converter)r0   )r   r   r+   r8   ro   r   )r+   r   r   r8   r   url_converter   s    	-zHashedFilesMixin.url_converterc             +   s  | r
 d Si  }  f d d     D } x7  j    | |  D]  \ } } } }	 | | | f Vq? W  f d d   | D   xj t  j  D]Y }
 d } xC  j    | |  D], \ } } } } | | | f V| p | } q W| s Pq W| rd d t d  f V j 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 Sr   )r   r*   ).0r   )r   r   r   
<listcomp>   s   	 z1HashedFilesMixin.post_process.<locals>.<listcomp>c                s   i  |  ] }   | |  q Sr   r   )rq   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+   r=   )r   rs   dry_runoptionsr+   adjustable_pathsr   rT   	processed_isubstitutionsZsubstr   )rs   r   r   post_process   s"    ((zHashedFilesMixin.post_processc             c   s  d d   } xt  | d | d d D]y} d } | | \ } } | j |  K}	 |  j |  }
 |  j |
  } | | k r |  j | |	  } n
 | | } t |	 d  r |	 j d  |  j |  } d } | | k rI| } |	 j   j	 t
 j  } x |  j j   D] \ } } t | | f  rxx | D]p \ } } |  j | | |  } y | j | |  } Wq,t k
 r} z | d  | d f VWYd  d  } ~ Xq,Xq,WqW| r|  j |  t | j    } |  j r|  j | |  |  j | |  } |  j |  r|  j |  |  j | |  } |  j |  } | | k rCd } d } | s|| s|d } |  j | |	  } |  j |  } | | | <| | | | f VWd  QRXq% Wd  S)	Nc             S   s   t  |  j t j   S)N)rh   rL   rK   ri   )r   r   r   r   
path_level  s    z2HashedFilesMixin._post_process.<locals>.path_levelkeyreverseTseekr   F)sortedrH   rQ   hash_keyrT   hasattrr   rF   readdecoder   ZFILE_CHARSETr*   itemsr   rp   subrG   deleter   encodekeep_intermediate_files_save)r   rs   r{   r+   r   r   r   Zstorager   Zoriginal_filecleaned_namer   rT   Zhashed_file_existsr|   Zold_hashed_namer?   r6   r,   r7   r8   ro   exccontent_fileZ
saved_namer   r   r   ru     sZ    
,	
zHashedFilesMixin._post_processc             C   s   | j  d d  S)N\rW   )rj   )r   r   r   r   r   rQ   I  s    zHashedFilesMixin.clean_namec             C   s   | S)Nr   )r   r   r   r   r   r   L  s    zHashedFilesMixin.hash_keyc             C   sd   t  j |  } |  j |  } |  j |  } | j |  } | d  k r` |  j |  j |   } | S)N)rk   normpathrQ   r   getrT   )r   r   r+   r   r   
cache_namer   r   r   rm   O  s    zHashedFilesMixin._stored_namec             C   s   |  j  |  } |  j |  } |  j j |  } | r: | S| } xb t |  j d  D]M } |  j  |  j | d d  d |  } | | k r | |  j | <| S| } qT Wt d | |  f   d  S)Nra   r?   rO   z*The name '%s' could not be hashed with %r.)rQ   r   r+   r   rv   rw   rT   rG   )r   r   r   r   r   Zintermediate_namer~   r   r   r   r`   [  s    
zHashedFilesMixin.stored_namer(   r)   r'   r   r&   r   )r   )r    r!   r"   r0   rw   r,   r   r   rA   rT   r_   r[   rp   r   ru   rQ   r   rm   r`   r   r   )r   r   r$   1   s$     "60Hr$   c                   s|   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   S)ManifestFilesMixinz1.0zstaticfiles.jsonTFc                s&   t    j | |   |  j   |  _ d  S)N)r   r   load_manifestr+   )r   r   r   )r   r   r   r   y  s    zManifestFilesMixin.__init__c             C   sM   y0 |  j  |  j   } | j   j   SWd  QRXWn t k
 rH d  SYn Xd  S)N)rH   manifest_namer   r   FileNotFoundError)r   manifestr   r   r   read_manifest}  s
    z ManifestFilesMixin.read_manifestc             C   s   |  j    } | d  k r i  Sy t j |  } Wn t j k
 rF Yn, X| j d  } | d k rr | j d i   St d |  j |  j f   d  S)Nversionz1.0rs   z(Couldn't load manifest '%s' (version %s))r   jsonloadsJSONDecodeErrorr   rG   r   manifest_version)r   r?   Zstoredr   r   r   r   r     s    z ManifestFilesMixin.load_manifestc             /   s>   i  |  _  t   j | |   Ed  H| j d  s: |  j   d  S)Nry   )r+   r   r   r   save_manifest)r   r   r   )r   r   r   r     s    	zManifestFilesMixin.post_processc             C   sl   d |  j  d |  j i } |  j |  j  r: |  j |  j  t j |  j   } |  j |  j t	 |   d  S)Nrs   r   )
r+   r   rF   r   r   r   dumpsr   r   r   )r   payloadcontentsr   r   r   r     s
    z ManifestFilesMixin.save_manifestc             C   s   t  t |   } | j j   } |  j |  } |  j j |  } | d  k r |  j rg t d |   |  j	 |  j
 |   } t |  } | | d <d | k r | d r | d d 7<t |  S)Nz+Missing staticfiles manifest entry for '%s'rB   z?#rC   rD   )r   r   r   rE   r   r+   r   manifest_strictrG   rQ   rT   r/   r   )r   r   rP   rQ   r   r   rU   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   s  s   r   c               @   sa   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   r   valuer   r   r   __setitem__  s    z_MappingCache.__setitem__c             C   s2   |  j  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  j   d  S)N)r
   clear)r   r   r   r   r     s    z_MappingCache.clearc             C   s   |  j  j |  d  S)N)r
   Zset_many)r   datar   r   r   r=     s    z_MappingCache.updateNc             C   s)   y |  | SWn t  k
 r$ | SYn Xd  S)N)r   )r   r   defaultr   r   r   r     s    z_MappingCache.get)
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   S)CachedFilesMixinc                sR   t    j | |   y t t d  |  _ Wn! t k
 rM t t  |  _ Yn Xd  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  j |  j |  j    j   } d | S)Nzstaticfiles:%s)r:   r;   rQ   r   r>   )r   r   r   r   r   r   r     s    $zCachedFilesMixin.hash_key)r    r!   r"   r   r   r   r   )r   r   r     s   r   c                   s(   e  Z d  Z d Z   f d d   Z   S)CachedStaticFilesStoragezh
    A static file system storage backend which also saves
    hashed copies of the files it saves.
    c                s-   t  j d t d d t   j | |   d  S)NzNCachedStaticFilesStorage is deprecated in favor of ManifestStaticFilesStorage.
stacklevelrB   )warningswarnr   r   r   )r   r   r   )r   r   r   r     s    z!CachedStaticFilesStorage.__init__)r    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   ))r:   r   rK   rk   r1   r   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.deprecationr   Zdjango.utils.functionalr   r   r$   r   r   r   r   r   r   Zstaticfiles_storager   r   r   r   <module>   s0   " C?