o
    a"<f:                     @   s   d dl Z d dlZd dl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Zd dlmZmZ d dlZd dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZmZmZ d dlmZ d dlmZmZm Z  d dl!m"Z" e Z#G dd deZ$dS )    N)Lock)OrderedDictdefaultdictfnmatch)import_module)BaseCommandCommandError)Context	smart_str)get_template)engines)get_offline_hexdigestwrite_offline_manifestget_offline_manifest)settings)OfflineGenerationErrorTemplateSyntaxErrorTemplateDoesNotExist)get_mod_funcc                   @   sj   e Zd ZdZejdkrg ZndZdd Zdd Zdd	 Z	d
d Z
edd ZdddZdd Zdd ZdS )Commandz6Compress content outside of the request/response cycle)      Fc                 C   sV   |j dddddd |j ddd	d
ddd |j dd	d
ddd |j dg dddd d S )Nz--extensionz-eappend
extensionszwThe file extension(s) to examine (default: ".html", separate multiple extensions with commas, or use -e multiple times))actiondesthelpz-fz--forceF
store_truez\Force the generation of compressed content even if the COMPRESS_ENABLED setting is not True.force)defaultr   r   r   z--follow-linkszFollow symlinks when traversing the COMPRESS_ROOT (which defaults to STATIC_ROOT). Be aware that using this can lead to infinite recursion if a link points to a parent directory of itself.follow_linksz--enginezSpecifies the templating engine. jinja2 and django are supported. It may be a specified more than once for multiple engines. If not specified, django engine is used.r   )add_argument)selfparser r&   ^/var/www/html/kck/venv/lib/python3.10/site-packages/compressor/management/commands/compress.pyadd_arguments#   s   


zCommand.add_argumentsc                 C   sf   g }t  D ]}t|dr||j|jj qg }|D ]}t|dr+||j q|| q|S )Nengineloaders)r   allhasattrextendr)   get_template_loadersr*   r   )r$   template_source_loaderser*   loaderr&   r&   r'   get_loaders6   s   

zCommand.get_loadersc                 C   sj   t drt jnd}|dkr ddlm} t  }|||d}|S |dkr1ddlm} ||d	}|S td
)NFILE_CHARSETzutf-8jinja2r   )Jinja2Parser)charsetenvdjango)DjangoParser)r6   z$Invalid templating engine specified.)	r   is_overriddenr3   compressor.offline.jinja2r5   COMPRESS_JINJA2_GET_ENVIRONMENTcompressor.offline.djangor9   r   )r$   r)   r6   r5   r7   r%   r9   r&   r&   r'   __get_parserP   s   
zCommand.__get_parserc                    s  |   stdt }|dkr|t }|   D ].}z t|j}	t|	dd}
|
du r+|j}
|dd |
dD  W q tt	t
fyD   Y qw |sKtd|d	kr[|d
d| d  |D ]tj|dD ]\}}|fdd|D  qfq]n$|dkrt   rt dr|t fdd jfdddD O }|std|d	kr|dd| d  tj}t|trzt|\}	}tt|	| }W n" t	tt
fy } z	tdtj|f d}~ww t|ttfs|g}| |}g }|dkr|d |D ]x}z||}||_|| W q ty-   |dkr*|d|  Y q tyP } z|dkrE|d|t|f  W Y d}~qd}~w t yf   |dkrc|d|  Y q t!y|   |dkry|d|  Y qw d}d}t" }g }|D ]}t" }|D ]Z}t#|$|}zt|j%||d }W n' t tfy } z|dkr|d!|jt|f  W Y d}~qd}~ww |r|&|t" }|D ]}|d7 }|&|g | qאqt'j(j)d"d#}|* D ]\}}||_+||_,|-| j.||||| q|j/d$d% |d7 }q|r|d |s&td&|dkr7|d't0|||f  |t0||1 fS )(a'  
        Searches templates containing 'compress' nodes and compresses them
        "offline" -- outside of the request/response cycle.

        The result is cached with a cache-key derived from the content of the
        compress nodes (not the content of the possibly linked files!).
        zzNo template loaders defined. You must set TEMPLATE_LOADERS in your settings or set 'loaders' in your TEMPLATES dictionary.r8   get_template_sourcesNc                 s   s    | ]}t |V  qd S )Nr   ).0originr&   r&   r'   	<genexpr>y   s    z#Command.compress.<locals>.<genexpr> zNo template paths found. None of the configured template loaders provided template paths. See https://docs.djangoproject.com/en/2.1/topics/templates/ for more information on template loaders.r   zConsidering paths:
	z
	
)followlinksc                 3   sH    | ]   d st fddD rtjtj V  qdS ).c                 3   s    | ]
}t  d | V  qdS )z*%sNr   )r@   globnamer&   r'   rB      s    z-Command.compress.<locals>.<genexpr>.<genexpr>N)
startswithanyospathrelpathjoin)r@   )r   rM   rootrH   r'   rB      s    
"r4   list_templatesc                    s   g | ]} j  |d  qS )   )r1   
get_source)r@   template)r7   r&   r'   
<listcomp>   s    z$Command.compress.<locals>.<listcomp>c                    s   t j| d  v S )N)rL   rM   splitext)_path)r   r&   r'   <lambda>      z"Command.compress.<locals>.<lambda>)filter_funcz[No templates found. Make sure your TEMPLATE_LOADERS and TEMPLATE_DIRS settings are correct.zFound templates:
	z/Couldn't import offline context function %s: %srR   zCompressing... zUnreadable template at: %s
zInvalid template %s: %s
zNon-existent template at: %s
z4UnicodeDecodeError while trying to read template %s
r   )contextzError parsing template %s: %s
   )max_workersT)waitz|No 'compress' template tags found in templates.Try running compress command with --follow-links and/or--extension=EXTENSIONSzCdone
Compressed %d block(s) from %d template(s) for %d context(s).
)2r2   r   setr   
__module__getattrr?   updateImportErrorAttributeError	TypeErrorwriterO   rL   walkr   r<   r,   rQ   COMPRESS_OFFLINE_CONTEXT
isinstancestrr   listtuple_Command__get_parserparsetemplate_namer   IOErrorr   r   r   UnicodeDecodeErrorr   r
   get_init_context
walk_nodes
setdefault
concurrentfuturesThreadPoolExecutoritems_log_log_verbositysubmit_compress_templateshutdownlenvalues)r$   r)   r   	verbosityr"   log	templatespathsr1   moduler?   dirsfilescontextsfunctionr0   r%   fine_templatesrp   rT   contexts_countnodes_countoffline_manifesterrorscontext_dictcompressor_nodesr\   nodestemplate_nodesnodepoolr&   )r7   r   rM   rP   r'   compressa   s   	













zCommand.compressc                 C   s  |  D ]\}}|D ]}|  |||sq
|||| ||||}t|}	t |	| v r8	 W d    q
d | |	< W d    n1 sFw   Y  z	||||}
W n& tyz } z|	t
d|jt|f  | |	= W Y d }~  d S d }~ww |
tjtj}
|
| |	< |  q
qd S )Nz)An error occurred during rendering %s: %s)ry   pushprocess_templateprocess_noderender_nodelistr   offline_manifest_lockrender_node	Exceptionr   r	   rp   r   replacer   COMPRESS_URLCOMPRESS_URL_PLACEHOLDERpop)r   r   r%   rT   r   r   node_contextsr\   renderedkeyresultr0   r&   r&   r'   r}      s>   

zCommand._compress_templatehtmlc                 C   sZ   g }|D ]}| |ddd qt|D ]\}}|ds(d||  ||< qt|S )a  
        organizes multiple extensions that are separated with commas or
        passed by using --extension/-e multiple times.

        for example: running 'django-admin compress -e js,txt -e xhtml -a'
        would result in an extension list: ['.js', '.txt', '.xhtml']

        >>> handle_extensions(['.html', 'html,js,py,py,py,.py', 'py,.py'])
        ['.html', '.js']
        >>> handle_extensions(['.html, txt,.tpl'])
        ['.html', '.tpl', '.txt']
         rC   ,rF   z.%s)r-   r   split	enumeraterJ   r`   )r$   r   ext_listextir&   r&   r'   handle_extensions  s   
zCommand.handle_extensionsc                 K   s   | j di | d S )Nr&   )handle_inner)r$   optionsr&   r&   r'   handle,  rZ   zCommand.handlec                 K   s   t js|dstdt js|dstd|dtj}|dd}|dd}| |d	p4d
g}dd |dg D pCdg}i }d}g }	|D ]}
| |
||||\}}}|		| ||7 }|
| qLt| ||	fS )Nr    zTCompressor is disabled. Set the COMPRESS_ENABLED setting or use --force to override.zUOffline compression is disabled. Set COMPRESS_OFFLINE or use the --force to override.r   r   rR   r"   Fr   r   c                 S   s   g | ]}|  qS r&   )strip)r@   r0   r&   r&   r'   rU   >  s    z(Command.handle_inner.<locals>.<listcomp>r   r8   r   )r   COMPRESS_ENABLEDgetr	   COMPRESS_OFFLINEsysstdoutr   r   r-   rc   r   )r$   r   r   r   r"   r   r   final_offline_manifestfinal_block_countfinal_resultsr)   r   block_countresultsr&   r&   r'   r   /  s0   

zCommand.handle_innerN)r   )__name__ra   __qualname__r   r8   VERSIONrequires_system_checksr(   r2   rn   r   staticmethodr}   r   r   r   r&   r&   r&   r'   r      s    
 

"r   )%rL   r   concurrent.futuresrv   	threadingr   collectionsr   r   r   	importlibr   r8   django.core.management.baser   r	   django.templater
   django.utils.encodingr   django.template.loaderr   r   compressor.cacher   r   r   compressor.confr   compressor.exceptionsr   r   r   compressor.utilsr   r   r   r&   r&   r&   r'   <module>   s(   