o
    ›¨Êh2  ã                   @   sÊ   d dl Z d dlZd dl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 d dlmZmZ d dlmZ d d	lmZ d
d„ Zdd„ Zdd„ ZG dd„ dƒZG dd„ dƒZG dd„ dƒZdS )é    N)ÚOrderedDict)Úsettings)ÚImproperlyConfigured)Úmodule_has_submodule)Ú	constants)Ú
NotHandledÚSearchFieldError)Ú	importlib)Úhaystack_get_app_modulesc                 C   sJ   |   d¡}| ¡ }d |¡}t |¡}t||ƒs td||f ƒ‚t||ƒS )NÚ.z)The Python module '%s' has no '%s' class.)ÚsplitÚpopÚjoinr	   Úimport_moduleÚhasattrÚImportErrorÚgetattr)ÚpathÚ	path_bitsÚ
class_nameÚmodule_pathÚmodule_itself© r   úH/var/www/html/env/lib/python3.10/site-packages/haystack/utils/loading.pyÚimport_class   s   




ÿ
r   c                 C   ó*   |   d¡}t|ƒdk rtd|  ƒ‚t| ƒS )am  
    Loads a backend for interacting with the search engine.

    Requires a ``backend_path``. It should be a string resembling a Python
    import path, pointing to a ``BaseEngine`` subclass. The built-in options
    available include::

      * haystack.backends.solr.SolrEngine
      * haystack.backends.xapian.XapianEngine (third-party)
      * haystack.backends.whoosh.WhooshEngine
      * haystack.backends.simple.SimpleEngine

    If you've implemented a custom backend, you can provide the path to
    your backend & matching ``Engine`` class. For example::

      ``myapp.search_backends.CustomSolrEngine``

    r   é   zQThe provided backend '%s' is not a complete Python path to a BaseEngine subclass.©r   Úlenr   r   )Úfull_backend_pathr   r   r   r   Úload_backend!   s   
ÿÿr    c                 C   r   )aÓ  
    Loads a router for choosing which connection to use.

    Requires a ``full_router_path``. It should be a string resembling a Python
    import path, pointing to a ``BaseRouter`` subclass. The built-in options
    available include::

      * haystack.routers.DefaultRouter

    If you've implemented a custom backend, you can provide the path to
    your backend & matching ``Engine`` class. For example::

      ``myapp.search_routers.MasterSlaveRouter``

    r   r   zPThe provided router '%s' is not a complete Python path to a BaseRouter subclass.r   )Úfull_router_pathr   r   r   r   Úload_router?   s   
ÿÿr"   c                   @   s4   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ ZdS )ÚConnectionHandlerc                 C   s   || _ t ¡ | _d | _d S ©N)Úconnections_infoÚ	threadingÚlocalÚthread_localÚ_index)Úselfr%   r   r   r   Ú__init__[   s   

zConnectionHandler.__init__c                 C   sD   z| j | }W n ty   td| ƒ‚w | d¡s d|d< d S d S )Nz+The key '%s' isn't an available connection.ÚENGINEz-haystack.backends.simple_backend.SimpleEngine)r%   ÚKeyErrorr   Úget)r*   ÚaliasÚconnr   r   r   Úensure_defaults`   s   ÿÿ
ÿz!ConnectionHandler.ensure_defaultsc                 C   sd   t | jdƒsi | j_n|| jjv r| jj| S |  |¡ t| j| d ƒ|d�| jj|< | jj| S )NÚconnectionsr,   )Úusing)r   r(   r2   r1   r    r%   ©r*   Úkeyr   r   r   Ú__getitem__k   s   

ÿþzConnectionHandler.__getitem__c                 C   s@   t | jdƒs
i | j_z| jj|= W n	 ty   Y nw |  |¡S )Nr2   )r   r(   r2   r-   r6   r4   r   r   r   Úreloadw   s   ÿ
zConnectionHandler.reloadc                    s   ‡ fdd„ˆ j D ƒS )Nc                    s   g | ]}ˆ | ‘qS r   r   )Ú.0r/   ©r*   r   r   Ú
<listcomp>‚   s    z)ConnectionHandler.all.<locals>.<listcomp>)r%   r9   r   r9   r   Úall�   ó   zConnectionHandler.allN)Ú__name__Ú
__module__Ú__qualname__r+   r1   r6   r7   r;   r   r   r   r   r#   Z   s    
r#   c                   @   s8   e Zd Zdd„ Zedd„ ƒZdd„ Zdd„ Zd	d
„ ZdS )ÚConnectionRouterc                 C   s
   d | _ d S r$   )Ú_routersr9   r   r   r   r+   †   s   
zConnectionRouter.__init__c                 C   sT   | j d u r'dg}ttd|ƒ}t|ƒs|}g | _ |D ]}t|ƒ}| j  |ƒ ¡ q| j S )Nzhaystack.routers.DefaultRouterÚHAYSTACK_ROUTERS)rA   r   r   r   r"   Úappend)r*   Údefault_routersÚrouter_listÚrouter_pathÚrouter_classr   r   r   Úrouters‰   s   
zConnectionRouter.routersc                 K   sh   g }| j D ],}t||ƒr1t||ƒ}|di |¤Ž}|d ur1t|tƒr'| |¡ n| |¡ |s1 |S q|S )Nr   )rH   r   r   Ú
isinstanceÚstrrC   Úextend)r*   ÚactionÚmanyÚhintsÚconnsÚrouterÚaction_callableÚconnection_to_user   r   r   Ú_for_action˜   s   




€ zConnectionRouter._for_actionc                 K   s   | j di |¤ŽS )NÚ	for_writeT)rT   T©rS   ©r*   rN   r   r   r   rT   ª   s   zConnectionRouter.for_writec                 K   s   | j di |¤Žd S )NÚfor_readFr   )rW   FrU   rV   r   r   r   rW   ­   r<   zConnectionRouter.for_readN)	r=   r>   r?   r+   ÚpropertyrH   rS   rT   rW   r   r   r   r   r@   …   s    
r@   c                   @   st   e Zd Zddd„Zedd„ ƒZdd„ Zdd	„ Zdd
d„Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ ZdS )ÚUnifiedIndexNc                 C   s<   i | _ tƒ | _d| _|pg | _i | _tj| _i | _	i | _
d S ©NF)Ú_indexesr   ÚfieldsÚ_builtÚexcluded_indexesÚexcluded_indexes_idsr   ÚDOCUMENT_FIELDÚdocument_fieldÚ_fieldnamesÚ_facet_fieldnames)r*   r^   r   r   r   r+   ³   s   

zUnifiedIndex.__init__c                 C   s   t  d¡ | jS )Nz`'UnifiedIndex.indexes' was deprecated in Haystack v2.3.0. Please use UnifiedIndex.get_indexes().)ÚwarningsÚwarnr[   r9   r   r   r   Úindexes½   s   ÿzUnifiedIndex.indexesc              	   C   sÄ   g }t ƒ D ]Z}z
t d|j ¡}W n ty    t|dƒr‚ Y qw t |tj¡D ]6\}}t	|ddƒr^t	|dd ƒr^d|j|f }|| j
v sN| j |¡t|ƒkrXt|ƒ| jt|ƒ< q(| |ƒ ¡ q(q|S )Nz%s.search_indexesÚsearch_indexesÚhaystack_use_for_indexingFÚ	get_modelz%s.search_indexes.%s)r
   r	   r   r=   r   r   ÚinspectÚ
getmembersÚisclassr   r^   r_   r.   ÚidrJ   rC   )r*   rf   Úapp_modÚsearch_index_moduleÚ	item_nameÚitemÚ
class_pathr   r   r   Úcollect_indexesÄ   s4   
ÿ
üÿÿ
€ðzUnifiedIndex.collect_indexesc                 C   s$   i | _ tƒ | _d| _i | _i | _d S rZ   )r[   r   r\   r]   rb   rc   r9   r   r   r   Úresetæ   s
   
zUnifiedIndex.resetc                 C   sj   |   ¡  |d u r|  ¡ }|D ]!}| ¡ }|| jv r%td|| j| |f ƒ‚|| j|< |  |¡ qd| _d S )Nz¬Model '%s' has more than one 'SearchIndex`` handling it. Please exclude either '%s' or '%s' using the 'EXCLUDED_INDEXES' setting defined in 'settings.HAYSTACK_CONNECTIONS'.T)rt   rs   ri   r[   r   Úcollect_fieldsr]   )r*   rf   ÚindexÚmodelr   r   r   Úbuildí   s   
ýÿ

zUnifiedIndex.buildc                 C   st  |j  ¡ D ]²\}}|jdu r|j| jkrtd| j|f ƒ‚|| jv r0|j| j| kr0td| ƒ‚|j| j|< t|dƒrK|jrE|| j	|j< n|| j	|j
< |j| j vra|| j |j< t |¡| j |j< q|jr{| j |j }|| j |j< t |¡| j |j< |}|jdu r‡d| j |j _|jdu r“d| j |j _|jdu rŸd| j |j _|jdu r«d| j |j _|jdu r·d| j |j _qd S )NTzrAll 'SearchIndex' classes must use the same '%s' fieldname for the 'document=True' field. Offending index is '%s'.zLAll uses of the '%s' field need to use the same 'index_fieldname' attribute.Ú	facet_for)r\   ÚitemsÚdocumentÚindex_fieldnamera   r   rb   r   ry   rc   Úinstance_nameÚcopyÚis_multivaluedÚindexedÚstoredÚfacetedÚuse_templateÚnull)r*   rv   Ú	fieldnameÚfield_objectÚ	old_fieldr   r   r   ru     sP   
ÿÿ
ÿÿ





€ÂzUnifiedIndex.collect_fieldsc                 C   ó   | j s|  ¡  | jS r$   )r]   rx   r[   r9   r   r   r   Úget_indexesD  ó   zUnifiedIndex.get_indexesc                 C   s   t |  ¡  ¡ ƒS r$   )Úlistr‰   Úkeysr9   r   r   r   Úget_indexed_modelsJ  s   zUnifiedIndex.get_indexed_modelsc                 C   s   | j s|  ¡  | j |¡p|S r$   )r]   rx   rb   r.   )r*   Úfieldr   r   r   Úget_index_fieldnameN  s   z UnifiedIndex.get_index_fieldnamec                 C   s$   |   ¡ }||vrtd| ƒ‚|| S )NzThe model %s is not registered)r‰   r   )r*   Úmodel_klassrf   r   r   r   Ú	get_indexT  s   zUnifiedIndex.get_indexc                 C   sf   | j s|  ¡  | j ¡ D ]$\}}||krqt|dƒr'|jr"|j  S |j  S | j |¡p.|  S |S )Nry   )	r]   rx   r\   rz   r   ry   r}   rc   r.   )r*   rŽ   r…   r†   r   r   r   Úget_facet_fieldname\  s   


z UnifiedIndex.get_facet_fieldnamec                 C   rˆ   r$   )r]   rx   r\   r9   r   r   r   Úall_searchfieldsn  rŠ   zUnifiedIndex.all_searchfieldsr$   )r=   r>   r?   r+   rX   rf   rs   rt   rx   ru   r‰   r�   r�   r‘   r’   r“   r   r   r   r   rY   ±   s    


"
ArY   )r~   rj   r&   rd   Úcollectionsr   Údjango.confr   Údjango.core.exceptionsr   Údjango.utils.module_loadingr   Úhaystackr   Úhaystack.exceptionsr   r   Úhaystack.utilsr	   Úhaystack.utils.app_loadingr
   r   r    r"   r#   r@   rY   r   r   r   r   Ú<module>   s$    +,