o
    >h5                     @   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   o/var/www/vedio/testing/chatpythonscript.ninositsolution.com/env/lib/python3.10/site-packages/channels/layers.py__init__   s   zChannelLayerManager.__init__c                 K   s   |dkr	i | _ dS dS )zX
        Removes cached channel layers when the CHANNEL_LAYERS setting changes.
        CHANNEL_LAYERSN)r   )r   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.
        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y   td| w | ||S )zB
        Instantiate channel layer using its test config.
        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 | v rtd| zt| j | d }W n  ty%   td|  ty8   td| j | d |f w |di |S )NROUTINGzBROUTING key found for %s - this is no longer needed in Channels 2.BACKENDzNo BACKEND specified for %sz)Cannot import BACKEND %r specified for %sr   )r   r	   r   r!   ImportError)r   r   r   backend_classr   r   r   r   9   s$   z!ChannelLayerManager._make_backendc                 C   s$   || j vr| || j |< | j | S r   )r   r   r   keyr   r   r   __getitem__M   s   

zChannelLayerManager.__getitem__c                 C   s
   || j v 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(   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d.d)d*Zd+d, ZdS )/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   r7   r8   r9   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   r9   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.
        )r9   r:   r8   )r   channelrC   r8   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|v r,|ds,|r,tddS )NChannel!z5Specific channel names in receive() must end at the !T)rM   	TypeErrorinvalid_name_errorformatboolchannel_name_regexr:   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)rM   rP   rQ   rR   rS   group_name_regexr:   rL   r   r   r   require_valid_group_name   s
   
z)BaseChannelLayer.require_valid_group_namec                 C   sB   |rdnd}t |t}|r|sJ d|D ]	}| j||d qdS )NTFznames must be a non-empty list)rV   )rH   listrW   )r   namesrV   _non_empty_list_names_typerF   r   r   r   valid_channel_names   s   
z$BaseChannelLayer.valid_channel_namesc                 C   s"   d|v r|d| dd  S |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.
        rO   Nr   )findrL   r   r   r   non_local_name   s   zBaseChannelLayer.non_local_namec                    
   t d)Nz/send() should be implemented in a channel layerNotImplementedError)r   rF   messager   r   r   send      zBaseChannelLayer.sendc                    rb   )Nz2receive() should be implemented in a channel layerrc   )r   rF   r   r   r   rV      rg   zBaseChannelLayer.receivec                    rb   )Nz6new_channel() should be implemented in a channel layerrc   r   r   r   r   new_channel   s   zBaseChannelLayer.new_channelc                    rb   )Nz)flush() not implemented (flush extension)rc   r   r   r   r   flush   rg   zBaseChannelLayer.flushc                    rb   )Nz.group_add() not implemented (groups extension)rc   r   grouprF   r   r   r   	group_add   rg   zBaseChannelLayer.group_addc                    rb   )Nz2group_discard() not implemented (groups extension)rc   rj   r   r   r   group_discard   rg   zBaseChannelLayer.group_discardc                    rb   )Nz/group_send() not implemented (groups extension)rc   )r   rk   re   r   r   r   
group_send   rg   zBaseChannelLayer.group_sendc                 C      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DeprecationWarningrW   )r   channel_namerV   r   r   r   valid_channel_name      
z#BaseChannelLayer.valid_channel_namec                 C   ro   )zD
        Deprecated: Use require_valid_group_name instead..
        zEvalid_group_name is deprecated, use require_valid_group_name instead.rp   rq   )rs   rt   ru   rZ   )r   
group_namer   r   r   valid_group_name   rx   z!BaseChannelLayer.valid_group_name)r5   r4   N)F)r.   r/   r0   r1   rK   r   rE   rG   rM   r>   r?   rT   rY   rR   rQ   rW   rZ   r_   ra   rf   rV   rh   ri   rl   rm   rn   rw   rz   r   r   r   r   r3   `   s8    



	

r3   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
    r5   Q r4   Nc                    s0   t  jd|||d| i | _i | _|| _d S )Nr6   r   )superr   channelsgroupsgroup_expiry)r   r7   r   r8   r9   r   	__class__r   r   r      s   
zInMemoryChannelLayer.__init__r   ri   c                    s   t |ts
J d| | d|vsJ | j|tj| |d}z|t		 | j
 t|f W dS  tjjyA   t|w )zF
        Send a message onto a (general or specific) channel.
        zmessage is not a dict__asgi_channel__maxsizeN)rH   dictrW   r~   
setdefaultasyncioQueuerG   
put_nowaittimer7   r   queues	QueueFullr   )r   rF   re   queuer   r   r   rf     s   
"zInMemoryChannelLayer.sendc              
      sz   |  | |   | j|tj| |d}z| I dH \}}W | r.| j	|d |S | r<| j	|d w w )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.
        r   N)
rW   _clean_expiredr~   r   r   r   rG   r   emptypop)r   rF   r   _re   r   r   r   rV     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   rh   .  s
   z InMemoryChannelLayer.new_channelc                 C   s   t | j D ]6\}}| s=|jd d t k r=|  | | | r.| j|d | s=|jd d t k sqt	t | j
 }| j D ]}t | D ]\}}|rd||k rd||d qTqLd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)r[   r~   r;   r   _queuer   
get_nowait_remove_from_groupsr   intr   r   values)r   rF   r   timeoutr~   r   	timestampr   r   r   r   :  s    
	z#InMemoryChannelLayer._clean_expiredc                    s   i | _ i | _d S r   )r~   r   r   r   r   r   ri   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)r   r   r   )r   rF   r~   r   r   r   r   ^  s   z(InMemoryChannelLayer._remove_from_groupsc                    s:   |  | | | | j|i  t | j| |< dS )z3
        Adds the channel name to a group.
        N)rZ   rW   r   r   r   rj   r   r   r   rl   g  s
   

zInMemoryChannelLayer.group_addc                    sR   |  | | | | j|d }|r%||d  |s'| j|d  d S d S d S r   )rW   rZ   r   r   r   )r   rk   rF   group_channelsr   r   r   rm   r  s   

z"InMemoryChannelLayer.group_discardc              	      s   t |ts
J d| | |   g }|| jv r0| j|  D ]}|t| 	|| q!t
|D ]}z|I d H  W q5 tyG   Y q5w d S )NzMessage is not a dict)rH   r   rZ   r   r   keysr=   r   create_taskrf   as_completedr   )r   rk   re   opsrF   send_resultr   r   r   rn     s   

zInMemoryChannelLayer.group_send)r5   r|   r4   N)r   )r.   r/   r0   r1   r   
extensionsrf   rV   rh   r   ri   r   r   rl   rm   rn   __classcell__r   r   r   r   r{      s$    
	r{   c                 C   s    zt |  W S  ty   Y dS w )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   )r   r@   r   r>   r   r   rs   copyr   django.confr   django.core.signalsr   django.utils.module_loadingr   r~   r   
exceptionsr   r	   r
   r3   r{   r   r   r   r   r   r   <module>   s(    M 
 *
