U
    ‡WjÙ5  ã                   @   sÆ   d dl Z d dlZd dlZ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 G d	d
„ d
ƒZG dd„ dƒZG dd„ deƒZefdd„Zeƒ ZdS )é    N)Údeepcopy)Úsettings)Úsetting_changed)Úimport_string)ÚDEFAULT_CHANNEL_LAYERé   )ÚChannelFullÚInvalidChannelLayerErrorc                   @   s\   e Zd ZdZdd„ Zdd„ Zedd„ ƒZdd	„ Zd
d„ Z	dd„ Z
dd„ Zdd„ Zdd„ ZdS )ÚChannelLayerManagerzR
    Takes a settings dictionary of backends and initialises them on request.
    c                 C   s   i | _ t | j¡ d S ©N)Úbackendsr   ÚconnectÚ_reset_backends©Úself© r   úZc:\users\psant\downloads\hotstarbackend\school\venv38\Lib\site-packages\channels/layers.pyÚ__init__   s    zChannelLayerManager.__init__c                 K   s   |dkri | _ dS )zX
        Removes cached channel layers when the CHANNEL_LAYERS setting changes.
        ÚCHANNEL_LAYERSN)r   )r   ZsettingÚkwargsr   r   r   r      s    z#ChannelLayerManager._reset_backendsc                 C   s   t tdi ƒS )Nr   )Úgetattrr   r   r   r   r   Úconfigs#   s    zChannelLayerManager.configsc                 C   s   | j |  di ¡}|  ||¡S )z,
        Instantiate channel layer.
        ZCONFIG)r   ÚgetÚ_make_backend©r   ÚnameÚconfigr   r   r   Úmake_backend(   s    z ChannelLayerManager.make_backendc                 C   s@   z| j | d }W n  tk
r2   td| ƒ‚Y nX |  ||¡S )zB
        Instantiate channel layer using its test config.
        ZTEST_CONFIGzNo TEST_CONFIG specified for %s)r   ÚKeyErrorr	   r   r   r   r   r   Úmake_test_backend/   s
    z%ChannelLayerManager.make_test_backendc                 C   sˆ   d| j | krtd| ƒ‚zt| j | d ƒ}W nL tk
rP   td| ƒ‚Y n. tk
r|   td| j | d |f ƒ‚Y nX |f |ŽS )NZROUTINGzBROUTING key found for %s - this is no longer needed in Channels 2.ZBACKENDzNo BACKEND specified for %sz)Cannot import BACKEND %r specified for %s)r   r	   r   r   ÚImportError)r   r   r   Zbackend_classr   r   r   r   9   s"    ÿÿÿÿ
z!ChannelLayerManager._make_backendc                 C   s$   || j kr|  |¡| j |< | j | S r   )r   r   ©r   Úkeyr   r   r   Ú__getitem__M   s    
zChannelLayerManager.__getitem__c                 C   s
   || j kS r   )r   r!   r   r   r   Ú__contains__R   s    z ChannelLayerManager.__contains__c                 C   s   | j  |d¡}|| j |< |S )z»
        Sets an alias to point to a new ChannelLayerWrapper instance, and
        returns the old one that it replaced. Useful for swapping out the
        backend during tests.
        N)r   r   )r   r"   ZlayerÚoldr   r   r   ÚsetU   s    
zChannelLayerManager.setN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   Úpropertyr   r   r   r   r#   r$   r&   r   r   r   r   r
      s   

r
   c                   @   sÊ   e Zd ZdZdZd-dd„Zdd„ Zd	d
„ Zdd„ Ze	 
d¡Ze	 
d¡Zdd e¡ d Zd.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'd(„ Zd0d)d*„Zd+d,„ ZdS )1ÚBaseChannelLayerzf
    Base channel layer class that others can inherit from, with useful
    common functionality.
    éd   é<   Nc                 C   s   || _ || _|pi | _d S r   ©ÚexpiryÚcapacityÚchannel_capacity)r   r0   r1   r2   r   r   r   r   h   s    zBaseChannelLayer.__init__c                 C   sN   g }|  ¡ D ]<\}}t|dƒr.| ||f¡ q| t t |¡¡|f¡ q|S )z 
        Takes an input channel_capacity dict and returns the compiled list
        of regexes that get_capacity will look for as self.channel_capacity
        Úmatch)ÚitemsÚhasattrÚappendÚreÚcompileÚfnmatchÚ	translate)r   r2   ÚresultÚpatternÚvaluer   r   r   Úcompile_capacitiesm   s    
z#BaseChannelLayer.compile_capacitiesc                 C   s(   | j D ]\}}| |¡r|  S q| jS )a  
        Gets the correct capacity for the given channel; either the default,
        or a matching result from channel_capacity. Returns the first matching
        result; if you want to control the order of matches, use an ordered dict
        as input.
        )r2   r3   r1   )r   Úchannelr<   r1   r   r   r   Úget_capacity|   s    

zBaseChannelLayer.get_capacityc                 C   s    t |tƒrt|ƒ| jk rdS dS )NTF)Ú
isinstanceÚstrÚlenÚMAX_NAME_LENGTH©r   r   r   r   r   Úmatch_type_and_lengthˆ   s    z&BaseChannelLayer.match_type_and_lengthz!^[a-zA-Z\d\-_.]+(\![\d\w\-_.]*)?$z^[a-zA-Z\d\-_.]+$z'{} name must be a valid unicode string zwith length < {} zFcontaining only ASCII alphanumerics, hyphens, underscores, or periods.Fc                 C   s\   |   |¡st| j d¡ƒ‚t| j |¡ƒs:t| j d¡ƒ‚d|krX| d¡sX|rXtdƒ‚dS )NZChannelú!z5Specific channel names in receive() must end at the !T)rF   Ú	TypeErrorÚinvalid_name_errorÚformatÚboolÚchannel_name_regexr3   Úendswith)r   r   Úreceiver   r   r   Úrequire_valid_channel_name—   s    
z+BaseChannelLayer.require_valid_channel_namec                 C   s>   |   |¡st| j d¡ƒ‚t| j |¡ƒs:t| j d¡ƒ‚dS )NÚGroupT)rF   rH   rI   rJ   rK   Úgroup_name_regexr3   rE   r   r   r   Úrequire_valid_group_name    s
    
z)BaseChannelLayer.require_valid_group_namec                 C   sB   |rdnd}t |tƒ}|r|s&tdƒ‚|D ]}| j||d� q*dS )NTFznames must be a non-empty list)rN   )rA   ÚlistÚAssertionErrorrO   )r   ÚnamesrN   Z_non_empty_listZ_names_typer?   r   r   r   Úvalid_channel_names§   s    
z$BaseChannelLayer.valid_channel_namesc                 C   s&   d|kr|d|  d¡d … S |S dS )zõ
        Given a channel name, returns the "non-local" part. If the channel name
        is a process-specific channel (contains !) this means the part up to
        and including the !; if it is anything else, this means the full name.
        rG   Nr   )ÚfindrE   r   r   r   Únon_local_name¯   s    zBaseChannelLayer.non_local_namec                 Ã   s   t dƒ‚d S )Nz/send() should be implemented in a channel layer©ÚNotImplementedError)r   r?   Úmessager   r   r   Úsendº   s    zBaseChannelLayer.sendc                 Ã   s   t dƒ‚d S )Nz2receive() should be implemented in a channel layerrY   )r   r?   r   r   r   rN   ½   s    zBaseChannelLayer.receivec                 Ã   s   t dƒ‚d S )Nz6new_channel() should be implemented in a channel layerrY   r   r   r   r   Únew_channelÀ   s    ÿzBaseChannelLayer.new_channelc                 Ã   s   t dƒ‚d S )Nz)flush() not implemented (flush extension)rY   r   r   r   r   ÚflushÅ   s    zBaseChannelLayer.flushc                 Ã   s   t dƒ‚d S )Nz.group_add() not implemented (groups extension)rY   ©r   Úgroupr?   r   r   r   Ú	group_addÈ   s    zBaseChannelLayer.group_addc                 Ã   s   t dƒ‚d S )Nz2group_discard() not implemented (groups extension)rY   r_   r   r   r   Úgroup_discardË   s    zBaseChannelLayer.group_discardc                 Ã   s   t dƒ‚d S )Nz/group_send() not implemented (groups extension)rY   )r   r`   r[   r   r   r   Ú
group_sendÎ   s    zBaseChannelLayer.group_sendc                 C   s   t jdtdd� |  |¡S )zE
        Deprecated: Use require_valid_channel_name instead.
        zIvalid_channel_name is deprecated, use require_valid_channel_name instead.é   ©Ú
stacklevel)ÚwarningsÚwarnÚDeprecationWarningrO   )r   Zchannel_namerN   r   r   r   Úvalid_channel_nameÒ   s    ýz#BaseChannelLayer.valid_channel_namec                 C   s   t jdtdd� |  |¡S )zD
        Deprecated: Use require_valid_group_name instead..
        zEvalid_group_name is deprecated, use require_valid_group_name instead.rd   re   )rg   rh   ri   rR   )r   Z
group_namer   r   r   Úvalid_group_nameÝ   s    ýz!BaseChannelLayer.valid_group_name)r.   r-   N)F)F)F)r'   r(   r)   r*   rD   r   r>   r@   rF   r7   r8   rL   rQ   rJ   rI   rO   rR   rV   rX   r\   rN   r]   r^   ra   rb   rc   rj   rk   r   r   r   r   r,   `   s6   


ÿþÿ
	

r,   c                       s|   e Zd ZdZd‡ fdd„	Zdd	g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‡  ZS )!ÚInMemoryChannelLayerz0
    In-memory channel layer implementation
    r.   é€Q r-   Nc                    s0   t ƒ jf |||dœ|—Ž i | _i | _|| _d S )Nr/   )Úsuperr   ÚchannelsÚgroupsÚgroup_expiry)r   r0   rq   r1   r2   r   ©Ú	__class__r   r   r   î   s    ýüzInMemoryChannelLayer.__init__rp   r^   c                 Ã   sŠ   t |tƒstdƒ‚|  |¡ d|ks(t‚| j |tj|  |¡d�¡}z | 	t
 
¡ | j t|ƒf¡ W n  tjjk
r„   t|ƒ‚Y nX dS )zF
        Send a message onto a (general or specific) channel.
        zmessage is not a dictZ__asgi_channel__©ÚmaxsizeN)rA   ÚdictrT   rO   ro   Ú
setdefaultÚasyncioÚQueuer@   Ú
put_nowaitÚtimer0   r   ÚqueuesÚ	QueueFullr   )r   r?   r[   Úqueuer   r   r   r\     s    
 ÿ zInMemoryChannelLayer.sendc              
   Ã   sb   |   |¡ |  ¡  | j |tj|  |¡d�¡}z| 	¡ I dH \}}W 5 | ¡ r\| j |d¡ X |S )zÊ
        Receive the first message that arrives on the channel.
        If more than one coroutine waits on the same channel, a random one
        of the waiting coroutines will get the result.
        rt   N)
rO   Ú_clean_expiredro   rw   rx   ry   r@   ÚemptyÚpopr   )r   r?   r~   Ú_r[   r   r   r   rN     s    
 ÿzInMemoryChannelLayer.receiveú	specific.c                 Ã   s    d|d  dd„ tdƒD ƒ¡f S )zx
        Returns a new channel name that can be used by something in our
        process as a specific channel.
        z%s.inmemory!%sÚ c                 s   s   | ]}t  tj¡V  qd S r   )ÚrandomÚchoiceÚstringÚascii_letters)Ú.0Úir   r   r   Ú	<genexpr>5  s     z3InMemoryChannelLayer.new_channel.<locals>.<genexpr>é   )ÚjoinÚrange)r   Úprefixr   r   r   r]   .  s    þz InMemoryChannelLayer.new_channelc                 C   s´   t | j ¡ ƒD ]P\}}| ¡ s|jd d t ¡ k r| ¡  |  |¡ | ¡ r| j |d¡ qqt	t ¡ ƒ| j
 }| j ¡ D ]2}t | ¡ ƒD ] \}}|rŒ||k rŒ| |d¡ qŒq|dS )z¢
        Goes through all messages and groups and removes those that are expired.
        Any channel with an expired message is removed from all groups.
        r   N)rS   ro   r4   r€   Ú_queuer{   Ú
get_nowaitÚ_remove_from_groupsr�   Úintrq   rp   Úvalues)r   r?   r~   Útimeoutro   r   Ú	timestampr   r   r   r   :  s    
z#InMemoryChannelLayer._clean_expiredc                 Ã   s   i | _ i | _d S r   )ro   rp   r   r   r   r   r^   V  s    zInMemoryChannelLayer.flushc                 Ã   s   d S r   r   r   r   r   r   ÚcloseZ  s    zInMemoryChannelLayer.closec                 C   s    | j  ¡ D ]}| |d¡ q
dS )zW
        Removes a channel from all groups. Used when a message on it expires.
        N)rp   r”   r�   )r   r?   ro   r   r   r   r’   ^  s    z(InMemoryChannelLayer._remove_from_groupsc                 Ã   s8   |   |¡ |  |¡ | j |i ¡ t ¡ | j| |< dS )z3
        Adds the channel name to a group.
        N)rR   rO   rp   rw   r{   r_   r   r   r   ra   g  s    

zInMemoryChannelLayer.group_addc                 Ã   sH   |   |¡ |  |¡ | j |d ¡}|rD| |d ¡ |sD| j |d ¡ d S r   )rO   rR   rp   r   r�   )r   r`   r?   Zgroup_channelsr   r   r   rb   r  s    

z"InMemoryChannelLayer.group_discardc              	   Ã   s–   t |tƒstdƒ‚|  |¡ |  ¡  g }|| jkr^| j|  ¡ D ]}| t 	|  
||¡¡¡ q@t |¡D ](}z|I d H  W qh tk
rŽ   Y qhX qhd S )NzMessage is not a dict)rA   rv   rT   rR   r   rp   Úkeysr6   rx   Úcreate_taskr\   Úas_completedr   )r   r`   r[   Úopsr?   Zsend_resultr   r   r   rc     s    

zInMemoryChannelLayer.group_send)r.   rm   r-   N)rƒ   )r'   r(   r)   r*   r   Ú
extensionsr\   rN   r]   r   r^   r—   r’   ra   rb   rc   Ú__classcell__r   r   rr   r   rl   é   s"       û
	rl   c                 C   s&   z
t |  W S  tk
r    Y dS X dS )zL
    Returns a channel layer by alias, or None if it is not configured.
    N)Úchannel_layersr   )Úaliasr   r   r   Úget_channel_layer’  s    
r    )rx   r9   r…   r7   r‡   r{   rg   Úcopyr   Zdjango.confr   Zdjango.core.signalsr   Zdjango.utils.module_loadingr   ro   r   Ú
exceptionsr   r	   r
   r,   rl   r    rž   r   r   r   r   Ú<module>   s&   M 
 *