
    _f.                         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
          Z G d d          Z G d de          ZefdZ e            ZdS )    N)deepcopy)settings)setting_changed)import_string)DEFAULT_CHANNEL_LAYER   )ChannelFullInvalidChannelLayerErrorc                   X    e Zd ZdZd Zd Zed             Zd Zd Z	d Z
d Zd	 Zd
 ZdS )ChannelLayerManagerzR
    Takes a settings dictionary of backends and initialises them on request.
    c                 F    i | _         t          j        | j                   d S N)backendsr   connect_reset_backendsselfs    A/var/www/html/env/lib/python3.11/site-packages/channels/layers.py__init__zChannelLayerManager.__init__   s#     455555    c                 $    |dk    r	i | _         dS dS )zX
        Removes cached channel layers when the CHANNEL_LAYERS setting changes.
        CHANNEL_LAYERSN)r   )r   settingkwargss      r   r   z#ChannelLayerManager._reset_backends   s#     &&&DMMM '&r   c                 .    t          t          di           S )Nr   )getattrr   r   s    r   configszChannelLayerManager.configs"   s     x!12666r   c                 p    | j         |                             di           }|                     ||          S )z,
        Instantiate channel layer.
        CONFIG)r   get_make_backendr   nameconfigs      r   make_backendz ChannelLayerManager.make_backend'   s6     d#''"55!!$///r   c                     	 | j         |         d         }n # t          $ r t          d|z            w xY w|                     ||          S )zB
        Instantiate channel layer using its test config.
        TEST_CONFIGzNo TEST_CONFIG specified for %s)r   KeyErrorr
   r!   r"   s      r   make_test_backendz%ChannelLayerManager.make_test_backend.   sd    	U\$'6FF 	U 	U 	U*+Lt+STTT	U!!$///s    3c                 6   d| j         |         v rt          d|z            	 t          | j         |         d                   }nO# t          $ r t          d|z            t          $ r' t          d| j         |         d         d|          w xY 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 z specified for  )r   r
   r   r(   ImportError)r   r#   r$   backend_classs       r   r!   z!ChannelLayerManager._make_backend8   s    T****T  
	)$,t*<Y*GHHMM 	Q 	Q 	Q*+H4+OPPP 	 	 	**<%i000$$8  	 }&&v&&&s    A ABc                 h    || j         vr|                     |          | j         |<   | j         |         S r   )r   r%   r   keys     r   __getitem__zChannelLayerManager.__getitem__L   s6    dm##!%!2!23!7!7DM#}S!!r   c                     || j         v S r   )r   r1   s     r   __contains__z ChannelLayerManager.__contains__Q   s    dl""r   c                 P    | 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   r2   layerolds       r   setzChannelLayerManager.setT   s,     mT**"c
r   N)__name__
__module____qualname____doc__r   r   propertyr   r%   r)   r!   r3   r5   r9   r-   r   r   r   r      s         6 6 6   7 7 X70 0 00 0 0' ' '(" " "
# # #    r   r   c                       e Zd ZdZdZddZd Zd Zd Z e	j
        d	          Z e	j
        d
          Zdd                    e          z   dz   dz   ZddZd ZddZd ZdS )BaseChannelLayerzf
    Base channel layer class that others can inherit from, with useful
    common functionality.
    d   <   Nc                 4    || _         || _        |pi | _        d S r   expirycapacitychannel_capacity)r   rE   rF   rG   s       r   r   zBaseChannelLayer.__init__g   s#      0 6Br   c                    g }|                                 D ]h\  }}t          |d          r|                    ||f           -|                    t          j        t          j        |                    |f           i|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   rG   resultpatternvalues        r   compile_capacitiesz#BaseChannelLayer.compile_capacitiesl   s    
 .4466 	O 	ONGU w(( Ow.////rz'*;G*D*DEEuMNNNNr   c                 \    | j         D ]\  }}|                    |          r|c S | 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.
        )rG   rI   rF   )r   channelrR   rF   s       r   get_capacityzBaseChannelLayer.get_capacity{   sE     "&!6 	  	 GX}}W%%   }r   c                 d    t          |t                    rt          |          | j        k     rdS dS )NTF)
isinstancestrlenMAX_NAME_LENGTHr   r#   s     r   match_type_and_lengthz&BaseChannelLayer.match_type_and_length   s1    dC   	c$ii$2F&F&F4ur   z!^[a-zA-Z\d\-_.]+(\![\d\w\-_.]*)?$z^[a-zA-Z\d\-_.]+$z'{} name must be a valid unicode string zwith length < {} zGcontaining only ASCII alphanumerics, hyphens, underscores, or periods, znot {}Fc                 "   |                      |          rSt          | j                            |                    r,d|v r&|                    d          s|rt          d          dS t          | j                            d|                    )N!z5Specific channel names in receive() must end at the !TChannel)r^   boolchannel_name_regexrI   endswith	TypeErrorinvalid_name_errorformat)r   r#   receives      r   valid_channel_namez#BaseChannelLayer.valid_channel_name   s    %%d++ 	D+11$7788 $;;t}}S'9'9;g;#O   t/66y$GGHHHr   c                     |                      |          r)t          | j                            |                    rdS t	          | j                            d|                    )NTGroup)r^   rb   group_name_regexrI   re   rf   rg   r]   s     r   valid_group_namez!BaseChannelLayer.valid_group_name   s_    %%d++ 	D)//5566 t/66wEEFFFr   c                      |rdnd}t          |t                    }|r|s
J d            t           fd|D                       sJ dS )NTFznames must be a non-empty listc              3   F   K   | ]}                     |           V  dS ))rh   N)ri   ).0rV   rh   r   s     r   	<genexpr>z7BaseChannelLayer.valid_channel_names.<locals>.<genexpr>   sG       
 
BID##GW#==
 
 
 
 
 
r   )rY   listall)r   namesrh   _non_empty_list_names_types   ` `  r   valid_channel_namesz$BaseChannelLayer.valid_channel_names   s    "'2$$U --P;PP0PPP. 
 
 
 
 
MR
 
 
 
 
 	
 	
 
 tr   c                 N    d|v r |d|                     d          dz            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.
        r`   Nr   )findr]   s     r   non_local_namezBaseChannelLayer.non_local_name   s2     $;;,$))C..1,,--Kr   )rB   rA   N)F)r:   r;   r<   r=   r\   r   rT   rW   r^   rM   rN   rc   rl   rg   rf   ri   rm   rw   rz   r-   r   r   r@   r@   _   s        
 O7 7 7 7
  
 
 
   $$HII!rz"6771

$
$_
5
5	6
S	T 	 	I 	I 	I 	IG G G   	 	 	 	 	r   r@   c                   r     e Zd ZdZ	 	 	 	 d fd	ZddgZd	 Zd
 ZddZd Z	d Z
d Zd Zd Zd Zd Z xZS )InMemoryChannelLayerz0
    In-memory channel layer implementation
    rB   Q rA   Nc                 l     t                      j        d|||d| i | _        i | _        || _        d S )NrD   r-   )superr   channelsgroupsgroup_expiry)r   rE   r   rF   rG   r   	__class__s         r   r   zInMemoryChannelLayer.__init__   s[     	 	
-	
 	
 		
 	
 	
 (r   r   flushc                   K   t          |t                    s
J d            |                     |          s
J d            d|vsJ | j                            |t          j                              }|                                | j        k    rt          |          |
                    t          j                    | j        z   t          |          f           d{V  dS )zF
        Send a message onto a (general or specific) channel.
        zmessage is not a dictChannel name not valid__asgi_channel__N)rY   dictri   r   
setdefaultasyncioQueueqsizerF   r	   puttimerE   r   )r   rV   messagequeues       r   sendzInMemoryChannelLayer.send   s      
 '4((AA*AAA(&&w//II1III/ "0000(('-//BB;;==DM))g&&& iit{2HW4E4EFGGGGGGGGGGGr   c                 p  K   |                      |          sJ |                                  | j                            |t	          j                              }	 |                                 d{V \  }}|                                r| j        |= n!# |                                r| j        |= w xY w|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.
        N)ri   _clean_expiredr   r   r   r   r    empty)r   rV   r   _r   s        r   rh   zInMemoryChannelLayer.receive   s       &&w/////(('-//BB	+$yy{{******JAw{{}} +M'* {{}} +M'*****s   B B3	specific.c                 h   K   |dd                     d t          d          D                       S )zx
        Returns a new channel name that can be used by something in our
        process as a specific channel.
        z
.inmemory! c              3   R   K   | ]"}t          j        t          j                  V  #d S r   )randomchoicestringascii_letters)rp   is     r   rq   z3InMemoryChannelLayer.new_channel.<locals>.<genexpr>  s/      KKAFM&"677KKKKKKr      )joinrange)r   prefixs     r   new_channelz InMemoryChannelLayer.new_channel   s@       FFGGKKrKKKKKK
 	
r   c                 4   t          | j                                                  D ]\  }}|                                s|j        d         d         t          j                    k     r|                                 |                     |           |                                r| j        |= |                                s(|j        d         d         t          j                    k     t          t          j                              | j	        z
  }| j
        D ]~}t          | j
                            |t                                          D ]G}| j
        |         |         r2t          | j
        |         |                   |k     r| j
        |         |= H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)rr   r   rJ   r   _queuer   
get_nowait_remove_from_groupsintr   r   r    r9   )r   rV   r   timeoutgroups        r   r   z#InMemoryChannelLayer._clean_expired  su    #4=#6#6#8#899 	/ 	/NGUkkmm /Q(:TY[[(H(H  """((111;;== /g. kkmm /Q(:TY[[(H(H dikk""T%66[ 	4 	4Esuu = =>> 4 4 K&w/4DK.w7887BB E*734	4 	4r   c                 &   K   i | _         i | _        d S r   )r   r   r   s    r   r   zInMemoryChannelLayer.flush*  s      r   c                 
   K   d S r   r-   r   s    r   closezInMemoryChannelLayer.close.  s      r   c                 L    | j                                         D ]	}||v r||= 
dS )zW
        Removes a channel from all groups. Used when a message on it expires.
        N)r   values)r   rV   r   s      r   r   z(InMemoryChannelLayer._remove_from_groups2  s?     **,, 	& 	&H(""W%	& 	&r   c                    K   |                      |          s
J d            |                     |          s
J d            | j                            |i            t	          j                    | j        |         |<   dS )z3
        Adds the channel name to a group.
        zGroup name not validr   N)rm   ri   r   r   r   r   r   rV   s      r   	group_addzInMemoryChannelLayer.group_add<  s      
 $$U++CC-CCC+&&w//II1III/ub)))&*ikkE7###r   c                   K   |                      |          s
J d            |                     |          s
J d            || j        v r4|| j        |         v r| j        |         |= | j        |         s| j        |= d S d S d S )NzInvalid channel nameInvalid group name)ri   rm   r   r   s      r   group_discardz"InMemoryChannelLayer.group_discardG  s      &&w//GG1GGG/$$U++AA-AAA+DK$+e,,,K&w/;u% 'K&&&	  ' 'r   c                 \  K   t          |t                    s
J d            |                     |          s
J d            |                                  | j                            |t                                D ]/}	 |                     ||           d {V   # t          $ r Y ,w xY wd S )NzMessage is not a dictr   )	rY   r   rm   r   r   r    r9   r   r	   )r   r   r   rV   s       r   
group_sendzInMemoryChannelLayer.group_sendR  s      '4((AA*AAA($$U++AA-AAA+{ucee44 	 	Gii1111111111   	 	s   ?B
B)(B))rB   r}   rA   N)r   )r:   r;   r<   r=   r   
extensionsr   rh   r   r   r   r   r   r   r   r   __classcell__)r   s   @r   r|   r|      s          ) ) ) ) ) )( G$JH H H&  (
 
 
 
4 4 4<    & & &	2 	2 	2	' 	' 	'      r   r|   c                 @    	 t           |          S # t          $ r Y dS w xY w)zL
    Returns a channel layer by alias, or None if it is not configured.
    N)channel_layersr(   )aliass    r   get_channel_layerr   `  s4    e$$   tts    
)r   rO   r   rM   r   r   copyr   django.confr   django.core.signalsr   django.utils.module_loadingr   r   r   
exceptionsr	   r
   r   r@   r|   r   r   r-   r   r   <module>r      sp      				                     / / / / / / 5 5 5 5 5 5 * * * * * * = = = = = = = =J J J J J J J JZ\ \ \ \ \ \ \ \~_ _ _ _ _+ _ _ _D 2     %$&&r   