
    >%iM3                         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    m/var/www/html/navyabakers_fullstack/navyabakers_prod/venv_new/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        	 t        | j                   |   d         } |di |S # t        $ r t        d|z        t        $ r" t        d| j                   |   d   d|      w xY w)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HM &v&&  	Q*+H4+OPP 	*<<%i0$8 	s   A ABc                 x    || j                   vr| j                  |      | j                   |<   | j                   |   S r   )r   r%   r   keys     r   __getitem__zChannelLayerManager.__getitem__L   s6    dmm#!%!2!23!7DMM#}}S!!r   c                     || j                   v S r   )r   r1   s     r   __contains__z ChannelLayerManager.__contains__Q   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   r2   layerolds       r   setzChannelLayerManager.setT   s-     mmT*"c
r   N)__name__
__module____qualname____doc__r   r   propertyr   r%   r)   r!   r3   r5   r9   r-   r   r   r   r      sC    6 7 7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   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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   rD   rE   rF   s       r   r   zBaseChannelLayer.__init__g   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   rF   resultpatternvalues        r   compile_capacitiesz#BaseChannelLayer.compile_capacitiesl   sp    
 .446 	ONGU w(w./rzz'*;*;G*DEuMN	O 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.
        )rF   rH   rE   )r   channelrQ   rE   s       r   get_capacityzBaseChannelLayer.get_capacity{   s;     "&!6!6 	 GX}}W%	  }}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 < {} zGcontaining only ASCII alphanumerics, hyphens, underscores, or periods, znot {}c                     | j                  |      rGt        | j                  j                  |            r#d|v r|j	                  d      s|rt        d      yt        | j                  j                  d|            )N!z5Specific channel names in receive() must end at the !TChannel)r]   boolchannel_name_regexrH   endswith	TypeErrorinvalid_name_errorformat)r   r#   receives      r   valid_channel_namez#BaseChannelLayer.valid_channel_name   sp    %%d+D++11$78$;t}}S'9g#O  //66y$GHHr   c                     | j                  |      r%t        | j                  j                  |            ryt	        | j
                  j                  d|            )NTGroup)r]   ra   group_name_regexrH   rd   re   rf   r\   s     r   valid_group_namez!BaseChannelLayer.valid_group_name   sJ    %%d+D))//56//66wEFFr   c                 x     |rdnd}t        |t              }|r|sJ d       t         fd|D              sJ y)NTFznames must be a non-empty listc              3   D   K   | ]  }j                  |         yw))rg   N)rh   ).0rU   rg   r   s     r   	<genexpr>z7BaseChannelLayer.valid_channel_names.<locals>.<genexpr>   s&      
BID##GW#=
s    )rX   listall)r   namesrg   _non_empty_list_names_types   ` `  r   valid_channel_namesz$BaseChannelLayer.valid_channel_names   sM    "'$U -;P0PP. 
MR
 
 	
 
 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.
        r_   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   rU   messages      r   sendzBaseChannelLayer.send        !"STT   c                     K   t        d      w)Nz2receive() should be implemented in a channel layerr{   )r   rU   s     r   rg   zBaseChannelLayer.receive        !"VWWr   c                     K   t        d      w)Nz6new_channel() should be implemented in a channel layerr{   r   s    r   new_channelzBaseChannelLayer.new_channel   s     !D
 	
r   c                     K   t        d      w)Nz)flush() not implemented (flush extension)r{   r   s    r   flushzBaseChannelLayer.flush   s     !"MNNr   c                     K   t        d      w)Nz.group_add() not implemented (groups extension)r{   r   grouprU   s      r   	group_addzBaseChannelLayer.group_add   s     !"RSSr   c                     K   t        d      w)Nz2group_discard() not implemented (groups extension)r{   r   s      r   group_discardzBaseChannelLayer.group_discard   r   r   c                     K   t        d      w)Nz/group_send() not implemented (groups extension)r{   )r   r   r}   s      r   
group_sendzBaseChannelLayer.group_send   r   r   )<   rA   N)F)r:   r;   r<   r=   r[   r   rS   rV   r]   rL   rM   rb   rk   rf   re   rh   rl   rv   ry   r~   rg   r   r   r   r   r   r-   r   r   r@   r@   _   s    
 O7

 $$HI!rzz"671

$
$_
5	6
S	T 	 	IG	UX

OTXU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
    c                 V    t        |   d|||d| i | _        i | _        || _        y )NrC   r-   )superr   channelsgroupsgroup_expiry)r   rD   r   rE   rF   r   	__class__s         r   r   zInMemoryChannelLayer.__init__   sB     	 	
-	
 		
 (r   r   r   c                   K   t        |t              sJ d       | j                  |      sJ d       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Channel name not valid__asgi_channel__maxsizeN)rX   dictrh   r   
setdefaultasyncioQueuerV   
put_nowaittimerD   r   queues	QueueFullr	   )r   rU   r}   queues       r   r~   zInMemoryChannelLayer.send   s     
 '4(A*AA(&&w/I1II/ "000((W]]4+<+<W+EF
	'diikDKK7'9JKL~~'' 	'g&&	's   A5C 8;B4 3C 4)CC c                   K   | j                  |      s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)
rh   _clean_expiredr   r   r   r   rV   r    emptypop)r   rU   r   _r}   s        r   rg   zInMemoryChannelLayer.receive  s      &&w///((W]]4+<+<W+EF

	1$yy{*JAw{{}!!'40 +{{}!!'40 s0   A#C#&B1 9B/:B1 .C#/B1 1/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)ro   is     r   rp   z3InMemoryChannelLayer.new_channel.<locals>.<genexpr>!  s     KAFMM&"6"67Ks   -/   )joinrange)r   prefixs     r   r   z InMemoryChannelLayer.new_channel  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)rq   r   rI   r   _queuer   
get_nowait_remove_from_groupsr   intr   r   values)r   rU   r   timeoutr   r#   	timestamps          r   r   z#InMemoryChannelLayer._clean_expired&  s    #4==#6#6#89 	5NGUkkmQ(:TYY[(H  "((1;;=MM%%gt4 kkmQ(:TYY[(H	5 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.flushB  s     s   c                    K   y wr   r-   r   s    r   closezInMemoryChannelLayer.closeF  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   rU   r   s      r   r   z(InMemoryChannelLayer._remove_from_groupsJ  s.     **, 	(HLL$'	(r   c                    K   | j                  |      sJ d       | j                  |      sJ d       | j                  j                  |i        t	        j                         | j                  |   |<   yw)z3
        Adds the channel name to a group.
        zGroup name not validr   N)rl   rh   r   r   r   r   s      r   r   zInMemoryChannelLayer.group_addS  si     
 $$U+C-CC+&&w/I1II/ub)&*iikE7#s   A2A4c                   K   | j                  |      sJ d       | j                  |      sJ d       | j                  j                  |d       }|r2|j	                  |d        |s| j                  j	                  |d        y y y w)NzInvalid channel nameInvalid group name)rh   rl   r   r    r   )r   r   rU   group_channelss       r   r   z"InMemoryChannelLayer.group_discard^  s     &&w/G1GG/$$U+A-AA+5w-!t, "	 s   BBc           	        K   t        |t              sJ d       | j                  |      sJ d       | 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 dictr   )rX   r   rl   r   r   keysrK   r   create_taskr~   as_completedr	   )r   r   r}   opsrU   send_results         r   r   zInMemoryChannelLayer.group_sendk  s     '4(A*AA($$U+A-AA+ DKK;;u-224 M

7..tyy'/JKLM"//4 	K!!!	! s<   B>CCCCCC	CCCC)r   iQ rA   N)z	specific.)r:   r;   r<   r=   r   
extensionsr~   rg   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   rN   r   rL   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      si       	      / 5 * =J JZsU sUlf+ fR 2  %&r   