o
    ˷eK                     @   s   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 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)md5)
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                    sX   |d u rt j}|d u rt j}t| t j||g|R i | |s*d | _d | _d S d S N)r   STATIC_ROOT
STATIC_URLr   super__init__base_locationlocation)selfr   base_urlargskwargs	__class__ Y/var/www/ideatree/venv/lib/python3.10/site-packages/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("%(url)s")   ))z*.css)z5(?P<matched>url\(['"]{0,1}\s*(?P<url>.*?)["']{0,1}\)))z.(?P<matched>@import\s*["']\s*(?P<url>.*?)["'])z@import url("%(url)s"))zI(?m)(?P<matched>)^(/\*#[ \t](?-i:sourceMappingURL)=(?P<url>.*)[ \t]*\*/)$z/*# sourceMappingURL=%(url)s */)z*.js))z;(?m)(?P<matched>)^(//# (?-i:sourceMappingURL)=(?P<url>.*))$z//# sourceMappingURL=%(url)sTc                    s   t  j|i | i | _i | _| jD ]+\}}|D ]$}t|ttfr&|\}}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templatecompiledr   r   r   r   P   s   
zHashedFilesMixin.__init__Nc                 C   s>   |du rdS t dd}| D ]}|| q| dd S )zU
        Return a hash of the file with the given name and optional content.
        NF)usedforsecurity   )r   chunksupdate	hexdigest)r   r!   contenthasherchunkr   r   r   	file_hash]   s   
zHashedFilesMixin.file_hashc                 C   s*  t t|}|j }|rt t|j p|}|d u }|r>| |s+td|| f z| |}W n ty=   | Y S w z| ||}W |rL|	  n|rT|	  w w t
j|\}}t
j|\}	}
|rkd| nd}t
j|d|	||
f }t|}||d< d|v 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OSErrorrB   closeossplitsplitextjoinr/   r   )r   r!   r?   filenameparsed_name
clean_nameopenedrB   r   rootexthashed_nameunparsed_namer   r   r   rX   h   s>   



zHashedFilesMixin.hashed_nameFc                    s   t jr|s|d}}n!t|\}}t|jdr|}n|f}|dur(||f7 }|| }t |}	d|v }
|s:|
r\tt|	}|rJ|d sJ||d< |
rX|d sX|d  d7  < t	|}	t
|	S )	:
        Return the non-hashed URL in DEBUG mode.
        rC   /NrE      rF   rD   rG   )r   DEBUGr   r   r   endswithr   urlr/   r   r   )r   hashed_name_funcr!   forcer+   rX   fragmentrT   r   	final_urlquery_fragmenturlpartsr   r   r   _url   s&   

zHashedFilesMixin._urlc                 C   s   |  | j||S )rZ   )rf   stored_name)r   r!   ra   r   r   r   r_      s   zHashedFilesMixin.urlc                    s$   du rj  fdd}|S )zJ
        Return the custom URL converter for the given file name.
        Nc           
         s  |   }|d }|d }td|r|S |dr!|tjs!|S t|\}}|dr>|tjs4J |ttjd }ntj	dkrEn
tj	d}tt||}jjt|d d}d|ddd |ddd  }	|r|	d	|v rd	nd
| 7 }	t|	|d< | 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.
            matchedr_   z^[a-z]+:r[   NT)ra   r+   rE   #)	groupdictr1   match
startswithr   r   r   lenrN   sepreplace	posixpathrQ   dirnamerf   _stored_namer   rO   )
matchobjmatchesrh   r_   url_pathrb   target_namesource_name
hashed_urltransformed_urlr+   r!   r   r8   r   r   	converter   s4   
"z1HashedFilesMixin.url_converter.<locals>.converter)r0   )r   r!   r+   r8   r|   r   r{   r   url_converter   s   4zHashedFilesMixin.url_converterc                 +   s   |rdS i }fdd D }i }  ||D ]\}}}	}
||vs(t|	tr/|||	fV  q|||	f||< q fdd|D  d}tjD ]!}d}  ||D ]\}}}	}|||	f||< |pb|}qR|sh nqG|rsddtdfV  j| | E dH  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   r~   )pathsr   r   
<dictcomp>  s    z1HashedFilesMixin.post_process.<locals>.<dictcomp>FAllz!Max post-process passes exceeded.)	_post_processr-   	Exceptionrangemax_post_process_passesRuntimeErrorr+   r=   values)r   r   dry_runoptionsr+   adjustable_pathsprocessed_adjustable_pathsr!   rX   	processed_substitutionsisubstr   )r   r   r   post_process   s<   

zHashedFilesMixin.post_processc                 c   s   dd }t ||ddD ]}d}|| \}}||}	| |}
| |
}||vr1| ||	}n|| }t|	dr?|	d | |}d}||v r|}|	 	d}| j
 D ]9\}}t||fr|D ],\}}| |||}z|||}W qd ty } z|d |dfV  W Y d }~qdd }~ww qX|r| | t| }| jr| || | ||}| |r| | | ||}| |}||krd}d}|s|sd}| ||	}| |}|||< ||||fV  W d    n1 sw   Y  qd S )	Nc                 S   s   t | tjS r   )rn   rO   rN   ro   )r!   r   r   r   
path_level-  s   z2HashedFilesMixin._post_process.<locals>.path_levelT)keyreverseseekr   Fzutf-8)sortedrK   rT   hash_keyrX   hasattrr   rI   readdecoder*   itemsr   r}   subrJ   deleter
   encodekeep_intermediate_files_save)r   r   r   r+   r   r!   r   storager   original_filecleaned_namer   rX   hashed_file_existsr   old_hashed_namer?   r6   r,   r7   r8   r|   exccontent_file
saved_namer   r   r   r   +  sl   









zHashedFilesMixin._post_processc                 C   s   | ddS )N\r[   )rp   r    r   r   r   rT   u  s   zHashedFilesMixin.clean_namec                 C   s   |S r   r   r    r   r   r   r   x  s   zHashedFilesMixin.hash_keyc                 C   sD   t |}| |}| |}||}|d u r | | |}|S r   )rq   normpathrT   r   getrX   )r   r!   r+   r   r   
cache_namer   r   r   rs   {  s   



zHashedFilesMixin._stored_namec                 C   s   |  |}| |}| j|}|r|S |}t| jd D ]}|  | j|d |d}||kr7|| j|< |  S |}qtd|| f )N   )r?   rR   z*The name '%s' could not be hashed with %r.)rT   r   r+   r   r   r   rX   rJ   )r   r!   r   r   r   intermediate_namer   r   r   r   rg     s   


zHashedFilesMixin.stored_namer   r"   )FN)F)r#   r$   r%   r0   r   r,   r   r   rB   rX   rf   r_   r}   r   r   rT   r   rs   rg   r'   r   r   r   r   r(   /   s"    

"


=?Jr(   c                       s^   e Zd ZdZdZdZdZdd 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.jsonTFN)manifest_storagec                   s2   t  j|i | |d u r| }|| _|  | _d S r   )r   r   r   load_manifestr+   )r   r   r   r   r   r   r   r     s
   zManifestFilesMixin.__init__c                 C   sX   z!| j | j}|  W  d    W S 1 sw   Y  W d S  ty+   Y d S w r   )r   rK   manifest_namer   r   FileNotFoundError)r   manifestr   r   r   read_manifest  s   
(z ManifestFilesMixin.read_manifestc                 C   sj   |   }|d u r
i S zt|}W n
 tjy   Y nw |d}|dkr+|di S td| j| jf )Nversionr   r   z(Couldn't load manifest '%s' (version %s))r   jsonloadsJSONDecodeErrorr   rJ   r   manifest_version)r   r?   storedr   r   r   r   r     s    

z ManifestFilesMixin.load_manifestc                 /   s:    i | _ t j|i |E d H  |ds|   d S d S )Nr   )r+   r   r   r   save_manifest)r   r   r   r   r   r   r     s   
zManifestFilesMixin.post_processc                 C   sP   | j | jd}| j| jr| j| j t| }| j	| jt
| d S )N)r   r   )r+   r   r   rI   r   r   r   dumpsr   r   r
   )r   payloadcontentsr   r   r   r     s
   z ManifestFilesMixin.save_manifestc                 C   s   t t|}|j }| |}| j|}|d u r+| jr#td| | 	| 
|}t|}||d< d|v rC|d sC|d  d7  < t|S )Nz+Missing staticfiles manifest entry for '%s'rD   rE   rF   rG   )r   r   r   rH   r   r+   r   manifest_strictrJ   rT   rX   r/   r   )r   r!   rS   rT   r   r   rY   r   r   r   rg     s   

zManifestFilesMixin.stored_name)r#   r$   r%   r   r   r   r   r   r   r   r   r   rg   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 r   )r   r   STATICFILES_STORAGE_wrappedr   r   r   r   _setup  s   zConfiguredStorage._setupN)r#   r$   r%   r   r   r   r   r   r     s    r   )r   rN   rq   r1   urllib.parser   r   r   r   django.confr    django.contrib.staticfiles.utilsr   r   django.core.exceptionsr	   django.core.files.baser
   django.core.files.storager   r   django.utils.cryptor   django.utils.functionalr   r   r(   r   r   r   staticfiles_storager   r   r   r   <module>   s(      rF	
