
    h=6                         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
      Z G d d      Z G d de      ZefdZ e       Zy)    N)deepcopy)settings)setting_changed)import_string)DEFAULT_CHANNEL_LAYER   )ChannelFullInvalidChannelLayerErrorc                   P    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y)ChannelLayerManagerzR
    Takes a settings dictionary of backends and initialises them on request.
    c                 P    i | _         t        j                  | j                         y N)backendsr   connect_reset_backendsselfs    K/var/www/Befach/backend/env/lib/python3.12/site-packages/channels/layers.py__init__zChannelLayerManager.__init__   s     4 45    c                     |dk(  ri | _         yy)zX
        Removes cached channel layers when the CHANNEL_LAYERS setting changes.
        CHANNEL_LAYERSN)r   )r   settingkwargss      r   r   z#ChannelLayerManager._reset_backends   s     &&DM 'r   c                 $    t        t        di       S )Nr   )getattrr   r   s    r   configszChannelLayerManager.configs#   s     x!1266r   c                 d    | j                   |   j                  di       }| j                  ||      S )z,
        Instantiate channel layer.
        CONFIG)r   get_make_backendr   nameconfigs      r   make_backendz ChannelLayerManager.make_backend(   s2     d#''"5!!$//r   c                     	 | j                   |   d   }| j                  ||      S # t        $ r t        d|z        w xY w)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/   sT    	U\\$'6F !!$//  	U*+Lt+STT	Us   & >c                     d| j                   |   v rt        d|z        	 | j                   |   d   }	 t        |      } |di |S # t        $ r" t        d| j                   |   d   d|      w xY w# t        $ r t        d|z        w xY w)NROUTINGzBROUTING key found for %s - this is no longer needed in Channels 2.BACKENDzCannot import BACKEND z specified for zNo BACKEND specified for %s )r   r
   r   ImportErrorr(   )r   r#   r$   backend_modulebackend_classs        r   r!   z!ChannelLayerManager._make_backend9   s    T***T 
	!\\$/	:N -n = &v&&  .||D))4d<   	Q*+H4+OPP	Qs   A5 A +A25Bc                 x    || j                   vr| j                  |      | j                   |<   | j                   |   S r   )r   r%   r   keys     r   __getitem__zChannelLayerManager.__getitem__Q   s6    dmm#!%!2!23!7DMM#}}S!!r   c                     || j                   v S r   )r   r2   s     r   __contains__z ChannelLayerManager.__contains__V   s    dll""r   c                 \    | j                   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   r3   layerolds       r   setzChannelLayerManager.setY   s-     mmT*"c
r   N)__name__
__module____qualname____doc__r   r   propertyr   r%   r)   r!   r4   r6   r:   r-   r   r   r   r      sC    6 7 7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j                  e      z   dz   ZddZd ZddZd Zd Zd Zd Zd Zd Zd Zd ZddZd Zy)BaseChannelLayerzf
    Base channel layer class that others can inherit from, with useful
    common functionality.
    d   Nc                 6    || _         || _        |xs i | _        y r   expirycapacitychannel_capacity)r   rE   rF   rG   s       r   r   zBaseChannelLayer.__init__l   s      0 6Br   c                     g }|j                         D ]^  \  }}t        |d      r|j                  ||f       &|j                  t        j                  t        j                  |            |f       ` |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_capacitiesq   si    
 .446NGU w(w./rzz'*;*;G*DEuMN 7 r   c                 l    | j                   D ]  \  }}|j                  |      s|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   s6     "&!6!6GX}}W% "7 }}r   c                 V    t        |t              rt        |      | j                  k  ryy)NTF)
isinstancestrlenMAX_NAME_LENGTHr   r#   s     r   match_type_and_lengthz&BaseChannelLayer.match_type_and_length   s#    dC c$i$2F2F&Fr   z!^[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.c                 B   | j                  |      s$t        | j                  j                  d            t	        | j
                  j                  |            s$t        | j                  j                  d            d|v r|j                  d      s|rt        d      y)NChannel!z5Specific channel names in receive() must end at the !T)r^   	TypeErrorinvalid_name_errorformatboolchannel_name_regexrI   endswith)r   r#   receives      r   require_valid_channel_namez+BaseChannelLayer.require_valid_channel_name   s    ))$/D33::9EFFD++11$78D33::9EFF$;t}}S1gSTTr   c                     | j                  |      s$t        | j                  j                  d            t	        | j
                  j                  |            s$t        | j                  j                  d            y)NGroupT)r^   rb   rc   rd   re   group_name_regexrI   r]   s     r   require_valid_group_namez)BaseChannelLayer.require_valid_group_name   sd    ))$/D33::7CDDD))//56D33::7CDDr   c                 z    |rdnd}t        |t              }|r|sJ d       |D ]  }| j                  ||        y)NTFznames must be a non-empty list)rh   )rY   listri   )r   namesrh   _non_empty_list_names_typerV   s         r   valid_channel_namesz$BaseChannelLayer.valid_channel_names   sH    "'$U -;P0PP.G++GW+E r   c                 <    d|v r|d|j                  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.
        ra   Nr   )findr]   s     r   non_local_namezBaseChannelLayer.non_local_name   s+     $;,$))C.1,--Kr   c                     K   t        d      w)Nz/send() should be implemented in a channel layerNotImplementedError)r   rV   messages      r   sendzBaseChannelLayer.send        !"STT   c                     K   t        d      w)Nz2receive() should be implemented in a channel layerrx   )r   rV   s     r   rh   zBaseChannelLayer.receive        !"VWWr}   c                     K   t        d      w)Nz6new_channel() should be implemented in a channel layerrx   r   s    r   new_channelzBaseChannelLayer.new_channel   s     !D
 	
r}   c                     K   t        d      w)Nz)flush() not implemented (flush extension)rx   r   s    r   flushzBaseChannelLayer.flush   s     !"MNNr}   c                     K   t        d      w)Nz.group_add() not implemented (groups extension)rx   r   grouprV   s      r   	group_addzBaseChannelLayer.group_add   s     !"RSSr}   c                     K   t        d      w)Nz2group_discard() not implemented (groups extension)rx   r   s      r   group_discardzBaseChannelLayer.group_discard   r   r}   c                     K   t        d      w)Nz/group_send() not implemented (groups extension)rx   )r   r   rz   s      r   
group_sendzBaseChannelLayer.group_send   r|   r}   c                 \    t        j                  dt        d       | j                  |      S )zE
        Deprecated: Use require_valid_channel_name instead.
        zIvalid_channel_name is deprecated, use require_valid_channel_name instead.   
stacklevel)warningswarnDeprecationWarningri   )r   channel_namerh   s      r   valid_channel_namez#BaseChannelLayer.valid_channel_name   s,     	W	

 ..|<<r   c                 \    t        j                  dt        d       | j                  |      S )zD
        Deprecated: Use require_valid_group_name instead..
        zEvalid_group_name is deprecated, use require_valid_group_name instead.r   r   )r   r   r   rm   )r   
group_names     r   valid_group_namez!BaseChannelLayer.valid_group_name   s,     	S	

 ,,Z88r   )<   rB   N)F)r;   r<   r=   r>   r\   r   rT   rW   r^   rM   rN   rf   rl   rd   rc   ri   rm   rs   rv   r{   rh   r   r   r   r   r   r   r   r-   r   r   rA   rA   d   s    
 O7

 $$HI!rzz"671

$
$_
5	6
R	S 	UX

OTXU	=	9r   rA   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
    c                 V    t        |   d|||d| i | _        i | _        || _        y )NrD   r-   )superr   channelsgroupsgroup_expiry)r   rE   r   rF   rG   r   	__class__s         r   r   zInMemoryChannelLayer.__init__   sB     	 	
-	
 		
 (r   r   r   c                   K   t        |t              sJ d       | j                  |       d|vsJ | j                  j	                  |t        j                  | j                  |                  }	 |j                  t        j                         | j                  z   t        |      f       y# t
        j                  j                  $ r t        |      w xY ww)zF
        Send a message onto a (general or specific) channel.
        zmessage is not a dict__asgi_channel__maxsizeN)rY   dictri   r   
setdefaultasyncioQueuerW   
put_nowaittimerE   r   queues	QueueFullr	   )r   rV   rz   queues       r   r{   zInMemoryChannelLayer.send  s     
 '4(A*AA(''0 "000((W]]4+<+<W+EF
	'diikDKK7'9JKL~~'' 	'g&&	's   A.C1;B- ,C-)CCc                   K   | j                  |       | j                          | j                  j                  |t	        j
                  | j                  |                  }	 |j                          d{   \  }}|j                         r| j                  j                  |d       |S 7 5# |j                         r| j                  j                  |d       w w xY 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)
ri   _clean_expiredr   r   r   r   rW   r    emptypop)r   rV   r   _rz   s        r   rh   zInMemoryChannelLayer.receive  s      	''0((W]]4+<+<W+EF

	1$yy{*JAw{{}!!'40 +{{}!!'40 s0   A!C!$B/ 7B-8B/ ?.C!-B/ //CC!c                 V   K   |ddj                  d t        d      D              S w)zx
        Returns a new channel name that can be used by something in our
        process as a specific channel.
        z
.inmemory! c              3   b   K   | ]'  }t        j                  t        j                         ) y wr   )randomchoicestringascii_letters).0is     r   	<genexpr>z3InMemoryChannelLayer.new_channel.<locals>.<genexpr>9  s     KAFMM&"6"67Ks   -/   )joinrange)r   prefixs     r   r   z InMemoryChannelLayer.new_channel2  s+      GGKrKK
 	
s   ')c                    t        | j                  j                               D ]  \  }}|j                         r|j                  d   d   t        j
                         k  s?|j                          | j                  |       |j                         r| j                  j                  |d       |j                         r|j                  d   d   t        j
                         k  r t        t        j
                               | j                  z
  }| j                  j                         D ]>  }t        |j                               D ]   \  }}|s	||k  s|j                  |d       " @ y)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)ro   r   rJ   r   _queuer   
get_nowait_remove_from_groupsr   intr   r   values)r   rV   r   timeoutr   r#   	timestamps          r   r   z#InMemoryChannelLayer._clean_expired>  s    #4==#6#6#89NGUkkmQ(:TYY[(H  "((1;;=MM%%gt4 kkmQ(:TYY[(H : diik"T%6%66**,H#'(8#9i W!4LLt, $: -r   c                 (   K   i | _         i | _        y wr   )r   r   r   s    r   r   zInMemoryChannelLayer.flushZ  s     s   c                    K   y wr   r-   r   s    r   closezInMemoryChannelLayer.close^  s	     s   c                 f    | j                   j                         D ]  }|j                  |d        y)zW
        Removes a channel from all groups. Used when a message on it expires.
        N)r   r   r   )r   rV   r   s      r   r   z(InMemoryChannelLayer._remove_from_groupsb  s)     **,HLL$' -r   c                    K   | j                  |       | j                  |       | j                  j                  |i        t	        j                         | j                  |   |<   yw)z3
        Adds the channel name to a group.
        N)rm   ri   r   r   r   r   s      r   r   zInMemoryChannelLayer.group_addk  sQ     
 	%%e,''0ub)&*iikE7#s   A$A&c                    K   | j                  |       | j                  |       | j                  j                  |d       }|r2|j	                  |d        |s| j                  j	                  |d        y y y wr   )ri   rm   r   r    r   )r   r   rV   group_channelss       r   r   z"InMemoryChannelLayer.group_discardv  sh     ''0%%e,5w-!t, "	 s   A4A6c           	        K   t        |t              sJ d       | j                  |       | j                          g }|| j                  v rV| j                  |   j                         D ]6  }|j                  t        j                  | j                  ||                   8 t        j                  |      D ]  }	 | d {     y 7 # t        $ r Y w xY ww)NzMessage is not a dict)rY   r   rm   r   r   keysrL   r   create_taskr{   as_completedr	   )r   r   rz   opsrV   send_results         r   r   zInMemoryChannelLayer.group_send  s     '4(A*AA(%%e, DKK;;u-224

7..tyy'/JKL 5"//4K!!! 5! s<   B7C:C	?C C	CC			CCCC)r   iQ rB   N)z	specific.)r;   r<   r=   r>   r   
extensionsr{   rh   r   r   r   r   r   r   r   r   __classcell__)r   s   @r   r   r      sY     )( G$J'(,
-8(	2-r   r   c                 4    	 t         |    S # t        $ r Y y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     s$    e$$ s    	)r   rO   r   rM   r   r   r   copyr   django.confr   django.core.signalsr   django.utils.module_loadingr   r   r   
exceptionsr	   r
   r   rA   r   r   r   r-   r   r   <module>r      sj       	       / 5 * =N NbF9 F9Rf+ fR 2  %&r   