o 3aD@sddlZddlZddlZddlZddlZddlmZmZmZm Z ddl m Z ddl m Z mZddlmZddlmZddlmZmZddlmZGd d d eZGd d d ZGd ddeZGdddeeZGdddeZeZdS)N)unquote urldefragurlsplit urlunsplit)settings)check_settingsmatches_patterns)ImproperlyConfigured) ContentFile)FileSystemStorageget_storage_class) LazyObjectcs.eZdZdZdfdd ZfddZZS)StaticFilesStoragez Standard file system storage for static files. The defaults for ``location`` and ``base_url`` are ``STATIC_ROOT`` and ``STATIC_URL``. NcsX|durtj}|durtj}t|tj||g|Ri||s*d|_d|_dSdSN)r STATIC_ROOT STATIC_URLrsuper__init__ base_locationlocation)selfrbase_urlargskwargs __class__D/usr/lib/python3/dist-packages/django/contrib/staticfiles/storage.pyrs zStaticFilesStorage.__init__cs|jstdt|S)NzaYou're using the staticfiles app without having set the STATIC_ROOT setting to a filesystem path.)rr rpathrnamerrrr$s zStaticFilesStorage.pathNN)__name__ __module__ __qualname____doc__rr __classcell__rrrrrs rcseZdZdZdZdZdZfddZddd Zd d d Z d!fd d Z d"ddZ dddZ d"ddZ ddZddZddZddZddZZS)#HashedFilesMixinz url("%s")))z*.css)z#(url\(['"]{0,1}\s*(.*?)["']{0,1}\)))z(@import\s*["']\s*(.*?)["'])z@import url("%s")Tcstj|i|i|_i|_|jD]+\}}|D]$}t|ttfr&|\}}n|j}t |t j }|j |g ||fqqdSr)rr _patterns hashed_filespatterns isinstancetuplelistdefault_templaterecompile IGNORECASE setdefaultappend)rrr extensionr+patterntemplatecompiledrrrr7s zHashedFilesMixin.__init__NcCs<|durdSt}|D]}||q|ddS)zU Return a hash of the file with the given name and optional content. N )hashlibmd5chunksupdate hexdigest)rr contentr;chunkrrr file_hashDs   zHashedFilesMixin.file_hashc Cs*tt|}|j}|rtt|jp|}|du}|r>||s+td||fz||}Wn ty=|YSwz|||}W|rL| n|rT| wwt j |\}}t j |\} } |rkd|nd}t j |d| || f} t|} | | d<d|vr| ds| dd7<t| S) Nz)The file '%s' could not be found with %r.z.%sz%s%s%s?#?)rrrstripexists ValueErroropenOSErrorrAcloseossplitsplitextjoinr.r) rr r?filename parsed_name clean_nameopenedrArrootext hashed_name unparsed_namerrrrWOs>      zHashedFilesMixin.hashed_nameFc stjr |s |d}}n!t|\}}t|jdr|}n|f}|dur(||f7}||}t|} d|v} |s:| r\tt| } |rJ| dsJ|| d<| rX| dsX| dd7<t | } t | S) : Return the non-hashed URL in DEBUG mode. rB/NrDrErCrF) rDEBUGrrrendswithrurlr.rr) rhashed_name_funcr forcer*rWfragmentrSr final_urlquery_fragmenturlpartsrrr_urlps&        zHashedFilesMixin._urlcCs||j||S)rY)re stored_name)rr r`rrrr^szHashedFilesMixin.urlcs$durjfdd}|S)zJ Return the custom URL converter for the given file name. Nc s|\}}td|r|S|dr|tjs|St|\}}|dr8|tjs.J|ttjd}ntj dkr?n tj d}t t ||}jjt|dd}d |ddd|ddd}|r~|d|vrydnd|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]+:rZNT)r`r*rD#)groupsr0match startswithrrrlenrMsepreplace posixpathrPdirnamere _stored_namerrN) matchobjmatchedr^url_pathra target_name source_name hashed_urltransformed_urlr*r rr7rr converters&     * z1HashedFilesMixin.url_converter..converter)r/)rr r*r7rzrryr url_converters-zHashedFilesMixin.url_converterc +s|rdSi}fddD}||D] \}}}} |||fVqfdd|DtjD] } d} ||D]\}}}} |||fV| pL| } q=| sRnq2| r]ddtdfVj|dS) 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. Ncsg|] }t|jr|qSr)rr).0rrrr s  z1HashedFilesMixin.post_process..csi|]}||qSrrr|)pathsrr sz1HashedFilesMixin.post_process..FAllz!Max post-process passes exceeded.) _post_processrangemax_post_process_passes RuntimeErrorr*r=) rrdry_runoptionsr*adjustable_pathsr rW processed_i substitutionssubstr)rrr post_processs*   zHashedFilesMixin.post_processccsdd}t||ddD]}d}||\}}||} ||} || } | |vr1||| } n|| } t| dr?| d|| } d}||vr| }|  d}|j D]9\}}t ||fr|D],\}}| |||}z|||}Wqdty}z |d|dfVWYd}~qdd}~wwqX| r|| t|}|jr|| ||||} || r|| || |}||} || krd}d}|s| sd}|| | }||} | || <|| ||fVWdn1swYq dS) NcSst|tjSr)rlrNrMrm)r rrr path_levelsz2HashedFilesMixin._post_process..path_levelT)keyreverseseekrFzutf-8)sortedrJrShash_keyrWhasattrrrHreaddecoder)itemsrr{subrIdeleter encodekeep_intermediate_files_save)rrrr*rr rstorager original_file cleaned_namerrWhashed_file_existsrold_hashed_namer?r5r+r6r7rzexc content_file saved_namerrrrsh                   zHashedFilesMixin._post_processcCs |ddS)N\rZ)rnrrrrrSCs zHashedFilesMixin.clean_namecCs|SrrrrrrrFszHashedFilesMixin.hash_keycCsDt|}||}||}||}|dur |||}|Sr)ronormpathrSrgetrW)rr r*rr cache_namerrrrqIs    zHashedFilesMixin._stored_namecCs||}||}|j|}|r|S|}t|jdD]}||j|d|d}||kr7||j|<|S|}qtd||f)N)r?rQz*The name '%s' could not be hashed with %r.)rSrr*rrrrWrI)rr rrrintermediate_namerrrrrfUs    zHashedFilesMixin.stored_namerr!)FN)F)r"r#r$r/rr+rrrArWrer^r{rrrSrrqrfr&rrrrr',s"  !   60H r'csXeZdZdZdZdZdZfddZddZd d Z fd d Z d dZ ddZ Z S)ManifestFilesMixin1.0zstaticfiles.jsonTFcs tj|i|||_dSr)rr load_manifestr*rrrrrrrsszManifestFilesMixin.__init__cCsVz ||j}|WdWS1swYWdSty*YdSwr)rJ manifest_namerrFileNotFoundError)rmanifestrrr read_manifestws ( z ManifestFilesMixin.read_manifestcCsj|}|dur iSzt|}Wn tjyYnw|d}|dkr+|diStd|j|jf)Nversionrrz(Couldn't load manifest '%s' (version %s))rjsonloadsJSONDecodeErrorrrIrmanifest_version)rr?storedrrrrr~s   z ManifestFilesMixin.load_manifestc/s:i|_tj|i|EdH|ds|dSdS)Nr)r*rrr save_manifestrrrrrs   zManifestFilesMixin.post_processcCsJ|j|jd}||jr||jt|}||jt |dS)N)rr) r*rrHrrrdumpsrrr )rpayloadcontentsrrrrs   z ManifestFilesMixin.save_manifestcCstt|}|j}||}|j|}|dur+|jr#td|| | |}t |}||d<d|vrC|dsC|dd7<t |S)Nz+Missing staticfiles manifest entry for '%s'rCrDrErF) rrrrGrr*rmanifest_strictrIrSrWr.r)rr rRrSrrrXrrrrfs     zManifestFilesMixin.stored_name)r"r#r$rrrrrrrrrrfr&rrrrrms  rc@seZdZdZdS)ManifestStaticFilesStoragezh A static file system storage backend which also saves hashed copies of the files it saves. N)r"r#r$r%rrrrrsrc@seZdZddZdS)ConfiguredStoragecCsttj|_dSr)r rSTATICFILES_STORAGE_wrappedr~rrr_setupszConfiguredStorage._setupN)r"r#r$rrrrrrs r)r:rrMror0 urllib.parserrrr django.confr django.contrib.staticfiles.utilsrrdjango.core.exceptionsr django.core.files.baser django.core.files.storager r django.utils.functionalr rr'rrrstaticfiles_storagerrrrs(    C?