o
    &zh                     @   s   d Z ddlZddlmZmZ ddlmZ ddlmZ ddl	m
Z
 ddlmZ d	d
 ZG dd dZG dd dZG dd dZe ZdS )a  
Source groups are the means by which image spec sources are identified. They
have two responsibilities:

1. To dispatch ``source_saved`` signals. (These will be relayed to the
   corresponding specs' cache file strategies.)
2. To provide the source files that they represent, via a generator method named
   ``files()``. (This is used by the generateimages management command for
   "pre-caching" image files.)

    N)	post_init	post_savewraps   )LazyImageCacheFile)source_saved)get_nonabstract_descendantsc                    s   t   fdd}|S )z
    A method decorator that filters out signals coming from models that don't
    have fields that function as ImageFieldSourceGroup sources.

    c                    sD   t |sd S | jD ]}t||jr | fd|i|  d S q
d S )Nsender)inspectisclass_source_groups
issubclassmodel_class)selfr
   kwargssrcfn V/var/www/html/kangema/venv/lib/python3.10/site-packages/imagekit/specs/sourcegroups.pyreceiver   s   

z#ik_model_receiver.<locals>.receiverr   )r   r   r   r   r   ik_model_receiver   s   
r   c                   @   s\   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Ze	dddZ
e	dddZdd ZdS )ModelSignalRoutera  
    Normally, ``ImageFieldSourceGroup`` would be directly responsible for
    watching for changes on the model field it represents. However, Django does
    not dispatch events for abstract base classes. Therefore, we must listen for
    the signals on all models and filter out those that aren't represented by
    ``ImageFieldSourceGroup``s. This class encapsulates that functionality.

    Related:
        https://github.com/matthewwithanm/django-imagekit/issues/126
        https://code.djangoproject.com/ticket/9318

    c                 C   s.   g | _ d}tj| j|d tj| j|d d S )Nik_spec_field_receivers)dispatch_uid)r   r   connectpost_init_receiverr   post_save_receiver)r   uidr   r   r   __init__9   s   zModelSignalRouter.__init__c                 C   s   | j | d S N)r   append)r   source_groupr   r   r   add?      zModelSignalRouter.addc                 C   s   t |di |_d S )N_ik)getattrr&   r   instancer   r   r   init_instanceB   s   zModelSignalRouter.init_instancec                    s2   |     fdd|  D  jd<  jd S )z
        Stores hashes of the source image files so that they can be compared
        later to see whether the source image has changed (and therefore whether
        the spec file needs to be regenerated).

        c                    s   i | ]
}|t t |qS r   )hashr'   ).0attnamer)   r   r   
<dictcomp>M   s    z:ModelSignalRouter.update_source_hashes.<locals>.<dictcomp>source_hashes)r*   get_source_fieldsr&   r(   r   r.   r   update_source_hashesE   s
   


z&ModelSignalRouter.update_source_hashesc                    s    fdd| j D S )zN
        Returns a list of the source fields for the given instance.

        c                    s   h | ]}t  |jr|jqS r   )
isinstancer   image_field)r,   r   r.   r   r   	<setcomp>W   s    
z6ModelSignalRouter.get_source_fields.<locals>.<setcomp>)r   r(   r   r.   r   r1   R   s   
z#ModelSignalRouter.get_source_fieldsNFc                 K   s   |s=|  | |jdi  }| |}| |D ]$}	|r#|	|vr#qt||	}
|
r<||	||	 kr<| t|
|||	 qd S d S )Nr0   )	r*   r&   getcopyr2   r1   r'   dispatch_signalr   )r   r
   r)   createdupdate_fieldsrawr   
old_hashes
new_hashesr-   filer   r   r   r   \   s   


z$ModelSignalRouter.post_save_receiverc                    sF   |  | | |  fdd|jjD }dd | D |jd< d S )Nc                    s   i | ]}|j  v r|j |qS r   )name)r,   fieldsource_fieldsr   r   r/   o   s
    
z8ModelSignalRouter.post_init_receiver.<locals>.<dictcomp>c                 S   s   i | ]	\}}|t |qS r   )r+   )r,   r-   
file_fieldr   r   r   r/   s   s    r0   )r*   r1   _metalocal_fieldsitemsr&   )r   r
   r)   r   rE   r   rA   r   r   k   s   


z$ModelSignalRouter.post_init_receiverc                 C   s4   | j D ]}t||jr|j|kr|j||d qdS )z
        Dispatch the signal for each of the matching source groups. Note that
        more than one source can have the same model and image_field; it's
        important that we dispatch the signal for each.

        )r
   sourceN)r   r   r   r4   send)r   signalr>   r   r)   r-   r#   r   r   r   r8   w   s
   
z!ModelSignalRouter.dispatch_signal)NFNFr!   )__name__
__module____qualname____doc__r    r$   r*   r2   r1   r   r   r   r8   r   r   r   r   r   +   s    
r   c                   @   s    e Zd ZdZdd Zdd ZdS )ImageFieldSourceGroupzt
    A source group that represents a particular field across all instances of a
    model and its subclasses.

    c                 C   s   || _ || _t|  d S r!   )r   r4   signal_routerr$   )r   r   r4   r   r   r   r       s   zImageFieldSourceGroup.__init__c                 c   s8    t | jD ]}|j  D ]	}t|| jV  qqdS )z
        A generator that returns the source files that this source group
        represents; in this case, a particular field of every instance of a
        particular model and its subclasses.

        N)r	   r   objectsalliteratorr'   r4   )r   modelr)   r   r   r   files   s   zImageFieldSourceGroup.filesN)rJ   rK   rL   rM   r    rT   r   r   r   r   rN      s    rN   c                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )SourceGroupFilesGeneratorzO
    A Python generator that yields cache file objects for source groups.

    c                 C   s   || _ || _d S r!   )r#   generator_id)r   r#   rV   r   r   r   r       s   
z"SourceGroupFilesGenerator.__init__c                 C   s   t || jo| j|jkS r!   )r3   	__class____dict__r   otherr   r   r   __eq__   s   
z SourceGroupFilesGenerator.__eq__c                 C   s   |  | S r!   )r[   rY   r   r   r   __ne__   s   z SourceGroupFilesGenerator.__ne__c                 C   s   t | j| jfS r!   )r+   r#   rV   )r   r   r   r   __hash__   r%   z"SourceGroupFilesGenerator.__hash__c                 c   s&    | j  D ]
}t| j|dV  qd S )N)rG   )r#   rT   r   rV   )r   source_filer   r   r   __call__   s   
z"SourceGroupFilesGenerator.__call__N)	rJ   rK   rL   rM   r    r[   r\   r]   r_   r   r   r   r   rU      s    rU   )rM   r   django.db.models.signalsr   r   django.utils.functionalr   
cachefilesr   signalsr   utilsr	   r   r   rN   rU   rO   r   r   r   r   <module>   s    X
