U
    9ˆj  ã                   @   s~   d dl 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lmZ d	d
„ ZG dd„ dƒZG dd„ deƒZdS )é    N)Úasync_to_syncé   )ÚDEFAULT_CHANNEL_LAYER)Úaclose_old_connectionsÚdatabase_sync_to_async)ÚStopConsumer)Úget_channel_layer)Úawait_many_dispatchc                 C   s6   d| krt dƒ‚| d  dd¡}| d¡r2t dƒ‚|S )zl
    Looks at a message, checks it has a sensible type, and returns the
    handler name for that type.
    Útypez(Incoming message has no 'type' attributeÚ.Ú_z.Malformed type in message (leading underscore))Ú
ValueErrorÚreplaceÚ
startswith)ÚmessageZhandler_name© r   ú5/tmp/pip-unpacked-wheel-o8d015gg/channels/consumer.pyÚget_handler_name   s    
r   c                   @   s<   e Zd ZdZdZeZdd„ Zdd„ Zdd„ Z	e
d	d
„ ƒZdS )ÚAsyncConsumerz­
    Base consumer class. Implements the ASGI application spec, and adds on
    channel layer management and routing of events to named methods based
    on their type.
    Fc                 Ã   s°   || _ t| jƒ| _| jdk	rB| j ¡ I dH | _t | jj| j¡| _	| j
rTt|ƒ| _n|| _z<| jdk	r€t|| j	g| jƒI dH  nt|g| jƒI dH  W n tk
rª   Y nX dS )úU
        Dispatches incoming messages to type-based handlers asynchronously.
        N)Úscoper   Úchannel_layer_aliasZchannel_layerZnew_channelZchannel_nameÚ	functoolsÚpartialÚreceiveZchannel_receiveÚ_syncr   Ú	base_sendr	   Údispatchr   )Úselfr   r   Úsendr   r   r   Ú__call__%   s(    
 ÿ
 ÿzAsyncConsumer.__call__c                 Ã   sD   t | t|ƒdƒ}|r0tƒ I dH  ||ƒI dH  ntd|d  ƒ‚dS )z6
        Works out what to do with a message.
        NúNo handler for message type %sr
   )Úgetattrr   r   r   ©r   r   Úhandlerr   r   r   r   C   s
    zAsyncConsumer.dispatchc                 Ã   s   |   |¡I dH  dS ©zB
        Overrideable/callable-by-subclasses send method.
        N©r   ©r   r   r   r   r   r   N   s    zAsyncConsumer.sendc                    s.   ‡ ‡fdd„}ˆ |_ ˆ|_tj|ˆ dd� |S )zÝ
        Return an ASGI v3 single callable that instantiates a consumer instance
        per scope. Similar in purpose to Django's as_view().

        initkwargs will be used to instantiate the consumer instance.
        c                 “   s   ˆ f ˆŽ}|| ||ƒI d H S )Nr   )r   r   r   Zconsumer©ÚclsÚ
initkwargsr   r   Úapp]   s    
z"AsyncConsumer.as_asgi.<locals>.appr   )Úupdated)Zconsumer_classZconsumer_initkwargsr   Úupdate_wrapper)r)   r*   r+   r   r(   r   Úas_asgiT   s
    	zAsyncConsumer.as_asgiN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r    r   r   Úclassmethodr.   r   r   r   r   r      s   r   c                   @   s(   e Zd ZdZdZedd„ ƒZdd„ ZdS )ÚSyncConsumeraÄ  
    Synchronous version of the consumer, which is what we write most of the
    generic consumers against (for now). Calls handlers in a threadpool and
    uses CallBouncer to get the send method out to the main event loop.

    It would have been possible to have "mixed" consumers and auto-detect
    if a handler was awaitable or not, but that would have made the API
    for user-called methods very confusing as there'd be two types of each.
    Tc                 C   s2   t | t|ƒdƒ}|r||ƒ ntd|d  ƒ‚dS )r   Nr!   r
   )r"   r   r   r#   r   r   r   r   v   s    
zSyncConsumer.dispatchc                 C   s   |   |¡ dS r%   r&   r'   r   r   r   r   ‚   s    zSyncConsumer.sendN)r/   r0   r1   r2   r   r   r   r   r   r   r   r   r4   i   s
   

r4   )r   Zasgiref.syncr   Ú r   Údbr   r   Ú
exceptionsr   Zlayersr   Úutilsr	   r   r   r4   r   r   r   r   Ú<module>   s   N